bool SkipCallback::handleZipEntry(std::istream& zipStream, const ZipLocalFileHeader& hdr) { if (!hdr.searchCRCAndSizesAfterData()) zipStream.seekg(hdr.getCompressedSize(), std::ios_base::cur); else ZipUtil::sync(zipStream); return true; }
ZipStreamBuf::ZipStreamBuf(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), _pIstr(&istr), _pOstr(0), _ptrBuf(), _ptrOBuf(), _ptrHelper(), _ptrOHelper(), _crc32(Poco::Checksum::TYPE_CRC32), _expectedCrc32(0), _checkCRC(true), _bytesWritten(0), _pHeader(0) { if (fileEntry.isDirectory()) return; _expectedCrc32 = fileEntry.getCRC(); std::streamoff start = fileEntry.getDataStartPos(); std::streamoff end = fileEntry.getDataEndPos(); _checkCRC = !fileEntry.searchCRCAndSizesAfterData(); if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE) { // Fake init bytes at beginning of stream std::string init = ZipUtil::fakeZLibInitString(fileEntry.getCompressionLevel()); // Fake adler at end of stream: just some dummy value, not checked anway std::string crc(4, ' '); if (fileEntry.searchCRCAndSizesAfterData()) { _ptrHelper = new AutoDetectInputStream(istr, init, crc, reposition, start); } else { _ptrHelper = new PartialInputStream(istr, start, end, reposition, init, crc); } _ptrBuf = new Poco::InflatingInputStream(*_ptrHelper, Poco::InflatingStreamBuf::STREAM_ZIP); } else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE) { if (fileEntry.searchCRCAndSizesAfterData()) { _ptrBuf = new AutoDetectInputStream(istr, "", "", reposition, start); } else { _ptrBuf = new PartialInputStream(istr, start, end, reposition); } } else throw Poco::NotImplementedException("Unsupported compression method"); }
ZipStreamBuf::ZipStreamBuf(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition): Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out), _pIstr(0), _pOstr(&ostr), _ptrBuf(), _ptrOBuf(), _ptrHelper(), _ptrOHelper(), _crc32(Poco::Checksum::TYPE_CRC32), _expectedCrc32(0), _checkCRC(false), _bytesWritten(0), _pHeader(&fileEntry) { if (fileEntry.isEncrypted()) throw Poco::NotImplementedException("Encryption not supported"); if (fileEntry.isDirectory()) { // only header, no payload, zero crc fileEntry.setSearchCRCAndSizesAfterData(false); fileEntry.setCompressedSize(0); fileEntry.setUncompressedSize(0); fileEntry.setCRC(0); std::string header = fileEntry.createHeader(); ostr.write(header.c_str(), static_cast<std::streamsize>(header.size())); } else { fileEntry.setSearchCRCAndSizesAfterData(!reposition); if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE) { int level = Z_DEFAULT_COMPRESSION; if (fileEntry.getCompressionLevel() == ZipCommon::CL_FAST || fileEntry.getCompressionLevel() == ZipCommon::CL_SUPERFAST) level = Z_BEST_SPEED; else if (fileEntry.getCompressionLevel() == ZipCommon::CL_MAXIMUM) level = Z_BEST_COMPRESSION; // ignore the zlib init string which is of size 2 and also ignore the 4 byte adler32 value at the end of the stream! _ptrOHelper = new PartialOutputStream(*_pOstr, 2, 4, false); _ptrOBuf = new Poco::DeflatingOutputStream(*_ptrOHelper, DeflatingStreamBuf::STREAM_ZLIB, level); } else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE) { _ptrOHelper = new PartialOutputStream(*_pOstr, 0, 0, false); _ptrOBuf = new PartialOutputStream(*_ptrOHelper, 0, 0, false); } else throw Poco::NotImplementedException("Unsupported compression method"); // now write the header to the ostr! std::string header = fileEntry.createHeader(); ostr.write(header.c_str(), static_cast<std::streamsize>(header.size())); } }
bool Decompress::handleZipEntry(std::istream& zipStream, const ZipLocalFileHeader& hdr) { if (hdr.isDirectory()) { // directory have 0 size, nth to read if (!_flattenDirs) { std::string dirName = hdr.getFileName(); if (!ZipCommon::isValidPath(dirName)) throw ZipException("Illegal entry name " + dirName + " containing parent directory reference"); Poco::Path dir(_outDir, dirName); dir.makeDirectory(); Poco::File aFile(dir); aFile.createDirectories(); } return true; } try { std::string fileName = hdr.getFileName(); if (_flattenDirs) { // remove path info Poco::Path p(fileName); p.makeFile(); fileName = p.getFileName(); } if (!ZipCommon::isValidPath(fileName)) throw ZipException("Illegal entry name " + fileName + " containing parent directory reference"); Poco::Path file(fileName); file.makeFile(); Poco::Path dest(_outDir, file); dest.makeFile(); if (dest.depth() > 0) { Poco::File aFile(dest.parent()); aFile.createDirectories(); } Poco::FileOutputStream out(dest.toString()); ZipInputStream inp(zipStream, hdr, false); Poco::StreamCopier::copyStream(inp, out); out.close(); Poco::File aFile(dest.toString()); if (!aFile.exists() || !aFile.isFile()) { std::pair<const ZipLocalFileHeader, const std::string> tmp = std::make_pair(hdr, "Failed to create output stream " + dest.toString()); EError.notify(this, tmp); return false; } if (!inp.crcValid()) { if (!_keepIncompleteFiles) aFile.remove(); std::pair<const ZipLocalFileHeader, const std::string> tmp = std::make_pair(hdr, "CRC mismatch. Corrupt file: " + dest.toString()); EError.notify(this, tmp); return false; } // cannot check against hdr.getUnCompressedSize if CRC and size are not set in hdr but in a ZipDataInfo // crc is typically enough to detect errors if (aFile.getSize() != hdr.getUncompressedSize() && !hdr.searchCRCAndSizesAfterData()) { if (!_keepIncompleteFiles) aFile.remove(); std::pair<const ZipLocalFileHeader, const std::string> tmp = std::make_pair(hdr, "Filesizes do not match. Corrupt file: " + dest.toString()); EError.notify(this, tmp); return false; } std::pair<const ZipLocalFileHeader, const Poco::Path> tmp = std::make_pair(hdr, file); EOk.notify(this, tmp); } catch (Poco::Exception& e) { std::pair<const ZipLocalFileHeader, const std::string> tmp = std::make_pair(hdr, std::string("Exception: " + e.displayText())); EError.notify(this, tmp); return false; } catch (...) { std::pair<const ZipLocalFileHeader, const std::string> tmp = std::make_pair(hdr, std::string("Unknown Exception")); EError.notify(this, tmp); return false; } return true; }