Skip to content

Commit 1494409

Browse files
committed
Will check if message is valid UTF8
1 parent a9e2738 commit 1494409

File tree

1 file changed

+46
-8
lines changed

1 file changed

+46
-8
lines changed

websocket.py

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from base64 import b64encode
77
from hashlib import sha1
88

9+
910
if sys.version_info[0] < 3 :
1011
from SocketServer import ThreadingMixIn, TCPServer, StreamRequestHandler
1112
else:
@@ -102,6 +103,7 @@ def handler_to_client(self, handler):
102103
return client
103104

104105

106+
105107
class WebSocketHandler(StreamRequestHandler):
106108

107109
def __init__(self, socket, addr, server):
@@ -122,13 +124,14 @@ def handle(self):
122124
self.read_next_message()
123125

124126
def read_next_message(self):
127+
125128
b1 = self.rfile.read(1)
126129
b2 = self.rfile.read(1)
127130
FIN = ord(b1) & 0b10000000
128131
OPCODE = ord(b1) & 0b00001111
129132
MASKED = ord(b2) & 0b10000000
130133
LENGTH = ord(b2) & 0b01111111
131-
134+
132135
if not b1:
133136
print("Client closed connection.")
134137
self.keep_alive = 0
@@ -191,35 +194,47 @@ def send_text(self, message):
191194
Fragmented(=continuation) messages are not being used since their usage
192195
is needed in very limited cases - when we don't know the payload length.
193196
'''
194-
197+
195198
# 0 = '0x00' = 0b00000000
196199
# 125 = '0x7d' = 0b01111101
197200
# 126 = '0x7e' = 0b01111110
198201
# 127 = '0x7f' = 0b01111111
199202
# 128 = '0x80' = 0b10000000
200203
# 129 = '0x81' = 0b10000001
201-
length = len(message)
204+
205+
# assure message is of acceptable format and encode to UTF-8 if needed
206+
encoded_message = None
207+
if isinstance(message, bytes):
208+
message = try_decode_UTF8(message) # this is slower but assures we have UTF-8
209+
if not message:
210+
print("Can\'t send message, message is not valid UTF-8")
211+
return False
212+
else:
213+
print('Can\'t send message, message has to be a string or bytes. Given type is %s' % type(message))
214+
return False
215+
encoded_message = encode_to_UTF8(message)
216+
length = len(encoded_message)
202217

203218
# normal payload
204219
if length <= 125:
205220
#print("sending single frame of size %s", length)
206221
self.request.send(b'\x81')
207222
self.request.send(chr(length).encode())
208-
self.request.send(unicode(message, 'UTF-8'))
223+
self.request.send(encoded_message)
209224

210225
# extended payload
211226
elif length >= 126 and length <= 65535:
212227
#print("sending extended frame of size %s", length)
213228
self.request.send(b'\x81\x7e')
214229
self.request.send(struct.pack(">H", length)) # MUST be 16bits
215-
self.request.send(unicode(message, 'UTF-8'))
230+
self.request.send(encoded_message)
216231

217232
# huge extended payload
218233
elif length < 18446744073709551616:
219234
#print("sending extended frame of size %s", length)
220235
self.request.send(b'\x81\x7f')
221236
self.request.send(struct.pack(">Q", length)) # MUST be 64bits
222-
self.request.send(unicode(message, 'UTF-8'))
237+
self.request.send(encoded_message)
223238

224239
def handshake(self):
225240
message = self.request.recv(1024).decode().strip()
@@ -238,15 +253,15 @@ def handshake(self):
238253
self.handshake_done = self.request.send(response.encode())
239254
self.valid_client = True
240255
self.server._new_client_(self)
241-
256+
242257
def make_handshake_response(self, key):
243258
return \
244259
'HTTP/1.1 101 Switching Protocols\r\n'\
245260
'Upgrade: websocket\r\n' \
246261
'Connection: Upgrade\r\n' \
247262
'Sec-WebSocket-Accept: %s\r\n' \
248263
'\r\n' % self.calculate_response_key(key)
249-
264+
250265
def calculate_response_key(self, key):
251266
GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
252267
hash = sha1(key.encode() + GUID.encode())
@@ -257,6 +272,29 @@ def finish(self):
257272
self.server._client_left_(self)
258273

259274

275+
276+
def encode_to_UTF8(data):
277+
try:
278+
return data.encode('UTF-8')
279+
except UnicodeEncodeError as e:
280+
print("Could not encode data to UTF-8 -- %s" % e)
281+
return False
282+
except Exception as e:
283+
raise(e)
284+
return False
285+
286+
287+
288+
def try_decode_UTF8(data):
289+
try:
290+
return data.decode('utf-8')
291+
except UnicodeDecodeError:
292+
return False
293+
except Exception as e:
294+
raise(e)
295+
296+
297+
260298
# This is only for testing purposes
261299
class DummyWebsocketHandler(WebSocketHandler):
262300
def __init__(self, *_):

0 commit comments

Comments
 (0)