def decode(cls, data, charset=None, mimetype=None): boundary = mimetype.boundary.encode('ISO8859-1') parts = data.split(b'--%s' % (boundary,)) part = parts.pop(0) if part: raise DecodeError(_(u'Data before boundary: %r'), part.decode('ISO8859-1')) try: part = parts.pop() except IndexError: raise DecodeError(u'No end of boundary') if part not in (b'--', b'--\r\n'): raise DecodeError(_(u'Invalid multipart end: %r'), part.decode('ISO8859-1')) from httoop.messages.body import Body multiparts = [] for part in parts: if not part.startswith('\r\n'): raise DecodeError(_(u'Invalid boundary end: %r'), part[:2].decode('ISO8859-1')) part = part[2:] headers, separator, content = part.partition(b'\r\n\r\n') if not separator: raise DecodeError(_(u'Multipart does not contain CRLF header separator')) if not content.endswith('\r\n'): raise DecodeError(_(u'Multipart does not end with CRLF: %r'), content[-2].decode('ISO8859-1')) content = content[:-2] body = Body() body.headers.clear() body.headers.parse(headers) body.headers.setdefault('Content-Type', cls.default_content_type) body.parse(content) multiparts.append(body) return multiparts
def _unquote_host(self, host): # IPv6 / IPvFuture if host.startswith(b'[') and host.endswith(b']'): host = host[1:-1] try: return u'[%s]' % inet_ntop(AF_INET6, inet_pton(AF_INET6, host)).decode('ascii') except SocketError: # IPvFuture if host.startswith(b'v') and b'.' in host and host[1:].split(b'.', 1)[0].isdigit(): try: return u'[%s]' % host.decode('ascii') except UnicodeDecodeError: raise InvalidURI(_('Invalid IPvFuture address: must be ASCII.')) raise InvalidURI(_('Invalid IP address in URI.')) # IPv4 if all(x.isdigit() for x in host.split(b'.')): try: return inet_ntop(AF_INET, inet_pton(AF_INET, host)).decode('ascii') except SocketError: raise InvalidURI(_('Invalid IPv4 address in URI.')) if host.strip(Percent.UNRESERVED + Percent.SUB_DELIMS + b'%'): raise InvalidURI(_('Invalid URI host.')) # DNS hostname host = self.unquote(host) try: return host.encode('ascii').decode('idna').lower() except UnicodeError: raise InvalidURI(_('Invalid host.'))
def parse(self, data): r"""parses HTTP headers :param data: the header string containing headers separated by "\r\n" without trailing "\r\n" :type data: bytes """ lines = data.split(b'\r\n') while lines: curr = lines.pop(0) name, __, value = curr.partition(b':') if __ != b':': raise InvalidHeader(_(u"Invalid header line: %r"), curr.decode('ISO8859-1')) if self.HEADER_RE.search(name): raise InvalidHeader(_(u"Invalid header name: %r"), name.decode('ISO8859-1')) name, value = name.strip(), [value.lstrip()] # continuation lines while lines and lines[0].startswith((' ', '\t')): value.append(lines.pop(0)[1:]) value = b''.join(value).rstrip() Element = HEADER.get(name, HeaderElement) value = Element.decode(value) self.append(name, value)
def parse(self, data): r"""parses HTTP headers :param data: the header string containing headers separated by "\r\n" without trailing "\r\n" :type data: bytes """ lines = data.split(b'\r\n') while lines: curr = lines.pop(0) name, __, value = curr.partition(b':') if __ != b':': raise InvalidHeader(_(u"Invalid header line: %r"), curr.decode('ISO8859-1')) if self.HEADER_RE.search(name): raise InvalidHeader(_(u"Invalid header name: %r"), name.decode('ISO8859-1')) name, value = name.strip(), [value.lstrip()] # continuation lines while lines and lines[0].startswith((b' ', b'\t')): value.append(lines.pop(0)[1:]) value = b''.join(value).rstrip() Element = HEADER.get(name, HeaderElement) value = Element.decode(value) self.append(name, value)
def _unquote_host(self, host): # IPv6 / IPvFuture if host.startswith(b'[') and host.endswith(b']'): host = host[1:-1] try: return u'[%s]' % inet_ntop(AF_INET6, inet_pton(AF_INET6, host)).decode('ascii') except SocketError: # IPvFuture if host.startswith(b'v') and b'.' in host and host[1:].split('.', 1)[0].isdigit(): try: return u'[%s]' % host.decode('ascii') except UnicodeDecodeError: raise InvalidURI(_('Invalid IPvFuture address: must be ASCII.')) raise InvalidURI(_('Invalid IP address in URI.')) # IPv4 if all(x.isdigit() for x in host.split(b'.')): try: return inet_ntop(AF_INET, inet_pton(AF_INET, host)).decode('ascii') except SocketError: raise InvalidURI(_('Invalid IPv4 address in URI.')) if host.strip(Percent.UNRESERVED + Percent.SUB_DELIMS + b'%'): raise InvalidURI(_('Invalid URI host.')) # DNS hostname host = self.unquote(host) try: return host.encode('ascii').decode('idna').lower() except UnicodeError: raise InvalidURI(_('Invalid host.'))
def parse(self, line): """parses the request line and sets method, uri and protocol version :param line: the request line :type line: bytes """ bits = line.strip().split(None, 2) try: method, uri, version = bits except ValueError: raise InvalidLine(_(u'Invalid request line: %r'), line.decode('ISO8859-1')) # protocol version super(Request, self).parse(version) # method self.method.parse(method) # URI if uri.startswith(b'//'): raise InvalidURI( _(u'The request URI must be an absolute path or contain a scheme.' )) if self.method == u'CONNECT': uri = b'//%s' % (uri, ) self.uri.parse(uri) self.validate_request_uri()
def prevent_denial_of_service(self): if len([x for x in self.ranges if x[0] is None]) > 1 or len([x for x in self.ranges if x[1] is None]) > 1: raise InvalidHeader(_(u'too many overlapping ranges.')) byterange = set() for start, stop in ((x, y) for x, y in self.ranges if x is not None and y is not None): range_ = set(range(start, stop)) if any(x in byterange for x in range_): raise InvalidHeader(_(u'duplicated range.')) byterange.update(range_)
def prevent_denial_of_service(self): if len([x for x in self.ranges if x[0] is None]) > 1 or len( [x for x in self.ranges if x[1] is None]) > 1: raise InvalidHeader(_(u'too many overlapping ranges.')) byterange = set() for start, stop in ((x, y) for x, y in self.ranges if x is not None and y is not None): range_ = set(range(start, stop)) if any(x in byterange for x in range_): raise InvalidHeader(_(u'duplicated range.')) byterange.update(range_)
def compose(self): try: scheme = self.schemes[self.value.lower()] except KeyError: raise InvalidHeader(_(u'Unsupported authentication scheme: %r'), self.value) try: authinfo = scheme.compose(self.params) except KeyError as key: raise InvalidHeader(_(u'Missing parameter %r for authentication scheme %r'), str(key), self.value) return b'%s %s' % (self.value.title(), authinfo)
def validate_request_uri(self): uri = self.uri if not isinstance(uri, (uri.SCHEMES['http'], uri.SCHEMES['https'])): raise InvalidURI(_(u'The request URI scheme must be HTTP based.')) if uri.fragment or uri.username or uri.password: raise InvalidURI(_(u'The request URI must not contain fragments or user information.')) if uri.path.startswith(b'//'): raise InvalidURI(_(u'The request URI path must not start with //.')) if uri.path and uri.path != u'*' and uri.path[0] != u'/': raise InvalidURI(_(u'The request URI path must start with /.')) if self.method == u'CONNECT' and (uri.scheme or uri.path or uri.query_string or not uri.host): raise InvalidURI(_(u'The request URI of an CONNECT request must be a authority.'))
def sanitize(self): self.value = self.value.lower() if self.attachment: if b'inline' in self.params: raise InvalidHeader(_(u'Mixed Content-Disposition')) elif self.inline: if b'attachment' in self.params: raise InvalidHeader(_(u'Mixed Content-Disposition')) elif self.form_data: if b'form-data' in self.params: raise InvalidHeader(_(u'Mixed Content-Disposition')) else: raise InvalidHeader(_(u'Unknown Content-Disposition: %r'), self.value,)
def _rfc2231_and_continuation_params(cls, params): # TODO: complexity count = set() continuations = dict() for key, value, quoted in params: if key in count: raise InvalidHeader(_(u'Parameter given twice: %r'), key.decode('ISO8859-1')) count.add(key) if '*' in key: if key.endswith('*') and not quoted: charset, language, value_ = decode_rfc2231( value.encode('ISO8859-1')) if not charset: yield key, value continue encoding = sanitize_encoding(charset) if encoding is None: raise InvalidHeader(_(u'Unknown encoding: %r'), charset) try: key, value = key[:-1], Percent.unquote(value_).decode( encoding) except UnicodeDecodeError as exc: raise InvalidHeader(_(u'%s') % (exc, )) key_, asterisk, num = key.rpartition('*') if asterisk: try: if num != '0' and num.startswith('0'): raise ValueError num = int(num) except ValueError: yield key, value continue continuations.setdefault(key_, {})[num] = value continue yield key, value for key, lines in iteritems(continuations): value = b'' for i in xrange(len(lines)): try: value += lines.pop(i) except KeyError: break if not key: raise InvalidHeader(_(u'...')) if value: yield key, value for k, v in iteritems(lines): yield '%s*%d' % (key, k), v
def parseparams(cls, elementstr): try: scheme, authinfo = elementstr.split(b' ', 1) except ValueError: raise InvalidHeader(_(u'Authorization headers must contain authentication scheme')) try: parser = cls.schemes[scheme.lower()] except KeyError: raise InvalidHeader(_(u'Unsupported authentication scheme: %r'), scheme) try: authinfo = parser.parse(authinfo) except KeyError as key: raise InvalidHeader(_(u'Missing parameter %r for authentication scheme %r'), str(key), scheme) return scheme.title(), authinfo
def parseparam(cls, atom): key, __, val = atom.partition(b'=') try: val, quoted = cls.unescape_param(val.strip()) except InvalidHeader: raise InvalidHeader(_(u'Unquoted parameter %r in %r containing TSPECIALS: %r'), key, cls.__name__, val) return cls.unescape_key(key), val, quoted
def _rfc2231_and_continuation_params(cls, params): # TODO: complexity count = set() continuations = dict() for key, value, quoted in params: if key in count: raise InvalidHeader(_(u'Parameter given twice: %r'), key.decode('ISO8859-1')) count.add(key) if '*' in key: if key.endswith('*') and not quoted: charset, language, value_ = decode_rfc2231(value.encode('ISO8859-1')) if not charset: yield key, value continue encoding = sanitize_encoding(charset) if encoding is None: raise InvalidHeader(_(u'Unknown encoding: %r'), charset) try: key, value = key[:-1], Percent.unquote(value_).decode(encoding) except UnicodeDecodeError as exc: raise InvalidHeader(_(u'%s') % (exc,)) key_, asterisk, num = key.rpartition('*') if asterisk: try: if num != '0' and num.startswith('0'): raise ValueError num = int(num) except ValueError: yield key, value continue continuations.setdefault(key_, {})[num] = value continue yield key, value for key, lines in iteritems(continuations): value = b'' for i in xrange(len(lines)): try: value += lines.pop(i) except KeyError: break if not key: raise InvalidHeader(_(u'...')) if value: yield key, value for k, v in iteritems(lines): yield '%s*%d' % (key, k), v
def unescape_param(cls, value): quoted = value.startswith(b'"') and value.endswith(b'"') if quoted: value = re.sub(r'\\(?!\\)', '', value.strip(b'"')) else: if cls.RE_TSPECIALS.search(value): raise InvalidHeader(_(u'Unquoted parameter in %r containing TSPECIALS: %r'), cls.__name__, value) return value, quoted
def decode(cls, data, charset=None, mimetype=None): try: with gzip.GzipFile(fileobj=io.BytesIO(data)) as fd: return fd.read() # data = zlib.decompress(data, 16 + zlib.MAX_WBITS) except (zlib.error, IOError, EOFError): raise DecodeError(_(u'Invalid gzip data.')) return Codec.decode(data, charset)
def sanitize(self): self.value = self.value.lower() self.host, self.port = self.HOSTPORT.match(self.value).groups() if self.host.endswith(']') and self.host.startswith('['): self.host = self.host[1:-1] if self.port: self.port = int(self.port) if not self.hostname: raise InvalidHeader(_(u'Invalid Host header'))
def encode(cls, data, charset=None, mimetype=None): try: out = io.BytesIO() with gzip.GzipFile(fileobj=out, mode="w") as fd: fd.write(Codec.encode(data, charset)) return out.getvalue() # return zlib.compress(Codec.encode(data, charset), cls.compression_level) except zlib.error: raise EncodeError(_(u'Invalid gzip data.'))
def decode(cls, data, charset=None): if any( in_table(x) for x in cls.unquote(data.encode('ISO8859-1'), 'ISO8859-1') for in_table in cls.INVALID): raise DecodeError( _(u'Invalid query string: contains invalid token')) data = super(QueryString, cls).decode(data, charset) return data
def validate_request_uri_scheme(self): if self.message.uri.scheme: if self.message.uri.scheme not in ('http', 'https'): exc = InvalidURI(_(u'Invalid URL: wrong scheme')) raise BAD_REQUEST(Unicode(exc)) else: self.message.uri.scheme = self._default_scheme self.message.uri.host = self._default_host self.message.uri.port = self._default_port
def parse(authinfo): try: authinfo = authinfo.encode('ascii') except ValueError: raise InvalidHeader(_(u'Invalid base64 in basic authentication')) try: username, password = decode_base64(authinfo.strip()).split(':') except Base64Error: raise InvalidHeader(_(u'Basic authentication contains invalid base64')) except ValueError: raise InvalidHeader(_(u'No username:password provided')) authinfo = { 'username': username.decode('ISO8859-1'), 'password': password.decode('ISO8859-1') } return authinfo
def validate_request_uri(self): uri = self.uri if not isinstance(uri, (uri.SCHEMES['http'], uri.SCHEMES['https'])): raise InvalidURI(_(u'The request URI scheme must be HTTP based.')) if uri.fragment or uri.username or uri.password: raise InvalidURI( _(u'The request URI must not contain fragments or user information.' )) if uri.path.startswith(b'//'): raise InvalidURI( _(u'The request URI path must not start with //.')) if uri.path and uri.path != u'*' and uri.path[0] != u'/': raise InvalidURI(_(u'The request URI path must start with /.')) if self.method == u'CONNECT' and (uri.scheme or uri.path or uri.query_string or not uri.host): raise InvalidURI( _(u'The request URI of an CONNECT request must be a authority.' ))
def parseparam(cls, atom): key, __, val = atom.partition(b'=') try: val, quoted = cls.unescape_param(val.strip()) except InvalidHeader: raise InvalidHeader( _(u'Unquoted parameter %r in %r containing TSPECIALS: %r'), key, cls.__name__, val) return cls.unescape_key(key), val, quoted
def port(self, port): port = port or self.PORT if port: try: port = int(port) if not 0 < int(port) <= 65535: raise ValueError except ValueError: raise InvalidURI(_(u'Invalid port: %r'), port) # TODO: TypeError self._port = port
def parse(cls, elementstr): bytesunit, __, byteranges = elementstr.partition(b'=') byteranges = cls.split(byteranges) ranges = set() for brange in byteranges: start, __, stop = (x.strip() for x in brange.partition(b'-')) if (not start and not stop) or not __: raise InvalidHeader(_(u'no range start/stop.')) try: start = int(start) if start else None stop = int(stop) if stop else None if start and start < 0 or stop and stop < 0: raise ValueError except ValueError: raise InvalidHeader(_(u'no range number.')) if start is not None and stop is not None and stop < start: raise InvalidHeader(_(u'range start must be smaller than end.')) ranges.add((start, stop)) return cls(bytesunit, list(sorted(ranges)))
def unescape_param(cls, value): quoted = value.startswith(b'"') and value.endswith(b'"') if quoted: value = re.sub(r'\\(?!\\)', '', value.strip(b'"')) else: if cls.RE_TSPECIALS.search(value): raise InvalidHeader( _(u'Unquoted parameter in %r containing TSPECIALS: %r'), cls.__name__, value) return value, quoted
def parse(authinfo): try: authinfo = authinfo.encode('ascii') except ValueError: raise InvalidHeader(_(u'Invalid base64 in basic authentication')) try: username, password = decode_base64(authinfo.strip()).split(':') except Base64Error: raise InvalidHeader( _(u'Basic authentication contains invalid base64')) except ValueError: raise InvalidHeader(_(u'No username:password provided')) authinfo = { 'username': username.decode('ISO8859-1'), 'password': password.decode('ISO8859-1') } return authinfo
def parse(self, status): """parse a Statuscode and Reason-Phrase :param status: the code and reason :type status: bytes """ match = self.STATUS_RE.match(status) if match is None: raise InvalidLine(_(u"Invalid status %r"), status.decode('ISO8859-1')) self.set((int(match.group(1)), match.group(2).decode('ascii'),))
def parse(cls, elementstr): bytesunit, __, byteranges = elementstr.partition(b'=') byteranges = cls.split(byteranges) ranges = set() for brange in byteranges: start, __, stop = (x.strip() for x in brange.partition(b'-')) if (not start and not stop) or not __: raise InvalidHeader(_(u'no range start/stop.')) try: start = int(start) if start else None stop = int(stop) if stop else None if start and start < 0 or stop and stop < 0: raise ValueError except ValueError: raise InvalidHeader(_(u'no range number.')) if start is not None and stop is not None and stop < start: raise InvalidHeader( _(u'range start must be smaller than end.')) ranges.add((start, stop)) return cls(bytesunit, list(sorted(ranges)))
def __parse_chunk_size(self): line, rest_chunk = self.buffer.split(self.line_end, 1) chunk_size = line.split(b";", 1)[0].strip() try: chunk_size = int(bytes(chunk_size), 16) if chunk_size < 0: raise ValueError except (ValueError, OverflowError): exc = InvalidHeader(_(u'Invalid chunk size: %r'), chunk_size.decode('ISO8859-1')) raise BAD_REQUEST(Unicode(exc)) else: return chunk_size, rest_chunk
def parse(self, line): u"""parses the response line""" bits = line.strip().split(None, 1) try: version, status = bits except ValueError: raise InvalidLine(_(u'Invalid response line: %r'), line.decode('ISO8859-1')) # version super(Response, self).parse(version) # status self.status.parse(status)
def parse(cls, elementstr): value, start, end, complete_length = None, None, None, None try: value, content_range = elementstr.split(None, 1) if value != b'bytes': raise InvalidHeader(_(u'Only "bytes" Content-Range supported')) byte_range, complete_length = content_range.split(b'/') if complete_length != b'*': complete_length = int(complete_length) if complete_length < 0: raise ValueError else: complete_length = None if byte_range != b'*': start, end = byte_range.split(b'-', 1) start, end = int(start), int(end) if start >= end or start < 0 or end < 0: raise ValueError if complete_length is None and start is None: raise ValueError except ValueError: raise InvalidHeader(_(u'Content-Range: %r'), elementstr) return cls(value, (start, end), complete_length)
def decode(cls, data, charset=None, mimetype=None): boundary = mimetype.boundary.encode('ISO8859-1') parts = data.split(b'--%s' % (boundary, )) part = parts.pop(0) if part: raise DecodeError(_(u'Data before boundary: %r'), part.decode('ISO8859-1')) try: part = parts.pop() except IndexError: raise DecodeError(u'No end of boundary') if part not in (b'--', b'--\r\n'): raise DecodeError(_(u'Invalid multipart end: %r'), part.decode('ISO8859-1')) from httoop.messages.body import Body multiparts = [] for part in parts: if not part.startswith('\r\n'): raise DecodeError(_(u'Invalid boundary end: %r'), part[:2].decode('ISO8859-1')) part = part[2:] headers, separator, content = part.partition(b'\r\n\r\n') if not separator: raise DecodeError( _(u'Multipart does not contain CRLF header separator')) if not content.endswith('\r\n'): raise DecodeError(_(u'Multipart does not end with CRLF: %r'), content[-2].decode('ISO8859-1')) content = content[:-2] body = Body() body.headers.clear() body.headers.parse(headers) body.headers.setdefault('Content-Type', cls.default_content_type) body.parse(content) multiparts.append(body) return multiparts
def parse(self, line): """parses the request line and sets method, uri and protocol version :param line: the request line :type line: bytes """ bits = line.strip().split(None, 2) try: method, uri, version = bits except ValueError: raise InvalidLine(_(u'Invalid request line: %r'), line.decode('ISO8859-1')) # protocol version super(Request, self).parse(version) # method self.method.parse(method) # URI if uri.startswith(b'//'): raise InvalidURI(_(u'The request URI must be an absolute path or contain a scheme.')) if self.method == u'CONNECT': uri = b'//%s' % (uri,) self.uri.parse(uri) self.validate_request_uri()
def parse(self, status): """parse a Statuscode and Reason-Phrase :param status: the code and reason :type status: bytes """ match = self.STATUS_RE.match(status) if match is None: raise InvalidLine(_(u"Invalid status %r"), status.decode('ISO8859-1')) self.set(( int(match.group(1)), match.group(2).decode('ascii'), ))
def _compose_authority_iter(self): if not self.host: return username, password, host, port, quote = self.username, self.password, self.host, self.port, self.quote if username: yield quote(username, Percent.USERINFO) if password: yield b':' yield quote(password, Percent.USERINFO) yield b'@' try: yield host.encode('idna') except UnicodeError: # u'..'.encode('idna') raise InvalidURI(_(u'Invalid URI: cannot encode host as IDNA.')) if port and int(port) != self.PORT: yield b':%d' % int(port)
def parse(cls, authinfo): params = super(cls, cls).parse(authinfo) if '"' in params['nonce']: raise InvalidHeader(_(u'Nonce must not contain double quote')) stale = params.get('stale') if stale: stale = {'false': False, 'true': True}.get(stale.lower()) params = [ ('realm', params['realm']), ('domain', params.get('domain', '').split()), ('nonce', params['nonce']), ('opaque', params.get('opaque')), ('stale', stale), ('algorithm', params.get('algorithm')), ('qop', [p.strip() for p in params.get('qop', '').split(',')]), ] return dict([(k, v) for k, v in params if v is not None])
def determine_message_length(self): # RFC 2616 Section 4.4 # get message length # TODO: check if both is set message = self.message if 'Transfer-Encoding' in message.headers and message.protocol >= (1, 1): # chunked transfer in HTTP/1.1 te = message.headers['Transfer-Encoding'].lower() self.chunked = 'chunked' == te if not self.chunked: raise NOT_IMPLEMENTED(u'Unknown HTTP/1.1 Transfer-Encoding: %r' % te) else: # Content-Length header defines the length of the message body try: self.message_length = int(message.headers.get("Content-Length", "0")) if self.message_length < 0: self.message_length = None raise ValueError except ValueError: raise BAD_REQUEST(_(u'Invalid Content-Length header.'))
def parse_trailers(self): # TODO: the code is exactly the same as parse_headers but # we have to make sure no invalid header fields are send (only values told in Trailer header allowed) if self.buffer.startswith(self.line_end): self.buffer = self.buffer[len(self.line_end):] return False # no trailers trailer_end = self.line_end + self.line_end if trailer_end not in self.buffer: # not received yet return NOT_RECEIVED_YET trailers, self.buffer = self.buffer.split(trailer_end, 1) self.trailers = Headers() try: self.trailers.parse(bytes(trailers)) except InvalidHeader as exc: exc = InvalidHeader(_(u'Invalid trailers: %r'), Unicode(exc)) raise BAD_REQUEST(Unicode(exc)) self.merge_trailer_into_header() return False
def parse(cls, timestr=None): u"""parses a HTTP date string and returns a :class:`Date` object :param timestr: the time string in one of the http formats :type timestr: str :returns: the HTTP Date object :rtype : :class:`Date` """ # parse the most common HTTP Date format (RFC 2822) date = parsedate(timestr) if date is not None: return cls(date[:9]) old = locale.getlocale(locale.LC_TIME) locale.setlocale(locale.LC_TIME, (None, None)) try: # parse RFC 1036 date format try: date = time.strptime(timestr, '%A, %d-%b-%y %H:%M:%S GMT') except ValueError: pass else: return cls(date) # parse C's asctime format try: date = time.strptime(timestr, '%a %b %d %H:%M:%S %Y') except ValueError: pass else: return cls(date) finally: locale.setlocale(locale.LC_TIME, old) raise InvalidDate(_(u'Invalid date: %r'), date)
def parse_chunked_body(self): if self.line_end not in self.buffer: # chunk size info not received yet return NOT_RECEIVED_YET chunk_size, rest_chunk = self.__parse_chunk_size() if len(rest_chunk) < (len(self.line_end) + chunk_size): # chunk not received completely return NOT_RECEIVED_YET body_part, rest_chunk = rest_chunk[:chunk_size], rest_chunk[chunk_size:] self.message.body.parse(bytes(body_part)) self.buffer = rest_chunk if chunk_size == 0: return self.parse_trailers() if not rest_chunk.startswith(self.line_end): raise InvalidBody(_(u'Invalid chunk terminator: %r'), repr(rest_chunk[:2])) self.buffer = self.buffer[len(self.line_end):] # next chunk return self.parse_chunked_body()
def parse(self, protocol): match = self.PROTOCOL_RE.match(protocol) if match is None: raise InvalidLine(_(u"Invalid HTTP protocol: %r"), protocol.decode('ISO8859-1')) self.__protocol = (int(match.group(2)), int(match.group(3))) self.name = match.group(1)
def decode(cls, data, charset=None, mimetype=None): try: data = zlib.decompress(data, 16 + zlib.MAX_WBITS) except zlib.error: raise DecodeError(_(u'Invalid gzip data.')) return Codec.decode(data, charset)