diff --git a/ChangeLog b/ChangeLog index 3c7257a..ba574c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ ChangeLog - Supporting http-basic auth in WebSocketApp (#143) - fix failer of test.testInternalRecvStrict(#141) + - skip utf8 validation by skip_utf8_validation argument (#137) - 0.23.0 diff --git a/websocket/_abnf.py b/websocket/_abnf.py index 01e4dcc..70de786 100644 --- a/websocket/_abnf.py +++ b/websocket/_abnf.py @@ -101,9 +101,10 @@ class ABNF(object): self.data = data self.get_mask_key = os.urandom - def validate(self): + def validate(self, skip_utf8_validation=False): """ validate the ABNF frame. + skip_utf8_validation: skip utf8 validation. """ if self.rsv1 or self.rsv2 or self.rsv3: raise WebSocketProtocolException("rsv is not implemented, yet") @@ -120,7 +121,7 @@ class ABNF(object): return if l == 1 or l >= 126: raise WebSocketProtocolException("Invalid close frame.") - if l > 2 and not validate_utf8(self.data[2:]): + if l > 2 and not skip_utf8_validation and not validate_utf8(self.data[2:]): raise WebSocketProtocolException("Invalid close frame.") code = 256*six.byte2int(self.data[0:1]) + six.byte2int(self.data[1:2]) diff --git a/websocket/_app.py b/websocket/_app.py index 08e01bc..160563c 100644 --- a/websocket/_app.py +++ b/websocket/_app.py @@ -113,7 +113,8 @@ class WebSocketApp(object): self.sock.ping() def run_forever(self, sockopt=None, sslopt=None, ping_interval=0, ping_timeout=None, - http_proxy_host=None, http_proxy_port=None, http_no_proxy=None, http_proxy_auth=None): + http_proxy_host=None, http_proxy_port=None, http_no_proxy=None, http_proxy_auth=None, + skip_utf8_validation=False): """ run event loop for WebSocket framework. This loop is infinite loop and is alive during websocket is available. @@ -126,6 +127,7 @@ class WebSocketApp(object): http_proxy_host: http proxy host name. http_proxy_port: http proxy port. If not set, set to 80. http_no_proxy: host names, which doesn't use proxy. + skip_utf8_validation: skip utf8 validation. """ if not ping_timeout or ping_timeout<=0: @@ -141,7 +143,8 @@ class WebSocketApp(object): try: self.sock = WebSocket(self.get_mask_key, sockopt=sockopt, sslopt=sslopt, - fire_cont_frame=self.on_cont_message and True or False) + fire_cont_frame=self.on_cont_message and True or False, + skip_utf8_validation=skip_utf8_validation) self.sock.settimeout(getdefaulttimeout()) self.sock.connect(self.url, header=self.header, cookie=self.cookie, http_proxy_host=http_proxy_host, http_proxy_port=http_proxy_port, diff --git a/websocket/_core.py b/websocket/_core.py index c13a0a1..f2accb8 100644 --- a/websocket/_core.py +++ b/websocket/_core.py @@ -256,13 +256,16 @@ def create_connection(url, timeout=None, **options): "sockopt" -> socket options "sslopt" -> ssl option "subprotocols" - array of available sub protocols. default is None. + "skip_utf8_validation" - skip utf8 validation. """ sockopt = options.get("sockopt", []) sslopt = options.get("sslopt", {}) fire_cont_frame = options.get("fire_cont_frame", False) enable_multithread = options.get("enable_multithread", False) + skip_utf8_validation = options.get("skip_utf8_validation", False) websock = WebSocket(sockopt=sockopt, sslopt=sslopt, - fire_cont_frame = fire_cont_frame, enable_multithread=enable_multithread) + fire_cont_frame = fire_cont_frame, enable_multithread=enable_multithread, + skip_utf8_validation=skip_utf8_validation) websock.settimeout(timeout if timeout is not None else default_timeout) websock.connect(url, **options) return websock @@ -376,10 +379,11 @@ class WebSocket(object): sslopt: dict object for ssl socket option. fire_cont_frame: fire recv event for each cont frame. default is False enable_multithread: if set to True, lock send method. + skip_utf8_validation: skip utf8 validation. """ def __init__(self, get_mask_key=None, sockopt=None, sslopt=None, - fire_cont_frame=False, enable_multithread=False): + fire_cont_frame=False, enable_multithread=False, skip_utf8_validation=False): """ Initalize WebSocket object. """ @@ -394,6 +398,7 @@ class WebSocket(object): self.sslopt = sslopt self.get_mask_key = get_mask_key self.fire_cont_frame = fire_cont_frame + self.skip_utf8_validation = skip_utf8_validation # Buffers over the packets from the layer beneath until desired amount # bytes of bytes are received. self._recv_buffer = [] @@ -790,7 +795,7 @@ class WebSocket(object): data = self._cont_data self._cont_data = None frame.data = data[1] - if not self.fire_cont_frame and data[0] == ABNF.OPCODE_TEXT and not validate_utf8(frame.data): + if not self.fire_cont_frame and data[0] == ABNF.OPCODE_TEXT and not self.skip_utf8_validation and not validate_utf8(frame.data): raise WebSocketPayloadException("cannot decode: " + repr(frame.data)) return [data[0], frame] @@ -839,7 +844,7 @@ class WebSocket(object): frame_buffer.clear() frame = ABNF(fin, rsv1, rsv2, rsv3, opcode, has_mask, payload) - frame.validate() + frame.validate(self.skip_utf8_validation) return frame