fixed SF# 2583934: Zip: No Unix permissions set

This commit is contained in:
Guenter Obiltschnig 2009-02-18 16:04:14 +00:00
parent 717dd9cf45
commit 12c1ae5823
4 changed files with 1284 additions and 1252 deletions

View File

@ -1,468 +1,484 @@
// //
// ZipFileInfo.h // ZipFileInfo.h
// //
// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipFileInfo.h#3 $ // $Id: //poco/Main/Zip/include/Poco/Zip/ZipFileInfo.h#8 $
// //
// Library: Zip // Library: Zip
// Package: Zip // Package: Zip
// Module: ZipFileInfo // Module: ZipFileInfo
// //
// Definition of the ZipFileInfo class. // Definition of the ZipFileInfo class.
// //
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
#ifndef Zip_ZipFileInfo_INCLUDED #ifndef Zip_ZipFileInfo_INCLUDED
#define Zip_ZipFileInfo_INCLUDED #define Zip_ZipFileInfo_INCLUDED
#include "Poco/Zip/Zip.h" #include "Poco/Zip/Zip.h"
#include "Poco/Zip/ZipCommon.h" #include "Poco/Zip/ZipCommon.h"
#include "Poco/Zip/ZipUtil.h" #include "Poco/Zip/ZipUtil.h"
namespace Poco { namespace Poco {
namespace Zip { namespace Zip {
class ZipLocalFileHeader; class ZipLocalFileHeader;
class Zip_API ZipFileInfo class Zip_API ZipFileInfo
/// Stores a Zip directory entry of a file /// Stores a Zip directory entry of a file
{ {
public: public:
static const char HEADER[ZipCommon::HEADER_SIZE]; static const char HEADER[ZipCommon::HEADER_SIZE];
ZipFileInfo(const ZipLocalFileHeader& header); ZipFileInfo(const ZipLocalFileHeader& header);
/// Creates a ZipFileInfo from a ZipLocalFileHeader /// Creates a ZipFileInfo from a ZipLocalFileHeader
ZipFileInfo(std::istream& in, bool assumeHeaderRead); ZipFileInfo(std::istream& in, bool assumeHeaderRead);
/// Creates the ZipFileInfo by parsing the input stream. /// Creates the ZipFileInfo by parsing the input stream.
/// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside. /// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside.
~ZipFileInfo(); ~ZipFileInfo();
/// Destroys the ZipFileInfo. /// Destroys the ZipFileInfo.
Poco::UInt32 getRelativeOffsetOfLocalHeader() const; Poco::UInt32 getRelativeOffsetOfLocalHeader() const;
/// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header /// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header
ZipCommon::CompressionMethod getCompressionMethod() const; ZipCommon::CompressionMethod getCompressionMethod() const;
bool isEncrypted() const; bool isEncrypted() const;
const Poco::DateTime& lastModifiedAt() const; const Poco::DateTime& lastModifiedAt() const;
Poco::UInt32 getCRC() const; Poco::UInt32 getCRC() const;
Poco::UInt32 getHeaderSize() const; Poco::UInt32 getHeaderSize() const;
/// Returns the total size of the header including filename + other additional fields /// Returns the total size of the header including filename + other additional fields
Poco::UInt32 getCompressedSize() const; Poco::UInt32 getCompressedSize() const;
Poco::UInt32 getUncompressedSize() const; Poco::UInt32 getUncompressedSize() const;
const std::string& getFileName() const; const std::string& getFileName() const;
bool isFile() const; bool isFile() const;
bool isDirectory() const; bool isDirectory() const;
bool hasExtraField() const; bool hasExtraField() const;
const std::string& getExtraField() const; const std::string& getExtraField() const;
const std::string& getFileComment() const; const std::string& getFileComment() const;
void getVersionMadeBy(int& major, int& minor); void getVersionMadeBy(int& major, int& minor);
/// The ZIP version used to create the file /// The ZIP version used to create the file
void getRequiredVersion(int& major, int& minor); void getRequiredVersion(int& major, int& minor);
/// The minimum version required to extract the data /// The minimum version required to extract the data
ZipCommon::HostSystem getHostSystem() const; ZipCommon::HostSystem getHostSystem() const;
Poco::UInt16 getDiskNumberStart() const; Poco::UInt16 getDiskNumberStart() const;
/// The number of the disk on which this file begins (multidisk archives) /// The number of the disk on which this file begins (multidisk archives)
ZipCommon::FileType getFileType() const; ZipCommon::FileType getFileType() const;
/// Binary or ASCII file? /// Binary or ASCII file?
std::string createHeader() const; std::string createHeader() const;
void setOffset(Poco::UInt32 val); void setOffset(Poco::UInt32 val);
private: private:
void setCRC(Poco::UInt32 val); void setCRC(Poco::UInt32 val);
void setCompressedSize(Poco::UInt32 val); void setCompressedSize(Poco::UInt32 val);
void setUncompressedSize(Poco::UInt32 val); void setUncompressedSize(Poco::UInt32 val);
void setCompressionMethod(ZipCommon::CompressionMethod cm); void setCompressionMethod(ZipCommon::CompressionMethod cm);
void setCompressionLevel(ZipCommon::CompressionLevel cl); void setCompressionLevel(ZipCommon::CompressionLevel cl);
void setRequiredVersion(int major, int minor); void setRequiredVersion(int major, int minor);
void setHostSystem(ZipCommon::HostSystem hs); void setHostSystem(ZipCommon::HostSystem hs);
void setLastModifiedAt(const Poco::DateTime& dt); void setLastModifiedAt(const Poco::DateTime& dt);
void setEncryption(bool val); void setEncryption(bool val);
void setFileNameLength(Poco::UInt16 size); void setFileNameLength(Poco::UInt16 size);
void setFileName(const std::string& str); void setFileName(const std::string& str);
void parse(std::istream& in, bool assumeHeaderRead); void setExternalFileAttributes(Poco::UInt32 attrs);
void parseDateTime(); void parse(std::istream& in, bool assumeHeaderRead);
Poco::UInt32 getCRCFromHeader() const; void parseDateTime();
Poco::UInt32 getCompressedSizeFromHeader() const; Poco::UInt32 getCRCFromHeader() const;
Poco::UInt32 getUncompressedSizeFromHeader() const; Poco::UInt32 getCompressedSizeFromHeader() const;
Poco::UInt16 getFileNameLength() const; Poco::UInt32 getUncompressedSizeFromHeader() const;
Poco::UInt16 getExtraFieldLength() const; Poco::UInt16 getFileNameLength() const;
Poco::UInt16 getFileCommentLength() const; Poco::UInt16 getExtraFieldLength() const;
Poco::UInt32 getExternalFileAttributes() const; Poco::UInt16 getFileCommentLength() const;
private: Poco::UInt32 getExternalFileAttributes() const;
enum
{ void setUnixAttributes();
HEADER_POS = 0,
VERSIONMADEBY_POS = HEADER_POS + ZipCommon::HEADER_SIZE, private:
VERSIONMADEBY_SIZE = 2, enum
VERSION_NEEDED_POS = VERSIONMADEBY_POS + VERSIONMADEBY_SIZE, {
VERSION_NEEDED_SIZE = 2, HEADER_POS = 0,
GENERAL_PURPOSE_POS = VERSION_NEEDED_POS + VERSION_NEEDED_SIZE, VERSIONMADEBY_POS = HEADER_POS + ZipCommon::HEADER_SIZE,
GENERAL_PURPOSE_SIZE = 2, VERSIONMADEBY_SIZE = 2,
COMPR_METHOD_POS = GENERAL_PURPOSE_POS + GENERAL_PURPOSE_SIZE, VERSION_NEEDED_POS = VERSIONMADEBY_POS + VERSIONMADEBY_SIZE,
COMPR_METHOD_SIZE = 2, VERSION_NEEDED_SIZE = 2,
LASTMODFILETIME_POS = COMPR_METHOD_POS + COMPR_METHOD_SIZE, GENERAL_PURPOSE_POS = VERSION_NEEDED_POS + VERSION_NEEDED_SIZE,
LASTMODFILETIME_SIZE = 2, GENERAL_PURPOSE_SIZE = 2,
LASTMODFILEDATE_POS = LASTMODFILETIME_POS + LASTMODFILETIME_SIZE, COMPR_METHOD_POS = GENERAL_PURPOSE_POS + GENERAL_PURPOSE_SIZE,
LASTMODFILEDATE_SIZE = 2, COMPR_METHOD_SIZE = 2,
CRC32_POS = LASTMODFILEDATE_POS + LASTMODFILEDATE_SIZE, LASTMODFILETIME_POS = COMPR_METHOD_POS + COMPR_METHOD_SIZE,
CRC32_SIZE = 4, LASTMODFILETIME_SIZE = 2,
COMPRESSED_SIZE_POS = CRC32_POS + CRC32_SIZE, LASTMODFILEDATE_POS = LASTMODFILETIME_POS + LASTMODFILETIME_SIZE,
COMPRESSED_SIZE_SIZE = 4, LASTMODFILEDATE_SIZE = 2,
UNCOMPRESSED_SIZE_POS = COMPRESSED_SIZE_POS + COMPRESSED_SIZE_SIZE, CRC32_POS = LASTMODFILEDATE_POS + LASTMODFILEDATE_SIZE,
UNCOMPRESSED_SIZE_SIZE = 4, CRC32_SIZE = 4,
FILENAME_LENGTH_POS = UNCOMPRESSED_SIZE_POS + UNCOMPRESSED_SIZE_SIZE, COMPRESSED_SIZE_POS = CRC32_POS + CRC32_SIZE,
FILENAME_LENGTH_SIZE = 2, COMPRESSED_SIZE_SIZE = 4,
EXTRAFIELD_LENGTH_POS = FILENAME_LENGTH_POS + FILENAME_LENGTH_SIZE, UNCOMPRESSED_SIZE_POS = COMPRESSED_SIZE_POS + COMPRESSED_SIZE_SIZE,
EXTRAFIELD_LENGTH_SIZE = 2, UNCOMPRESSED_SIZE_SIZE = 4,
FILECOMMENT_LENGTH_POS = EXTRAFIELD_LENGTH_POS + EXTRAFIELD_LENGTH_SIZE, FILENAME_LENGTH_POS = UNCOMPRESSED_SIZE_POS + UNCOMPRESSED_SIZE_SIZE,
FILECOMMENT_LENGTH_SIZE = 2, FILENAME_LENGTH_SIZE = 2,
DISKNUMBERSTART_POS = FILECOMMENT_LENGTH_POS + FILECOMMENT_LENGTH_SIZE, EXTRAFIELD_LENGTH_POS = FILENAME_LENGTH_POS + FILENAME_LENGTH_SIZE,
DISKNUMBERSTART_SIZE = 2, EXTRAFIELD_LENGTH_SIZE = 2,
INTERNALFILE_ATTR_POS = DISKNUMBERSTART_POS + DISKNUMBERSTART_SIZE, FILECOMMENT_LENGTH_POS = EXTRAFIELD_LENGTH_POS + EXTRAFIELD_LENGTH_SIZE,
INTERNALFILE_ATTR_SIZE = 2, FILECOMMENT_LENGTH_SIZE = 2,
EXTERNALFILE_ATTR_POS = INTERNALFILE_ATTR_POS + INTERNALFILE_ATTR_SIZE, DISKNUMBERSTART_POS = FILECOMMENT_LENGTH_POS + FILECOMMENT_LENGTH_SIZE,
EXTERNALFILE_ATTR_SIZE = 4, DISKNUMBERSTART_SIZE = 2,
RELATIVEOFFSETLOCALHEADER_POS = EXTERNALFILE_ATTR_POS + EXTERNALFILE_ATTR_SIZE, INTERNALFILE_ATTR_POS = DISKNUMBERSTART_POS + DISKNUMBERSTART_SIZE,
RELATIVEOFFSETLOCALHEADER_SIZE = 4, INTERNALFILE_ATTR_SIZE = 2,
FULLHEADER_SIZE = 46 EXTERNALFILE_ATTR_POS = INTERNALFILE_ATTR_POS + INTERNALFILE_ATTR_SIZE,
}; EXTERNALFILE_ATTR_SIZE = 4,
RELATIVEOFFSETLOCALHEADER_POS = EXTERNALFILE_ATTR_POS + EXTERNALFILE_ATTR_SIZE,
char _rawInfo[FULLHEADER_SIZE]; RELATIVEOFFSETLOCALHEADER_SIZE = 4,
Poco::UInt32 _crc32; FULLHEADER_SIZE = 46
Poco::UInt32 _compressedSize; };
Poco::UInt32 _uncompressedSize;
std::string _fileName; enum
Poco::DateTime _lastModifiedAt; {
std::string _extraField; DEFAULT_UNIX_FILE_MODE = 0640,
std::string _fileComment; DEFAULT_UNIX_DIR_MODE = 0755
}; };
char _rawInfo[FULLHEADER_SIZE];
inline Poco::UInt32 ZipFileInfo::getRelativeOffsetOfLocalHeader() const Poco::UInt32 _crc32;
{ Poco::UInt32 _compressedSize;
return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS); Poco::UInt32 _uncompressedSize;
} std::string _fileName;
Poco::DateTime _lastModifiedAt;
std::string _extraField;
inline Poco::UInt32 ZipFileInfo::getCRCFromHeader() const std::string _fileComment;
{ };
return ZipUtil::get32BitValue(_rawInfo, CRC32_POS);
}
inline Poco::UInt32 ZipFileInfo::getRelativeOffsetOfLocalHeader() const
{
inline Poco::UInt32 ZipFileInfo::getCompressedSizeFromHeader() const return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
{ }
return ZipUtil::get32BitValue(_rawInfo, COMPRESSED_SIZE_POS);
}
inline Poco::UInt32 ZipFileInfo::getCRCFromHeader() const
{
inline Poco::UInt32 ZipFileInfo::getUncompressedSizeFromHeader() const return ZipUtil::get32BitValue(_rawInfo, CRC32_POS);
{ }
return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_SIZE_POS);
}
inline Poco::UInt32 ZipFileInfo::getCompressedSizeFromHeader() const
{
inline void ZipFileInfo::parseDateTime() return ZipUtil::get32BitValue(_rawInfo, COMPRESSED_SIZE_POS);
{ }
_lastModifiedAt = ZipUtil::parseDateTime(_rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
}
inline Poco::UInt32 ZipFileInfo::getUncompressedSizeFromHeader() const
{
inline ZipCommon::CompressionMethod ZipFileInfo::getCompressionMethod() const return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_SIZE_POS);
{ }
return static_cast<ZipCommon::CompressionMethod>(ZipUtil::get16BitValue(_rawInfo, COMPR_METHOD_POS));
}
inline void ZipFileInfo::parseDateTime()
{
inline bool ZipFileInfo::isEncrypted() const _lastModifiedAt = ZipUtil::parseDateTime(_rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
{ }
// bit 0 indicates encryption
return ((ZipUtil::get16BitValue(_rawInfo, GENERAL_PURPOSE_POS) & 0x0001) != 0);
} inline ZipCommon::CompressionMethod ZipFileInfo::getCompressionMethod() const
{
return static_cast<ZipCommon::CompressionMethod>(ZipUtil::get16BitValue(_rawInfo, COMPR_METHOD_POS));
inline const Poco::DateTime& ZipFileInfo::lastModifiedAt() const }
{
return _lastModifiedAt;
} inline bool ZipFileInfo::isEncrypted() const
{
// bit 0 indicates encryption
inline Poco::UInt32 ZipFileInfo::getCRC() const return ((ZipUtil::get16BitValue(_rawInfo, GENERAL_PURPOSE_POS) & 0x0001) != 0);
{ }
return _crc32;
}
inline const Poco::DateTime& ZipFileInfo::lastModifiedAt() const
{
inline Poco::UInt32 ZipFileInfo::getCompressedSize() const return _lastModifiedAt;
{ }
return _compressedSize;
}
inline Poco::UInt32 ZipFileInfo::getCRC() const
{
inline Poco::UInt32 ZipFileInfo::getUncompressedSize() const return _crc32;
{ }
return _uncompressedSize;
}
inline Poco::UInt32 ZipFileInfo::getCompressedSize() const
{
inline const std::string& ZipFileInfo::getFileName() const return _compressedSize;
{ }
return _fileName;
}
inline Poco::UInt32 ZipFileInfo::getUncompressedSize() const
{
inline bool ZipFileInfo::isFile() const return _uncompressedSize;
{ }
return !isDirectory();
}
inline const std::string& ZipFileInfo::getFileName() const
{
inline bool ZipFileInfo::isDirectory() const return _fileName;
{ }
poco_assert_dbg(!_fileName.empty());
return getUncompressedSize() == 0 && getCompressionMethod() == ZipCommon::CM_STORE && _fileName[_fileName.length()-1] == '/';
} inline bool ZipFileInfo::isFile() const
{
return !isDirectory();
inline Poco::UInt16 ZipFileInfo::getFileNameLength() const }
{
return ZipUtil::get16BitValue(_rawInfo, FILENAME_LENGTH_POS);
} inline bool ZipFileInfo::isDirectory() const
{
poco_assert_dbg(!_fileName.empty());
inline Poco::UInt16 ZipFileInfo::getExtraFieldLength() const return getUncompressedSize() == 0 && getCompressionMethod() == ZipCommon::CM_STORE && _fileName[_fileName.length()-1] == '/';
{ }
return ZipUtil::get16BitValue(_rawInfo, EXTRAFIELD_LENGTH_POS);
}
inline Poco::UInt16 ZipFileInfo::getFileNameLength() const
{
inline bool ZipFileInfo::hasExtraField() const return ZipUtil::get16BitValue(_rawInfo, FILENAME_LENGTH_POS);
{ }
return getExtraFieldLength() > 0;
}
inline Poco::UInt16 ZipFileInfo::getExtraFieldLength() const
{
inline const std::string& ZipFileInfo::getExtraField() const return ZipUtil::get16BitValue(_rawInfo, EXTRAFIELD_LENGTH_POS);
{ }
return _extraField;
}
inline bool ZipFileInfo::hasExtraField() const
{
inline const std::string& ZipFileInfo::getFileComment() const return getExtraFieldLength() > 0;
{ }
return _fileComment;
}
inline const std::string& ZipFileInfo::getExtraField() const
{
inline Poco::UInt16 ZipFileInfo::getFileCommentLength() const return _extraField;
{ }
return ZipUtil::get16BitValue(_rawInfo, FILECOMMENT_LENGTH_POS);
}
inline const std::string& ZipFileInfo::getFileComment() const
{
inline void ZipFileInfo::getVersionMadeBy(int& major, int& minor) return _fileComment;
{ }
major = (_rawInfo[VERSIONMADEBY_POS]/10);
minor = (_rawInfo[VERSIONMADEBY_POS]%10);
} inline Poco::UInt16 ZipFileInfo::getFileCommentLength() const
{
return ZipUtil::get16BitValue(_rawInfo, FILECOMMENT_LENGTH_POS);
inline void ZipFileInfo::getRequiredVersion(int& major, int& minor) }
{
major = (_rawInfo[VERSION_NEEDED_POS]/10);
minor = (_rawInfo[VERSION_NEEDED_POS]%10); inline void ZipFileInfo::getVersionMadeBy(int& major, int& minor)
} {
major = (_rawInfo[VERSIONMADEBY_POS]/10);
minor = (_rawInfo[VERSIONMADEBY_POS]%10);
inline ZipCommon::HostSystem ZipFileInfo::getHostSystem() const }
{
return static_cast<ZipCommon::HostSystem>(_rawInfo[VERSION_NEEDED_POS + 1]);
} inline void ZipFileInfo::getRequiredVersion(int& major, int& minor)
{
major = (_rawInfo[VERSION_NEEDED_POS]/10);
inline Poco::UInt16 ZipFileInfo::getDiskNumberStart() const minor = (_rawInfo[VERSION_NEEDED_POS]%10);
{ }
return ZipUtil::get16BitValue(_rawInfo, DISKNUMBERSTART_POS);
}
inline ZipCommon::HostSystem ZipFileInfo::getHostSystem() const
{
inline ZipCommon::FileType ZipFileInfo::getFileType() const return static_cast<ZipCommon::HostSystem>(_rawInfo[VERSION_NEEDED_POS + 1]);
{ }
return static_cast<ZipCommon::FileType>(_rawInfo[INTERNALFILE_ATTR_POS] & 0x01);
}
inline Poco::UInt16 ZipFileInfo::getDiskNumberStart() const
{
inline Poco::UInt32 ZipFileInfo::getExternalFileAttributes() const return ZipUtil::get16BitValue(_rawInfo, DISKNUMBERSTART_POS);
{ }
return ZipUtil::get32BitValue(_rawInfo, EXTERNALFILE_ATTR_POS);
}
inline ZipCommon::FileType ZipFileInfo::getFileType() const
{
inline Poco::UInt32 ZipFileInfo::getHeaderSize() const return static_cast<ZipCommon::FileType>(_rawInfo[INTERNALFILE_ATTR_POS] & 0x01);
{ }
return FULLHEADER_SIZE + getFileNameLength() + getExtraFieldLength() + getFileCommentLength();
}
inline Poco::UInt32 ZipFileInfo::getExternalFileAttributes() const
{
inline void ZipFileInfo::setCRC(Poco::UInt32 val) return ZipUtil::get32BitValue(_rawInfo, EXTERNALFILE_ATTR_POS);
{ }
_crc32 = val;
ZipUtil::set32BitValue(val, _rawInfo, CRC32_POS);
} inline Poco::UInt32 ZipFileInfo::getHeaderSize() const
{
return FULLHEADER_SIZE + getFileNameLength() + getExtraFieldLength() + getFileCommentLength();
inline void ZipFileInfo::setOffset(Poco::UInt32 val) }
{
ZipUtil::set32BitValue(val, _rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
} inline void ZipFileInfo::setCRC(Poco::UInt32 val)
{
_crc32 = val;
inline void ZipFileInfo::setCompressedSize(Poco::UInt32 val) ZipUtil::set32BitValue(val, _rawInfo, CRC32_POS);
{ }
_compressedSize = val;
ZipUtil::set32BitValue(val, _rawInfo, COMPRESSED_SIZE_POS);
} inline void ZipFileInfo::setOffset(Poco::UInt32 val)
{
ZipUtil::set32BitValue(val, _rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
inline void ZipFileInfo::setUncompressedSize(Poco::UInt32 val) }
{
_uncompressedSize = val;
ZipUtil::set32BitValue(val, _rawInfo, UNCOMPRESSED_SIZE_POS); inline void ZipFileInfo::setCompressedSize(Poco::UInt32 val)
} {
_compressedSize = val;
ZipUtil::set32BitValue(val, _rawInfo, COMPRESSED_SIZE_POS);
inline void ZipFileInfo::setCompressionMethod(ZipCommon::CompressionMethod cm) }
{
ZipUtil::set16BitValue(static_cast<Poco::UInt16>(cm), _rawInfo, COMPR_METHOD_POS);
} inline void ZipFileInfo::setUncompressedSize(Poco::UInt32 val)
{
_uncompressedSize = val;
inline void ZipFileInfo::setCompressionLevel(ZipCommon::CompressionLevel cl) ZipUtil::set32BitValue(val, _rawInfo, UNCOMPRESSED_SIZE_POS);
{ }
// bit 1 and 2 indicate the level
Poco::UInt16 val = static_cast<Poco::UInt16>(cl);
val <<= 1; inline void ZipFileInfo::setCompressionMethod(ZipCommon::CompressionMethod cm)
Poco::UInt16 mask = 0xfff9; {
_rawInfo[GENERAL_PURPOSE_POS] = ((_rawInfo[GENERAL_PURPOSE_POS] & mask) | val); ZipUtil::set16BitValue(static_cast<Poco::UInt16>(cm), _rawInfo, COMPR_METHOD_POS);
} }
inline void ZipFileInfo::setFileNameLength(Poco::UInt16 size) inline void ZipFileInfo::setCompressionLevel(ZipCommon::CompressionLevel cl)
{ {
ZipUtil::set16BitValue(size, _rawInfo, FILENAME_LENGTH_POS); // bit 1 and 2 indicate the level
} Poco::UInt16 val = static_cast<Poco::UInt16>(cl);
val <<= 1;
Poco::UInt16 mask = 0xfff9;
inline void ZipFileInfo::setHostSystem(ZipCommon::HostSystem hs) _rawInfo[GENERAL_PURPOSE_POS] = ((_rawInfo[GENERAL_PURPOSE_POS] & mask) | val);
{ }
_rawInfo[VERSIONMADEBY_POS + 1] = static_cast<char>(hs);
_rawInfo[VERSION_NEEDED_POS + 1] = static_cast<char>(hs);
} inline void ZipFileInfo::setFileNameLength(Poco::UInt16 size)
{
ZipUtil::set16BitValue(size, _rawInfo, FILENAME_LENGTH_POS);
inline void ZipFileInfo::setRequiredVersion(int major, int minor) }
{
poco_assert (minor < 10);
poco_assert (major < 24); inline void ZipFileInfo::setHostSystem(ZipCommon::HostSystem hs)
Poco::UInt8 val = static_cast<unsigned char>(major)*10+static_cast<unsigned char>(minor); {
_rawInfo[VERSIONMADEBY_POS] = static_cast<char>(val); _rawInfo[VERSIONMADEBY_POS + 1] = static_cast<char>(hs);
_rawInfo[VERSION_NEEDED_POS] = static_cast<char>(val); _rawInfo[VERSION_NEEDED_POS + 1] = static_cast<char>(hs);
} }
inline void ZipFileInfo::setLastModifiedAt(const Poco::DateTime& dt) inline void ZipFileInfo::setRequiredVersion(int major, int minor)
{ {
_lastModifiedAt = dt; poco_assert (minor < 10);
ZipUtil::setDateTime(dt, _rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS); poco_assert (major < 24);
} Poco::UInt8 val = static_cast<unsigned char>(major)*10+static_cast<unsigned char>(minor);
_rawInfo[VERSIONMADEBY_POS] = static_cast<char>(val);
_rawInfo[VERSION_NEEDED_POS] = static_cast<char>(val);
inline void ZipFileInfo::setEncryption(bool val) }
{
if (val)
_rawInfo[GENERAL_PURPOSE_POS] |= 0x01; inline void ZipFileInfo::setLastModifiedAt(const Poco::DateTime& dt)
else {
_rawInfo[GENERAL_PURPOSE_POS] &= 0xfe; _lastModifiedAt = dt;
} ZipUtil::setDateTime(dt, _rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
}
inline void ZipFileInfo::setFileName(const std::string& str)
{ inline void ZipFileInfo::setEncryption(bool val)
_fileName = str; {
setFileNameLength(static_cast<Poco::UInt16>(str.size())); if (val)
} _rawInfo[GENERAL_PURPOSE_POS] |= 0x01;
else
_rawInfo[GENERAL_PURPOSE_POS] &= 0xfe;
} } // namespace Poco::Zip }
#endif // Zip_ZipFileInfo_INCLUDED inline void ZipFileInfo::setFileName(const std::string& str)
{
_fileName = str;
setFileNameLength(static_cast<Poco::UInt16>(str.size()));
}
inline void ZipFileInfo::setExternalFileAttributes(Poco::UInt32 attrs)
{
ZipUtil::set32BitValue(attrs, _rawInfo, EXTERNALFILE_ATTR_POS);
}
} } // namespace Poco::Zip
#endif // Zip_ZipFileInfo_INCLUDED

View File

@ -1,322 +1,322 @@
// //
// Compress.cpp // Compress.cpp
// //
// $Id: //poco/1.3/Zip/src/Compress.cpp#4 $ // $Id: //poco/Main/Zip/src/Compress.cpp#8 $
// //
// Library: Zip // Library: Zip
// Package: Zip // Package: Zip
// Module: Compress // Module: Compress
// //
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
#include "Poco/Zip/Compress.h" #include "Poco/Zip/Compress.h"
#include "Poco/Zip/ZipLocalFileHeader.h" #include "Poco/Zip/ZipLocalFileHeader.h"
#include "Poco/Zip/ZipStream.h" #include "Poco/Zip/ZipStream.h"
#include "Poco/Zip/ZipArchiveInfo.h" #include "Poco/Zip/ZipArchiveInfo.h"
#include "Poco/Zip/ZipDataInfo.h" #include "Poco/Zip/ZipDataInfo.h"
#include "Poco/Zip/ZipException.h" #include "Poco/Zip/ZipException.h"
#include "Poco/StreamCopier.h" #include "Poco/StreamCopier.h"
#include "Poco/File.h" #include "Poco/File.h"
#include <fstream> #include <fstream>
namespace Poco { namespace Poco {
namespace Zip { namespace Zip {
Compress::Compress(std::ostream& out, bool seekableOut): Compress::Compress(std::ostream& out, bool seekableOut):
_out(out), _out(out),
_seekableOut(seekableOut), _seekableOut(seekableOut),
_files(), _files(),
_infos(), _infos(),
_dirs(), _dirs(),
_offset(0) _offset(0)
{ {
} }
Compress::~Compress() Compress::~Compress()
{ {
} }
void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl) void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl)
{ {
std::string fn = ZipUtil::validZipEntryFileName(fileName); std::string fn = ZipUtil::validZipEntryFileName(fileName);
if (_files.size() >= 65535) if (_files.size() >= 65535)
throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); throw ZipException("Maximum number of entries for a ZIP file reached: 65535");
if (!in.good()) if (!in.good())
throw ZipException("Invalid input stream"); throw ZipException("Invalid input stream");
std::streamoff localHeaderOffset = _offset; std::streamoff localHeaderOffset = _offset;
ZipLocalFileHeader hdr(fileName, lastModifiedAt, cm, cl); ZipLocalFileHeader hdr(fileName, lastModifiedAt, cm, cl);
hdr.setStartPos(localHeaderOffset); hdr.setStartPos(localHeaderOffset);
ZipOutputStream zipOut(_out, hdr, _seekableOut); ZipOutputStream zipOut(_out, hdr, _seekableOut);
Poco::StreamCopier::copyStream(in, zipOut); Poco::StreamCopier::copyStream(in, zipOut);
zipOut.close(); zipOut.close();
hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known
_offset = hdr.getEndPos(); _offset = hdr.getEndPos();
if (hdr.searchCRCAndSizesAfterData()) if (hdr.searchCRCAndSizesAfterData())
_offset += ZipDataInfo::getFullHeaderSize(); _offset += ZipDataInfo::getFullHeaderSize();
_files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); _files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr));
poco_assert (_out); poco_assert (_out);
ZipFileInfo nfo(hdr); ZipFileInfo nfo(hdr);
nfo.setOffset(localHeaderOffset); nfo.setOffset(localHeaderOffset);
_infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo)); _infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo));
EDone.notify(this, hdr); EDone.notify(this, hdr);
} }
void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const Poco::Path& fileName) void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const Poco::Path& fileName)
{ {
std::string fn = ZipUtil::validZipEntryFileName(fileName); std::string fn = ZipUtil::validZipEntryFileName(fileName);
//bypass the header of the input stream and point to the first byte of the data payload //bypass the header of the input stream and point to the first byte of the data payload
in.seekg(h.getDataStartPos(), std::ios_base::beg); in.seekg(h.getDataStartPos(), std::ios_base::beg);
if (_files.size() >= 65535) if (_files.size() >= 65535)
throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); throw ZipException("Maximum number of entries for a ZIP file reached: 65535");
if (!in.good()) if (!in.good())
throw ZipException("Invalid input stream"); throw ZipException("Invalid input stream");
std::streamoff localHeaderOffset = _offset; std::streamoff localHeaderOffset = _offset;
ZipLocalFileHeader hdr(h); ZipLocalFileHeader hdr(h);
hdr.setFileName(fn, h.isDirectory()); hdr.setFileName(fn, h.isDirectory());
hdr.setStartPos(localHeaderOffset); hdr.setStartPos(localHeaderOffset);
//bypass zipoutputstream //bypass zipoutputstream
//write the header directly //write the header directly
std::string header = hdr.createHeader(); std::string header = hdr.createHeader();
_out.write(header.c_str(), static_cast<std::streamsize>(header.size())); _out.write(header.c_str(), static_cast<std::streamsize>(header.size()));
// now fwd the payload to _out in chunks of size CHUNKSIZE // now fwd the payload to _out in chunks of size CHUNKSIZE
Poco::UInt32 totalSize = hdr.getCompressedSize(); Poco::UInt32 totalSize = hdr.getCompressedSize();
if (totalSize > 0) if (totalSize > 0)
{ {
Poco::Buffer<char> buffer(COMPRESS_CHUNK_SIZE); Poco::Buffer<char> buffer(COMPRESS_CHUNK_SIZE);
Poco::UInt32 remaining = totalSize; Poco::UInt32 remaining = totalSize;
while(remaining > 0) while(remaining > 0)
{ {
if (remaining > COMPRESS_CHUNK_SIZE) if (remaining > COMPRESS_CHUNK_SIZE)
{ {
in.read(buffer.begin(), COMPRESS_CHUNK_SIZE); in.read(buffer.begin(), COMPRESS_CHUNK_SIZE);
std::streamsize n = in.gcount(); std::streamsize n = in.gcount();
poco_assert_dbg (n == COMPRESS_CHUNK_SIZE); poco_assert_dbg (n == COMPRESS_CHUNK_SIZE);
_out.write(buffer.begin(), n); _out.write(buffer.begin(), n);
remaining -= COMPRESS_CHUNK_SIZE; remaining -= COMPRESS_CHUNK_SIZE;
} }
else else
{ {
in.read(buffer.begin(), remaining); in.read(buffer.begin(), remaining);
std::streamsize n = in.gcount(); std::streamsize n = in.gcount();
poco_assert_dbg (n == remaining); poco_assert_dbg (n == remaining);
_out.write(buffer.begin(), n); _out.write(buffer.begin(), n);
remaining = 0; remaining = 0;
} }
} }
} }
//write optional block afterwards //write optional block afterwards
if (hdr.searchCRCAndSizesAfterData()) if (hdr.searchCRCAndSizesAfterData())
{ {
ZipDataInfo info(in, false); ZipDataInfo info(in, false);
_out.write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize())); _out.write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize()));
} }
hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known
_offset = hdr.getEndPos(); _offset = hdr.getEndPos();
if (hdr.searchCRCAndSizesAfterData()) if (hdr.searchCRCAndSizesAfterData())
_offset += ZipDataInfo::getFullHeaderSize(); _offset += ZipDataInfo::getFullHeaderSize();
_files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); _files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr));
poco_assert (_out); poco_assert (_out);
ZipFileInfo nfo(hdr); ZipFileInfo nfo(hdr);
nfo.setOffset(localHeaderOffset); nfo.setOffset(localHeaderOffset);
_infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo)); _infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo));
EDone.notify(this, hdr); EDone.notify(this, hdr);
} }
void Compress::addFile(std::istream& in, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl) void Compress::addFile(std::istream& in, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl)
{ {
if (!fileName.isFile()) if (!fileName.isFile())
throw ZipException("Not a file: "+ fileName.toString()); throw ZipException("Not a file: "+ fileName.toString());
if (fileName.depth() > 1) if (fileName.depth() > 1)
{ {
addDirectory(fileName.parent(), lastModifiedAt); addDirectory(fileName.parent(), lastModifiedAt);
} }
addEntry(in, lastModifiedAt, fileName, cm, cl); addEntry(in, lastModifiedAt, fileName, cm, cl);
} }
void Compress::addFile(const Poco::Path& file, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl) void Compress::addFile(const Poco::Path& file, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl)
{ {
Poco::File aFile(file); Poco::File aFile(file);
Poco::File::FileSize size = aFile.getSize(); Poco::File::FileSize size = aFile.getSize();
if (size < 16) if (size < 16)
{ {
cm = ZipCommon::CM_STORE; cm = ZipCommon::CM_STORE;
cl = ZipCommon::CL_NORMAL; cl = ZipCommon::CL_NORMAL;
} }
std::ifstream in(file.toString().c_str(), std::ios::binary);
std::ifstream in(file.toString().c_str(), std::ios::binary); if (!in.good())
if (!in.good()) throw ZipException("Invalid input stream for " + aFile.path());
throw ZipException("Invalid input stream for " + aFile.path()); if (fileName.depth() > 1)
if (fileName.depth() > 1) {
{ Poco::File aParent(file.parent());
Poco::File aParent(file.parent()); addDirectory(fileName.parent(), aParent.getLastModified());
addDirectory(fileName.parent(), aParent.getLastModified()); }
}
addFile(in, aFile.getLastModified(), fileName, cm, cl); addFile(in, aFile.getLastModified(), fileName, cm, cl);
} }
void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& lastModifiedAt) void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& lastModifiedAt)
{ {
if (!entryName.isDirectory()) if (!entryName.isDirectory())
throw ZipException("Not a directory: "+ entryName.toString()); throw ZipException("Not a directory: "+ entryName.toString());
std::string fileStr = entryName.toString(Poco::Path::PATH_UNIX); std::string fileStr = entryName.toString(Poco::Path::PATH_UNIX);
if (_files.find(fileStr) != _files.end()) if (_files.find(fileStr) != _files.end())
return; // ignore duplicate add return; // ignore duplicate add
if (_files.size() >= 65535) if (_files.size() >= 65535)
throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); throw ZipException("Maximum number of entries for a ZIP file reached: 65535");
if (fileStr == "/") if (fileStr == "/")
throw ZipException("Illegal entry name /"); throw ZipException("Illegal entry name /");
if (fileStr.empty()) if (fileStr.empty())
throw ZipException("Illegal empty entry name"); throw ZipException("Illegal empty entry name");
if (fileStr.find(ZipCommon::ILLEGAL_PATH) != std::string::npos) if (fileStr.find(ZipCommon::ILLEGAL_PATH) != std::string::npos)
throw ZipException("Illegal entry name " + fileStr + " containing " + ZipCommon::ILLEGAL_PATH); throw ZipException("Illegal entry name " + fileStr + " containing " + ZipCommon::ILLEGAL_PATH);
if (entryName.depth() > 1) if (entryName.depth() > 1)
{ {
addDirectory(entryName.parent(), lastModifiedAt); addDirectory(entryName.parent(), lastModifiedAt);
} }
std::streamoff localHeaderOffset = _offset; std::streamoff localHeaderOffset = _offset;
ZipCommon::CompressionMethod cm = ZipCommon::CM_STORE; ZipCommon::CompressionMethod cm = ZipCommon::CM_STORE;
ZipCommon::CompressionLevel cl = ZipCommon::CL_NORMAL; ZipCommon::CompressionLevel cl = ZipCommon::CL_NORMAL;
ZipLocalFileHeader hdr(entryName, lastModifiedAt, cm, cl); ZipLocalFileHeader hdr(entryName, lastModifiedAt, cm, cl);
hdr.setStartPos(localHeaderOffset); hdr.setStartPos(localHeaderOffset);
ZipOutputStream zipOut(_out, hdr, _seekableOut); ZipOutputStream zipOut(_out, hdr, _seekableOut);
zipOut.close(); zipOut.close();
hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known
_offset = hdr.getEndPos(); _offset = hdr.getEndPos();
if (hdr.searchCRCAndSizesAfterData()) if (hdr.searchCRCAndSizesAfterData())
_offset += ZipDataInfo::getFullHeaderSize(); _offset += ZipDataInfo::getFullHeaderSize();
_files.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), hdr)); _files.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), hdr));
poco_assert (_out); poco_assert (_out);
ZipFileInfo nfo(hdr); ZipFileInfo nfo(hdr);
nfo.setOffset(localHeaderOffset); nfo.setOffset(localHeaderOffset);
_infos.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), nfo)); _infos.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), nfo));
EDone.notify(this, hdr); EDone.notify(this, hdr);
} }
void Compress::addRecursive(const Poco::Path& entry, ZipCommon::CompressionLevel cl, bool excludeRoot, const Poco::Path& name) void Compress::addRecursive(const Poco::Path& entry, ZipCommon::CompressionLevel cl, bool excludeRoot, const Poco::Path& name)
{ {
Poco::File aFile(entry); Poco::File aFile(entry);
if (!aFile.isDirectory()) if (!aFile.isDirectory())
throw ZipException("Not a directory: "+ entry.toString()); throw ZipException("Not a directory: "+ entry.toString());
Poco::Path aName(name); Poco::Path aName(name);
aName.makeDirectory(); aName.makeDirectory();
if (!excludeRoot) if (!excludeRoot)
{ {
if (aName.depth() == 0) if (aName.depth() == 0)
{ {
Poco::Path tmp(entry); Poco::Path tmp(entry);
tmp.makeAbsolute(); // eliminate ../ tmp.makeAbsolute(); // eliminate ../
aName = Poco::Path(tmp[tmp.depth()-1]); aName = Poco::Path(tmp[tmp.depth()-1]);
aName.makeDirectory(); aName.makeDirectory();
} }
addDirectory(aName, aFile.getLastModified()); addDirectory(aName, aFile.getLastModified());
} }
// iterate over children // iterate over children
std::vector<std::string> children; std::vector<std::string> children;
aFile.list(children); aFile.list(children);
std::vector<std::string>::const_iterator it = children.begin(); std::vector<std::string>::const_iterator it = children.begin();
std::vector<std::string>::const_iterator itEnd = children.end(); std::vector<std::string>::const_iterator itEnd = children.end();
for (; it != itEnd; ++it) for (; it != itEnd; ++it)
{ {
Poco::Path realFile(entry, *it); Poco::Path realFile(entry, *it);
Poco::Path renamedFile(aName, *it); Poco::Path renamedFile(aName, *it);
Poco::File aFile(realFile); Poco::File aFile(realFile);
if (aFile.isDirectory()) if (aFile.isDirectory())
{ {
realFile.makeDirectory(); realFile.makeDirectory();
renamedFile.makeDirectory(); renamedFile.makeDirectory();
addRecursive(realFile, cl, false, renamedFile); addRecursive(realFile, cl, false, renamedFile);
} }
else else
{ {
realFile.makeFile(); realFile.makeFile();
renamedFile.makeFile(); renamedFile.makeFile();
addFile(realFile, renamedFile, ZipCommon::CM_DEFLATE, cl); addFile(realFile, renamedFile, ZipCommon::CM_DEFLATE, cl);
} }
} }
} }
ZipArchive Compress::close() ZipArchive Compress::close()
{ {
if (!_dirs.empty()) if (!_dirs.empty())
return ZipArchive(_files, _infos, _dirs); return ZipArchive(_files, _infos, _dirs);
poco_assert (_infos.size() == _files.size()); poco_assert (_infos.size() == _files.size());
poco_assert (_files.size() < 65536); poco_assert (_files.size() < 65536);
Poco::UInt32 centralDirStart = _offset; Poco::UInt32 centralDirStart = _offset;
Poco::UInt32 centralDirSize = 0; Poco::UInt32 centralDirSize = 0;
// write all infos // write all infos
ZipArchive::FileInfos::const_iterator it = _infos.begin(); ZipArchive::FileInfos::const_iterator it = _infos.begin();
ZipArchive::FileInfos::const_iterator itEnd = _infos.end(); ZipArchive::FileInfos::const_iterator itEnd = _infos.end();
for (; it != itEnd; ++it) for (; it != itEnd; ++it)
{ {
const ZipFileInfo& nfo = it->second; const ZipFileInfo& nfo = it->second;
std::string info(nfo.createHeader()); std::string info(nfo.createHeader());
_out.write(info.c_str(), static_cast<std::streamsize>(info.size())); _out.write(info.c_str(), static_cast<std::streamsize>(info.size()));
Poco::UInt32 entrySize = static_cast<Poco::UInt32>(info.size()); Poco::UInt32 entrySize = static_cast<Poco::UInt32>(info.size());
centralDirSize += entrySize; centralDirSize += entrySize;
_offset += entrySize; _offset += entrySize;
} }
poco_assert (_out); poco_assert (_out);
Poco::UInt16 numEntries = static_cast<Poco::UInt16>(_infos.size()); Poco::UInt16 numEntries = static_cast<Poco::UInt16>(_infos.size());
ZipArchiveInfo central; ZipArchiveInfo central;
central.setCentralDirectorySize(centralDirSize); central.setCentralDirectorySize(centralDirSize);
central.setNumberOfEntries(numEntries); central.setNumberOfEntries(numEntries);
central.setTotalNumberOfEntries(numEntries); central.setTotalNumberOfEntries(numEntries);
central.setHeaderOffset(centralDirStart); central.setHeaderOffset(centralDirStart);
std::string centr(central.createHeader()); std::string centr(central.createHeader());
_out.write(centr.c_str(), static_cast<std::streamsize>(centr.size())); _out.write(centr.c_str(), static_cast<std::streamsize>(centr.size()));
_out.flush(); _out.flush();
_dirs.insert(std::make_pair(0, central)); _dirs.insert(std::make_pair(0, central));
return ZipArchive(_files, _infos, _dirs); return ZipArchive(_files, _infos, _dirs);
} }
} } // namespace Poco::Zip } } // namespace Poco::Zip

View File

@ -1,143 +1,159 @@
// //
// ZipFileInfo.cpp // ZipFileInfo.cpp
// //
// $Id: //poco/1.3/Zip/src/ZipFileInfo.cpp#4 $ // $Id: //poco/Main/Zip/src/ZipFileInfo.cpp#9 $
// //
// Library: Zip // Library: Zip
// Package: Zip // Package: Zip
// Module: ZipFileInfo // Module: ZipFileInfo
// //
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
#include "Poco/Zip/ZipFileInfo.h" #include "Poco/Zip/ZipFileInfo.h"
#include "Poco/Zip/ZipLocalFileHeader.h" #include "Poco/Zip/ZipLocalFileHeader.h"
#include "Poco/Buffer.h" #include "Poco/Buffer.h"
#include <istream> #include <istream>
#include <cstring> #include <cstring>
namespace Poco { namespace Poco {
namespace Zip { namespace Zip {
const char ZipFileInfo::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x01', '\x02'}; const char ZipFileInfo::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x01', '\x02'};
ZipFileInfo::ZipFileInfo(const ZipLocalFileHeader& header): ZipFileInfo::ZipFileInfo(const ZipLocalFileHeader& header):
_rawInfo(), _rawInfo(),
_crc32(0), _crc32(0),
_compressedSize(0), _compressedSize(0),
_uncompressedSize(0), _uncompressedSize(0),
_fileName(), _fileName(),
_lastModifiedAt(), _lastModifiedAt(),
_extraField() _extraField()
{ {
std::memset(_rawInfo, 0, FULLHEADER_SIZE); std::memset(_rawInfo, 0, FULLHEADER_SIZE);
std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE);
setCompressedSize(header.getCompressedSize()); setCompressedSize(header.getCompressedSize());
setUncompressedSize(header.getUncompressedSize()); setUncompressedSize(header.getUncompressedSize());
setCRC(header.getCRC()); setCRC(header.getCRC());
setCompressionMethod(header.getCompressionMethod()); setCompressionMethod(header.getCompressionMethod());
setCompressionLevel(header.getCompressionLevel()); setCompressionLevel(header.getCompressionLevel());
setRequiredVersion(header.getMajorVersionNumber(), header.getMinorVersionNumber()); setRequiredVersion(header.getMajorVersionNumber(), header.getMinorVersionNumber());
setHostSystem(header.getHostSystem()); setHostSystem(header.getHostSystem());
setLastModifiedAt(header.lastModifiedAt()); setLastModifiedAt(header.lastModifiedAt());
setEncryption(false); setEncryption(false);
setFileName(header.getFileName()); setFileName(header.getFileName());
}
if (getHostSystem() == ZipCommon::HS_UNIX)
setUnixAttributes();
ZipFileInfo::ZipFileInfo(std::istream& in, bool assumeHeaderRead): }
_rawInfo(),
_crc32(0),
_compressedSize(0), ZipFileInfo::ZipFileInfo(std::istream& in, bool assumeHeaderRead):
_uncompressedSize(0), _rawInfo(),
_fileName(), _crc32(0),
_lastModifiedAt(), _compressedSize(0),
_extraField() _uncompressedSize(0),
{ _fileName(),
// sanity check _lastModifiedAt(),
poco_assert_dbg (RELATIVEOFFSETLOCALHEADER_POS + RELATIVEOFFSETLOCALHEADER_SIZE == FULLHEADER_SIZE); _extraField()
parse(in, assumeHeaderRead); {
} // sanity check
poco_assert_dbg (RELATIVEOFFSETLOCALHEADER_POS + RELATIVEOFFSETLOCALHEADER_SIZE == FULLHEADER_SIZE);
parse(in, assumeHeaderRead);
ZipFileInfo::~ZipFileInfo() }
{
}
ZipFileInfo::~ZipFileInfo()
{
void ZipFileInfo::parse(std::istream& inp, bool assumeHeaderRead) }
{
if (!assumeHeaderRead)
{ void ZipFileInfo::parse(std::istream& inp, bool assumeHeaderRead)
inp.read(_rawInfo, ZipCommon::HEADER_SIZE); {
} if (!assumeHeaderRead)
else {
{ inp.read(_rawInfo, ZipCommon::HEADER_SIZE);
std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); }
} else
poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); {
// read the rest of the header std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE);
inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); }
_crc32 = getCRCFromHeader(); poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0);
_compressedSize = getCompressedSizeFromHeader(); // read the rest of the header
_uncompressedSize = getUncompressedSizeFromHeader(); inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE);
parseDateTime(); _crc32 = getCRCFromHeader();
Poco::UInt16 len = getFileNameLength(); _compressedSize = getCompressedSizeFromHeader();
Poco::Buffer<char> buf(len); _uncompressedSize = getUncompressedSizeFromHeader();
inp.read(buf.begin(), len); parseDateTime();
_fileName = std::string(buf.begin(), len); Poco::UInt16 len = getFileNameLength();
if (hasExtraField()) Poco::Buffer<char> buf(len);
{ inp.read(buf.begin(), len);
len = getExtraFieldLength(); _fileName = std::string(buf.begin(), len);
Poco::Buffer<char> xtra(len); if (hasExtraField())
inp.read(xtra.begin(), len); {
_extraField = std::string(xtra.begin(), len); len = getExtraFieldLength();
} Poco::Buffer<char> xtra(len);
len = getFileCommentLength(); inp.read(xtra.begin(), len);
if (len > 0) _extraField = std::string(xtra.begin(), len);
{ }
Poco::Buffer<char> buf2(len); len = getFileCommentLength();
inp.read(buf2.begin(), len); if (len > 0)
_fileComment = std::string(buf2.begin(), len); {
} Poco::Buffer<char> buf2(len);
} inp.read(buf2.begin(), len);
_fileComment = std::string(buf2.begin(), len);
}
std::string ZipFileInfo::createHeader() const }
{
std::string result(_rawInfo, FULLHEADER_SIZE);
result.append(_fileName); std::string ZipFileInfo::createHeader() const
result.append(_extraField); {
result.append(_fileComment); std::string result(_rawInfo, FULLHEADER_SIZE);
return result; result.append(_fileName);
} result.append(_extraField);
result.append(_fileComment);
return result;
} } // namespace Poco::Zip }
void ZipFileInfo::setUnixAttributes()
{
bool isDir = isDirectory();
int mode;
if (isDir)
mode = DEFAULT_UNIX_DIR_MODE;
else
mode = DEFAULT_UNIX_FILE_MODE;
Poco::UInt32 attrs = (mode << 16) | (isDir ? 0x10 : 0);
setExternalFileAttributes(attrs);
}
} } // namespace Poco::Zip

View File

@ -1,319 +1,319 @@
// //
// ZipStream.cpp // ZipStream.cpp
// //
// $Id: //poco/1.3/Zip/src/ZipStream.cpp#4 $ // $Id: //poco/Main/Zip/src/ZipStream.cpp#14 $
// //
// Library: Zip // Library: Zip
// Package: Zip // Package: Zip
// Module: ZipStream // Module: ZipStream
// //
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
#include "Poco/Zip/ZipStream.h" #include "Poco/Zip/ZipStream.h"
#include "Poco/zlib.h" #include "Poco/zlib.h"
#include "Poco/Zip/ZipArchive.h" #include "Poco/Zip/ZipArchive.h"
#include "Poco/Zip/AutoDetectStream.h" #include "Poco/Zip/AutoDetectStream.h"
#include "Poco/Zip/PartialStream.h" #include "Poco/Zip/PartialStream.h"
#include "Poco/Zip/ZipDataInfo.h" #include "Poco/Zip/ZipDataInfo.h"
#include "Poco/Zip/ZipException.h" #include "Poco/Zip/ZipException.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/InflatingStream.h" #include "Poco/InflatingStream.h"
#include "Poco/DeflatingStream.h" #include "Poco/DeflatingStream.h"
namespace Poco { namespace Poco {
namespace Zip { namespace Zip {
ZipStreamBuf::ZipStreamBuf(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): ZipStreamBuf::ZipStreamBuf(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition):
Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in),
_pIstr(&istr), _pIstr(&istr),
_pOstr(0), _pOstr(0),
_ptrBuf(), _ptrBuf(),
_ptrOBuf(), _ptrOBuf(),
_ptrHelper(), _ptrHelper(),
_ptrOHelper(), _ptrOHelper(),
_crc32(Poco::Checksum::TYPE_CRC32), _crc32(Poco::Checksum::TYPE_CRC32),
_expectedCrc32(0), _expectedCrc32(0),
_checkCRC(true), _checkCRC(true),
_bytesWritten(0), _bytesWritten(0),
_pHeader(0) _pHeader(0)
{ {
if (fileEntry.isDirectory()) if (fileEntry.isDirectory())
return; return;
_expectedCrc32 = fileEntry.getCRC(); _expectedCrc32 = fileEntry.getCRC();
std::streamoff start = fileEntry.getDataStartPos(); std::streamoff start = fileEntry.getDataStartPos();
std::streamoff end = fileEntry.getDataEndPos(); std::streamoff end = fileEntry.getDataEndPos();
_checkCRC = !fileEntry.searchCRCAndSizesAfterData(); _checkCRC = !fileEntry.searchCRCAndSizesAfterData();
if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE) if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE)
{ {
// Fake init bytes at beginning of stream // Fake init bytes at beginning of stream
std::string init = ZipUtil::fakeZLibInitString(fileEntry.getCompressionLevel()); std::string init = ZipUtil::fakeZLibInitString(fileEntry.getCompressionLevel());
// Fake adler at end of stream: just some dummy value, not checked anway // Fake adler at end of stream: just some dummy value, not checked anway
std::string crc(4, ' '); std::string crc(4, ' ');
if (fileEntry.searchCRCAndSizesAfterData()) if (fileEntry.searchCRCAndSizesAfterData())
{ {
_ptrHelper = new AutoDetectInputStream(istr, init, crc, reposition, start); _ptrHelper = new AutoDetectInputStream(istr, init, crc, reposition, start);
} }
else else
_ptrHelper = new PartialInputStream(istr, start, end, reposition, init, crc); _ptrHelper = new PartialInputStream(istr, start, end, reposition, init, crc);
_ptrBuf = new Poco::InflatingInputStream(*_ptrHelper, Poco::InflatingStreamBuf::STREAM_ZIP); _ptrBuf = new Poco::InflatingInputStream(*_ptrHelper, Poco::InflatingStreamBuf::STREAM_ZIP);
} }
else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE) else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE)
{ {
if (fileEntry.searchCRCAndSizesAfterData()) if (fileEntry.searchCRCAndSizesAfterData())
{ {
_ptrBuf = new AutoDetectInputStream(istr, "", "", reposition, start); _ptrBuf = new AutoDetectInputStream(istr, "", "", reposition, start);
} }
else else
_ptrBuf = new PartialInputStream(istr, start, end, reposition); _ptrBuf = new PartialInputStream(istr, start, end, reposition);
} }
else else
{ {
throw Poco::NotImplementedException("Unsupported compression method"); throw Poco::NotImplementedException("Unsupported compression method");
} }
} }
ZipStreamBuf::ZipStreamBuf(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition): ZipStreamBuf::ZipStreamBuf(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition):
Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out), Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out),
_pIstr(0), _pIstr(0),
_pOstr(&ostr), _pOstr(&ostr),
_ptrBuf(), _ptrBuf(),
_ptrOBuf(), _ptrOBuf(),
_ptrHelper(), _ptrHelper(),
_ptrOHelper(), _ptrOHelper(),
_crc32(Poco::Checksum::TYPE_CRC32), _crc32(Poco::Checksum::TYPE_CRC32),
_expectedCrc32(0), _expectedCrc32(0),
_checkCRC(false), _checkCRC(false),
_bytesWritten(0), _bytesWritten(0),
_pHeader(&fileEntry) _pHeader(&fileEntry)
{ {
if (fileEntry.isEncrypted()) if (fileEntry.isEncrypted())
throw Poco::NotImplementedException("Encryption not supported"); throw Poco::NotImplementedException("Encryption not supported");
if (fileEntry.isDirectory()) if (fileEntry.isDirectory())
{ {
// only header, no payload, zero crc // only header, no payload, zero crc
fileEntry.setSearchCRCAndSizesAfterData(false); fileEntry.setSearchCRCAndSizesAfterData(false);
fileEntry.setCompressedSize(0); fileEntry.setCompressedSize(0);
fileEntry.setUncompressedSize(0); fileEntry.setUncompressedSize(0);
fileEntry.setCRC(0); fileEntry.setCRC(0);
std::string header = fileEntry.createHeader(); std::string header = fileEntry.createHeader();
ostr.write(header.c_str(), static_cast<std::streamsize>(header.size())); ostr.write(header.c_str(), static_cast<std::streamsize>(header.size()));
} }
else else
{ {
fileEntry.setSearchCRCAndSizesAfterData(!reposition); fileEntry.setSearchCRCAndSizesAfterData(!reposition);
if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE) if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE)
{ {
int level = Z_DEFAULT_COMPRESSION; int level = Z_DEFAULT_COMPRESSION;
if (fileEntry.getCompressionLevel() == ZipCommon::CL_FAST || fileEntry.getCompressionLevel() == ZipCommon::CL_SUPERFAST) if (fileEntry.getCompressionLevel() == ZipCommon::CL_FAST || fileEntry.getCompressionLevel() == ZipCommon::CL_SUPERFAST)
level = Z_BEST_SPEED; level = Z_BEST_SPEED;
else if (fileEntry.getCompressionLevel() == ZipCommon::CL_MAXIMUM) else if (fileEntry.getCompressionLevel() == ZipCommon::CL_MAXIMUM)
level = Z_BEST_COMPRESSION; 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! // 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); _ptrOHelper = new PartialOutputStream(*_pOstr, 2, 4, false);
_ptrOBuf = new Poco::DeflatingOutputStream(*_ptrOHelper, DeflatingStreamBuf::STREAM_ZLIB, level); _ptrOBuf = new Poco::DeflatingOutputStream(*_ptrOHelper, DeflatingStreamBuf::STREAM_ZLIB, level);
} }
else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE) else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE)
{ {
_ptrOHelper = new PartialOutputStream(*_pOstr, 0, 0, false); _ptrOHelper = new PartialOutputStream(*_pOstr, 0, 0, false);
_ptrOBuf = _ptrOHelper; _ptrOBuf = _ptrOHelper;
} }
else else
{ {
throw Poco::NotImplementedException("Unsupported compression method"); throw Poco::NotImplementedException("Unsupported compression method");
} }
// now write the header to the ostr! // now write the header to the ostr!
std::string header = fileEntry.createHeader(); std::string header = fileEntry.createHeader();
ostr.write(header.c_str(), static_cast<std::streamsize>(header.size())); ostr.write(header.c_str(), static_cast<std::streamsize>(header.size()));
} }
} }
ZipStreamBuf::~ZipStreamBuf() ZipStreamBuf::~ZipStreamBuf()
{ {
} }
int ZipStreamBuf::readFromDevice(char* buffer, std::streamsize length) int ZipStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{ {
if (!_ptrBuf) return 0; // directory entry if (!_ptrBuf) return 0; // directory entry
_ptrBuf->read(buffer, length); _ptrBuf->read(buffer, length);
int cnt = _ptrBuf->gcount(); int cnt = _ptrBuf->gcount();
if (cnt > 0) if (cnt > 0)
{ {
_crc32.update(buffer, cnt); _crc32.update(buffer, cnt);
} }
else else
{ {
if (_crc32.checksum() != _expectedCrc32) if (_crc32.checksum() != _expectedCrc32)
{ {
if (_checkCRC) if (_checkCRC)
throw ZipException("CRC failure"); throw ZipException("CRC failure");
else else
{ {
// the CRC value is written directly after the data block // the CRC value is written directly after the data block
// parse it directly from the input stream // parse it directly from the input stream
ZipDataInfo nfo(*_pIstr, false); ZipDataInfo nfo(*_pIstr, false);
// now push back the header to the stream, so that the ZipLocalFileHeader can read it // now push back the header to the stream, so that the ZipLocalFileHeader can read it
Poco::Int32 size = static_cast<Poco::Int32>(nfo.getFullHeaderSize()); Poco::Int32 size = static_cast<Poco::Int32>(nfo.getFullHeaderSize());
_expectedCrc32 = nfo.getCRC32(); _expectedCrc32 = nfo.getCRC32();
const char* rawHeader = nfo.getRawHeader(); const char* rawHeader = nfo.getRawHeader();
for (Poco::Int32 i = size-1; i >= 0; --i) for (Poco::Int32 i = size-1; i >= 0; --i)
_pIstr->putback(rawHeader[i]); _pIstr->putback(rawHeader[i]);
if (!crcValid()) if (!crcValid())
throw ZipException("CRC failure"); throw ZipException("CRC failure");
} }
} }
} }
return cnt; return cnt;
} }
int ZipStreamBuf::writeToDevice(const char* buffer, std::streamsize length) int ZipStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{ {
if (!_ptrOBuf) return 0; // directory entry if (!_ptrOBuf) return 0; // directory entry
if (length == 0) if (length == 0)
return 0; return 0;
_bytesWritten += length; _bytesWritten += length;
_ptrOBuf->write(buffer, length); _ptrOBuf->write(buffer, length);
_crc32.update(buffer, length); _crc32.update(buffer, length);
return length; return length;
} }
void ZipStreamBuf::close() void ZipStreamBuf::close()
{ {
if (_ptrOBuf && _pHeader) if (_ptrOBuf && _pHeader)
{ {
_ptrOBuf->flush(); _ptrOBuf->flush();
DeflatingOutputStream* pDO = dynamic_cast<DeflatingOutputStream*>(_ptrOBuf.get()); DeflatingOutputStream* pDO = dynamic_cast<DeflatingOutputStream*>(_ptrOBuf.get());
if (pDO) if (pDO)
pDO->close(); pDO->close();
if (_ptrOHelper) if (_ptrOHelper)
{ {
_ptrOHelper->flush(); _ptrOHelper->flush();
_ptrOHelper->close(); _ptrOHelper->close();
} }
_ptrOBuf = 0; _ptrOBuf = 0;
poco_assert (*_pOstr); poco_assert (*_pOstr);
// write an extra datablock if required // write an extra datablock if required
// or fix the crc entries // or fix the crc entries
if (_pHeader->searchCRCAndSizesAfterData()) if (_pHeader->searchCRCAndSizesAfterData())
{ {
ZipDataInfo info; ZipDataInfo info;
info.setCRC32(_crc32.checksum()); info.setCRC32(_crc32.checksum());
info.setUncompressedSize(_bytesWritten); info.setUncompressedSize(_bytesWritten);
info.setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten())); info.setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten()));
_pOstr->write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize())); _pOstr->write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize()));
} }
else else
{ {
poco_check_ptr (_pHeader); poco_check_ptr (_pHeader);
_pHeader->setCRC(_crc32.checksum()); _pHeader->setCRC(_crc32.checksum());
_pHeader->setUncompressedSize(_bytesWritten); _pHeader->setUncompressedSize(_bytesWritten);
_pHeader->setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten())); _pHeader->setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten()));
_pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg); _pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg);
poco_assert (*_pOstr); poco_assert (*_pOstr);
std::string header = _pHeader->createHeader(); std::string header = _pHeader->createHeader();
_pOstr->write(header.c_str(), static_cast<std::streamsize>(header.size())); _pOstr->write(header.c_str(), static_cast<std::streamsize>(header.size()));
_pOstr->seekp(0, std::ios_base::end); _pOstr->seekp(0, std::ios_base::end);
poco_assert (*_pOstr); poco_assert (*_pOstr);
} }
_pHeader = 0; _pHeader = 0;
} }
} }
bool ZipStreamBuf::crcValid() const bool ZipStreamBuf::crcValid() const
{ {
if (!_ptrBuf) return true; // directory entry if (!_ptrBuf) return true; // directory entry
return _crc32.checksum() == _expectedCrc32; return _crc32.checksum() == _expectedCrc32;
} }
ZipIOS::ZipIOS(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): _buf(istr, fileEntry, reposition) ZipIOS::ZipIOS(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): _buf(istr, fileEntry, reposition)
{ {
poco_ios_init(&_buf); poco_ios_init(&_buf);
} }
ZipIOS::ZipIOS(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition): _buf(ostr, fileEntry, reposition) ZipIOS::ZipIOS(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition): _buf(ostr, fileEntry, reposition)
{ {
poco_ios_init(&_buf); poco_ios_init(&_buf);
} }
ZipIOS::~ZipIOS() ZipIOS::~ZipIOS()
{ {
} }
ZipStreamBuf* ZipIOS::rdbuf() ZipStreamBuf* ZipIOS::rdbuf()
{ {
return &_buf; return &_buf;
} }
ZipInputStream::ZipInputStream(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): ZipIOS(istr, fileEntry, reposition), std::istream(&_buf) ZipInputStream::ZipInputStream(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): ZipIOS(istr, fileEntry, reposition), std::istream(&_buf)
{ {
} }
ZipInputStream::~ZipInputStream() ZipInputStream::~ZipInputStream()
{ {
} }
bool ZipInputStream::crcValid() const bool ZipInputStream::crcValid() const
{ {
return _buf.crcValid(); return _buf.crcValid();
} }
ZipOutputStream::ZipOutputStream(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool seekableOutput): ZipIOS(ostr, fileEntry, seekableOutput), std::ostream(&_buf) ZipOutputStream::ZipOutputStream(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool seekableOutput): ZipIOS(ostr, fileEntry, seekableOutput), std::ostream(&_buf)
{ {
} }
ZipOutputStream::~ZipOutputStream() ZipOutputStream::~ZipOutputStream()
{ {
} }
void ZipOutputStream::close() void ZipOutputStream::close()
{ {
flush(); flush();
_buf.close(); _buf.close();
} }
} } // namespace Poco::Zip } } // namespace Poco::Zip