Пример #1
0
 def _get_lzma_decompressor(self, coders: List[Dict[str, Any]],
                            unpacksize: int):
     filters: List[Dict[str, Any]] = []
     lzma1 = False
     for coder in coders:
         if coder["numinstreams"] != 1 or coder["numoutstreams"] != 1:
             raise UnsupportedCompressionMethodError(
                 coders,
                 "Only a simple compression method is currently supported.")
         if not SupportedMethods.is_native_coder(coder):
             raise UnsupportedCompressionMethodError(
                 coders, "Non python native method is requested.")
         properties = coder.get("properties", None)
         filter_id = SupportedMethods.get_filter_id(coder)
         if filter_id == FILTER_LZMA:
             lzma1 = True
         if properties is not None:
             filters[:0] = [
                 lzma._decode_filter_properties(filter_id, properties)
             ]  # type: ignore
         else:
             filters[:0] = [{"id": filter_id}]
     if lzma1:
         return LZMA1Decompressor(filters, unpacksize)
     else:
         return lzma.LZMADecompressor(format=lzma.FORMAT_RAW,
                                      filters=filters)
Пример #2
0
 def _get_alternative_decompressor(
     self,
     coder: Dict[str, Any],
     unpacksize=None,
     password=None
 ) -> Union[bz2.BZ2Decompressor, lzma.LZMADecompressor,
            ISevenZipDecompressor]:  # noqa
     filter_id = SupportedMethods.get_filter_id(coder)
     # Special treatment for BCJ filters
     if filter_id in [
             FILTER_X86, FILTER_ARM, FILTER_ARMTHUMB, FILTER_POWERPC,
             FILTER_SPARC
     ]:
         return algorithm_class_map[filter_id][1](size=unpacksize)
     # Check supported?
     if SupportedMethods.is_native_coder(coder):
         raise UnsupportedCompressionMethodError(
             'Unknown method code:{}'.format(coder['method']))
     if filter_id not in algorithm_class_map:
         raise UnsupportedCompressionMethodError(
             'Unknown method filter_id:{}'.format(filter_id))
     #
     if SupportedMethods.is_crypto_id(filter_id):
         return algorithm_class_map[filter_id][1](coder['properties'],
                                                  password)
     elif SupportedMethods.need_property(filter_id):
         return algorithm_class_map[filter_id][1](coder['properties'])
     else:
         return algorithm_class_map[filter_id][1]()
Пример #3
0
 def __init__(self, properties: bytes, blocksize: int):
     if len(properties) not in [3, 5]:
         raise UnsupportedCompressionMethodError(
             properties, "Zstd takes 3 or 5 bytes properties.")
     if (properties[0], properties[1], 0) > pyzstd.zstd_version_info:
         raise UnsupportedCompressionMethodError(
             properties, "Zstd version of archive is higher than us.")
     self.decompressor = pyzstd.ZstdDecompressor()
Пример #4
0
 def __init__(self,
              filters=None,
              password=None,
              blocksize: Optional[int] = None):
     self.filters: List[Dict[str, Any]] = []
     self.chain: List[ISevenZipCompressor] = []
     self.digest = 0
     self.packsize = 0
     self._unpacksizes: List[int] = []
     if blocksize:
         self._block_size = blocksize
     else:
         self._block_size = get_default_blocksize()
     if filters is None:
         self.filters = [{
             "id": lzma.FILTER_LZMA2,
             "preset": 7 | lzma.PRESET_EXTREME
         }]
     else:
         self.filters = filters
     if len(self.filters) > 4:
         raise UnsupportedCompressionMethodError(
             filters, "Maximum cascade of filters is 4 but got {}.".format(
                 len(self.filters)))
     self.methods_map = [
         SupportedMethods.is_native_filter(filter)
         for filter in self.filters
     ]
     self.coders: List[Dict[str, Any]] = []
     if all(self.methods_map) and SupportedMethods.is_compressor(
             self.filters[-1]):  # all native
         self._set_native_compressors_coders(self.filters)
         return
     #
     has_lzma2 = False
     for f in self.filters:
         if f["id"] == FILTER_LZMA2:
             has_lzma2 = True
             break
     if not has_lzma2:
         # when specified other than lzma2, BCJ filters should be alternative
         for i, f in enumerate(self.filters):
             if (f["id"] == FILTER_X86 or f["id"] == FILTER_ARM
                     or f["id"] == FILTER_ARMTHUMB
                     or f["id"] == FILTER_SPARC
                     or f["id"] == FILTER_POWERPC):
                 self.methods_map[i] = False
     #
     if not any(self.methods_map):  # all alternative
         for f in filters:
             self._set_alternate_compressors_coders(f, password)
     elif SupportedMethods.is_crypto_id(self.filters[-1]["id"]) and all(
             self.methods_map[:-1]):
         self._set_native_compressors_coders(self.filters[:-1])
         self._set_alternate_compressors_coders(self.filters[-1], password)
     else:
         raise UnsupportedCompressionMethodError(
             filters, "Unknown combination of methods.")
Пример #5
0
 def __init__(self, properties: bytes, block_size: int):
     if len(properties) != 3:
         raise UnsupportedCompressionMethodError(
             properties, "Unknown size of properties are passed")
     if (properties[0], properties[1]) > (brotli_major, brotli_minor):
         raise UnsupportedCompressionMethodError(
             properties,
             "Unsupported brotli version: {}.{} our {}.{}".format(
                 properties[0], properties[1], brotli_major, brotli_minor),
         )
     self._prefix_checked = False
     self._decompressor = brotli.Decompressor()
Пример #6
0
 def __init__(self, properties: bytes, blocksize: Optional[int] = None):
     if not isinstance(properties, bytes):
         raise UnsupportedCompressionMethodError(
             properties, "Unknown type of properties is passed")
     if len(properties) == 5:
         order, mem = struct.unpack("<BL", properties)
     elif len(properties) == 7:
         order, mem, _, _ = struct.unpack("<BLBB", properties)
     else:
         raise UnsupportedCompressionMethodError(
             properties, "Unknown size of properties is passed")
     self.decoder = pyppmd.Ppmd7Decoder(order, mem)
Пример #7
0
 def __init__(self, filters=None, password=None):
     self.filters = []  # type: List[ISevenZipCompressor]
     self.chain = []
     self.digest = 0
     self.packsize = 0
     self._unpacksizes = []
     if filters is None:
         self.filters = [{"id": lzma.FILTER_LZMA2, "preset": 7 | lzma.PRESET_EXTREME}]
     else:
         self.filters = filters
     if len(self.filters) > 4:
         raise UnsupportedCompressionMethodError('Maximum cascade of filters is 4 but got {}.'.format(len(self.filters)))
     self.methods_map = [SupportedMethods.is_native_filter(filter) for filter in self.filters]
     self.coders = []
     if all(self.methods_map) and SupportedMethods.is_compressor(self.filters[-1]):  # all native
         self._set_native_compressors_coders(self.filters)
         return
     #
     for i, f in enumerate(self.filters):
         if f['id'] == FILTER_X86:
             self.methods_map[i] = False
     #
     if not any(self.methods_map):  # all alternative
         for f in filters:
             self._set_alternate_compressors_coders(f, password)
     elif SupportedMethods.is_crypto_id(self.filters[-1]['id']) and all(self.methods_map[:-1]):
         self._set_native_compressors_coders(self.filters[:-1])
         self._set_alternate_compressors_coders(self.filters[-1], password)
     else:
         raise UnsupportedCompressionMethodError
Пример #8
0
    def _get_headerdata_from_streams(self, fp: BinaryIO,
                                     streams: StreamsInfo) -> BytesIO:
        """get header data from given streams.unpackinfo and packinfo.
        folder data are stored in raw data positioned in afterheader."""
        buffer = io.BytesIO()
        src_start = self._start_pos
        for folder in streams.unpackinfo.folders:
            if folder.is_encrypted():
                raise UnsupportedCompressionMethodError()

            uncompressed = folder.unpacksizes
            if not isinstance(uncompressed, (list, tuple)):
                uncompressed = [uncompressed] * len(folder.coders)
            compressed_size = streams.packinfo.packsizes[0]
            uncompressed_size = uncompressed[-1]

            src_start += streams.packinfo.packpos
            fp.seek(src_start, 0)
            decompressor = folder.get_decompressor(compressed_size)
            folder_data = decompressor.decompress(
                fp.read(compressed_size))[:uncompressed_size]
            src_start += uncompressed_size
            if folder.digestdefined:
                if folder.crc != calculate_crc32(folder_data):
                    raise Bad7zFile('invalid block data')
            buffer.write(folder_data)
        buffer.seek(0, 0)
        return buffer
Пример #9
0
 def __init__(self,
              aes_properties: bytes,
              password: str,
              blocksize: Optional[int] = None) -> None:
     firstbyte = aes_properties[0]
     numcyclespower = firstbyte & 0x3F
     if firstbyte & 0xC0 != 0:
         saltsize = (firstbyte >> 7) & 1
         ivsize = (firstbyte >> 6) & 1
         secondbyte = aes_properties[1]
         saltsize += secondbyte >> 4
         ivsize += secondbyte & 0x0F
         assert len(aes_properties) == 2 + saltsize + ivsize
         salt = aes_properties[2:2 + saltsize]
         iv = aes_properties[2 + saltsize:2 + saltsize + ivsize]
         assert len(salt) == saltsize
         assert len(iv) == ivsize
         assert numcyclespower <= 24
         if ivsize < 16:
             iv += bytes("\x00" * (16 - ivsize), "ascii")
         key = calculate_key(password.encode("utf-16LE"), numcyclespower,
                             salt, "sha256")
         self.cipher = AES.new(key, AES.MODE_CBC, iv)
         if blocksize:
             self.buf = Buffer(size=blocksize + 16)
         else:
             self.buf = Buffer(size=get_default_blocksize() + 16)
     else:
         raise UnsupportedCompressionMethodError(firstbyte,
                                                 "Wrong 7zAES properties")
Пример #10
0
 def decompress(self,
                data: Union[bytes, bytearray, memoryview],
                max_length: int = -1):
     if not self._prefix_checked:
         # check first 4bytes
         if data[:4] == b"\x50\x2a\x4d\x18":
             raise UnsupportedCompressionMethodError(
                 data[:4],
                 "Unauthorized and modified Brotli data (skipable frame) found."
             )
         self._prefix_checked = True
     return self._decompressor.process(data)
Пример #11
0
 def raise_unsupported_method_id(cls, coder):
     if coder["method"] == COMPRESSION_METHOD.P7Z_BCJ2:
         raise UnsupportedCompressionMethodError(
             coder["method"],
             "BCJ2 filter is not supported by py7zr."
             " Please consider to contribute to XZ/liblzma project"
             " and help Python core team implementing it."
             " Or please use another tool to extract it.",
         )
     if coder["method"] == COMPRESSION_METHOD.MISC_DEFLATE64:
         raise UnsupportedCompressionMethodError(
             coder["method"],
             "DEFLATE64 compression is not supported by py7zr yet."
             " Please check the progress in py7zr project home page.",
         )
     if coder["method"] == COMPRESSION_METHOD.MISC_LZ4:
         raise UnsupportedCompressionMethodError(
             coder["method"],
             "Archive is compressed by an unsupported algorythm LZ4.")
     raise UnsupportedCompressionMethodError(
         coder["method"],
         "Archive is compressed by an unsupported compression algorythm.")
Пример #12
0
 def decompress(self,
                data: Union[bytes, bytearray, memoryview],
                max_length: int = -1) -> bytes:
     if not self._enabled:
         raise UnsupportedCompressionMethodError(
             None, "inflate64 is not installed.")
     if len(data) == 0:
         if self.flushed:
             return b""
         else:
             self.flushed = True
             return self._decompressor.inflate(b"")
     return self._decompressor.inflate(data)
Пример #13
0
 def _set_alternate_compressors_coders(self, alt_filter, password=None):
     filter_id = alt_filter["id"]
     properties = None
     if filter_id not in algorithm_class_map:
         raise UnsupportedCompressionMethodError(
             filter_id, "Unknown filter_id is given.")
     elif SupportedMethods.is_crypto_id(filter_id):
         compressor = algorithm_class_map[filter_id][0](password)
     elif SupportedMethods.need_property(filter_id):
         if filter_id == FILTER_ZSTD:
             level = alt_filter.get("level", 3)
             properties = struct.pack("BBBBB", pyzstd.zstd_version_info[0],
                                      pyzstd.zstd_version_info[1], level, 0,
                                      0)
             compressor = algorithm_class_map[filter_id][0](level=level)
         elif filter_id == FILTER_PPMD:
             properties = PpmdCompressor.encode_filter_properties(
                 alt_filter)
             compressor = algorithm_class_map[filter_id][0](properties)
         elif filter_id == FILTER_BROTLI:
             level = alt_filter.get("level", 11)
             properties = struct.pack("BBB", brotli_major, brotli_minor,
                                      level)
             compressor = algorithm_class_map[filter_id][0](level)
     else:
         compressor = algorithm_class_map[filter_id][0]()
     if SupportedMethods.is_crypto_id(filter_id):
         properties = compressor.encode_filter_properties()
     self.chain.append(compressor)
     self._unpacksizes.append(0)
     self.coders.insert(
         0,
         {
             "method": SupportedMethods.get_method_id(filter_id),
             "properties": properties,
             "numinstreams": 1,
             "numoutstreams": 1,
         },
     )
Пример #14
0
 def __init__(self,
              coders: List[Dict[str, Any]],
              packsize: int,
              unpacksizes: List[int],
              crc: Optional[int],
              password: Optional[str] = None) -> None:
     self.input_size = packsize
     self.unpacksizes = unpacksizes
     self.consumed = 0  # type: int
     self.crc = crc
     self.digest = 0
     if len(coders) > 4:
         raise UnsupportedCompressionMethodError(
             'Maximum cascade of filters is 4 but got {}.'.format(
                 len(coders)))
     self.methods_map = [
         SupportedMethods.is_native_coder(coder) for coder in coders
     ]  # type: List[bool]
     # Check if password given for encrypted archive
     if SupportedMethods.needs_password(coders) and password is None:
         raise PasswordRequired(
             "Password is required for extracting given archive.")
     # Check filters combination and required parameters
     if len(coders) >= 2:
         target_compressor = False
         has_bcj = False
         bcj_index = -1
         for i, coder in enumerate(coders):
             filter_id = SupportedMethods.get_filter_id(coder)
             if SupportedMethods.is_compressor_id(
                     filter_id) and filter_id != FILTER_LZMA2:
                 target_compressor = True
             if filter_id in [
                     FILTER_X86, FILTER_ARM, FILTER_ARMTHUMB,
                     FILTER_POWERPC, FILTER_SPARC
             ]:
                 has_bcj = True
                 bcj_index = i
             # hack for LZMA1+BCJ which should be native+alternative
             if target_compressor and has_bcj:
                 self.methods_map[bcj_index] = False
                 break
     self.chain = [
     ]  # type: List[Union[bz2.BZ2Decompressor, lzma.LZMADecompressor, ISevenZipDecompressor]]
     self._unpacksizes = []  # type: List[int]
     self.input_size = self.input_size
     shift = 0
     prev = False
     for i, r in enumerate(self.methods_map):
         shift += 1 if r and prev else 0
         prev = r
         self._unpacksizes.append(unpacksizes[i - shift])
     self._unpacked = [0 for _ in range(len(self._unpacksizes))]
     self.consumed = 0
     self._unused = bytearray()
     self._buf = bytearray()
     # ---
     if all(self.methods_map):
         decompressor = self._get_lzma_decompressor(coders, unpacksizes[-1])
         self.chain.append(decompressor)
     elif not any(self.methods_map):
         for i in range(len(coders)):
             self.chain.append(
                 self._get_alternative_decompressor(coders[i],
                                                    unpacksizes[i],
                                                    password))
     elif any(self.methods_map):
         for i in range(len(coders)):
             if (not any(self.methods_map[:i])) and all(
                     self.methods_map[i:]):
                 for j in range(i):
                     self.chain.append(
                         self._get_alternative_decompressor(
                             coders[j], unpacksizes[j], password))
                 self.chain.append(
                     self._get_lzma_decompressor(coders[i:],
                                                 unpacksizes[i]))
                 break
         else:
             for i in range(len(coders)):
                 if self.methods_map[i]:
                     self.chain.append(
                         self._get_lzma_decompressor([coders[i]],
                                                     unpacksizes[i]))
                 else:
                     self.chain.append(
                         self._get_alternative_decompressor(
                             coders[i], unpacksizes[i], password))
     else:
         raise UnsupportedCompressionMethodError
Пример #15
0
 def need_property(cls, filter_id):
     method = cls._find_method("filter_id", filter_id)
     if method is None:
         raise UnsupportedCompressionMethodError(
             filter_id, "Found an sunpported filter id.")
     return method["need_prop"]
Пример #16
0
 def raise_unsupported_filter_id(cls, filter_id):
     raise UnsupportedCompressionMethodError(
         filter_id, "Found an unsupported filter id is specified."
         "Please use another compression method.")
Пример #17
0
 def is_native_filter(cls, filter) -> bool:
     method = cls._find_method("filter_id", filter["id"])
     if method is None:
         raise UnsupportedCompressionMethodError(
             filter["id"], "Unknown method id is given.")
     return method["native"]