ZipLocalFileHeader::ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, ParseCallback& callback): _forceZip64(false), _rawHeader(), _startPos(inp.tellg()), _endPos(-1), _fileName(), _lastModifiedAt(), _extraField(), _crc32(0), _compressedSize(0), _uncompressedSize(0) { poco_assert_dbg( (EXTRA_FIELD_POS+EXTRA_FIELD_LENGTH) == FULLHEADER_SIZE); if (assumeHeaderRead) _startPos -= ZipCommon::HEADER_SIZE; parse(inp, assumeHeaderRead); bool ok = callback.handleZipEntry(inp, *this); if (ok) { if (searchCRCAndSizesAfterData()) { char header[ZipCommon::HEADER_SIZE]={'\x00', '\x00', '\x00', '\x00'}; inp.read(header, ZipCommon::HEADER_SIZE); if (std::memcmp(header, ZipDataInfo64::HEADER, sizeof(header)) == 0) { ZipDataInfo64 nfo(inp, true); setCRC(nfo.getCRC32()); setCompressedSize(nfo.getCompressedSize()); setUncompressedSize(nfo.getUncompressedSize()); } else { ZipDataInfo nfo(inp, true); setCRC(nfo.getCRC32()); setCompressedSize(nfo.getCompressedSize()); setUncompressedSize(nfo.getUncompressedSize()); } } } else { poco_assert_dbg(!searchCRCAndSizesAfterData()); ZipUtil::sync(inp); } _endPos = _startPos + getHeaderSize() + _compressedSize; // exclude the data block! }
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 ZipArchive::parse(std::istream& in, ParseCallback& pc) { // read 4 bytes while (in.good() && !in.eof()) { char header[ZipCommon::HEADER_SIZE]={'\x00', '\x00', '\x00', '\x00'}; in.read(header, ZipCommon::HEADER_SIZE); if (in.eof()) return; if (std::memcmp(header, ZipLocalFileHeader::HEADER, ZipCommon::HEADER_SIZE) == 0) { ZipLocalFileHeader entry(in, true, pc); poco_assert (_entries.insert(std::make_pair(entry.getFileName(), entry)).second); } else if (std::memcmp(header, ZipFileInfo::HEADER, ZipCommon::HEADER_SIZE) == 0) { ZipFileInfo info(in, true); FileHeaders::iterator it = _entries.find(info.getFileName()); if (it != _entries.end()) { it->second.setStartPos(info.getRelativeOffsetOfLocalHeader()); } poco_assert (_infos.insert(std::make_pair(info.getFileName(), info)).second); } else if (std::memcmp(header, ZipArchiveInfo::HEADER, ZipCommon::HEADER_SIZE) == 0) { ZipArchiveInfo nfo(in, true); poco_assert (_disks.insert(std::make_pair(nfo.getDiskNumber(), nfo)).second); } else { if (_disks.empty()) throw Poco::IllegalStateException("Illegal header in zip file"); else throw Poco::IllegalStateException("Garbage after directory header"); } } }
bool MakeJunction(const string& target, const string& junkpath, mgr_file::Attrs* attrs) { if (mgr_file::Exists(junkpath)) return false; if (!mgr_file::Exists(target)) return false; mgr_file::Info nfo(target); if (!nfo.IsDir()) return false; mgr_file::MkDir(junkpath, attrs); str::u16string tgt(target); str::u16string junk(junkpath); ResHandle hLink(OpenLinkHandle(str::u16string(junkpath).c_str(), GENERIC_WRITE)); if ((bool)hLink) { str::u16string SubstituteName("\\??\\" + target); REPARSE_BUF rdb; rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; rdb.fill(tgt.c_str(), tgt.size(), SubstituteName.c_str(), SubstituteName.size()); if (rdb.set(junk.c_str())) { return true; } } mgr_file::Remove(junkpath); return false; }