3
3
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
4
5
5
import base64
6
+ import json
6
7
import os
7
8
8
- import json
9
+ import six
9
10
import http_ece
10
11
import pyelliptic
11
12
import requests
@@ -100,22 +101,22 @@ def __init__(self, subscription_info):
100
101
for k in ['p256dh' , 'auth' ]:
101
102
if keys .get (k ) is None :
102
103
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' ]))
105
107
if len (receiver_raw ) != 65 and receiver_raw [0 ] != "\x04 " :
106
108
raise WebPushException ("Invalid p256dh key specified" )
107
109
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' ]))
110
111
111
- def _repad (self , str ):
112
+ def _repad (self , data ):
112
113
"""Add base64 padding to the end of a string, if required"""
113
- return str + "====" [:len (str ) % 4 ]
114
+ return data + b "====" [:len (data ) % 4 ]
114
115
115
116
def encode (self , data ):
116
117
"""Encrypt the data.
117
118
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,
119
120
etc.) Make sure that whatever you send, your client knows how
120
121
to understand it.
121
122
@@ -129,6 +130,9 @@ def encode(self, data):
129
130
# ID tag.
130
131
server_key_id = base64 .urlsafe_b64encode (server_key .get_pubkey ()[1 :])
131
132
133
+ if isinstance (data , six .string_types ):
134
+ data = bytes (data .encode ('utf8' ))
135
+
132
136
# http_ece requires that these both be set BEFORE encrypt or
133
137
# decrypt is called if you specify the key as "dh".
134
138
http_ece .keys [server_key_id ] = server_key
@@ -143,8 +147,8 @@ def encode(self, data):
143
147
144
148
return CaseInsensitiveDict ({
145
149
'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'=' ),
148
152
'body' : encrypted ,
149
153
})
150
154
@@ -160,6 +164,10 @@ def send(self, data, headers={}, ttl=0, gcm_key=None, reg_id=None):
160
164
:param ttl: The Time To Live in seconds for this message if the
161
165
recipient is not online. (Defaults to "0", which discards the
162
166
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.
163
171
164
172
"""
165
173
# Encode the data.
@@ -169,11 +177,12 @@ def send(self, data, headers={}, ttl=0, gcm_key=None, reg_id=None):
169
177
crypto_key = headers .get ("crypto-key" , "" )
170
178
if crypto_key :
171
179
crypto_key += ','
172
- crypto_key += "keyid=p256dh;dh=" + encoded ["crypto_key" ]
180
+ crypto_key += "keyid=p256dh;dh=" + encoded ["crypto_key" ]. decode ( 'utf8' )
173
181
headers .update ({
174
182
'crypto-key' : crypto_key ,
175
183
'content-encoding' : 'aesgcm' ,
176
- 'encryption' : "keyid=p256dh;salt=" + encoded ['salt' ],
184
+ 'encryption' : "keyid=p256dh;salt=" +
185
+ encoded ['salt' ].decode ('utf8' ),
177
186
})
178
187
gcm_endpoint = 'https://android.googleapis.com/gcm/send'
179
188
if self .subscription_info ['endpoint' ].startswith (gcm_endpoint ):
0 commit comments