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));
		}
	}
Esempio n. 2
0
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();
}
Esempio n. 3
0
	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;
	}