Whitespace, indentation, nounce -> nonce

This commit is contained in:
Aldo Cortesi 2015-04-21 13:39:00 +12:00
parent 7d83e388aa
commit e5f1264838
3 changed files with 79 additions and 66 deletions

View File

@ -1,18 +1,18 @@
"""
A flexible module for cookie parsing and manipulation.
This module differs from usual standards-compliant cookie modules in a number of
ways. We try to be as permissive as possible, and to retain even mal-formed
This module differs from usual standards-compliant cookie modules in a number
of ways. We try to be as permissive as possible, and to retain even mal-formed
information. Duplicate cookies are preserved in parsing, and can be set in
formatting. We do attempt to escape and quote values where needed, but will not
reject data that violate the specs.
Parsing accepts the formats in RFC6265 and partially RFC2109 and RFC2965. We do
not parse the comma-separated variant of Set-Cookie that allows multiple cookies
to be set in a single header. Technically this should be feasible, but it turns
out that violations of RFC6265 that makes the parsing problem indeterminate are
much more common than genuine occurences of the multi-cookie variants.
Serialization follows RFC6265.
not parse the comma-separated variant of Set-Cookie that allows multiple
cookies to be set in a single header. Technically this should be feasible, but
it turns out that violations of RFC6265 that makes the parsing problem
indeterminate are much more common than genuine occurences of the multi-cookie
variants. Serialization follows RFC6265.
http://tools.ietf.org/html/rfc6265
http://tools.ietf.org/html/rfc2109
@ -32,11 +32,11 @@ def _read_until(s, start, term):
Read until one of the characters in term is reached.
"""
if start == len(s):
return "", start+1
return "", start + 1
for i in range(start, len(s)):
if s[i] in term:
return s[start:i], i
return s[start:i+1], i+1
return s[start:i + 1], i + 1
def _read_token(s, start):
@ -59,7 +59,7 @@ def _read_quoted_string(s, start):
escaping = False
ret = []
# Skip the first quote
for i in range(start+1, len(s)):
for i in range(start + 1, len(s)):
if escaping:
ret.append(s[i])
escaping = False
@ -70,7 +70,7 @@ def _read_quoted_string(s, start):
pass
else:
ret.append(s[i])
return "".join(ret), i+1
return "".join(ret), i + 1
def _read_value(s, start, delims):
@ -103,7 +103,7 @@ def _read_pairs(s, off=0, specials=()):
rhs = None
if off < len(s):
if s[off] == "=":
rhs, off = _read_value(s, off+1, ";")
rhs, off = _read_value(s, off + 1, ";")
vals.append([lhs, rhs])
off += 1
if not off < len(s):

View File

@ -67,23 +67,23 @@ class Frame(object):
mask_bit, # decimal integer 1 or 0
payload_length_code, # decimal integer 1 - 127
decoded_payload, # bytestring
rsv1 = 0, # decimal integer 1 or 0
rsv2 = 0, # decimal integer 1 or 0
rsv3 = 0, # decimal integer 1 or 0
payload = None, # bytestring
masking_key = None, # 32 bit byte string
rsv1 = 0, # decimal integer 1 or 0
rsv2 = 0, # decimal integer 1 or 0
rsv3 = 0, # decimal integer 1 or 0
payload = None, # bytestring
masking_key = None, # 32 bit byte string
actual_payload_length = None, # any decimal integer
):
self.fin = fin
self.rsv1 = rsv1
self.rsv2 = rsv2
self.rsv3 = rsv3
self.opcode = opcode
self.mask_bit = mask_bit
self.payload_length_code = payload_length_code
self.masking_key = masking_key
self.payload = payload
self.decoded_payload = decoded_payload
self.fin = fin
self.rsv1 = rsv1
self.rsv2 = rsv2
self.rsv3 = rsv3
self.opcode = opcode
self.mask_bit = mask_bit
self.payload_length_code = payload_length_code
self.masking_key = masking_key
self.payload = payload
self.decoded_payload = decoded_payload
self.actual_payload_length = actual_payload_length
@classmethod
@ -162,7 +162,7 @@ class Frame(object):
"""
Construct a websocket frame from an in-memory bytestring
to construct a frame from a stream of bytes, use from_file() directly
"""
"""
return cls.from_file(io.BytesIO(bytestring))
def safe_to_bytes(self):
@ -206,7 +206,7 @@ class Frame(object):
# '!H' pack as 16 bit unsigned short
# add 2 byte extended payload length
bytes += struct.pack('!H', self.actual_payload_length)
elif self.actual_payload_length < CONST.MAX_64_BIT_INT:
elif self.actual_payload_length < CONST.MAX_64_BIT_INT:
# '!Q' = pack as 64 bit unsigned long long
# add 8 bytes extended payload length
bytes += struct.pack('!Q', self.actual_payload_length)
@ -225,10 +225,10 @@ class Frame(object):
def from_file(cls, reader):
"""
read a websockets frame sent by a server or client
reader is a "file like" object that could be backed by a network stream or a disk
or an in memory stream reader
"""
reader is a "file like" object that could be backed by a network
stream or a disk or an in memory stream reader
"""
first_byte = utils.bytes_to_int(reader.read(1))
second_byte = utils.bytes_to_int(reader.read(1))
@ -336,7 +336,7 @@ def create_server_handshake(key):
headers = [
('Connection', 'Upgrade'),
('Upgrade', 'websocket'),
('Sec-WebSocket-Accept', create_server_nounce(key))
('Sec-WebSocket-Accept', create_server_nonce(key))
]
request = "HTTP/1.1 101 Switching Protocols"
return build_handshake(headers, request)
@ -406,11 +406,11 @@ def headers_from_http_message(http_message):
)
def create_server_nounce(client_nounce):
def create_server_nonce(client_nonce):
return base64.b64encode(
hashlib.sha1(client_nounce + websockets_magic).hexdigest().decode('hex')
hashlib.sha1(client_nonce + websockets_magic).hexdigest().decode('hex')
)
def create_client_nounce():
def create_client_nonce():
return base64.b64encode(os.urandom(16)).decode('utf-8')

View File

@ -27,7 +27,7 @@ class WebSocketsEchoHandler(tcp.BaseHandler):
def send_message(self, message):
frame = websockets.Frame.default(message, from_client = False)
frame.to_file(self.wfile)
def handshake(self):
client_hs = websockets.read_handshake(self.rfile, 1)
key = websockets.process_handshake_from_client(client_hs)
@ -45,7 +45,7 @@ class WebSocketsClient(tcp.TCPClient):
def __init__(self, address, source_address=None):
super(WebSocketsClient, self).__init__(address, source_address)
self.version = "13"
self.client_nounce = websockets.create_client_nounce()
self.client_nonce = websockets.create_client_nonce()
self.resource = "/"
def connect(self):
@ -54,7 +54,7 @@ class WebSocketsClient(tcp.TCPClient):
handshake = websockets.create_client_handshake(
self.address.host,
self.address.port,
self.client_nounce,
self.client_nonce,
self.version,
self.resource
)
@ -63,9 +63,11 @@ class WebSocketsClient(tcp.TCPClient):
self.wfile.flush()
server_handshake = websockets.read_handshake(self.rfile, 1)
server_nounce = websockets.process_handshake_from_server(server_handshake)
server_nonce = websockets.process_handshake_from_server(
server_handshake
)
if not server_nounce == websockets.create_server_nounce(self.client_nounce):
if not server_nonce == websockets.create_server_nonce(self.client_nonce):
self.close()
def read_next_message(self):
@ -75,6 +77,7 @@ class WebSocketsClient(tcp.TCPClient):
frame = websockets.Frame.default(message, from_client = True)
frame.to_file(self.wfile)
class TestWebSockets(test.ServerTestBase):
handler = WebSocketsEchoHandler
@ -124,7 +127,9 @@ class TestWebSockets(test.ServerTestBase):
frame = websockets.Frame.default(
self.random_bytes(num_bytes), is_client
)
assert frame == websockets.Frame.from_bytes(frame.safe_to_bytes())
assert frame == websockets.Frame.from_bytes(
frame.safe_to_bytes()
)
bytes = b'\x81\x03cba'
assert websockets.Frame.from_bytes(bytes).safe_to_bytes() == bytes
@ -136,36 +141,44 @@ class TestWebSockets(test.ServerTestBase):
frame.safe_to_bytes()
def test_handshake(self):
bad_upgrade = "not_websockets"
bad_header_handshake = websockets.build_handshake([
('Host', '%s:%s' % ("a", "b")),
('Connection', "c"),
('Upgrade', bad_upgrade),
('Sec-WebSocket-Key', "d"),
('Sec-WebSocket-Version', "e")
], "f")
bad_upgrade = "not_websockets"
bad_header_handshake = websockets.build_handshake([
('Host', '%s:%s' % ("a", "b")),
('Connection', "c"),
('Upgrade', bad_upgrade),
('Sec-WebSocket-Key', "d"),
('Sec-WebSocket-Version', "e")
], "f")
# check behavior when required header values are missing
assert None == websockets.process_handshake_from_server(bad_header_handshake)
assert None == websockets.process_handshake_from_client(bad_header_handshake)
# check behavior when required header values are missing
assert None is websockets.process_handshake_from_server(
bad_header_handshake
)
assert None is websockets.process_handshake_from_client(
bad_header_handshake
)
key = "test_key"
key = "test_key"
client_handshake = websockets.create_client_handshake("a","b",key,"d","e")
assert key == websockets.process_handshake_from_client(client_handshake)
client_handshake = websockets.create_client_handshake(
"a", "b", key, "d", "e"
)
assert key == websockets.process_handshake_from_client(
client_handshake
)
server_handshake = websockets.create_server_handshake(key)
assert websockets.create_server_nounce(key) == websockets.process_handshake_from_server(server_handshake)
server_handshake = websockets.create_server_handshake(key)
assert websockets.create_server_nonce(key) == websockets.process_handshake_from_server(server_handshake)
handshake = websockets.create_client_handshake("a","b","c","d","e")
stream = io.BytesIO(handshake)
assert handshake == websockets.read_handshake(stream, 1)
handshake = websockets.create_client_handshake("a", "b", "c", "d", "e")
stream = io.BytesIO(handshake)
assert handshake == websockets.read_handshake(stream, 1)
# ensure readhandshake doesn't loop forever on empty stream
empty_stream = io.BytesIO("")
assert "" == websockets.read_handshake(empty_stream, 1)
# ensure readhandshake doesn't loop forever on empty stream
empty_stream = io.BytesIO("")
assert "" == websockets.read_handshake(empty_stream, 1)
class BadHandshakeHandler(WebSocketsEchoHandler):
def handshake(self):
client_hs = websockets.read_handshake(self.rfile, 1)