int ZipStreamBuf::readFromDevice(char* buffer, std::streamsize length) { if (!_ptrBuf) return 0; // directory entry _ptrBuf->read(buffer, length); int cnt = _ptrBuf->gcount(); if (cnt > 0) { _crc32.update(buffer, cnt); } else { if (_crc32.checksum() != _expectedCrc32) { if (_checkCRC) throw ZipException("CRC failure"); else { // the CRC value is written directly after the data block // parse it directly from the input stream ZipDataInfo nfo(*_pIstr, false); // now push back the header to the stream, so that the ZipLocalFileHeader can read it Poco::Int32 size = static_cast<Poco::Int32>(nfo.getFullHeaderSize()); _expectedCrc32 = nfo.getCRC32(); const char* rawHeader = nfo.getRawHeader(); for (Poco::Int32 i = size-1; i >= 0; --i) _pIstr->putback(rawHeader[i]); if (!crcValid()) throw ZipException("CRC failure"); } } } return cnt; }
void ZipUtil::verifyZipEntryFileName(const std::string& fn) { if (fn.find("\\") != std::string::npos) throw ZipException("Illegal entry name " + fn + " containing \\"); if (fn == "/") throw ZipException("Illegal entry name /"); if (fn.empty()) throw ZipException("Illegal empty entry name"); if (!ZipCommon::isValidPath(fn)) throw ZipException("Illegal entry name " + fn + " containing parent directory reference"); }
_Ptr<IO::Stream> File::GetStream() { FileRawStream* rawstream = new FileRawStream(m_ar->m_p->m_stream, m_bytepos+m_dataoffset, m_compressed_size); if (m_compression_method == 0) // No compression { return rawstream; } else if (m_compression_method == 8) // Deflate { IO::Inflate* stream = new IO::Inflate(rawstream, 7/*compressionInfo*/, m_uncompressed_size); return stream; } else { raise(ZipException("Unknown compression method")); return NULL; } }
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; }