class decompressobj(object): def __init__(self, wbits=MAX_WBITS): # Jython only uses wbits to determine to skip the header if it's negative; # but apparently there are some tests around this that we do some bogus # param checking if abs(wbits) < 8: raise ValueError, "Invalid initialization option" if abs(wbits) > 16: # NOTE apparently this also implies being negative in CPython/zlib wbits = -1 self.inflater = Inflater(wbits < 0) self._ended = False self.unused_data = "" self.unconsumed_tail = "" self.gzip = wbits < 0 self.gzip_header_skipped = False self._crc32 = CRC32() def decompress(self, string, max_length=0): if self._ended: raise error("decompressobj may not be used after flush()") # unused_data is always "" until inflation is finished; then it is # the unused bytes of the input; # unconsumed_tail is whatever input was not used because max_length # was exceeded before inflation finished. # Thus, at most one of {unused_data, unconsumed_tail} may be non-empty. self.unconsumed_tail = "" if not self.inflater.finished() and not (self.gzip and not self.gzip_header_skipped): self.unused_data = "" if max_length < 0: raise ValueError("max_length must be a positive integer") # Suppress gzip header if present and wbits < 0 if self.gzip and not self.gzip_header_skipped: string = self.unused_data + string self.unused_data = "" try: string = _skip_gzip_header(string) except IndexError: # need more input! self.unused_data = string return "" self.gzip_header_skipped = True string = _to_input(string) self.inflater.setInput(string) inflated = _get_inflate_data(self.inflater, max_length) self._crc32.update(inflated) r = self.inflater.getRemaining() if r: if self.gzip and self.inflater.finished() and r == 8: # Consume tail, check inflate size, and crc32 crc,isize = struct.unpack_from("<LL", string[-r:]) mysize = self.inflater.getBytesWritten() & _MASK32 mycrc = self._crc32.getValue() & _MASK32 if mysize != isize: raise error('Error -3 while decompressing data: incorrect length check') if mycrc != crc: raise error("Error -3 while decompressing data: incorrect data check") elif max_length and not self.inflater.finished(): self.unconsumed_tail = string[-r:] else: self.unused_data += string[-r:] return inflated def flush(self, length=None): if self._ended: raise error("decompressobj may not be used after flush()") if length is None: length = 0 elif length <= 0: raise ValueError('length must be greater than zero') last = _get_inflate_data(self.inflater, length) self.inflater.end() return last