2008-06-24 00:35 UTC+0200 Viktor Szakats (harbour.01 syenar hu)

* contrib/hbziparch/_features.h
   * contrib/hbziparch/_platform.h
   * contrib/hbziparch/Aes.cpp
   * contrib/hbziparch/Aes.h
   * contrib/hbziparch/BaseLibCompressor.cpp
   * contrib/hbziparch/BaseLibCompressor.h
   * contrib/hbziparch/BytesWriter.h
   * contrib/hbziparch/Bzip2Compressor.cpp
   * contrib/hbziparch/Bzip2Compressor.h
   * contrib/hbziparch/DeflateCompressor.cpp
   * contrib/hbziparch/DeflateCompressor.h
   * contrib/hbziparch/DirEnumerator.cpp
   * contrib/hbziparch/DirEnumerator.h
   * contrib/hbziparch/FileFilter.cpp
   * contrib/hbziparch/FileFilter.h
   * contrib/hbziparch/FileInfo.h
   * contrib/hbziparch/Hmac.cpp
   * contrib/hbziparch/Hmac.h
   * contrib/hbziparch/RandomPool.cpp
   * contrib/hbziparch/RandomPool.h
   * contrib/hbziparch/Sha1.cpp
   * contrib/hbziparch/Sha1.h
   * contrib/hbziparch/std_mfc.h
   * contrib/hbziparch/std_stl.h
   * contrib/hbziparch/Wildcard.cpp
   * contrib/hbziparch/Wildcard.h
   * contrib/hbziparch/ZipAbstractFile.h
   * contrib/hbziparch/ZipAesCryptograph.cpp
   * contrib/hbziparch/ZipAesCryptograph.h
   * contrib/hbziparch/ZipArchive.cpp
   * contrib/hbziparch/ZipArchive.h
   * contrib/hbziparch/ZipAutoBuffer.cpp
   * contrib/hbziparch/ZipAutoBuffer.h
   * contrib/hbziparch/ZipBaseException.h
   * contrib/hbziparch/ZipCallback.h
   * contrib/hbziparch/ZipCallbackProvider.h
   * contrib/hbziparch/ZipCentralDir.cpp
   * contrib/hbziparch/ZipCentralDir.h
   * contrib/hbziparch/ZipCollections.h
   * contrib/hbziparch/ZipCollections_mfc.h
   * contrib/hbziparch/ZipCollections_stl.h
   * contrib/hbziparch/ZipCompatibility.cpp
   * contrib/hbziparch/ZipCompatibility.h
   * contrib/hbziparch/ZipCompressor.cpp
   * contrib/hbziparch/ZipCompressor.h
   * contrib/hbziparch/ZipCrc32Cryptograph.cpp
   * contrib/hbziparch/ZipCrc32Cryptograph.h
   * contrib/hbziparch/ZipCryptograph.cpp
   * contrib/hbziparch/ZipCryptograph.h
   * contrib/hbziparch/ZipException.cpp
   * contrib/hbziparch/ZipException.h
   * contrib/hbziparch/ZipExtraData.cpp
   * contrib/hbziparch/ZipExtraData.h
   * contrib/hbziparch/ZipExtraField.cpp
   * contrib/hbziparch/ZipExtraField.h
   * contrib/hbziparch/ZipFile.h
   * contrib/hbziparch/ZipFile_mfc.cpp
   * contrib/hbziparch/ZipFile_mfc.h
   * contrib/hbziparch/ZipFile_stl.cpp
   * contrib/hbziparch/ZipFile_stl.h
   * contrib/hbziparch/ZipFileHeader.cpp
   * contrib/hbziparch/ZipFileHeader.h
   * contrib/hbziparch/ZipFileMapping.h
   * contrib/hbziparch/ZipFileMapping_lnx.h
   * contrib/hbziparch/ZipFileMapping_win.h
   * contrib/hbziparch/ZipMemFile.cpp
   * contrib/hbziparch/ZipMemFile.h
   * contrib/hbziparch/ZipMutex.h
   * contrib/hbziparch/ZipMutex_lnx.h
   * contrib/hbziparch/ZipMutex_win.h
   * contrib/hbziparch/ZipPathComponent.h
   * contrib/hbziparch/ZipPlatform.h
   * contrib/hbziparch/ZipPlatformComm.cpp
   * contrib/hbziparch/ZipStorage.cpp
   * contrib/hbziparch/ZipStorage.h
   * contrib/hbziparch/ZipString.h
   * contrib/hbziparch/ZipString_mfc.h
   * contrib/hbziparch/ZipString_stl.h
   * contrib/hbziparch/ZipStringStoreSettings.h
     + ZipArchive lib update finished.
     ; Pass 2/2
     ; Please test.
This commit is contained in:
Viktor Szakats
2008-06-23 22:41:33 +00:00
parent e0a744149d
commit 40338a87d6
80 changed files with 20393 additions and 0 deletions

View File

@@ -8,6 +8,90 @@
2008-12-31 13:59 UTC+0100 Foo Bar <foo.bar@foobar.org>
*/
2008-06-24 00:35 UTC+0200 Viktor Szakats (harbour.01 syenar hu)
* contrib/hbziparch/_features.h
* contrib/hbziparch/_platform.h
* contrib/hbziparch/Aes.cpp
* contrib/hbziparch/Aes.h
* contrib/hbziparch/BaseLibCompressor.cpp
* contrib/hbziparch/BaseLibCompressor.h
* contrib/hbziparch/BytesWriter.h
* contrib/hbziparch/Bzip2Compressor.cpp
* contrib/hbziparch/Bzip2Compressor.h
* contrib/hbziparch/DeflateCompressor.cpp
* contrib/hbziparch/DeflateCompressor.h
* contrib/hbziparch/DirEnumerator.cpp
* contrib/hbziparch/DirEnumerator.h
* contrib/hbziparch/FileFilter.cpp
* contrib/hbziparch/FileFilter.h
* contrib/hbziparch/FileInfo.h
* contrib/hbziparch/Hmac.cpp
* contrib/hbziparch/Hmac.h
* contrib/hbziparch/RandomPool.cpp
* contrib/hbziparch/RandomPool.h
* contrib/hbziparch/Sha1.cpp
* contrib/hbziparch/Sha1.h
* contrib/hbziparch/std_mfc.h
* contrib/hbziparch/std_stl.h
* contrib/hbziparch/Wildcard.cpp
* contrib/hbziparch/Wildcard.h
* contrib/hbziparch/ZipAbstractFile.h
* contrib/hbziparch/ZipAesCryptograph.cpp
* contrib/hbziparch/ZipAesCryptograph.h
* contrib/hbziparch/ZipArchive.cpp
* contrib/hbziparch/ZipArchive.h
* contrib/hbziparch/ZipAutoBuffer.cpp
* contrib/hbziparch/ZipAutoBuffer.h
* contrib/hbziparch/ZipBaseException.h
* contrib/hbziparch/ZipCallback.h
* contrib/hbziparch/ZipCallbackProvider.h
* contrib/hbziparch/ZipCentralDir.cpp
* contrib/hbziparch/ZipCentralDir.h
* contrib/hbziparch/ZipCollections.h
* contrib/hbziparch/ZipCollections_mfc.h
* contrib/hbziparch/ZipCollections_stl.h
* contrib/hbziparch/ZipCompatibility.cpp
* contrib/hbziparch/ZipCompatibility.h
* contrib/hbziparch/ZipCompressor.cpp
* contrib/hbziparch/ZipCompressor.h
* contrib/hbziparch/ZipCrc32Cryptograph.cpp
* contrib/hbziparch/ZipCrc32Cryptograph.h
* contrib/hbziparch/ZipCryptograph.cpp
* contrib/hbziparch/ZipCryptograph.h
* contrib/hbziparch/ZipException.cpp
* contrib/hbziparch/ZipException.h
* contrib/hbziparch/ZipExtraData.cpp
* contrib/hbziparch/ZipExtraData.h
* contrib/hbziparch/ZipExtraField.cpp
* contrib/hbziparch/ZipExtraField.h
* contrib/hbziparch/ZipFile.h
* contrib/hbziparch/ZipFile_mfc.cpp
* contrib/hbziparch/ZipFile_mfc.h
* contrib/hbziparch/ZipFile_stl.cpp
* contrib/hbziparch/ZipFile_stl.h
* contrib/hbziparch/ZipFileHeader.cpp
* contrib/hbziparch/ZipFileHeader.h
* contrib/hbziparch/ZipFileMapping.h
* contrib/hbziparch/ZipFileMapping_lnx.h
* contrib/hbziparch/ZipFileMapping_win.h
* contrib/hbziparch/ZipMemFile.cpp
* contrib/hbziparch/ZipMemFile.h
* contrib/hbziparch/ZipMutex.h
* contrib/hbziparch/ZipMutex_lnx.h
* contrib/hbziparch/ZipMutex_win.h
* contrib/hbziparch/ZipPathComponent.h
* contrib/hbziparch/ZipPlatform.h
* contrib/hbziparch/ZipPlatformComm.cpp
* contrib/hbziparch/ZipStorage.cpp
* contrib/hbziparch/ZipStorage.h
* contrib/hbziparch/ZipString.h
* contrib/hbziparch/ZipString_mfc.h
* contrib/hbziparch/ZipString_stl.h
* contrib/hbziparch/ZipStringStoreSettings.h
+ ZipArchive lib update finished.
; Pass 2/2
; Please test.
2008-06-24 00:33 UTC+0200 Viktor Szakats (harbour.01 syenar hu)
+ contrib/hbziparch/readme.txt
+ contrib/hbziparch/zlib

View File

@@ -0,0 +1,16 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "_features.h"

View File

@@ -0,0 +1,14 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,44 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BaseLibCompressor.h"
namespace ZipArchiveLib
{
void CBaseLibCompressor::SetOpaque(void** opaque, const COptions* pOptions)
{
*opaque = pOptions->m_bDetectLibMemoryLeaks ? &m_list : 0;
}
void CBaseLibCompressor::EmptyPtrList()
{
if (m_list.GetCount())
{
// if some memory hasn't been freed due to an error in zlib, so free it now
CZipPtrListIter iter = m_list.GetHeadPosition();
while (m_list.IteratorValid(iter))
delete[] (char*) m_list.GetNext(iter);
}
m_list.RemoveAll();
}
} // namespace

View File

@@ -0,0 +1,198 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file BaseLibCompressor.h
* Includes the ZipArchiveLib::CBaseLibCompressor class.
*
*/
#if !defined(ZIPARCHIVE_BASELIBCOMPRESSOR_DOT_H)
#define ZIPARCHIVE_BASELIBCOMPRESSOR_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "ZipExport.h"
#include "ZipCompressor.h"
#include "ZipCollections.h"
#include "ZipException.h"
namespace ZipArchiveLib
{
/**
A base class for compressors that use external libraries, such as zlib or bzip2.
*/
class ZIP_API CBaseLibCompressor : public CZipCompressor
{
public:
/**
Represents options of compressors that use external libraries.
\see
<a href="kb">0610231446|options</a>
\see
CZipArchive::SetCompressionOptions
*/
struct ZIP_API COptions : CZipCompressor::COptions
{
COptions()
{
m_bDetectLibMemoryLeaks = true;
}
/**
\c true, if the ZipArchive Library should detect memory leaks in an external library; \c false otherwise.
Recommended to be set to \c true.
*/
bool m_bDetectLibMemoryLeaks;
};
/**
Initializes a new instance of the CBaseLibCompressor class.
\param pStorage
The current storage object.
*/
CBaseLibCompressor(CZipStorage* pStorage)
:CZipCompressor(pStorage)
{
}
void InitDecompression(CZipFileHeader* pFile, CZipCryptograph* pCryptograph)
{
CZipCompressor::InitDecompression(pFile, pCryptograph);
m_bDecompressionDone = false;
}
~CBaseLibCompressor()
{
EmptyPtrList();
}
protected:
/**
A memory allocation method called by an external library.
\param opaque
Internal data.
\param items
The number of blocks to allocate.
\param size
The size of each block to allocate.
\return
The address of a newly allocated memory.
*/
static void* _zipalloc(void* opaque, UINT items, UINT size)
{
void* p = new char[size * items];
if (opaque)
{
CZipPtrList<void*>* list = (CZipPtrList<void*>*) opaque;
list->AddTail(p);
}
return p;
}
/**
A memory deallocation method called by an external library.
\param opaque
Internal data.
\param address
Memory address to free.
*/
static void _zipfree(void* opaque, void* address)
{
if (opaque)
{
CZipPtrList<void*>* list = (CZipPtrList<void*>*) opaque;
CZipPtrListIter iter = list->Find(address);
if (list->IteratorValid(iter))
list->RemoveAt(iter);
}
delete[] (char*) address;
}
/**
Frees the memory allocated by an external library that hasn't been freed
due to an error in the library (usually never happens).
*/
void EmptyPtrList();
/**
Checks, if \a iErr value is an error code.
\param iErr
The code to check.
\return
\c true, if \a iErr is an error code; \c false otherwise.
*/
virtual bool IsCodeErrorOK(int iErr) const = 0;
/**
Checks, if \a iErr value is an error code and throws an exception, if it is.
\param iErr
The error code.
\note
Throws exceptions.
*/
void CheckForError(int iErr)
{
if (!IsCodeErrorOK(iErr))
ThrowError(iErr, true);
}
/**
Sets an address of internal data used in ZipArchive Library memory allocation and deallocation methods.
\param opaque
Receives an address on the internal data.
\param pOptions
The current decompressor options.
*/
void SetOpaque(void** opaque, const COptions* pOptions);
/**
Signalizes, that the decompression process reached the end of the compressed data. It is internally set by derived classes.
*/
bool m_bDecompressionDone;
private:
typedef CZipPtrList<void*>::iterator CZipPtrListIter;
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning (push)
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#endif
CZipPtrList<void*> m_list; ///< A list holding pointers to the memory areas allocated by an external library.
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning( pop)
#endif
};
} // namespace
#endif

View File

@@ -0,0 +1,180 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file BytesWriter.h
* Includes the ZipArchiveLib::CBytesWriter class.
*
*/
#if !defined(ZIPARCHIVE_BYTESWRITER_DOT_H)
#define ZIPARCHIVE_BYTESWRITER_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "ZipCompatibility.h"
namespace ZipArchiveLib
{
/**
Provides implementation for various
buffer operations depending on the current platform and configuration.
*/
class ZIP_API CBytesWriter
{
public:
#ifdef ZIP_ARCHIVE_LITTLE_ENDIAN
/**
Reads \a iCount bytes from \a pSource into \a pDestination.
\param[out] pDestination
The buffer to retrieve data with byte-ordering depending on the machine.
\param[in] pSource
The buffer with little-endian ordered data.
\param iCount
The number of bytes to read.
*/
static void ReadBytes(WORD& uDestination, const char* pSource, int iCount = 2)
{
uDestination = 0;
memcpy(&uDestination, pSource, iCount);
}
static void ReadBytes(DWORD& uDestination, const char* pSource, int iCount = 4)
{
uDestination = 0;
memcpy(&uDestination, pSource, iCount);
}
#ifndef _ZIP_STRICT_U16
static void ReadBytes(int& iDestination, const char* pSource, int iCount)
{
iDestination = 0;
memcpy(&iDestination, pSource, iCount);
}
#endif
/**
Writes \a iCount bytes from \a pSource into \a pDestination.
\param[out] pDestination
The buffer to retrieve little-endian ordered data.
\param[in] pSource
The buffer with byte-ordering depending on the machine.
\param iCount
The number of bytes to write.
*/
static void WriteBytes(char* pDestination, WORD uSource)
{
memcpy(pDestination, &uSource, 2);
}
static void WriteBytes(char* pDestination, DWORD uSource, int iCount = 4)
{
memcpy(pDestination, &uSource, iCount);
}
#ifndef _ZIP_STRICT_U16
static void WriteBytes(char* pDestination, int uSource, int iCount)
{
memcpy(pDestination, &uSource, iCount);
}
#endif
#else
static void ReadBytes(char* pDestination, const char* pSource, int iDestSize, int iCount)
{
int i = iCount - iDestSize;
while (i < 0)
{
*pDestination++ = 0;
i++;
}
for (; i < iCount; i++)
(pDestination)[i] = pSource[iCount - i - 1];
}
static void ReadBytes(WORD& uDestination, const char* pSource, int iCount = 2)
{
ReadBytes((char*)&uDestination, pSource, 2, iCount);
}
static void ReadBytes(DWORD& uDestination, const char* pSource, int iCount = 4)
{
ReadBytes((char*)&uDestination, pSource, 4, iCount);
}
#ifndef _ZIP_STRICT_U16
static void ReadBytes(int& iDestination, const char* pSource, int iCount)
{
ReadBytes((char*)&iDestination, pSource, sizeof(int), iCount);
}
#endif
static void WriteBytes(char* pDestination, WORD uSource)
{
for (int i = 0; i < 2; i++)
pDestination[i] = ((char*)&uSource)[2 - i - 1];
}
static void WriteBytes(char* pDestination, DWORD uSource, int iCount = 4)
{
for (int i = 0; i < iCount; i++)
pDestination[i] = ((char*)&uSource)[4 - i - 1];
}
#ifndef _ZIP_STRICT_U16
static void WriteBytes(char* pDestination, int iSource, int iCount)
{
for (int i = 0; i < iCount; i++)
pDestination[i] = ((char*)&iSource)[sizeof(int) - i - 1];
}
#endif
#endif
static DWORD WriteSafeU32(DWORD uValue)
{
return uValue;
}
#ifdef _ZIP_STRICT_U16
static WORD WriteSafeU16(WORD uValue)
{
return uValue;
}
#else
static WORD WriteSafeU16(int uValue)
{
return (WORD)uValue;
}
#endif
};
}
#endif

View File

@@ -0,0 +1,16 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "_features.h"

View File

@@ -0,0 +1,14 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,251 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DeflateCompressor.h"
#include "zlib/deflate.h"
namespace ZipArchiveLib
{
#ifndef DEF_MEM_LEVEL
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
#endif
CDeflateCompressor::CDeflateCompressor(CZipStorage* pStorage)
:CBaseLibCompressor(pStorage)
{
m_stream.zalloc = (zarch_alloc_func)_zipalloc;
m_stream.zfree = (zarch_free_func)_zipfree;
}
void CDeflateCompressor::InitCompression(int iLevel, CZipFileHeader* pFile, CZipCryptograph* pCryptograph)
{
CZipCompressor::InitCompression(iLevel, pFile, pCryptograph);
m_stream.avail_in = (zarch_uInt)0;
m_stream.avail_out = (zarch_uInt)m_pBuffer.GetSize();
m_stream.next_out = (zarch_Bytef*)(char*)m_pBuffer;
m_stream.total_in = 0;
m_stream.total_out = 0;
if (pFile->m_uMethod == methodDeflate)
{
SetOpaque(&m_stream.opaque, &m_options);
int err = zarch_deflateInit2_(&m_stream, iLevel,
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, ZLIB_VERSION, sizeof(zarch_z_stream));
CheckForError(err);
}
}
void CDeflateCompressor::Compress(const void *pBuffer, DWORD uSize)
{
m_stream.next_in = (zarch_Bytef*)pBuffer;
m_stream.avail_in = uSize;
UpdateFileCrc(pBuffer, uSize);
while (m_stream.avail_in > 0)
{
if (m_stream.avail_out == 0)
{
FlushWriteBuffer();
m_stream.avail_out = m_pBuffer.GetSize();
m_stream.next_out = (zarch_Bytef*)(char*)m_pBuffer;
}
if (m_pFile->m_uMethod == methodDeflate)
{
ZIP_ZLIB_TYPE uTotal = m_stream.total_out;
CheckForError(zarch_deflate(&m_stream, Z_NO_FLUSH));
m_uComprLeft += m_stream.total_out - uTotal;
}
else
{
DWORD uToCopy = (m_stream.avail_in < m_stream.avail_out)
? m_stream.avail_in : m_stream.avail_out;
memcpy(m_stream.next_out, m_stream.next_in, uToCopy);
m_stream.avail_in -= uToCopy;
m_stream.avail_out -= uToCopy;
m_stream.next_in += uToCopy;
m_stream.next_out += uToCopy;
m_stream.total_in += uToCopy;
m_stream.total_out += uToCopy;
m_uComprLeft += uToCopy;
}
}
}
void CDeflateCompressor::FinishCompression(bool bAfterException)
{
m_stream.avail_in = 0;
if (!bAfterException)
{
if (m_pFile->m_uMethod == methodDeflate)
{
int err;
do
{
if (m_stream.avail_out == 0)
{
FlushWriteBuffer();
m_stream.avail_out = m_pBuffer.GetSize();
m_stream.next_out = (zarch_Bytef*)(char*)m_pBuffer;
}
ZIP_SIZE_TYPE uTotal = m_stream.total_out;
err = zarch_deflate(&m_stream, Z_FINISH);
m_uComprLeft += m_stream.total_out - uTotal;
}
while (err == Z_OK);
if (err == Z_STREAM_END)
err = Z_OK;
CheckForError(err);
}
if (m_uComprLeft > 0)
FlushWriteBuffer();
if (m_pFile->m_uMethod == methodDeflate)
CheckForError(zarch_deflateEnd(&m_stream));
// it may be increased by the encrypted header size in CZipFileHeader::PrepareData
m_pFile->m_uComprSize += m_stream.total_out;
m_pFile->m_uUncomprSize = m_stream.total_in;
}
EmptyPtrList();
ReleaseBuffer();
}
void CDeflateCompressor::InitDecompression(CZipFileHeader* pFile, CZipCryptograph* pCryptograph)
{
CBaseLibCompressor::InitDecompression(pFile, pCryptograph);
if (m_pFile->m_uMethod == methodDeflate)
{
SetOpaque(&m_stream.opaque, &m_options);
CheckForError(zarch_inflateInit2_(&m_stream, -MAX_WBITS, ZLIB_VERSION, sizeof(zarch_z_stream)));
}
m_stream.total_out = 0;
m_stream.avail_in = 0;
}
DWORD CDeflateCompressor::Decompress(void *pBuffer, DWORD uSize)
{
if (m_bDecompressionDone)
return 0;
m_stream.next_out = (zarch_Bytef*)pBuffer;
m_stream.avail_out = uSize > m_uUncomprLeft
? (DWORD)m_uUncomprLeft : uSize;
DWORD uRead = 0;
// may happen when the file is 0 sized
bool bForce = m_stream.avail_out == 0 && m_uComprLeft > 0;
while (m_stream.avail_out > 0 || (bForce && m_uComprLeft > 0))
{
if ((m_stream.avail_in == 0) &&
(m_uComprLeft >= 0)) // Also when there are zero bytes left
{
DWORD uToRead = m_pBuffer.GetSize();
if (m_uComprLeft < uToRead)
uToRead = (DWORD)m_uComprLeft;
if (uToRead == 0)
uToRead = 1; // Add dummy byte at end of compressed data.
else
{
m_pStorage->Read(m_pBuffer, uToRead, false);
if (m_pCryptograph)
m_pCryptograph->Decode(m_pBuffer, uToRead);
}
m_uComprLeft -= uToRead;
m_stream.next_in = (zarch_Bytef*)(char*)m_pBuffer;
m_stream.avail_in = uToRead;
}
if (m_pFile->m_uMethod == methodStore)
{
DWORD uToCopy = m_stream.avail_out < m_stream.avail_in
? m_stream.avail_out : m_stream.avail_in;
memcpy(m_stream.next_out, m_stream.next_in, uToCopy);
UpdateCrc(m_stream.next_out, uToCopy);
m_uUncomprLeft -= uToCopy;
m_stream.avail_in -= uToCopy;
m_stream.avail_out -= uToCopy;
m_stream.next_out += uToCopy;
m_stream.next_in += uToCopy;
m_stream.total_out += uToCopy;
uRead += uToCopy;
}
else
{
ZIP_SIZE_TYPE uTotal = m_stream.total_out;
zarch_Bytef* pOldBuf = m_stream.next_out;
int ret = zarch_inflate(&m_stream, Z_SYNC_FLUSH);
// will not exceed DWORD
DWORD uToCopy = (DWORD)(m_stream.total_out - uTotal);
UpdateCrc(pOldBuf, uToCopy);
m_uUncomprLeft -= uToCopy;
uRead += uToCopy;
if (ret == Z_STREAM_END)
{
m_bDecompressionDone = true;
return uRead;
}
else
CheckForError(ret);
}
}
if (!uRead && m_options.m_bCheckLastBlock && uSize != 0 && m_pFile->m_uMethod == methodDeflate)
{
if (zarch_inflate(&m_stream, Z_SYNC_FLUSH) != Z_STREAM_END)
// there were no more bytes to read and there was no ending block,
// otherwise the method would return earlier
ThrowError(CZipException::badZipFile);
}
return uRead;
}
void CDeflateCompressor::FinishDecompression(bool bAfterException)
{
if (!bAfterException && m_pFile->m_uMethod == methodDeflate)
zarch_inflateEnd(&m_stream);
EmptyPtrList();
ReleaseBuffer();
}
} // namespace

View File

@@ -0,0 +1,148 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file DeflateCompressor.h
* Includes the ZipArchiveLib::CDeflateCompressor class.
*
*/
#if !defined(ZIPARCHIVE_DEFLATECOMPRESSOR_DOT_H)
#define ZIPARCHIVE_DEFLATECOMPRESSOR_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "ZipExport.h"
#include "BaseLibCompressor.h"
#include "ZipException.h"
#include "zlib/zlib.h"
namespace ZipArchiveLib
{
/**
Compresses and decompresses data using the Zlib library.
*/
class ZIP_API CDeflateCompressor : public CBaseLibCompressor
{
public:
/**
Represents options of the CDeflateCompressor.
\see
<a href="kb">0610231446|options</a>
\see
CZipArchive::SetCompressionOptions
*/
struct ZIP_API COptions : CBaseLibCompressor::COptions
{
COptions()
{
m_bCheckLastBlock = true;
}
int GetType() const
{
return typeDeflate;
}
CZipCompressor::COptions* Clone() const
{
return new COptions(*this);
}
/**
Enables or disables checking, if the compressed data ends with an end-of-stream block.
This should be enabled to protect against malformed data.
\c true, if the checking of the last block should be enabled; \c false otherwise.
*/
bool m_bCheckLastBlock;
};
/**
Initializes a new instance of the CDeflateCompressor class.
\param pStorage
The current storage object.
*/
CDeflateCompressor(CZipStorage* pStorage);
bool CanProcess(WORD uMethod) {return uMethod == methodStore || uMethod == methodDeflate;}
void InitCompression(int iLevel, CZipFileHeader* pFile, CZipCryptograph* pCryptograph);
void InitDecompression(CZipFileHeader* pFile, CZipCryptograph* pCryptograph);
DWORD Decompress(void *pBuffer, DWORD uSize);
void Compress(const void *pBuffer, DWORD uSize);
void FinishCompression(bool bAfterException);
void FinishDecompression(bool bAfterException);
const CZipCompressor::COptions* GetOptions() const
{
return &m_options;
}
~CDeflateCompressor()
{
}
protected:
void UpdateOptions(const CZipCompressor::COptions* pOptions)
{
m_options = *(COptions*)pOptions;
}
int ConvertInternalError(int iErr) const
{
switch (iErr)
{
case Z_NEED_DICT:
return CZipException::needDict;
case Z_STREAM_END:
return CZipException::streamEnd;
case Z_ERRNO:
return CZipException::errNo;
case Z_STREAM_ERROR:
return CZipException::streamError;
case Z_DATA_ERROR:
return CZipException::dataError;
case Z_MEM_ERROR:
return CZipException::memError;
case Z_BUF_ERROR:
return CZipException::bufError;
case Z_VERSION_ERROR:
return CZipException::versionError;
default:
return CZipException::genericError;
}
}
bool IsCodeErrorOK(int iErr) const
{
return iErr == Z_OK || iErr == Z_NEED_DICT;
}
private:
COptions m_options;
zarch_z_stream m_stream;
};
} // namespace
#endif

View File

@@ -0,0 +1,185 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#if defined _MSC_VER && _MSC_VER < 1300
// STL warnings
#pragma warning (push, 3)
#endif
#include "DirEnumerator.h"
#include "FileFilter.h"
#include <queue>
#if defined __GNUC__ && !defined __MINGW32__
#include <sys/stat.h>
#include <dirent.h>
#else
#include <io.h>
#ifdef __BORLANDC__
#ifndef _tfindfirsti64
#define _tfindfirsti64 __tfindfirsti64
#endif
#ifndef _tfindnexti64
#define _tfindnexti64 __tfindnexti64
#endif
#ifndef _tfinddatai64_t
#define _tfinddatai64_t __tfinddatai64_t
#endif
#endif
#endif
namespace ZipArchiveLib
{
#if defined __GNUC__ && !defined __MINGW32__
#define ZIP_ENUMERATOR_FOR_GNUC
#endif
bool CDirEnumerator::Start(CFileFilter& filter)
{
OnEnumerationBegin();
std::queue<CZipString> dirs;
dirs.push(CZipString(m_lpszDirectory));
bool ret = true;
do
{
m_szCurrentDirectory = dirs.front();
dirs.pop();
CZipPathComponent::AppendSeparator(m_szCurrentDirectory);
EnterDirectory();
#ifdef ZIP_ENUMERATOR_FOR_GNUC
DIR* dp = opendir(m_szCurrentDirectory);
if (dp)
{
while (true)
{
struct dirent* entry = readdir(dp);
if (!entry)
break;
CZipString path(m_szCurrentDirectory + entry->d_name);
#if !defined __APPLE__ && !defined __CYGWIN__
struct stat64 sStats;
if (stat64(path, &sStats) == -1)
#else
struct stat sStats;
if (stat(path, &sStats) == -1)
#endif
continue;
LPCTSTR name = entry->d_name;
CFileInfo info;
info.m_uAttributes = sStats.st_mode;
#else
CZipString szFullFileName = m_szCurrentDirectory + _T("*");
_tfinddatai64_t ffInfo;
#if _MSC_VER > 1200
intptr_t hFile;
#else
long hFile;
#endif
if( (hFile = _tfindfirsti64( (LPTSTR)(LPCTSTR)szFullFileName, &ffInfo )) != -1L )
{
do
{
LPCTSTR name = ffInfo.name;
CFileInfo info;
info.m_uAttributes = ffInfo.attrib;
#endif
bool isDir;
if (ZipPlatform::IsDirectory(info.m_uAttributes))
{
if (!m_bRecursive || IsDots(name))
continue;
isDir = true;
}
else
isDir = false;
#ifdef ZIP_ENUMERATOR_FOR_GNUC
info.m_uSize = (ZIP_FILE_USIZE)sStats.st_size;
info.m_uCreateTime = sStats.st_ctime;
info.m_uModTime = sStats.st_mtime;
info.m_uAccessTime = sStats.st_atime;
#else
info.m_uSize = (ZIP_FILE_USIZE)ffInfo.size;
info.m_uCreateTime = ffInfo.time_create;
info.m_uModTime = ffInfo.time_write;
info.m_uAccessTime = ffInfo.time_access;
CZipString path(m_szCurrentDirectory + ffInfo.name);
#endif
if (isDir)
{
bool bAllow;
if (filter.HandlesFile(info))
bAllow = filter.Evaluate(path, name, info);
else
// examine directory, if the filter cannot decide
bAllow = true;
if (bAllow)
dirs.push(path);
}
else
{
bool bAllow;
if (filter.HandlesFile(info))
bAllow = filter.Evaluate(path, name, info);
else
// skip file, if the filter cannot decide
bAllow = false;
if (bAllow && !Process(path, info))
{
ret = false;
break;
}
}
#ifdef ZIP_ENUMERATOR_FOR_GNUC
}
closedir(dp);
}
#else
}
while (_tfindnexti64(hFile, &ffInfo) == 0L);
_findclose(hFile);
}
#endif
ExitDirectory();
}
while(!dirs.empty() && ret);
OnEnumerationEnd(ret);
return ret;
}
bool CDirEnumerator::IsDots(LPCTSTR lpszName)
{
CZipString name(lpszName);
return name.Compare(_T(".")) == 0 || name.Compare(_T("..")) == 0;
}
} // namespace
#if defined _MSC_VER && _MSC_VER < 1300
// STL warnings
#pragma warning (pop)
#endif

View File

@@ -0,0 +1,198 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file DirEnumerator.h
* Includes the ZipArchiveLib::CDirEnumerator class.
*
*/
#if !defined(ZIPARCHIVE_DIRENUMERATOR_DOT_H)
#define ZIPARCHIVE_DIRENUMERATOR_DOT_H
#if _MSC_VER > 1000
#pragma once
#pragma warning( push )
#pragma warning (disable : 4100) // unreferenced formal parameter
#if defined ZIP_HAS_DLL
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#endif
#endif
#include "ZipString.h"
#include "ZipPathComponent.h"
#include "FileFilter.h"
/**
Includes helper classes. Some of them can be reused in other applications.
*/
namespace ZipArchiveLib
{
/**
A base class for processing multiple files in a directory.
It provides a directory enumeration functionality.
*/
class ZIP_API CDirEnumerator
{
LPCTSTR m_lpszDirectory;
LPCTSTR m_lpszFileNameMask;
bool m_bRecursive;
CZipString m_szCurrentDirectory;
protected:
/**
Initializes a new CDirEnumerator object.
\param lpszDirectory
A directory to process.
\param bRecursive
The value indicating whether the subfolders of \a lpszDirectory
should be processed recursively or not.
\see
GetDirectory
\see
IsRecursive
*/
CDirEnumerator(LPCTSTR lpszDirectory, bool bRecursive = true)
{
CZipString dir(lpszDirectory);
if (dir.IsEmpty())
m_lpszDirectory = _T(".");
else
m_lpszDirectory = lpszDirectory;
m_bRecursive = bRecursive;
}
/**
Override this method to perform file processing while enumerating directories.
This method is not called for directories, but for files only.
\param lpszPath
The full path to the current file.
\param info
A structure containing an information about the current file.
\return
Return \c true to continue the enumeration.
When you return \c false, the enumeration is aborted.
\see
CFileFilter::Evaluate
*/
virtual bool Process(LPCTSTR lpszPath, const CFileInfo& info) = 0;
/**
This method is called at the beginning of the enumeration process.
\see
OnEnumerationEnd
*/
virtual void OnEnumerationBegin(){}
/**
This method is called at the end of the enumeration process.
\param bResult
It is set to \c false, if the #Process method returned \c false (the enumeration
was aborted). Otherwise, it is set to \c true.
\see
OnEnumerationBegin
*/
virtual void OnEnumerationEnd(bool bResult){}
/**
This method is called when an enumeration process enters a new directory.
\see
GetCurrentDirectory
\see
ExitDirectory
*/
virtual void EnterDirectory(){}
/**
This method is method called when an enumeration process exits a directory.
\see
GetCurrentDirectory
\see
EnterDirectory
*/
virtual void ExitDirectory(){}
public:
/**
Returns the directory being enumerated.
\return
The directory being enumerated (root).
\see
CDirEnumerator::CDirEnumerator
*/
LPCTSTR GetDirectory() const {return m_lpszDirectory;}
/**
Returns the value indicating whether the subfolders of the root directory
are processed recursively or not.
\return
\c true, if the enumeration process is recursive; \c false otherwise.
\see
CDirEnumerator::CDirEnumerator
*/
bool IsRecursive() const {return m_bRecursive;}
/**
Returns the directory which the enumeration process is currently processing.
\return
The directory which the enumeration process is currently processing.
*/
LPCTSTR GetCurrentDirectory() const {return m_szCurrentDirectory;}
/**
Starts the enumeration process. Calls CFileFilter::Evaluate method for every file or directory found.
If CFileFilter::Evaluate returns \c true, the file is processed by the #Process method.
\param filter
A filter that decides which directories and/or files should be processed and which should not.
\return
\c false, if the process was aborted (the #Process method returned \c false); \c true otherwise.
\see
CFileFilter::Evaluate
*/
bool Start(CFileFilter& filter);
virtual ~CDirEnumerator(){}
private:
static bool IsDots(LPCTSTR lpszName);
};
}
#if _MSC_VER > 1000
#pragma warning( pop )
#endif
#endif

View File

@@ -0,0 +1,60 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#if defined _MSC_VER && _MSC_VER < 1300
// STL warnings
#include "stdafx.h"
#pragma warning (push, 3)
#endif
#include "FileFilter.h"
namespace ZipArchiveLib
{
bool CGroupFileFilter::Accept(LPCTSTR lpszParentDir, LPCTSTR lpszName, const CFileInfo& info)
{
bool conditionToBreak;
bool valueToReturn;
// handle the evaluation as quickly as possible
if (m_iType == CGroupFileFilter::And)
{
conditionToBreak = false;
valueToReturn = m_bInverted;
}
else
{
conditionToBreak = true;
valueToReturn = !m_bInverted;
}
for (ZIP_ARRAY_SIZE_TYPE i = 0; i < m_filters.GetSize(); i++)
{
CFileFilter* pFilter = m_filters[i];
if (pFilter->HandlesFile(info) && pFilter->Evaluate(lpszParentDir, lpszName, info) == conditionToBreak)
return valueToReturn;
}
return !valueToReturn;
}
} // namespace
#if defined _MSC_VER && _MSC_VER < 1300
// STL warnings
#pragma warning (pop)
#endif

View File

@@ -0,0 +1,657 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file FileFilter.h
* Includes the ZipArchiveLib::CFileFilter and the derived classes.
*
*/
#if !defined(ZIPARCHIVE_FILEFILTER_DOT_H)
#define ZIPARCHIVE_FILEFILTER_DOT_H
#if _MSC_VER > 1000
#pragma once
#pragma warning( push )
#pragma warning (disable : 4100) // unreferenced formal parameter
#endif
#include "stdafx.h"
#include "ZipExport.h"
#include "FileInfo.h"
#include "Wildcard.h"
#include "ZipPlatform.h"
#include "ZipCollections.h"
namespace ZipArchiveLib
{
/**
A base class for filters used in the directory enumeration process.
\see
<a href="kb">0610231446|filters</a>
\see
CDirEnumerator::Start
*/
class ZIP_API CFileFilter
{
public:
/**
Initializes a new instance of the CFileFilter class.
\param bInverted
Set to \c true to invert the behavior of the filter or to \c false for the normal behavior.
\see
SetInverted
*/
CFileFilter(bool bInverted = false)
:m_bInverted(bInverted)
{
}
/**
This method is directly called by the CDirEnumerator::Start for each file or directory that was
previously accepted with the #HandlesFile method.
It internally calls the #Accept method and inverts it's result, if the filter is in the inverted
mode and does not handle the inversion internally.
- If this method returns \c true for a file, then the file is processed (the CDirEnumerator::Process method
is called for the file). Otherwise the file is not processed.
- If this method returns \c true for a directory, then the directory can be traversed for files and subfolders
(depending on the CDirEnumerator::IsRecursive() method). Otherwise the directory is not traversed.
\param lpszParentDir
The parent directory containing the file to accept.
\param lpszName
The name of the file to accept (without a path).
\param info
A structure containing the information about the current file.
\return
\c true, if the file is accepted (taking inversion into account); \c false otherwise.
\see
Accept
\see
HandlesFile
\see
HandlesInversion
\see
SetInverted
\see
IsInverted
\see
CDirEnumerator::Start
\see
CDirEnumerator::Process
*/
bool Evaluate(LPCTSTR lpszParentDir, LPCTSTR lpszName, const CFileInfo& info)
{
bool ret = Accept(lpszParentDir, lpszName, info);
if (!HandlesInversion())
return m_bInverted ? !ret : ret;
return ret;
}
/**
Sets the filter to operate in the inverted or in the normal mode.
If the filter operates in an inverted mode, the file that this filer accepts
is \b not processed and vice versa. Normal mode means that a file is processed
(the CDirEnumerator::Process method is called for that file),
if the filter accepts the file.
\param bInverted
\c true to make the filter operate in an inverted mode or \c false to make
the filter operate in a normal mode.
\see
HandlesInversion
\see
IsInverted
*/
void SetInverted(bool bInverted = true) { m_bInverted = bInverted;}
/**
Returns the value indicating whether the filter operates in an inverted mode or in a normal mode.
\return
\c true, if the filter operates in an inverted mode; \c false otherwise.
\see
SetInverted
\see
HandlesInversion
*/
bool IsInverted() const {return m_bInverted;}
/**
Returns the value indicating whether the filter can decide about processing of the \a info file.
If it can, then the #Evaluate method will be called for the \a info file.
By default this method returns \c true for files and \c false for directories. Override this method
to change it's behavior.
- If \a info is a file and this method returns \c false, then the file is not processed.
- If \a info is a directory and this method returns \c false, then the directory can still be traversed for files
and subfolders (depending on the CDirEnumerator::IsRecursive() method).
The #Evaluate method is not called in both cases.
\param info
A structure containing the information about the file.
\return
\c true, if the \a info file should be evaluated by the #Evaluate method; \c false otherwise.
\note
This method is particularly useful when the filter operates in the inverted mode (see #SetInverted).
For example, if a filter should accept directories in both inverted and non-inverted mode, it would need
to particularly handle inversion for directories without this method. With this method it can just not accept
directories for evaluation and they still will be traversed.
*/
virtual bool HandlesFile(const CFileInfo& info)
{
return !info.IsDirectory();
}
virtual ~CFileFilter()
{
}
protected:
/**
This method is directly called by the #Evaluate method during an enumeration process.
If this method returns \c true, the file will later be processed
by the CDirEnumerator::Process method. If this method returns \c false for a directory,
the directory is not enumerated at all.
The meaning of the return value can be reversed by the #SetInverted method.
If this filter handles the inversion internally, the return value from this method
is not reversed by the #Evaluate method.
\param lpszParentDir
The parent directory containing the file to accept.
\param lpszName
The name of the file to accept (without a path).
\param info
A structure containing the information about the current file.
\return
\c true, if the file is accepted; \c false otherwise.
\see
Evaluate
\see
HandlesInversion
\see
CDirEnumerator::Start
\see
CDirEnumerator::Process
*/
virtual bool Accept(LPCTSTR lpszParentDir, LPCTSTR lpszName, const CFileInfo& info)
{
return true;
}
/**
Returns the value indicating, whether the current filter handles the inversion mode internally
or not.
- If the filter is in the inverted mode and it handles the inversion, then the return value \c true
from the #Accept method means that the file should be processed.
- If the filter is in the inverted mode and it does not handle the inversion, then the return value \c true
from the #Accept method means that the file should not be processed.
It may be more efficient to handle the inversion internally in some cases.
\return
\c true, if the filter handles the inversion internally; \c false otherwise.
\note
This method returns \c false by default. Override this method to change this behavior.
\see
SetInverted
\see
IsInverted
*/
virtual bool HandlesInversion() const
{
return false;
}
bool m_bInverted;
};
/**
A filter that allows filtering files by a filename mask while an enumeration process.
\see
<a href="kb">0610231446|filters</a>
\see
<a href="kb">0610242025|wildcards</a>
\see
CDirEnumerator::Start
*/
class ZIP_API CNameFileFilter : public CFileFilter
{
CWildcard m_matcher;
int m_iAppliesToTypes;
public:
/**
The file type to which the CNameFileFilter filter can be applied.
You can use the logical \c OR to combine them.
\see
SetAppliesToTypes
\see
GetAppliesToTypes
*/
enum AppliesToTypes
{
toFile = 0x1, ///< Regular files only.
toDirectory = 0x2, ///< Directories only.
toAll = toFile | toDirectory ///< Both regular files and directories.
};
/**
Initializes a new instance of the CNameFileFilter class.
\param lpszPattern
A mask to match against a filename. This filter uses the CWildcard functionality for this purpose.
\param iAppliesToTypes
The file type to which this filter applies. The file type to which this filter applies. Can be one or more of the #AppliesToTypes values.
\param bInverted
Set to \c true to invert the behavior of the filter or to \c false for the normal behavior.
\param bCaseSensitive
\c true, if the matching process is case-sensitive; \c false otherwise.
By default, a system case-sensitivity setting is used.
\see
<a href="kb">0610231446|filters</a>
\see
<a href="kb">0610242025|wildcards</a>
\see
SetInverted
\see
SetAppliesToTypes
\see
CWildcard
\see
ZipPlatform::GetSystemCaseSensitivity
*/
CNameFileFilter(LPCTSTR lpszPattern = _T("*.*"), bool bInverted = false, int iAppliesToTypes = toFile, bool bCaseSensitive = ZipPlatform::GetSystemCaseSensitivity())
:CFileFilter(bInverted), m_matcher(lpszPattern, bCaseSensitive)
{
m_iAppliesToTypes = iAppliesToTypes;
}
/**
Returns the value indicating whether the filter can be applied to the given \a iType type.
\param iType
Can be one or more of the #AppliesToTypes values.
\return
\c true, if the filter can be applied to \a iType type; \c false otherwise.
\see
SetAppliesToTypes
\see
GetAppliesToTypes
*/
bool AppliesToType(int iType)
{
return (m_iAppliesToTypes & iType) == iType;
}
/**
Set the file type to which this filter applies.
\param iType
The file type to which this filter applies. Can be one or more of the #AppliesToTypes values.
\see
GetAppliesToTypes
*/
void SetAppliesToTypes(int iType) { m_iAppliesToTypes = iType; }
/**
Return the file type to which this filter applies.
\return
The file type to which this filter applies. Can be one or more of the #AppliesToTypes values.
\see
SetAppliesToTypes
*/
int GetAppliesToTypes() {return m_iAppliesToTypes;}
/**
Returns the value indicating whether the filter can decide about processing of the \a info file.
The CNameFileFilter returns the value depending on the #GetAppliesToTypes value.
\param info
A structure containing the information about the file.
\return
\c true, if the \a info file will be evaluated by the #Evaluate method; \c false otherwise.
\see
GetAppliesToTypes
\see
SetAppliesToTypes
*/
bool HandlesFile(const CFileInfo& info)
{
return info.IsDirectory() ? AppliesToType(toDirectory) : AppliesToType(toFile);
}
protected:
virtual bool Accept(LPCTSTR, LPCTSTR lpszName, const CFileInfo& info)
{
return m_matcher.IsMatch(lpszName);
}
};
/**
A filter that allows grouping of other filters.
\see
<a href="kb">0610231446|filters</a>
\see
CDirEnumerator::Start
*/
class ZIP_API CGroupFileFilter : public CFileFilter
{
public:
/**
The grouping type.
*/
enum GroupType
{
And, ///< Logical AND. All the grouped filters must accept a file for the file to be processed.
Or ///< Logical OR. At least one of the grouped filters must accept a file for the file to be processed.
};
/**
Initializes a new instance of the CGroupFileFilter class.
\param groupType
The grouping type. Should be one of the #GroupType values.
\param bAutoDelete
\c true, if the grouped filters should be automatically destroyed by this filter; \c false otherwise.
\param bInverted
Set to \c true to invert the behavior of the filter or to \c false for the normal behavior.
This filter handles the inversion mode internally.
\see
<a href="kb">0610231446|filters</a>
\see
SetType
\see
SetAutoDelete
\see
SetInverted
\see
HandlesInversion
*/
CGroupFileFilter(GroupType groupType = CGroupFileFilter::And, bool bAutoDelete = true, bool bInverted = false)
:CFileFilter(bInverted), m_iType(groupType), m_bAutoDelete(bAutoDelete)
{
}
/**
Add \a pFilter to the filter's group.
\param pFilter
The filter to add.
*/
void Add(CFileFilter* pFilter)
{
m_filters.Add(pFilter);
}
/**
Returns the filter at the given position.
\param uIndex
The index of the filter to return.
*/
CFileFilter* GetAt(ZIP_ARRAY_SIZE_TYPE uIndex)
{
return m_filters[uIndex];
}
/**
Returns the filter at the given position.
\param uIndex
The index of the filter to return.
*/
const CFileFilter* GetAt(ZIP_ARRAY_SIZE_TYPE uIndex) const
{
return m_filters[uIndex];
}
/**
Returns the filter at the given position.
\param uIndex
The index of the filter to return.
*/
const CFileFilter* operator[] (ZIP_ARRAY_SIZE_TYPE uIndex) const
{
return GetAt(uIndex);
}
/**
Returns the filter at the given position.
\param uIndex
The index of the filter to return.
*/
CFileFilter* operator[] (ZIP_ARRAY_SIZE_TYPE uIndex)
{
return GetAt(uIndex);
}
/**
Remove the filter at the given position.
The removed filter is deleted from memory,
if the CGroupFileFilter object is in the auto-delete mode.
\param uIndex
The index of the filter to remove.
\see
SetAutoDelete
*/
void RemoveAt(ZIP_ARRAY_SIZE_TYPE uIndex)
{
CFileFilter* filter = m_filters[uIndex];
// first remove, then delete
m_filters.RemoveAt(uIndex);
if (m_bAutoDelete)
delete filter;
}
/**
Removes all contained filters from the collection.
The removed filters are deleted from memory,
if the CGroupFileFilter object is in the auto-delete mode.
\see
SetAutoDelete
*/
void Clear()
{
if (m_filters.GetSize() == 0)
return;
ZIP_ARRAY_SIZE_TYPE i = m_filters.GetSize() - 1;
for (; ;)
{
RemoveAt(i);
if (i == 0)
break;
i--;
}
}
/**
Returns the number of grouped filters.
\return
The number of grouped filters.
*/
ZIP_ARRAY_SIZE_TYPE GetSize()
{
return m_filters.GetSize();
}
/**
Sets the type of grouping.
\param iType
The type of grouping. Should be one of the #GroupType values.
\see
GetType
*/
void SetType(GroupType iType) {m_iType = iType;}
/**
Returns the type of grouping.
\return
The type of groupgroupeding. Can be one of the #GroupType values.
\see
SetType
*/
GroupType GetType() const {return m_iType;}
/**
Enable or disable auto-deletion of grouped filters.
If auto-deletion is enabled, the grouped filters are released from memory
when they are removed from the group or when the CGroupFileFilter
object is destroyed.
\param bAutoDelete
\c true, to enable auto-deletion; \c false to disable.
\see
IsAutoDelete
*/
void SetAutoDelete(bool bAutoDelete) {m_bAutoDelete = bAutoDelete;}
/**
Return the value indicating whether the auto-deletion is enabled or not.
\return
\c true, if the auto-deletion is enabled; \c false otherwise.
\see
SetAutoDelete
*/
bool IsAutoDelete() const {return m_bAutoDelete;}
/**
Returns the value indicating whether the filter can decide about processing of the \a info file.
The CGroupFileFilter returns the value depending on the value returned by the grouped filters.
\param info
A structure containing the information about the file.
\return
\c true, if any of the grouped filters accepts \a info; \c false otherwise.
*/
bool HandlesFile(const CFileInfo& info)
{
for (ZIP_ARRAY_SIZE_TYPE i = 0; i < m_filters.GetSize(); i++)
// it is enough that one filter handles it
if (m_filters[i]->HandlesFile(info))
return true;
return false;
}
~CGroupFileFilter()
{
Clear();
}
protected:
virtual bool Accept(LPCTSTR lpszParentDir, LPCTSTR lpszName, const CFileInfo& info);
/**
This filter handles inversion internally.
\return
This method returns \c true for this class.
\see
CFileFilter::HandlesInversion
*/
bool HandlesInversion() const
{
return true;
}
GroupType m_iType; ///< Set with the #SetType method or in constructor.
bool m_bAutoDelete; ///< Set with the #SetAutoDelete or in constructor.
private:
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning (push)
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#endif
CZipArray<CFileFilter*> m_filters;
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning( pop)
#endif
};
}
#if _MSC_VER > 1000
#pragma warning( pop )
#endif
#endif

View File

@@ -0,0 +1,69 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file FileInfo.h
* Includes the ZipArchiveLib::CFileInfo class.
*
*/
#if !defined(ZIPARCHIVE_FILEINFO_DOT_H)
#define ZIPARCHIVE_FILEINFO_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "stdafx.h"
#include "ZipExport.h"
#include "ZipPlatform.h"
namespace ZipArchiveLib
{
/**
A structure holding a file or a directory information.
*/
struct ZIP_API CFileInfo
{
public:
/**
Initializes a new instance of the CFileInfo class.
*/
CFileInfo()
{
m_uSize = 0;
m_uAttributes = 0;
m_uCreateTime = m_uModTime = m_uAccessTime = 0;
}
ZIP_FILE_USIZE m_uSize; ///< The file size.
DWORD m_uAttributes; ///< The file system attributes.
time_t m_uCreateTime; ///< Creation time.
time_t m_uModTime; ///< Last modification time.
time_t m_uAccessTime; ///< Last access time.
/**
Returns the value indicating whether the current CFileInfo
object represents a directory or a regular file.
\return
\c true, if the current CFileInfo object represents
a directory; \c false, if it represents a regular file.
*/
bool IsDirectory() const
{
return ZipPlatform::IsDirectory(m_uAttributes);
}
};
}
#endif

View File

@@ -0,0 +1,16 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "_features.h"

View File

@@ -0,0 +1,14 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,16 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "_features.h"

View File

@@ -0,0 +1,14 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,16 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "_features.h"

View File

@@ -0,0 +1,14 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,401 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Wildcard.h"
namespace ZipArchiveLib
{
bool CWildcard::IsPatternValid(LPCTSTR lpszPattern, int* iErrorType)
{
try
{
/* loop through pattern to EOS */
while (*lpszPattern)
{
/* determine pattern type */
switch (*lpszPattern)
{
/* check literal escape, it cannot be at end of pattern */
case _T('\\'):
if (!*++lpszPattern)
throw patternEsc;
lpszPattern++;
break;
/* the [..] construct must be well formed */
case _T('['):
lpszPattern++;
/* if the next character is ']' then bad pattern */
if (*lpszPattern == _T(']'))
throw patternEmpty;
/* if end of pattern here then bad pattern */
if (!*lpszPattern)
throw patternClose;
/* loop to end of [..] construct */
while (*lpszPattern != _T(']'))
{
/* check for literal escape */
if (*lpszPattern == _T('\\'))
{
lpszPattern++;
/* if end of pattern here then bad pattern */
if (!*lpszPattern++)
throw patternEsc;
}
else lpszPattern++;
/* if end of pattern here then bad pattern */
if (!*lpszPattern)
throw patternClose;
/* if this a range */
if (*lpszPattern == _T('-'))
{
/* we must have an end of range */
if (!*++lpszPattern || *lpszPattern == ']')
throw patternRange;
else
{
/* check for literal escape */
if (*lpszPattern == _T('\\'))
lpszPattern++;
/* if end of pattern here
then bad pattern */
if (!*lpszPattern++)
throw patternEsc;
}
}
}
break;
/* all other characters are valid pattern elements */
case '*':
case '?':
default:
lpszPattern++; /* "normal" character */
break;
}
}
throw patternValid;
}
catch (int i)
{
if (iErrorType)
*iErrorType = i;
return i == patternValid;
}
}
bool CWildcard::IsPattern(LPCTSTR lpszPattern)
{
while (*lpszPattern)
{
switch (*lpszPattern++)
{
case _T('?'):
case _T('*'):
case _T('['):
case _T('\\'):
return true;
}
}
return false;
}
bool CWildcard::IsMatch(LPCTSTR lpszText, int *iRetCode)
{
CZipString sz;
if (!m_bCaseSensitive)
{
sz = lpszText;
sz.MakeLower();
lpszText = (LPCTSTR)sz;
}
int i = Match((LPCTSTR)m_szPattern, lpszText);
if (iRetCode)
*iRetCode = i;
return i == matchValid;
}
int CWildcard::MatchAfterStar(LPCTSTR p, LPCTSTR t)
{
int iMatch = matchNone;
TCHAR nextp;
/* pass over existing ? and * in pattern */
while ( *p == _T('?') || *p == _T('*') )
{
/* take one char for each ? and + */
if (*p == _T('?'))
{
/* if end of text then no match */
if (!*t++)
return matchAbort;
}
/* move to next char in pattern */
p++;
}
/* if end of pattern we have matched regardless of text left */
if (!*p)
return matchValid;
/* get the next character to match which must be a literal or '[' */
nextp = *p;
if (nextp == _T('\\'))
{
nextp = p[1];
/* if end of text then we have a bad pattern */
if (!nextp)
return matchPattern;
}
/* Continue until we run out of text or definite result seen */
do
{
/* a precondition for matching is that the next character
in the pattern match the next character in the text or that
the next pattern char is the beginning of a range. Increment
text pointer as we go here */
if (nextp == *t || nextp == _T('['))
iMatch = Match(p, t);
/* try finding another precondition */
if (iMatch == matchPattern)
iMatch = matchNone;
/* if the end of text is reached then no iMatch */
if (!*t++)
iMatch = matchAbort;
} while ( iMatch != matchValid &&
iMatch != matchAbort);
/* return result */
return iMatch;
}
int CWildcard::Match(LPCTSTR lpszPattern, LPCTSTR lpszText)
{
TCHAR range_start, range_end; /* start and end in range */
bool bInvert; /* is this [..] or [!..] */
bool bMemberMatch; /* have I matched the [..] construct? */
bool bLoop; /* should I terminate? */
for ( ; *lpszPattern; lpszPattern++, lpszText++)
{
/* if this is the end of the text
then this is the end of the match */
if (!*lpszText)
{
if ( *lpszPattern == _T('*') && *++lpszPattern == _T('\0') )
return matchValid;
else
return matchAbort;
}
/* determine and react to pattern type */
switch (*lpszPattern)
{
case _T('?'): /* single any character match */
break;
case _T('*'): /* multiple any character match */
return MatchAfterStar (lpszPattern, lpszText);
/* [..] construct, single member/exclusion character match */
case _T('['):
{
/* move to beginning of range */
lpszPattern++;
/* check if this is a member match or exclusion match */
bInvert = false;
if (*lpszPattern == _T('!') || *lpszPattern == _T('^'))
{
bInvert = true;
lpszPattern++;
}
/* if closing bracket here or at range start then we have a
malformed pattern */
if (*lpszPattern == _T(']'))
return matchPattern;
bMemberMatch = false;
bLoop = true;
while (bLoop)
{
/* if end of construct then bLoop is done */
if (*lpszPattern == _T(']'))
{
bLoop = false;
continue;
}
/* matching a '!', '^', '-', '\' or a ']' */
if (*lpszPattern == _T('\\'))
range_start = range_end = *++lpszPattern;
else
range_start = range_end = *lpszPattern;
/* if end of pattern then bad pattern (Missing ']') */
if (!*lpszPattern)
return matchPattern;
/* check for range bar */
if (*++lpszPattern == _T('-'))
{
/* get the range end */
range_end = *++lpszPattern;
/* if end of pattern or construct
then bad pattern */
if (range_end == _T('\0') || range_end == _T(']'))
return matchPattern;
/* special character range end */
if (range_end == _T('\\'))
{
range_end = *++lpszPattern;
/* if end of text then
we have a bad pattern */
if (!range_end)
return matchPattern;
}
/* move just beyond this range */
lpszPattern++;
}
/* if the text character is in range then match found.
make sure the range letters have the proper
relationship to one another before comparison */
if (range_start < range_end)
{
if (*lpszText >= range_start && *lpszText <= range_end)
{
bMemberMatch = true;
bLoop = false;
}
}
else
{
if (*lpszText >= range_end && *lpszText <= range_start)
{
bMemberMatch = true;
bLoop = false;
}
}
}
/* if there was a match in an exclusion set then no match */
/* if there was no match in a member set then no match */
if ((bInvert && bMemberMatch) || !(bInvert || bMemberMatch))
return matchRange;
/* if this is not an exclusion then skip the rest of
the [...] construct that already matched. */
if (bMemberMatch)
{
while (*lpszPattern != _T(']'))
{
/* bad pattern (Missing ']') */
if (!*lpszPattern)
return matchPattern;
/* skip exact match */
if (*lpszPattern == _T('\\'))
{
lpszPattern++;
/* if end of text then
we have a bad pattern */
if (!*lpszPattern)
return matchPattern;
}
/* move to next pattern char */
lpszPattern++;
}
}
break;
}
case _T('\\'): /* next character is quoted and must match exactly */
/* move pattern pointer to quoted char and fall through */
lpszPattern++;
/* if end of text then we have a bad pattern */
if (!*lpszPattern)
return matchPattern;
/* must match this character exactly */
default:
if (*lpszPattern != *lpszText)
return matchPattern;
}
}
/* if end of text not reached then the pattern fails */
if (*lpszText)
return matchEnd;
else
return matchValid;
}
} // namespace

View File

@@ -0,0 +1,195 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/*
This class is based on code by J. Kercheval, created 01/05/1991
and available as a public domain at http://www.snippets.org.
*/
/**
* \file Wildcard.h
* Includes the ZipArchiveLib::CWildcard class.
*
*/
#if !defined(ZIPARCHIVE_WILDCARD_DOT_H)
#define ZIPARCHIVE_WILDCARD_DOT_H
#if _MSC_VER > 1000
#pragma once
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning( push )
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#endif
#endif
#include "ZipString.h"
namespace ZipArchiveLib
{
/**
A class used in the wildcard pattern matching.
\see
<a href="kb">0610242025|wildcards</a>
*/
class ZIP_API CWildcard
{
public:
enum Match
{
matchNone, ///< For internal use.
matchValid, ///< Valid match.
matchEnd, ///< Premature end of the pattern string.
matchAbort, ///< Premature end of the text string.
matchRange, ///< Match failure on the \c [..] construct.
matchLiteral, ///< Match failure on a literal match
matchPattern ///< Bad pattern.
};
enum Pattern
{
patternEmpty = -4, ///< The \c [..] construct is empty
patternClose, ///< There is no end bracket in the \c [..] construct.
patternRange, ///< Malformed range in the \c [..] construct.
patternEsc, ///< Literal escape at the end of the pattern.
patternValid, ///< Valid pattern.
};
/**
Matches \a lpszText against the pattern.
A match means the entire \a lpszText is used up in matching.
Set the pattern with the #SetPattern method or in the constructor.
\param lpszText
The string to match against the pattern.
\param iRetCode
If not \c NULL, receives one of #Match values indicating a return code.
\return
\c true, if \a lpszText matches the pattern.
\see
SetPattern
*/
bool IsMatch(LPCTSTR lpszText, int* iRetCode = NULL);
/**
Gets a value indicating if \a lpszPattern has any special wildcard characters.
\param lpszPattern
The pattern to test.
\return
\c true, if the pattern has wildcard characters; \c false otherwise.
*/
static bool IsPattern(LPCTSTR lpszPattern);
/**
Tests \a lpszPattern for validity.
\param lpszPattern
The pattern to test.
\param iErrorType
If not \c NULL, receives one of the #Pattern values indicating a return code.
\return
\c true, if \a lpszPattern is a well formed regular expression according
to the CWildcard class syntax (see #SetPattern); \c false otherwise.
*/
static bool IsPatternValid(LPCTSTR lpszPattern, int* iErrorType = NULL);
/**
Matches \a lpszText against \a lpszPattern.
A match means the entire \a lpszText is used in matching.
\param lpszPattern
The pattern to match.
\param lpszText
The string to match against the pattern.
\return
One of #Match values.
\see
SetPattern
*/
static int Match(LPCTSTR lpszPattern, LPCTSTR lpszText);
/**
Initializes a new instance of the CWildcard class.
*/
CWildcard(){}
/**
Initializes a new instance of the CWildcard class.
\param lpszPattern
The pattern to use in matching.
\param bCaseSensitive
The case-sensitivity of matching.
\see
<a href="kb">0610242025|wildcards</a>
*/
CWildcard(LPCTSTR lpszPattern, bool bCaseSensitive)
{
SetPattern(lpszPattern, bCaseSensitive);
}
virtual ~CWildcard(){}
/**
Sets the current pattern
\param lpszPattern
The pattern used in matching.
\param bCaseSensitive
The case-sensitivity of matching.
\see
<a href="kb">0610242025|wildcards</a>
*/
void SetPattern(LPCTSTR lpszPattern, bool bCaseSensitive)
{
m_szPattern = lpszPattern;
m_bCaseSensitive=bCaseSensitive;
if (!bCaseSensitive)
m_szPattern.MakeLower();
}
operator LPCTSTR()
{
return (LPCTSTR)m_szPattern;
}
private:
bool m_bCaseSensitive;
static int MatchAfterStar(LPCTSTR p , LPCTSTR t);
CZipString m_szPattern;
};
}
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning (pop)
#endif
#endif

View File

@@ -0,0 +1,74 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipAbstractFile.h
* Includes the CZipAbstractFile class.
*
*/
#if !defined(ZIPARCHIVE_ZIPABSTRACTFILE_DOT_H)
#define ZIPARCHIVE_ZIPABSTRACTFILE_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "ZipExport.h"
#include "ZipString.h"
class ZIP_API CZipAbstractFile
{
public:
enum { begin = SEEK_SET, // 0
current = SEEK_CUR, // 1
end = SEEK_END // 2
};
CZipAbstractFile(){}
virtual bool Open(LPCTSTR , UINT , bool ){return false;}
virtual void Close() = 0;
virtual void Flush() = 0;
virtual ZIP_FILE_USIZE GetPosition() const = 0;
virtual ZIP_FILE_USIZE Seek(ZIP_FILE_SIZE lOff, int nFrom) = 0;
ZIP_FILE_USIZE Seek(ZIP_FILE_USIZE lOff, bool fromBeginning = true)
{
ZIP_FILE_SIZE offset;
if (lOff > ZIP_FILE_SIZEMAX)
{
offset = GetLength() - lOff;
fromBeginning = !fromBeginning;
}
else
offset = (ZIP_FILE_USIZE)lOff;
if (fromBeginning)
return Seek(offset, CZipAbstractFile::begin);
else
return Seek(-offset, CZipAbstractFile::end);
}
virtual ZIP_FILE_USIZE GetLength() const = 0;
virtual void SetLength(ZIP_FILE_USIZE nNewLen) = 0;
virtual ZIP_FILE_USIZE SeekToBegin(){return Seek(0, begin);}
virtual ZIP_FILE_USIZE SeekToEnd(){return Seek(0, end);}
virtual CZipString GetFilePath() const = 0;
virtual UINT Read(void *lpBuf, UINT nCount) = 0;
virtual void Write(const void* lpBuf, UINT nCount) = 0;
virtual bool IsClosed() const = 0;
virtual ~CZipAbstractFile(){};
};
#endif // !defined(ZIPARCHIVE_ZIPABSTRACTFILE_DOT_H)

View File

@@ -0,0 +1,16 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "_features.h"

View File

@@ -0,0 +1,14 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,95 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipAutoBuffer.h"
#include <memory.h>
CZipAutoBuffer::CZipAutoBuffer()
{
m_iSize = 0;
m_pBuffer = NULL;
}
CZipAutoBuffer::CZipAutoBuffer(DWORD iSize, bool bZeroMemory)
{
m_iSize = 0;
m_pBuffer = NULL;
Allocate(iSize, bZeroMemory);
}
CZipAutoBuffer::~CZipAutoBuffer()
{
Release();
}
void CZipAutoBuffer::Release()
{
if (m_pBuffer)
{
delete [] m_pBuffer;
m_iSize = 0;
m_pBuffer = NULL;
}
}
char* CZipAutoBuffer::Allocate(DWORD iSize, bool bZeroMemory)
{
if (iSize != m_iSize)
Release();
else
{
if (bZeroMemory)
memset(m_pBuffer, 0, iSize); // zerowanie bufora
return m_pBuffer;
}
if (iSize > 0)
{
m_pBuffer = new char [iSize];
if (bZeroMemory)
memset(m_pBuffer, 0, iSize); // zerowanie bufora
m_iSize = iSize;
}
else
m_pBuffer = NULL;
return m_pBuffer;
}
CZipAutoBuffer::CZipAutoBuffer(const CZipAutoBuffer& buffer)
{
m_pBuffer = NULL;
m_iSize = 0;
if (buffer.m_pBuffer)
{
Allocate(buffer.m_iSize);
memcpy(m_pBuffer, buffer.m_pBuffer, buffer.m_iSize);
}
}
CZipAutoBuffer& CZipAutoBuffer::operator=(const CZipAutoBuffer& buffer)
{
if (this == &buffer)
return *this;
Release();
if (buffer.m_pBuffer)
{
Allocate(buffer.m_iSize);
memcpy(m_pBuffer, buffer.m_pBuffer, buffer.m_iSize);
}
return *this;
}

View File

@@ -0,0 +1,67 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipAutoBuffer.h
* Includes the CZipAutoBuffer class.
*
*/
#if !defined(ZIPARCHIVE_ZIPAUTOBUFFER_DOT_H)
#define ZIPARCHIVE_ZIPAUTOBUFFER_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "ZipExport.h"
/**
A smart buffer freeing its contents on destruction.
*/
class ZIP_API CZipAutoBuffer
{
public:
operator char*()
{
return m_pBuffer;
}
#if !defined (__BORLANDC__) || (__BORLANDC__ > 0x560) // The actual version may be different.
operator const char*() const
{
return m_pBuffer;
}
#endif
const char* GetBuffer() const {return m_pBuffer;}
char* Allocate(DWORD iSize, bool bZeroMemory = false);
void Release();
DWORD GetSize() const
{
return m_iSize;
}
bool IsAllocated() const
{
return (m_pBuffer != NULL);
}
CZipAutoBuffer(DWORD iSize, bool bZeroMemory = false);
CZipAutoBuffer();
CZipAutoBuffer(const CZipAutoBuffer& buffer);
virtual ~CZipAutoBuffer();
CZipAutoBuffer& operator=(const CZipAutoBuffer& buffer);
protected:
char* m_pBuffer;
DWORD m_iSize;
};
#endif // !defined(ZIPARCHIVE_ZIPAUTOBUFFER_DOT_H)

View File

@@ -0,0 +1,30 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipBaseException.h
* Contains a type definition of the base exception class.
*
*/
#ifndef ZIPARCHIVE_ZIPBASEEXCEPTION_DOT_H
#define ZIPARCHIVE_ZIPBASEEXCEPTION_DOT_H
#ifdef ZIP_ARCHIVE_STL
typedef std::exception CZipBaseException;
#else
typedef CException CZipBaseException;
#endif
#endif //ZIPARCHIVE_ZIPBASEEXCEPTION_DOT_H

View File

@@ -0,0 +1,730 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipCallback.h
* Includes the CZipCallback and the derived classes.
*
*/
#if !defined(ZIPARCHIVE_ZIPCALLBACK_DOT_H)
#define ZIPARCHIVE_ZIPCALLBACK_DOT_H
#if _MSC_VER > 1000
#pragma once
#if defined ZIP_HAS_DLL
#pragma warning (push)
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#endif
#endif
#include "ZipString.h"
#include "ZipExport.h"
/*
When processing split archives, this value is passes as the argument to the CZipCallback::Callback method
to notify that the current volume is the last one.
*/
#define ZIP_SPLIT_LAST_VOLUME (ZIP_SIZE_TYPE)(-1)
/**
A base class for callback objects that are notified when various actions take place.
You need to derive your own class and overload the #Callback method to use it.
Do not derive from CZipCallback directly but derive from:
\li CZipSegmCallback, when you create a segmented archive - you will be notified
when there the next volume is processed in a segmented archive.
\li CZipActionCallback, for other notifications.
\see
<a href="kb">0610051553|span</a>
\see
<a href="kb">0610231200</a>
\see
CZipSegmCallback
\see
CZipActionCallback
*/
struct ZIP_API CZipCallback
{
/**
The method called as a callback.
Return \c false from inside the method to abort the current operation. If it is a segmented archive callback object,
a CZipException with CZipException::aborted code will be thrown, otherwise the code will be CZipException::abortedAction or CZipException::abortedSafely.
The following actions can be safely aborted (without corrupting the archive):
- counting bytes before deleting files
- testing
- saving the central directory in a not segmented archive
(saved data is removed in case of break and you can save it again).
If the archive is segmented and if saving is aborted, the archive
will not be damaged, but saved part of the central directory will be not removed
and the new central directory will have to be saved after it.
\param uProgress
The value depends on the type of the operation.
\return
\c false to abort the current operation; \c true to continue it.
\note
Override this method in the derived class. If you define this method inside the class declaration, consider inlining
it to make the action progress faster.
\see
CZipSegmCallback
*/
virtual bool Callback(ZIP_SIZE_TYPE uProgress) = 0;
/**
Stored the filename of an external file, if the action (adding, extracting or segmentation) uses such a file.
*/
CZipString m_szExternalFile;
virtual ~CZipCallback(){}
};
/**
When you derive from CZipSegmCallback, you can use the derived class as a callback object for:
- the disk change notification in a spanned archive,
- notification about the next part being processed in a split archive.
You need to override the CZipActionCallback::Callback method.
The value of the \a uProgress parameter in the callback method has the following meaning:
- the minimum number of free bytes required on the disk when writing a spanned archive
- it is set to \c 0 when reading a spanned archive
- when writing or reading a split archive it is set to \c 0 apart for the last volume when it is set to \c ZIP_SPLIT_LAST_VOLUME
Return \c false from the callback function to abort the operation: the proper exception will be thrown.
\see
<a href="kb">0610051553|span</a>
\see
CZipActionCallback::Callback
\see
CZipArchive::SetSegmCallback
*/
struct ZIP_API CZipSegmCallback : public CZipCallback
{
/**
Values indicating the reason for calling the callback.
*/
enum SegmCodes
{
scVolumeNeededForRead, ///< The next volume is needed when reading a segmented archive. The number of the volume is stored in #m_uVolumeNeeded.
scVolumeNeededForWrite, ///< The next volume is needed when writing a segmented archive. The number of the volume is stored in #m_uVolumeNeeded.
scFileNameDuplicated, ///< The file used for writing a new volume already exists.
scCannotSetVolLabel, ///< The disk label could not be set. The disk may be write-protected. Called only for spanned archives.
scFileCreationFailure, ///< The archive file could not be created. The disk may be write-protected.
scFileNotFound, ///< The given volume file was not found when reading a split archive. The number of the volume is stored in #m_uVolumeNeeded. Called only for split archives.
};
ZIP_VOLUME_TYPE m_uVolumeNeeded; ///< The number of the volume needed when reading or writing a segmented archive. Volumes are numbered starting from 1.
int m_iCode; ///< The reason for calling the callback. Can be one of the #SegmCodes values.
};
/**
When you derive from CZipActionCallback, you can use the new class as a callback object when adding, extracting, deleting, testing files
or saving the central directory.
You need to override the CZipActionCallback::Callback method.
The value of the \a uProgress parameter in the callback method is the amount of data just processed.
\see
<a href="kb">0610231200</a>
\see
CZipActionCallback::Callback
\see
CZipArchive::SetCallback
*/
struct ZIP_API CZipActionCallback : public CZipCallback
{
friend class CZipArchive;
friend class CZipCentralDir;
/**
Values used for specifying a callback type in the CZipArchive::SetCallback method.
You can assign several values to the same callback object (use the logical \c OR).
\see
<a href="kb">0610231200</a>
\see
CZipArchive::SetCallback
\see
CZipActionCallback
*/
enum CallbackType
{
/**
Not used.
You can use it for your own purposes.
*/
cbNothing = 0x0000,
/**
Compressing a file.
The callback called when adding a file with one of the CZipArchive::AddNewFile methods.
*/
cbAdd = 0x0001,
/**
Moving a file from a temporary archive.
The callback called while adding a file (only on a segmented archive) when the smartness level contains
CZipArchive::zipsmCheckForEff or CZipArchive::zipsmCheckForEffInMem
and if the just compressed file is being moved from a temporary place (file or memory) to the archive.
*/
cbAddTmp = 0x0002,
/**
Storing a file.
The callback called while adding a file and if its compressing has proven to be inefficient
and it is now being stored (instead of compressed) in the archive. The smartness level must
contain CZipArchive::zipsmCheckForEff or CZipArchive::zipsmCheckForEffInMem. The archive can be
segmented or not.
*/
cbAddStore = 0x0004,
/**
Extracting a file.
The callback called when extracting a file with one of the CZipArchive::ExtractFile methods.
*/
cbExtract = 0x0008,
/**
Counting data to process before deleting.
The callback called before the actual deletion takes place and the map of holes and continuous
areas is being created. It is safe to abort the operation (by returning \c false from
the callback method).
*/
cbDeleteCnt = 0x0010,
/**
Deleting files.
The callback called when moving data while deleting file(s) with the CZipArchive::RemoveFile
method or one of the CZipArchive::RemoveFiles methods.
*/
cbDelete = 0x0020,
/**
Testing a file.
The callback called when testing a file with the CZipArchive::TestFile method.
*/
cbTest = 0x0040,
/**
Saving the central directory.
The callback called when saving the central directory with the CZipCentralDir::Write method
(usually on close or flush). It is safe to abort the operation on a segmented archive -
the saved part of the central directory will be removed from disk.
*/
cbSave = 0x0080,
/**
Getting a file from another archive.
The callback called when using one of the CZipArchive::GetFromArchive methods.
*/
cbGet = 0x0100,
/**
Renaming a file.
The callback called when during renaming a file there is a need to make less or more space
for the new filename.
*/
cbRename = 0x0200,
/**
Moving data.
The callback called when moving data inside the archive. It happens while replacing files to make less or more space
for the new file or while shifting data with the CZipArchive::ShiftData() method.
*/
cbMoveData = 0x0400,
/**
The callback called when counting files and bytes to process when performing multiple actions.
When this callback is called, CZipActionCallback::m_uTotalToProcess is
not set (because it is not known and that's why the counting is performed),
but it allows to abort the counting process.
*/
cbCalculateForMulti= 0x0800,
/**
The callback called when adding multiple files with one of the CZipArchive::AddNewFiles
methods. This callback also registers for #cbAdd.
\see
<a href="kb">0610231200|multi</a>
*/
cbMultiAdd = 0x1000 | cbAdd,
/**
The callback called when preparing existing files for encryption.
\see
<a href="kb">0610201627|existing</a>
*/
cbEncryptPrepare= 0x2000,
/**
The callback called in order to report the progress of making space inside the archive before the actual encryption takes place.
\see
<a href="kb">0610201627|existing</a>
*/
cbEncryptMoveData= 0x4000,
/**
The callback called for every file being encrypted.
\see
<a href="kb">0610201627|existing</a>
*/
cbEncrypt = 0x8000,
/**
The callback called when encrypting existing files in the archive. This callback also registers for #cbEncryptMoveData and #cbEncrypt.
\see
<a href="kb">0610201627|existing</a>
\see
<a href="kb">0610231200|multi</a>
*/
cbMultiEncrypt = 0x10000 | cbEncryptMoveData | cbEncrypt,
/**
Reserved.
You can declare your own callback types above this value. Do not use the numeric value,
but the symbol name - the value may change in the future releases of the library.
*/
cbNextValue = 0x20000,
/**
All sub-actions.
Represents the sub-actions callbacks - they are called as a part of bigger actions
(#cbAddTmp | #cbAddStore | #cbDeleteCnt | #cbMoveData | #cbCalculateForMulti | #cbEncryptPrepare | #cbEncryptMoveData).
*/
cbSubActions = cbAddTmp | cbAddStore | cbDeleteCnt | cbMoveData | cbCalculateForMulti | cbEncryptPrepare | cbEncryptMoveData,
/**
Main callbacks.
Represents the main action callbacks (#cbAdd | #cbExtract | #cbDelete | #cbTest | #cbSave | #cbGet | #cbRename | #cbEncrypt).
*/
cbActions = cbAdd | cbExtract | cbDelete | cbTest | cbSave | cbGet | cbRename | cbEncrypt,
/**
Multiple action callbacks.
Represents the multiple action callbacks.
*/
cbMultiActions = cbMultiAdd | cbMultiEncrypt,
/**
All values.
Use this value to call one callback object for all callback types.
*/
cbAll = cbActions | cbSubActions | cbMultiActions
};
/**
A structure that provides global information in case of using multiple actions callbacks.
\see
<a href="kb">0610231200|multi</a>
\see
cbMultiActions
*/
struct ZIP_API CMultiActionsInfo
{
friend struct CZipActionCallback;
ZIP_SIZE_TYPE m_uTotalBytesToProcess; ///< The total number of bytes to process.
ZIP_SIZE_TYPE m_uTotalFilesToProcess; ///< The total number of files to process.
ZIP_SIZE_TYPE m_uBytesProcessed; ///< The total number of bytes processed so far.
ZIP_SIZE_TYPE m_uFilesProcessed; ///< The total number of files processed so far.
/**
Returns the number of files left to process.
\return
The number of files left to process.
*/
ZIP_SIZE_TYPE LeftFilesToProcess() const {return m_uTotalFilesToProcess - m_uFilesProcessed;}
/**
Returns the number of bytes left to process.
\return
The number of bytes left to process.
*/
ZIP_SIZE_TYPE LeftBytesToProcess() const {return m_uTotalBytesToProcess - m_uBytesProcessed;}
private:
void Init(ZIP_SIZE_TYPE uTotalItemsToProcess, ZIP_SIZE_TYPE uTotalBytesToProcess, int iReactType)
{
m_uTotalFilesToProcess = uTotalItemsToProcess;
m_uTotalBytesToProcess = uTotalBytesToProcess;
m_uBytesProcessed = m_uFilesProcessed = 0;
m_iReactType = iReactType;
m_bActive = false;
}
void OnCallbackInit(int iType)
{
// this assumes, that the callback type will stay unchanged
// between Init() and CallbackEnd()
m_bActive = iType == m_iReactType;
}
void OnCallCallback(ZIP_SIZE_TYPE uProgress)
{
if (m_bActive)
m_uBytesProcessed += uProgress;
}
bool OnNextFile()
{
if (m_bActive)
{
m_uFilesProcessed++;
return true;
}
else
return false;
}
bool m_bActive;
int m_iReactType;
};
CZipActionCallback()
{
m_uTotalToProcess = 0;
m_uProcessed = 0;
m_pMultiActionsInfo = NULL;
}
/**
Called when the multiple actions operation is about to begin. Initializes CMultiActionsInfo object.
\param uTotalFilesToProcess
The number of files to process.
\param uTotalBytesToProcess
The number of bytes to process.
\param iReactType
The type of the callback that will cause increasing of values in CMultiActionsInfo.
Can be one of #CallbackType values.
\see
<a href="kb">0610231200|multi</a>
\see
GetMultiActionsInfo
\note
When overriding this method, call the base method from your code.
*/
virtual void MultiActionsInit(ZIP_SIZE_TYPE uTotalFilesToProcess, ZIP_SIZE_TYPE uTotalBytesToProcess, int iReactType)
{
InitMultiActionsInfo();
m_pMultiActionsInfo->Init(uTotalFilesToProcess, uTotalBytesToProcess, iReactType);
}
/**
Called to initialize the callback object.
Sets the filenames and resets #m_uTotalToProcess and #m_uProcessed variables to \c 0.
#m_iType variable is already set to the proper value. Called at the beginning of the operation.
\param lpszFileInZip
The file that is being processed in the archive.
\param lpszExternalFile
The external file being processed. This is set to \c NULL, if the operation takes place in memory.
*/
virtual void Init(LPCTSTR lpszFileInZip = NULL, LPCTSTR lpszExternalFile = NULL)
{
m_szFileInZip = lpszFileInZip;
m_szExternalFile = lpszExternalFile;
m_uTotalToProcess = 0; // not yet known
m_uProcessed = 0; // nothing yet done
CacheStepSize();
ResetProgressStage();
if (m_pMultiActionsInfo)
// the type is known now
m_pMultiActionsInfo->OnCallbackInit(m_iType);
}
/**
Called after calculating the total amount of data to process.
\param uTotalToDo
Total amount of data to process. The method initializes #m_uTotalToProcess with this value.
*/
virtual void SetTotal(ZIP_SIZE_TYPE uTotalToDo)
{
m_uTotalToProcess = uTotalToDo;
// m_uProcessed = 0; // already done in CZipCallbackProvider::Get
}
/**
Called when a next action begins in multiple actions processing.
This method calls #Callback method with \a uProgress parameter set to \c 0.
\return
The value returned from the #Callback method.
\see
<a href="kb">0610231200|multi</a>
\note
When overriding this method, call the base method from your code.
*/
virtual bool MultiActionsNext()
{
if (m_pMultiActionsInfo && m_pMultiActionsInfo->OnNextFile())
return Callback(0);
else
return true;
}
/**
Called after the operation finishes.
It is not called in case of an exception, but
it is called before throwing CZipException::abortedAction or CZipException::abortedSafely.
*/
virtual void CallbackEnd()
{
//ASSERT(m_uProcessed == m_uTotalToProcess);
};
/**
Called at the end of the multiple actions operation.
Releases multiple actions information (CMultiActionsInfo).
Override this method, if you want this information to be persisted after
operation finishes. In that case, CMultiActionsInfo will be released
on destruction.
\see
<a href="kb">0610231200|multi</a>
*/
virtual void MultiActionsEnd()
{
ReleaseMultiActionsInfo();
}
/**
Gets the amount of data left to process.
\return
The amount of data left to process.
*/
ZIP_SIZE_TYPE LeftToProcess() const {return m_uTotalToProcess - m_uProcessed;}
/**
The total amount of data to process. This value is set when the #SetTotal method is called.
Depending on the action it is set then to:
- Adding a file : the size the external file being added (or if the type of the callback is CZipActionCallback::cbAddTmp,
the size of the compressed data: CZipFileHeader::m_uComprSize).
- Extracting a file : the size of the uncompressed data (CZipFileHeader::m_uUncomprSize).
- Testing a file : the same as above.
- Deleting a file : the number of bytes to move - the size of all files to remain above the first
file to delete (calculated from offsets in CZipFileHeader::m_uOffset).
- Saving the central directory : the number of files in the archive.
*/
ZIP_SIZE_TYPE m_uTotalToProcess;
ZIP_SIZE_TYPE m_uProcessed; ///< The total amount of data processed so far.
CZipString m_szFileInZip; ///< The name of the file that is being processed in the archive.
/**
The type of the callback. It is set to one of the #CallbackType values when the action begins.
It's useful, if you have more than one callback assigned to the same callback object.
*/
int m_iType;
/**
Returns the current CMultiActionsInfo object in multiple actions operation or \c NULL, if
the current operation is not one of CZipActionCallback::cbMultiActions actions.
\return
The current CMultiActionsInfo object.
\see
<a href="kb">0610231200|multi</a>
*/
CMultiActionsInfo* GetMultiActionsInfo()
{
return m_pMultiActionsInfo;
}
/**
Sets the type of the callback, that will cause the current CMultiActionsInfo object to update its progress.
\param iType
The type of the callback. It can be one of the #CallbackType values.
*/
void SetReactType(int iType)
{
m_pMultiActionsInfo->m_iReactType = iType;
}
/**
Specifies how often the Callback() method is called. The Callback() method is called every \b n-th callback request,
where \b n is the value returned from the GetStepSize() method.
Override this method to adjust the frequency of calling the callback.
\return
The value that determines the frequency of calling the Callback() method.
By default, it returns \c 256 for #cbSave, #cbDeleteCnt, #cbCalculateForMulti and #cbEncryptPrepare and \c 1
for other callback types.
\note
This method is called in the Init() method and the returned value is cached for further processing.
This means that when you override this method, even with some time-consuming operations, it will not affect
the in-action performance.
\note
Do not use a too low value, because it may increase significantly the time needed to process a huge number of files.
*/
virtual int GetStepSize()
{
return m_iType == cbSave || m_iType == cbDeleteCnt || m_iType == cbCalculateForMulti || m_iType == cbEncryptPrepare ? 256 : 1;
}
~CZipActionCallback()
{
ReleaseMultiActionsInfo();
}
/**
Called by processing classes when data processing progressed.
\param uProgress
The amount of data processed.
\return
The value returned from #Callback, if the method was called; \c true otherwise.
*/
bool RequestCallback(ZIP_SIZE_TYPE uProgress = 1)
{
if (!uProgress)
return true;
if (m_iCachedStepSize == 1)
return CallCallback(uProgress);
else
{
m_uAccumulatedProgress += uProgress;
if (m_iCurrentStep >= m_iCachedStepSize)
{
bool ret = CallCallback(m_uAccumulatedProgress);
ResetProgressStage();
return ret;
}
else
{
m_iCurrentStep++;
return true;
}
}
}
/**
Called by processing classes when data processing has finished to
allow calling the Callback() method for the amount of processed data for
which the Callback() has not been called. This usually happens,
when GetStepSize() does not return 1.
\param uProgress
The amount of data processed.
\return
The value returned from the #Callback method, if the method was called; \c true otherwise.
*/
bool RequestLastCallback(ZIP_SIZE_TYPE uProgress = 0)
{
bool ret;
if (m_uAccumulatedProgress == 0 && uProgress == 0)
ret = true;
else
ret = CallCallback(m_uAccumulatedProgress + uProgress);
ResetProgressStage();
return ret;
}
protected:
/**
Calls the Callback() method internally, increases CZipActionCallback::m_uProcessed and lets the CZipActionCallback
increase its values, if needed.
\param uProgress
The amount of data processed.
\return
The return value from the Callback() method.
*/
virtual bool CallCallback(ZIP_SIZE_TYPE uProgress)
{
m_uProcessed += uProgress;
if (m_pMultiActionsInfo)
m_pMultiActionsInfo->OnCallCallback(uProgress);
return Callback(uProgress);
}
/**
Caches the value returned from the GetStepSize() method. Called in the Init()method.
*/
void CacheStepSize()
{
m_iCachedStepSize = GetStepSize();
if (m_iCachedStepSize == 0)
m_iCachedStepSize = 1;
}
/**
Initializes the values that depend on the frequency of calling the Callback() method.
Called with every call to the Callback() method.
\see
GetStepSize
*/
void ResetProgressStage()
{
m_iCurrentStep = 1;
m_uAccumulatedProgress = 0;
}
private:
CMultiActionsInfo* m_pMultiActionsInfo;
void InitMultiActionsInfo()
{
ReleaseMultiActionsInfo();
m_pMultiActionsInfo = new CMultiActionsInfo();
}
void ReleaseMultiActionsInfo()
{
if (m_pMultiActionsInfo != NULL)
{
delete m_pMultiActionsInfo;
m_pMultiActionsInfo = NULL;
}
}
int m_iCachedStepSize; ///< The cached step value for the time of processing.
int m_iCurrentStep;
ZIP_SIZE_TYPE m_uAccumulatedProgress;
};
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning (pop)
#endif
#endif

View File

@@ -0,0 +1,90 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipCallbackProvider.h
* Includes the ZipArchiveLib::CZipCallbackProvider class.
*
*/
#if !defined(ZIPARCHIVE_ZIPCALLBACKPROVIDER_DOT_H)
#define ZIPARCHIVE_ZIPCALLBACKPROVIDER_DOT_H
#if _MSC_VER > 1000
#pragma once
#if defined ZIP_HAS_DLL
#pragma warning (push)
#pragma warning( disable : 4275 ) // non dll-interface used as base for dll-interface class
#endif
#endif
#include "ZipCallback.h"
#include "ZipExport.h"
#include "ZipCollections.h"
namespace ZipArchiveLib
{
/**
The storage for callback objects. A structure for the internal use only.
\see
CZipArchive::SetCallback
CZipArchive::GetCallback
*/
class ZIP_API CZipCallbackProvider : public CZipMap<CZipActionCallback::CallbackType, CZipActionCallback*>
{
public:
void Set(CZipActionCallback* pCallback, int iWhich)
{
CZipActionCallback::CallbackType cbs[] = {CZipActionCallback::cbAdd, CZipActionCallback::cbAddTmp, CZipActionCallback::cbAddStore, CZipActionCallback::cbExtract, CZipActionCallback::cbDeleteCnt, CZipActionCallback::cbDelete, CZipActionCallback::cbTest, CZipActionCallback::cbSave, CZipActionCallback::cbGet, CZipActionCallback::cbRename, CZipActionCallback::cbMoveData, CZipActionCallback::cbCalculateForMulti, CZipActionCallback::cbMultiAdd, CZipActionCallback::cbEncryptPrepare, CZipActionCallback::cbEncryptMoveData, CZipActionCallback::cbEncrypt, CZipActionCallback::cbMultiEncrypt};
int iCount = sizeof(cbs)/sizeof(CZipActionCallback::CallbackType);
for (int i = 0; i < iCount; i++)
{
CZipActionCallback::CallbackType iCallback = cbs[i];
if (iWhich & iCallback)
SetInternal(pCallback, iCallback);
}
}
CZipActionCallback* Get(CZipActionCallback::CallbackType iType)
{
CZipActionCallback* pCallback = NULL;
if (Lookup(iType, pCallback))
{
pCallback->m_iType = iType;
return pCallback;
}
else
return NULL;
}
protected:
void SetInternal(CZipActionCallback* pCallback, CZipActionCallback::CallbackType iType)
{
if (pCallback)
{
SetAt(iType, pCallback);
}
else
RemoveKey(iType);
}
};
} // namespace
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning (pop)
#endif
#endif // !defined(ZIPARCHIVE_ZIPCALLBACKPROVIDER_DOT_H)

View File

@@ -0,0 +1,955 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
//#include <string>
#include "ZipCentralDir.h"
#include "ZipArchive.h"
#include "ZipFileMapping.h"
#include "ZipPlatform.h"
#include "BytesWriter.h"
#define CENTRAL_DIR_END_SIZE 22
using namespace ZipArchiveLib;
char CZipCentralDir::m_gszSignature[] = {0x50, 0x4b, 0x05, 0x06};
char CZipCentralDir::m_gszSignature64Locator[] = {0x50, 0x4b, 0x06, 0x07};
CZipCentralDir::CZipCentralDir()
{
m_pInfo = NULL;
m_pHeaders = NULL;
m_pFindArray = NULL;
m_pStorage = NULL;
m_pOpenedFile = NULL;
m_iIgnoredChecks = 0;
m_pCallbacks = NULL;
}
void CZipCentralDir::Init(CZipStorage* pStorage, ZipArchiveLib::CZipCallbackProvider* pCallbacks, CZipStringStoreSettings* pStringSettings, CZipCentralDir* pSource)
{
m_pStorage = pStorage;
m_pCallbacks = pCallbacks;
m_pStringSettings = pStringSettings;
m_pOpenedFile = NULL;
m_iIgnoredChecks = CZipArchive::checkIgnoredByDefault;
// just in case
DestroySharedData();
if (pSource != NULL)
{
#ifdef ZIP_ARCHIVE_USE_LOCKING
pSource->LockAccess();
#endif
m_pInfo = pSource->m_pInfo;
m_pInfo->m_iReference++;
m_pHeaders = pSource->m_pHeaders;
m_pFindArray = pSource->m_pFindArray;
#ifdef ZIP_ARCHIVE_USE_LOCKING
// points to the same object now
UnlockAccess();
#endif
m_pStorage->UpdateSegmMode(m_pInfo->m_uLastVolume);
m_pStorage->m_uBytesBeforeZip = pSource->m_pStorage->m_uBytesBeforeZip;
}
else
CreateSharedData();
}
CZipCentralDir::~CZipCentralDir()
{
DestroySharedData();
}
void CZipCentralDir::Read(bool bExhaustiveRead)
{
if (!m_pStorage)
{
ASSERT(FALSE);
return;
}
m_pStorage->m_pFile->SeekToEnd();
// maximum size of end of central dir record
m_pInfo->m_uEndOffset = (ZIP_SIZE_TYPE)m_pStorage->LocateSignature(m_gszSignature, 0xFFFF + CENTRAL_DIR_END_SIZE);
if (m_pInfo->m_uEndOffset == CZipStorage::SignatureNotFound)
ThrowError(CZipException::cdirNotFound);
m_pStorage->m_pFile->Seek((ZIP_FILE_USIZE)(m_pInfo->m_uEndOffset + 4));
CZipAutoBuffer buf(CENTRAL_DIR_END_SIZE);
// we can skip the signature, we already know it is good - it was found
int uRead = m_pStorage->m_pFile->Read(buf, CENTRAL_DIR_END_SIZE - 4);
if (uRead != CENTRAL_DIR_END_SIZE - 4)
ThrowError(CZipException::badZipFile);
WORD uCommentSize;
CBytesWriter::ReadBytes(m_pInfo->m_uLastVolume, buf, 2);
CBytesWriter::ReadBytes(m_pInfo->m_uVolumeWithCD, buf + 2, 2);
CBytesWriter::ReadBytes(m_pInfo->m_uVolumeEntriesNo,buf + 4, 2);
CBytesWriter::ReadBytes(m_pInfo->m_uEntriesNumber,buf + 6, 2);
CBytesWriter::ReadBytes(m_pInfo->m_uSize, buf + 8, 4);
CBytesWriter::ReadBytes(m_pInfo->m_uOffset, buf + 12, 4);
CBytesWriter::ReadBytes(uCommentSize, buf + 16);
buf.Release();
if (uCommentSize)
{
m_pInfo->m_pszComment.Allocate(uCommentSize);
uRead = m_pStorage->m_pFile->Read(m_pInfo->m_pszComment, uCommentSize);
if (uRead != uCommentSize)
ThrowError(CZipException::badZipFile);
}
if ( m_pInfo->NeedsZip64() )
{
m_pStorage->m_pFile->Seek((ZIP_FILE_USIZE)(m_pInfo->m_uEndOffset));
ULONGLONG uPosition = m_pStorage->LocateSignature(m_gszSignature64Locator, ZIP_SIZE_TYPE(-1));
if (uPosition != CZipStorage::SignatureNotFound)
ThrowError(CZipException::noZip64);
// when the zip64 locator is not found, try to treat this archive as normal
}
// if m_uLastVolume is not zero, it is enough to say that it is a multi-volume archive
ASSERT((!m_pInfo->m_uLastVolume && (m_pInfo->m_uEntriesNumber == m_pInfo->m_uVolumeEntriesNo) && !m_pInfo->m_uVolumeWithCD) || m_pInfo->m_uLastVolume);
m_pStorage->UpdateSegmMode(m_pInfo->m_uLastVolume);
if (!m_pStorage->IsSegmented() && !m_pInfo->CheckIfOK_1())
ThrowError(CZipException::badZipFile);
if (m_pStorage->m_uBytesBeforeZip == 0 && m_pInfo->m_uLastVolume == 0)
m_pStorage->m_uBytesBeforeZip = m_pInfo->CalculateBytesBeforeZip();
if (!m_pInfo->CheckIfOK_2())
ThrowError(CZipException::badZipFile);
m_pInfo->m_bInArchive = true;
m_pStorage->ChangeVolume(m_pInfo->m_uVolumeWithCD);
if (!m_pInfo->m_uSize)
return;
ReadHeaders(bExhaustiveRead);
}
void CZipCentralDir::ThrowError(int err) const
{
CZipException::Throw(err, m_pStorage->m_pFile->GetFilePath());
}
void CZipCentralDir::ReadHeaders(bool bExhaustiveRead)
{
m_pStorage->Seek(m_pInfo->m_uOffset);
RemoveHeaders(); //just in case
for (ZIP_INDEX_TYPE i = 0; i < m_pInfo->m_uEntriesNumber; i++)
{
CZipFileHeader* pHeader = new CZipFileHeader;
m_pHeaders->Add(pHeader);
if (!pHeader->Read(*this, true))
ThrowError(CZipException::badZipFile);
}
if (bExhaustiveRead)
{
ZIP_FILE_USIZE uPosition = m_pStorage->m_pFile->GetPosition();
// different offset, or different parts
if (uPosition != m_pInfo->m_uEndOffset || m_pStorage->IsSegmented() && m_pStorage->GetCurrentVolume() != m_pInfo->m_uLastVolume)
for(;;)
{
CZipAutoBuffer buf(4);
m_pStorage->Read(buf, 4, true);
if (!CZipFileHeader::VerifySignature(buf))
break;
CZipFileHeader* pHeader = new CZipFileHeader;
m_pHeaders->Add(pHeader);
if (!pHeader->Read(*this, false))
ThrowError(CZipException::badZipFile);
}
}
// this is necessary when removing data descriptors, CZipArchive::MakeSpaceForReplace, deleting, replacing or encrypting files
// sort always, to yield the same results in requesting files by index regardless of the reason for opening
m_pHeaders->Sort(CompareHeaders);
RebuildFindFastArray();
}
void CZipCentralDir::Close()
{
m_pOpenedFile = NULL;
DestroySharedData();
// do not reference it anymore
m_pInfo = NULL;
m_pHeaders = NULL;
m_pFindArray = NULL;
}
bool CZipCentralDir::IsValidIndex(ZIP_INDEX_TYPE uIndex)const
{
return uIndex < (ZIP_INDEX_TYPE)m_pHeaders->GetSize() && uIndex != ZIP_FILE_INDEX_UNSPECIFIED;
}
void CZipCentralDir::OpenFile(ZIP_INDEX_TYPE uIndex)
{
CZipFileHeader* pOpenedFile = (*this)[uIndex];
m_pStorage->ChangeVolume(pOpenedFile->m_uVolumeStart);
m_pStorage->Seek(pOpenedFile->m_uOffset);
if (!pOpenedFile->ReadLocal(*this))
ThrowError(CZipException::badZipFile);
m_pOpenedFile = pOpenedFile;
}
void CZipCentralDir::CloseFile(bool skipCheckingDataDescriptor)
{
if (!m_pOpenedFile)
return;
if (!skipCheckingDataDescriptor && IsConsistencyCheckOn(CZipArchive::checkDataDescriptor)
&& !m_pOpenedFile->CheckDataDescriptor(m_pStorage))
ThrowError(CZipException::badZipFile);
m_pOpenedFile = NULL;
}
// add new header using the argument as a template
CZipFileHeader* CZipCentralDir::AddNewFile(const CZipFileHeader & header, ZIP_INDEX_TYPE uReplaceIndex, int iLevel, bool bRichHeaderTemplateCopy)
{
// copy some of the template data
m_pOpenedFile = NULL;
ZIP_INDEX_TYPE uIndex;
CZipFileHeader* pHeader = new CZipFileHeader();
try
{
pHeader->m_uMethod = header.m_uMethod;
pHeader->m_uModDate = header.m_uModDate;
pHeader->m_uModTime = header.m_uModTime;
pHeader->m_uExternalAttr = header.m_uExternalAttr;
pHeader->m_uLocalComprSize = header.m_uLocalComprSize;
pHeader->m_uLocalUncomprSize = header.m_uLocalUncomprSize;
if (header.m_pszFileName != NULL)
pHeader->m_pszFileName = new CZipString(*header.m_pszFileName);
pHeader->m_pszFileNameBuffer = header.m_pszFileNameBuffer;
pHeader->m_pszComment = header.m_pszComment;
pHeader->m_aLocalExtraData = header.m_aLocalExtraData;
// local will be removed in a moment in PrepareData
pHeader->m_aCentralExtraData = header.m_aCentralExtraData;
pHeader->m_aCentralExtraData.RemoveInternalHeaders();
pHeader->SetSystemCompatibility(header.GetSystemCompatibility());
pHeader->m_uEncryptionMethod = header.m_uEncryptionMethod;
// current settings
pHeader->m_stringSettings = *m_pStringSettings;
// set only when adding a new file, not in PrepareData (which may be called under different circumstances)
// we need the proper encryption method to be set already
RemoveFromDisk();
bool bReplace = IsValidIndex(uReplaceIndex);
pHeader->PrepareData(iLevel, m_pStorage->IsSegmented() != 0);
if (bRichHeaderTemplateCopy)
{
// call here, because PrepareData will zero them
pHeader->m_uCrc32 = header.m_uCrc32;
pHeader->m_uComprSize = header.m_uComprSize;
pHeader->m_uUncomprSize = header.m_uUncomprSize;
}
// local extra field is updated if needed, so we can check the lengths
if (!pHeader->CheckLengths(true))
ThrowError(CZipException::tooLongData);
// now that everything is all right, we can add the new file
if (bReplace)
{
CZipFileHeader* pfh = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)uReplaceIndex];
m_pStorage->Seek(pfh->m_uOffset);
RemoveFile(pfh, uReplaceIndex, false);
m_pHeaders->InsertAt((ZIP_ARRAY_SIZE_TYPE)uReplaceIndex, pHeader);
m_pOpenedFile = pHeader;
uIndex = uReplaceIndex;
}
else
{
uIndex = (ZIP_INDEX_TYPE)m_pHeaders->Add(pHeader);
m_pOpenedFile = pHeader;
m_pStorage->m_pFile->SeekToEnd();
}
}
catch(...)
{
// otherwise it is added to the collection and will be auto-deleted
if (pHeader != NULL && m_pOpenedFile == NULL)
delete pHeader;
throw;
}
if (m_pInfo->m_bFindFastEnabled)
InsertFindFastElement(pHeader, uIndex); // GetCount > 0, because we have just added a header
return pHeader;
}
void CZipCentralDir::SetComment(LPCTSTR lpszComment)
{
ZipCompatibility::ConvertStringToBuffer(lpszComment, m_pInfo->m_pszComment, m_pStringSettings->m_uCommentCodePage);
RemoveFromDisk();
}
bool CZipCentralDir::SetFileComment(ZIP_INDEX_TYPE uIndex, LPCTSTR lpszComment)
{
if (!IsValidIndex(uIndex))
{
ASSERT(FALSE);
return false;
}
CZipFileHeader* pHeader = (*this)[uIndex];
pHeader->m_stringSettings.m_uCommentCodePage = m_pStringSettings->m_uCommentCodePage;
pHeader->SetComment(lpszComment);
RemoveFromDisk();
return true;
}
void CZipCentralDir::RemoveFromDisk()
{
if (m_pInfo->m_bInArchive)
{
ASSERT(!m_pStorage->IsSegmented()); // you can't add files to an existing segmented archive or to delete them from it
m_pStorage->m_pFile->SetLength((ZIP_FILE_USIZE)(m_pStorage->m_uBytesBeforeZip + m_pInfo->m_uOffset));
m_pInfo->m_bInArchive = false;
}
else
m_pStorage->Flush(); // if remove from disk is requested, then the archive modification will follow, so flush the buffers
}
void CZipCentralDir::CloseNewFile()
{
m_pOpenedFile->OnNewFileClose(m_pStorage);
m_pOpenedFile = NULL;
}
void CZipCentralDir::Write()
{
if (m_pInfo->m_bInArchive)
return;
m_pInfo->m_uEntriesNumber = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();
if (!m_pStorage->IsSegmented())
{
m_pStorage->Flush();
m_pStorage->m_pFile->SeekToEnd();
}
// else
// we are at the end already
m_pInfo->m_uSize = 0;
bool bDontAllowVolumeChange = false;
if (m_pStorage->IsSegmented())
{
// segmentation signature at the beginning (4 bytes) + the size of the data descr. for each file
ZIP_SIZE_TYPE uSize = GetSize(true);
// if there is a segmented archive in creation and it is only one-volume,
// (current volume number is 0 so far, no bytes has been written so we know they are
// all in the buffer) make sure that it will be after writing central dir
// and make it a not segmented archive
if (m_pStorage->GetCurrentVolume() == 0)
{
// calculate the size of data descriptors already in the buffer or on the disk
// (they will be removed in the not segmented archive).
ZIP_SIZE_TYPE uToGrow = uSize - 4;
for (ZIP_INDEX_TYPE i = 0; i < m_pInfo->m_uEntriesNumber; i++)
{
CZipFileHeader* pHeader = (*this)[i];
if (pHeader->NeedsDataDescriptor())
{
if (!pHeader->IsEncrypted())
uToGrow -= 4; // remove the signature only
}
else
uToGrow -= pHeader->GetDataDescriptorSize(true);
}
ZIP_SIZE_TYPE uVolumeFree = m_pStorage->VolumeLeft();
if (uVolumeFree >= uToGrow)
// lets make sure it will be one-volume archive
{
// can the operation be done only in the buffer?
if (!m_pStorage->m_uBytesWritten && // no bytes on the disk yet
(m_pStorage->GetFreeInBuffer() >= uToGrow)) // is the buffer big enough?
{
RemoveDataDescr(true);
bDontAllowVolumeChange = true; // if a volume change occurs somehow, we'll throw an error later
}
else
{
m_pStorage->Flush();
if (RemoveDataDescr(false))
bDontAllowVolumeChange = true; // if a volume change occurs somehow, we'll throw an error later
}
}
}
// make sure that in a segmented archive, the whole central directory will fit on the single volume
if (!bDontAllowVolumeChange)
m_pStorage->AssureFree(uSize);
}
try
{
WriteHeaders(bDontAllowVolumeChange || !m_pStorage->IsSegmented());
WriteCentralEnd();
if (bDontAllowVolumeChange)
{
if (m_pStorage->GetCurrentVolume() != 0)
ThrowError(CZipException::badZipFile);
}
}
catch (...)
{
if (bDontAllowVolumeChange)
{
m_pStorage->FinalizeSegm();
m_pInfo->m_uLastVolume = 0;
}
throw;
}
m_pInfo->m_bInArchive = true;
}
void CZipCentralDir::WriteHeaders(bool bOneDisk)
{
CZipActionCallback* pCallback = m_pCallbacks->Get(CZipActionCallback::cbSave);
m_pInfo->m_uVolumeEntriesNo = 0;
m_pInfo->m_uVolumeWithCD = m_pStorage->GetCurrentVolume();
m_pInfo->m_uOffset = m_pStorage->GetPosition();
if (!m_pInfo->m_uEntriesNumber)
return;
ZIP_VOLUME_TYPE uDisk = m_pInfo->m_uVolumeWithCD;
if (pCallback)
{
pCallback->Init();
pCallback->SetTotal(m_pInfo->m_uEntriesNumber);
}
int iAborted = 0;
if (m_pInfo->m_uEntriesNumber > 0)
{
ZIP_INDEX_TYPE uLast = (ZIP_INDEX_TYPE)(m_pInfo->m_uEntriesNumber - 1);
ZIP_INDEX_TYPE i = 0;
for (;;)
{
CZipFileHeader* pHeader = (*this)[i];
m_pInfo->m_uSize += pHeader->Write(m_pStorage);
if (m_pStorage->GetCurrentVolume() != uDisk)
{
m_pInfo->m_uVolumeEntriesNo = 1;
uDisk = m_pStorage->GetCurrentVolume();
// update the information about the offset and starting volume if the
// first header was written in the new volume
if (i == 0)
{
m_pInfo->m_uOffset = 0;
m_pInfo->m_uVolumeWithCD = uDisk;
}
}
else
m_pInfo->m_uVolumeEntriesNo++;
if (pCallback)
{
bool ret, last;
if (i == uLast)
{
ret = pCallback->RequestLastCallback(1);
last = true;
}
else
{
ret = pCallback->RequestCallback();
last = false;
}
if (ret)
{
if (last)
break;
}
else
{
if (bOneDisk)
{
ASSERT(!m_pStorage->IsSegmented());
// if segmented, would need to m_pStorage->Flush(), but the headers can span multiple volumes
m_pStorage->EmptyWriteBuffer();
// remove saved part from the volume
m_pStorage->m_pFile->SetLength((ZIP_FILE_USIZE)(m_pStorage->m_uBytesBeforeZip + m_pInfo->m_uOffset));
// We can now abort safely
iAborted = CZipException::abortedSafely;
}
else
iAborted = CZipException::abortedAction;
break;
}
}
else if (i == uLast)
break;
i++;
}
}
if (pCallback)
{
pCallback->CallbackEnd();
if (iAborted)
ThrowError(iAborted);
}
}
void CZipCentralDir::WriteCentralEnd()
{
ZIP_SIZE_TYPE uSize = CENTRAL_DIR_END_SIZE + m_pInfo->m_pszComment.GetSize();
CZipAutoBuffer buf((DWORD)uSize);
char* pBuf = buf;
ZIP_VOLUME_TYPE uDisk = m_pStorage->GetCurrentVolume();
if (m_pStorage->IsSegmented() != 0)
{
// update the volume number
m_pStorage->AssureFree(uSize);
m_pInfo->m_uLastVolume = m_pStorage->GetCurrentVolume();
}
if (m_pInfo->m_uLastVolume != uDisk)
m_pInfo->m_uVolumeEntriesNo = 0;
WORD uCommentSize = (WORD)m_pInfo->m_pszComment.GetSize();
memcpy(pBuf, m_gszSignature, 4);
CBytesWriter::WriteBytes(pBuf + 4, CBytesWriter::WriteSafeU16(m_pInfo->m_uLastVolume));
CBytesWriter::WriteBytes(pBuf + 6, CBytesWriter::WriteSafeU16(m_pInfo->m_uVolumeWithCD));
CBytesWriter::WriteBytes(pBuf + 8, CBytesWriter::WriteSafeU16(m_pInfo->m_uVolumeEntriesNo));
CBytesWriter::WriteBytes(pBuf + 10, CBytesWriter::WriteSafeU16(m_pInfo->m_uEntriesNumber));
CBytesWriter::WriteBytes(pBuf + 12, CBytesWriter::WriteSafeU32(m_pInfo->m_uSize));
CBytesWriter::WriteBytes(pBuf + 16, CBytesWriter::WriteSafeU32(m_pInfo->m_uOffset));
CBytesWriter::WriteBytes(pBuf + 20, uCommentSize);
memcpy(pBuf + 22, m_pInfo->m_pszComment, uCommentSize);
if (uSize > (DWORD)(-1))
CZipException::Throw(CZipException::internalError);
m_pStorage->Write(buf, (DWORD)uSize, true);
}
void CZipCentralDir::RemoveAll()
{
ClearFindFastArray();
RemoveHeaders();
}
void CZipCentralDir::RemoveFile(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex, bool bShift)
{
if (uIndex == ZIP_FILE_INDEX_UNSPECIFIED)
{
// we need to know the index to remove
ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();
for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
if (pHeader == (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i])
{
uIndex = i;
break;
}
}
ASSERT(uIndex != ZIP_FILE_INDEX_UNSPECIFIED || pHeader);
if (!pHeader)
pHeader = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)uIndex];
if (m_pInfo->m_bFindFastEnabled)
{
ZIP_INDEX_TYPE i = FindFileNameIndex(pHeader->GetFileName());
ASSERT(i != ZIP_FILE_INDEX_NOT_FOUND);
CZipFindFast* pFindFast = (*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)i];
ZIP_INDEX_TYPE uBorderIndex = pFindFast->m_uIndex;
delete pFindFast;
pFindFast = NULL;
m_pFindArray->RemoveAt((ZIP_ARRAY_SIZE_TYPE)i);
// shift down the indexes
if (bShift)
{
ZIP_INDEX_TYPE uSize = (ZIP_INDEX_TYPE)m_pFindArray->GetSize();
for (ZIP_INDEX_TYPE j = 0; j < uSize; j++)
{
if ((*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)j]->m_uIndex > uBorderIndex)
(*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)j]->m_uIndex--;
}
}
}
if (uIndex != ZIP_FILE_INDEX_UNSPECIFIED)
{
delete pHeader;
m_pHeaders->RemoveAt((ZIP_ARRAY_SIZE_TYPE)uIndex);
}
}
void CZipCentralDir::RemoveLastFile(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex)
{
if (uIndex == ZIP_FILE_INDEX_UNSPECIFIED)
{
if (m_pHeaders->GetSize() == 0)
return;
uIndex = (ZIP_VOLUME_TYPE)(m_pHeaders->GetSize() - 1);
}
if (!pHeader)
pHeader = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)uIndex];
ZIP_SIZE_TYPE uNewSize = pHeader->m_uOffset + m_pStorage->m_uBytesBeforeZip;
// then remove
RemoveFile(pHeader, uIndex);
m_pStorage->Flush();
m_pStorage->m_pFile->SetLength((ZIP_FILE_USIZE)uNewSize);
m_pInfo->m_bInArchive = false; // it is true when AutoFlush is set to true
}
ZIP_SIZE_TYPE CZipCentralDir::GetSize(bool bWhole) const
{
ZIP_SIZE_TYPE uTotal = CENTRAL_DIR_END_SIZE + m_pInfo->m_pszComment.GetSize();
ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();
if (bWhole)
{
for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
{
const CZipFileHeader* pHeader = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i];
uTotal += pHeader->GetSize();
}
}
return uTotal;
}
bool CZipCentralDir::RemoveDataDescr(bool bFromBuffer)
{
// this will not work if there are bytes before zip
CZipFileMapping fm;
char* pFile;
ZIP_SIZE_TYPE uSize;
if (bFromBuffer)
{
uSize = m_pStorage->m_uBytesInWriteBuffer;
pFile = m_pStorage->m_pWriteBuffer;
}
else
{
uSize = (ZIP_SIZE_TYPE)m_pStorage->m_pFile->GetLength();
// we cannot use CZipMemFile in multi-volume archive
// so it must be CZipFile
if (!fm.CreateMapping(static_cast<CZipFile*>(m_pStorage->m_pFile)))
return false;
pFile = fm.GetMappedMemory();
}
ZIP_SIZE_TYPE uOffsetToChange = 4;
ZIP_SIZE_TYPE uPosInBuffer = 0;
WORD uExtraHeaderLen;
ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();
for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
{
CZipFileHeader* pHeader = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i];
char* pSour = pFile + pHeader->m_uOffset;
if (pHeader->NeedsDataDescriptor())
uExtraHeaderLen = (WORD)(pHeader->IsEncrypted() ? 0 : 4);
else
{
uExtraHeaderLen = pHeader->GetDataDescriptorSize(true);
// removing data descriptor
pHeader->m_uFlag &= ~8;
// update local header:
// write modified flag in the local header
CBytesWriter::WriteBytes(pSour + 6, pHeader->m_uFlag);
pHeader->WriteSmallDataDescriptor(pSour + 14, false);
}
ZIP_SIZE_TYPE uToCopy = (i == (uCount - 1) ? uSize : (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)(i + 1)]->m_uOffset)
- pHeader->m_uOffset - uExtraHeaderLen;
if (uToCopy > 0)
// TODO: [postponed] the size_t limit on uToCopy, but creating such a big segment is unlikely (at least at the moment of writing)
memmove(pFile + uPosInBuffer, pSour, (size_t)uToCopy);
uPosInBuffer += uToCopy;
pHeader->m_uOffset -= uOffsetToChange;
uOffsetToChange += uExtraHeaderLen;
}
if (bFromBuffer)
m_pStorage->m_uBytesInWriteBuffer = (DWORD)uPosInBuffer;
else
{
m_pStorage->m_uBytesWritten = uPosInBuffer;
fm.RemoveMapping();
m_pStorage->m_pFile->SetLength((ZIP_FILE_USIZE)uPosInBuffer);
}
return true;
}
void CZipCentralDir::RemoveHeaders()
{
ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();
for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
delete (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i];
m_pHeaders->RemoveAll();
}
void CZipCentralDir::BuildFindFastArray( bool bCaseSensitive )
{
ClearFindFastArray();
m_pInfo->m_bCaseSensitive = bCaseSensitive;
// for later
m_pInfo->m_pCompare = GetCZipStrCompFunc(bCaseSensitive);
ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();
for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
m_pFindArray->Add(new CZipFindFast((*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i], i));
m_pFindArray->Sort(bCaseSensitive ? CompareFindFastCollate : CompareFindFastCollateNoCase);
}
void CZipCentralDir::EnableFindFast(bool bEnable, bool bCaseSensitive)
{
if (m_pInfo->m_bFindFastEnabled == bEnable)
return;
m_pInfo->m_bFindFastEnabled = bEnable;
if (bEnable)
BuildFindFastArray(bCaseSensitive);
else
m_pFindArray->RemoveAll();
}
ZIP_INDEX_TYPE CZipCentralDir::FindFile(LPCTSTR lpszFileName, bool bCaseSensitive, bool bSporadically, bool bFileNameOnly)
{
if (!m_pInfo->m_bFindFastEnabled)
EnableFindFast(true, bSporadically ? !bCaseSensitive : bCaseSensitive);
ZIP_INDEX_TYPE uResult = ZIP_FILE_INDEX_NOT_FOUND;
if (bFileNameOnly)
{
// a non-effective search (treat an array as unsorted)
// set the proper compare function
ZIPSTRINGCOMPARE pCompare = bCaseSensitive == m_pInfo->m_bCaseSensitive ? m_pInfo->m_pCompare : GetCZipStrCompFunc(bCaseSensitive);
ZIP_INDEX_TYPE uSize = (ZIP_INDEX_TYPE)m_pFindArray->GetSize();
for (ZIP_INDEX_TYPE i = 0; i < uSize; i++)
{
CZipString sz = (*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)i]->m_pHeader->GetFileName();
CZipPathComponent::RemoveSeparators(sz); // to find a dir
CZipPathComponent zpc(sz);
sz = zpc.GetFileName();
if ((sz.*pCompare)(lpszFileName) == 0)
{
uResult = i;
break;
}
}
}
else if (bCaseSensitive == m_pInfo->m_bCaseSensitive)
uResult = FindFileNameIndex(lpszFileName);
else
{
if (bSporadically)
{
// a non-effective search (treat an array as unsorted)
// do not use m_pInfo->m_pCompare, as it may be shared
ZIPSTRINGCOMPARE pCompare = GetCZipStrCompFunc(bCaseSensitive);
ZIP_INDEX_TYPE uSize = (ZIP_INDEX_TYPE)m_pFindArray->GetSize();
for (ZIP_INDEX_TYPE i = 0; i < uSize; i++)
if (((*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)i]->m_pHeader->GetFileName().*pCompare)(lpszFileName) == 0)
{
uResult = i;
break;
}
}
else
{
BuildFindFastArray(bCaseSensitive);
uResult = FindFileNameIndex(lpszFileName);
}
}
return uResult == ZIP_FILE_INDEX_NOT_FOUND ? ZIP_FILE_INDEX_NOT_FOUND : (*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)uResult]->m_uIndex;
}
ZIP_INDEX_TYPE CZipCentralDir::InsertFindFastElement(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex)
{
CZipString fileName = pHeader->GetFileName();
ZIP_ARRAY_SIZE_TYPE uSize = m_pFindArray->GetSize();
// Our initial binary search range encompasses the entire array of filenames:
ZIP_ARRAY_SIZE_TYPE start = 0;
ZIP_ARRAY_SIZE_TYPE end = uSize;
// Keep halving our search range until we find the right place
// to insert the new element:
while ( start < end )
{
// Find the midpoint of the search range:
ZIP_ARRAY_SIZE_TYPE midpoint = ( start + end ) / 2;
// Compare the filename with the filename at the midpoint of the current search range:
int result = CompareElement(fileName, (ZIP_INDEX_TYPE)midpoint);
// If our filename is larger, it must fall in the first half of the search range:
if ( result > 0 )
{
end = midpoint;
}
// If it's smaller, it must fall in the last half:
else if ( result < 0 )
{
start = midpoint + 1;
}
// If they're equal, we can go ahead and insert here:
else
{
start = midpoint;
break;
}
}
m_pFindArray->InsertAt(start, new CZipFindFast(pHeader, uIndex == ZIP_FILE_INDEX_UNSPECIFIED ? (ZIP_INDEX_TYPE)uSize : uIndex /* just in case */));
return (ZIP_INDEX_TYPE)start;
}
ZIP_INDEX_TYPE CZipCentralDir::FindFileNameIndex(LPCTSTR lpszFileName) const
{
ZIP_ARRAY_SIZE_TYPE start = 0;
ZIP_ARRAY_SIZE_TYPE end = m_pFindArray->GetSize();
if (end == 0)
return ZIP_FILE_INDEX_NOT_FOUND;
else
end--;
// Keep halving our search range until we find the given element:
while ( start <= end )
{
// Find the midpoint of the search range:
ZIP_ARRAY_SIZE_TYPE midpoint = ( start + end ) / 2;
// Compare the given filename with the filename at the midpoint of the search range:
int result = CompareElement(lpszFileName, (ZIP_INDEX_TYPE)midpoint);
// If our filename is smaller, it must fall in the first half of the search range:
if ( result > 0 )
{
if (midpoint == 0)
return ZIP_FILE_INDEX_NOT_FOUND;
end = midpoint - 1;
}
// If it's larger, it must fall in the last half:
else if ( result < 0 )
{
start = midpoint + 1;
}
// If they're equal, return the result:
else
{
return (ZIP_INDEX_TYPE)midpoint;
}
}
// Signal failure:
return ZIP_FILE_INDEX_NOT_FOUND;
}
void CZipCentralDir::CreateSharedData()
{
m_pInfo = new CInfo();
m_pInfo->Init();
m_pHeaders = new CZipArray<CZipFileHeader*>();
m_pFindArray = new CZipArray<CZipFindFast*>();
}
void CZipCentralDir::DestroySharedData()
{
if (!m_pInfo)
return;
#ifdef ZIP_ARCHIVE_USE_LOCKING
LockAccess();
try
{
#endif
m_pInfo->m_iReference--;
if (m_pInfo->m_iReference <= 0) // <= is just in case instead of ==
{
if (m_pHeaders != NULL)
{
RemoveHeaders();
delete m_pHeaders;
m_pHeaders = NULL;
}
if (m_pFindArray != NULL)
{
ClearFindFastArray();
delete m_pFindArray;
m_pFindArray = NULL;
}
#ifdef ZIP_ARCHIVE_USE_LOCKING
UnlockAccess();
#endif
delete m_pInfo;
m_pInfo = NULL;
}
#ifdef ZIP_ARCHIVE_USE_LOCKING
}
catch(...)
{
UnlockAccess();
throw;
}
UnlockAccess();
#endif
}

View File

@@ -0,0 +1,822 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipCentralDir.h
* Includes the CZipCentralDir class.
*
*/
#if !defined(ZIPARCHIVE_ZIPCENTRALDIR_DOT_H)
#define ZIPARCHIVE_ZIPCENTRALDIR_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning (push)
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#endif
#include "ZipException.h"
#include "ZipFileHeader.h"
#include "ZipAutoBuffer.h"
#include "ZipCollections.h"
#include "ZipCompatibility.h"
#include "ZipExport.h"
#include "ZipCallbackProvider.h"
#include "ZipMutex.h"
/**
Represents the central directory record in the archive.
*/
class ZIP_API CZipCentralDir
{
public:
/**
Used in fast finding files by the filename.
A structure for the internal use only.
\see
CZipCentralDir::m_pFindArray
\see
CZipArchive::FindFile
\see
CZipArchive::EnableFindFast
*/
struct ZIP_API CZipFindFast
{
CZipFindFast()
{
m_uIndex = 0;
m_pHeader= NULL;
}
CZipFindFast(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex):m_pHeader(pHeader), m_uIndex(uIndex){}
/**
A pointer to the structure in CZipCentralDir. We extract a name from it.
*/
CZipFileHeader* m_pHeader;
/**
The index in the central directory of the #m_pHeader.
*/
ZIP_INDEX_TYPE m_uIndex;
};
/**
Stores general information about the central directory.
\see
CZipArchive::GetCentralDirInfo
*/
struct ZIP_API CInfo
{
/**
The position of the End of Central Directory Record.
In the Zip64 it points to the Zip64 counterpart.
*/
ZIP_SIZE_TYPE m_uEndOffset;
/**
The zero-based number of the volume with the End of Central Directory Record. To determine the total number of segments in an archive,
add one to this value. Request this information with CZipArchive::GetCentralDirInfo.
*/
ZIP_VOLUME_TYPE m_uLastVolume;
ZIP_VOLUME_TYPE m_uVolumeWithCD; ///< The number of the volume with the start of the central directory.
ZIP_INDEX_TYPE m_uVolumeEntriesNo; ///< The total number of entries in the central directory on the last volume.
ZIP_INDEX_TYPE m_uEntriesNumber; ///< The total number of entries in the central directory.
/**
The size of the central directory.
This value is valid only if #m_bInArchive is \c true; in other cases use the #GetSize method instead.
*/
ZIP_SIZE_TYPE m_uSize;
/**
The offset of the start of the central directory with respect to the starting volume number.
It is the value written in the central directory record.
This value is valid only if #m_bInArchive is \c true.
*/
ZIP_SIZE_TYPE m_uOffset;
/**
This value is \c true if the central directory is physically present in the archive; \c false otherwise.
*/
bool m_bInArchive;
private:
friend class CZipCentralDir;
void Init()
{
m_iReference = 1;
#ifdef ZIP_ARCHIVE_USE_LOCKING
m_mutex.Open();
#endif
m_pCompare = GetCZipStrCompFunc(ZipPlatform::GetSystemCaseSensitivity());
m_bCaseSensitive = false;
m_bFindFastEnabled = false;
m_pszComment.Release();
// initialize ( necessary when using 64 bits - we are copying only 4 bytes in Read())
m_bInArchive = false;
m_uEndOffset = 0;
m_uLastVolume = 0;
m_uVolumeWithCD = 0;
m_uVolumeEntriesNo = 0;
m_uEntriesNumber = 0;
m_uSize = 0;
m_uOffset = 0;
}
bool CheckIfOK_1()
{
return (m_uEndOffset >= m_uOffset + m_uSize);
}
ZIP_SIZE_TYPE CalculateBytesBeforeZip()
{
return m_uEndOffset - m_uSize - m_uOffset;
}
bool CheckIfOK_2()
{
return (m_uSize || !m_uEntriesNumber) && (m_uEntriesNumber || !m_uSize);
}
void DiskChange(ZIP_VOLUME_TYPE uCurrentVolume)
{
m_uLastVolume = uCurrentVolume;
if (m_uEntriesNumber)
{
m_uVolumeEntriesNo = 0;
}
else
{
m_uVolumeWithCD = m_uLastVolume;
m_uOffset = 0;
}
}
/**
Gets a value indicating if the current archive properties requires the Zip64 format.
\return
\c true, if the Zip64 is needed; \c false otherwise.
\see
<a href="kb">0610051629</a>
*/
bool NeedsZip64() const
{
return m_uLastVolume >= USHRT_MAX || m_uVolumeWithCD >= USHRT_MAX || m_uVolumeEntriesNo >= USHRT_MAX || m_uEntriesNumber >= USHRT_MAX || m_uSize >= UINT_MAX || m_uOffset >= UINT_MAX;
}
CZipAutoBuffer m_pszComment; ///< The global archive comment.
/**
The case-sensitivity of CZipCentralDir::m_pFindArray sorting.
*/
bool m_bCaseSensitive;
/**
The value set with the CZipCentralDir::EnableFindFast method.
*/
bool m_bFindFastEnabled;
private:
/**
The method used in string comparisons. It is set depending on the current case-sensitivity.
*/
ZIPSTRINGCOMPARE m_pCompare;
int m_iReference;
#ifdef ZIP_ARCHIVE_USE_LOCKING
ZipArchiveLib::CZipMutex m_mutex;
#endif
};
CZipCentralDir();
virtual ~CZipCentralDir();
static char m_gszSignature[]; ///< The End of Central Directory Record signature.
static char m_gszSignature64Locator[]; ///< The Zip64 End of Central Directory Locator signature.
CZipFileHeader* m_pOpenedFile; ///< It points to the currently opened file or it is \c NULL, if no file is opened.
/**
Initializes the object.
\param pStorage
The current storage to use.
\param pCallbacks
The current callbacks provider.
\param pStringSettings
The current string settings.
\param pSource
If not \c NULL, then it specifies the central directory for sharing.
\note
Throws exceptions.
*/
void Init(CZipStorage* pStorage, ZipArchiveLib::CZipCallbackProvider* pCallbacks, CZipStringStoreSettings* pStringSettings, CZipCentralDir* pSource = NULL);
/**
Reads the central directory from the archive.
\param bExhaustiveRead
\c true, if the exhaustive read should be performed, \c false otherwise.
\note
Throws exceptions.
\see
CZipArchive::SetExhaustiveRead
*/
void Read(bool bExhaustiveRead);
/**
Opens the file with the given index.
\param uIndex
A zero-based index of the file to open.
\note
Throws exceptions.
*/
void OpenFile(ZIP_INDEX_TYPE uIndex);
/**
Tests if the given file index is valid.
\param uIndex
A zero-based index to test.
\return
\c true, if the file with the given index exists inside the archive; \c false otherwise.
*/
bool IsValidIndex(ZIP_INDEX_TYPE uIndex)const;
/**
Removes the file header from the central directory.
\param pHeader
The header to remove.
\param uIndex
The index of the header to remove. Use \c ZIP_FILE_INDEX_UNSPECIFIED, if the index is not known.
\param bShift
If \c true, the data inside the archive is moved over the hole created after removing the file.
If \c false, the unused area inside the archive remains.
\note
Throws exceptions.
*/
void RemoveFile(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex = ZIP_FILE_INDEX_UNSPECIFIED, bool bShift = true);
/**
Removes last file from the central directory.
\param pHeader
The header to remove.
\param uIndex
The index of the header to remove. Use \c ZIP_FILE_INDEX_UNSPECIFIED, if the index is not known.
*/
void RemoveLastFile(CZipFileHeader* pHeader = NULL, ZIP_INDEX_TYPE uIndex = ZIP_FILE_INDEX_UNSPECIFIED);
/**
Removes all files.
\note
Throws exceptions.
*/
void RemoveAll();
/**
Closes the central directory.
*/
void Close();
/**
Adds a new file to the central directory.
\param header
Used as a template for the data stored inside the archive.
\param uReplaceIndex
The index of the file to be replaced. Use \c ZIP_FILE_INDEX_UNSPECIFIED, if the index is not known.
\param iLevel
The compression level.
\param bRichHeaderTemplateCopy
\c true, if copy crc and sizes values from \a header; \c false otherwise.
\return
The new header.
\note
Throws exceptions.
*/
CZipFileHeader* AddNewFile(const CZipFileHeader & header, ZIP_INDEX_TYPE uReplaceIndex, int iLevel, bool bRichHeaderTemplateCopy = false);
/**
Removes physically the central directory from the archive.
\note
Throws exceptions.
*/
void RemoveFromDisk();
/**
Gets the central directory size.
\param bWhole
If \c true, include the size of the file headers.
If \c false, the size of the file headers is not included.
\return
The size of the central directory.
\see
CZipArchive::GetCentralDirSize
*/
ZIP_SIZE_TYPE GetSize(bool bWhole = false) const;
/**
Closes a file opened for reading inside the archive.
\param skipCheckingDataDescriptor
If \c true, the data descriptor that is located after the compressed data in the archive is checked for validity.
Set this value to \c false after closing the file after an exception was thrown.
\note
Throws exceptions.
*/
void CloseFile(bool skipCheckingDataDescriptor = false);
/**
Closes a file opened for reading inside the archive.
\note
Throws exceptions.
*/
void CloseNewFile();
/**
Writes the central directory to the archive.
\note
Throws exceptions.
*/
void Write();
/**
Enables Find Fast.
\see
CZipArchive::EnableFindFast
*/
void EnableFindFast(bool bEnable, bool bCaseSensitive);
/**
Searches for the file.
\see
CZipArchive::FindFile
*/
ZIP_INDEX_TYPE FindFile(LPCTSTR lpszFileName, bool bCaseSensitive, bool bSporadically, bool bFileNameOnly);
/**
Gets the Find Fast index.
\see
CZipArchive::GetFindFastIndex
*/
ZIP_INDEX_TYPE GetFindFastIndex(ZIP_INDEX_TYPE uFindFastIndex)const
{
if (!IsValidIndex(uFindFastIndex) || !m_pInfo->m_bFindFastEnabled)
return ZIP_FILE_INDEX_NOT_FOUND;
return (*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)uFindFastIndex]->m_uIndex;
}
/**
Points to CZipArchive::m_storage.
*/
CZipStorage* m_pStorage;
/**
Points to the current callback provider.
*/
ZipArchiveLib::CZipCallbackProvider* m_pCallbacks;
/**
Gets the information about the file with the given index.
\see
CZipArchive::operator[](ZIP_INDEX_TYPE)
*/
CZipFileHeader* operator[](ZIP_INDEX_TYPE uIndex)
{
return (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)uIndex];
}
/**
Gets the information about the file with the given index.
\see
CZipArchive::operator[](ZIP_INDEX_TYPE) const
*/
const CZipFileHeader* operator[](ZIP_INDEX_TYPE uIndex) const
{
return (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)uIndex];
}
/**
Gets the number of files in the archive.
\return
The number of files in the archive.
*/
ZIP_ARRAY_SIZE_TYPE GetCount() const
{
return m_pHeaders == NULL ? 0 : m_pHeaders->GetSize();
}
/**
Sets the global comment.
\see
CZipArchive::SetGlobalComment
*/
void SetComment(LPCTSTR lpszComment);
/**
Gets the global comment.
\see
CZipArchive::GetGlobalComment
*/
void GetComment(CZipString& szComment) const
{
ZipCompatibility::ConvertBufferToString(szComment, m_pInfo->m_pszComment, m_pStringSettings->m_uCommentCodePage);
}
/**
Sets the file comment.
\see
CZipArchive::SetFileComment
*/
bool SetFileComment(ZIP_INDEX_TYPE uIndex, LPCTSTR lpszComment);
/**
Finds the index of the file with the given name.
\param lpszFileName
The name of the file to find.
\return
The index in CZipCentralDir::m_pFindArray with the corresponding CZipFindFast structure
or \c ZIP_FILE_INDEX_NOT_FOUND, if there is no such file with the given name.
\see
CZipArchive::FindFile
*/
ZIP_INDEX_TYPE FindFileNameIndex(LPCTSTR lpszFileName) const;
/**
Gets the information about the central directory.
\see
CZipArchive::GetCentralDirInfo
*/
void GetInfo(CInfo& info) const {info = *m_pInfo;}
/**
Gets a value indicating whether the Find Fast feature is enabled or not.
\return
The value of CInfo::m_bFindFastEnabled.
*/
bool IsFindFastEnabled(){return m_pInfo->m_bFindFastEnabled;}
/**
Rebuilds the CZipCentralDir::m_pFindArray array.
*/
void RebuildFindFastArray()
{
if (m_pInfo->m_bFindFastEnabled)
BuildFindFastArray(m_pInfo->m_bCaseSensitive);
}
/**
The current string store settings.
\see
SetStringStoreSettings
*/
CZipStringStoreSettings* m_pStringSettings;
/**
Consistency checks to ignore. Can be one or more of the CZipArchive::ConsistencyCheck values.
\see
CZipArchive::SetIgnoredConsistencyChecks
*/
int m_iIgnoredChecks;
/**
Checks if the specified consistency check should be performed or not.
\param iLevel
The level to check. Can be one or more of CZipArchive::ConsistencyCheck values.
\return
\c true, if the specified check should be performed; \c false otherwise.
\see
m_iIgnoredChecks
*/
bool IsConsistencyCheckOn(int iLevel)
{
// check, if not ignored
return (m_iIgnoredChecks & iLevel) == 0;
}
protected:
#if _MSC_VER > 1000
#pragma warning( push )
#pragma warning (disable : 4702) // unreachable code
#endif
/**
The method used in comparison when sorting headers.
*/
static int CompareHeaders(const void *pArg1, const void *pArg2)
{
CZipFileHeader* pw1 = *(CZipFileHeader**)pArg1;
CZipFileHeader* pw2 = *(CZipFileHeader**)pArg2;
if (pw1 == pw2)
return 0;
if (pw1->m_uVolumeStart == pw2->m_uVolumeStart)
{
if (pw1->m_uOffset < pw2->m_uOffset)
return -1;
else if (pw1->m_uOffset > pw2->m_uOffset)
return 1;
ASSERT(FALSE);
// two files with the same offsets in the same volume???
CZipException::Throw(CZipException::badZipFile);
return 0; // just for the compiler comfort (and discomfort of another)
}
else if (pw1->m_uVolumeStart < pw2->m_uVolumeStart)
return -1;
else // if (pw1->m_uVolumeStart > pw2->m_uVolumeStart)
return 1;
}
#if _MSC_VER > 1000
#pragma warning( pop )
#endif
static int CompareFindFastCollate(const void* pArg1, const void* pArg2)
{
CZipFindFast* pHeader1 = *(CZipFindFast**)pArg1;
CZipFindFast* pHeader2 = *(CZipFindFast**)pArg2;
return pHeader1->m_pHeader->GetFileName().Collate(pHeader2->m_pHeader->GetFileName());
}
static int CompareFindFastCollateNoCase(const void* pArg1, const void* pArg2)
{
CZipFindFast* pHeader1 = *(CZipFindFast**)pArg1;
CZipFindFast* pHeader2 = *(CZipFindFast**)pArg2;
return pHeader1->m_pHeader->GetFileName().CollateNoCase(pHeader2->m_pHeader->GetFileName());
}
/**
Holds the information about all the files inside the archive.
\see
CZipFileHeader
*/
CZipArray<CZipFileHeader*>* m_pHeaders;
/**
Builds the CZipCentralDir::m_pFindArray array.
*/
void BuildFindFastArray( bool bCaseSensitive );
void ClearFindFastArray()
{
ZIP_ARRAY_SIZE_TYPE uCount = m_pFindArray->GetSize();
for (ZIP_ARRAY_SIZE_TYPE i = 0; i < uCount; i++)
delete (*m_pFindArray)[i];
m_pFindArray->RemoveAll();
}
/**
The Find Fast array.
\see
CZipFindFast
\see
CInfo::m_bFindFastEnabled
\see
CZipArchive::FindFile
*/
CZipArray<CZipFindFast*>* m_pFindArray;
/**
The method used in comparison involving the Find Fast feature.
\param lpszFileName
The name of the file.
\param uIndex
The index from the CZipCentralDir::m_pFindArray array.
\return
The return value has the following meaning:
- 0 if the filenames are the same
- < 0 if the filename stored in the array is less than \a lpszFileName
- > 0 if the filename stored in the array is greater than \a lpszFileName
*/
int CompareElement(LPCTSTR lpszFileName, ZIP_INDEX_TYPE uIndex) const
{
return ((*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)uIndex]->m_pHeader->GetFileName().*(m_pInfo->m_pCompare))(lpszFileName);
}
/**
Inserts a new CZipFindFast element to the CZipCentralDir::m_pFindArray array
Initializes the CZipFindFast object with \a pHeader and \a uIndex values.
\param pHeader
The element to insert.
\param uIndex
The original index of \a pHeader in the central directory.
If set to \c ZIP_FILE_INDEX_UNSPECIFIED, it is assumed to be the last element.
\return
The index in the CZipCentralDir::m_pFindArray array.
*/
ZIP_INDEX_TYPE InsertFindFastElement(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex);
/**
The central directory information.
\see
CInfo
*/
CInfo* m_pInfo;
/**
Reads file headers from the archive.
\param bExhaustiveRead
\c true, if the exhaustive read should be performed, \c false otherwise.
\note
Throws exceptions.
\see
CZipArchive::SetExhaustiveRead
*/
void ReadHeaders(bool bExhaustiveRead);
/**
Frees the memory allocated for the CZipFileHeader structures.
*/
void RemoveHeaders();
/**
Removes data descriptors from a segmented archive that turned out to be one-segment only.
It is not called for encrypted files.
\param bFromBuffer
If \c true, removes from the write buffer in memory otherwise from the file on the disk.
\return
\c false, if the file mapping to memory was not successful
(can happen only when \a bFromBuffer is \c false); \c true otherwise.
\note
Throws exceptions.
*/
bool RemoveDataDescr(bool bFromBuffer);
/**
Writes the file headers to the archive.
\note
Throws exceptions.
*/
void WriteHeaders(bool bOneDisk);
/**
Writes the End of Central Directory Record.
\return
The size of the record.
\note
Throws exceptions.
*/
void WriteCentralEnd();
/**
Throws an exception with the given code.
*/
void ThrowError(int err) const;
/**
Creates data that can be shared between different archive objects.
\see
DestroySharedData
*/
void CreateSharedData();
/**
Destroys data shared between different archive objects, if the usage reference count
of the data is zero.
\note
Throws exceptions.
\see
CreateSharedData
*/
void DestroySharedData();
#ifdef ZIP_ARCHIVE_USE_LOCKING
/**
Locks the access to the shared data.
\note
Throws exceptions.
\see
UnlockAccess
\see
CreateSharedData
*/
void LockAccess()
{
ASSERT(m_pInfo);
m_pInfo->m_mutex.Lock();
}
/**
Unlocks the access to the shared data.
\note
Throws exceptions.
\see
LockAccess
\see
CreateSharedData
*/
void UnlockAccess()
{
if (m_pInfo)
m_pInfo->m_mutex.Unlock();
}
#endif
};
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning (pop)
#endif
#endif // !defined(ZIPARCHIVE_ZIPCENTRALDIR_DOT_H)

View File

@@ -0,0 +1,41 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipCollections.h
* Includes the collections classes used by the ZipArchive Library.
*
*/
#ifndef ZIPARCHIVE_ZIPCOLLECTIONS_DOT_H
#define ZIPARCHIVE_ZIPCOLLECTIONS_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "_platform.h"
#include "ZipExport.h"
#ifdef ZIP_ARCHIVE_STL
#include "ZipCollections_stl.h"
#else
#include "ZipCollections_mfc.h"
#endif
typedef CZipArray<ZIP_INDEX_TYPE> CZipIndexesArray;
#endif /* ZIPARCHIVE_ZIPCOLLECTIONS_DOT_H */

View File

@@ -0,0 +1,91 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_ZIPCOLLECTIONS_DOT_H
#error Do not include this file directly. Include ZipCollections.h instead
#endif
#if _MSC_VER > 1000
#pragma warning( push )
#pragma warning (disable:4786) // 'identifier' : identifier was truncated to 'number' characters in the debug information
#endif
#include <afxtempl.h>
#define ZIP_ARRAY_SIZE_TYPE INT_PTR
typedef CStringArray CZipStringArray;
template <class TYPE>
class CZipArray : public CArray<TYPE, TYPE>
{
public:
typedef int (*CompareFunction)(const void* pArg1, const void* pArg2);
private:
static int CompareAsc(const void *pArg1, const void *pArg2)
{
TYPE w1 = *(TYPE*)pArg1;
TYPE w2 = *(TYPE*)pArg2;
return w1 == w2 ? 0 :(w2 > w1 ? - 1 : 1);
}
static int CompareDesc(const void *pArg1, const void *pArg2)
{
TYPE w1 = *(TYPE*)pArg1;
TYPE w2 = *(TYPE*)pArg2;
return w1 == w2 ? 0 :(w1 > w2 ? - 1 : 1);
}
public:
void Sort(bool bAscending)
{
Sort(bAscending ? CompareAsc : CompareDesc);
}
void Sort(CompareFunction pFunction)
{
INT_PTR uSize = GetSize();
if (!uSize) // if ommitted operator [] will fail if empty
return;
qsort((void*)&((*this)[0]), (size_t)uSize , sizeof(TYPE), pFunction);
}
};
template<class TYPE>
class CZipPtrList : public CTypedPtrList<CPtrList, TYPE>
{
public:
typedef POSITION iterator;
typedef POSITION const_iterator;
bool IteratorValid(const iterator &iter) const
{
return iter != NULL;
}
};
template<class KEY, class VALUE>
class CZipMap : public CMap<KEY, KEY, VALUE, VALUE>
{
public:
typedef POSITION iterator;
typedef POSITION const_iterator;
bool IteratorValid(const iterator &iter) const
{
return iter != NULL;
}
};
#if _MSC_VER > 1000
#pragma warning( pop )
#endif

View File

@@ -0,0 +1,226 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_ZIPCOLLECTIONS_DOT_H
#error Do not include this file directly. Include ZipCollections.h instead
#endif
#if _MSC_VER > 1000
#pragma warning( push, 3 ) // STL
#pragma warning (disable : 4284) //return type for 'identifier::operator >' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
#pragma warning (disable : 4018) //'expression' : signed/unsigned mismatch
#endif
#include <vector>
#include <list>
#include <map>
#include <algorithm>
#include <functional>
#include "ZipString.h"
#include "ZipException.h"
#define ZIP_ARRAY_SIZE_TYPE size_t
template<class TYPE>
class CZipArray : private std::vector<TYPE>
{
public:
typedef int (*CompareFunction)(const void* pArg1, const void* pArg2);
private:
struct Sorter
{
CompareFunction m_pFunction;
Sorter(CompareFunction pFunction)
{
m_pFunction = pFunction;
}
bool operator ()(TYPE const& t1, TYPE const& t2)
{
return (*m_pFunction)(&t1, &t2) < 0;
}
};
public:
typedef typename std::vector<TYPE>::iterator iterator;
typedef typename std::vector<TYPE> inherited;
protected:
iterator GetIterFromIndex(size_t uIndex)
{
iterator iter = this->begin();
iter += uIndex;
// int t = 0; while (t != uIndex) {iter++;t++;}
return iter;
}
public:
void Sort(bool bAscending)
{
if (bAscending)
std::sort (this->begin(), this->end(), std::less<TYPE>());
else
std::sort (this->begin(), this->end(), std::greater<TYPE>());
}
void Sort(CompareFunction pFunction)
{
std::sort(this->begin(), this->end(), Sorter(pFunction));
}
size_t GetSize() const{return this->size(); }
size_t GetCount() const{return this->size(); }
size_t GetUpperBound() const
{
size_t ret = this->size();
if (ret == 0)
CZipException::Throw(CZipException::outOfBounds);
return ret - 1;
}
TYPE& GetAt(size_t uIndex) {return this->at(uIndex);}
const TYPE& GetAt(size_t uIndex) const {return this->at(uIndex);}
size_t Add(const TYPE& x) {push_back(x);return GetUpperBound();}
void RemoveAll() {this->clear();}
void RemoveAt(size_t uIndex) { erase(GetIterFromIndex(uIndex));}
void InsertAt(size_t uIndex, const TYPE& x){insert(GetIterFromIndex(uIndex), x);}
TYPE& operator[](size_t uIndex)
{
return inherited::operator[](uIndex);
}
TYPE operator[](size_t uIndex) const
{
return inherited::operator[](uIndex);
}
};
typedef CZipArray<CZipString> CZipStringArray;
typedef CZipArray<WORD> CZipWordArray;
template<class TYPE>
class CZipPtrList : private std::list<TYPE>
{
public:
typedef typename std::list<TYPE>::iterator iterator;
typedef typename std::list<TYPE>::const_iterator const_iterator;
size_t GetCount() const {return this->size();}
void AddTail(const TYPE& x){push_back(x);}
void AddHead(const TYPE& x){push_front(x);}
void RemoveHead() {this->pop_front();}
void RemoveTail() {this->pop_back();}
void RemoveAll() {this->clear();}
TYPE& GetHead() {return this->front();}
TYPE GetHead() const {return this->front();}
TYPE& GetTail() {return this->back();}
TYPE GetTail() const {return this->back();}
iterator GetHeadPosition() { return this->begin();}
const_iterator GetHeadPosition() const { return this->begin();}
iterator GetTailPosition() { return this->back();}
TYPE& GetNext(iterator& pos) { return *pos++;}
const TYPE GetNext(const_iterator& pos) const{ return *pos++;}
TYPE& GetPrev(iterator& pos) { return *pos--;}
TYPE GetPrev(iterator& pos) const{ return *pos--;}
iterator Find(TYPE& x) { return std::find(this->begin(), this->end(), x);}
void RemoveAt(iterator& pos) { erase(pos);}
bool IteratorValid(const_iterator &iter) const
{
return iter != this->end();
}
bool IteratorValid(iterator &iter)
{
return iter != this->end();
}
iterator FindIndex(size_t uIndex)
{
iterator iter = this->begin();
size_t t = 0; while (t != uIndex) {iter++;t++;}
return iter;
}
const_iterator FindIndex(size_t uIndex) const
{
const_iterator iter = this->begin();
size_t t = 0; while (t != uIndex) {iter++;t++;}
return iter;
}
TYPE& GetAt(const iterator& pos) { return *pos;}
TYPE GetAt(const_iterator& pos) const{ return *pos;}
};
// simplified and partial only
template<class KEY, class VALUE>
class CZipMap : private std::map<KEY, VALUE>
{
public:
typedef typename std::map<KEY, VALUE>::iterator iterator;
typedef typename std::map<KEY, VALUE>::const_iterator const_iterator;
typedef typename std::map<KEY,VALUE, std::less<KEY>, std::allocator<std::pair<const KEY, VALUE> > >::value_type v_type;
void SetAt( KEY key, VALUE newValue)
{
insert(v_type(key, newValue));
}
ZBOOL RemoveKey( KEY key )
{
return erase(key) != 0;
}
ZBOOL Lookup( KEY key, VALUE& rValue ) const
{
#if (__GNUC__ >= 3) // The actual version number may be different.
const_iterator iter = std::map<KEY, VALUE>::find(key);
if (iter == std::map<KEY, VALUE>::end())
#else
const_iterator iter = find(key);
if (iter == end())
#endif
return FALSE;
else
{
rValue = iter->second;
return TRUE;
}
}
iterator GetStartPosition() { return this->begin();}
const_iterator GetStartPosition() const { return this->begin();}
bool IteratorValid(const_iterator &iter) const
{
return iter != this->end();
}
bool IteratorValid(iterator &iter)
{
return iter != this->end();
}
void GetNextAssoc(iterator &iter, KEY& key, VALUE& value)
{
key = iter->first;
value = iter->second;
iter++;
}
void GetNextAssoc(const_iterator &iter, KEY& key, VALUE& value)
{
key = iter->first;
value = iter->second;
iter++;
}
void RemoveAll() {this->clear();}
};
#if _MSC_VER > 1000
#pragma warning( pop)
#endif

View File

@@ -0,0 +1,219 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipCompatibility.h"
#include "ZipPlatform.h"
#include "ZipException.h"
#include "ZipAutoBuffer.h"
#include "ZipFileHeader.h"
enum iInternalAttr
{
attROnly = 0x01,
attHidd = 0x02,
attSys = 0x04,
attDir = 0x10,
attArch = 0x20
};
// *********************** WINDOWS **************************
#ifndef _WIN32
#define FILE_ATTRIBUTE_READONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
#endif
// *********************** UINX **************************
#define USER_PERMISSIONS_MASK 0x01C0
#define EXTRACT_USER_PERMISSIONS(x) ((x & USER_PERMISSIONS_MASK) >> 6)
#define CREATE_USER_PERMISSIONS(x) ((x & 0x0007) << 6)
#define GROUP_PERMISSIONS_MASK 0x0038
#define CREATE_GROUP_PERMISSIONS(x) ((x & 0x0007) << 3)
#define OTHER_PERMISSIONS_MASK 0x0007
#define CREATE_OTHER_PERMISSIONS(x) (x & 0x0007)
#define UNIX_DIRECTORY_ATTRIBUTE 0x4000
#define UNIX_FILE_ATTRIBUTE 0x8000
#define UNIX_EXEC 1
#define UNIX_WRITE 2
#define UNIX_READ 4
using namespace ZipCompatibility;
typedef DWORD(*conv_func)(DWORD , bool );
DWORD AttrDos(DWORD , bool );
DWORD AttrUnix(DWORD, bool);
DWORD AttrMac(DWORD , bool );
conv_func conv_funcs[11] = {AttrDos,
NULL,
NULL,
AttrUnix,
NULL,
NULL,
AttrDos,
AttrMac,
NULL,
NULL,
AttrDos
};
DWORD ZipCompatibility::ConvertToSystem(DWORD uAttr, int iFromSystem, int iToSystem)
{
if (iToSystem != iFromSystem && iFromSystem < 11 && iToSystem < 11)
{
conv_func p = conv_funcs[iFromSystem], q = conv_funcs[iToSystem];
if (p && q)
uAttr = q( p(uAttr, true), false);
else
CZipException::Throw(CZipException::platfNotSupp);
}
return uAttr;
}
DWORD AttrDos(DWORD uAttr, bool )
{
return uAttr;
}
DWORD AttrUnix(DWORD uAttr, bool bFrom)
{
DWORD uNewAttr = 0;
if (bFrom)
{
bool isDir = (uAttr & UNIX_DIRECTORY_ATTRIBUTE) != 0;
if (isDir)
uNewAttr = attDir;
uAttr = EXTRACT_USER_PERMISSIONS (uAttr);
// we may set archive attribute if the file hasn't got the execute permissions
// and is not a directory
if (!isDir && !(uAttr & UNIX_EXEC))
uNewAttr |= attArch ;
if (!(uAttr & UNIX_WRITE))
uNewAttr |= attROnly;
if (!(uAttr & UNIX_READ))
uNewAttr |= attHidd;
}
else
{
uNewAttr = 0;
// we cannot assume that if the file hasn't the archive attribute set
// then it is executable and set execute permissions
if (!(uAttr & attHidd))
uNewAttr |= (CREATE_OTHER_PERMISSIONS (UNIX_READ) | CREATE_GROUP_PERMISSIONS (UNIX_READ)) |
CREATE_USER_PERMISSIONS (UNIX_READ);
if (!(uAttr & attROnly))
uNewAttr |= (CREATE_GROUP_PERMISSIONS (UNIX_WRITE) | CREATE_USER_PERMISSIONS (UNIX_WRITE));
if (uAttr & attDir)
{
uNewAttr |= UNIX_DIRECTORY_ATTRIBUTE;
uNewAttr |= (CREATE_OTHER_PERMISSIONS (UNIX_EXEC) | CREATE_GROUP_PERMISSIONS (UNIX_EXEC)) |
CREATE_USER_PERMISSIONS (UNIX_EXEC);
}
else
uNewAttr |= UNIX_FILE_ATTRIBUTE;
}
return uNewAttr;
}
DWORD AttrMac(DWORD uAttr, bool )
{
return uAttr & (attDir | attROnly);
}
// ************************************************************************
ZIPINLINE bool ZipCompatibility::IsPlatformSupported(int iCode)
{
return iCode == zcDosFat || iCode == zcUnix || iCode == zcMacintosh
|| iCode == zcNtfs || iCode == zcOs2Hpfs;
}
void ZipCompatibility::ConvertBufferToString(CZipString& szString, const CZipAutoBuffer& buffer, UINT uCodePage)
{
#ifdef _UNICODE
ZipPlatform::MultiByteToWide(buffer, szString, uCodePage);
#else
// iLen does not include the NULL character
int iLen;
if (uCodePage == CP_OEMCP)
{
CZipAutoBuffer buf;
buf = buffer;
ZipPlatform::AnsiOem(buf, false);
iLen = buf.GetSize();
memcpy(szString.GetBuffer(iLen), buf.GetBuffer(), iLen);
}
else
{
iLen = buffer.GetSize();
memcpy(szString.GetBuffer(iLen), buffer.GetBuffer(), iLen);
}
szString.ReleaseBuffer(iLen);
#endif
}
void ZipCompatibility::ConvertStringToBuffer(LPCTSTR lpszString, CZipAutoBuffer& buffer, UINT uCodePage)
{
#ifdef _UNICODE
ZipPlatform::WideToMultiByte(lpszString, buffer, uCodePage);
#else
int iLen = (int)strlen(lpszString);
// iLen does not include the NULL character
buffer.Allocate(iLen);
memcpy(buffer, lpszString, (size_t)iLen);
if (uCodePage == CP_OEMCP)
ZipPlatform::AnsiOem(buffer, true);
#endif
}
void ZipCompatibility::SlashBackslashChg(CZipString& szFileName, bool bReplaceSlash)
{
TCHAR t1 = _T('\\') /*backslash*/, t2 = _T('/'), c1, c2;
if (bReplaceSlash)
{
c1 = t1;
c2 = t2;
}
else
{
c1 = t2;
c2 = t1;
}
szFileName.Replace(c2, c1);
}

View File

@@ -0,0 +1,145 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipCompatibility.h
* ZipCompatibility namespace declaration.
*
*/
#if !defined(ZIPARCHIVE_ZIPCOMPATIBILITY_DOT_H)
#define ZIPARCHIVE_ZIPCOMPATIBILITY_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
class CZipAutoBuffer;
class CZipFileHeader;
#include "ZipString.h"
/**
Includes functions that provide support for the proper conversion of attributes
and filenames between different system platforms.
*/
namespace ZipCompatibility
{
/**
The codes of the compatibility of the file attribute information.
\see
CZipArchive::GetSystemCompatibility
\see
CZipFileHeader::GetSystemCompatibility
\see
ZipPlatform::GetSystemID
*/
enum ZipPlatforms
{
zcDosFat, ///< MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)
zcAmiga, ///< Amiga
zcVaxVms, ///< VAX/VMS
zcUnix, ///< Unix / Linux
zcVmCms, ///< VM/CMS
zcAtari, ///< Atari ST
zcOs2Hpfs, ///< OS/2 H.P.F.S.
zcMacintosh, ///< Macintosh
zcZsystem, ///< Z-System
zcCpm, ///< CP/M
zcNtfs ///< Windows NTFS
};
/**
Checks whether the system with the given code is supported by the ZipArchive Library.
\param iCode
One of the #ZipPlatforms values to check.
\return
\c true, if supported; \c false otherwise.
*/
bool IsPlatformSupported(int iCode);
/**
Converts the system attributes between different system platforms.
\param uAttr
The attributes to convert.
\param iFromSystem
The system code to convert \a uAttr from.
\param iToSystem
The system code to convert \a uAttr to.
\return
The converted attributes.
\note
Throws exceptions.
\see
ZipPlatforms
*/
DWORD ConvertToSystem(DWORD uAttr, int iFromSystem, int iToSystem);
/**
Converts the string stored in \a buffer using the given code page.
\param buffer
The buffer to convert the string from.
\param szString
The string to receive the result.
\param uCodePage
The code page used in conversion.
\see
<a href="kb">0610051525</a>
*/
void ConvertBufferToString(CZipString& szString, const CZipAutoBuffer& buffer, UINT uCodePage);
/**
Converts the \a lpszString using the given code page.
\param lpszString
The string to convert from.
\param buffer
The buffer to receive the result.
\param uCodePage
The code page used in conversion.
\see
<a href="kb">0610051525</a>
*/
void ConvertStringToBuffer(LPCTSTR lpszString, CZipAutoBuffer& buffer, UINT uCodePage);
/**
Changes the path separators from slash to backslash or vice-versa in \a szFileName.
\param szFileName
The filename to have the path separators changed.
\param bReplaceSlash
If \c true, changes slash to backslash. If \c false, changes backslash to slash.
*/
void SlashBackslashChg(CZipString& szFileName, bool bReplaceSlash);
};
#endif // !defined(ZIPARCHIVE_ZIPCOMPATIBILITY_DOT_H)

View File

@@ -0,0 +1,104 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipCompressor.h"
#include "BytesWriter.h"
#include "DeflateCompressor.h"
using namespace ZipArchiveLib;
CZipCompressor* CZipCompressor::CreateCompressor(WORD uMethod, CZipStorage* pStorage)
{
if (uMethod == methodStore || uMethod == methodDeflate)
return new CDeflateCompressor(pStorage);
return NULL;
}
void CZipCompressor::UpdateFileCrc(const void *pBuffer, DWORD uSize)
{
m_pFile->m_uCrc32 = zarch_crc32(m_pFile->m_uCrc32, (zarch_Bytef*)pBuffer, uSize);
}
void CZipCompressor::UpdateCrc(const void *pBuffer, DWORD uSize)
{
m_uCrc32 = zarch_crc32(m_uCrc32, (zarch_Bytef*)pBuffer, uSize);
}
void CZipCompressor::UpdateOptions(const COptionsMap& optionsMap)
{
const COptions* pOptions = GetOptions();
if (pOptions == NULL)
return;
const COptions* pNewOptions = optionsMap.Get(pOptions->GetType());
if (pNewOptions != NULL)
UpdateOptions(pNewOptions);
}
void CZipCompressor::InitBuffer()
{
// This should be greated that 64k for deflate when creating offsets pairs is enabled
// otherwise deflate will not be able to write one block in one go and will never report
// a flushed block for low-compressable data
const COptions* pOptions = GetOptions();
DWORD bufferSize = 0;
if (pOptions != NULL)
bufferSize = pOptions->m_iBufferSize;
if (bufferSize == 0)
bufferSize = COptions::cDefaultBufferSize;
m_pBuffer.Allocate(bufferSize);
}
void CZipCompressor::COptionsMap::Set(const CZipCompressor::COptions* pOptions)
{
if (pOptions == NULL)
return;
int iType = pOptions->GetType();
Remove(iType);
SetAt(iType, pOptions->Clone());
}
CZipCompressor::COptions* CZipCompressor::COptionsMap::Get(int iType) const
{
COptions* pTemp = NULL;
if (Lookup(iType, pTemp))
return pTemp;
else
return NULL;
}
void CZipCompressor::COptionsMap::Remove(int iType)
{
COptions* pTemp = Get(iType);
if (pTemp != NULL)
{
delete pTemp;
RemoveKey(iType);
}
}
CZipCompressor::COptionsMap::~COptionsMap()
{
COptionsMap::iterator iter = GetStartPosition();
while (IteratorValid(iter))
{
COptions* pOptions = NULL;
int iType = 0;
GetNextAssoc(iter, iType, pOptions);
delete pOptions;
}
RemoveAll();
}

View File

@@ -0,0 +1,485 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipCompressor.h
* Includes the CZipCompressor class.
*
*/
#if !defined(ZIPARCHIVE_ZIPCOMPRESSOR_DOT_H)
#define ZIPARCHIVE_ZIPCOMPRESSOR_DOT_H
#if _MSC_VER > 1000
#pragma once
#pragma warning( push )
#pragma warning (disable : 4100) // unreferenced formal parameter
#endif
#include "ZipExport.h"
#include "ZipAutoBuffer.h"
#include "ZipFileHeader.h"
#include "ZipStorage.h"
#include "ZipCryptograph.h"
#include "ZipException.h"
/**
A base class for compressors used in compression and decompression of data.
*/
class ZIP_API CZipCompressor
{
protected:
CZipStorage* m_pStorage; ///< The current storage object.
CZipAutoBuffer m_pBuffer; ///< A buffer that receives compressed data or provides data for decompression.
CZipCryptograph* m_pCryptograph; ///< Current cryptograph.
CZipFileHeader* m_pFile; ///< The file header being compressed or decompressed.
/**
Initializes a new instance of the CZipCompressor class.
\param pStorage
The current storage object.
*/
CZipCompressor(CZipStorage* pStorage)
:m_pStorage(pStorage)
{
m_pCryptograph = NULL;
m_uUncomprLeft = 0;
m_uComprLeft = 0;
m_uCrc32 = 0;
}
public:
/**
The type of a compressor.
*/
enum CompressorType
{
typeDeflate = 1, ///< Deflate compression (default in zip archives).
typeBzip2 ///< Bzip2 compression.
};
/**
The compression level.
*/
enum CompressionLevel
{
levelDefault = -1, ///< The default compression level (equals 6 for deflate).
levelStore = 0, ///< No compression used. Data is stored.
levelFastest = 1, ///< The fastest compression. The compression ratio is the lowest (apart from #levelStore).
levelBest = 9 ///< The highest compression ratio. It's usually the slowest.
};
/**
The compression method.
*/
enum CompressionMethod
{
methodStore = 0, ///< A file is stored, not compressed.
methodDeflate = 8, ///< The deflate compression method.
/**
A file is compressed using the bzip2 algorithm.
\see
<a href="kb">0610231446|bzip2</a>
*/
methodBzip2 = 12,
/**
This value means that WinZip AES encryption is used.
The original compression method is stored in a WinZip extra field.
It is only an informational value - you cannot set it as a compression method. The ZipArchive
Library handles this value internally.
\see
<a href="kb">0610201627|aes</a>
*/
methodWinZipAes = 99
};
/**
The base class for compressors options.
\see
<a href="kb">0610231446|options</a>
\see
CZipArchive::SetCompressionOptions
*/
struct ZIP_API COptions
{
/**
Helper constants.
*/
enum Constants
{
/**
The default size of the buffer used in compression and decompression operations.
*/
cDefaultBufferSize = 2 * 65536
};
COptions()
{
m_iBufferSize = cDefaultBufferSize;
}
/**
Gets the type of the compressor to which the current options apply.
\return
The type of the compressor. It can be one of the #CompressorType values.
*/
virtual int GetType() const = 0;
/**
Clones the current options object.
\return
The cloned object of the same type as the current object.
*/
virtual COptions* Clone() const = 0;
/**
The size of the buffer used in compression and decompression operations.
By default it is set to to #cDefaultBufferSize. For the optimal performance of the
deflate algorithm it should be set at least to 128kB.
\see
CZipArchive::SetAdvanced
*/
int m_iBufferSize;
virtual ~COptions()
{
}
};
/**
A dictionary used for keeping options for different types of compressors.
\see
CZipArchive::SetCompressionOptions
*/
class ZIP_API COptionsMap : public CZipMap<int, COptions*>
{
public:
void Set(const COptions* pOptions);
void Remove(int iType);
COptions* Get(int iType) const;
~COptionsMap();
};
/**
Returns the value indicating whether the given compression method is supported by the ZipArchive Library.
\param uCompressionMethod
The compression method. Can be one of the #CompressionMethod values.
\return
\c true, if the compression method is supported, \c false otherwise.
*/
static bool IsCompressionSupported(WORD uCompressionMethod)
{
return uCompressionMethod == methodStore || uCompressionMethod == methodDeflate
;
}
ZIP_SIZE_TYPE m_uUncomprLeft; ///< The number of bytes left to decompress.
ZIP_SIZE_TYPE m_uComprLeft; ///< The number of bytes left to compress.
DWORD m_uCrc32; ///< The CRC32 file checksum.
/**
Returns the value indicating, if the current #CZipCompressor object supports the given compression method.
\param uMethod
The compression method. Can be one of the #CompressionMethod values.
\return
\c true, if the compression method is supported; \c false otherwise.
*/
virtual bool CanProcess(WORD uMethod) = 0;
/**
The method called when a new file is opened for compression.
\param iLevel
The compression level.
\param pFile
The file being compressed.
\param pCryptograph
The current CZipCryptograph. Can be \c NULL, if no encryption is used.
\see
Compress
\see
FinishCompression
*/
virtual void InitCompression(int iLevel, CZipFileHeader* pFile, CZipCryptograph* pCryptograph)
{
InitBuffer();
m_uComprLeft = 0;
m_pFile = pFile;
m_pCryptograph = pCryptograph;
}
/**
The method called when a new file is opened for extraction.
\param pFile
The file being extracted.
\param pCryptograph
The current CZipCryptograph. Can be \c NULL, if no decryption is used.
\see
Decompress
\see
FinishDecompression
*/
virtual void InitDecompression(CZipFileHeader* pFile, CZipCryptograph* pCryptograph)
{
InitBuffer();
m_pFile = pFile;
m_pCryptograph = pCryptograph;
m_uComprLeft = m_pFile->GetDataSize(false, true);
m_uUncomprLeft = m_pFile->m_uUncomprSize;
m_uCrc32 = 0;
}
/**
Compresses the given data.
\param pBuffer
The buffer that holds the data to compress.
\param uSize
The size of \a pBuffer.
\see
InitCompression
\see
FinishCompression
*/
virtual void Compress(const void *pBuffer, DWORD uSize) = 0;
/**
Decompresses the given data.
\param pBuffer
The buffer that receives the decompressed data.
\param uSize
The size of \a pBuffer.
\return
The number of bytes decompressed and written to \a pBuffer.
\note
This method should be called repeatedly until it returns 0.
\see
InitDecompression
\see
FinishDecompression
*/
virtual DWORD Decompress(void *pBuffer, DWORD uSize) = 0;
/**
The method called at the end of the compression process.
\param bAfterException
Set to \c true, if an exception occurred before or to \c false otherwise.
\see
InitCompression
\see
Compress
*/
virtual void FinishCompression(bool bAfterException){}
/**
The method called at the end of the decompression process.
\param bAfterException
Set to \c true, if an exception occurred before or to \c false otherwise.
\see
InitDecompression
\see
Decompress
*/
virtual void FinishDecompression(bool bAfterException){}
/**
Returns the current options of the compressor.
\return
The current options for the compressor.
\see
<a href="kb">0610231446|options</a>
\see
CZipArchive::SetCompressionOptions
\see
UpdateOptions
*/
virtual const COptions* GetOptions() const
{
return NULL;
}
/**
Updates the current options with the options stored in \a optionsMap,
if the appropriate options are present in the map.
\param optionsMap
The map to get the new options from.
\see
<a href="kb">0610231446|options</a>
\see
GetOptions
*/
void UpdateOptions(const COptionsMap& optionsMap);
virtual ~CZipCompressor()
{
}
/**
A factory method that creates an appropriate compressor for the given compression method.
\param uMethod
The compression method to create a compressor for. Can be one of #CompressionMethod values.
\param pStorage
The current storage object.
*/
static CZipCompressor* CreateCompressor(WORD uMethod, CZipStorage* pStorage);
protected:
/**
Updates the current options with the new options.
\param pOptions
The new options to apply.
*/
virtual void UpdateOptions(const COptions* pOptions)
{
}
/**
Updates CRC value while compression.
\param pBuffer
A buffer with data for which the CRC value should be updated.
\param uSize
The size of the buffer.
*/
void UpdateFileCrc(const void *pBuffer, DWORD uSize);
/**
Updates CRC value while decompression.
\param pBuffer
A buffer with data for which the CRC value should be updated.
\param uSize
The size of the buffer.
*/
void UpdateCrc(const void *pBuffer, DWORD uSize);
/**
Flushes data in the buffer into the storage, encrypting the data if needed.
\note
Throws exceptions.
*/
void FlushWriteBuffer()
{
if (m_pCryptograph)
m_pCryptograph->Encode(m_pBuffer, (DWORD)m_uComprLeft);
m_pStorage->Write(m_pBuffer, (DWORD)m_uComprLeft, false);
m_uComprLeft = 0;
}
/**
Initializes the internal buffer.
\see
ReleaseBuffer
*/
void InitBuffer();
/**
Releases the internal buffer.
\see
InitBuffer
*/
void ReleaseBuffer()
{
m_pBuffer.Release();
}
/**
Converts internal error code of the compressor to the ZipArchive Library error code.
\param iErr
An internal error code.
\return
A ZipArchive Library error code.
*/
virtual int ConvertInternalError(int iErr) const
{
return iErr;
}
/**
Throws an exception with a given error code.
\param iErr
An error code.
\param bInternal
\c true, if \a iErr is an internal error code and needs a conversion to the ZipArchive Library error code; \c false otherwise.
\note
Throws exceptions.
\see
ConvertInternalError
*/
void ThrowError(int iErr, bool bInternal = false)
{
if (bInternal)
iErr = ConvertInternalError(iErr);
CZipException::Throw(iErr, m_pStorage->IsClosed(true) ? _T("") : (LPCTSTR)m_pStorage->m_pFile->GetFilePath());
}
};
#if _MSC_VER > 1000
#pragma warning( pop )
#endif
#endif

View File

@@ -0,0 +1,81 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipCrc32Cryptograph.h"
bool CZipCrc32Cryptograph::InitDecode(CZipAutoBuffer& password, CZipFileHeader& currentFile, CZipStorage& storage)
{
CryptInitKeys(password);
CZipAutoBuffer buf(ZIPARCHIVE_ENCR_HEADER_LEN);
storage.Read(buf, ZIPARCHIVE_ENCR_HEADER_LEN, false);
BYTE b = 0;
for (int i = 0; i < ZIPARCHIVE_ENCR_HEADER_LEN; i++)
{
b = buf[i]; // only temporary
CryptDecode((char&)b);
}
// check the last byte
return currentFile.IsDataDescriptor() ?
(BYTE(currentFile.m_uModTime >> 8) == b) : (BYTE(currentFile.m_uCrc32 >> 24) == b);
}
void CZipCrc32Cryptograph::InitEncode(CZipAutoBuffer& password, CZipFileHeader& currentFile, CZipStorage& storage)
{
CZipAutoBuffer buf(ZIPARCHIVE_ENCR_HEADER_LEN);
// use pseudo-crc since we don't know it yet
CryptInitKeys(password);
srand(UINT(time(NULL)));
// genereate pseudo-random sequence
char c;
char* buffer = (char*)buf;
for (int i = 0; i < ZIPARCHIVE_ENCR_HEADER_LEN - 2; i++)
{
int t1 = rand();
c = (char)((t1 >> 6) & 0xFF);
if (!c)
c = (char)(t1 & 0xFF);
CryptEncode(c);
buffer[i] = c;
}
long iCrc = (long)currentFile.m_uModTime << 16;
c = (char)((iCrc >> 16) & 0xFF);
CryptEncode(c);
buffer[ZIPARCHIVE_ENCR_HEADER_LEN - 2] = c;
c = (char)((iCrc >> 24) & 0xFF);
CryptEncode(c);
buffer[ZIPARCHIVE_ENCR_HEADER_LEN - 1] = c;
storage.Write(buf, ZIPARCHIVE_ENCR_HEADER_LEN, false);
currentFile.m_uComprSize += ZIPARCHIVE_ENCR_HEADER_LEN;
}
void CZipCrc32Cryptograph::CryptInitKeys(CZipAutoBuffer& password)
{
m_keys[0] = 305419896L;
m_keys[1] = 591751049L;
m_keys[2] = 878082192L;
for (DWORD i = 0; i < password.GetSize(); i++)
CryptUpdateKeys(password[i]);
}
void CZipCrc32Cryptograph::CryptUpdateKeys(char c)
{
m_keys[0] = CryptCRC32(m_keys[0], c);
m_keys[1] += m_keys[0] & 0xff;
m_keys[1] = m_keys[1] * 134775813L + 1;
c = char(m_keys[1] >> 24);
m_keys[2] = CryptCRC32(m_keys[2], c);
}

View File

@@ -0,0 +1,120 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipCrc32Cryptograph.h
* Includes the CZipCrc32Cryptograph class.
*
*/
#if !defined(ZIPARCHIVE_ZIPCRC32CRYPTOGRAPH_DOT_H)
#define ZIPARCHIVE_ZIPCRC32CRYPTOGRAPH_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "zlib/zlib.h"
#include "ZipCryptograph.h"
#include "ZipFileHeader.h"
#include "ZipStorage.h"
#define ZIPARCHIVE_ENCR_HEADER_LEN 12
/**
Performs the traditional zip encryption.
\see
<a href="kb">0610201627|std</a>
*/
class ZIP_API CZipCrc32Cryptograph : public CZipCryptograph
{
public:
CZipCrc32Cryptograph(){}
bool InitDecode(CZipAutoBuffer& password, CZipFileHeader& currentFile, CZipStorage& storage);
void InitEncode(CZipAutoBuffer& password, CZipFileHeader& currentFile, CZipStorage& storage);
void Decode(char* pBuffer, DWORD uSize)
{
for (DWORD i = 0; i < uSize; i++)
CryptDecode(pBuffer[i]);
}
void Encode(char* pBuffer, DWORD uSize)
{
for (DWORD i = 0; i < uSize; i++)
CryptEncode(pBuffer[i]);
}
bool CanHandle(int iEncryptionMethod)
{
return iEncryptionMethod == CZipCryptograph::encStandard;
}
/**
See CZipCryptograph::GetEncryptedInfoSizeBeforeData
*/
static DWORD GetEncryptedInfoSizeBeforeData()
{
return ZIPARCHIVE_ENCR_HEADER_LEN;
}
/**
See CZipCryptograph::GetEncryptedInfoSizeAfterData
*/
static DWORD GetEncryptedInfoSizeAfterData()
{
return 0;
}
/**
Returns the CRC table.
*/
static const DWORD* GetCRCTable()
{
return zarch_get_crc_table();
}
private:
void CryptDecode(char &c)
{
c ^= CryptDecryptByte();
CryptUpdateKeys(c);
}
char CryptDecryptByte()
{
int temp = (m_keys[2] & 0xffff) | 2;
return (char)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
void CryptInitKeys(CZipAutoBuffer& password);
void CryptUpdateKeys(char c);
DWORD CryptCRC32(DWORD l, char c)
{
const DWORD *CRC_TABLE = zarch_get_crc_table();
return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
}
void CryptEncode(char &c)
{
char t = CryptDecryptByte();
CryptUpdateKeys(c);
c ^= t;
}
DWORD m_keys[3];
public:
~CZipCrc32Cryptograph(){}
};
#endif

View File

@@ -0,0 +1,57 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipCryptograph.h"
#include "ZipAesCryptograph.h"
#include "ZipCrc32Cryptograph.h"
CZipCryptograph* CZipCryptograph::CreateCryptograph(int iEncryptionMethod)
{
if (iEncryptionMethod == encNone)
return NULL;
return new CZipCrc32Cryptograph();
}
DWORD CZipCryptograph::GetEncryptedInfoSize(int iEncryptionMethod)
{
if (iEncryptionMethod != encNone)
{
if (iEncryptionMethod == encStandard)
return CZipCrc32Cryptograph::GetEncryptedInfoSizeBeforeData() + CZipCrc32Cryptograph::GetEncryptedInfoSizeAfterData();
}
return 0;
}
DWORD CZipCryptograph::GetEncryptedInfoSizeBeforeData(int iEncryptionMethod)
{
if (iEncryptionMethod != encNone)
{
if (iEncryptionMethod == encStandard)
return CZipCrc32Cryptograph::GetEncryptedInfoSizeBeforeData();
}
return 0;
}
DWORD CZipCryptograph::GetEncryptedInfoSizeAfterData(int iEncryptionMethod)
{
if (iEncryptionMethod != encNone)
{
if (iEncryptionMethod == encStandard)
return CZipCrc32Cryptograph::GetEncryptedInfoSizeAfterData();
}
return 0;
}

View File

@@ -0,0 +1,231 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipCryptograph.h
* Includes the CZipCryptograph class.
*
*/
#if !defined(ZIPARCHIVE_ZIPCRYPTOGRAPH_DOT_H)
#define ZIPARCHIVE_ZIPCRYPTOGRAPH_DOT_H
#if _MSC_VER > 1000
#pragma once
#pragma warning( push )
#pragma warning (disable : 4100) // unreferenced formal parameter
#endif // _MSC_VER > 1000
#include "ZipAutoBuffer.h"
#include "ZipStorage.h"
class CZipFileHeader;
/**
The base class for cryptographs used in encryption and decryption of file data.
\see
<a href="kb">0610201627</a>
*/
class ZIP_API CZipCryptograph
{
public:
/**
The encryption method.
\see
<a href="kb">0610201627</a>
*/
enum EncryptionMethod
{
encStandard, ///< The traditional zip encryption.
encWinZipAes128, ///< WinZip AES 128-bit encryption.
encWinZipAes192, ///< WinZip AES 192-bit encryption.
encWinZipAes256, ///< WinZip AES 256-bit encryption.
encNone = 0xFF ///< Indicates no encryption.
};
/**
A factory method that creates an appropriate cryptograph for the given method.
\param iEncryptionMethod
The encryption method to create a cryptograph for. Can be one of #EncryptionMethod values.
\return
The new cryptograph. The caller is responsible for destroying the object.
If the method is not supported, creates CZipCrc32Cryptograph.
*/
static CZipCryptograph* CreateCryptograph(int iEncryptionMethod);
/**
Determines if the given method is one of the WinZip AES encryption method.
\param iEncryptionMethod
The encryption method to test. Can be one of #EncryptionMethod values.
\return
\c true, if the method is one the WinZip AES encryption methods; \c false otherwise.
*/
static bool IsWinZipAesEncryption(int iEncryptionMethod)
{
return iEncryptionMethod == encWinZipAes128 || iEncryptionMethod == encWinZipAes192 || iEncryptionMethod == encWinZipAes256;
}
/**
Returns the total size of the extra data that is added to the compression stream during encryption with the given method.
\param iEncryptionMethod
The encryption method. Can be one of #EncryptionMethod values.
\return
The total size of extra data for the given encryption method.
*/
static DWORD GetEncryptedInfoSize(int iEncryptionMethod);
/**
Returns the size of the extra data that is added before the compression stream during encryption with the given method.
\param iEncryptionMethod
The encryption method. Can be one of #EncryptionMethod values.
\return
The size of extra data at the beginning of the compression stream for the given encryption method.
*/
static DWORD GetEncryptedInfoSizeBeforeData(int iEncryptionMethod);
/**
Returns the size of the extra data that is added after the compression stream during encryption with the given method.
\param iEncryptionMethod
The encryption method. Can be one of #EncryptionMethod values.
\return
The size of extra data at the end of the compression stream for the given encryption method.
*/
static DWORD GetEncryptedInfoSizeAfterData(int iEncryptionMethod);
/**
Determines if the given encryption method is supported by the current compilation of the ZipArchive Library.
\param iEncryptionMethod
The encryption method to test. Can be one of #EncryptionMethod values.
\return
\c true, if the method is supported; \c false otherwise.
*/
static bool IsEncryptionSupported(int iEncryptionMethod)
{
return iEncryptionMethod == encStandard;
}
/**
The method called when an existing file is opened for extraction.
\param password
The supplied password with the CZipArchive::SetPassword method.
\param currentFile
The file being decoded and extracted.
\param storage
The current CZipStorage.
\return
\c true, if the password is initially considered correct; \c false otherwise.
*/
virtual bool InitDecode(CZipAutoBuffer& password, CZipFileHeader& currentFile, CZipStorage& storage) = 0;
/**
The method called when a new file is opened for compression.
\param password
The supplied password with the CZipArchive::SetPassword method.
\param currentFile
The file being compressed and encoded.
\param storage
The current CZipStorage.
*/
virtual void InitEncode(CZipAutoBuffer& password, CZipFileHeader& currentFile, CZipStorage& storage) = 0;
/**
Decodes the given data.
\param pBuffer
The buffer that holds the data to decode and that receives the results.
\param uSize
The size of \a pBuffer.
*/
virtual void Decode(char* pBuffer, DWORD uSize) = 0;
/**
Encodes the given data.
\param pBuffer
The buffer that holds the data to encode and that receives the results.
\param uSize
The size of \a pBuffer.
*/
virtual void Encode(char* pBuffer, DWORD uSize) = 0;
/**
The method called at the end of the decoding process.
\param currentFile
The file being decoded and extracted.
\param storage
The current CZipStorage.
*/
virtual void FinishDecode(CZipFileHeader& currentFile, CZipStorage& storage){};
/**
The method called at the end of the decoding process.
\param currentFile
The file being compressed and encoded.
\param storage
The current CZipStorage.
*/
virtual void FinishEncode(CZipFileHeader& currentFile, CZipStorage& storage){};
/**
Returns the value indicating whether the current compressor can handle the given encryption method.
\param iEncryptionMethod
The encryption method to test. Can be one of #EncryptionMethod values.
\return
\c true, if the current compressor can handle the given encryption method; \c false otherwise.
*/
virtual bool CanHandle(int iEncryptionMethod)
{
return false;
}
virtual ~CZipCryptograph(){}
};
#if _MSC_VER > 1000
#pragma warning( pop )
#endif // _MSC_VER > 1000
#endif

View File

@@ -0,0 +1,279 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipException.h"
#include "zlib/zlib.h"
#include <errno.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#if defined _MFC_VER && defined ZIP_ARCHIVE_MFC
IMPLEMENT_DYNAMIC( CZipException, CException)
#endif
CZipException::CZipException(int iCause, LPCTSTR lpszZipName)
#ifdef _MFC_VER
:CException(TRUE)
#endif
{
m_iCause = iCause;
if (lpszZipName)
m_szFileName = lpszZipName;
}
CZipException::~CZipException() throw()
{
}
// inline void CZipException::Throw(int iZipError, LPCTSTR lpszZipName)
// {
// #ifdef _MFC_VER
// throw new CZipException(iZipError, lpszZipName);
// #else
// CZipException e(iZipError, lpszZipName);
// throw e;
// #endif
// MSVC++: ignore "Unreachable code" warning here, it's due to
// optimizations
// }
#ifdef ZIP_ENABLE_ERROR_DESCRIPTION
ZBOOL CZipException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
UINT* )
{
if (!lpszError || !nMaxError)
return FALSE;
CZipString sz = GetErrorDescription();
if (sz.IsEmpty())
return FALSE;
UINT iLen = sz.GetLength();
if (nMaxError - 1 < iLen)
iLen = nMaxError - 1;
LPTSTR lpsz = sz.GetBuffer(iLen);
#if _MSC_VER >= 1400
#ifdef _UNICODE
wcsncpy_s(lpszError, nMaxError, lpsz, iLen);
#else
strncpy_s(lpszError, nMaxError, lpsz, iLen);
#endif
#else
#ifdef _UNICODE
wcsncpy(lpszError, lpsz, iLen);
#else
strncpy(lpszError, lpsz, iLen);
#endif
#endif
lpszError[iLen] = _T('\0');
return TRUE;
}
CZipString CZipException::GetErrorDescription()
{
return GetInternalErrorDescription(m_iCause);
}
CZipString CZipException::GetSystemErrorDescription()
{
#ifdef WIN32
DWORD x = GetLastError();
if (x)
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, x, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf, 0, NULL);
CZipString sz = (LPCTSTR)lpMsgBuf;
LocalFree(lpMsgBuf);
return sz;
}
#endif
return GetInternalErrorDescription(errno == 0 ? genericError : errno, true);
}
CZipString CZipException::GetInternalErrorDescription(int iCause, bool bNoLoop)
{
CZipString sz;
switch (iCause)
{
case EROFS:
sz = _T("Read-only file system.");
break;
case ESPIPE:
sz = _T("Illegal seek.");
break;
case ENOSPC:
sz = _T("No space left on device.");
break;
case EFBIG:
sz = _T("File too large.");
break;
case EMFILE:
sz = _T("Too many open files.");
break;
case ENFILE:
sz = _T("File table overflow.");
break;
case EINVAL:
sz = _T("Invalid argument.");
break;
case EISDIR:
sz = _T("Is a directory.");
break;
case ENOTDIR:
sz = _T("Not a directory.");
break;
case ENODEV:
sz = _T("No such device.");
break;
case EXDEV:
sz = _T("Cross-device link.");
break;
case EEXIST:
sz = _T("File exists.");
break;
case EFAULT:
sz = _T("Bad address.");
break;
case EACCES:
sz = _T("Permission denied.");
break;
case ENOMEM:
sz = _T("Not enough space.");
break;
case EBADF:
sz = _T("Bad file number.");
break;
case ENXIO:
sz = _T("No such device or address.");
break;
case EIO:
sz = _T("I/O error.");
break;
case EINTR:
sz = _T("Interrupted system call.");
break;
case ENOENT:
sz = _T("No such file or directory.");
break;
case EPERM:
sz = _T("Not super-user.");
break;
case badZipFile:
sz = _T("Damaged or not a zip file.");
break;
case badCrc:
sz = _T("Crc is mismatched.");
break;
case noCallback:
sz = _T("There is no spanned archive callback object set.");
break;
case aborted:
sz = _T("Volume change aborted in a segmented archive.");
break;
case abortedAction:
sz = _T("Action aborted.");
break;
case abortedSafely:
sz = _T("Action aborted safely.");
break;
case nonRemovable:
sz = _T("The device selected for the spanned archive is not removable.");
break;
case tooManyVolumes:
sz = _T("The limit of the maximum volumes reached.");
break;
case tooManyFiles:
sz = _T("The limit of the maximum files in an archive reached.");
break;
case tooLongData:
sz = _T("The filename, the comment or the local or central extra field of the file added to the archive is too long.");
break;
case tooBigSize:
sz = _T("The file size is too large to be supported.");
break;
case badPassword:
sz = _T("An incorrect password set for the file being decrypted.");
break;
case dirWithSize:
sz = _T("The directory with a non-zero size found while testing.");
break;
case internalError:
sz = _T("An internal error.");
break;
case notRemoved:
sz.Format(_T("%s (%s)."), _T("Error while removing a file"), (LPCTSTR)GetSystemErrorDescription());
break;
case notRenamed:
sz.Format(_T("%s (%s)."), _T("Error while renaming a file"), (LPCTSTR)GetSystemErrorDescription());
break;
case platfNotSupp:
sz = _T("Cannot create a file for the specified platform.");
break;
case cdirNotFound:
sz = _T("The central directory was not found in the archive (or you were trying to open not the last volume of a segmented archive).");
break;
case noZip64:
sz = _T("The Zip64 format has not been enabled for the library, but is required to use the archive.");
break;
case noAES:
sz = _T("WinZip AES encryption has not been enabled for the library, but is required to decompress the archive.");
break;
#ifdef ZIP_ARCHIVE_STL
case outOfBounds:
sz = _T("The collection is empty and the bounds do not exist.");
break;
#endif
#ifdef ZIP_ARCHIVE_USE_LOCKING
case mutexError:
sz = _T("Locking or unlocking resources access was unsuccessful.");
break;
#endif
case streamEnd:
sz = _T("Zlib library error (end of stream).");
break;
case errNo:
sz = GetInternalErrorDescription(errno != errNo ? errno : genericError);
break;
case streamError:
sz = _T("Zlib library error (stream error).");
break;
case dataError:
sz = _T("Zlib library error (data error).");
break;
case memError:
sz = _T("Not enough memory.");
break;
case bufError:
sz = _T("Zlib library error (buffer error).");
break;
case versionError:
sz = _T("Zlib library error (version error).");
break;
default:
sz = bNoLoop ? _T("Unknown error") :(LPCTSTR) GetSystemErrorDescription();
}
return sz;
}
#endif //ZIP_ENABLE_ERROR_DESCRIPTION

View File

@@ -0,0 +1,223 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipException.h
* Includes the CZipException class.
*
*/
#if !defined(ZIPARCHIVE_ZIPEXCEPTION_DOT_H)
#define ZIPARCHIVE_ZIPEXCEPTION_DOT_H
#if _MSC_VER > 1000
#pragma once
#pragma warning( push )
#pragma warning (disable:4702) // disable "Unreachable code" warning in Throw function in the Release mode
#if defined ZIP_HAS_DLL
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#pragma warning( disable : 4275 ) // non dll-interface used as base for dll-interface class
#endif
#endif
#include "ZipString.h"
#include "ZipBaseException.h"
#include "ZipExport.h"
/**
Represents exceptions specific to the ZipArchive Library.
\see
<a href="kb">0610222049</a>
*/
class ZIP_API CZipException : public CZipBaseException
{
public:
/**
Throws an exception.
Whether it throws an object or a pointer to it, depends
on the current version (STL or MFC correspondingly).
\param iCause
The error cause. Takes one of the #ZipErrors values.
\param lpszZipName
The name of the file where the error occurred (if applicable).
May be \c NULL.
\see
<a href="kb">0610222049</a>
*/
static void Throw(int iCause = CZipException::genericError, LPCTSTR lpszZipName = NULL)
{
#ifdef ZIP_ARCHIVE_MFC
throw new CZipException(iCause, lpszZipName);
#else
CZipException e(iCause, lpszZipName);
throw e;
#endif
}
/**
Initializes a new instance of the CZipException class.
\param iCause
The error cause. Takes one of the #ZipErrors values.
\param lpszZipName
The name of the file where the error occurred (if applicable).
May be \c NULL.
*/
CZipException(int iCause = genericError, LPCTSTR lpszZipName = NULL);
CZipException(CZipException& e)
{
m_szFileName = e.m_szFileName;
m_iCause = e.m_iCause;
}
#ifdef ZIP_ENABLE_ERROR_DESCRIPTION
/**
Gets the error description.
\return
The error description.
*/
CZipString GetErrorDescription();
/**
Gets the error description. This method is provided for compatibility with the MFC version (\c CException::GetErrorMessage).
\param lpszError
The buffer to receive the error message.
\param nMaxError
The maximum number of characters \a lpszError can hold,
including the ending \c NULL character.
\return
\c TRUE if the error string was successfully copied to \a lpszError; \c FALSE otherwise.
\note
The method will not copy more than \c nMaxError - 1 characters
to the buffer, and it always appends a \c NULL character.
If \a lpszError is too small, the error message will be truncated.
*/
ZBOOL GetErrorMessage(LPTSTR lpszError, UINT nMaxError, UINT* = NULL);
#endif //ZIP_ENABLE_ERROR_DESCRIPTION
/**
The name of the zip file where the error occurred.
*/
CZipString m_szFileName;
/**
The codes of errors thrown by the ZipArchive Library.
*/
enum ZipErrors
{
noError, ///< No error.
// 1 - 42 reserved for errno (from STL) values - used only in non-MFC versions
// 43 - 99 reserved
genericError = 100, ///< An unknown error.
badZipFile, ///< Damaged or not a zip file.
badCrc, ///< Crc is mismatched.
noCallback, ///< There is no spanned archive callback object set.
aborted, ///< The volume change callback in a segmented archive method returned \c false.
abortedAction, ///< The action callback method returned \c false.
abortedSafely, ///< The action callback method returned \c false, but the data is not corrupted.
nonRemovable, ///< The device selected for the spanned archive is not removable.
tooManyVolumes, ///< The limit of the maximum volumes reached.
tooManyFiles, ///< The limit of the maximum files in an archive reached.
tooLongData, ///< The filename, the comment or the local or central extra field of the file added to the archive is too long.
tooBigSize, ///< The file size is too large to be supported.
badPassword, ///< An incorrect password set for the file being decrypted.
dirWithSize, ///< The directory with a non-zero size found while testing.
internalError, ///< An internal error.
notRemoved, ///< Error while removing a file (under Windows call \c GetLastError() to find out more).
notRenamed, ///< Error while renaming a file (under Windows call \c GetLastError() to find out more).
platfNotSupp, ///< Cannot create a file for the specified platform.
cdirNotFound, ///< The central directory was not found in the archive (or you were trying to open not the last disk of a segmented archive).
noZip64, ///< The Zip64 format has not been enabled for the library, but is required to use the archive.
noAES, ///< WinZip AES encryption has not been enabled for the library, but is required to decompress the archive.
#ifdef ZIP_ARCHIVE_STL
outOfBounds, ///< The collection is empty and the bounds do not exist.
#endif
#ifdef ZIP_ARCHIVE_USE_LOCKING
mutexError, ///< Locking or unlocking resources access was unsuccessful.
#endif
streamEnd = 500, ///< Zlib library error.
needDict, ///< Zlib library error.
errNo, ///< Zlib library error.
streamError, ///< Zlib library error.
dataError, ///< Zlib library error.
memError, ///< Zlib library or \c CZipMemFile error.
bufError, ///< Zlib library error.
versionError, ///< Zlib library error.
};
/**
The error code - takes one of the CZipException::ZipErrors values.
*/
int m_iCause;
virtual ~CZipException() throw();
protected:
#ifdef ZIP_ENABLE_ERROR_DESCRIPTION
/**
Gets the error description.
\param iCause
The error cause. Takes one of the #ZipErrors values.
\param bNoLoop
If \c true, does not search for en error description, it the error code is #genericError.
\return
The error description.
*/
CZipString GetInternalErrorDescription(int iCause, bool bNoLoop = false);
/**
Gets the error description based on system variables.
\return
The error description.
*/
CZipString GetSystemErrorDescription();
#endif //ZIP_ENABLE_ERROR_DESCRIPTION
#if defined _MFC_VER && defined ZIP_ARCHIVE_MFC
DECLARE_DYNAMIC(CZipException)
#endif
};
#if _MSC_VER > 1000
#pragma warning( pop )
#endif
#endif // !defined(ZIPARCHIVE_ZIPEXCEPTION_DOT_H)

View File

@@ -0,0 +1,43 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipArchive.h"
#include "ZipExtraData.h"
#include "BytesWriter.h"
using namespace ZipArchiveLib;
bool CZipExtraData::Read(char* buffer, WORD uSize)
{
if (uSize < 4)
return false;
WORD size;
CBytesWriter::ReadBytes(m_uHeaderID, buffer);
CBytesWriter::ReadBytes(size, buffer + 2);
if (uSize - 4 < size)
return false;
m_data.Allocate(size);
memcpy(m_data, buffer + 4, size);
return true;
}
WORD CZipExtraData::Write(char* buffer)const
{
CBytesWriter::WriteBytes(buffer, m_uHeaderID);
WORD size = (WORD)m_data.GetSize();
CBytesWriter::WriteBytes(buffer + 2, size);
memcpy(buffer + 4, m_data, size);
return (WORD)(size + 4);
}

View File

@@ -0,0 +1,158 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipExtraData.h
* Includes the CZipExtraData class.
*
*/
#if !defined(ZIPARCHIVE_ZIPEXTRADATA_DOT_H)
#define ZIPARCHIVE_ZIPEXTRADATA_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "ZipExport.h"
#include "ZipAutoBuffer.h"
#include "ZipExtraField.h"
#include "memory.h"
/**
Represents a single data record in an extra field.
\see
<a href="kb">0610242300</a>
*/
class ZIP_API CZipExtraData
{
friend class CZipExtraField;
public:
/**
The custom data contained by this record.
*/
CZipAutoBuffer m_data;
CZipExtraData()
{
m_uHeaderID = 0;
}
CZipExtraData(const CZipExtraData& extra)
{
*this = extra;
}
/**
Initializes a new instance of the CZipExtraData class.
\param uHeaderID
The unique ID of the data.
*/
CZipExtraData(WORD uHeaderID)
{
m_uHeaderID = uHeaderID;
}
CZipExtraData& operator=(const CZipExtraData& extra)
{
m_uHeaderID = extra.m_uHeaderID;
DWORD uSize = extra.m_data.GetSize();
m_data.Allocate(uSize);
if (uSize > 0)
memcpy(m_data, extra.m_data, uSize);
return *this;
}
bool operator==(const CZipExtraData& extra)
{
return m_uHeaderID == extra.m_uHeaderID && m_data.GetSize() == extra.m_data.GetSize() && memcmp(m_data, extra.m_data, m_data.GetSize()) == 0;
}
bool operator != (const CZipExtraData& extra)
{
return !(*this == extra);
}
bool operator > (const CZipExtraData& extra)
{
return m_uHeaderID > extra.m_uHeaderID;
}
bool operator < (const CZipExtraData& extra)
{
return m_uHeaderID < extra.m_uHeaderID;
}
bool operator >= (const CZipExtraData& extra)
{
return m_uHeaderID > extra.m_uHeaderID || *this == extra;
}
bool operator <= (const CZipExtraData& extra)
{
return m_uHeaderID < extra.m_uHeaderID || *this == extra;
}
/**
Gets the total size, the extra data will occupy in the archive.
\return
The size in bytes.
*/
int GetTotalSize() const
{
return 4 + m_data.GetSize();
}
/**
Gets the data ID.
\return
The data ID.
*/
WORD GetHeaderID() const
{
return m_uHeaderID;
}
protected:
/**
Reads the extra data record from \a buffer.
\param buffer
The buffer to read the data from.
\param uSize
The size of the data to read.
\return
\c false, if \a uSize was smaller than the declared extra data size; \c true otherwise.
*/
bool Read(char* buffer, WORD uSize);
/**
Writes the extra data record to \a buffer.
\param buffer
The buffer to write to.
\return
The total size of extra data in bytes.
*/
WORD Write(char* buffer)const;
private:
WORD m_uHeaderID;
};
#endif // !defined(ZIPARCHIVE_ZIPEXTRADATA_DOT_H)

View File

@@ -0,0 +1,88 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipExtraField.h"
bool CZipExtraField::Read(CZipStorage *pStorage, WORD uSize)
{
if (uSize == 0)
return true;
Clear();
CZipAutoBuffer buffer;
buffer.Allocate(uSize);
pStorage->Read(buffer, uSize, true);
char* position = (char*) buffer;
do
{
CZipExtraData* pExtra = new CZipExtraData();
if (!pExtra->Read(position, uSize))
{
delete pExtra;
return false;
}
int totalSize = pExtra->GetTotalSize();
if (totalSize > uSize || totalSize < 0)
return false;
position += totalSize;
uSize = (WORD)(uSize - totalSize);
Add(pExtra);
}
while (uSize > 0);
return true;
}
void CZipExtraField::Write(char* buffer)const
{
int offset = 0;
for (int i = 0; i < GetCount(); i++)
offset += GetAt(i)->Write(buffer + offset);
}
int CZipExtraField::GetTotalSize()const
{
int total = 0;
for (int i = 0; i < GetCount(); i++)
total += GetAt(i)->GetTotalSize();
return total;
}
void CZipExtraField::RemoveInternalHeaders()
{
for (int i = GetCount() - 1; i >= 0; i--)
{
WORD headerID = GetAt(i)->GetHeaderID();
if (
headerID == ZIP_EXTRA_ZARCH_NAME)
RemoveAt(i);
}
}
CZipExtraData* CZipExtraField::Lookup(WORD headerID, int& index) const
{
// we can do a non-efficient search here
// usually the number of extra fields is low, if any
for (int i = 0; i < GetCount(); i++)
{
CZipExtraData* pExtra = GetAt(i);
if (pExtra->m_uHeaderID == headerID)
{
index = i;
return pExtra;
}
}
return NULL;
}

View File

@@ -0,0 +1,273 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipExtraField.h
* Includes the CZipExtraField class.
*
*/
#if !defined(ZIPARCHIVE_ZIPEXTRAFIELD_DOT_H)
#define ZIPARCHIVE_ZIPEXTRAFIELD_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "ZipExport.h"
#include "ZipExtraData.h"
#include "ZipCollections.h"
#include "ZipStorage.h"
#define ZIP_EXTRA_ZARCH_NAME 0x5A4C // ZL - ZipArchive Library
#define ZIP_EXTRA_ZARCH_SEEK 0x5A4D
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#endif
/**
Represents a local or central extra field in a zip archive.
This is a collection of extra data records (CZipExtraData).
\see
<a href="kb">0610242300</a>
\see
CZipExtraData
*/
class ZIP_API CZipExtraField
{
friend class CZipFileHeader;
public:
CZipExtraField(){}
CZipExtraField(const CZipExtraField& arr)
{
*this = arr;
}
CZipExtraField& operator=(const CZipExtraField& field)
{
Clear();
for (int i = 0; i < field.GetCount(); i++)
Add(new CZipExtraData(*field.GetAt(i)));
return *this;
}
/**
Gets the total size, the extra data will occupy in the archive.
\return
The size in bytes.
*/
int GetTotalSize() const;
/**
Validates the current size of the extra field.
\return
\c false, if the size is larger than allowed; \c false otherwise.
*/
bool Validate() const
{
return GetTotalSize() <= USHRT_MAX;
}
/**
Gets the number of extra data records included in the extra field.
\return
The number of extra fields included.
*/
int GetCount() const
{
return (int)m_aData.GetSize();
}
/**
Gets the extra data record at the given index.
\param index
The index of extra data record to retrieve.
\return
The extra data record.
*/
CZipExtraData* GetAt(int index) const
{
return m_aData.GetAt(index);
}
/**
Removes the extra data record at the given index.
\param index
The index of the extra data record to remove.
*/
void RemoveAt(int index)
{
delete (GetAt(index));
m_aData.RemoveAt(index);
}
/**
Adds a new extra data record to the extra field.
\param pExtra
The extra data record to add.
\return
The index of \a pExtra in the internal collection.
*/
int Add(CZipExtraData* pExtra)
{
return (int)m_aData.Add(pExtra);
}
/**
Creates a new extra data record with the given ID
and adds it to the extra field.
\param headerID
The extra data ID.
\return
The created extra data record.
\see
CZipExtraData::GetHeaderID
*/
CZipExtraData* CreateNew(WORD headerID)
{
int temp;
return CreateNew(headerID, temp);
}
/**
Creates a new extra data record with the given ID
and adds it to the extra field.
\param headerID
The extra data ID.
\param idx
Receives the value of the index of the new
extra data in the internal collection.
\return
The created extra data record.
\see
CZipExtraData::GetHeaderID
*/
CZipExtraData* CreateNew(WORD headerID, int& idx)
{
CZipExtraData* pData = new CZipExtraData(headerID);
idx = (int)m_aData.Add(pData);
return pData;
}
/**
Removes all extra data records from the extra field,
that are internally used by the ZipArchive Library.
*/
void RemoveInternalHeaders();
/**
Lookups the extra field for the extra data record with the given ID.
\param headerID
The ID of the extra data to lookup.
\return
The found extra data record or \c NULL, if the extra data could not be found.
*/
CZipExtraData* Lookup(WORD headerID) const
{
int temp;
return Lookup(headerID, temp);
}
/**
Returns the value indicating whether the extra data record with the given ID is present in the extra field.
\param headerID
The ID of the extra data to check.
\return
\c true, if the extra data record with the given ID is present in the extra field; \c false otherwise.
*/
bool HasHeader(WORD headerID)
{
return Lookup(headerID) != NULL;
}
/**
Lookups the extra field for the extra data record with the given ID.
\param headerID
The ID of the extra data to lookup.
\param index
Receives the value of the index of the found
extra data in the internal collection.
\return
The found extra data record or \c NULL, if the extra data could not be found.
*/
CZipExtraData* Lookup(WORD headerID, int& index) const;
~CZipExtraField()
{
Clear();
}
protected:
/**
Removes all extra data records from the extra field.
*/
void Clear()
{
for (int i = 0; i < GetCount(); i++)
delete (GetAt(i));
m_aData.RemoveAll();
}
/**
Reads the extra field from \a buffer.
\param pStorage
The storage to read the data from.
\param uSize
The size of the data to read.
\return
\c false, if \a uSize was smaller than the declared extra field size; \c true otherwise.
*/
bool Read(CZipStorage* pStorage, WORD uSize);
/**
Writes the extra field to \a buffer.
\param buffer
The buffer to write to.
*/
void Write(char* buffer) const;
private:
CZipArray<CZipExtraData*> m_aData;
};
#endif // !defined(ZIPARCHIVE_ZIPEXTRAFIELD_DOT_H)

View File

@@ -0,0 +1,39 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipFile.h
* Includes the CZipFile class.
*
*/
#if !defined(ZIPARCHIVE_ZIPFILE_DOT_H)
#define ZIPARCHIVE_ZIPFILE_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "_features.h"
#if defined ZIP_ARCHIVE_STL || defined ZIP_FILE_USES_STL
#include "ZipFile_stl.h"
#else
#include "ZipFile_mfc.h"
#endif
#endif // !defined(ZIPARCHIVE_ZIPFILE_DOT_H)

View File

@@ -0,0 +1,792 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipFileHeader.h"
#include "ZipAutoBuffer.h"
#include "ZipArchive.h"
#include "ZipPlatform.h"
#include "ZipCompatibility.h"
#include <time.h>
#include "ZipCrc32Cryptograph.h"
#include "BytesWriter.h"
#define FILEHEADERSIZE 46
#define LOCALFILEHEADERSIZE 30
#define ZIP_EXTRA_ZARCH_NAME_VER 1
using namespace ZipArchiveLib;
char CZipFileHeader::m_gszSignature[] = {0x50, 0x4b, 0x01, 0x02};
char CZipFileHeader::m_gszLocalSignature[] = {0x50, 0x4b, 0x03, 0x04};
CZipFileHeader::CZipFileHeader()
{
m_uExternalAttr = 0;//ZipPlatform::GetDefaultAttributes();
m_uModDate = m_uModTime = 0;
m_uMethod = CZipCompressor::methodDeflate;
m_uVersionMadeBy = 0;
m_uCrc32 = 0;
// initialize to 0, because on 64 bit platform unsigned long is 8 byte and we are copying only 4 bytes in Read()
m_uComprSize = m_uUncomprSize = m_uOffset = 0;
m_uLocalFileNameSize = 0;
m_uLocalComprSize = m_uLocalUncomprSize = 0;
m_uVolumeStart = 0;
m_pszFileName = NULL;
m_uEncryptionMethod = CZipCryptograph::encNone;
m_bIgnoreCrc32 = false;
m_uFlag = 0;
}
CZipFileHeader::~CZipFileHeader()
{
if (m_pszFileName != NULL)
delete m_pszFileName;
}
bool CZipFileHeader::Read(CZipCentralDir& centralDir, bool bReadSignature)
{
CZipStorage *pStorage = centralDir.m_pStorage;
WORD uFileNameSize, uCommentSize, uExtraFieldSize;
CZipAutoBuffer buf(FILEHEADERSIZE);
if (bReadSignature)
{
pStorage->Read(buf, FILEHEADERSIZE, true);
if (!VerifySignature(buf))
return false;
}
else
pStorage->Read((char*)buf + 4, FILEHEADERSIZE - 4, true);
CBytesWriter::ReadBytes(m_uVersionMadeBy, buf + 4);
CBytesWriter::ReadBytes(m_uVersionNeeded, buf + 6);
CBytesWriter::ReadBytes(m_uFlag, buf + 8);
CBytesWriter::ReadBytes(m_uMethod, buf + 10);
CBytesWriter::ReadBytes(m_uModTime, buf + 12);
CBytesWriter::ReadBytes(m_uModDate, buf + 14);
CBytesWriter::ReadBytes(m_uCrc32, buf + 16);
CBytesWriter::ReadBytes(m_uComprSize, buf + 20, 4);
CBytesWriter::ReadBytes(m_uUncomprSize, buf + 24, 4);
CBytesWriter::ReadBytes(uFileNameSize, buf + 28);
CBytesWriter::ReadBytes(uExtraFieldSize, buf + 30);
CBytesWriter::ReadBytes(uCommentSize, buf + 32);
CBytesWriter::ReadBytes(m_uVolumeStart, buf + 34, 2);
CBytesWriter::ReadBytes(m_uInternalAttr, buf + 36);
CBytesWriter::ReadBytes(m_uExternalAttr, buf + 38);
CBytesWriter::ReadBytes(m_uOffset, buf + 42, 4);
buf.Release();
// we may need to modify this later
m_uEncryptionMethod = (BYTE)((m_uFlag & (WORD) 1) != 0 ? CZipCryptograph::encStandard : CZipCryptograph::encNone);
ZIP_VOLUME_TYPE uCurDsk = pStorage->GetCurrentVolume();
m_pszFileNameBuffer.Allocate(uFileNameSize); // don't add NULL at the end
pStorage->Read(m_pszFileNameBuffer, uFileNameSize, true);
if (centralDir.m_pStringSettings->IsStandardNameCodePage())
m_stringSettings.SetDefaultNameCodePage(GetSystemCompatibility());
else
m_stringSettings.m_uNameCodePage = centralDir.m_pStringSettings->m_uNameCodePage;
if (!centralDir.m_pStringSettings->IsStandardCommentCodePage())
m_stringSettings.m_uCommentCodePage = centralDir.m_pStringSettings->m_uCommentCodePage;
if (!m_aCentralExtraData.Read(pStorage, uExtraFieldSize))
return false;
CZipExtraData* pExtra = m_aCentralExtraData.Lookup(ZIP_EXTRA_ZARCH_NAME);
if (pExtra != NULL)
{
WORD uExtraDataSize = (WORD)pExtra->m_data.GetSize();
int offset = 1;
if (offset > uExtraDataSize)
return false;
if (pExtra->m_data[0] <= ZIP_EXTRA_ZARCH_NAME_VER) // else don't parse it
{
offset++;
if (offset > uExtraDataSize)
return false;
BYTE flag = pExtra->m_data[1];
bool bReadCommentCp = (flag & 4) != 0;
if ((flag & 1) != 0)
{
// code page present
if (offset + 4 > uExtraDataSize)
return false;
// avoid warnings
DWORD temp;
CBytesWriter::ReadBytes(temp, pExtra->m_data + offset);
m_stringSettings.m_uNameCodePage = temp;
offset += 4;
}
if ((flag & 3) == 3)
{
m_stringSettings.m_bStoreNameInExtraData = true;
int iFileNameSize = pExtra->m_data.GetSize() - 2 - 4;
if (bReadCommentCp)
iFileNameSize -= 4;
// code page present
if (offset + iFileNameSize > uExtraDataSize || iFileNameSize <= 0)
return false;
CZipAutoBuffer buffer;
buffer.Allocate(iFileNameSize);
memcpy(buffer, pExtra->m_data + offset, iFileNameSize);
m_pszFileName = new CZipString(_T(""));
ZipCompatibility::ConvertBufferToString(*m_pszFileName, buffer, m_stringSettings.m_uNameCodePage);
offset += iFileNameSize;
m_pszFileNameBuffer.Release();
}
else
m_stringSettings.m_bStoreNameInExtraData = false;
if (bReadCommentCp)
{
// code page present
if (offset + 4 > uExtraDataSize)
return false;
DWORD temp;
CBytesWriter::ReadBytes(temp, pExtra->m_data + offset);
m_stringSettings.m_uCommentCodePage = temp;
// offset += 4;
}
}
}
if (uCommentSize)
{
m_pszComment.Allocate(uCommentSize);
pStorage->Read(m_pszComment, uCommentSize, true);
}
return pStorage->GetCurrentVolume() == uCurDsk; // check that the whole header is in one volume
}
time_t CZipFileHeader::GetTime()const
{
struct tm atm;
atm.tm_sec = (m_uModTime & ~0xFFE0) << 1;
atm.tm_min = (m_uModTime & ~0xF800) >> 5;
atm.tm_hour = m_uModTime >> 11;
atm.tm_mday = m_uModDate & ~0xFFE0;
atm.tm_mon = ((m_uModDate & ~0xFE00) >> 5) - 1;
atm.tm_year = (m_uModDate >> 9) + 80;
atm.tm_isdst = -1;
return mktime(&atm);
}
// write the header to the central dir
DWORD CZipFileHeader::Write(CZipStorage *pStorage)
{
m_aCentralExtraData.RemoveInternalHeaders();
WORD uMethod = m_uMethod;
if (!CheckLengths(false))
CZipException::Throw(CZipException::tooLongData);
PrepareFileName();
if (m_stringSettings.m_bStoreNameInExtraData)
{
if (m_pszFileName == NULL && m_pszFileNameBuffer.IsAllocated())
GetFileName(false); // don't clear the buffer, it will be needed in a moment
ASSERT(m_pszFileName != NULL);
if (m_pszFileName->GetLength() == 0)
m_stringSettings.m_bStoreNameInExtraData = false;
}
int iSystemCompatibility = GetSystemCompatibility();
if (!m_stringSettings.IsStandard(iSystemCompatibility))
{
CZipExtraData* pExtra = m_aCentralExtraData.CreateNew(ZIP_EXTRA_ZARCH_NAME);
bool bWriteCommentCp = !m_stringSettings.IsStandardCommentCodePage();
BYTE flag = 0;
int offset = 2;
char* data = NULL;
if (m_stringSettings.m_bStoreNameInExtraData)
{
CZipAutoBuffer buffer;
// m_pszFileNameBuffer contains CP_ACP page, we don't check if the current page is CP_ACP - too large dependency on PrepareFileName
ZipCompatibility::ConvertStringToBuffer(*m_pszFileName, buffer, m_stringSettings.m_uNameCodePage);
int size = 2 + 4 + buffer.GetSize();
if (bWriteCommentCp)
size += 4;
pExtra->m_data.Allocate(size);
data = (char*)pExtra->m_data;
CBytesWriter::WriteBytes(data + offset, (DWORD)m_stringSettings.m_uNameCodePage);
offset += 4;
memcpy(data + offset, buffer, buffer.GetSize());
offset += buffer.GetSize();
flag = 3;
}
else if (!m_stringSettings.IsStandardNameCodePage(iSystemCompatibility))
{
int size = 2 + 4;
if (bWriteCommentCp)
size += 4;
pExtra->m_data.Allocate(size);
data = (char*)pExtra->m_data;
CBytesWriter::WriteBytes(data + offset, (DWORD)m_stringSettings.m_uNameCodePage);
offset += 4;
flag = 1;
}
if (bWriteCommentCp)
{
if (!pExtra->m_data.IsAllocated())
{
pExtra->m_data.Allocate(2 + 4);
data = (char*)pExtra->m_data;
}
ASSERT(data);
CBytesWriter::WriteBytes(data + offset, (DWORD)m_stringSettings.m_uCommentCodePage);
flag |= 4;
}
data[0] = ZIP_EXTRA_ZARCH_NAME_VER;
data[1] = flag;
}
WORD uFileNameSize = (WORD)m_pszFileNameBuffer.GetSize(), uCommentSize = (WORD)GetCommentSize(),
uExtraFieldSize = (WORD)m_aCentralExtraData.GetTotalSize();
DWORD uSize = FILEHEADERSIZE + uFileNameSize + uCommentSize + uExtraFieldSize;
CZipAutoBuffer buf(uSize);
char* dest = (char*)buf;
memcpy(dest, m_gszSignature, 4);
CBytesWriter::WriteBytes(dest + 4, m_uVersionMadeBy);
CBytesWriter::WriteBytes(dest + 6, m_uVersionNeeded);
CBytesWriter::WriteBytes(dest + 8, m_uFlag);
CBytesWriter::WriteBytes(dest + 10, uMethod);
CBytesWriter::WriteBytes(dest + 12, m_uModTime);
CBytesWriter::WriteBytes(dest + 14, m_uModDate);
WriteCrc32(dest + 16);
CBytesWriter::WriteBytes(dest + 20, CBytesWriter::WriteSafeU32(m_uComprSize));
CBytesWriter::WriteBytes(dest + 24, CBytesWriter::WriteSafeU32(m_uUncomprSize));
CBytesWriter::WriteBytes(dest + 28, uFileNameSize);
CBytesWriter::WriteBytes(dest + 30, uExtraFieldSize);
CBytesWriter::WriteBytes(dest + 32, uCommentSize);
CBytesWriter::WriteBytes(dest + 34, CBytesWriter::WriteSafeU16(m_uVolumeStart));
CBytesWriter::WriteBytes(dest + 36, m_uInternalAttr);
CBytesWriter::WriteBytes(dest + 38, m_uExternalAttr);
CBytesWriter::WriteBytes(dest + 42, CBytesWriter::WriteSafeU32(m_uOffset));
memcpy(dest + 46, m_pszFileNameBuffer, uFileNameSize);
if (uExtraFieldSize)
m_aCentralExtraData.Write(dest + 46 + uFileNameSize);
if (uCommentSize)
memcpy(dest + 46 + uFileNameSize + uExtraFieldSize, m_pszComment, uCommentSize);
pStorage->Write(dest, uSize, true);
// remove to avoid miscalculations in GetSize()
m_aCentralExtraData.RemoveInternalHeaders();
ClearFileName();
return uSize;
}
bool CZipFileHeader::ReadLocal(CZipCentralDir& centralDir)
{
char buf[LOCALFILEHEADERSIZE];
CZipStorage* pStorage = centralDir.m_pStorage;
pStorage->Read(buf, LOCALFILEHEADERSIZE, true);
if (memcmp(buf, m_gszLocalSignature, 4) != 0)
return false;
bool bIsDataDescr = (((WORD)*(buf + 6)) & 8) != 0;
WORD uTemp;
CBytesWriter::ReadBytes(uTemp, buf + 6);
// do not compare the whole flag - the bits reserved by PKWARE may differ
// in local and central headers
if (centralDir.IsConsistencyCheckOn( CZipArchive::checkLocalFlag)
&& (uTemp & 0xf) != (m_uFlag & 0xf))
return false;
// method
WORD uMethod;
CBytesWriter::ReadBytes(uMethod, buf + 8);
// this may be different in the local header (it may contain disk name for example)
CBytesWriter::ReadBytes(m_uLocalFileNameSize, buf + 26);
WORD uExtraFieldSize;
CBytesWriter::ReadBytes(uExtraFieldSize, buf + 28);
ZIP_VOLUME_TYPE uCurDsk = pStorage->GetCurrentVolume();
// skip reading the local file name
pStorage->m_pFile->Seek(m_uLocalFileNameSize, CZipAbstractFile::current);
if (!m_aLocalExtraData.Read(pStorage, uExtraFieldSize))
return false;
CBytesWriter::ReadBytes(m_uLocalComprSize, buf + 18, 4);
CBytesWriter::ReadBytes(m_uLocalUncomprSize, buf + 22, 4);
if (uMethod == CZipCompressor::methodWinZipAes && IsEncrypted())
CZipException::Throw(CZipException::noAES);
if (centralDir.IsConsistencyCheckOn( CZipArchive::checkLocalMethod)
&& uMethod != m_uMethod )
return false;
if (!bIsDataDescr && centralDir.IsConsistencyCheckOn( CZipArchive::checkLocalCRC | CZipArchive::checkLocalSizes))
{
// read all at once - probably overally faster than checking and reading separately
DWORD uCrc32;
CBytesWriter::ReadBytes(uCrc32, buf + 14);
if (centralDir.IsConsistencyCheckOn( CZipArchive::checkLocalCRC)
&& uCrc32 != m_uCrc32)
return false;
if (centralDir.IsConsistencyCheckOn( CZipArchive::checkLocalSizes)
// do not check, if local compressed size is 0 - this usually means, that some archiver
// could not update the compressed size after compression
&& ( m_uLocalComprSize != 0 && m_uLocalComprSize != m_uComprSize || m_uLocalUncomprSize != m_uUncomprSize))
return false;
}
return pStorage->GetCurrentVolume() == uCurDsk; // check that the whole header is in one volume
}
void CZipFileHeader::SetTime(const time_t & ttime)
{
#if _MSC_VER >= 1400
tm gts;
tm* gt = &gts;
localtime_s(gt, &ttime);
#else
tm* gt = localtime(&ttime);
#endif
WORD year, month, day, hour, min, sec;
if (gt == NULL)
{
year = 0;
month = day = 1;
hour = min = sec = 0;
}
else
{
year = (WORD)(gt->tm_year + 1900);
if (year <= 1980)
year = 0;
else
year -= 1980;
month = (WORD)gt->tm_mon + 1;
day = (WORD)gt->tm_mday;
hour = (WORD)gt->tm_hour;
min = (WORD)gt->tm_min;
sec = (WORD)gt->tm_sec;
}
m_uModDate = (WORD) (day + ( month << 5) + (year << 9));
m_uModTime = (WORD) ((sec >> 1) + (min << 5) + (hour << 11));
}
void CZipFileHeader::ConvertFileName(CZipAutoBuffer& buffer) const
{
if (m_pszFileName == NULL)
return;
CZipString temp = *m_pszFileName;
ZipCompatibility::SlashBackslashChg(temp, false);
if (m_stringSettings.m_bStoreNameInExtraData)
ZipCompatibility::ConvertStringToBuffer(temp, buffer, m_stringSettings.GetDefaultNameCodePage(GetSystemCompatibility()));
else
ZipCompatibility::ConvertStringToBuffer(temp, buffer, m_stringSettings.m_uNameCodePage);
}
void CZipFileHeader::ConvertFileName(CZipString& szFileName) const
{
if (!m_pszFileNameBuffer.IsAllocated() || m_pszFileNameBuffer.GetSize() == 0)
return;
ZipCompatibility::ConvertBufferToString(szFileName, m_pszFileNameBuffer, m_stringSettings.m_uNameCodePage);
int sc = ZipPlatform::GetSystemID();
if (sc == ZipCompatibility::zcDosFat || sc == ZipCompatibility::zcNtfs)
ZipCompatibility::SlashBackslashChg(szFileName, true);
else // some archives may have an invalid path separator stored
ZipCompatibility::SlashBackslashChg(szFileName, false);
}
// write the local header
void CZipFileHeader::WriteLocal(CZipStorage *pStorage)
{
if (IsDataDescriptor())
{
m_uLocalComprSize = 0;
// write, if we know it - WinZip 9.0 in segmented mode with AES encryption will
// complain otherwise (this seems like a bug, because the data descriptor is present and
// local descriptor should be discarded)
if (!IsWinZipAesEncryption())
m_uLocalUncomprSize = 0;
}
else
{
m_uLocalComprSize = GetDataSize(true, false);
}
WORD uMethod = m_uMethod;
PrepareFileName();
m_uLocalFileNameSize = (WORD)m_pszFileNameBuffer.GetSize();
DWORD uExtraFieldSize = m_aLocalExtraData.GetTotalSize();
DWORD iLocalSize = LOCALFILEHEADERSIZE + uExtraFieldSize + m_uLocalFileNameSize;
CZipAutoBuffer buf(iLocalSize);
char* dest = (char*) buf;
memcpy(dest, m_gszLocalSignature, 4);
CBytesWriter::WriteBytes(dest + 4, m_uVersionNeeded);
CBytesWriter::WriteBytes(dest + 6, m_uFlag);
CBytesWriter::WriteBytes(dest + 8, uMethod);
CBytesWriter::WriteBytes(dest + 10, m_uModTime);
CBytesWriter::WriteBytes(dest + 12, m_uModDate);
WriteSmallDataDescriptor(dest + 14);
CBytesWriter::WriteBytes(dest + 26, m_uLocalFileNameSize);
CBytesWriter::WriteBytes(dest + 28, (WORD)uExtraFieldSize);
memcpy(dest + 30, m_pszFileNameBuffer, m_uLocalFileNameSize);
if (uExtraFieldSize)
m_aLocalExtraData.Write(dest + 30 + m_uLocalFileNameSize);
// possible volume change before writing to the file in the segmented archive
// so write the local header first
pStorage->Write(dest, iLocalSize, true);
m_uVolumeStart = pStorage->GetCurrentVolume();
m_uOffset = pStorage->GetPosition() - iLocalSize;
ClearFileName();
}
WORD CZipFileHeader::GetDataDescriptorSize(bool bConsiderSignature) const
{
if (IsDataDescriptor())
{
WORD size = 12;
return (WORD)(bConsiderSignature ? size + 4 : size);
}
else
return 0;
}
bool CZipFileHeader::NeedsDataDescriptor() const
{
return m_uEncryptionMethod == CZipCryptograph::encStandard;
}
void CZipFileHeader::PrepareData(int iLevel, bool bSegm)
{
// could be == 1, but the way below it works for PredictMaximumFileSizeInArchive when used on an existing segmented archive - for whatever reason
m_uInternalAttr = 0;
// version made by
SetVersion((WORD)(0x14));
m_uCrc32 = 0;
m_uComprSize = 0;
m_uUncomprSize = 0;
ASSERT(CZipCompressor::IsCompressionSupported(m_uMethod) && ((iLevel == 0) == (m_uMethod == CZipCompressor::methodStore)));
m_uFlag = 0;
if (m_uMethod == CZipCompressor::methodDeflate)
switch (iLevel)
{
case 1:
m_uFlag |= 6;
break;
case 2:
m_uFlag |= 4;
break;
case 8:
case 9:
m_uFlag |= 2;
break;
}
UpdateFlag(bSegm);
m_uVersionNeeded = 0;
if (m_uVersionNeeded == 0)
m_uVersionNeeded = IsDirectory() ? 0xa : 0x14; // 1.0 or 2.0
}
void CZipFileHeader::GetCrcAndSizes(char * pBuffer)const
{
WriteCrc32(pBuffer);
CBytesWriter::WriteBytes(pBuffer + 4, m_uComprSize, 4);
CBytesWriter::WriteBytes(pBuffer + 8, m_uUncomprSize, 4);
}
bool CZipFileHeader::CheckDataDescriptor(CZipStorage* pStorage) const
{
if (!IsDataDescriptor())
return true;
const int sizeOfSize = 4;
const int size = 4 + 2 * sizeOfSize; // crc and two sizes
CZipAutoBuffer buf(size + 4);
pStorage->Read(buf, size, false);
char* pBuf;
// when an archive is segmented, files that are divided between volume have bit 3 of flag set
// which tell about the presence of the data descriptor after the compressed data
// This signature may be in a segmented archive that is one volume only
// (it is detected as a not segmented archive)
if (memcmp(buf, CZipStorage::m_gszExtHeaderSignat, 4) == 0) // there is a signature
{
pStorage->Read((char*)buf + size, 4, false);
pBuf = (char*)buf + 4;
}
else
pBuf = buf;
DWORD uCrc32 = 0;
ZIP_SIZE_TYPE uCompressed = 0, uUncompressed = 0;
CBytesWriter::ReadBytes(uCrc32, pBuf);
CBytesWriter::ReadBytes(uCompressed, pBuf + 4, sizeOfSize);
CBytesWriter::ReadBytes(uUncompressed, pBuf + 4 + sizeOfSize, sizeOfSize);
return uCrc32 == m_uCrc32 && uCompressed == m_uComprSize && uUncompressed == m_uUncomprSize;
}
DWORD CZipFileHeader::GetSize()const
{
DWORD uSize = FILEHEADERSIZE + PredictFileNameSize() + GetCommentSize();
uSize += m_aCentralExtraData.GetTotalSize();
if (m_stringSettings.m_bStoreNameInExtraData)
{
CZipString temp;
if (m_pszFileName != NULL)
temp = *m_pszFileName;
else
ConvertFileName(temp);
if (temp.GetLength() > 0)
{
uSize += 4 + 2 + 4; // headerID, size + version, flag + filename code page
CZipAutoBuffer buffer;
ZipCompatibility::ConvertStringToBuffer(temp, buffer, m_stringSettings.m_uNameCodePage);
uSize += buffer.GetSize();
if (!m_stringSettings.IsStandardCommentCodePage())
uSize += 4;
}
}
return uSize;
}
DWORD CZipFileHeader::GetLocalSize(bool bReal)const
{
DWORD uSize = LOCALFILEHEADERSIZE + m_aLocalExtraData.GetTotalSize();
if (bReal)
uSize += m_uLocalFileNameSize;
else
uSize += PredictFileNameSize();
return uSize;
}
void CZipFileHeader::SetComment(LPCTSTR lpszComment)
{
ZipCompatibility::ConvertStringToBuffer(lpszComment, m_pszComment, m_stringSettings.m_uCommentCodePage);
}
CZipString CZipFileHeader::GetComment() const
{
CZipString temp;
ZipCompatibility::ConvertBufferToString(temp, m_pszComment, m_stringSettings.m_uCommentCodePage);
return temp;
}
int CZipFileHeader::GetCompressionLevel() const
{
if (m_uMethod == CZipCompressor::methodStore)
return CZipCompressor::levelStore;
else if ((m_uFlag & (WORD) 6) != 0)
return 1;
else if ((m_uFlag & (WORD) 4) != 0)
return 2;
else if ((m_uFlag & (WORD) 2) != 0)
return CZipCompressor::levelBest;
else
return CZipCompressor::levelDefault;
}
void CZipFileHeader::SetFileName(LPCTSTR lpszFileName)
{
if (m_pszFileName == NULL)
m_pszFileName = new CZipString(lpszFileName);
else
*m_pszFileName = lpszFileName;
m_pszFileNameBuffer.Release();
}
CZipString& CZipFileHeader::GetFileName(bool bClearBuffer)
{
if (m_pszFileName != NULL)
return *m_pszFileName;
m_pszFileName = new CZipString(_T(""));
ConvertFileName(*m_pszFileName);
// don't keep it in memory
if (bClearBuffer)
m_pszFileNameBuffer.Release();
return *m_pszFileName;
}
bool CZipFileHeader::IsDirectory()
{
return ZipPlatform::IsDirectory(GetSystemAttr());
}
DWORD CZipFileHeader::GetSystemAttr()
{
int iSystemComp = GetSystemCompatibility();
if (ZipCompatibility::IsPlatformSupported(iSystemComp))
{
DWORD uAttr = iSystemComp == ZipCompatibility::zcUnix ? (m_uExternalAttr >> 16) : (m_uExternalAttr & 0xFFFF);
if (!uAttr && CZipPathComponent::HasEndingSeparator(GetFileName()))
return ZipPlatform::GetDefaultDirAttributes(); // can happen
else
{
uAttr = ZipCompatibility::ConvertToSystem(uAttr, iSystemComp, ZipPlatform::GetSystemID());
#ifdef ZIP_ARCHIVE_LNX
// converting from Windows attributes may create a not readable linux directory
if (iSystemComp != ZipCompatibility::zcUnix && ZipPlatform::IsDirectory(uAttr))
return ZipPlatform::GetDefaultDirAttributes();
#endif
return uAttr;
}
}
else
return CZipPathComponent::HasEndingSeparator(GetFileName()) ? ZipPlatform::GetDefaultDirAttributes() : ZipPlatform::GetDefaultAttributes();
}
void CZipFileHeader::SetSystemAttr(DWORD uAttr)
{
// make it readable under Unix as well, since it stores its attributes in HIWORD(uAttr)
int iSystemComp = GetSystemCompatibility();
m_uExternalAttr = ZipCompatibility::ConvertToSystem(uAttr, ZipPlatform::GetSystemID(), iSystemComp);
if (iSystemComp == ZipCompatibility::zcUnix)
{
m_uExternalAttr <<= 16;
if (ZipPlatform::IsDirectory(uAttr))
m_uExternalAttr |= 0x10; // make it recognizable under other systems (all use 0x10 for directory)
}
else
// make it readable under linux
m_uExternalAttr |= (ZipCompatibility::ConvertToSystem(uAttr, ZipPlatform::GetSystemID(), ZipCompatibility::zcUnix) << 16);
}
CZipFileHeader& CZipFileHeader::operator=(const CZipFileHeader& header)
{
m_uVersionMadeBy = header.m_uVersionMadeBy;
m_uVersionNeeded = header.m_uVersionNeeded;
m_uFlag = header.m_uFlag;
m_uMethod = header.m_uMethod;
m_uModTime = header.m_uModTime;
m_uModDate = header.m_uModDate;
m_uCrc32 = header.m_uCrc32;
m_uComprSize = header.m_uComprSize;
m_uUncomprSize = header.m_uUncomprSize;
m_uVolumeStart = header.m_uVolumeStart;
m_uInternalAttr = header.m_uInternalAttr;
m_uLocalComprSize = header.m_uLocalComprSize;
m_uLocalUncomprSize = header.m_uUncomprSize;
m_uExternalAttr = header.m_uExternalAttr;
m_uLocalFileNameSize = header.m_uLocalFileNameSize;;
m_uOffset = header.m_uOffset;
m_aLocalExtraData = header.m_aLocalExtraData;
m_aCentralExtraData = header.m_aCentralExtraData;
m_uEncryptionMethod = header.m_uEncryptionMethod;
if (m_pszFileName)
delete m_pszFileName;
if (header.m_pszFileName)
m_pszFileName = new CZipString(*header.m_pszFileName);
else
m_pszFileName = NULL;
m_pszFileNameBuffer = header.m_pszFileNameBuffer;
m_pszComment = header.m_pszComment;
m_stringSettings = header.m_stringSettings;
return *this;
}
void CZipFileHeader::WriteSmallDataDescriptor(char* pDest, bool bLocal)
{
WriteCrc32(pDest);
if (bLocal)
{
CBytesWriter::WriteBytes(pDest + 4, m_uLocalComprSize, 4);
CBytesWriter::WriteBytes(pDest + 8, m_uLocalUncomprSize, 4);
}
else
{
CBytesWriter::WriteBytes(pDest + 4, m_uComprSize, 4);
CBytesWriter::WriteBytes(pDest + 8, m_uUncomprSize, 4);
}
}
void CZipFileHeader::WriteDataDescriptor(CZipStorage* pStorage)
{
if (!IsDataDescriptor())
return;
bool signature = NeedsSignatureInDataDescriptor(pStorage);
CZipAutoBuffer buf;
buf.Allocate(GetDataDescriptorSize(signature));
char* pBuf;
if (signature)
{
memcpy(buf, CZipStorage::m_gszExtHeaderSignat, 4);
pBuf = (char*)buf + 4;
}
else
pBuf = buf;
WriteCrc32(pBuf);
CBytesWriter::WriteBytes(pBuf + 4, m_uComprSize, 4);
CBytesWriter::WriteBytes(pBuf + 8, m_uUncomprSize, 4);
pStorage->Write(buf, buf.GetSize(), true);
}
void CZipFileHeader::UpdateLocalHeader(CZipStorage* pStorage)
{
if (pStorage->IsSegmented() != 0 || IsDataDescriptor())
// there is nothing to fix
return;
pStorage->Flush();
ZIP_FILE_USIZE uPos = pStorage->m_pFile->GetPosition();
// update crc and sizes, the sizes may already be all right,
// but 8 more bytes won't make a difference, we need to update crc32 anyway
CZipAutoBuffer buf(12);
m_uLocalComprSize = CBytesWriter::WriteSafeU32(m_uComprSize);
m_uLocalUncomprSize = CBytesWriter::WriteSafeU32(m_uUncomprSize);
WriteSmallDataDescriptor(buf);
pStorage->Seek(m_uOffset + 14);
pStorage->m_pFile->Write(buf, 12);
pStorage->m_pFile->Seek(uPos);
}
void CZipFileHeader::WriteCrc32(char* pBuf) const
{
DWORD uCrc = m_bIgnoreCrc32 ? 0 : m_uCrc32;
CBytesWriter::WriteBytes(pBuf, uCrc);
}

View File

@@ -0,0 +1,709 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipFileHeader.h
* Includes the CZipFileHeader class.
*
*/
#if !defined(ZIPARCHIVE_ZIPFILEHEADER_DOT_H)
#define ZIPARCHIVE_ZIPFILEHEADER_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "ZipExport.h"
#include "ZipStorage.h"
#include "ZipAutoBuffer.h"
#include "sys/types.h"
#include "ZipCompatibility.h"
#include "ZipCollections.h"
#include "ZipExtraField.h"
#include "ZipStringStoreSettings.h"
#include "ZipCryptograph.h"
class CZipCentralDir;
/**
Represents a single file stored in a zip archive.
*/
class ZIP_API CZipFileHeader
{
friend class CZipCentralDir;
friend class CZipArchive;
public:
CZipFileHeader();
CZipFileHeader(const CZipFileHeader& header)
{
*this = header;
}
CZipFileHeader& operator=(const CZipFileHeader& header);
virtual ~CZipFileHeader();
/**
Predicts the filename size after conversion using the current filename code page.
\return
The number of characters not including a terminating \c NULL character.
*/
int PredictFileNameSize() const
{
if (m_pszFileNameBuffer.IsAllocated())
return m_pszFileNameBuffer.GetSize();
CZipAutoBuffer buffer;
ConvertFileName(buffer);
return buffer.GetSize();
}
/**
Gets the comment size.
\return
The number of characters in the comment not including a terminating \c NULL character.
*/
WORD GetCommentSize() const {return (WORD)m_pszComment.GetSize();}
/**
Gets the filename. If necessary, performs the conversion using the current filename code page.
Caches the result of conversion for faster access the next time.
\param bClearBuffer
If \c true, releases the internal buffer after performing the filename conversion.
If \c false, the internal buffer is not released and both representations of the
filename are kept in memory (converted and not converted). This takes more memory, but the
conversion does not take place again when the central directory is written back to the archive.
\return
The converted filename.
\see
<a href="kb">0610051525</a>
\see
GetStringStoreSettings
\see
CZipStringStoreSettings::m_uNameCodePage
*/
CZipString& GetFileName(bool bClearBuffer = true);
/**
Sets the filename.
\param lpszFileName
The filename to set.
*/
void SetFileName(LPCTSTR lpszFileName);
/**
Gets the file comment.
\return
The file comment.
*/
CZipString GetComment() const;
/**
Sets the file comment.
\param lpszComment
The file comment.
*/
void SetComment(LPCTSTR lpszComment);
/**
Gets a value indicating whether the data descriptor is present or not.
\return
\c true, if the data descriptor is present; \c false otherwise.
*/
bool IsDataDescriptor()const { return (m_uFlag & (WORD) 8) != 0;}
/**
Gets the data descriptor size as it is required for the current file.
Takes into account various factors, such as the archive segmentation type,
encryption and the need for the Zip64 format.
\param pStorage
The storage to test for segmentation type.
\return
The required data descriptor size in bytes.
*/
WORD GetDataDescriptorSize(const CZipStorage* pStorage) const
{
return GetDataDescriptorSize(NeedsSignatureInDataDescriptor(pStorage));
}
/**
Gets the data descriptor size as it is required for the current file.
Takes into account various factors, such as the need for the data descriptor signature
or for the Zip64 format.
\param bConsiderSignature
\c true, if the data descriptor signature is needed; \c false otherwise.
\return
The required data descriptor size in bytes.
*/
WORD GetDataDescriptorSize(bool bConsiderSignature = false) const;
/**
Gets the size of the compressed data.
\param bUseLocal
If \c true, uses #m_uLocalComprSize; otherwise uses #m_uComprSize;
\param bReal
If \c true, the returned value does not include the encrypted information size, only the data size.
If \c false, the encrypted information size is added (you should not use this value
when the file exists in the archive).
\return
The compressed data size in bytes.
\see
GetEncryptedInfoSize
*/
ZIP_SIZE_TYPE GetDataSize(bool bUseLocal = false, bool bReal = true) const
{
ZIP_SIZE_TYPE uSize = bUseLocal ? m_uLocalComprSize : m_uComprSize;
DWORD uEncrSize = GetEncryptedInfoSize();
return bReal ? (uSize - uEncrSize) : (uSize + uEncrSize);
}
/**
Gets the encrypted information size. The returned value depends on the used encryption method.
\return
The encrypted information size in bytes.
*/
DWORD GetEncryptedInfoSize() const
{
return CZipCryptograph::GetEncryptedInfoSize(m_uEncryptionMethod);
}
/**
Gets the total size of the structure in the central directory.
\return
The total size in bytes.
*/
DWORD GetSize()const;
/**
Gets the local header size. Before calling this method, the local information must be up-to-date
(see <a href="kb">0610242128|local</a> for more information).
\param bReal
If \c true, uses the real local filename size.
If \c false, predicts the filename size.
\return
The local header size in bytes.
*/
DWORD GetLocalSize(bool bReal) const;
/**
Gets a value indicating if the compression is efficient.
\return
\c true if the compression is efficient; \c false if the file should be
stored without the compression instead.
*/
bool CompressionEfficient()
{
ZIP_SIZE_TYPE uBefore = m_uUncomprSize;
// ignore the length of encryption info
ZIP_SIZE_TYPE uAfter = GetDataSize(false, true);
return uAfter <= uBefore;
}
/**
Gets the compression ratio.
\return
The compression ratio of the file.
*/
float GetCompressionRatio()
{
#if _MSC_VER >= 1300 || !defined(_ZIP64)
return m_uUncomprSize ? ((float)m_uComprSize * 100 ) / m_uUncomprSize: 0;
#else
return m_uUncomprSize ? ((float)(__int64)(m_uComprSize) / (float)(__int64)m_uUncomprSize) * 100: 0;
#endif
}
/**
Sets the file modification date.
\param ttime
The date to set. If this value is incorrect, the date defaults to January 1, 1980.
\see
GetTime
*/
void SetTime(const time_t& ttime);
/**
Gets the file modification time.
\return
The modification time.
\see
SetTime
*/
time_t GetTime()const;
/**
Gets the file system compatibility.
External software can use this information e.g. to determine end-of-line
format for text files etc.
The ZipArchive Library uses it to perform a proper file attributes conversion.
\return
The file system compatibility. Can be one of the ZipCompatibility::ZipPlatforms values.
\see
CZipArchive::GetSystemComatibility
\see
ZipPlatform::GetSystemID
*/
int GetSystemCompatibility()const
{
return (m_uVersionMadeBy & 0xFF00) >> 8;
}
/**
Gets the file attributes.
\return
The file attributes, converted if necessary to be compatible with the current system.
\note
Throws an exception, if the archive system or the current system
is not supported by the ZipArchive Library.
\see
GetOriginalAttributes
*/
DWORD GetSystemAttr();
/**
Gets the file attributes exactly as they are stored in the archive.
\return
The file attributes as they are stored in the archive.
No conversion is performed.
\note
The attributes for Linux are stored shifted left by 16 bits in this field.
\see
GetSystemAttr
*/
DWORD GetOriginalAttributes() const {return m_uExternalAttr;}
/**
Gets a value indicating whether the file represents a directory or not.
This method checks the file attributes. If the attributes value is zero,
the method checks for the presence of a path
separator at the end of the filename. If the path separator is present,
the file is assumed to be a directory.
\return
\c true, if the file represents a directory; \c false otherwise.
*/
bool IsDirectory();
/**
Gets the string store settings for the file.
\return
The string store settings.
\see
<a href="kb">0610051525</a>
\see
CZipArchive::GetStringStoreSettings
*/
CZipStringStoreSettings GetStringStoreSettings()
{
return m_stringSettings;
}
/**
Gets a value indicating if the file is encrypted or not.
If the file is encrypted, you need to set the password with the
CZipArchive::SetPassword method before decompressing the file.
\return
\c true if the file is encrypted; \c false otherwise.
\see
CZipArchive::SetPassword
*/
bool IsEncrypted()const { return m_uEncryptionMethod != CZipCryptograph::encNone;}
/**
Gets the encryption method of the file.
\return
The file encryption method. Can be one of the CZipCryptograph::EncryptionMethod values.
*/
int GetEncryptionMethod() const {return m_uEncryptionMethod;}
/**
Gets a value indicating if the file is encrypted using WinZip AES encryption method or not.
\return
\c true, if the file is encrypted using WinZip AES encryption method; \c false otherwise.
*/
bool IsWinZipAesEncryption() const
{
return CZipCryptograph::IsWinZipAesEncryption(m_uEncryptionMethod);
}
/**
Gets an approximate file compression level.
\return
The compression level. May not be the real value used when compressing the file.
*/
int GetCompressionLevel() const;
/**
Returns the value indicating whether the current CZipFileHeader object has the time set or not.
\return
\c true, if the time is set; \c false otherwise.
*/
bool HasTime()
{
return m_uModTime != 0 || m_uModDate != 0;
}
static char m_gszSignature[]; ///< The central file header signature.
static char m_gszLocalSignature[]; ///< The local file header signature.
WORD m_uVersionMadeBy; ///< The "made by" version and the system compatibility.
WORD m_uVersionNeeded; ///< The version needed to extract the file.
WORD m_uFlag; ///< A general purpose bit flag.
WORD m_uMethod; ///< The compression method. Can be one of the CZipCompressor::CompressionMethod values.
WORD m_uModTime; ///< The file last modification time.
WORD m_uModDate; ///< The file last modification date.
DWORD m_uCrc32; ///< The crc-32 value.
ZIP_SIZE_TYPE m_uComprSize; ///< The compressed size.
ZIP_SIZE_TYPE m_uUncomprSize; ///< The uncompressed size.
ZIP_VOLUME_TYPE m_uVolumeStart; ///< The volume number at which the compressed file starts.
WORD m_uInternalAttr; ///< Internal file attributes.
ZIP_SIZE_TYPE m_uLocalComprSize; ///< The compressed size written in the local header.
ZIP_SIZE_TYPE m_uLocalUncomprSize; ///< The uncompressed size written in the local header.
ZIP_SIZE_TYPE m_uOffset; ///< Relative offset of the local header with respect to CZipFileHeader::m_uVolumeStart.
CZipExtraField m_aLocalExtraData; ///< The local extra field. Do not modify after you have started compressing the file.
CZipExtraField m_aCentralExtraData; ///< The central extra field.
protected:
DWORD m_uExternalAttr; ///< External file attributes.
WORD m_uLocalFileNameSize; ///< The local filename length.
BYTE m_uEncryptionMethod; ///< The file encryption method. Can be one of the CZipCryptograph::EncryptionMethod values.
bool m_bIgnoreCrc32; ///< A value indicating whether to ignore Crc32 checking or not.
/**
Sets the file system compatibility.
\param iSystemID
The file system compatibility. Can be one of the ZipCompatibility::ZipPlatforms values.
\see
GetSystemCompatibility
*/
void SetSystemCompatibility(int iSystemID)
{
m_uVersionMadeBy &= 0x00FF;
m_uVersionMadeBy |= (WORD)(iSystemID << 8);
}
/**
Sets the file attributes.
To set the attributes of this structure use the CZipArchive::SetFileHeaderAttr method.
\param uAttr
The attributes to set.
\note
Throws exceptions, if the archive system or the current system
is not supported by the ZipArchive Library.
\see
CZipArchive::SetFileHeaderAttr
\see
GetSystemAttr
*/
void SetSystemAttr(DWORD uAttr);
/**
Prepares the filename for writing to the archive.
*/
void PrepareFileName()
{
if (m_pszFileNameBuffer.IsAllocated() || m_pszFileName == NULL)
return;
ConvertFileName(m_pszFileNameBuffer);
}
/**
Validates an existing data descriptor after file decompression.
\param pStorage
The storage to read the data descriptor from.
\return
\c true, if the data descriptor is valid; \c false otherwise.
*/
bool CheckDataDescriptor(CZipStorage* pStorage) const;
/**
Prepares the data for writing when adding a new file. When Zip64 extensions are required for this file,
this method adds Zip64 extra data to #m_aLocalExtraData.
\param iLevel
The compression level.
\param bSegm
Set to \c true, if the archive is segmented; \c false otherwise.
*/
void PrepareData(int iLevel, bool bSegm);
/**
Writes the local file header to the \a pStorage.
The filename and extra field are the same as those that will be stored in the central directory.
\param pStorage
The storage to write the local file header to.
\note
Throws exceptions.
*/
void WriteLocal(CZipStorage *pStorage);
/**
Reads the local file header from an archive and validates the read data.
\param centralDir
The current central directory.
\return
\c true, if read data is consistent; \c false otherwise.
\note
Throws exceptions.
\see
CZipArchive::SetIgnoredConsistencyChecks
*/
bool ReadLocal(CZipCentralDir& centralDir);
/**
Writes the central file header to \a pStorage.
\param pStorage
The storage to write the central file header to.
\return
The size of the file header.
\note
Throws exceptions.
*/
DWORD Write(CZipStorage *pStorage);
/**
Reads the central file header from \a pStorage and validates the read data.
\param centralDir
The current central directory.
\param bReadSignature
\c true, if the the central header signature should be read; \c false otherwise.
\return
\c true, if the read data is consistent; \c false otherwise.
\note
Throws exceptions.
*/
bool Read(CZipCentralDir& centralDir, bool bReadSignature);
/**
Validates the member fields lengths.
The tested fields are: filename, extra fields and comment.
\return
\c false, if any of the lengths exceeds the allowed value.
*/
bool CheckLengths(bool local) const
{
if (m_pszComment.GetSize() > USHRT_MAX || m_pszFileNameBuffer.GetSize() > USHRT_MAX)
return false;
else if (local)
return m_aLocalExtraData.Validate();
else
return m_aCentralExtraData.Validate();
}
/**
Writes the Crc32 to \a pBuf.
\param pBuf
The buffer to write the Crc32 to. Must have be of at least 4 bytes size.
*/
void WriteCrc32(char* pBuf) const;
/**
Gets a value indicating whether the file needs the data descriptor.
The data descriptor is needed when a file is encrypted or the Zip64 format needs to be used.
\return
\c true, if the data descriptor is needed; \c false otherwise.
*/
bool NeedsDataDescriptor() const;
/**
Writes the data descriptor.
\param pDest
The buffer to receive the data.
\param bLocal
Set to \c true, if the local sizes are used; \c false otherwise.
*/
void WriteSmallDataDescriptor(char* pDest, bool bLocal = true);
/**
Writes the data descriptor taking into account the Zip64 format.
\param pStorage
The storage to write the data descriptor to.
*/
void WriteDataDescriptor(CZipStorage* pStorage);
bool NeedsSignatureInDataDescriptor(const CZipStorage* pStorage) const
{
return pStorage->IsSegmented() != 0 || IsEncrypted();
}
/**
Updates the local header in the archive after is has already been written.
\param pStorage
The storage to update the data descriptor in.
*/
void UpdateLocalHeader(CZipStorage* pStorage);
/**
Verifies the central header signature.
\param buf
The buffer that contains the signature to verify.
\return
\c true, if the signature is valid; \c false otherwise.
*/
static bool VerifySignature(CZipAutoBuffer& buf)
{
return memcmp(buf, m_gszSignature, 4) == 0;
}
/**
Updates the general purpose bit flag.
\param bSegm
\c true, if the current archive is a segmented archive; \c false otherwise.
*/
void UpdateFlag(bool bSegm)
{
if (bSegm || m_uEncryptionMethod == CZipCryptograph::encStandard)
m_uFlag |= 8; // data descriptor present
if (IsEncrypted())
m_uFlag |= 1; // encrypted file
}
private:
/**
Sets the "made by" version.
\param uVersion
The version to set.
*/
void SetVersion(WORD uVersion)
{
if ((m_uVersionMadeBy & 0x00FF) != (uVersion & 0x00FF))
{
m_uVersionMadeBy &= 0xFF00;
m_uVersionMadeBy |= (WORD)(uVersion & 0x00FF);
}
}
void ConvertFileName(CZipAutoBuffer& buffer) const;
void ConvertFileName(CZipString& szFileName) const;
void ClearFileName()
{
if (m_stringSettings.m_bStoreNameInExtraData)
// we are keeping m_pszFileName, clear the buffer, we need the original, when writing extra header and when accessing the filename
m_pszFileNameBuffer.Release();
else if (m_pszFileName != NULL)
{
delete m_pszFileName;
m_pszFileName = NULL;
}
}
void GetCrcAndSizes(char* pBuffer)const;
bool NeedsZip64() const
{
return m_uComprSize >= UINT_MAX || m_uUncomprSize >= UINT_MAX || m_uVolumeStart >= USHRT_MAX || m_uOffset >= UINT_MAX;
}
void OnNewFileClose(CZipStorage* pStorage)
{
UpdateLocalHeader(pStorage);
WriteDataDescriptor(pStorage);
pStorage->Flush();
}
CZipAutoBuffer m_pszFileNameBuffer;
CZipString* m_pszFileName;
CZipStringStoreSettings m_stringSettings;
CZipAutoBuffer m_pszComment;
};
#endif // !defined(ZIPARCHIVE_ZIPFILEHEADER_DOT_H)

View File

@@ -0,0 +1,37 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipFileMapping.h
* Includes the ZipArchiveLib::CZipFileMapping class.
*
*/
#if !defined(ZIPARCHIVE_ZIPFILEMAPPING_DOT_H)
#define ZIPARCHIVE_ZIPFILEMAPPING_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "_platform.h"
#ifdef ZIP_ARCHIVE_WIN
#include "ZipFileMapping_win.h"
#else
#include "ZipFileMapping_lnx.h"
#endif
#endif // !defined(ZIPARCHIVE_ZIPFILEMAPPING_DOT_H)

View File

@@ -0,0 +1,62 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_ZIPFILEMAPPING_DOT_H
#error Do not include this file directly. Include ZipFileMapping.h instead
#endif
#include <sys/mman.h>
namespace ZipArchiveLib
{
struct CZipFileMapping
{
CZipFileMapping()
{
m_iSize = 0;
m_pFileMap = NULL;
}
bool CreateMapping(CZipFile* pFile)
{
if (!pFile)
return false;
m_iSize = pFile->GetLength();
m_pFileMap = mmap(0, m_iSize, PROT_READ|PROT_WRITE, MAP_SHARED, pFile->m_hFile, 0);
return (m_pFileMap != NULL);
}
void RemoveMapping()
{
if (m_pFileMap)
{
munmap(m_pFileMap, m_iSize);
m_pFileMap = NULL;
}
}
~CZipFileMapping()
{
RemoveMapping();
}
char* GetMappedMemory()
{
return reinterpret_cast<char*> (m_pFileMap);
}
protected:
void* m_pFileMap;
size_t m_iSize;
};
}

View File

@@ -0,0 +1,68 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_ZIPFILEMAPPING_DOT_H
#error Do not include this file directly. Include ZipFileMapping.h instead
#endif
#include "ZipFile.h"
namespace ZipArchiveLib
{
struct CZipFileMapping
{
CZipFileMapping()
{
m_hFileMap = NULL;
m_pFileMap = NULL;
}
bool CreateMapping(CZipFile* pFile)
{
if (!pFile)
return false;
m_hFileMap = CreateFileMapping((*pFile), NULL, PAGE_READWRITE,
0, 0, _T("ZipArchive Mapping File"));
if (!m_hFileMap)
return false;
// Get pointer to memory representing file
m_pFileMap = MapViewOfFile(m_hFileMap, FILE_MAP_WRITE, 0, 0, 0);
return (m_pFileMap != NULL);
}
void RemoveMapping()
{
if (m_pFileMap)
{
UnmapViewOfFile(m_pFileMap);
m_pFileMap = NULL;
}
if (m_hFileMap)
{
CloseHandle(m_hFileMap);
m_hFileMap = NULL;
}
}
~CZipFileMapping()
{
RemoveMapping();
}
char* GetMappedMemory()
{
return reinterpret_cast<char*> (m_pFileMap);
}
protected:
HANDLE m_hFileMap;
LPVOID m_pFileMap;
};
}

View File

@@ -0,0 +1,39 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "_features.h"
#if defined ZIP_ARCHIVE_MFC && !defined ZIP_FILE_USES_STL
#include "stdafx.h"
#include "ZipFile.h"
// IMPLEMENT_DYNAMIC(CZipAbstractFile, CFile)
IMPLEMENT_DYNAMIC(CZipFile, CFile)
CZipFile::CZipFile()
{
}
CZipFile::~CZipFile()
{
Close();
}
CZipFile::operator HANDLE()
{
return (HANDLE)m_hFile;
}
#endif

View File

@@ -0,0 +1,87 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_ZIPFILE_DOT_H
#error Do not include this file directly. Include ZipFile.h instead
#endif
#if _MSC_VER > 1000 && defined ZIP_HAS_DLL
#pragma warning (push)
#pragma warning( disable : 4275 ) // non dll-interface used as base for dll-interface class
#endif
#include "ZipAbstractFile.h"
#include "ZipExport.h"
class ZIP_API CZipFile : public CZipAbstractFile, public CFile
{
public:
DECLARE_DYNAMIC(CZipFile)
void Flush(){CFile::Flush();}
CZipString GetFilePath() const
{
try
{
// it throws an exception when working on an offline file
return CFile::GetFilePath();
}
catch (CException* e)
{
e->Delete();
return this->m_strFileName;
}
}
ZIP_FILE_USIZE GetPosition() const {return CFile::GetPosition() ;}
void SetLength(ZIP_FILE_USIZE nNewLen) {CFile::SetLength(nNewLen);}
ZIP_FILE_USIZE Seek(ZIP_FILE_SIZE lOff , int nFrom){return CFile::Seek(lOff, nFrom);}
ZIP_FILE_USIZE GetLength() const {return CFile::GetLength();}
UINT Read(void *lpBuf, UINT nCount){return CFile::Read(lpBuf, nCount);}
void Write(const void* lpBuf, UINT nCount){CFile::Write(lpBuf, nCount);}
bool Open( LPCTSTR lpszFileName, UINT nOpenFlags, bool bThrowExc)
{
CFileException* e = new CFileException;
bool bRet = CFile::Open(lpszFileName, nOpenFlags, e) != 0;
if (!bRet && bThrowExc)
throw e;
e->Delete();
return bRet;
}
CZipFile();
bool IsClosed() const
{
return m_hFile == CFile::hFileNull;
}
CZipFile( LPCTSTR lpszFileName, UINT nOpenFlags ):CFile(lpszFileName, nOpenFlags)
{
}
void Close( )
{
if (!IsClosed())
CFile::Close();
}
operator HANDLE();
virtual ~CZipFile();
};
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning (pop)
#endif

View File

@@ -0,0 +1,144 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "_features.h"
#if defined ZIP_ARCHIVE_STL || defined ZIP_FILE_USES_STL
#if defined __APPLE__ || defined __CYGWIN__
#define FILE_FUNCTIONS_64B_BY_DEFAULT
#else
#undef FILE_FUNCTIONS_64B_BY_DEFAULT
#endif
#include "stdafx.h"
#include "ZipFile.h"
#include "ZipException.h"
#include "ZipPlatform.h"
#include <fcntl.h>
CZipFile::CZipFile()
{
m_hFile = -1;
}
void CZipFile::ThrowError() const
{
CZipException::Throw(errno, m_szFileName);
}
ZIP_FILE_USIZE CZipFile::GetLength() const
{
// cannot use Seek here, Seek is not const
ZIP_SIZE_TYPE lLen, lCur;
lCur = _lseek(m_hFile, 0, current);
if (lCur == (ZIP_SIZE_TYPE)-1)
ThrowError();
lLen = _lseek(m_hFile, 0, end);
// first go back
bool err = _lseek(m_hFile, lCur, begin) == -1;
if (err || lLen == (ZIP_SIZE_TYPE)-1)
ThrowError();
return lLen;
}
bool CZipFile::Open(LPCTSTR lpszFileName, UINT openFlags, bool bThrow)
{
if (!IsClosed())
Close();
#ifdef O_BINARY
UINT iNewFlags = O_BINARY;
#else
UINT iNewFlags = 0;
#endif
bool bReadOnly = false;
if (openFlags & CZipFile::modeCreate)
iNewFlags |= O_CREAT;
if ((openFlags & CZipFile::modeReadWrite) == CZipFile::modeReadWrite)
iNewFlags |= O_RDWR;
else if (openFlags & CZipFile::modeRead)
{
// O_RDONLY is defined as 0
bReadOnly = true;
iNewFlags |= O_RDONLY;
}
else if (openFlags & CZipFile::modeWrite)
iNewFlags |= O_WRONLY;
if (!(openFlags & CZipFile::modeNoTruncate) && !bReadOnly)
iNewFlags |= O_TRUNC;
m_hFile = ZipPlatform::OpenFile(lpszFileName, iNewFlags, openFlags & 0x1C);
if (m_hFile == -1)
if (bThrow)
CZipException::Throw(errno, lpszFileName);
else
return false;
m_szFileName = lpszFileName;
return true;
}
void CZipFile::SetLength(ULONGLONG uNewLen)
{
ZipPlatform::TruncateFile(m_hFile, uNewLen);
}
ZIP_FILE_USIZE CZipFile::GetPosition() const
{
#ifndef __GNUC__
ZIP_FILE_USIZE ret = _tell(m_hFile);
#else
ZIP_FILE_USIZE ret = lseek(m_hFile, 0, SEEK_CUR);
#endif
if (ret == (ZIP_FILE_USIZE)-1)
ThrowError();
return ret;
}
ZIP_FILE_USIZE CZipFile::Seek(ZIP_FILE_SIZE dOff, int nFrom)
{
// restricted to signed
ZIP_FILE_SIZE ret = (ZIP_FILE_SIZE)_lseek(m_hFile, (long)dOff, nFrom);
if (ret == -1)
ThrowError();
return (ZIP_FILE_USIZE)ret;
}
void CZipFile::Flush()
{
if (!ZipPlatform::FlushFile(m_hFile))
ThrowError();
}
CZipFile::operator HANDLE()
{
intptr_t fh = ZipPlatform::GetFileSystemHandle(m_hFile);
if (fh == -1)
ThrowError();
#if _MSC_VER >= 1300
return (HANDLE)fh;
#else
return (HANDLE)fh;
#endif
}
#endif

View File

@@ -0,0 +1,119 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_ZIPFILE_DOT_H
#error Do not include this file directly. Include ZipFile.h instead
#endif
#include "ZipAbstractFile.h"
#include "ZipString.h"
#include "ZipExport.h"
#ifndef __GNUC__
#include <io.h>
#else
#include <unistd.h>
#include <errno.h>
#endif
#if !defined (_MSC_VER) || _MSC_VER < 1400
// there seems to be a problem under Windows sometimes when using one of the functions below
// without the underscore at the beginning
#ifndef _lseek
#define _lseek lseek
#endif
#ifndef _read
#define _read read
#endif
#ifndef _close
#define _close close
#endif
#ifndef _tell
#define _tell tell
#endif
#ifndef _write
#define _write write
#endif
#endif
class ZIP_API CZipFile : public CZipAbstractFile
{
void ThrowError() const;
public:
int m_hFile;
operator HANDLE();
enum OpenModes
{
modeRead = 0x0001,
modeWrite = 0x0002,
modeReadWrite = modeRead | modeWrite,
shareDenyWrite = 0x0004,
shareDenyRead = 0x0008,
shareDenyNone = 0x0010,
modeCreate = 0x0020,
modeNoTruncate = 0x0040,
};
CZipFile(LPCTSTR lpszFileName, UINT openFlags)
{
m_hFile = -1;
Open(lpszFileName, openFlags, true);
}
void Flush();
ZIP_FILE_USIZE GetLength() const;
CZipString GetFilePath() const {return m_szFileName;}
bool IsClosed()const { return m_hFile == -1;}
bool Open(LPCTSTR lpszFileName, UINT openFlags, bool bThrow);
void Close()
{
if (IsClosed())
return;
if (_close(m_hFile) != 0)
ThrowError();
else
{
m_szFileName.Empty();
m_hFile = -1;
}
}
void Write(const void* lpBuf, UINT nCount)
{
if (_write(m_hFile, lpBuf, nCount) != (int) nCount)
ThrowError();
}
ZIP_FILE_USIZE GetPosition() const;
void SetLength(ZIP_FILE_USIZE uNewLen);
UINT Read(void *lpBuf, UINT nCount)
{
errno = 0;
int ret = _read(m_hFile, lpBuf, nCount);
if (ret < (int) nCount && errno != 0)
ThrowError();
return ret;
}
ZIP_FILE_USIZE Seek(ZIP_FILE_SIZE dOff, int nFrom);
CZipFile ();
virtual ~CZipFile (){Close();};
protected:
CZipString m_szFileName;
};

View File

@@ -0,0 +1,110 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipMemFile.h"
#include "ZipException.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
void CZipMemFile::Grow(size_t nGrowTo)
{
if (m_nBufSize < (UINT)nGrowTo)
{
if (m_nGrowBy == 0)
CZipException::Throw(CZipException::memError);
size_t nNewSize = m_nBufSize;
while (nNewSize < nGrowTo)
nNewSize += m_nGrowBy;
BYTE* lpNew;
if (m_lpBuf)
lpNew = (BYTE*)realloc((void*) m_lpBuf, nNewSize);
else
lpNew = (BYTE*)malloc(nNewSize);
if (!lpNew)
CZipException::Throw(CZipException::memError);
m_nBufSize = nNewSize;
m_lpBuf = lpNew;
}
}
void CZipMemFile::SetLength(ZIP_FILE_USIZE nNewLen)
{
if (m_nBufSize < (size_t)nNewLen)
Grow((size_t)nNewLen);
else
m_nPos = (size_t)nNewLen;
m_nDataSize = (size_t)nNewLen;
}
UINT CZipMemFile::Read(void *lpBuf, UINT nCount)
{
if (m_nPos >= m_nDataSize)
return 0;
UINT nToRead = (m_nPos + nCount > m_nDataSize) ? (UINT)(m_nDataSize - m_nPos) : nCount;
memcpy(lpBuf, m_lpBuf + m_nPos, nToRead);
m_nPos += nToRead;
return nToRead;
}
void CZipMemFile::Write(const void *lpBuf, UINT nCount)
{
if (!nCount)
return;
if (m_nPos + nCount > m_nBufSize)
Grow(m_nPos + nCount);
memcpy(m_lpBuf + m_nPos, lpBuf, nCount);
m_nPos += nCount;
if (m_nPos > m_nDataSize)
m_nDataSize = m_nPos;
}
ZIP_FILE_USIZE CZipMemFile::Seek(ZIP_FILE_SIZE lOff, int nFrom)
{
ZIP_FILE_USIZE lNew = m_nPos;
if (nFrom == CZipAbstractFile::begin)
{
if (lOff < 0)
CZipException::Throw(CZipException::memError);
lNew = lOff;
}
else if (nFrom == CZipAbstractFile::current)
{
if (lOff < 0 && (ZIP_FILE_USIZE)(-lOff) > lNew)
CZipException::Throw(CZipException::memError);
lNew += lOff;
}
else if (nFrom == CZipAbstractFile::end)
{
if (lOff < 0 && ZIP_FILE_USIZE(-lOff) > m_nDataSize)
CZipException::Throw(CZipException::memError);
lNew = m_nDataSize + lOff;
}
else
return lNew;
// assumption that size_t is always signed
if (lNew > (size_t)(-1)) // max of size_t
CZipException::Throw(CZipException::memError);
if (lNew > m_nDataSize)
Grow((size_t)lNew);
m_nPos = (size_t)lNew;
return lNew;
}

View File

@@ -0,0 +1,129 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipMemFile.h
* Includes the CZipMemFile class.
*
*/
#if !defined(ZIPARCHIVE_ZIPMEMFILE_DOT_H)
#define ZIPARCHIVE_ZIPMEMFILE_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "ZipAbstractFile.h"
#include "ZipString.h"
#include "ZipExport.h"
/**
Represents a file in memory.
Automatically grows when necessary.
*/
class ZIP_API CZipMemFile : public CZipAbstractFile
{
protected:
size_t m_nGrowBy, m_nPos;
size_t m_nBufSize, m_nDataSize;
BYTE* m_lpBuf;
bool m_bAutoDelete;
void Free()
{
if (m_lpBuf)
{
free(m_lpBuf);
m_lpBuf = NULL;
}
}
void Init()
{
m_nGrowBy = m_nPos = 0;
m_nBufSize = m_nDataSize = 0;
m_lpBuf = NULL;
}
void Grow(size_t nBytes);
public:
bool IsClosed() const { return m_lpBuf == NULL;}
void Flush(){}
ZIP_FILE_USIZE Seek(ZIP_FILE_SIZE lOff, int nFrom);
ZIP_FILE_USIZE GetLength() const {return m_nDataSize;}
void Write(const void* lpBuf, UINT nCount);
UINT Read(void* lpBuf, UINT nCount);
void SetLength(ZIP_FILE_USIZE nNewLen);
CZipString GetFilePath() const {return _T("");}
CZipMemFile(long nGrowBy = 1024)
{
Init();
m_nGrowBy = nGrowBy;
m_bAutoDelete = true;
}
CZipMemFile(BYTE* lpBuf, UINT nBufSize, long nGrowBy = 0)
{
Init();
Attach(lpBuf, nBufSize, nGrowBy);
}
CZipMemFile(CZipMemFile& from)
{
Copy(from);
}
void Copy(CZipMemFile& from)
{
SetLength(from.m_nDataSize);
from.Read(m_lpBuf, (UINT)from.m_nDataSize);
}
ZIP_FILE_USIZE GetPosition() const { return m_nPos;}
void Attach(BYTE* lpBuf, UINT nBufSize, long nGrowBy = 0)
{
Close();
m_lpBuf = lpBuf;
m_nGrowBy = nGrowBy;
m_nBufSize = nBufSize;
m_nDataSize = nGrowBy == 0 ? nBufSize : 0;
m_bAutoDelete = false;
}
void ReInit(long nGrowBy = 1024)
{
Close();
Init();
m_nGrowBy = nGrowBy;
m_bAutoDelete = true;
}
BYTE* Detach()
{
BYTE* b = m_lpBuf;
Init();
return b;
}
void Close()
{
if (m_bAutoDelete)
Free();
Init();
}
virtual ~CZipMemFile(){Close();}
};
#endif // !defined(ZIPARCHIVE_ZIPMEMFILE_DOT_H)

View File

@@ -0,0 +1,38 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipMutex.h
* Includes the ZipArchiveLib::CZipMutex class.
*
*/
#if !defined(ZIPARCHIVE_ZIPMUTEX_DOT_H)
#define ZIPARCHIVE_ZIPMUTEX_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "_features.h"
#ifdef ZIP_ARCHIVE_LNX
#include "ZipMutex_lnx.h"
#else
#include "ZipMutex_win.h"
#endif
#endif

View File

@@ -0,0 +1,84 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_ZIPMUTEX_DOT_H
#error Do not include this file directly. Include ZipMutex.h instead
#endif
#ifdef ZIP_ARCHIVE_USE_LOCKING
#include <pthread.h>
namespace ZipArchiveLib
{
class ZIP_API CZipMutex
{
pthread_mutex_t m_mutex;
bool m_bOpened;
public:
CZipMutex(bool bOpen = false)
{
if (bOpen)
Open();
else
m_bOpened = false;
}
void Open()
{
Close();
if (pthread_mutex_init(&m_mutex, NULL) == 0)
m_bOpened = true;
else
CZipException::Throw(CZipException::mutexError);
}
void Lock()
{
if (pthread_mutex_lock(&m_mutex) != 0)
CZipException::Throw(CZipException::mutexError);
}
void Unlock()
{
if (pthread_mutex_unlock(&m_mutex) != 0)
CZipException::Throw(CZipException::mutexError);
}
CZipMutex& operator=(const CZipMutex&)
{
m_bOpened = false;
return *this;
}
void Close()
{
if (m_bOpened)
if (pthread_mutex_destroy(&m_mutex) == 0)
m_bOpened = false;
else
CZipException::Throw(CZipException::mutexError);
}
~CZipMutex()
{
Close();
}
};
}
#endif

View File

@@ -0,0 +1,81 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_ZIPMUTEX_DOT_H
#error Do not include this file directly. Include ZipMutex.h instead
#endif
#ifdef ZIP_ARCHIVE_USE_LOCKING
#include "ZipException.h"
namespace ZipArchiveLib
{
class ZIP_API CZipMutex
{
HANDLE m_handle;
public:
CZipMutex(bool bOpen = false)
{
if (bOpen)
Open();
else
m_handle = NULL;
}
void Open()
{
Close();
m_handle = ::CreateMutex(NULL, FALSE, NULL);
if (m_handle == NULL)
CZipException::Throw(CZipException::mutexError);
}
void Lock()
{
DWORD dwRet = ::WaitForSingleObject(m_handle, INFINITE);
if (dwRet != WAIT_OBJECT_0 && dwRet != WAIT_ABANDONED)
CZipException::Throw(CZipException::mutexError);
}
void Unlock()
{
if (!::ReleaseMutex(m_handle))
CZipException::Throw(CZipException::mutexError);
}
void Close()
{
if (m_handle != NULL)
{
::CloseHandle(m_handle);
m_handle = NULL;
}
}
CZipMutex& operator=(const CZipMutex&)
{
m_handle = NULL;
return *this;
}
~CZipMutex()
{
Close();
}
};
}
#endif

View File

@@ -0,0 +1,276 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipPathComponent.h
* Includes the CZipPathComponent class.
*
*/
#if !defined(ZIPARCHIVE_ZIPPATHCOMPONENT_DOT_H)
#define ZIPARCHIVE_ZIPPATHCOMPONENT_DOT_H
#if _MSC_VER > 1000
#pragma once
#if defined ZIP_HAS_DLL
#pragma warning (push)
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#endif
#endif
#include "ZipString.h"
#include "ZipExport.h"
/**
Splits a file path into components.
*/
class ZIP_API CZipPathComponent
{
public:
CZipPathComponent(){}
virtual ~CZipPathComponent();
static const TCHAR m_cSeparator; ///< A system - specific default path separator.
/**
Appends a path separator to \a szPath, if it is not already appended.
\param szPath
The path to have a separator appended.
*/
static void AppendSeparator(CZipString& szPath)
{
RemoveSeparators(szPath);
szPath += m_cSeparator;
}
/**
Combines a path information with a file name information.
\param szPath
Provides the path information and retrieves the result.
\param lpszName
The filename to be appended to the path.
*/
static void Combine(CZipString& szPath, LPCTSTR lpszName)
{
AppendSeparator(szPath);
if (lpszName != NULL)
szPath += lpszName;
}
/**
Removes path separators from the end of \a szPath
\param szPath
The path to have path separators removed.
*/
static void RemoveSeparators(CZipString& szPath)
{
// szPath.TrimRight(m_cSeparator);
szPath.TrimRight(_T("\\/"));
}
/**
Removes path separators from the beginning of \a szPath.
\param szPath
The path to have path separators removed.
*/
static void RemoveSeparatorsLeft(CZipString& szPath)
{
szPath.TrimLeft(_T("\\/"));
}
/**
Tests the character, if it is a separator or not.
\param c
The character to test.
\return
\c true, if \a c is a path separator; \c false otherwise.
*/
static bool IsSeparator(TCHAR c)
{
return c == _T('\\') || c == _T('/');
}
/**
Checks if \a szPath has a path separator appended.
\param szPath
The path to be tested.
\return
\c true, if \a szPath has a path separator at the end; \c false otherwise.
*/
static bool HasEndingSeparator(const CZipString& szPath)
{
int iLen = szPath.GetLength();
if (iLen)
return IsSeparator(szPath[iLen - 1]);
else
return false;
}
/**
Initializes a new instance of the CZipPathComponent class.
\param lpszFullPath
The full path to the file.
\see
SetFullPath
*/
CZipPathComponent(LPCTSTR lpszFullPath)
{
SetFullPath(lpszFullPath);
}
/**
Sets the full path to the file.
\param lpszFullPath
The full path to the file including a filename.
The last element in the path is assumed to be a filename.
*/
void SetFullPath(LPCTSTR lpszFullPath);
/**
Gets the name of the file without an extension (and without a path).
\return
The title of the file.
*/
CZipString GetFileTitle() const { return m_szFileTitle;}
/**
Sets the file title (the name without an extension and without a path).
\param lpszFileTitle
The title to set.
*/
void SetFileTitle(LPCTSTR lpszFileTitle) { m_szFileTitle = lpszFileTitle;}
/**
Sets the extension alone.
\param lpszExt
The extension to set. May contain a dot at the beginning, but doesn't have to.
*/
void SetExtension(LPCTSTR lpszExt)
{
m_szFileExt = lpszExt;
m_szFileExt.TrimLeft(_T('.'));
}
/**
Gets the extension of the file.
\return
The extension without a dot.
*/
CZipString GetFileExt() const { return m_szFileExt;}
/**
Gets the drive of the file.
\return
The drive without a path separator at the end.
*/
CZipString GetFileDrive() const { return m_szDrive;}
/**
Gets the full path to the file without the drive.
\return
The path without the drive and without a path separator at the beginning.
*/
CZipString GetNoDrive() const ;
/**
Get the filename.
\return
The filename including an extension and without a path.
*/
CZipString GetFileName() const
{
CZipString szFullFileName = m_szFileTitle;
if (!m_szFileExt.IsEmpty())
{
szFullFileName += _T(".");
szFullFileName += m_szFileExt;
}
return szFullFileName;
}
/**
Gets the full path to the file.
\return
The full path information including the filename.
*/
CZipString GetFullPath() const
{
CZipString szFullPath = GetFilePath();
CZipString szFileName = GetFileName();
if (!szFileName.IsEmpty())
{
if (szFullPath.IsEmpty())
szFullPath += _T('.');
szFullPath += m_cSeparator;
szFullPath += szFileName;
}
return szFullPath;
}
/**
Gets the path part only.
\return
The path to the file without a filename and without a path separator at the end.
*/
CZipString GetFilePath() const
{
CZipString szDrive = m_szDrive;
CZipString szDir = m_szDirectory;
if (!szDrive.IsEmpty() && !szDir.IsEmpty())
szDrive += m_cSeparator;
return m_szPrefix + szDrive + szDir;
}
protected:
/**
\name Path parts.
*/
//@{
CZipString m_szDirectory, ///< A directory(ies) only without path separators at the end and the beginning.
m_szFileTitle, ///< A filename without an extension.
m_szFileExt, ///< A file extension without a dot.
m_szDrive, ///< A drive (if the system path standard uses it) without a path separator at the end.
m_szPrefix; ///< A prefix (e.g. for the UNC path or Unicode path under Windows).
//@}
};
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning (pop)
#endif
#endif // !defined(ZIPARCHIVE_ZIPPATHCOMPONENT_DOT_H)

View File

@@ -0,0 +1,265 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipPlatform.h
* ZipPlatform namespace declaration.
*
*/
#if !defined(ZIPARCHIVE_ZIPPLATFORM_DOT_H)
#define ZIPARCHIVE_ZIPPLATFORM_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
class CZipFileHeader;
class CZipAutoBuffer;
#include "ZipString.h"
#include "ZipPathComponent.h"
#include <sys/types.h>
#include "ZipExport.h"
/**
Includes functions that require system-specific implementation.
*/
namespace ZipPlatform
{
/**
Gets the default case-sensitivity for the current file system.
\return
\c true, if the system is case-sensitive; \c false otherwise.
*/
ZIP_API bool GetSystemCaseSensitivity();
/**
Gets the current system identifier.
\return
One of the ZipCompatibility::ZipPlatforms values.
\see
CZipArchive::SetSystemCompatibility
*/
ZIP_API int GetSystemID();
/**
Gets the default file attributes for the current system.
\return
The default file attributes.
*/
ZIP_API DWORD GetDefaultAttributes();
/**
Gets the default directory attributes for the current system.
\return
The default directory attributes.
*/
ZIP_API DWORD GetDefaultDirAttributes();
/**
Gets the free space on the given device.
\param lpszPath
Points to the device to test.
\return
The free space in bytes.
*/
ZIP_API ULONGLONG GetDeviceFreeSpace(LPCTSTR lpszPath);
/**
Gets the name of a temporary file ensuring there is enough free space in the destination directory.
\param lpszPath
The path to the directory to initially create the file in.
\param uSizeNeeded
The requested free space size in bytes. If set to <code>ZIP_SIZE_TYPE(-1)</code>, the
space availability is not checked.
*/
ZIP_API CZipString GetTmpFileName(LPCTSTR lpszPath = NULL, ZIP_SIZE_TYPE uSizeNeeded = ZIP_SIZE_TYPE(-1));
/**
\name Various operations on files and directories.
If the functions returns a \c bool value, then \c true indicates that the operation was successful.
*/
//@{
ZIP_API bool GetCurrentDirectory(CZipString& sz); ///< Gets the current directory and stores it in \a sz.
ZIP_API bool ChangeDirectory(LPCTSTR lpDirectory); ///< Changes the current directory.
ZIP_API bool SetFileAttr(LPCTSTR lpFileName, DWORD uAttr); ///< Sets the file attributes.
ZIP_API bool GetFileAttr(LPCTSTR lpFileName, DWORD& uAttr); ///< Gets the file attributes.
ZIP_API bool GetFileModTime(LPCTSTR lpFileName, time_t & ttime); ///< Gets the file modification time.
ZIP_API bool SetFileModTime(LPCTSTR lpFileName, time_t ttime); ///< Set the file modification time.
ZIP_API bool GetFileSize(LPCTSTR lpszFileName, ZIP_SIZE_TYPE& dSize); ///< Gets the file size.
ZIP_API bool CreateDirectory(LPCTSTR lpDirectory); ///< Creates a new directory.
ZIP_API bool SetVolLabel(LPCTSTR lpszPath, LPCTSTR lpszLabel); ///< Sets a label on a removable device. \c lpszPath may point to a file on the device.
ZIP_API bool ForceDirectory(LPCTSTR lpDirectory); ///< Creates nested directories at once.
ZIP_API bool RemoveFile(LPCTSTR lpszFileName, bool bThrow = true); ///< Removes a file.
ZIP_API bool RenameFile( LPCTSTR lpszOldName, LPCTSTR lpszNewName, bool bThrow = true); ///< Renames a file.
#ifdef ZIP_ARCHIVE_LNX
ZIP_API bool SetExeAttr( LPCTSTR lpFileName ); ///< Sets executable permissions for a file.
#endif
#if defined ZIP_ARCHIVE_STL || defined ZIP_FILE_USES_STL
/**
Truncates the file.
\note
Defined only in the STL version.
*/
ZIP_API bool TruncateFile(int iDes, ULONGLONG uSize);
/**
Opens the file.
\note
Defined only in the STL version.
*/
ZIP_API int OpenFile(LPCTSTR lpszFileName, UINT iMode, int iShareMode);
/**
Flushes the file to the disk.
\note
Defined only in the STL version.
*/
ZIP_API bool FlushFile(int iDes);
/**
Gets the underlying system handle.
\note
Defined only in the STL version.
*/
ZIP_API intptr_t GetFileSystemHandle(int iDes);
#endif
//@}
/**
Checks if the given directory exists.
\param lpszDir
The directory to test.
\return
\c true, if \a lpszDir exists; \c false otherwise.
*/
ZIP_API bool DirectoryExists(LPCTSTR lpszDir);
/**
Checks if the given drive is removable.
\param lpszFilePath
The path to the drive. May point to a file path or a directory on the drive.
\return
\c true. if the drive is removable; \c false otherwise.
\note
Implemented only on Windows system, on all others always returns \c true.
*/
ZIP_API bool IsDriveRemovable(LPCTSTR lpszFilePath);
/**
Checks if the given attributes represent a directory.
\param uAttr
The attributes to test.
\return
\c true if the attributes represent a directory; \c false otherwise.
*/
ZIP_API bool IsDirectory(DWORD uAttr);
/**
Performs the translation between ANSI and OEM character sets.
\param buffer
The buffer containing characters to be translated.
\param bAnsiToOem
If \c true, convert ANSI to OEM; if \c false, OEM to ANSI.
*/
ZIP_API void AnsiOem(CZipAutoBuffer& buffer, bool bAnsiToOem);
/**
Checks if the given file or directory exists.
\param lpszName
The path to the file or directory to test.
\return
One of the following values:
- \c -1 : the given file exists and is a directory
- \c 1 : the given file exists and is a regular file
- \c 0 : there is no such a file
*/
ZIP_API int FileExists(LPCTSTR lpszName);
#ifdef _UNICODE
/**
Converts a wide character string to a multi-byte character string.
\param lpszIn
The wide character string to convert.
\param szOut
The buffer to receive the converted string.
Does not contain the terminating \c NULL character.
\param uCodePage
The code page used in conversion.
\return
The \a szOut buffer length, or \c -1 when not succeeded.
\note
Defined only in the UNICODE version.
*/
ZIP_API int WideToMultiByte(LPCWSTR lpszIn, CZipAutoBuffer &szOut, UINT uCodePage);
/**
Converts a multi-byte character string to a wide character string.
\param szIn
The multi-byte character string to convert.
Should not contain the terminating \c NULL character.
\param szOut
Receives the converted string.
\param uCodePage
The code page used in conversion.
\return
The length of the string after the conversion (without the terminating \c NULL character)
or \c -1 when the function did not succeed.
\note
Defined only in the UNICODE version.
*/
ZIP_API int MultiByteToWide(const CZipAutoBuffer &szIn, CZipString& szOut, UINT uCodePage);
#endif
};
#endif // !defined(ZIPARCHIVE_ZIPPLATFORM_DOT_H)

View File

@@ -0,0 +1,94 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipFile.h"
#include "ZipPlatform.h"
#include "ZipException.h"
using namespace ZipPlatform;
bool ZipPlatform::DirectoryExists(LPCTSTR lpszDir)
{
CZipString sz;
if (!GetCurrentDirectory(sz))
return false;
if (!ChangeDirectory(lpszDir))
return false;
ChangeDirectory(sz);
return true;
}
bool ZipPlatform::ForceDirectory(LPCTSTR lpDirectory)
{
ASSERT(lpDirectory);
CZipString szDirectory = lpDirectory;
szDirectory.TrimRight(CZipPathComponent::m_cSeparator);
CZipPathComponent zpc(szDirectory);
if ((zpc.GetFilePath().Compare((LPCTSTR)szDirectory)) == 0 ||
(FileExists(szDirectory) == -1))
return true;
if (!ForceDirectory(zpc.GetFilePath()))
return false;
if (!CreateDirectory(szDirectory))
return false;
return true;
}
bool ZipPlatform::GetFileSize(LPCTSTR lpszFileName, ZIP_SIZE_TYPE& dSize)
{
CZipFile f;
if (!f.Open(lpszFileName, CZipFile::modeRead | CZipFile::shareDenyWrite, false))
return false;
bool ret;
try
{
ZIP_FILE_USIZE size = f.GetLength();
// the file may be too large if zip64 is not enabled
ret = size <= ZIP_SIZE_TYPE(-1);
if (ret)
dSize = (ZIP_SIZE_TYPE)size;
}
#ifdef ZIP_ARCHIVE_MFC
catch(CZipBaseException* e)
{
e->Delete();
ret = false;
}
#else
catch(CZipBaseException e)
{
ret = false;
}
#endif
try
{
f.Close();
}
#ifdef ZIP_ARCHIVE_MFC
catch(CZipBaseException* e)
{
e->Delete();
}
#else
catch(CZipBaseException e)
{
}
#endif
return ret;
}

View File

@@ -0,0 +1,615 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZipStorage.h"
#include "ZipArchive.h"
#include "ZipPlatform.h"
char CZipStorage::m_gszExtHeaderSignat[] = {0x50, 0x4b, 0x07, 0x08};
const ZIP_FILE_USIZE CZipStorage::SignatureNotFound = ZIP_FILE_USIZE(-1);
CZipStorage::CZipStorage()
{
Initialize();
}
void CZipStorage::Initialize()
{
m_pSplitChangeVolumeFunc = m_pSpanChangeVolumeFunc = m_pChangeVolumeFunc = NULL;
m_iWriteBufferSize = 65536;
m_pFile = NULL;
m_szSplitExtension = _T("zip");
m_iLocateBufferSize = 32768;
m_uBytesBeforeZip = 0;
m_uCurrentVolume = ZIP_VOLUME_NUMBER_UNSPECIFIED;
m_szArchiveName.Empty();
}
CZipStorage::~CZipStorage()
{
}
DWORD CZipStorage::Read(void *pBuf, DWORD iSize, bool bAtOnce)
{
if (iSize == 0)
return 0;
DWORD iRead;
for(;;)
{
iRead = m_pFile->Read(pBuf, iSize);
if (!iRead)
{
if (IsSegmented())
ChangeVolume();
else
ThrowError(CZipException::badZipFile);
}
else
break;
}
if (iRead == iSize)
return iRead;
else if (bAtOnce || !IsSegmented())
ThrowError(CZipException::badZipFile);
while (iRead < iSize)
{
ChangeVolume();
UINT iNewRead = m_pFile->Read((char*)pBuf + iRead, iSize - iRead);
if (!iNewRead && iRead < iSize)
ThrowError(CZipException::badZipFile);
iRead += iNewRead;
}
return iRead;
}
void CZipStorage::Open(LPCTSTR lpszPathName, int iMode, ZIP_SIZE_TYPE uVolumeSize)
{
m_uCurrentVolume = ZIP_VOLUME_NUMBER_UNSPECIFIED;
m_pWriteBuffer.Allocate(m_iWriteBufferSize);
m_uBytesInWriteBuffer = 0;
m_bNewSegm = false;
m_pFile = &m_internalfile;
m_bInMemory = false;
m_szArchiveName = lpszPathName;
m_pChangeVolumeFunc = NULL;
if (iMode == CZipArchive::zipCreate || iMode == CZipArchive::zipCreateSegm
|| iMode == CZipArchive::zipCreateAppend) // create new archive
{
m_bReadOnly = false;
m_uCurrentVolume = 0;
if (iMode == CZipArchive::zipCreate || iMode == CZipArchive::zipCreateAppend)
{
m_iSegmMode = noSegments;
OpenFile(lpszPathName, (iMode == CZipArchive::zipCreate ? CZipFile::modeCreate : CZipFile::modeNoTruncate) | CZipFile::modeReadWrite);
}
else // create a segmented archive
{
m_bNewSegm = true;
m_uBytesWritten = 0;
if (uVolumeSize == ZIP_AUTODETECT_VOLUME_SIZE) // spanned archive
{
if (!m_pSpanChangeVolumeFunc)
ThrowError(CZipException::noCallback);
if (!ZipPlatform::IsDriveRemovable(lpszPathName))
ThrowError(CZipException::nonRemovable);
m_iSegmMode = spannedArchive;
m_pChangeVolumeFunc = m_pSpanChangeVolumeFunc;
}
else
{
m_uSplitData = uVolumeSize;
m_iSegmMode = splitArchive;
m_pChangeVolumeFunc = m_pSplitChangeVolumeFunc;
}
NextVolume(4);
Write(m_gszExtHeaderSignat, 4, true);
}
}
else // open existing
{
m_bReadOnly = iMode == CZipArchive::zipOpenReadOnly;
OpenFile(lpszPathName, CZipFile::modeNoTruncate |
(m_bReadOnly ? CZipFile::modeRead : CZipFile::modeReadWrite));
// m_uData and m_iSegmMode are automatically set during reading the central dir
m_iSegmMode = uVolumeSize == 0 ? suggestedAuto : suggestedSplit;
}
}
void CZipStorage::Open(CZipAbstractFile& af, int iMode)
{
m_pWriteBuffer.Allocate(m_iWriteBufferSize);
m_uBytesInWriteBuffer = 0;
m_bNewSegm = false;
m_pFile = &af;
m_bInMemory = true;
if (iMode == CZipArchive::zipCreate || iMode == CZipArchive::zipCreateAppend)
{
m_uCurrentVolume = 0;
m_iSegmMode = noSegments;
if (iMode == CZipArchive::zipCreate)
af.SetLength(0);
else
af.SeekToEnd();
}
else // open existing
{
af.SeekToBegin();
m_iSegmMode = suggestedAuto;
}
}
void CZipStorage::ChangeVolume(ZIP_VOLUME_TYPE uNumber)
{
if (uNumber == m_uCurrentVolume || m_iSegmMode == noSegments) // the second condition may happen in some bad archives
return;
m_uCurrentVolume = uNumber;
OpenFile(IsSpanned() ? ChangeSpannedRead() : ChangeSplitRead(),
CZipFile::modeNoTruncate | CZipFile::modeRead);
}
void CZipStorage::ThrowError(int err)
{
CZipException::Throw(err, m_pFile->GetFilePath());
}
bool CZipStorage::OpenFile(LPCTSTR lpszName, UINT uFlags, bool bThrow)
{
return m_pFile->Open(lpszName, uFlags | CZipFile::shareDenyWrite, bThrow);
}
CZipString CZipStorage::ChangeSpannedRead()
{
CZipString szTemp = m_pFile->GetFilePath();
m_pFile->Close();
CallCallback(0, CZipSegmCallback::scVolumeNeededForRead, szTemp);
return szTemp;
}
CZipString CZipStorage::ChangeSplitRead()
{
bool lastPart = (ZIP_SIZE_TYPE)m_uCurrentVolume == m_uSplitData;
CZipString szTemp = GetSplitVolumeName(lastPart);
if (m_pChangeVolumeFunc)
{
int iCode = CZipSegmCallback::scVolumeNeededForRead;
for(;;)
{
CallCallback(lastPart ? ZIP_SPLIT_LAST_VOLUME : 0, iCode, szTemp);
if (ZipPlatform::FileExists(m_pChangeVolumeFunc->m_szExternalFile))
{
szTemp = m_pChangeVolumeFunc->m_szExternalFile;
break;
}
else
iCode = CZipSegmCallback::scFileNotFound;
}
}
m_pFile->Close();
return szTemp;
}
CZipString CZipStorage::RenameLastFileInSplitArchive()
{
ASSERT(IsSplit());
// give to the last volume the zip extension
CZipString szFileName = m_pFile->GetFilePath();
CZipString szNewFileName = GetSplitVolumeName(true);
if (m_pChangeVolumeFunc)
{
int code = CZipSegmCallback::scVolumeNeededForWrite;
for(;;)
{
CallCallback(ZIP_SPLIT_LAST_VOLUME, code, szNewFileName);
szNewFileName = m_pChangeVolumeFunc->m_szExternalFile;
if (ZipPlatform::FileExists(szNewFileName))
code = CZipSegmCallback::scFileNameDuplicated;
else
break;
}
}
if (!m_bInMemory)
{
m_pFile->Flush();
m_pFile->Close();
}
if (!m_pChangeVolumeFunc && ZipPlatform::FileExists(szNewFileName))
ZipPlatform::RemoveFile(szNewFileName);
ZipPlatform::RenameFile(szFileName, szNewFileName);
return szNewFileName;
}
CZipString CZipStorage::Close(bool bAfterException)
{
bool bClose = true;
CZipString sz;
if (!bAfterException)
{
Flush();
if (IsSplit() && m_bNewSegm)
{
sz = RenameLastFileInSplitArchive();
bClose = false;// already closed in RenameLastFileInSplitArchive
}
}
if (sz.IsEmpty())
sz = m_pFile->GetFilePath();
if (bClose && !m_bInMemory)
{
if (!bAfterException)
FlushFile();
m_pFile->Close();
}
m_pWriteBuffer.Release();
m_uCurrentVolume = ZIP_VOLUME_NUMBER_UNSPECIFIED;
m_iSegmMode = noSegments;
m_pFile = NULL;
m_uBytesBeforeZip = 0;
return sz;
}
CZipString CZipStorage::GetSplitVolumeName(bool bLast) const
{
CZipString szFilePath = m_szArchiveName;
CZipPathComponent zpc(szFilePath);
CZipString szExt;
if (bLast)
szExt = m_szSplitExtension;
else
{
DWORD vol = m_uCurrentVolume + 1;
if (vol < 100)
szExt.Format(_T("z%.2u"), vol);
else
szExt.Format(_T("z%u"), vol);
}
zpc.SetExtension(szExt);
return zpc.GetFullPath();
}
void CZipStorage::NextVolume(ZIP_SIZE_TYPE uNeeded)
{
Flush();
ASSERT(m_iSegmMode != noSegments);
bool bSpan = IsSpanned();
if (m_uBytesWritten)
{
m_uBytesWritten = 0;
m_uCurrentVolume++;
ZIP_VOLUME_TYPE uMaxVolumes = (ZIP_VOLUME_TYPE)(bSpan ? 999 : 0xFFFF);
if (m_uCurrentVolume >= uMaxVolumes) // m_uCurrentVolume is a zero-based index
ThrowError(CZipException::tooManyVolumes);
}
CZipString szFileName;
if (bSpan)
szFileName = m_szArchiveName;
else
szFileName = GetSplitVolumeName(false);
if (!m_pFile->IsClosed())
{
m_pFile->Flush();
m_pFile->Close();
}
if (m_pChangeVolumeFunc)
{
int iCode = CZipSegmCallback::scVolumeNeededForWrite;
for(;;)
{
CallCallback(uNeeded, iCode, szFileName);
if (!bSpan)
// allow the user to change the filename
szFileName = m_pChangeVolumeFunc->m_szExternalFile;
if (ZipPlatform::FileExists(szFileName))
iCode = CZipSegmCallback::scFileNameDuplicated;
else
{
if (bSpan)
{
CZipString label;
label.Format(_T("pkback# %.3d"), m_uCurrentVolume + 1);
if (!ZipPlatform::SetVolLabel(szFileName, label))
{
iCode = CZipSegmCallback::scCannotSetVolLabel;
continue;
}
}
if (OpenFile(szFileName, CZipFile::modeCreate | CZipFile::modeReadWrite, false))
break;
else
iCode = CZipSegmCallback::scFileCreationFailure;
}
}
m_uCurrentVolSize = bSpan ? GetFreeVolumeSpace() : m_uSplitData;
}
else
{
if (bSpan)
ThrowError(CZipException::internalError);
m_uCurrentVolSize = m_uSplitData;
OpenFile(szFileName, CZipFile::modeCreate | CZipFile::modeReadWrite);
}
}
void CZipStorage::CallCallback(ZIP_SIZE_TYPE uNeeded, int iCode, CZipString szTemp)
{
if (!m_pChangeVolumeFunc)
ThrowError(CZipException::internalError);
m_pChangeVolumeFunc->m_szExternalFile = szTemp;
m_pChangeVolumeFunc->m_uVolumeNeeded = (ZIP_VOLUME_TYPE)(m_uCurrentVolume + 1);
m_pChangeVolumeFunc->m_iCode = iCode;
if (!m_pChangeVolumeFunc->Callback(uNeeded))
CZipException::Throw(CZipException::aborted, szTemp);
}
ZIP_SIZE_TYPE CZipStorage::GetFreeVolumeSpace() const
{
ASSERT (IsSpanned());
CZipString szTemp = m_pFile->GetFilePath();
if (szTemp.IsEmpty()) // called once when creating a segmented archive
return 0;
else
{
CZipPathComponent zpc(szTemp);
ULONGLONG ret = ZipPlatform::GetDeviceFreeSpace(zpc.GetFilePath());
if (ret > (ZIP_SIZE_TYPE)(-1))
return (ZIP_SIZE_TYPE)(-1);
else
return (ZIP_SIZE_TYPE)ret;
}
}
void CZipStorage::UpdateSegmMode(ZIP_VOLUME_TYPE uLastDisk)
{
m_uCurrentVolume = uLastDisk;
if (uLastDisk)
{
// segmentation detected
CZipString szFilePath = m_pFile->GetFilePath();
if (m_iSegmMode == suggestedAuto)
m_iSegmMode = ZipPlatform::IsDriveRemovable(szFilePath) ?
spannedArchive : splitArchive;
else
{
ASSERT(m_iSegmMode == suggestedSplit);
m_iSegmMode = splitArchive;
}
if (IsSpanned())
{
if (!m_pSpanChangeVolumeFunc)
ThrowError(CZipException::noCallback);
m_pChangeVolumeFunc = m_pSpanChangeVolumeFunc;
}
else /*if (IsSplit())*/
{
m_uSplitData = uLastDisk; // volume with .zip extension ( the last one)
m_pChangeVolumeFunc = m_pSplitChangeVolumeFunc;
}
CZipPathComponent zpc(szFilePath);
m_szSplitExtension = zpc.GetFileExt();
m_pWriteBuffer.Release(); // no need for this in this case
}
else
m_iSegmMode = noSegments;
}
ZIP_SIZE_TYPE CZipStorage::AssureFree(ZIP_SIZE_TYPE uNeeded)
{
ZIP_SIZE_TYPE uFree;
while ((uFree = VolumeLeft()) < uNeeded)
{
if (IsSplit() && !m_uBytesWritten && !m_uBytesInWriteBuffer)
// in the splitArchive mode, if the size of the archive is less
// than the size of the packet to be written at once,
// increase once the size of the volume
m_uCurrentVolSize = uNeeded;
else
NextVolume(uNeeded);
}
return uFree;
}
void CZipStorage::Write(const void *pBuf, DWORD iSize, bool bAtOnce)
{
if (!IsSegmented())
WriteInternalBuffer((char*)pBuf, iSize);
else
{
// if not at once, one byte is enough free space
DWORD iNeeded = bAtOnce ? iSize : 1;
DWORD uTotal = 0;
while (uTotal < iSize)
{
ZIP_SIZE_TYPE uFree = AssureFree(iNeeded);
DWORD uLeftToWrite = iSize - uTotal;
DWORD uToWrite = uFree < uLeftToWrite ? (DWORD)uFree : uLeftToWrite;
WriteInternalBuffer((char*)pBuf + uTotal, uToWrite);
if (bAtOnce)
return;
else
uTotal += uToWrite;
}
}
}
void CZipStorage::WriteInternalBuffer(const char *pBuf, DWORD uSize)
{
DWORD uWritten = 0;
while (uWritten < uSize)
{
DWORD uFreeInBuffer = GetFreeInBuffer();
if (uFreeInBuffer == 0)
{
Flush();
uFreeInBuffer = m_pWriteBuffer.GetSize();
}
DWORD uLeftToWrite = uSize - uWritten;
DWORD uToCopy = uLeftToWrite < uFreeInBuffer ? uLeftToWrite : uFreeInBuffer;
memcpy((char*)m_pWriteBuffer + m_uBytesInWriteBuffer, pBuf + uWritten, uToCopy);
uWritten += uToCopy;
m_uBytesInWriteBuffer += uToCopy;
}
}
ZIP_SIZE_TYPE CZipStorage::VolumeLeft() const
{
// for spanned archives m_uCurrentVolSize is updated after each flush()
ZIP_SIZE_TYPE uBytes = m_uBytesInWriteBuffer + (IsSpanned() ? 0 : m_uBytesWritten);
return uBytes > m_uCurrentVolSize ? 0 : m_uCurrentVolSize - uBytes;
}
void CZipStorage::Flush()
{
if (m_uBytesInWriteBuffer)
{
m_pFile->Write(m_pWriteBuffer, m_uBytesInWriteBuffer);
if (m_iSegmMode != noSegments)
m_uBytesWritten += m_uBytesInWriteBuffer;
m_uBytesInWriteBuffer = 0;
}
if (IsSpanned())
// after writing it is difficult to predict the free space due to
// not completly written clusters, write operation may start from a new cluster
m_uCurrentVolSize = GetFreeVolumeSpace();
}
ZIP_FILE_USIZE CZipStorage::LocateSignature(char* szSignature, ZIP_SIZE_TYPE uMaxDepth)
{
const int recordSize = 4;
CZipAutoBuffer buffer(m_iLocateBufferSize);
ZIP_FILE_USIZE uFileLength = m_pFile->GetLength();
ZIP_SIZE_TYPE max = (ZIP_SIZE_TYPE)(uFileLength < uMaxDepth ? uFileLength : uMaxDepth);
ZIP_SIZE_TYPE position = (ZIP_SIZE_TYPE)(uFileLength - m_pFile->GetPosition());
int offset = 0;
int leftToFind = recordSize - 1;
int toRead = m_iLocateBufferSize;
bool found = false; // for fast checking if leftToFind needs resetting
while ( position < max )
{
position += toRead;
if ( position > max )
{
int diff = (int) ( position - max );
toRead -= diff;
offset = diff;
position = max;
}
Seek(position, seekFromEnd);
int actuallyRead = m_pFile->Read((char*)buffer + offset, toRead);
if (actuallyRead != toRead)
ThrowError(CZipException::badZipFile);
int pos = m_iLocateBufferSize - 1;
while ( pos >= offset )
{
if ( buffer[pos] == szSignature[leftToFind] )
{
if ( leftToFind == 0 )
return (ZIP_FILE_USIZE)(uFileLength - ( position - ( pos - offset ) ));
if ( !found )
found = true;
leftToFind--;
pos--;
}
else if ( found )
{
leftToFind = recordSize - 1;
found = false;
// do not decrease position, the current pos may be the first to find
}
else
pos--;
}
}
return SignatureNotFound;
}
ULONGLONG CZipStorage::Seek(ULONGLONG lOff, SeekType iSeekType)
{
if (iSeekType == seekCurrent)
{
ZIP_SIZE_TYPE uPosition = (ZIP_SIZE_TYPE)m_pFile->GetPosition();
if (IsSegmented() == -1)
{
ZIP_FILE_USIZE uLength = m_pFile->GetLength();
while (uPosition + lOff >= uLength)
{
ZIP_SIZE_TYPE uCanSeek = (ZIP_SIZE_TYPE)(uLength - uPosition);
lOff -= uCanSeek;
ChangeVolume();
uPosition = 0;
uLength = m_pFile->GetLength();
}
return lOff > 0 ? m_pFile->Seek((ZIP_FILE_USIZE)lOff) : 0;
}
else
return m_pFile->Seek((ZIP_FILE_SIZE)lOff, CZipAbstractFile::current);
}
else
{
if (m_uCurrentVolume == 0 && m_uBytesBeforeZip > 0)
lOff += m_uBytesBeforeZip;
return m_pFile->Seek((ZIP_FILE_USIZE)lOff, iSeekType == seekFromBeginning);
}
}
void CZipStorage::FinalizeSegm()
{
ASSERT(IsSegmented() == 1); // spanned archive in creation
ASSERT(!m_bInMemory);
CZipString szFileName;
if (IsSplit() && m_bNewSegm)
szFileName = RenameLastFileInSplitArchive();
else
{
szFileName = m_pFile->GetFilePath();
// the file is already closed
m_pFile->Close();
}
m_bNewSegm = false;
if (m_uCurrentVolume == 0) // one-volume segmented archive was converted to normal archive
m_iSegmMode = noSegments;
else
m_uSplitData = m_uCurrentVolume;
OpenFile(szFileName, CZipFile::modeNoTruncate | (m_iSegmMode == noSegments ? CZipFile::modeReadWrite : CZipFile::modeRead));
}

View File

@@ -0,0 +1,619 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipStorage.h
* Includes the CZipStorage class.
*
*/
#if !defined(ZIPARCHIVE_ZIPSTORAGE_DOT_H)
#define ZIPARCHIVE_ZIPSTORAGE_DOT_H
#if _MSC_VER > 1000
#pragma once
#if defined ZIP_HAS_DLL
#pragma warning (push)
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#endif
#endif
#include "ZipFile.h"
#include "ZipAutoBuffer.h"
#include "ZipString.h"
#include "ZipMemFile.h"
#include "ZipExport.h"
#include "ZipCallback.h"
/**
Represents the storage layer for an archive.
*/
class ZIP_API CZipStorage
{
friend class CZipArchive;
friend class CZipCentralDir;
public:
/**
The type of the segmentation of the archive.
\see
<a href="kb">0610051553</a>
\see
CZipArchive::GetSegmMode
*/
enum ZipSegmentationMode
{
noSegments, ///< No archive segmentation.
spannedArchive, ///< A spanned archive.
splitArchive, ///< A split archive.
/**
The archive segmentation type will be auto-detected.
If the archive is on the removable device,
assume a spanned archive, otherwise assume a split archive.
*/
suggestedAuto,
/**
If a segmented archive is on a removable device, assume a split archive.
Normally you create spanned archives on removable devices.
*/
suggestedSplit
};
/**
The direction of seeking operation.
\see
CZipStorage::Seek
*/
enum SeekType
{
seekFromBeginning, ///< Start seeking from the beginning of a file.
seekFromEnd, ///< Start seeking from the end of a file.
/**
Start seeking from the current position in an archive.
This value can cause a volume change when a segmented archive is opened for reading.
*/
seekCurrent
};
CZipStorage();
virtual ~CZipStorage();
void Initialize();
/**
Opens a new or existing archive in memory.
The meaning for the parameters is the same as in the CZipArchive::Open(CZipAbstractFile& , int) method.
*/
void Open(CZipAbstractFile& af, int iMode);
/**
Opens or creates an archive.
The meaning for the parameters is the same as in the CZipArchive::Open(LPCTSTR, int, ZIP_SIZE_TYPE) method.
*/
void Open(LPCTSTR lpszPathName, int iMode, ZIP_SIZE_TYPE uVolumeSize);
/**
Closes a segmented archive in creation and reopens it as an existing segmented archive (no modifications allowed).
The archive may also turn out to be a not segmented archive.
*/
void FinalizeSegm();
/**
Called only by CZipCentralDir::Read when opening an existing archive.
\param uLastVolume
The number of the volme the central directory is on.
\note Throws exceptions.
*/
void UpdateSegmMode(ZIP_VOLUME_TYPE uLastVolume);
/**
Ensures than in a segmented archive, there is enough free space on the current volume.
\param uNeeded
The size of the required free space in bytes.
\return
The number of free bytes on the current volume.
\note
Throws exceptions.
*/
ZIP_SIZE_TYPE AssureFree(ZIP_SIZE_TYPE uNeeded);
/**
Writes a chunk of data to the archive.
\param pBuf
The buffer with data.
\param iSize
The number of bytes to write.
\param bAtOnce
If \c true, the whole chunk must fit in the current volume.
If there is not enough free space, a volume change is performed.
\note
Throws exceptions.
*/
void Write(const void *pBuf, DWORD iSize, bool bAtOnce);
/**
Gets the total size currently occupied by the archive.
\return
The length of the current archive file increased by the number of bytes in the write buffer.
*/
ZIP_SIZE_TYPE GetOccupiedSpace() const
{
return ZIP_SIZE_TYPE(m_pFile->GetLength() + m_uBytesInWriteBuffer);
}
/**
The same as the CZipArchive::IsClosed method.
*/
bool IsClosed(bool bArchive) const
{
if (bArchive)
return GetCurrentVolume() == ZIP_VOLUME_NUMBER_UNSPECIFIED;
else
return !m_pFile || !m_bInMemory && m_pFile->IsClosed();
}
/**
Reads a chunk of data from the archive.
\param pBuf
The buffer to receive the data.
\param iSize
The number of bytes to read.
\param bAtOnce
If \c true, the specified number of bytes must be read
from the same volume (no volume change is allowed).
\note
Throws exceptions.
*/
DWORD Read(void* pBuf, DWORD iSize, bool bAtOnce);
/**
Gets the position in the file, taking into account the number of bytes in the write buffer
and the number of bytes before the archive.
\return
The position in the file.
\note
Throws exceptions.
*/
ZIP_SIZE_TYPE GetPosition() const
{
ZIP_SIZE_TYPE uPos = (ZIP_SIZE_TYPE)(m_pFile->GetPosition()) + m_uBytesInWriteBuffer;
if (m_uCurrentVolume == 0)
uPos -= m_uBytesBeforeZip;
return uPos;
}
/**
Flushes the data from the read buffer to the disk.
\note
Throws exceptions.
*/
void Flush();
/**
Forces any data remaining in the file buffer to be written to the disk.
*/
void FlushFile()
{
if (!m_bInMemory && !IsReadOnly())
m_pFile->Flush();
}
void FlushBuffers()
{
Flush();
FlushFile();
}
/**
Changes volumes during writing to a segmented archive.
\param uNeeded
The number of bytes needed in the volume.
\note
Throws exceptions.
*/
void NextVolume(ZIP_SIZE_TYPE uNeeded);
/**
Gets a zero-based number of the current volume.
*/
ZIP_VOLUME_TYPE GetCurrentVolume() const {return m_uCurrentVolume;}
/**
Changes the volume during extract operations.
\param uNumber
A zero-based number of the requested volume.
*/
void ChangeVolume(ZIP_VOLUME_TYPE uNumber);
/**
Changes the current volume to the next volume during extract operations.
*/
void ChangeVolume()
{
ChangeVolume((ZIP_VOLUME_TYPE)(m_uCurrentVolume + 1));
}
/**
Detects the segmentation mode.
\return
- \c -1 : An existing segmented archive is opened.
- \c 0 : The archive is not segmented.
- \c 1 : A segmented archive in creation.
*/
int IsSegmented() const
{
return m_iSegmMode == noSegments ? 0 : (m_bNewSegm ? 1 : -1);
}
/**
Checks, if the archive is a split archive.
\return
\c true, if the archive is a split archive; \c false otherwise.
*/
bool IsSplit() const
{
return m_iSegmMode == splitArchive;
}
/**
Checks, if the archive is a spanned archive.
\return
\c true, if the archive is a spanned archive; \c false otherwise.
*/
bool IsSpanned() const
{
return m_iSegmMode == spannedArchive;
}
/**
The same as the CZipArchive::IsReadOnly method.
*/
bool IsReadOnly()
{
return m_bReadOnly || IsSegmented() < 0;
}
/**
Performs the seeking operation on the #m_pFile.
\param lOff
The new position in the file.
\param iSeekType
The direction of the seek operation.
It can be one of the #SeekType values.
*/
ULONGLONG Seek(ULONGLONG lOff, SeekType iSeekType = seekFromBeginning);
/**
Gets the number of free bytes on the current volume.
\return
The number of free bytes on the current volume.
*/
ZIP_SIZE_TYPE VolumeLeft() const;
/**
Closes the storage.
\param bAfterException
Set to \c true, if an exception was thrown before.
\return
The file path of the archive.
\note
Throws exceptions.
*/
CZipString Close(bool bAfterException);
/**
Represents the physical storage of the current archive segment.
*/
CZipAbstractFile* m_pFile;
/**
The signature of the extended header.
*/
static char m_gszExtHeaderSignat[];
protected:
/**
Returns the file offset after the last data byte in the archive.
\return
The file offset after the last data byte in the archive.
*/
ZIP_SIZE_TYPE GetLastDataOffset()
{
return (ZIP_SIZE_TYPE)m_pFile->GetLength() - m_uBytesBeforeZip;
}
/**
Reverse-finds the location of the given signature starting from the current position in file.
\param szSignature
The signature to locate.
\param uMaxDepth
The maximum number of bytes to search for \a szSignature.
\return
The location of the signature.
\note
Throws exceptions.
*/
ZIP_FILE_USIZE LocateSignature(char* szSignature, ZIP_SIZE_TYPE uMaxDepth);
/**
Flushes without writing. Can be used only on not segmented archives.
*/
void EmptyWriteBuffer()
{
m_uBytesInWriteBuffer = 0;
}
/**
Opens a physical file.
\param lpszName
The name of the file to open.
\param uFlags
The file open flags.
\param bThrow
If \c true, throw an exception in case of failure.
\return
\c true if successful; \c false otherwise.
*/
bool OpenFile(LPCTSTR lpszName, UINT uFlags, bool bThrow = true);
/**
Renames the last segment file in a split archive when finalizing the whole archive.
\return
The name of the last segment.
*/
CZipString RenameLastFileInSplitArchive();
/**
Writes data to the internal buffer.
\param *pBuf
The buffer to copy the data from.
\param uSize
The number of bytes to write.
\note
Throws exceptions.
*/
void WriteInternalBuffer(const char *pBuf, DWORD uSize);
/**
Gets the free space size on the current removable disk.
\return
The free space in bytes.
*/
ZIP_SIZE_TYPE GetFreeVolumeSpace() const;
/**
Notifies the callback object.
Throws an exception if the callback method returns \c false.
\param uNeeded
The minimum number of free bytes required on the disk.
\param iCode
The code to be passed to the callback method.
\param szTemp
The string to be used as a filename (as an argument
in the CZipException::Throw method) when an exception must be thrown.
\note
Throws exceptions.
\see
CZipArchive::SetSegmCallback
*/
void CallCallback(ZIP_SIZE_TYPE uNeeded, int iCode, CZipString szTemp);
/**
Constructs the name of a segment in a split archive.
\param bLast
Set it to \c true, if constructing the last volume name.
\return
The segment name.
*/
CZipString GetSplitVolumeName(bool bLast) const;
/**
Changes a file when processing a split archive.
*/
CZipString ChangeSplitRead();
/**
Changes a disk when processing a spanned archive.
*/
CZipString ChangeSpannedRead();
/**
Gets the free space left in the write buffer.
\return
The free space left in the write buffer in bytes.
*/
DWORD GetFreeInBuffer() const {return m_pWriteBuffer.GetSize() - m_uBytesInWriteBuffer;}
/**
The value it holds, depends on the current mode:
- An opened existing split archive - stores the number of the last volume ( the one with "zip" extension).
- A split archive in creation - the size of the volume.
This method is used only when processing split archives.
*/
ZIP_SIZE_TYPE m_uSplitData;
/**
The extension of the last segment.
*/
CZipString m_szSplitExtension;
/**
The number of bytes available in the write buffer.
*/
DWORD m_uBytesInWriteBuffer;
/**
The value it holds depends on the segmentation mode:
- A split archive : the total size of the current volume.
- A spanned archive: the free space on the current volume.
*/
ZIP_SIZE_TYPE m_uCurrentVolSize;
/**
The write buffer caching data.
*/
CZipAutoBuffer m_pWriteBuffer;
/**
Stores the number of bytes that have been written physically to the current segment.
Used only when processing a segmented archive in creation.
*/
ZIP_SIZE_TYPE m_uBytesWritten;
/**
\c true, if the current archive is a new segmented archive; \c false otherwise.
*/
bool m_bNewSegm;
/**
The current volume number in a segmented archive.
The value is zero-based.
*/
ZIP_VOLUME_TYPE m_uCurrentVolume;
/**
\c true when the archive is created in memory; \c false otherwise.
*/
bool m_bInMemory;
/**
\c true if OpenMode::zipOpenReadOnly was specified when opening the archive.
*/
bool m_bReadOnly;
/**
The number of bytes before the actual zip archive in a file.
\see
CZipArchive::GetBytesBeforeZip
*/
ZIP_SIZE_TYPE m_uBytesBeforeZip;
/**
The size of the write buffer.
\see
CZipArchive::SetAdvanced
*/
int m_iWriteBufferSize;
/**
The size of the buffer used in searching for the central directory.
\see
CZipArchive::SetAdvanced
*/
int m_iLocateBufferSize;
/**
Takes one of the #ZipSegmentationMode values.
*/
int m_iSegmMode;
/**
A callback object called when there is a need for a volume change
in a spanned archive.
\see
CZipArchive::SetSegmCallback
*/
CZipSegmCallback* m_pSpanChangeVolumeFunc;
/**
A callback object called when there is a need for a volume change
in a split archive.
\see
CZipArchive::SetSegmCallback
*/
CZipSegmCallback* m_pSplitChangeVolumeFunc;
private:
CZipSegmCallback* m_pChangeVolumeFunc;
CZipString m_szArchiveName;
CZipFile m_internalfile;
static const ZIP_FILE_USIZE SignatureNotFound;
void ThrowError(int err);
};
#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
#pragma warning (pop)
#endif
#endif // !defined(ZIPARCHIVE_ZIPSTORAGE_DOT_H)

View File

@@ -0,0 +1,37 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipString.h
* Includes the CZipString class.
*
*/
#ifndef ZIPARCHIVE_ZIPSTRING_DOT_H
#define ZIPARCHIVE_ZIPSTRING_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "_platform.h"
#ifdef ZIP_ARCHIVE_STL
#include "ZipString_stl.h"
#else
#include "ZipString_mfc.h"
#endif
#endif /* ZIPARCHIVE_ZIPSTRING_DOT_H */

View File

@@ -0,0 +1,210 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file ZipStringStoreSettings.h
* Includes the CZipStringStoreSettings class.
*
*/
#if !defined(ZIPARCHIVE_ZIPSTRINGSTRINGSTORESETTINGS_DOT_H)
#define ZIPARCHIVE_ZIPSTRINGSTRINGSTORESETTINGS_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
#include "stdafx.h"
#include "ZipPlatform.h"
#include "ZipCompatibility.h"
/**
Settings used in storing strings inside archives.
\see
<a href="kb">0610051525</a>
\see
CZipArchive::SetStringStoreSettings.
*/
class ZIP_API CZipStringStoreSettings
{
public:
/**
Gets the default filename code page for the given platform.
\param iPlatform
One of the ZipCompatibility::ZipPlatforms values.
\return
The default filename code page.
*/
static UINT GetDefaultNameCodePage(int iPlatform)
{
return iPlatform == ZipCompatibility::zcDosFat ? CP_OEMCP : CP_ACP;
}
/**
Gets the default filename code page for the current platform.
\return
The default filename code page.
*/
static UINT GetDefaultNameCodePage()
{
return GetDefaultNameCodePage(ZipPlatform::GetSystemID());
}
/**
Gets the default comment code page. It is not platform-dependent.
*/
static UINT GetDefaultCommentCodePage()
{
return CP_ACP;
}
/**
Initializes a new instance of the CZipStringStoreSettings class.
*/
CZipStringStoreSettings()
{
Reset();
}
/**
Sets the default filename code page depening on the given platform.
\param iPlatform
One of the ZipCompatibility::ZipPlatforms values.
*/
void SetDefaultNameCodePage(int iPlatform)
{
m_uNameCodePage = GetDefaultNameCodePage(iPlatform);
}
/**
Gets a value indicating whether the current filename code page is
standard for the current platform or not.
\return
\c true, if the current filename code page is standard; \c false otherwise.
\see
ZipPlatform::GetSystemID
*/
bool IsStandardNameCodePage() const
{
return m_uNameCodePage == GetDefaultNameCodePage();
}
/**
Gets a value indicating whether the current filename code page is
standard for the given platform or not.
\param iPlatform
One of the ZipCompatibility::ZipPlatforms values.
\return
\c true, if the current filename code page is standard; \c false otherwise.
*/
bool IsStandardNameCodePage(int iPlatform) const
{
return m_uNameCodePage == GetDefaultNameCodePage(iPlatform);
}
/**
Gets a value indicating whether the current comment code page is standard.
\return
\c true, if the current comment code page is standard; \c false otherwise.
*/
bool IsStandardCommentCodePage() const
{
return m_uCommentCodePage == GetDefaultCommentCodePage();
}
/**
Gets a value indicating whether the current settings are
standard for the given platform or not.
\param iPlatform
One of the ZipCompatibility::ZipPlatforms values.
\return
\c true, if the current settings are standard; \c false otherwise.
*/
bool IsStandard(int iPlatform) const
{
return !m_bStoreNameInExtraData && IsStandardNameCodePage(iPlatform) && IsStandardCommentCodePage();
}
/**
Reset the settings to its default values for the given platform.
\param iPlatform
One of the ZipCompatibility::ZipPlatforms values.
\see
Reset
*/
void Reset(int iPlatform)
{
m_bStoreNameInExtraData = false;
SetDefaultNameCodePage(iPlatform);
m_uCommentCodePage = GetDefaultCommentCodePage();
}
/**
Reset the settings to its default values for the current platform.
\see
Reset(int)
\see
ZipPlatform::GetSystemID
*/
void Reset()
{
Reset(ZipPlatform::GetSystemID());
}
/**
Sets the string store settings.
\see
CZipArchive::SetStringStoreSettings(UINT, bool, UINT)
*/
void Set(UINT uFileNameCodePage, bool bStoreNameInExtraData, UINT uCommentCodePage)
{
m_uNameCodePage = uFileNameCodePage;
m_bStoreNameInExtraData = bStoreNameInExtraData;
m_uCommentCodePage = uCommentCodePage;
}
/**
If \c true, the converted filenames are stored in extra field in the archive.
*/
bool m_bStoreNameInExtraData;
/**
The current filename code page.
*/
UINT m_uNameCodePage;
/**
The current comment code page.
*/
UINT m_uCommentCodePage;
};
#endif // !defined(ZIPARCHIVE_ZIPSTRINGSTRINGSTORESETTINGS_DOT_H)

View File

@@ -0,0 +1,34 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_ZIPSTRING_DOT_H
#error Do not include this file directly. Include ZipString.h instead
#endif
#include "stdafx.h"
#include "ZipExport.h"
typedef CString CZipString;
/**
A pointer type to point to one of: Collate, CollateNoCase, Compare, CompareNoCase.
*/
typedef int (CZipString::*ZIPSTRINGCOMPARE)( LPCTSTR ) const;
/**
Return a pointer to a method in the CZipString structure,
used to compare elements depending on the arguments.
*/
ZIP_API ZIPSTRINGCOMPARE GetCZipStrCompFunc(bool bCaseSensitive, bool bCollate = true);

View File

@@ -0,0 +1,328 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_ZIPSTRING_DOT_H
#error Do not include this file directly. Include ZipString.h instead
#endif
#include "stdafx.h"
#if _MSC_VER > 1000
#pragma warning( push, 3 ) // STL requirements
#endif
#include <string>
#include <algorithm>
#include <stdarg.h>
#include <stdio.h>
#include <cctype>
#include <locale>
#include "ZipExport.h"
#ifndef __GNUC__
#ifndef _vsntprintf
#ifdef _UNICODE
#define _vsntprintf _vsnwprintf
#else
#define _vsntprintf _vsnprintf
#endif
#endif
#elif !defined(_vsntprintf)
#define _vsntprintf vsnprintf
#endif
typedef std::basic_string<TCHAR> stdbs;
/**
It contains mostly the methods required by ZipArchive Library.
*/
class ZIP_API CZipString : public stdbs
{
void TrimInternalL(size_type iPos)
{
if (iPos == npos)
erase ();
if (iPos)
erase(0, iPos);
}
void TrimInternalR(size_type iPos)
{
if (iPos == npos)
erase ();
erase(++iPos);
}
#ifndef __GNUC__
static int zslen(const TCHAR* lpsz)
{
if (!lpsz) return 0;
// we want to take into account the locale stuff (by using standard templates)
#ifdef _UNICODE
return (int)std::wstring(lpsz).length();
#else
return (int)std::string(lpsz).length();
#endif
}
#else
static int zslen(const TCHAR* lpsz)
{
#if (__GNUC__ < 3) // I'm not sure which precisely version should be put here
return lpsz ? std::string_char_traits<TCHAR>::length(lpsz) : 0;
#else
return lpsz ? std::char_traits<TCHAR>::length(lpsz) : 0;
#endif
}
#endif
static TCHAR tl(TCHAR c)
{
// use_facet doesn't work here well (doesn't convert all the local characters properly)
return std::tolower(c, std::locale());
}
static TCHAR tu(TCHAR c)
{
// use_facet doesn't work here well (doesn't convert all the local characters properly)
return std::toupper(c, std::locale());
}
public:
CZipString(){}
explicit CZipString (TCHAR ch, int nRepeat = 1):stdbs(nRepeat, ch){}
CZipString( const CZipString& stringSrc ) {assign(stringSrc);}
CZipString( const stdbs& stringSrc ) {assign(stringSrc);}
CZipString( LPCTSTR lpsz ){if (!lpsz) Empty(); else assign(lpsz);}
operator LPCTSTR() const{return c_str();}
int GetLength() const {return (int) size();}
bool IsEmpty() const {return empty();}
void Empty() {erase(begin(), end());}
TCHAR GetAt (int iIndex) const{return at(iIndex);}
TCHAR operator[] (int iIndex) const{return at(iIndex);}
void SetAt( int nIndex, TCHAR ch ) {at(nIndex) = ch;}
LPTSTR GetBuffer(int nMinBufLength)
{
if ((int)size() < nMinBufLength)
resize(nMinBufLength);
return empty() ? const_cast<TCHAR*>(data()) : &(at(0));
}
void ReleaseBuffer( int nNewLength = -1 ) { resize(nNewLength > -1 ? nNewLength : zslen(c_str()));}
void TrimLeft( TCHAR chTarget )
{
TrimInternalL(find_first_not_of(chTarget));
}
void TrimLeft( LPCTSTR lpszTargets )
{
TrimInternalL(find_first_not_of(lpszTargets));
}
void TrimRight( TCHAR chTarget )
{
TrimInternalR(find_last_not_of(chTarget));
}
void TrimRight( LPCTSTR lpszTargets )
{
TrimInternalR(find_last_not_of(lpszTargets));
}
#if _MSC_VER >= 1300
#pragma warning( push )
#pragma warning (disable : 4793) // 'vararg' : causes native code generation for function 'void CZipString::Format(LPCTSTR,...)'
#endif
void Format(LPCTSTR lpszFormat, ...)
{
va_list arguments;
va_start (arguments, lpszFormat);
TCHAR* pBuf = NULL;
int iCounter = 1, uTotal = 0;
do
{
int nChars = iCounter * 1024;
int nLen = sizeof(TCHAR) * nChars;
TCHAR* pTempBuf = (TCHAR*)realloc((void*)pBuf, nLen);
if (!pTempBuf)
{
if (pBuf != NULL)
free(pBuf);
va_end (arguments);
return;
}
pBuf = pTempBuf;
#if _MSC_VER >= 1400
uTotal = _vsntprintf_s(pBuf, nChars, nChars - 1, lpszFormat, arguments);
#else
uTotal = _vsntprintf(pBuf, nChars - 1, lpszFormat, arguments);
#endif
if (uTotal == -1 || (uTotal == nChars - 1) ) // for some implementations
{
pBuf[nChars - 1] = _T('\0');
if (iCounter == 7)
break;
}
else
{
pBuf[uTotal] = _T('\0');
break;
}
iCounter++;
} while (true);
va_end (arguments);
*this = pBuf;
free(pBuf);
}
#if _MSC_VER >= 1300
#pragma warning( pop )
#endif
void Insert( int nIndex, LPCTSTR pstr ){insert(nIndex, pstr, zslen(pstr));}
void Insert( int nIndex, TCHAR ch ) {insert(nIndex, 1, ch);}
int Delete( int nIndex, int nCount = 1 )
{
int iSize = (int) size();
int iToDelete = iSize < nIndex + nCount ? iSize - nIndex : nCount;
if (iToDelete > 0)
{
erase(nIndex, iToDelete);
iSize -= iToDelete;
}
return iSize;
}
#ifndef __MINGW32__
void MakeLower()
{
std::transform(begin(),end(),begin(),tl);
}
void MakeUpper()
{
std::transform(begin(),end(),begin(),tu);
}
#else
void MakeLower()
{
std::transform(begin(),end(),begin(),tolower);
}
void MakeUpper()
{
std::transform(begin(),end(),begin(),toupper);
}
#endif
void MakeReverse()
{
std::reverse(begin(), end());
}
CZipString Left( int nCount ) const { return substr(0, nCount);}
CZipString Right( int nCount) const
{
nCount = (int)size() < nCount ? (int)size() : nCount;
return substr(size() - nCount);
}
CZipString Mid( int nFirst ) const {return substr(nFirst);}
CZipString Mid( int nFirst, int nCount ) const {return substr(nFirst, nCount);}
int Collate( LPCTSTR lpsz ) const
{
#if !defined __GNUC__ || defined __MINGW32__
return _tcscoll(c_str(), lpsz);
#else
//return compare(lpsz);
return strcoll(c_str(), lpsz);
#endif
}
int CollateNoCase( LPCTSTR lpsz ) const
{
#if !defined __GNUC__ || defined __MINGW32__
return _tcsicoll(c_str(), lpsz);
#else
if (std::locale() == std::locale::classic())
return strcasecmp(c_str(), lpsz);
else
// this may be not case-insensitive !!!
return strcoll(c_str(), lpsz);
//return stricoll(c_str(), lpsz);
#endif
}
int Compare( LPCTSTR lpsz ) const
{
return compare(lpsz);
}
int CompareNoCase( LPCTSTR lpsz ) const
{
#if !defined __GNUC__ || defined __MINGW32__
return _tcsicmp(c_str(), lpsz);
#else
return strcasecmp(c_str(), lpsz);
//return stricmp(c_str(), lpsz);
#endif
}
bool operator != (LPCTSTR lpsz)
{
return Compare(lpsz) != 0;
}
bool operator == (LPCTSTR lpsz)
{
return Compare(lpsz) == 0;
}
int Find( TCHAR ch, int nStart = 0) const
{
return (int) find(ch, nStart);
}
int Find( LPCTSTR pstr, int nStart = 0) const
{
return (int) find(pstr, nStart);
}
int Replace( TCHAR chOld, TCHAR chNew )
{
int iCount = 0;
for (iterator it = begin(); it != end(); ++it)
if (*it == chOld)
{
*it = chNew;
iCount++;
}
return iCount;
}
};
/**
A poiter type to point to CZipString to Collate or CollateNoCase
or Compare or CompareNoCase
*/
typedef int (CZipString::*ZIPSTRINGCOMPARE)( LPCTSTR ) const;
/**
return a pointer to the function in CZipString structure,
used to compare elements depending on the arguments
*/
ZIP_API ZIPSTRINGCOMPARE GetCZipStrCompFunc(bool bCaseSensitive, bool bCollate = true);
#if _MSC_VER > 1000
#pragma warning( pop)
#endif

View File

@@ -0,0 +1,97 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file _features.h
* Contains definitions that enable or disable certain features in the ZipArchive Library.
*
*/
#if !defined(ZIPARCHIVE_FEATURES_DOT_H)
/// @cond
#define ZIPARCHIVE_FEATURES_DOT_H
/// @endcond
#if _MSC_VER > 1000
#pragma once
#endif
#include "_platform.h"
#ifdef __GNUC__
#ifndef __int64
#define __int64 long long
#endif
#endif
/************ Feel free to adjust the definitions in the following block ************/
/************************************ BLOCK START ***********************************/
/**
Make sure it is defined, if you use ZIP64. Comment this out otherwise.
\see
<a href="kb">0610051629</a>
*/
// #define _ZIP64
/**
Make sure it is defined, if you use AES. Comment this out otherwise.
\see
<a href="kb">0610201627|aes</a>
*/
// #define _ZIP_AES
/**
Make sure it is defined, if you use the BZIP2 algorithm for compression. Comment this out otherwise.
\see
<a href="kb">0610231446|bzip2</a>
*/
// #define _BZIP2
/**
Make sure it is defined, if you want to create seekable data.
\see
<a href="kb">0711101739</a>
*/
// #define _ZIP_SEEK
/**
Make sure it is defined, if you use the AES encryption in a multithreaded environment or archive sharing (CZipArchive::OpenFrom). Comment this out otherwise.
\see
<a href="kb">0610201627|aes</a>
\see
<a href="kb">0610241003|thread</a>
*/
// #define ZIP_ARCHIVE_USE_LOCKING
#ifndef _ZIP64
// Uncomment this to have the index and volume numbers types defined as WORD. Otherwise they are defined as int.
#define _ZIP_STRICT_U16
#endif
/************************************* BLOCK END ***********************************/
/***** The contents below this line are usually not intended for modification ******/
#endif // !defined(ZIPARCHIVE_FEATURES_DOT_H)

View File

@@ -0,0 +1,76 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
/**
* \file _platform.h
* Contains definitions that determine the target compilation platform.
*
*/
#if !defined(ZIPARCHIVE_PLATFORM_DOT_H)
#define ZIPARCHIVE_PLATFORM_DOT_H
#if _MSC_VER > 1000
#pragma once
#endif
/************ Feel free to adjust the definitions in the following block ************/
/************************************ BLOCK START ***********************************/
//#define ZIP_ARCHIVE_MFC
//#define ZIP_ARCHIVE_LNX
// simplified endianess detection
#ifdef __APPLE__
#ifdef __LITTLE_ENDIAN__
#define ZIP_ARCHIVE_LITTLE_ENDIAN
#endif
#else
#define ZIP_ARCHIVE_LITTLE_ENDIAN
#endif
/************************************* BLOCK END ***********************************/
/********* The contents below this line are not intended for modification **********/
#ifndef ZIP_ARCHIVE_MFC
#define ZIP_ARCHIVE_STL
#else
#ifdef ZIP_ARCHIVE_STL
#undef ZIP_ARCHIVE_STL
#endif
#endif
#ifndef ZIP_ARCHIVE_LNX
#define ZIP_ARCHIVE_WIN
#else
#ifdef ZIP_ARCHIVE_WIN
#undef ZIP_ARCHIVE_WIN
#endif
#endif
#ifndef ZIP_ARCHIVE_LITTLE_ENDIAN
#define ZIP_ARCHIVE_BIG_ENDIAN
#else
#ifdef ZIP_ARCHIVE_BIG_ENDIAN
#undef ZIP_ARCHIVE_BIG_ENDIAN
#endif
#endif
#if defined (ZIP_ARCHIVE_LNX) && defined (ZIP_ARCHIVE_MFC)
#undef ZIP_ARCHIVE_MFC
#define ZIP_ARCHIVE_STL
#error Using MFC under a non-Windows platform is not supported
#endif
#endif // !defined(ZIPARCHIVE_PLATFORM_DOT_H)

View File

@@ -0,0 +1,46 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_STDAFX_DOT_H
#error Do not include this file directly. Include stdafx.h instead
#endif
#if _MSC_VER > 1000
#ifndef WINVER
#define WINVER 0x0400
#endif
#pragma once
#endif
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#endif
#include <afx.h>
#include <afxwin.h>
typedef BOOL ZBOOL;
#if _MSC_VER >= 1300 || defined ZIP_FILE_USES_STL
#define ZIP_FILE_USIZE ULONGLONG
#define ZIP_FILE_SIZE LONGLONG
#define ZIP_FILE_SIZEMAX _I64_MAX
#else
#define ZIP_FILE_USIZE DWORD
#define ZIP_FILE_SIZE LONG
#define ZIP_FILE_SIZEMAX MAXLONG
#endif

View File

@@ -0,0 +1,126 @@
////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2007 by Artpol Software - Tadeusz Dracz
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#ifndef ZIPARCHIVE_STDAFX_DOT_H
#error Do not include this file directly. Include stdafx.h instead
#endif
#include "_features.h"
#if _MSC_VER > 1000
// STL warnings
#pragma warning (disable : 4710) // 'function' : function not inlined
#pragma warning (disable : 4514) // unreferenced inline/local function has been removed
#pragma warning (disable : 4786) // 'identifier' : identifier was truncated to 'number' characters in the debug information
#pragma warning (disable : 4702) // unreachable code
#endif
#if defined (_UNICODE) && !defined (UNICODE)
#define UNICODE
#endif
#if defined (UNICODE) && !defined (_UNICODE)
#define _UNICODE
#endif
#ifndef _WIN32
#ifndef NULL
#define NULL 0
#endif
#include <ctype.h>
typedef int HFILE;
typedef void* HANDLE;
typedef unsigned long DWORD;
typedef long LONG;
typedef int ZBOOL; /* to avoid conflicts when using Objective-C under Mac */
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int UINT;
#ifndef FALSE
#define FALSE (int)0
#endif
#ifndef TRUE
#define TRUE (int)1
#endif
typedef unsigned short WCHAR; // wc, 16-bit UNICODE character
typedef const WCHAR *LPCWSTR;
typedef const char *LPCSTR;
typedef WCHAR *LPWSTR;
typedef char *LPSTR;
#ifdef _UNICODE
typedef wchar_t TCHAR;
typedef LPCWSTR LPCTSTR;
typedef LPWSTR LPTSTR;
#define _T(x) L ## x
#else /* _UNICODE */ // r_winnt
typedef char TCHAR;
typedef LPCSTR LPCTSTR;
typedef LPSTR LPTSTR;
#ifdef _T
#undef _T
#endif
#define _T(x) x
#endif /* _UNICODE */ // r_winnt
typedef unsigned long long ULONGLONG;
typedef long long LONGLONG;
#define CP_ACP 0
#define CP_OEMCP 1
#ifndef _I64_MAX
#ifdef LLONG_MAX
#define _I64_MAX LLONG_MAX
#else
#define _I64_MAX LONG_LONG_MAX
#endif
#endif
#ifndef _UI64_MAX
#ifdef ULLONG_MAX
#define _UI64_MAX ULLONG_MAX
#else
#define _UI64_MAX ULONG_LONG_MAX
#endif
#endif
#define _lseeki64 lseek64
#else
#include <TCHAR.H>
#include <windows.h>
#include <stddef.h>
#ifndef STRICT
#define STRICT
#endif
typedef BOOL ZBOOL;
#endif // #ifndef _WIN32
#ifndef ASSERT
#include <assert.h>
#define ASSERT(f) assert((f))
#endif
#ifndef VERIFY
#ifdef _DEBUG
#define VERIFY(x) ASSERT((x))
#else
#define VERIFY(x) x
#endif
#endif
#define ZIP_FILE_USIZE ULONGLONG
#define ZIP_FILE_SIZE LONGLONG
#define ZIP_FILE_SIZEMAX _I64_MAX