void ZipIODevice_FileEntry::init() { iodevice.seek(file_entry.impl->record.relative_offset_of_local_header, IODevice::seek_set); file_header.load(iodevice); //This fix allows OS X created .zips to be opened - SAR if (file_header.general_purpose_bit_flag & ZIP_CRC32_IN_FILE_DESCRIPTOR) //if this bit is set, it means the local header data for sizes was not { //the correct size data is not in the local header.. luckily, we have a real copy from the entry database file_header.compressed_size = file_entry.get_compressed_size(); file_header.uncompressed_size = file_entry.get_uncompressed_size(); } pos = 0; compressed_pos = 0; // Initialize decompression: int result = 0; switch (file_header.compression_method) { case zip_compress_store: // no compression break; case zip_compress_deflate: memset(&zs, 0, sizeof(mz_stream)); zs.next_in = nullptr; zs.avail_in = 0; zs.zalloc = nullptr; zs.zfree = nullptr; zs.opaque = nullptr; //result = inflateInit(&zs); result = mz_inflateInit2(&zs, -15); // Undocumented: if wbits is negative, zlib skips header check if (result != MZ_OK) throw Exception("Zlib inflateInit failed for zip index!"); zstream_open = true; break; case zip_compress_shrunk: case zip_compress_expand_factor_1: case zip_compress_expand_factor_2: case zip_compress_expand_factor_3: case zip_compress_expand_factor_4: case zip_compress_implode: case zip_compress_tokenize: case zip_compress_deflate64: case zip_compress_pkware_implode: default: throw Exception(string_format("Unsupported compression method %1", file_header.compression_method)); } }
DataBuffer ZLibCompression::decompress(const DataBuffer &data, bool raw) { const int window_bits = 15; DataBuffer zbuffer(1024*1024); IODevice_Memory output; mz_stream zs = { nullptr }; int result = mz_inflateInit2(&zs, raw ? -window_bits : window_bits); if (result != MZ_OK) throw Exception("Zlib inflateInit failed"); zs.next_in = (unsigned char *) data.get_data(); zs.avail_in = data.get_size(); // Continue feeding zlib data until we get our data: while (true) { zs.next_out = (unsigned char *) zbuffer.get_data(); zs.avail_out = zbuffer.get_size(); // Decompress data: int result = mz_inflate(&zs, 0); if (result == MZ_NEED_DICT) throw Exception("Zlib inflate wants a dictionary!"); if (result == MZ_DATA_ERROR) throw Exception("Zip data stream is corrupted"); if (result == MZ_STREAM_ERROR) throw Exception("Zip stream structure was inconsistent!"); if (result == MZ_MEM_ERROR) throw Exception("Zlib did not have enough memory to decompress file!"); if (result == MZ_BUF_ERROR) throw Exception("Not enough data in buffer when Z_FINISH was used"); if (result != MZ_OK && result != MZ_STREAM_END) throw Exception("Zlib inflate failed while decompressing zip file!"); output.write(zbuffer.get_data(), zbuffer.get_size() - zs.avail_out); if (result == MZ_STREAM_END) break; } mz_inflateEnd(&zs); return output.get_data(); }
bool ZipReader::read_local_file_header(bool allow_data_descriptor) { try { impl->local_header.load(impl->input); } catch (const Exception&) { return false; } if (has_data_descriptor() && !allow_data_descriptor) throw Exception("Zip file entry uses a data descriptor"); if ((impl->local_header.general_purpose_bit_flag & ZIP_ENCRYPTED) || (impl->local_header.general_purpose_bit_flag & ZIP_STRONG_ENCRYPTED)) throw Exception("Zip file entry is encrypted"); if (impl->zstream_open) mz_inflateEnd(&impl->zs); impl->zstream_open = false; if (impl->local_header.compression_method == zip_compress_deflate) { memset(&impl->zs, 0, sizeof(mz_stream)); int result = mz_inflateInit2(&impl->zs, -15); // Undocumented: if wbits is negative, zlib skips header check if (result != MZ_OK) throw Exception("Zlib inflateInit failed for zip index!"); impl->zstream_open = true; impl->compressed_pos = 0; } else if (impl->local_header.compression_method != zip_compress_store) { throw Exception("Zip file entry is compressed with an unsupported compression method"); } return true; }