| OLD | NEW |
| 1 # Copyright 2012, Google Inc. | 1 # Copyright 2012, Google Inc. |
| 2 # All rights reserved. | 2 # All rights reserved. |
| 3 # | 3 # |
| 4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
| 5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
| 6 # met: | 6 # met: |
| 7 # | 7 # |
| 8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
| 9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
| 10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 SEC_WEBSOCKET_VERSION_HEADER = 'Sec-WebSocket-Version' | 95 SEC_WEBSOCKET_VERSION_HEADER = 'Sec-WebSocket-Version' |
| 96 SEC_WEBSOCKET_PROTOCOL_HEADER = 'Sec-WebSocket-Protocol' | 96 SEC_WEBSOCKET_PROTOCOL_HEADER = 'Sec-WebSocket-Protocol' |
| 97 SEC_WEBSOCKET_EXTENSIONS_HEADER = 'Sec-WebSocket-Extensions' | 97 SEC_WEBSOCKET_EXTENSIONS_HEADER = 'Sec-WebSocket-Extensions' |
| 98 SEC_WEBSOCKET_DRAFT_HEADER = 'Sec-WebSocket-Draft' | 98 SEC_WEBSOCKET_DRAFT_HEADER = 'Sec-WebSocket-Draft' |
| 99 SEC_WEBSOCKET_KEY1_HEADER = 'Sec-WebSocket-Key1' | 99 SEC_WEBSOCKET_KEY1_HEADER = 'Sec-WebSocket-Key1' |
| 100 SEC_WEBSOCKET_KEY2_HEADER = 'Sec-WebSocket-Key2' | 100 SEC_WEBSOCKET_KEY2_HEADER = 'Sec-WebSocket-Key2' |
| 101 SEC_WEBSOCKET_LOCATION_HEADER = 'Sec-WebSocket-Location' | 101 SEC_WEBSOCKET_LOCATION_HEADER = 'Sec-WebSocket-Location' |
| 102 | 102 |
| 103 # Extensions | 103 # Extensions |
| 104 DEFLATE_FRAME_EXTENSION = 'deflate-frame' | 104 DEFLATE_FRAME_EXTENSION = 'deflate-frame' |
| 105 PERFRAME_COMPRESSION_EXTENSION = 'perframe-compress' | |
| 106 PERMESSAGE_COMPRESSION_EXTENSION = 'permessage-compress' | 105 PERMESSAGE_COMPRESSION_EXTENSION = 'permessage-compress' |
| 107 PERMESSAGE_DEFLATE_EXTENSION = 'permessage-deflate' | 106 PERMESSAGE_DEFLATE_EXTENSION = 'permessage-deflate' |
| 108 X_WEBKIT_DEFLATE_FRAME_EXTENSION = 'x-webkit-deflate-frame' | 107 X_WEBKIT_DEFLATE_FRAME_EXTENSION = 'x-webkit-deflate-frame' |
| 109 X_WEBKIT_PERMESSAGE_COMPRESSION_EXTENSION = 'x-webkit-permessage-compress' | 108 X_WEBKIT_PERMESSAGE_COMPRESSION_EXTENSION = 'x-webkit-permessage-compress' |
| 110 MUX_EXTENSION = 'mux_DO_NOT_USE' | 109 MUX_EXTENSION = 'mux_DO_NOT_USE' |
| 111 | 110 |
| 112 # Status codes | 111 # Status codes |
| 113 # Code STATUS_NO_STATUS_RECEIVED, STATUS_ABNORMAL_CLOSURE, and | 112 # Code STATUS_NO_STATUS_RECEIVED, STATUS_ABNORMAL_CLOSURE, and |
| 114 # STATUS_TLS_HANDSHAKE are pseudo codes to indicate specific error cases. | 113 # STATUS_TLS_HANDSHAKE are pseudo codes to indicate specific error cases. |
| 115 # Could not be used for codes in actual closing frames. | 114 # Could not be used for codes in actual closing frames. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 for param_name, param_value in self._parameters: | 187 for param_name, param_value in self._parameters: |
| 189 if param_name == name: | 188 if param_name == name: |
| 190 return param_value | 189 return param_value |
| 191 | 190 |
| 192 | 191 |
| 193 class ExtensionParsingException(Exception): | 192 class ExtensionParsingException(Exception): |
| 194 def __init__(self, name): | 193 def __init__(self, name): |
| 195 super(ExtensionParsingException, self).__init__(name) | 194 super(ExtensionParsingException, self).__init__(name) |
| 196 | 195 |
| 197 | 196 |
| 198 def _parse_extension_param(state, definition, allow_quoted_string): | 197 def _parse_extension_param(state, definition): |
| 199 param_name = http_header_util.consume_token(state) | 198 param_name = http_header_util.consume_token(state) |
| 200 | 199 |
| 201 if param_name is None: | 200 if param_name is None: |
| 202 raise ExtensionParsingException('No valid parameter name found') | 201 raise ExtensionParsingException('No valid parameter name found') |
| 203 | 202 |
| 204 http_header_util.consume_lwses(state) | 203 http_header_util.consume_lwses(state) |
| 205 | 204 |
| 206 if not http_header_util.consume_string(state, '='): | 205 if not http_header_util.consume_string(state, '='): |
| 207 definition.add_parameter(param_name, None) | 206 definition.add_parameter(param_name, None) |
| 208 return | 207 return |
| 209 | 208 |
| 210 http_header_util.consume_lwses(state) | 209 http_header_util.consume_lwses(state) |
| 211 | 210 |
| 212 if allow_quoted_string: | 211 # TODO(tyoshino): Add code to validate that parsed param_value is token |
| 213 # TODO(toyoshim): Add code to validate that parsed param_value is token | 212 param_value = http_header_util.consume_token_or_quoted_string(state) |
| 214 param_value = http_header_util.consume_token_or_quoted_string(state) | |
| 215 else: | |
| 216 param_value = http_header_util.consume_token(state) | |
| 217 if param_value is None: | 213 if param_value is None: |
| 218 raise ExtensionParsingException( | 214 raise ExtensionParsingException( |
| 219 'No valid parameter value found on the right-hand side of ' | 215 'No valid parameter value found on the right-hand side of ' |
| 220 'parameter %r' % param_name) | 216 'parameter %r' % param_name) |
| 221 | 217 |
| 222 definition.add_parameter(param_name, param_value) | 218 definition.add_parameter(param_name, param_value) |
| 223 | 219 |
| 224 | 220 |
| 225 def _parse_extension(state, allow_quoted_string): | 221 def _parse_extension(state): |
| 226 extension_token = http_header_util.consume_token(state) | 222 extension_token = http_header_util.consume_token(state) |
| 227 if extension_token is None: | 223 if extension_token is None: |
| 228 return None | 224 return None |
| 229 | 225 |
| 230 extension = ExtensionParameter(extension_token) | 226 extension = ExtensionParameter(extension_token) |
| 231 | 227 |
| 232 while True: | 228 while True: |
| 233 http_header_util.consume_lwses(state) | 229 http_header_util.consume_lwses(state) |
| 234 | 230 |
| 235 if not http_header_util.consume_string(state, ';'): | 231 if not http_header_util.consume_string(state, ';'): |
| 236 break | 232 break |
| 237 | 233 |
| 238 http_header_util.consume_lwses(state) | 234 http_header_util.consume_lwses(state) |
| 239 | 235 |
| 240 try: | 236 try: |
| 241 _parse_extension_param(state, extension, allow_quoted_string) | 237 _parse_extension_param(state, extension) |
| 242 except ExtensionParsingException, e: | 238 except ExtensionParsingException, e: |
| 243 raise ExtensionParsingException( | 239 raise ExtensionParsingException( |
| 244 'Failed to parse parameter for %r (%r)' % | 240 'Failed to parse parameter for %r (%r)' % |
| 245 (extension_token, e)) | 241 (extension_token, e)) |
| 246 | 242 |
| 247 return extension | 243 return extension |
| 248 | 244 |
| 249 | 245 |
| 250 def parse_extensions(data, allow_quoted_string=False): | 246 def parse_extensions(data): |
| 251 """Parses Sec-WebSocket-Extensions header value returns a list of | 247 """Parses Sec-WebSocket-Extensions header value returns a list of |
| 252 ExtensionParameter objects. | 248 ExtensionParameter objects. |
| 253 | 249 |
| 254 Leading LWSes must be trimmed. | 250 Leading LWSes must be trimmed. |
| 255 """ | 251 """ |
| 256 | 252 |
| 257 state = http_header_util.ParsingState(data) | 253 state = http_header_util.ParsingState(data) |
| 258 | 254 |
| 259 extension_list = [] | 255 extension_list = [] |
| 260 while True: | 256 while True: |
| 261 extension = _parse_extension(state, allow_quoted_string) | 257 extension = _parse_extension(state) |
| 262 if extension is not None: | 258 if extension is not None: |
| 263 extension_list.append(extension) | 259 extension_list.append(extension) |
| 264 | 260 |
| 265 http_header_util.consume_lwses(state) | 261 http_header_util.consume_lwses(state) |
| 266 | 262 |
| 267 if http_header_util.peek(state) is None: | 263 if http_header_util.peek(state) is None: |
| 268 break | 264 break |
| 269 | 265 |
| 270 if not http_header_util.consume_string(state, ','): | 266 if not http_header_util.consume_string(state, ','): |
| 271 raise ExtensionParsingException( | 267 raise ExtensionParsingException( |
| (...skipping 26 matching lines...) Expand all Loading... |
| 298 def format_extensions(extension_list): | 294 def format_extensions(extension_list): |
| 299 """Formats a list of ExtensionParameter objects.""" | 295 """Formats a list of ExtensionParameter objects.""" |
| 300 | 296 |
| 301 formatted_extension_list = [] | 297 formatted_extension_list = [] |
| 302 for extension in extension_list: | 298 for extension in extension_list: |
| 303 formatted_extension_list.append(format_extension(extension)) | 299 formatted_extension_list.append(format_extension(extension)) |
| 304 return ', '.join(formatted_extension_list) | 300 return ', '.join(formatted_extension_list) |
| 305 | 301 |
| 306 | 302 |
| 307 # vi:sts=4 sw=4 et | 303 # vi:sts=4 sw=4 et |
| OLD | NEW |