mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-01 09:24:55 +02:00
fixed SF# 2583934: Zip: No Unix permissions set
This commit is contained in:
parent
717dd9cf45
commit
12c1ae5823
@ -1,468 +1,484 @@
|
||||
//
|
||||
// ZipFileInfo.h
|
||||
//
|
||||
// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipFileInfo.h#3 $
|
||||
//
|
||||
// Library: Zip
|
||||
// Package: Zip
|
||||
// Module: ZipFileInfo
|
||||
//
|
||||
// Definition of the ZipFileInfo class.
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// 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
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// 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
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// 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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#ifndef Zip_ZipFileInfo_INCLUDED
|
||||
#define Zip_ZipFileInfo_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Zip/Zip.h"
|
||||
#include "Poco/Zip/ZipCommon.h"
|
||||
#include "Poco/Zip/ZipUtil.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Zip {
|
||||
|
||||
|
||||
class ZipLocalFileHeader;
|
||||
|
||||
|
||||
class Zip_API ZipFileInfo
|
||||
/// Stores a Zip directory entry of a file
|
||||
{
|
||||
public:
|
||||
static const char HEADER[ZipCommon::HEADER_SIZE];
|
||||
|
||||
ZipFileInfo(const ZipLocalFileHeader& header);
|
||||
/// Creates a ZipFileInfo from a ZipLocalFileHeader
|
||||
|
||||
ZipFileInfo(std::istream& in, bool assumeHeaderRead);
|
||||
/// Creates the ZipFileInfo by parsing the input stream.
|
||||
/// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside.
|
||||
|
||||
~ZipFileInfo();
|
||||
/// Destroys the ZipFileInfo.
|
||||
|
||||
Poco::UInt32 getRelativeOffsetOfLocalHeader() const;
|
||||
/// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header
|
||||
|
||||
ZipCommon::CompressionMethod getCompressionMethod() const;
|
||||
|
||||
bool isEncrypted() const;
|
||||
|
||||
const Poco::DateTime& lastModifiedAt() const;
|
||||
|
||||
Poco::UInt32 getCRC() const;
|
||||
|
||||
Poco::UInt32 getHeaderSize() const;
|
||||
/// Returns the total size of the header including filename + other additional fields
|
||||
|
||||
Poco::UInt32 getCompressedSize() const;
|
||||
|
||||
Poco::UInt32 getUncompressedSize() const;
|
||||
|
||||
const std::string& getFileName() const;
|
||||
|
||||
bool isFile() const;
|
||||
|
||||
bool isDirectory() const;
|
||||
|
||||
bool hasExtraField() const;
|
||||
|
||||
const std::string& getExtraField() const;
|
||||
|
||||
const std::string& getFileComment() const;
|
||||
|
||||
void getVersionMadeBy(int& major, int& minor);
|
||||
/// The ZIP version used to create the file
|
||||
|
||||
void getRequiredVersion(int& major, int& minor);
|
||||
/// The minimum version required to extract the data
|
||||
|
||||
ZipCommon::HostSystem getHostSystem() const;
|
||||
|
||||
Poco::UInt16 getDiskNumberStart() const;
|
||||
/// The number of the disk on which this file begins (multidisk archives)
|
||||
|
||||
ZipCommon::FileType getFileType() const;
|
||||
/// Binary or ASCII file?
|
||||
|
||||
std::string createHeader() const;
|
||||
|
||||
void setOffset(Poco::UInt32 val);
|
||||
|
||||
private:
|
||||
void setCRC(Poco::UInt32 val);
|
||||
|
||||
void setCompressedSize(Poco::UInt32 val);
|
||||
|
||||
void setUncompressedSize(Poco::UInt32 val);
|
||||
|
||||
void setCompressionMethod(ZipCommon::CompressionMethod cm);
|
||||
|
||||
void setCompressionLevel(ZipCommon::CompressionLevel cl);
|
||||
|
||||
void setRequiredVersion(int major, int minor);
|
||||
|
||||
void setHostSystem(ZipCommon::HostSystem hs);
|
||||
|
||||
void setLastModifiedAt(const Poco::DateTime& dt);
|
||||
|
||||
void setEncryption(bool val);
|
||||
|
||||
void setFileNameLength(Poco::UInt16 size);
|
||||
|
||||
void setFileName(const std::string& str);
|
||||
|
||||
void parse(std::istream& in, bool assumeHeaderRead);
|
||||
|
||||
void parseDateTime();
|
||||
|
||||
Poco::UInt32 getCRCFromHeader() const;
|
||||
|
||||
Poco::UInt32 getCompressedSizeFromHeader() const;
|
||||
|
||||
Poco::UInt32 getUncompressedSizeFromHeader() const;
|
||||
|
||||
Poco::UInt16 getFileNameLength() const;
|
||||
|
||||
Poco::UInt16 getExtraFieldLength() const;
|
||||
|
||||
Poco::UInt16 getFileCommentLength() const;
|
||||
|
||||
Poco::UInt32 getExternalFileAttributes() const;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
HEADER_POS = 0,
|
||||
VERSIONMADEBY_POS = HEADER_POS + ZipCommon::HEADER_SIZE,
|
||||
VERSIONMADEBY_SIZE = 2,
|
||||
VERSION_NEEDED_POS = VERSIONMADEBY_POS + VERSIONMADEBY_SIZE,
|
||||
VERSION_NEEDED_SIZE = 2,
|
||||
GENERAL_PURPOSE_POS = VERSION_NEEDED_POS + VERSION_NEEDED_SIZE,
|
||||
GENERAL_PURPOSE_SIZE = 2,
|
||||
COMPR_METHOD_POS = GENERAL_PURPOSE_POS + GENERAL_PURPOSE_SIZE,
|
||||
COMPR_METHOD_SIZE = 2,
|
||||
LASTMODFILETIME_POS = COMPR_METHOD_POS + COMPR_METHOD_SIZE,
|
||||
LASTMODFILETIME_SIZE = 2,
|
||||
LASTMODFILEDATE_POS = LASTMODFILETIME_POS + LASTMODFILETIME_SIZE,
|
||||
LASTMODFILEDATE_SIZE = 2,
|
||||
CRC32_POS = LASTMODFILEDATE_POS + LASTMODFILEDATE_SIZE,
|
||||
CRC32_SIZE = 4,
|
||||
COMPRESSED_SIZE_POS = CRC32_POS + CRC32_SIZE,
|
||||
COMPRESSED_SIZE_SIZE = 4,
|
||||
UNCOMPRESSED_SIZE_POS = COMPRESSED_SIZE_POS + COMPRESSED_SIZE_SIZE,
|
||||
UNCOMPRESSED_SIZE_SIZE = 4,
|
||||
FILENAME_LENGTH_POS = UNCOMPRESSED_SIZE_POS + UNCOMPRESSED_SIZE_SIZE,
|
||||
FILENAME_LENGTH_SIZE = 2,
|
||||
EXTRAFIELD_LENGTH_POS = FILENAME_LENGTH_POS + FILENAME_LENGTH_SIZE,
|
||||
EXTRAFIELD_LENGTH_SIZE = 2,
|
||||
FILECOMMENT_LENGTH_POS = EXTRAFIELD_LENGTH_POS + EXTRAFIELD_LENGTH_SIZE,
|
||||
FILECOMMENT_LENGTH_SIZE = 2,
|
||||
DISKNUMBERSTART_POS = FILECOMMENT_LENGTH_POS + FILECOMMENT_LENGTH_SIZE,
|
||||
DISKNUMBERSTART_SIZE = 2,
|
||||
INTERNALFILE_ATTR_POS = DISKNUMBERSTART_POS + DISKNUMBERSTART_SIZE,
|
||||
INTERNALFILE_ATTR_SIZE = 2,
|
||||
EXTERNALFILE_ATTR_POS = INTERNALFILE_ATTR_POS + INTERNALFILE_ATTR_SIZE,
|
||||
EXTERNALFILE_ATTR_SIZE = 4,
|
||||
RELATIVEOFFSETLOCALHEADER_POS = EXTERNALFILE_ATTR_POS + EXTERNALFILE_ATTR_SIZE,
|
||||
RELATIVEOFFSETLOCALHEADER_SIZE = 4,
|
||||
FULLHEADER_SIZE = 46
|
||||
};
|
||||
|
||||
char _rawInfo[FULLHEADER_SIZE];
|
||||
Poco::UInt32 _crc32;
|
||||
Poco::UInt32 _compressedSize;
|
||||
Poco::UInt32 _uncompressedSize;
|
||||
std::string _fileName;
|
||||
Poco::DateTime _lastModifiedAt;
|
||||
std::string _extraField;
|
||||
std::string _fileComment;
|
||||
};
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getRelativeOffsetOfLocalHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCRCFromHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, CRC32_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCompressedSizeFromHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, COMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getUncompressedSizeFromHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::parseDateTime()
|
||||
{
|
||||
_lastModifiedAt = ZipUtil::parseDateTime(_rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline ZipCommon::CompressionMethod ZipFileInfo::getCompressionMethod() const
|
||||
{
|
||||
return static_cast<ZipCommon::CompressionMethod>(ZipUtil::get16BitValue(_rawInfo, COMPR_METHOD_POS));
|
||||
}
|
||||
|
||||
|
||||
inline bool ZipFileInfo::isEncrypted() const
|
||||
{
|
||||
// bit 0 indicates encryption
|
||||
return ((ZipUtil::get16BitValue(_rawInfo, GENERAL_PURPOSE_POS) & 0x0001) != 0);
|
||||
}
|
||||
|
||||
|
||||
inline const Poco::DateTime& ZipFileInfo::lastModifiedAt() const
|
||||
{
|
||||
return _lastModifiedAt;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCRC() const
|
||||
{
|
||||
return _crc32;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCompressedSize() const
|
||||
{
|
||||
return _compressedSize;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getUncompressedSize() const
|
||||
{
|
||||
return _uncompressedSize;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& ZipFileInfo::getFileName() const
|
||||
{
|
||||
return _fileName;
|
||||
}
|
||||
|
||||
|
||||
inline bool ZipFileInfo::isFile() const
|
||||
{
|
||||
return !isDirectory();
|
||||
}
|
||||
|
||||
|
||||
inline bool ZipFileInfo::isDirectory() const
|
||||
{
|
||||
poco_assert_dbg(!_fileName.empty());
|
||||
return getUncompressedSize() == 0 && getCompressionMethod() == ZipCommon::CM_STORE && _fileName[_fileName.length()-1] == '/';
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt16 ZipFileInfo::getFileNameLength() const
|
||||
{
|
||||
return ZipUtil::get16BitValue(_rawInfo, FILENAME_LENGTH_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt16 ZipFileInfo::getExtraFieldLength() const
|
||||
{
|
||||
return ZipUtil::get16BitValue(_rawInfo, EXTRAFIELD_LENGTH_POS);
|
||||
}
|
||||
|
||||
|
||||
inline bool ZipFileInfo::hasExtraField() const
|
||||
{
|
||||
return getExtraFieldLength() > 0;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& ZipFileInfo::getExtraField() const
|
||||
{
|
||||
return _extraField;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& ZipFileInfo::getFileComment() const
|
||||
{
|
||||
return _fileComment;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt16 ZipFileInfo::getFileCommentLength() const
|
||||
{
|
||||
return ZipUtil::get16BitValue(_rawInfo, FILECOMMENT_LENGTH_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::getVersionMadeBy(int& major, int& minor)
|
||||
{
|
||||
major = (_rawInfo[VERSIONMADEBY_POS]/10);
|
||||
minor = (_rawInfo[VERSIONMADEBY_POS]%10);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::getRequiredVersion(int& major, int& minor)
|
||||
{
|
||||
major = (_rawInfo[VERSION_NEEDED_POS]/10);
|
||||
minor = (_rawInfo[VERSION_NEEDED_POS]%10);
|
||||
}
|
||||
|
||||
|
||||
inline ZipCommon::HostSystem ZipFileInfo::getHostSystem() const
|
||||
{
|
||||
return static_cast<ZipCommon::HostSystem>(_rawInfo[VERSION_NEEDED_POS + 1]);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt16 ZipFileInfo::getDiskNumberStart() const
|
||||
{
|
||||
return ZipUtil::get16BitValue(_rawInfo, DISKNUMBERSTART_POS);
|
||||
}
|
||||
|
||||
|
||||
inline ZipCommon::FileType ZipFileInfo::getFileType() const
|
||||
{
|
||||
return static_cast<ZipCommon::FileType>(_rawInfo[INTERNALFILE_ATTR_POS] & 0x01);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getExternalFileAttributes() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, EXTERNALFILE_ATTR_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getHeaderSize() const
|
||||
{
|
||||
return FULLHEADER_SIZE + getFileNameLength() + getExtraFieldLength() + getFileCommentLength();
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setCRC(Poco::UInt32 val)
|
||||
{
|
||||
_crc32 = val;
|
||||
ZipUtil::set32BitValue(val, _rawInfo, CRC32_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setOffset(Poco::UInt32 val)
|
||||
{
|
||||
ZipUtil::set32BitValue(val, _rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setCompressedSize(Poco::UInt32 val)
|
||||
{
|
||||
_compressedSize = val;
|
||||
ZipUtil::set32BitValue(val, _rawInfo, COMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setUncompressedSize(Poco::UInt32 val)
|
||||
{
|
||||
_uncompressedSize = val;
|
||||
ZipUtil::set32BitValue(val, _rawInfo, UNCOMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setCompressionMethod(ZipCommon::CompressionMethod cm)
|
||||
{
|
||||
ZipUtil::set16BitValue(static_cast<Poco::UInt16>(cm), _rawInfo, COMPR_METHOD_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setCompressionLevel(ZipCommon::CompressionLevel cl)
|
||||
{
|
||||
// bit 1 and 2 indicate the level
|
||||
Poco::UInt16 val = static_cast<Poco::UInt16>(cl);
|
||||
val <<= 1;
|
||||
Poco::UInt16 mask = 0xfff9;
|
||||
_rawInfo[GENERAL_PURPOSE_POS] = ((_rawInfo[GENERAL_PURPOSE_POS] & mask) | val);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setFileNameLength(Poco::UInt16 size)
|
||||
{
|
||||
ZipUtil::set16BitValue(size, _rawInfo, FILENAME_LENGTH_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setHostSystem(ZipCommon::HostSystem hs)
|
||||
{
|
||||
_rawInfo[VERSIONMADEBY_POS + 1] = static_cast<char>(hs);
|
||||
_rawInfo[VERSION_NEEDED_POS + 1] = static_cast<char>(hs);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setRequiredVersion(int major, int minor)
|
||||
{
|
||||
poco_assert (minor < 10);
|
||||
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::setLastModifiedAt(const Poco::DateTime& dt)
|
||||
{
|
||||
_lastModifiedAt = dt;
|
||||
ZipUtil::setDateTime(dt, _rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setEncryption(bool val)
|
||||
{
|
||||
if (val)
|
||||
_rawInfo[GENERAL_PURPOSE_POS] |= 0x01;
|
||||
else
|
||||
_rawInfo[GENERAL_PURPOSE_POS] &= 0xfe;
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setFileName(const std::string& str)
|
||||
{
|
||||
_fileName = str;
|
||||
setFileNameLength(static_cast<Poco::UInt16>(str.size()));
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Zip
|
||||
|
||||
|
||||
#endif // Zip_ZipFileInfo_INCLUDED
|
||||
//
|
||||
// ZipFileInfo.h
|
||||
//
|
||||
// $Id: //poco/Main/Zip/include/Poco/Zip/ZipFileInfo.h#8 $
|
||||
//
|
||||
// Library: Zip
|
||||
// Package: Zip
|
||||
// Module: ZipFileInfo
|
||||
//
|
||||
// Definition of the ZipFileInfo class.
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// 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
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// 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
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// 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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#ifndef Zip_ZipFileInfo_INCLUDED
|
||||
#define Zip_ZipFileInfo_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Zip/Zip.h"
|
||||
#include "Poco/Zip/ZipCommon.h"
|
||||
#include "Poco/Zip/ZipUtil.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Zip {
|
||||
|
||||
|
||||
class ZipLocalFileHeader;
|
||||
|
||||
|
||||
class Zip_API ZipFileInfo
|
||||
/// Stores a Zip directory entry of a file
|
||||
{
|
||||
public:
|
||||
static const char HEADER[ZipCommon::HEADER_SIZE];
|
||||
|
||||
ZipFileInfo(const ZipLocalFileHeader& header);
|
||||
/// Creates a ZipFileInfo from a ZipLocalFileHeader
|
||||
|
||||
ZipFileInfo(std::istream& in, bool assumeHeaderRead);
|
||||
/// Creates the ZipFileInfo by parsing the input stream.
|
||||
/// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside.
|
||||
|
||||
~ZipFileInfo();
|
||||
/// Destroys the ZipFileInfo.
|
||||
|
||||
Poco::UInt32 getRelativeOffsetOfLocalHeader() const;
|
||||
/// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header
|
||||
|
||||
ZipCommon::CompressionMethod getCompressionMethod() const;
|
||||
|
||||
bool isEncrypted() const;
|
||||
|
||||
const Poco::DateTime& lastModifiedAt() const;
|
||||
|
||||
Poco::UInt32 getCRC() const;
|
||||
|
||||
Poco::UInt32 getHeaderSize() const;
|
||||
/// Returns the total size of the header including filename + other additional fields
|
||||
|
||||
Poco::UInt32 getCompressedSize() const;
|
||||
|
||||
Poco::UInt32 getUncompressedSize() const;
|
||||
|
||||
const std::string& getFileName() const;
|
||||
|
||||
bool isFile() const;
|
||||
|
||||
bool isDirectory() const;
|
||||
|
||||
bool hasExtraField() const;
|
||||
|
||||
const std::string& getExtraField() const;
|
||||
|
||||
const std::string& getFileComment() const;
|
||||
|
||||
void getVersionMadeBy(int& major, int& minor);
|
||||
/// The ZIP version used to create the file
|
||||
|
||||
void getRequiredVersion(int& major, int& minor);
|
||||
/// The minimum version required to extract the data
|
||||
|
||||
ZipCommon::HostSystem getHostSystem() const;
|
||||
|
||||
Poco::UInt16 getDiskNumberStart() const;
|
||||
/// The number of the disk on which this file begins (multidisk archives)
|
||||
|
||||
ZipCommon::FileType getFileType() const;
|
||||
/// Binary or ASCII file?
|
||||
|
||||
std::string createHeader() const;
|
||||
|
||||
void setOffset(Poco::UInt32 val);
|
||||
|
||||
private:
|
||||
void setCRC(Poco::UInt32 val);
|
||||
|
||||
void setCompressedSize(Poco::UInt32 val);
|
||||
|
||||
void setUncompressedSize(Poco::UInt32 val);
|
||||
|
||||
void setCompressionMethod(ZipCommon::CompressionMethod cm);
|
||||
|
||||
void setCompressionLevel(ZipCommon::CompressionLevel cl);
|
||||
|
||||
void setRequiredVersion(int major, int minor);
|
||||
|
||||
void setHostSystem(ZipCommon::HostSystem hs);
|
||||
|
||||
void setLastModifiedAt(const Poco::DateTime& dt);
|
||||
|
||||
void setEncryption(bool val);
|
||||
|
||||
void setFileNameLength(Poco::UInt16 size);
|
||||
|
||||
void setFileName(const std::string& str);
|
||||
|
||||
void setExternalFileAttributes(Poco::UInt32 attrs);
|
||||
|
||||
void parse(std::istream& in, bool assumeHeaderRead);
|
||||
|
||||
void parseDateTime();
|
||||
|
||||
Poco::UInt32 getCRCFromHeader() const;
|
||||
|
||||
Poco::UInt32 getCompressedSizeFromHeader() const;
|
||||
|
||||
Poco::UInt32 getUncompressedSizeFromHeader() const;
|
||||
|
||||
Poco::UInt16 getFileNameLength() const;
|
||||
|
||||
Poco::UInt16 getExtraFieldLength() const;
|
||||
|
||||
Poco::UInt16 getFileCommentLength() const;
|
||||
|
||||
Poco::UInt32 getExternalFileAttributes() const;
|
||||
|
||||
void setUnixAttributes();
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
HEADER_POS = 0,
|
||||
VERSIONMADEBY_POS = HEADER_POS + ZipCommon::HEADER_SIZE,
|
||||
VERSIONMADEBY_SIZE = 2,
|
||||
VERSION_NEEDED_POS = VERSIONMADEBY_POS + VERSIONMADEBY_SIZE,
|
||||
VERSION_NEEDED_SIZE = 2,
|
||||
GENERAL_PURPOSE_POS = VERSION_NEEDED_POS + VERSION_NEEDED_SIZE,
|
||||
GENERAL_PURPOSE_SIZE = 2,
|
||||
COMPR_METHOD_POS = GENERAL_PURPOSE_POS + GENERAL_PURPOSE_SIZE,
|
||||
COMPR_METHOD_SIZE = 2,
|
||||
LASTMODFILETIME_POS = COMPR_METHOD_POS + COMPR_METHOD_SIZE,
|
||||
LASTMODFILETIME_SIZE = 2,
|
||||
LASTMODFILEDATE_POS = LASTMODFILETIME_POS + LASTMODFILETIME_SIZE,
|
||||
LASTMODFILEDATE_SIZE = 2,
|
||||
CRC32_POS = LASTMODFILEDATE_POS + LASTMODFILEDATE_SIZE,
|
||||
CRC32_SIZE = 4,
|
||||
COMPRESSED_SIZE_POS = CRC32_POS + CRC32_SIZE,
|
||||
COMPRESSED_SIZE_SIZE = 4,
|
||||
UNCOMPRESSED_SIZE_POS = COMPRESSED_SIZE_POS + COMPRESSED_SIZE_SIZE,
|
||||
UNCOMPRESSED_SIZE_SIZE = 4,
|
||||
FILENAME_LENGTH_POS = UNCOMPRESSED_SIZE_POS + UNCOMPRESSED_SIZE_SIZE,
|
||||
FILENAME_LENGTH_SIZE = 2,
|
||||
EXTRAFIELD_LENGTH_POS = FILENAME_LENGTH_POS + FILENAME_LENGTH_SIZE,
|
||||
EXTRAFIELD_LENGTH_SIZE = 2,
|
||||
FILECOMMENT_LENGTH_POS = EXTRAFIELD_LENGTH_POS + EXTRAFIELD_LENGTH_SIZE,
|
||||
FILECOMMENT_LENGTH_SIZE = 2,
|
||||
DISKNUMBERSTART_POS = FILECOMMENT_LENGTH_POS + FILECOMMENT_LENGTH_SIZE,
|
||||
DISKNUMBERSTART_SIZE = 2,
|
||||
INTERNALFILE_ATTR_POS = DISKNUMBERSTART_POS + DISKNUMBERSTART_SIZE,
|
||||
INTERNALFILE_ATTR_SIZE = 2,
|
||||
EXTERNALFILE_ATTR_POS = INTERNALFILE_ATTR_POS + INTERNALFILE_ATTR_SIZE,
|
||||
EXTERNALFILE_ATTR_SIZE = 4,
|
||||
RELATIVEOFFSETLOCALHEADER_POS = EXTERNALFILE_ATTR_POS + EXTERNALFILE_ATTR_SIZE,
|
||||
RELATIVEOFFSETLOCALHEADER_SIZE = 4,
|
||||
FULLHEADER_SIZE = 46
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DEFAULT_UNIX_FILE_MODE = 0640,
|
||||
DEFAULT_UNIX_DIR_MODE = 0755
|
||||
};
|
||||
|
||||
char _rawInfo[FULLHEADER_SIZE];
|
||||
Poco::UInt32 _crc32;
|
||||
Poco::UInt32 _compressedSize;
|
||||
Poco::UInt32 _uncompressedSize;
|
||||
std::string _fileName;
|
||||
Poco::DateTime _lastModifiedAt;
|
||||
std::string _extraField;
|
||||
std::string _fileComment;
|
||||
};
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getRelativeOffsetOfLocalHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCRCFromHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, CRC32_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCompressedSizeFromHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, COMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getUncompressedSizeFromHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::parseDateTime()
|
||||
{
|
||||
_lastModifiedAt = ZipUtil::parseDateTime(_rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline ZipCommon::CompressionMethod ZipFileInfo::getCompressionMethod() const
|
||||
{
|
||||
return static_cast<ZipCommon::CompressionMethod>(ZipUtil::get16BitValue(_rawInfo, COMPR_METHOD_POS));
|
||||
}
|
||||
|
||||
|
||||
inline bool ZipFileInfo::isEncrypted() const
|
||||
{
|
||||
// bit 0 indicates encryption
|
||||
return ((ZipUtil::get16BitValue(_rawInfo, GENERAL_PURPOSE_POS) & 0x0001) != 0);
|
||||
}
|
||||
|
||||
|
||||
inline const Poco::DateTime& ZipFileInfo::lastModifiedAt() const
|
||||
{
|
||||
return _lastModifiedAt;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCRC() const
|
||||
{
|
||||
return _crc32;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCompressedSize() const
|
||||
{
|
||||
return _compressedSize;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getUncompressedSize() const
|
||||
{
|
||||
return _uncompressedSize;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& ZipFileInfo::getFileName() const
|
||||
{
|
||||
return _fileName;
|
||||
}
|
||||
|
||||
|
||||
inline bool ZipFileInfo::isFile() const
|
||||
{
|
||||
return !isDirectory();
|
||||
}
|
||||
|
||||
|
||||
inline bool ZipFileInfo::isDirectory() const
|
||||
{
|
||||
poco_assert_dbg(!_fileName.empty());
|
||||
return getUncompressedSize() == 0 && getCompressionMethod() == ZipCommon::CM_STORE && _fileName[_fileName.length()-1] == '/';
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt16 ZipFileInfo::getFileNameLength() const
|
||||
{
|
||||
return ZipUtil::get16BitValue(_rawInfo, FILENAME_LENGTH_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt16 ZipFileInfo::getExtraFieldLength() const
|
||||
{
|
||||
return ZipUtil::get16BitValue(_rawInfo, EXTRAFIELD_LENGTH_POS);
|
||||
}
|
||||
|
||||
|
||||
inline bool ZipFileInfo::hasExtraField() const
|
||||
{
|
||||
return getExtraFieldLength() > 0;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& ZipFileInfo::getExtraField() const
|
||||
{
|
||||
return _extraField;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& ZipFileInfo::getFileComment() const
|
||||
{
|
||||
return _fileComment;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt16 ZipFileInfo::getFileCommentLength() const
|
||||
{
|
||||
return ZipUtil::get16BitValue(_rawInfo, FILECOMMENT_LENGTH_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::getVersionMadeBy(int& major, int& minor)
|
||||
{
|
||||
major = (_rawInfo[VERSIONMADEBY_POS]/10);
|
||||
minor = (_rawInfo[VERSIONMADEBY_POS]%10);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::getRequiredVersion(int& major, int& minor)
|
||||
{
|
||||
major = (_rawInfo[VERSION_NEEDED_POS]/10);
|
||||
minor = (_rawInfo[VERSION_NEEDED_POS]%10);
|
||||
}
|
||||
|
||||
|
||||
inline ZipCommon::HostSystem ZipFileInfo::getHostSystem() const
|
||||
{
|
||||
return static_cast<ZipCommon::HostSystem>(_rawInfo[VERSION_NEEDED_POS + 1]);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt16 ZipFileInfo::getDiskNumberStart() const
|
||||
{
|
||||
return ZipUtil::get16BitValue(_rawInfo, DISKNUMBERSTART_POS);
|
||||
}
|
||||
|
||||
|
||||
inline ZipCommon::FileType ZipFileInfo::getFileType() const
|
||||
{
|
||||
return static_cast<ZipCommon::FileType>(_rawInfo[INTERNALFILE_ATTR_POS] & 0x01);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getExternalFileAttributes() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, EXTERNALFILE_ATTR_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getHeaderSize() const
|
||||
{
|
||||
return FULLHEADER_SIZE + getFileNameLength() + getExtraFieldLength() + getFileCommentLength();
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setCRC(Poco::UInt32 val)
|
||||
{
|
||||
_crc32 = val;
|
||||
ZipUtil::set32BitValue(val, _rawInfo, CRC32_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setOffset(Poco::UInt32 val)
|
||||
{
|
||||
ZipUtil::set32BitValue(val, _rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setCompressedSize(Poco::UInt32 val)
|
||||
{
|
||||
_compressedSize = val;
|
||||
ZipUtil::set32BitValue(val, _rawInfo, COMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setUncompressedSize(Poco::UInt32 val)
|
||||
{
|
||||
_uncompressedSize = val;
|
||||
ZipUtil::set32BitValue(val, _rawInfo, UNCOMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setCompressionMethod(ZipCommon::CompressionMethod cm)
|
||||
{
|
||||
ZipUtil::set16BitValue(static_cast<Poco::UInt16>(cm), _rawInfo, COMPR_METHOD_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setCompressionLevel(ZipCommon::CompressionLevel cl)
|
||||
{
|
||||
// bit 1 and 2 indicate the level
|
||||
Poco::UInt16 val = static_cast<Poco::UInt16>(cl);
|
||||
val <<= 1;
|
||||
Poco::UInt16 mask = 0xfff9;
|
||||
_rawInfo[GENERAL_PURPOSE_POS] = ((_rawInfo[GENERAL_PURPOSE_POS] & mask) | val);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setFileNameLength(Poco::UInt16 size)
|
||||
{
|
||||
ZipUtil::set16BitValue(size, _rawInfo, FILENAME_LENGTH_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setHostSystem(ZipCommon::HostSystem hs)
|
||||
{
|
||||
_rawInfo[VERSIONMADEBY_POS + 1] = static_cast<char>(hs);
|
||||
_rawInfo[VERSION_NEEDED_POS + 1] = static_cast<char>(hs);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setRequiredVersion(int major, int minor)
|
||||
{
|
||||
poco_assert (minor < 10);
|
||||
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::setLastModifiedAt(const Poco::DateTime& dt)
|
||||
{
|
||||
_lastModifiedAt = dt;
|
||||
ZipUtil::setDateTime(dt, _rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setEncryption(bool val)
|
||||
{
|
||||
if (val)
|
||||
_rawInfo[GENERAL_PURPOSE_POS] |= 0x01;
|
||||
else
|
||||
_rawInfo[GENERAL_PURPOSE_POS] &= 0xfe;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@ -1,322 +1,322 @@
|
||||
//
|
||||
// Compress.cpp
|
||||
//
|
||||
// $Id: //poco/1.3/Zip/src/Compress.cpp#4 $
|
||||
//
|
||||
// Library: Zip
|
||||
// Package: Zip
|
||||
// Module: Compress
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// 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
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// 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
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// 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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Zip/Compress.h"
|
||||
#include "Poco/Zip/ZipLocalFileHeader.h"
|
||||
#include "Poco/Zip/ZipStream.h"
|
||||
#include "Poco/Zip/ZipArchiveInfo.h"
|
||||
#include "Poco/Zip/ZipDataInfo.h"
|
||||
#include "Poco/Zip/ZipException.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/File.h"
|
||||
#include <fstream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Zip {
|
||||
|
||||
|
||||
Compress::Compress(std::ostream& out, bool seekableOut):
|
||||
_out(out),
|
||||
_seekableOut(seekableOut),
|
||||
_files(),
|
||||
_infos(),
|
||||
_dirs(),
|
||||
_offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Compress::~Compress()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
if (_files.size() >= 65535)
|
||||
throw ZipException("Maximum number of entries for a ZIP file reached: 65535");
|
||||
if (!in.good())
|
||||
throw ZipException("Invalid input stream");
|
||||
|
||||
std::streamoff localHeaderOffset = _offset;
|
||||
ZipLocalFileHeader hdr(fileName, lastModifiedAt, cm, cl);
|
||||
hdr.setStartPos(localHeaderOffset);
|
||||
|
||||
ZipOutputStream zipOut(_out, hdr, _seekableOut);
|
||||
Poco::StreamCopier::copyStream(in, zipOut);
|
||||
zipOut.close();
|
||||
hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known
|
||||
_offset = hdr.getEndPos();
|
||||
if (hdr.searchCRCAndSizesAfterData())
|
||||
_offset += ZipDataInfo::getFullHeaderSize();
|
||||
_files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr));
|
||||
poco_assert (_out);
|
||||
ZipFileInfo nfo(hdr);
|
||||
nfo.setOffset(localHeaderOffset);
|
||||
_infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo));
|
||||
EDone.notify(this, hdr);
|
||||
}
|
||||
|
||||
|
||||
void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const Poco::Path& fileName)
|
||||
{
|
||||
std::string fn = ZipUtil::validZipEntryFileName(fileName);
|
||||
//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);
|
||||
|
||||
if (_files.size() >= 65535)
|
||||
throw ZipException("Maximum number of entries for a ZIP file reached: 65535");
|
||||
if (!in.good())
|
||||
throw ZipException("Invalid input stream");
|
||||
|
||||
std::streamoff localHeaderOffset = _offset;
|
||||
ZipLocalFileHeader hdr(h);
|
||||
hdr.setFileName(fn, h.isDirectory());
|
||||
hdr.setStartPos(localHeaderOffset);
|
||||
//bypass zipoutputstream
|
||||
//write the header directly
|
||||
std::string header = hdr.createHeader();
|
||||
_out.write(header.c_str(), static_cast<std::streamsize>(header.size()));
|
||||
// now fwd the payload to _out in chunks of size CHUNKSIZE
|
||||
Poco::UInt32 totalSize = hdr.getCompressedSize();
|
||||
if (totalSize > 0)
|
||||
{
|
||||
Poco::Buffer<char> buffer(COMPRESS_CHUNK_SIZE);
|
||||
Poco::UInt32 remaining = totalSize;
|
||||
while(remaining > 0)
|
||||
{
|
||||
if (remaining > COMPRESS_CHUNK_SIZE)
|
||||
{
|
||||
in.read(buffer.begin(), COMPRESS_CHUNK_SIZE);
|
||||
std::streamsize n = in.gcount();
|
||||
poco_assert_dbg (n == COMPRESS_CHUNK_SIZE);
|
||||
_out.write(buffer.begin(), n);
|
||||
remaining -= COMPRESS_CHUNK_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
in.read(buffer.begin(), remaining);
|
||||
std::streamsize n = in.gcount();
|
||||
poco_assert_dbg (n == remaining);
|
||||
_out.write(buffer.begin(), n);
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//write optional block afterwards
|
||||
if (hdr.searchCRCAndSizesAfterData())
|
||||
{
|
||||
ZipDataInfo info(in, false);
|
||||
_out.write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize()));
|
||||
}
|
||||
hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known
|
||||
_offset = hdr.getEndPos();
|
||||
if (hdr.searchCRCAndSizesAfterData())
|
||||
_offset += ZipDataInfo::getFullHeaderSize();
|
||||
_files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr));
|
||||
poco_assert (_out);
|
||||
ZipFileInfo nfo(hdr);
|
||||
nfo.setOffset(localHeaderOffset);
|
||||
_infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo));
|
||||
EDone.notify(this, hdr);
|
||||
}
|
||||
|
||||
|
||||
void Compress::addFile(std::istream& in, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl)
|
||||
{
|
||||
if (!fileName.isFile())
|
||||
throw ZipException("Not a file: "+ fileName.toString());
|
||||
|
||||
if (fileName.depth() > 1)
|
||||
{
|
||||
addDirectory(fileName.parent(), lastModifiedAt);
|
||||
}
|
||||
addEntry(in, lastModifiedAt, fileName, cm, cl);
|
||||
}
|
||||
|
||||
|
||||
void Compress::addFile(const Poco::Path& file, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl)
|
||||
{
|
||||
Poco::File aFile(file);
|
||||
Poco::File::FileSize size = aFile.getSize();
|
||||
if (size < 16)
|
||||
{
|
||||
cm = ZipCommon::CM_STORE;
|
||||
cl = ZipCommon::CL_NORMAL;
|
||||
}
|
||||
|
||||
std::ifstream in(file.toString().c_str(), std::ios::binary);
|
||||
if (!in.good())
|
||||
throw ZipException("Invalid input stream for " + aFile.path());
|
||||
if (fileName.depth() > 1)
|
||||
{
|
||||
Poco::File aParent(file.parent());
|
||||
addDirectory(fileName.parent(), aParent.getLastModified());
|
||||
}
|
||||
addFile(in, aFile.getLastModified(), fileName, cm, cl);
|
||||
}
|
||||
|
||||
|
||||
void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& lastModifiedAt)
|
||||
{
|
||||
if (!entryName.isDirectory())
|
||||
throw ZipException("Not a directory: "+ entryName.toString());
|
||||
|
||||
std::string fileStr = entryName.toString(Poco::Path::PATH_UNIX);
|
||||
if (_files.find(fileStr) != _files.end())
|
||||
return; // ignore duplicate add
|
||||
if (_files.size() >= 65535)
|
||||
throw ZipException("Maximum number of entries for a ZIP file reached: 65535");
|
||||
if (fileStr == "/")
|
||||
throw ZipException("Illegal entry name /");
|
||||
if (fileStr.empty())
|
||||
throw ZipException("Illegal empty entry name");
|
||||
if (fileStr.find(ZipCommon::ILLEGAL_PATH) != std::string::npos)
|
||||
throw ZipException("Illegal entry name " + fileStr + " containing " + ZipCommon::ILLEGAL_PATH);
|
||||
|
||||
if (entryName.depth() > 1)
|
||||
{
|
||||
addDirectory(entryName.parent(), lastModifiedAt);
|
||||
}
|
||||
|
||||
std::streamoff localHeaderOffset = _offset;
|
||||
ZipCommon::CompressionMethod cm = ZipCommon::CM_STORE;
|
||||
ZipCommon::CompressionLevel cl = ZipCommon::CL_NORMAL;
|
||||
ZipLocalFileHeader hdr(entryName, lastModifiedAt, cm, cl);
|
||||
hdr.setStartPos(localHeaderOffset);
|
||||
ZipOutputStream zipOut(_out, hdr, _seekableOut);
|
||||
zipOut.close();
|
||||
hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known
|
||||
_offset = hdr.getEndPos();
|
||||
if (hdr.searchCRCAndSizesAfterData())
|
||||
_offset += ZipDataInfo::getFullHeaderSize();
|
||||
_files.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), hdr));
|
||||
poco_assert (_out);
|
||||
ZipFileInfo nfo(hdr);
|
||||
nfo.setOffset(localHeaderOffset);
|
||||
_infos.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), nfo));
|
||||
EDone.notify(this, hdr);
|
||||
}
|
||||
|
||||
|
||||
void Compress::addRecursive(const Poco::Path& entry, ZipCommon::CompressionLevel cl, bool excludeRoot, const Poco::Path& name)
|
||||
{
|
||||
Poco::File aFile(entry);
|
||||
if (!aFile.isDirectory())
|
||||
throw ZipException("Not a directory: "+ entry.toString());
|
||||
Poco::Path aName(name);
|
||||
aName.makeDirectory();
|
||||
if (!excludeRoot)
|
||||
{
|
||||
if (aName.depth() == 0)
|
||||
{
|
||||
Poco::Path tmp(entry);
|
||||
tmp.makeAbsolute(); // eliminate ../
|
||||
aName = Poco::Path(tmp[tmp.depth()-1]);
|
||||
aName.makeDirectory();
|
||||
}
|
||||
|
||||
addDirectory(aName, aFile.getLastModified());
|
||||
}
|
||||
|
||||
// iterate over children
|
||||
std::vector<std::string> children;
|
||||
aFile.list(children);
|
||||
std::vector<std::string>::const_iterator it = children.begin();
|
||||
std::vector<std::string>::const_iterator itEnd = children.end();
|
||||
for (; it != itEnd; ++it)
|
||||
{
|
||||
Poco::Path realFile(entry, *it);
|
||||
Poco::Path renamedFile(aName, *it);
|
||||
Poco::File aFile(realFile);
|
||||
if (aFile.isDirectory())
|
||||
{
|
||||
realFile.makeDirectory();
|
||||
renamedFile.makeDirectory();
|
||||
addRecursive(realFile, cl, false, renamedFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
realFile.makeFile();
|
||||
renamedFile.makeFile();
|
||||
addFile(realFile, renamedFile, ZipCommon::CM_DEFLATE, cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZipArchive Compress::close()
|
||||
{
|
||||
if (!_dirs.empty())
|
||||
return ZipArchive(_files, _infos, _dirs);
|
||||
|
||||
poco_assert (_infos.size() == _files.size());
|
||||
poco_assert (_files.size() < 65536);
|
||||
Poco::UInt32 centralDirStart = _offset;
|
||||
Poco::UInt32 centralDirSize = 0;
|
||||
// write all infos
|
||||
ZipArchive::FileInfos::const_iterator it = _infos.begin();
|
||||
ZipArchive::FileInfos::const_iterator itEnd = _infos.end();
|
||||
for (; it != itEnd; ++it)
|
||||
{
|
||||
const ZipFileInfo& nfo = it->second;
|
||||
std::string info(nfo.createHeader());
|
||||
_out.write(info.c_str(), static_cast<std::streamsize>(info.size()));
|
||||
Poco::UInt32 entrySize = static_cast<Poco::UInt32>(info.size());
|
||||
centralDirSize += entrySize;
|
||||
_offset += entrySize;
|
||||
}
|
||||
poco_assert (_out);
|
||||
|
||||
|
||||
Poco::UInt16 numEntries = static_cast<Poco::UInt16>(_infos.size());
|
||||
ZipArchiveInfo central;
|
||||
central.setCentralDirectorySize(centralDirSize);
|
||||
central.setNumberOfEntries(numEntries);
|
||||
central.setTotalNumberOfEntries(numEntries);
|
||||
central.setHeaderOffset(centralDirStart);
|
||||
std::string centr(central.createHeader());
|
||||
_out.write(centr.c_str(), static_cast<std::streamsize>(centr.size()));
|
||||
_out.flush();
|
||||
_dirs.insert(std::make_pair(0, central));
|
||||
return ZipArchive(_files, _infos, _dirs);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Zip
|
||||
//
|
||||
// Compress.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Zip/src/Compress.cpp#8 $
|
||||
//
|
||||
// Library: Zip
|
||||
// Package: Zip
|
||||
// Module: Compress
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// 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
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// 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
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// 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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Zip/Compress.h"
|
||||
#include "Poco/Zip/ZipLocalFileHeader.h"
|
||||
#include "Poco/Zip/ZipStream.h"
|
||||
#include "Poco/Zip/ZipArchiveInfo.h"
|
||||
#include "Poco/Zip/ZipDataInfo.h"
|
||||
#include "Poco/Zip/ZipException.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/File.h"
|
||||
#include <fstream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Zip {
|
||||
|
||||
|
||||
Compress::Compress(std::ostream& out, bool seekableOut):
|
||||
_out(out),
|
||||
_seekableOut(seekableOut),
|
||||
_files(),
|
||||
_infos(),
|
||||
_dirs(),
|
||||
_offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Compress::~Compress()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
if (_files.size() >= 65535)
|
||||
throw ZipException("Maximum number of entries for a ZIP file reached: 65535");
|
||||
if (!in.good())
|
||||
throw ZipException("Invalid input stream");
|
||||
|
||||
std::streamoff localHeaderOffset = _offset;
|
||||
ZipLocalFileHeader hdr(fileName, lastModifiedAt, cm, cl);
|
||||
hdr.setStartPos(localHeaderOffset);
|
||||
|
||||
ZipOutputStream zipOut(_out, hdr, _seekableOut);
|
||||
Poco::StreamCopier::copyStream(in, zipOut);
|
||||
zipOut.close();
|
||||
hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known
|
||||
_offset = hdr.getEndPos();
|
||||
if (hdr.searchCRCAndSizesAfterData())
|
||||
_offset += ZipDataInfo::getFullHeaderSize();
|
||||
_files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr));
|
||||
poco_assert (_out);
|
||||
ZipFileInfo nfo(hdr);
|
||||
nfo.setOffset(localHeaderOffset);
|
||||
_infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo));
|
||||
EDone.notify(this, hdr);
|
||||
}
|
||||
|
||||
|
||||
void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const Poco::Path& fileName)
|
||||
{
|
||||
std::string fn = ZipUtil::validZipEntryFileName(fileName);
|
||||
//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);
|
||||
|
||||
if (_files.size() >= 65535)
|
||||
throw ZipException("Maximum number of entries for a ZIP file reached: 65535");
|
||||
if (!in.good())
|
||||
throw ZipException("Invalid input stream");
|
||||
|
||||
std::streamoff localHeaderOffset = _offset;
|
||||
ZipLocalFileHeader hdr(h);
|
||||
hdr.setFileName(fn, h.isDirectory());
|
||||
hdr.setStartPos(localHeaderOffset);
|
||||
//bypass zipoutputstream
|
||||
//write the header directly
|
||||
std::string header = hdr.createHeader();
|
||||
_out.write(header.c_str(), static_cast<std::streamsize>(header.size()));
|
||||
// now fwd the payload to _out in chunks of size CHUNKSIZE
|
||||
Poco::UInt32 totalSize = hdr.getCompressedSize();
|
||||
if (totalSize > 0)
|
||||
{
|
||||
Poco::Buffer<char> buffer(COMPRESS_CHUNK_SIZE);
|
||||
Poco::UInt32 remaining = totalSize;
|
||||
while(remaining > 0)
|
||||
{
|
||||
if (remaining > COMPRESS_CHUNK_SIZE)
|
||||
{
|
||||
in.read(buffer.begin(), COMPRESS_CHUNK_SIZE);
|
||||
std::streamsize n = in.gcount();
|
||||
poco_assert_dbg (n == COMPRESS_CHUNK_SIZE);
|
||||
_out.write(buffer.begin(), n);
|
||||
remaining -= COMPRESS_CHUNK_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
in.read(buffer.begin(), remaining);
|
||||
std::streamsize n = in.gcount();
|
||||
poco_assert_dbg (n == remaining);
|
||||
_out.write(buffer.begin(), n);
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//write optional block afterwards
|
||||
if (hdr.searchCRCAndSizesAfterData())
|
||||
{
|
||||
ZipDataInfo info(in, false);
|
||||
_out.write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize()));
|
||||
}
|
||||
hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known
|
||||
_offset = hdr.getEndPos();
|
||||
if (hdr.searchCRCAndSizesAfterData())
|
||||
_offset += ZipDataInfo::getFullHeaderSize();
|
||||
_files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr));
|
||||
poco_assert (_out);
|
||||
ZipFileInfo nfo(hdr);
|
||||
nfo.setOffset(localHeaderOffset);
|
||||
_infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo));
|
||||
EDone.notify(this, hdr);
|
||||
}
|
||||
|
||||
|
||||
void Compress::addFile(std::istream& in, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl)
|
||||
{
|
||||
if (!fileName.isFile())
|
||||
throw ZipException("Not a file: "+ fileName.toString());
|
||||
|
||||
if (fileName.depth() > 1)
|
||||
{
|
||||
addDirectory(fileName.parent(), lastModifiedAt);
|
||||
}
|
||||
addEntry(in, lastModifiedAt, fileName, cm, cl);
|
||||
}
|
||||
|
||||
|
||||
void Compress::addFile(const Poco::Path& file, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl)
|
||||
{
|
||||
Poco::File aFile(file);
|
||||
Poco::File::FileSize size = aFile.getSize();
|
||||
if (size < 16)
|
||||
{
|
||||
cm = ZipCommon::CM_STORE;
|
||||
cl = ZipCommon::CL_NORMAL;
|
||||
}
|
||||
std::ifstream in(file.toString().c_str(), std::ios::binary);
|
||||
if (!in.good())
|
||||
throw ZipException("Invalid input stream for " + aFile.path());
|
||||
if (fileName.depth() > 1)
|
||||
{
|
||||
Poco::File aParent(file.parent());
|
||||
addDirectory(fileName.parent(), aParent.getLastModified());
|
||||
}
|
||||
|
||||
addFile(in, aFile.getLastModified(), fileName, cm, cl);
|
||||
}
|
||||
|
||||
|
||||
void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& lastModifiedAt)
|
||||
{
|
||||
if (!entryName.isDirectory())
|
||||
throw ZipException("Not a directory: "+ entryName.toString());
|
||||
|
||||
std::string fileStr = entryName.toString(Poco::Path::PATH_UNIX);
|
||||
if (_files.find(fileStr) != _files.end())
|
||||
return; // ignore duplicate add
|
||||
if (_files.size() >= 65535)
|
||||
throw ZipException("Maximum number of entries for a ZIP file reached: 65535");
|
||||
if (fileStr == "/")
|
||||
throw ZipException("Illegal entry name /");
|
||||
if (fileStr.empty())
|
||||
throw ZipException("Illegal empty entry name");
|
||||
if (fileStr.find(ZipCommon::ILLEGAL_PATH) != std::string::npos)
|
||||
throw ZipException("Illegal entry name " + fileStr + " containing " + ZipCommon::ILLEGAL_PATH);
|
||||
|
||||
if (entryName.depth() > 1)
|
||||
{
|
||||
addDirectory(entryName.parent(), lastModifiedAt);
|
||||
}
|
||||
|
||||
std::streamoff localHeaderOffset = _offset;
|
||||
ZipCommon::CompressionMethod cm = ZipCommon::CM_STORE;
|
||||
ZipCommon::CompressionLevel cl = ZipCommon::CL_NORMAL;
|
||||
ZipLocalFileHeader hdr(entryName, lastModifiedAt, cm, cl);
|
||||
hdr.setStartPos(localHeaderOffset);
|
||||
ZipOutputStream zipOut(_out, hdr, _seekableOut);
|
||||
zipOut.close();
|
||||
hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known
|
||||
_offset = hdr.getEndPos();
|
||||
if (hdr.searchCRCAndSizesAfterData())
|
||||
_offset += ZipDataInfo::getFullHeaderSize();
|
||||
_files.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), hdr));
|
||||
poco_assert (_out);
|
||||
ZipFileInfo nfo(hdr);
|
||||
nfo.setOffset(localHeaderOffset);
|
||||
_infos.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), nfo));
|
||||
EDone.notify(this, hdr);
|
||||
}
|
||||
|
||||
|
||||
void Compress::addRecursive(const Poco::Path& entry, ZipCommon::CompressionLevel cl, bool excludeRoot, const Poco::Path& name)
|
||||
{
|
||||
Poco::File aFile(entry);
|
||||
if (!aFile.isDirectory())
|
||||
throw ZipException("Not a directory: "+ entry.toString());
|
||||
Poco::Path aName(name);
|
||||
aName.makeDirectory();
|
||||
if (!excludeRoot)
|
||||
{
|
||||
if (aName.depth() == 0)
|
||||
{
|
||||
Poco::Path tmp(entry);
|
||||
tmp.makeAbsolute(); // eliminate ../
|
||||
aName = Poco::Path(tmp[tmp.depth()-1]);
|
||||
aName.makeDirectory();
|
||||
}
|
||||
|
||||
addDirectory(aName, aFile.getLastModified());
|
||||
}
|
||||
|
||||
// iterate over children
|
||||
std::vector<std::string> children;
|
||||
aFile.list(children);
|
||||
std::vector<std::string>::const_iterator it = children.begin();
|
||||
std::vector<std::string>::const_iterator itEnd = children.end();
|
||||
for (; it != itEnd; ++it)
|
||||
{
|
||||
Poco::Path realFile(entry, *it);
|
||||
Poco::Path renamedFile(aName, *it);
|
||||
Poco::File aFile(realFile);
|
||||
if (aFile.isDirectory())
|
||||
{
|
||||
realFile.makeDirectory();
|
||||
renamedFile.makeDirectory();
|
||||
addRecursive(realFile, cl, false, renamedFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
realFile.makeFile();
|
||||
renamedFile.makeFile();
|
||||
addFile(realFile, renamedFile, ZipCommon::CM_DEFLATE, cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZipArchive Compress::close()
|
||||
{
|
||||
if (!_dirs.empty())
|
||||
return ZipArchive(_files, _infos, _dirs);
|
||||
|
||||
poco_assert (_infos.size() == _files.size());
|
||||
poco_assert (_files.size() < 65536);
|
||||
Poco::UInt32 centralDirStart = _offset;
|
||||
Poco::UInt32 centralDirSize = 0;
|
||||
// write all infos
|
||||
ZipArchive::FileInfos::const_iterator it = _infos.begin();
|
||||
ZipArchive::FileInfos::const_iterator itEnd = _infos.end();
|
||||
for (; it != itEnd; ++it)
|
||||
{
|
||||
const ZipFileInfo& nfo = it->second;
|
||||
std::string info(nfo.createHeader());
|
||||
_out.write(info.c_str(), static_cast<std::streamsize>(info.size()));
|
||||
Poco::UInt32 entrySize = static_cast<Poco::UInt32>(info.size());
|
||||
centralDirSize += entrySize;
|
||||
_offset += entrySize;
|
||||
}
|
||||
poco_assert (_out);
|
||||
|
||||
|
||||
Poco::UInt16 numEntries = static_cast<Poco::UInt16>(_infos.size());
|
||||
ZipArchiveInfo central;
|
||||
central.setCentralDirectorySize(centralDirSize);
|
||||
central.setNumberOfEntries(numEntries);
|
||||
central.setTotalNumberOfEntries(numEntries);
|
||||
central.setHeaderOffset(centralDirStart);
|
||||
std::string centr(central.createHeader());
|
||||
_out.write(centr.c_str(), static_cast<std::streamsize>(centr.size()));
|
||||
_out.flush();
|
||||
_dirs.insert(std::make_pair(0, central));
|
||||
return ZipArchive(_files, _infos, _dirs);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Zip
|
||||
|
@ -1,143 +1,159 @@
|
||||
//
|
||||
// ZipFileInfo.cpp
|
||||
//
|
||||
// $Id: //poco/1.3/Zip/src/ZipFileInfo.cpp#4 $
|
||||
//
|
||||
// Library: Zip
|
||||
// Package: Zip
|
||||
// Module: ZipFileInfo
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// 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
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// 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
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// 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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Zip/ZipFileInfo.h"
|
||||
#include "Poco/Zip/ZipLocalFileHeader.h"
|
||||
#include "Poco/Buffer.h"
|
||||
#include <istream>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Zip {
|
||||
|
||||
|
||||
const char ZipFileInfo::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x01', '\x02'};
|
||||
|
||||
|
||||
ZipFileInfo::ZipFileInfo(const ZipLocalFileHeader& header):
|
||||
_rawInfo(),
|
||||
_crc32(0),
|
||||
_compressedSize(0),
|
||||
_uncompressedSize(0),
|
||||
_fileName(),
|
||||
_lastModifiedAt(),
|
||||
_extraField()
|
||||
{
|
||||
std::memset(_rawInfo, 0, FULLHEADER_SIZE);
|
||||
std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE);
|
||||
setCompressedSize(header.getCompressedSize());
|
||||
setUncompressedSize(header.getUncompressedSize());
|
||||
setCRC(header.getCRC());
|
||||
setCompressionMethod(header.getCompressionMethod());
|
||||
setCompressionLevel(header.getCompressionLevel());
|
||||
setRequiredVersion(header.getMajorVersionNumber(), header.getMinorVersionNumber());
|
||||
setHostSystem(header.getHostSystem());
|
||||
setLastModifiedAt(header.lastModifiedAt());
|
||||
setEncryption(false);
|
||||
setFileName(header.getFileName());
|
||||
}
|
||||
|
||||
|
||||
ZipFileInfo::ZipFileInfo(std::istream& in, bool assumeHeaderRead):
|
||||
_rawInfo(),
|
||||
_crc32(0),
|
||||
_compressedSize(0),
|
||||
_uncompressedSize(0),
|
||||
_fileName(),
|
||||
_lastModifiedAt(),
|
||||
_extraField()
|
||||
{
|
||||
// sanity check
|
||||
poco_assert_dbg (RELATIVEOFFSETLOCALHEADER_POS + RELATIVEOFFSETLOCALHEADER_SIZE == FULLHEADER_SIZE);
|
||||
parse(in, assumeHeaderRead);
|
||||
}
|
||||
|
||||
|
||||
ZipFileInfo::~ZipFileInfo()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ZipFileInfo::parse(std::istream& inp, bool assumeHeaderRead)
|
||||
{
|
||||
if (!assumeHeaderRead)
|
||||
{
|
||||
inp.read(_rawInfo, ZipCommon::HEADER_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE);
|
||||
}
|
||||
poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0);
|
||||
// read the rest of the header
|
||||
inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE);
|
||||
_crc32 = getCRCFromHeader();
|
||||
_compressedSize = getCompressedSizeFromHeader();
|
||||
_uncompressedSize = getUncompressedSizeFromHeader();
|
||||
parseDateTime();
|
||||
Poco::UInt16 len = getFileNameLength();
|
||||
Poco::Buffer<char> buf(len);
|
||||
inp.read(buf.begin(), len);
|
||||
_fileName = std::string(buf.begin(), len);
|
||||
if (hasExtraField())
|
||||
{
|
||||
len = getExtraFieldLength();
|
||||
Poco::Buffer<char> xtra(len);
|
||||
inp.read(xtra.begin(), len);
|
||||
_extraField = std::string(xtra.begin(), len);
|
||||
}
|
||||
len = getFileCommentLength();
|
||||
if (len > 0)
|
||||
{
|
||||
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);
|
||||
result.append(_extraField);
|
||||
result.append(_fileComment);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Zip
|
||||
//
|
||||
// ZipFileInfo.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Zip/src/ZipFileInfo.cpp#9 $
|
||||
//
|
||||
// Library: Zip
|
||||
// Package: Zip
|
||||
// Module: ZipFileInfo
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// 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
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// 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
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// 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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Zip/ZipFileInfo.h"
|
||||
#include "Poco/Zip/ZipLocalFileHeader.h"
|
||||
#include "Poco/Buffer.h"
|
||||
#include <istream>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Zip {
|
||||
|
||||
|
||||
const char ZipFileInfo::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x01', '\x02'};
|
||||
|
||||
|
||||
ZipFileInfo::ZipFileInfo(const ZipLocalFileHeader& header):
|
||||
_rawInfo(),
|
||||
_crc32(0),
|
||||
_compressedSize(0),
|
||||
_uncompressedSize(0),
|
||||
_fileName(),
|
||||
_lastModifiedAt(),
|
||||
_extraField()
|
||||
{
|
||||
std::memset(_rawInfo, 0, FULLHEADER_SIZE);
|
||||
std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE);
|
||||
setCompressedSize(header.getCompressedSize());
|
||||
setUncompressedSize(header.getUncompressedSize());
|
||||
setCRC(header.getCRC());
|
||||
setCompressionMethod(header.getCompressionMethod());
|
||||
setCompressionLevel(header.getCompressionLevel());
|
||||
setRequiredVersion(header.getMajorVersionNumber(), header.getMinorVersionNumber());
|
||||
setHostSystem(header.getHostSystem());
|
||||
setLastModifiedAt(header.lastModifiedAt());
|
||||
setEncryption(false);
|
||||
setFileName(header.getFileName());
|
||||
|
||||
if (getHostSystem() == ZipCommon::HS_UNIX)
|
||||
setUnixAttributes();
|
||||
}
|
||||
|
||||
|
||||
ZipFileInfo::ZipFileInfo(std::istream& in, bool assumeHeaderRead):
|
||||
_rawInfo(),
|
||||
_crc32(0),
|
||||
_compressedSize(0),
|
||||
_uncompressedSize(0),
|
||||
_fileName(),
|
||||
_lastModifiedAt(),
|
||||
_extraField()
|
||||
{
|
||||
// sanity check
|
||||
poco_assert_dbg (RELATIVEOFFSETLOCALHEADER_POS + RELATIVEOFFSETLOCALHEADER_SIZE == FULLHEADER_SIZE);
|
||||
parse(in, assumeHeaderRead);
|
||||
}
|
||||
|
||||
|
||||
ZipFileInfo::~ZipFileInfo()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ZipFileInfo::parse(std::istream& inp, bool assumeHeaderRead)
|
||||
{
|
||||
if (!assumeHeaderRead)
|
||||
{
|
||||
inp.read(_rawInfo, ZipCommon::HEADER_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE);
|
||||
}
|
||||
poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0);
|
||||
// read the rest of the header
|
||||
inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE);
|
||||
_crc32 = getCRCFromHeader();
|
||||
_compressedSize = getCompressedSizeFromHeader();
|
||||
_uncompressedSize = getUncompressedSizeFromHeader();
|
||||
parseDateTime();
|
||||
Poco::UInt16 len = getFileNameLength();
|
||||
Poco::Buffer<char> buf(len);
|
||||
inp.read(buf.begin(), len);
|
||||
_fileName = std::string(buf.begin(), len);
|
||||
if (hasExtraField())
|
||||
{
|
||||
len = getExtraFieldLength();
|
||||
Poco::Buffer<char> xtra(len);
|
||||
inp.read(xtra.begin(), len);
|
||||
_extraField = std::string(xtra.begin(), len);
|
||||
}
|
||||
len = getFileCommentLength();
|
||||
if (len > 0)
|
||||
{
|
||||
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);
|
||||
result.append(_extraField);
|
||||
result.append(_fileComment);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@ -1,319 +1,319 @@
|
||||
//
|
||||
// ZipStream.cpp
|
||||
//
|
||||
// $Id: //poco/1.3/Zip/src/ZipStream.cpp#4 $
|
||||
//
|
||||
// Library: Zip
|
||||
// Package: Zip
|
||||
// Module: ZipStream
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// 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
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// 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
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// 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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Zip/ZipStream.h"
|
||||
#include "Poco/zlib.h"
|
||||
#include "Poco/Zip/ZipArchive.h"
|
||||
#include "Poco/Zip/AutoDetectStream.h"
|
||||
#include "Poco/Zip/PartialStream.h"
|
||||
#include "Poco/Zip/ZipDataInfo.h"
|
||||
#include "Poco/Zip/ZipException.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/InflatingStream.h"
|
||||
#include "Poco/DeflatingStream.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Zip {
|
||||
|
||||
|
||||
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 = _ptrOHelper;
|
||||
}
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZipStreamBuf::~ZipStreamBuf()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
int ZipStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
|
||||
{
|
||||
if (!_ptrOBuf) return 0; // directory entry
|
||||
if (length == 0)
|
||||
return 0;
|
||||
_bytesWritten += length;
|
||||
_ptrOBuf->write(buffer, length);
|
||||
_crc32.update(buffer, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
void ZipStreamBuf::close()
|
||||
{
|
||||
if (_ptrOBuf && _pHeader)
|
||||
{
|
||||
_ptrOBuf->flush();
|
||||
DeflatingOutputStream* pDO = dynamic_cast<DeflatingOutputStream*>(_ptrOBuf.get());
|
||||
if (pDO)
|
||||
pDO->close();
|
||||
if (_ptrOHelper)
|
||||
{
|
||||
_ptrOHelper->flush();
|
||||
_ptrOHelper->close();
|
||||
}
|
||||
_ptrOBuf = 0;
|
||||
poco_assert (*_pOstr);
|
||||
// write an extra datablock if required
|
||||
// or fix the crc entries
|
||||
if (_pHeader->searchCRCAndSizesAfterData())
|
||||
{
|
||||
ZipDataInfo info;
|
||||
info.setCRC32(_crc32.checksum());
|
||||
info.setUncompressedSize(_bytesWritten);
|
||||
info.setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten()));
|
||||
_pOstr->write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize()));
|
||||
}
|
||||
else
|
||||
{
|
||||
poco_check_ptr (_pHeader);
|
||||
_pHeader->setCRC(_crc32.checksum());
|
||||
_pHeader->setUncompressedSize(_bytesWritten);
|
||||
_pHeader->setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten()));
|
||||
_pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg);
|
||||
poco_assert (*_pOstr);
|
||||
std::string header = _pHeader->createHeader();
|
||||
_pOstr->write(header.c_str(), static_cast<std::streamsize>(header.size()));
|
||||
_pOstr->seekp(0, std::ios_base::end);
|
||||
poco_assert (*_pOstr);
|
||||
}
|
||||
_pHeader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ZipStreamBuf::crcValid() const
|
||||
{
|
||||
if (!_ptrBuf) return true; // directory entry
|
||||
return _crc32.checksum() == _expectedCrc32;
|
||||
}
|
||||
|
||||
|
||||
ZipIOS::ZipIOS(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): _buf(istr, fileEntry, reposition)
|
||||
{
|
||||
poco_ios_init(&_buf);
|
||||
}
|
||||
|
||||
|
||||
ZipIOS::ZipIOS(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition): _buf(ostr, fileEntry, reposition)
|
||||
{
|
||||
poco_ios_init(&_buf);
|
||||
}
|
||||
|
||||
|
||||
ZipIOS::~ZipIOS()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ZipStreamBuf* ZipIOS::rdbuf()
|
||||
{
|
||||
return &_buf;
|
||||
}
|
||||
|
||||
|
||||
ZipInputStream::ZipInputStream(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): ZipIOS(istr, fileEntry, reposition), std::istream(&_buf)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ZipInputStream::~ZipInputStream()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool ZipInputStream::crcValid() const
|
||||
{
|
||||
return _buf.crcValid();
|
||||
}
|
||||
|
||||
|
||||
ZipOutputStream::ZipOutputStream(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool seekableOutput): ZipIOS(ostr, fileEntry, seekableOutput), std::ostream(&_buf)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ZipOutputStream::~ZipOutputStream()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ZipOutputStream::close()
|
||||
{
|
||||
flush();
|
||||
_buf.close();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Zip
|
||||
//
|
||||
// ZipStream.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Zip/src/ZipStream.cpp#14 $
|
||||
//
|
||||
// Library: Zip
|
||||
// Package: Zip
|
||||
// Module: ZipStream
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// 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
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// 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
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// 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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Zip/ZipStream.h"
|
||||
#include "Poco/zlib.h"
|
||||
#include "Poco/Zip/ZipArchive.h"
|
||||
#include "Poco/Zip/AutoDetectStream.h"
|
||||
#include "Poco/Zip/PartialStream.h"
|
||||
#include "Poco/Zip/ZipDataInfo.h"
|
||||
#include "Poco/Zip/ZipException.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/InflatingStream.h"
|
||||
#include "Poco/DeflatingStream.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Zip {
|
||||
|
||||
|
||||
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 = _ptrOHelper;
|
||||
}
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZipStreamBuf::~ZipStreamBuf()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
int ZipStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
|
||||
{
|
||||
if (!_ptrOBuf) return 0; // directory entry
|
||||
if (length == 0)
|
||||
return 0;
|
||||
_bytesWritten += length;
|
||||
_ptrOBuf->write(buffer, length);
|
||||
_crc32.update(buffer, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
void ZipStreamBuf::close()
|
||||
{
|
||||
if (_ptrOBuf && _pHeader)
|
||||
{
|
||||
_ptrOBuf->flush();
|
||||
DeflatingOutputStream* pDO = dynamic_cast<DeflatingOutputStream*>(_ptrOBuf.get());
|
||||
if (pDO)
|
||||
pDO->close();
|
||||
if (_ptrOHelper)
|
||||
{
|
||||
_ptrOHelper->flush();
|
||||
_ptrOHelper->close();
|
||||
}
|
||||
_ptrOBuf = 0;
|
||||
poco_assert (*_pOstr);
|
||||
// write an extra datablock if required
|
||||
// or fix the crc entries
|
||||
if (_pHeader->searchCRCAndSizesAfterData())
|
||||
{
|
||||
ZipDataInfo info;
|
||||
info.setCRC32(_crc32.checksum());
|
||||
info.setUncompressedSize(_bytesWritten);
|
||||
info.setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten()));
|
||||
_pOstr->write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize()));
|
||||
}
|
||||
else
|
||||
{
|
||||
poco_check_ptr (_pHeader);
|
||||
_pHeader->setCRC(_crc32.checksum());
|
||||
_pHeader->setUncompressedSize(_bytesWritten);
|
||||
_pHeader->setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten()));
|
||||
_pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg);
|
||||
poco_assert (*_pOstr);
|
||||
std::string header = _pHeader->createHeader();
|
||||
_pOstr->write(header.c_str(), static_cast<std::streamsize>(header.size()));
|
||||
_pOstr->seekp(0, std::ios_base::end);
|
||||
poco_assert (*_pOstr);
|
||||
}
|
||||
_pHeader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ZipStreamBuf::crcValid() const
|
||||
{
|
||||
if (!_ptrBuf) return true; // directory entry
|
||||
return _crc32.checksum() == _expectedCrc32;
|
||||
}
|
||||
|
||||
|
||||
ZipIOS::ZipIOS(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): _buf(istr, fileEntry, reposition)
|
||||
{
|
||||
poco_ios_init(&_buf);
|
||||
}
|
||||
|
||||
|
||||
ZipIOS::ZipIOS(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition): _buf(ostr, fileEntry, reposition)
|
||||
{
|
||||
poco_ios_init(&_buf);
|
||||
}
|
||||
|
||||
|
||||
ZipIOS::~ZipIOS()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ZipStreamBuf* ZipIOS::rdbuf()
|
||||
{
|
||||
return &_buf;
|
||||
}
|
||||
|
||||
|
||||
ZipInputStream::ZipInputStream(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): ZipIOS(istr, fileEntry, reposition), std::istream(&_buf)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ZipInputStream::~ZipInputStream()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool ZipInputStream::crcValid() const
|
||||
{
|
||||
return _buf.crcValid();
|
||||
}
|
||||
|
||||
|
||||
ZipOutputStream::ZipOutputStream(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool seekableOutput): ZipIOS(ostr, fileEntry, seekableOutput), std::ostream(&_buf)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ZipOutputStream::~ZipOutputStream()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ZipOutputStream::close()
|
||||
{
|
||||
flush();
|
||||
_buf.close();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Zip
|
||||
|
Loading…
x
Reference in New Issue
Block a user