Exemple #1
0
PWIZ_API_DECL string SHA1Calculator::hash(istream& is)
{
    CSHA1 sha1;
    is.clear();
    is.seekg(0);
    unsigned char buffer[65535];
    size_t bytesRead;
    while (is && (bytesRead = is.readsome(reinterpret_cast<char*>(buffer), 65535)) > 0)
        sha1.Update(buffer, static_cast<UINT_32>(bytesRead));
    sha1.Final();
    return formatHash(sha1);
}
Exemple #2
0
	static inline int readChar(istream& is) {
		char b[1];
		return (is.readsome(b, 1) == 1) ? b[0] : -1;
	}
bool read_next_file(istream& s, ZIPLocalFileHeader& fh)
{
	char b[30];
	
	if (s.readsome(b, 4) != 4)
		THROW(("Truncated ePub file"));

	if (b[0] != 'P' or b[1] != 'K')
		THROW(("Invalid ePub file"));
	
	if (b[2] == '0' and b[3] == '0')			// split
		THROW(("Split ePub archives are not supported"));
	
	if ((b[2] == '\001' and b[3] == '\002') or	// central directory
		(b[2] == '\005' and b[3] == '\006'))	// end of archive record
	{
		return false;
	}

	// now it must be a regular file entry, otherwise we bail out
	if (not (b[2] == '\003' and b[3] == '\004'))
		THROW(("Invalid ePub file, perhaps it is damaged"));

	if (s.readsome(b + 4, sizeof(b) - 4) != sizeof(b) - 4)
		THROW(("Truncated ePub file"));

	uint16 versionNeededToExtract, bitFlag, compressionMethod, fileNameLength, extraFieldLength;
	
	char* p = read(versionNeededToExtract, b + 4);
	p = read(bitFlag, p);
	p = read(compressionMethod, p);
	p = read(fh.file_mod_time, p);
	p = read(fh.file_mod_date, p);
	p = read(fh.crc, p);
	p = read(fh.compressed_size, p);
	p = read(fh.uncompressed_size, p);
	p = read(fileNameLength, p);
	p = read(extraFieldLength, p);

	// sanity checks
	if (compressionMethod != 0 and compressionMethod != 8)
		THROW(("Unsupported compression method used in ePub file"));

	assert(p == b + sizeof(b));
	
	// read file name
	
	vector<char> fn(fileNameLength);
	if (s.readsome(&fn[0], fileNameLength) != fileNameLength)
		THROW(("Truncated ePub file"));
	
	fh.filename.assign(&fn[0], fileNameLength);
	
	// skip over the extra data
	
	s.seekg(extraFieldLength, ios::cur);
	
	// OK, now read in the data and inflate if required

	fh.data.clear();

	// save the offset in the stream to be able to seek back if needed
	std::streamsize offset = s.tellg();
	
	if (compressionMethod == 0) // no compression
	{
		if (fh.compressed_size > 0)
		{
			vector<char> b(fh.compressed_size);
			if (s.readsome(&b[0], fh.compressed_size) != fh.compressed_size)
				THROW(("Truncated ePub file"));
			
			fh.data.assign(&b[0], fh.compressed_size);
		}
	}
	else	 // inflate
	{
		if (fh.compressed_size == 0 and not (bitFlag & kZipLengthAtEndMask))
			THROW(("Invalid ePub file, missing compressed size"));
		
		// setup a boost::iostreams pair to read the compressed data
		io::zlib_params params;
		params.noheader = true;	// don't read header, i.e. true deflate compression
		params.calculate_crc = true;
		
		io::zlib_decompressor z_stream(params);
		
		io::filtering_streambuf<io::input> in;
		in.push(z_stream);
		in.push(s);
		
		io::filtering_ostream out(io::back_inserter(fh.data));
		io::copy(in, out);
		
		s.seekg(offset + z_stream.filter().total_in(), ios::beg);
		
		// now read the trailing length if needed
		
		if (bitFlag & kZipLengthAtEndMask)
		{
			char b2[16];
			if (s.readsome(b2, sizeof(b2)) != sizeof(b2))
				THROW(("Truncated ePub file"));

			uint32 signature;
			char* p = read(signature, b2);
			
			if (signature == 0x08074b50UL)
				p = read(fh.crc, p);
			else
			{
				fh.crc = signature;
				s.seekg(-4, ios::cur);
			}
			
			p = read(fh.compressed_size, p);
			p = read(fh.uncompressed_size, p);
		}
		
		// OK, so decompression succeeded, now validate the data

//		if (compressed_size != fh.compressed_size)
//			THROW(("ePub data, compressed data is wrong size"));

		if (static_cast<uint32>(z_stream.total_out()) != fh.uncompressed_size)
			THROW(("ePub data, uncompressed data is wrong size"));
		
		if (z_stream.crc() != fh.crc)
			THROW(("ePub data, bad crc"));
	}
	
	return true;
}