From 86333d9103e5a7a55909eb4a81d9cd28e043ca35 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 17 Feb 2017 20:18:57 +0100 Subject: [PATCH] one more fix for #1597: check for empty streams in Compress::addEntry() so this also works with non-seekable output streams --- Zip/src/Compress.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Zip/src/Compress.cpp b/Zip/src/Compress.cpp index f37a7b80e..51e644045 100644 --- a/Zip/src/Compress.cpp +++ b/Zip/src/Compress.cpp @@ -57,9 +57,14 @@ void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, { std::string ext = Poco::toLower(fileName.getExtension()); if (_storeExtensions.find(ext) != _storeExtensions.end()) + { cm = ZipCommon::CM_STORE; + cl = ZipCommon::CL_NORMAL; + } else + { cm = ZipCommon::CM_DEFLATE; + } } std::string fn = ZipUtil::validZipEntryFileName(fileName); @@ -67,12 +72,27 @@ void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, if (!in.good()) throw ZipException("Invalid input stream"); + // Check if stream is empty. + // In this case, we have to set compression to STORE, otherwise + // extraction will fail with various tools. + const int eof = std::char_traits::eof(); + int firstChar = in.get(); + if (firstChar == eof) + { + cm = ZipCommon::CM_STORE; + cl = ZipCommon::CL_NORMAL; + } + std::streamoff localHeaderOffset = _offset; ZipLocalFileHeader hdr(fileName, lastModifiedAt, cm, cl, _forceZip64); hdr.setStartPos(localHeaderOffset); ZipOutputStream zipOut(_out, hdr, _seekableOut); - Poco::StreamCopier::copyStream(in, zipOut); + if (firstChar != eof) + { + zipOut.put(static_cast(firstChar)); + Poco::StreamCopier::copyStream(in, zipOut); + } Poco::UInt64 extraDataSize; zipOut.close(extraDataSize); _offset = hdr.getEndPos();