33# file, You can obtain one at http://mozilla.org/MPL/2.0/.
44
55import base64
6+ import json
67import os
78
8- import json
9+ import six
910import http_ece
1011import pyelliptic
1112import requests
@@ -100,22 +101,22 @@ def __init__(self, subscription_info):
100101 for k in ['p256dh' , 'auth' ]:
101102 if keys .get (k ) is None :
102103 raise WebPushException ("Missing keys value: %s" , k )
103- receiver_raw = base64 .urlsafe_b64decode (
104- self ._repad (keys ['p256dh' ].encode ('utf8' )))
104+ if isinstance (keys [k ], six .string_types ):
105+ keys [k ] = bytes (keys [k ].encode ('utf8' ))
106+ receiver_raw = base64 .urlsafe_b64decode (self ._repad (keys ['p256dh' ]))
105107 if len (receiver_raw ) != 65 and receiver_raw [0 ] != "\x04 " :
106108 raise WebPushException ("Invalid p256dh key specified" )
107109 self .receiver_key = receiver_raw
108- self .auth_key = base64 .urlsafe_b64decode (
109- self ._repad (keys ['auth' ].encode ('utf8' )))
110+ self .auth_key = base64 .urlsafe_b64decode (self ._repad (keys ['auth' ]))
110111
111- def _repad (self , str ):
112+ def _repad (self , data ):
112113 """Add base64 padding to the end of a string, if required"""
113- return str + "====" [:len (str ) % 4 ]
114+ return data + b "====" [:len (data ) % 4 ]
114115
115116 def encode (self , data ):
116117 """Encrypt the data.
117118
118- :param data: A serialized block of data (String, JSON, bit array,
119+ :param data: A serialized block of byte data (String, JSON, bit array,
119120 etc.) Make sure that whatever you send, your client knows how
120121 to understand it.
121122
@@ -129,6 +130,9 @@ def encode(self, data):
129130 # ID tag.
130131 server_key_id = base64 .urlsafe_b64encode (server_key .get_pubkey ()[1 :])
131132
133+ if isinstance (data , six .string_types ):
134+ data = bytes (data .encode ('utf8' ))
135+
132136 # http_ece requires that these both be set BEFORE encrypt or
133137 # decrypt is called if you specify the key as "dh".
134138 http_ece .keys [server_key_id ] = server_key
@@ -143,8 +147,8 @@ def encode(self, data):
143147
144148 return CaseInsensitiveDict ({
145149 'crypto_key' : base64 .urlsafe_b64encode (
146- server_key .get_pubkey ()).strip ('=' ),
147- 'salt' : base64 .urlsafe_b64encode (salt ).strip ("=" ),
150+ server_key .get_pubkey ()).strip (b '=' ),
151+ 'salt' : base64 .urlsafe_b64encode (salt ).strip (b'=' ),
148152 'body' : encrypted ,
149153 })
150154
@@ -160,6 +164,10 @@ def send(self, data, headers={}, ttl=0, gcm_key=None, reg_id=None):
160164 :param ttl: The Time To Live in seconds for this message if the
161165 recipient is not online. (Defaults to "0", which discards the
162166 message immediately if the recipient is unavailable.)
167+ :param gcm_key: API key obtained from the Google Developer Console.
168+ Needed if endpoint is https://android.googleapis.com/gcm/send
169+ :param reg_id: registration id of the recipient. If not provided,
170+ it will be extracted from the endpoint.
163171
164172 """
165173 # Encode the data.
@@ -169,11 +177,12 @@ def send(self, data, headers={}, ttl=0, gcm_key=None, reg_id=None):
169177 crypto_key = headers .get ("crypto-key" , "" )
170178 if crypto_key :
171179 crypto_key += ','
172- crypto_key += "keyid=p256dh;dh=" + encoded ["crypto_key" ]
180+ crypto_key += "keyid=p256dh;dh=" + encoded ["crypto_key" ]. decode ( 'utf8' )
173181 headers .update ({
174182 'crypto-key' : crypto_key ,
175183 'content-encoding' : 'aesgcm' ,
176- 'encryption' : "keyid=p256dh;salt=" + encoded ['salt' ],
184+ 'encryption' : "keyid=p256dh;salt=" +
185+ encoded ['salt' ].decode ('utf8' ),
177186 })
178187 gcm_endpoint = 'https://android.googleapis.com/gcm/send'
179188 if self .subscription_info ['endpoint' ].startswith (gcm_endpoint ):
0 commit comments