Added linux makefiles
This commit is contained in:
25
harbour/contrib/hbzlib/ZipString.cpp
Normal file
25
harbour/contrib/hbzlib/ZipString.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipString.cpp $
|
||||
// $Archive: /ZipArchive/ZipString.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "zipstring.h"
|
||||
|
||||
ZIPSTRINGCOMPARE GetCZipStrCompFunc(bool bCaseSensitive, bool bCollate)
|
||||
{
|
||||
if (bCollate)
|
||||
return bCaseSensitive ? & CZipString::Collate : & CZipString::CollateNoCase;
|
||||
else
|
||||
return bCaseSensitive ? & CZipString::Compare : & CZipString::CompareNoCase;
|
||||
}
|
||||
20
harbour/contrib/hbzlib/stdafx.cpp
Normal file
20
harbour/contrib/hbzlib/stdafx.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: stdafx.cpp $
|
||||
// $Archive: /ZipArchive/stdafx.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
3236
harbour/contrib/hbzlib/ziparchive.cpp
Normal file
3236
harbour/contrib/hbzlib/ziparchive.cpp
Normal file
File diff suppressed because it is too large
Load Diff
108
harbour/contrib/hbzlib/zipautobuffer.cpp
Normal file
108
harbour/contrib/hbzlib/zipautobuffer.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipAutoBuffer.cpp $
|
||||
// $Archive: /ZipArchive_STL/ZipAutoBuffer.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "zipautobuffer.h"
|
||||
#include <memory.h>
|
||||
|
||||
// #ifdef _DEBUG
|
||||
// #undef THIS_FILE
|
||||
// static char THIS_FILE[]=__FILE__;
|
||||
// #define new DEBUG_NEW
|
||||
// #endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
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;
|
||||
}
|
||||
852
harbour/contrib/hbzlib/zipcentraldir.cpp
Normal file
852
harbour/contrib/hbzlib/zipcentraldir.cpp
Normal file
@@ -0,0 +1,852 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipCentralDir.cpp $
|
||||
// $Archive: /ZipArchive/ZipCentralDir.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "zipcentraldir.h"
|
||||
#include "ziparchive.h"
|
||||
#include "zipfilemapping.h"
|
||||
#include "zipplatform.h"
|
||||
|
||||
|
||||
#define CENTRALDIRSIZE 22
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
char CZipCentralDir::m_gszSignature[] = {0x50, 0x4b, 0x05, 0x06};
|
||||
CZipCentralDir::CZipCentralDir()
|
||||
{
|
||||
m_bConvertAfterOpen = true;
|
||||
m_bFindFastEnabled = false;
|
||||
m_bCaseSensitive = false;
|
||||
m_pCompare = GetCZipStrCompFunc(ZipPlatform::GetSystemCaseSensitivity());
|
||||
m_pStorage = NULL;
|
||||
m_pOpenedFile = NULL;
|
||||
m_iBufferSize = 32768;
|
||||
|
||||
}
|
||||
|
||||
void CZipCentralDir::Init()
|
||||
{
|
||||
m_info.m_bOnDisk = false;
|
||||
m_info.m_uBytesBeforeZip = m_info.m_uCentrDirPos = 0;
|
||||
m_pOpenedFile = NULL;
|
||||
m_pszComment.Release();
|
||||
|
||||
}
|
||||
|
||||
CZipCentralDir::~CZipCentralDir()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void CZipCentralDir::Read()
|
||||
{
|
||||
ASSERT(m_pStorage);
|
||||
WORD uCommentSize;
|
||||
m_info.m_uCentrDirPos = Locate();
|
||||
m_pStorage->m_pFile->Seek(m_info.m_uCentrDirPos, CZipAbstractFile::begin);
|
||||
CZipAutoBuffer buf(CENTRALDIRSIZE);
|
||||
|
||||
int uRead = m_pStorage->m_pFile->Read(buf, CENTRALDIRSIZE);
|
||||
if (uRead != CENTRALDIRSIZE)
|
||||
ThrowError(CZipException::badZipFile);
|
||||
memcpy(&m_szSignature, buf, 4);
|
||||
memcpy(&m_info.m_uThisDisk, buf + 4, 2);
|
||||
memcpy(&m_info.m_uDiskWithCD, buf + 6, 2);
|
||||
memcpy(&m_info.m_uDiskEntriesNo,buf + 8, 2);
|
||||
memcpy(&m_info.m_uEntriesNumber,buf + 10, 2);
|
||||
memcpy(&m_info.m_uSize, buf + 12, 4);
|
||||
memcpy(&m_info.m_uOffset, buf + 16, 4);
|
||||
memcpy(&uCommentSize, buf + 20, 2);
|
||||
buf.Release();
|
||||
|
||||
|
||||
m_pStorage->UpdateSpanMode(m_info.m_uThisDisk);
|
||||
// if m_uThisDisk is not zero, it is enough to say that it is a multi disk archive
|
||||
ASSERT((!m_info.m_uThisDisk && (m_info.m_uEntriesNumber == m_info.m_uDiskEntriesNo) && !m_info.m_uDiskWithCD) || m_info.m_uThisDisk);
|
||||
|
||||
|
||||
|
||||
if (!m_pStorage->IsSpanMode() && !m_info.CheckIfOK_1())
|
||||
ThrowError(CZipException::badZipFile);
|
||||
|
||||
if (uCommentSize)
|
||||
{
|
||||
m_pszComment.Allocate(uCommentSize);
|
||||
uRead = m_pStorage->m_pFile->Read(m_pszComment, uCommentSize);
|
||||
if (uRead != uCommentSize)
|
||||
ThrowError(CZipException::badZipFile);
|
||||
}
|
||||
|
||||
m_info.SetBytesBeforeZip(m_pStorage->IsSpanMode() != 0);
|
||||
|
||||
if (!m_info.CheckIfOK_2())
|
||||
ThrowError(CZipException::badZipFile);
|
||||
|
||||
m_info.m_bOnDisk = true;
|
||||
m_pStorage->ChangeDisk(m_info.m_uDiskWithCD);
|
||||
|
||||
if (!m_info.m_uSize)
|
||||
return;
|
||||
|
||||
ReadHeaders();
|
||||
}
|
||||
|
||||
DWORD CZipCentralDir::Locate()
|
||||
{
|
||||
|
||||
// maximum size of end of central dir record
|
||||
long uMaxRecordSize = 0xffff + CENTRALDIRSIZE;
|
||||
DWORD uFileSize = m_pStorage->m_pFile->GetLength();
|
||||
|
||||
if ((DWORD)uMaxRecordSize > uFileSize)
|
||||
uMaxRecordSize = uFileSize;
|
||||
|
||||
CZipAutoBuffer buf(m_iBufferSize);
|
||||
|
||||
long uPosInFile = 0;
|
||||
int uRead = 0;
|
||||
// backward reading
|
||||
while (uPosInFile < uMaxRecordSize)
|
||||
{
|
||||
uPosInFile = uRead + m_iBufferSize;
|
||||
if (uPosInFile > uMaxRecordSize)
|
||||
uPosInFile = uMaxRecordSize;
|
||||
|
||||
int iToRead = uPosInFile - uRead;
|
||||
|
||||
m_pStorage->m_pFile->Seek(-uPosInFile, CZipAbstractFile::end);
|
||||
int iActuallyRead = m_pStorage->m_pFile->Read(buf, iToRead);
|
||||
if (iActuallyRead != iToRead)
|
||||
ThrowError(CZipException::badZipFile);
|
||||
// search from the very last bytes to prevent an error if inside archive
|
||||
// there are packed other arhives
|
||||
for (int i = iToRead - 4; i >=0 ; i--)
|
||||
if (!memcmp((char*)buf + i, m_gszSignature, 4))
|
||||
return uFileSize - (uPosInFile - i);
|
||||
|
||||
uRead += iToRead - 3;
|
||||
|
||||
}
|
||||
|
||||
ThrowError(CZipException::cdirNotFound);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CZipCentralDir::ThrowError(int err) const
|
||||
{
|
||||
CZipException::Throw(err, m_pStorage->m_pFile->GetFilePath());
|
||||
}
|
||||
|
||||
|
||||
void CZipCentralDir::ReadHeaders()
|
||||
{
|
||||
m_pStorage->m_pFile->Seek(m_info.m_uOffset + m_info.m_uBytesBeforeZip, CZipAbstractFile::begin);
|
||||
RemoveHeaders(); //just in case
|
||||
for (int i = 0; i < m_info.m_uEntriesNumber; i++)
|
||||
{
|
||||
CZipFileHeader* pHeader = new CZipFileHeader;
|
||||
m_headers.Add(pHeader);
|
||||
|
||||
if (!pHeader->Read(m_pStorage))
|
||||
ThrowError(CZipException::badZipFile);
|
||||
ConvertFileName(true, true, pHeader);
|
||||
}
|
||||
SortHeaders(); // this is necessary when deleting files and removing data descriptors
|
||||
if (m_bFindFastEnabled)
|
||||
BuildFindFastArray(m_bCaseSensitive);
|
||||
}
|
||||
|
||||
void CZipCentralDir::SortHeaders()
|
||||
{
|
||||
// we cannot use the Sort method of the CZipWordArray,
|
||||
// because we store pointers (and we need to store pointers
|
||||
// to make sure that the address of the CZipFileHeader structure
|
||||
// remains the same while working with the library)
|
||||
int iSize = m_headers.GetSize();
|
||||
if (iSize)
|
||||
qsort((void*)&(m_headers[0]),iSize , sizeof(CZipFileHeader*), CompareHeaders);
|
||||
}
|
||||
|
||||
void CZipCentralDir::Clear(bool bEverything)
|
||||
{
|
||||
m_pOpenedFile = NULL;
|
||||
m_pLocalExtraField.Release();
|
||||
if (bEverything)
|
||||
{
|
||||
RemoveHeaders();
|
||||
m_findarray.RemoveAll();
|
||||
m_pszComment.Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CZipCentralDir::IsValidIndex(int uIndex)const
|
||||
{
|
||||
return uIndex < m_headers.GetSize() && uIndex >= 0;
|
||||
}
|
||||
|
||||
|
||||
void CZipCentralDir::OpenFile(WORD uIndex)
|
||||
{
|
||||
WORD uLocalExtraFieldSize;
|
||||
m_pOpenedFile = (*this)[uIndex];
|
||||
m_pStorage->ChangeDisk(m_pOpenedFile->m_uDiskStart);
|
||||
m_pStorage->m_pFile->Seek(m_pOpenedFile->m_uOffset + m_info.m_uBytesBeforeZip, CZipAbstractFile::begin);
|
||||
if (!m_pOpenedFile->ReadLocal(m_pStorage, uLocalExtraFieldSize))
|
||||
ThrowError(CZipException::badZipFile);
|
||||
|
||||
|
||||
m_pLocalExtraField.Release(); // just in case
|
||||
if (uLocalExtraFieldSize)
|
||||
{
|
||||
int iCurrDsk = m_pStorage->GetCurrentDisk();
|
||||
m_pLocalExtraField.Allocate(uLocalExtraFieldSize);
|
||||
m_pStorage->Read(m_pLocalExtraField, uLocalExtraFieldSize, true);
|
||||
if (m_pStorage->GetCurrentDisk() != iCurrDsk)
|
||||
ThrowError(CZipException::badZipFile);
|
||||
}
|
||||
}
|
||||
|
||||
void CZipCentralDir::CloseFile(bool bAfterException)
|
||||
{
|
||||
if (!m_pOpenedFile)
|
||||
return;
|
||||
m_pLocalExtraField.Release();
|
||||
if (!bAfterException && m_pOpenedFile->IsDataDescr())
|
||||
{
|
||||
CZipAutoBuffer buf(12);
|
||||
m_pStorage->Read(buf, 4, false);
|
||||
// in span mode, files that are divided between disks have bit 3 of flag set
|
||||
// which tell about the presence of the data descriptor after the compressed data
|
||||
// This signature may be in the disk spanning archive that is one volume only
|
||||
// (it is detected as a non disk spanning archive)
|
||||
if (memcmp(buf, CZipStorage::m_gszExtHeaderSignat, 4) != 0) // there is no signature
|
||||
m_pStorage->m_pFile->Seek(-4, CZipAbstractFile::current);
|
||||
|
||||
|
||||
m_pStorage->Read(buf, 12, false);
|
||||
if (!m_pOpenedFile->CheckCrcAndSizes(buf))
|
||||
ThrowError(CZipException::badZipFile);
|
||||
}
|
||||
m_pOpenedFile = NULL;
|
||||
}
|
||||
|
||||
// add new header using the argument as a template
|
||||
CZipFileHeader* CZipCentralDir::AddNewFile(const CZipFileHeader & header, int iReplaceIndex)
|
||||
{
|
||||
CZipFileHeader* pHeader = new CZipFileHeader(header);
|
||||
m_pOpenedFile = pHeader;
|
||||
WORD uIndex;
|
||||
DWORD uOffset = 0;
|
||||
bool bReplace = IsValidIndex(iReplaceIndex);
|
||||
if (bReplace)
|
||||
{
|
||||
CZipFileHeader* pfh = m_headers[iReplaceIndex];
|
||||
uOffset = pfh->m_uOffset + m_info.m_uBytesBeforeZip;
|
||||
RemoveFile(pfh, iReplaceIndex, false);
|
||||
m_headers.InsertAt(iReplaceIndex, pHeader);
|
||||
uIndex = (WORD)iReplaceIndex;
|
||||
}
|
||||
else
|
||||
uIndex = m_headers.Add(pHeader);
|
||||
|
||||
if (m_bFindFastEnabled)
|
||||
InsertFindFastElement(pHeader, uIndex); // GetCount > 0, 'cos we've just added a header
|
||||
RemoveFromDisk();
|
||||
if (bReplace)
|
||||
m_pStorage->m_pFile->Seek(uOffset, CZipAbstractFile::begin);
|
||||
else
|
||||
m_pStorage->m_pFile->SeekToEnd();
|
||||
return pHeader;
|
||||
}
|
||||
|
||||
|
||||
void CZipCentralDir::RemoveFromDisk()
|
||||
{
|
||||
if (m_info.m_bOnDisk)
|
||||
{
|
||||
ASSERT(!m_pStorage->IsSpanMode()); // you can't add files to the existing disk span archive or to delete them from it
|
||||
m_pStorage->m_pFile->SetLength(m_info.m_uBytesBeforeZip + m_info.m_uOffset);
|
||||
m_info.m_bOnDisk = false;
|
||||
}
|
||||
else
|
||||
m_pStorage->Flush(); // if remove from disk is requested, then the archive modification will follow, so flush the buffers
|
||||
}
|
||||
|
||||
|
||||
void CZipCentralDir::CloseNewFile()
|
||||
{
|
||||
CZipAutoBuffer buf(ZIPARCHIVE_DATADESCRIPTOR_LEN + 4);
|
||||
short iToWrite = 0;
|
||||
bool bIsSpan = m_pStorage->IsSpanMode() != 0;
|
||||
bool bEncrypted = m_pOpenedFile->IsEncrypted();
|
||||
if (m_pOpenedFile->IsDataDescr())
|
||||
{
|
||||
if (bIsSpan || bEncrypted)
|
||||
{
|
||||
memcpy(buf, m_pStorage->m_gszExtHeaderSignat, 4);
|
||||
iToWrite += 4;
|
||||
}
|
||||
}
|
||||
else /*if (!IsSpan)*/
|
||||
{
|
||||
ASSERT(!bIsSpan && !bEncrypted);
|
||||
m_pStorage->Flush();
|
||||
// the offset contains bytes before zip (set while writting the local header)
|
||||
m_pStorage->m_pFile->Seek(m_pOpenedFile->m_uOffset + 14, CZipAbstractFile::begin);
|
||||
// we don't have to restore the pointer, because before adding a new file,
|
||||
// the pointer is moved to the end
|
||||
}
|
||||
|
||||
m_pOpenedFile->GetCrcAndSizes(buf + iToWrite);
|
||||
iToWrite += ZIPARCHIVE_DATADESCRIPTOR_LEN;
|
||||
|
||||
// offset set during writing the local header
|
||||
m_pOpenedFile->m_uOffset -= m_info.m_uBytesBeforeZip;
|
||||
|
||||
// write the data descriptor and a disk spanning signature at once
|
||||
m_pStorage->Write(buf, iToWrite, true);
|
||||
if (!bIsSpan)
|
||||
{
|
||||
if (bEncrypted)
|
||||
{
|
||||
// write the information to the local header too
|
||||
m_pStorage->Flush();
|
||||
m_pStorage->m_pFile->Seek(m_info.m_uBytesBeforeZip + m_pOpenedFile->m_uOffset + 14, CZipAbstractFile::begin);
|
||||
m_pStorage->Write(buf + 4, ZIPARCHIVE_DATADESCRIPTOR_LEN, true);
|
||||
}
|
||||
m_pStorage->Flush();
|
||||
}
|
||||
|
||||
m_pOpenedFile = NULL;
|
||||
|
||||
}
|
||||
|
||||
void CZipCentralDir::Write(CZipActionCallback* pCallback)
|
||||
{
|
||||
if (m_info.m_bOnDisk)
|
||||
return;
|
||||
if (!m_pStorage->IsSpanMode())
|
||||
{
|
||||
m_pStorage->Flush();
|
||||
m_pStorage->m_pFile->SeekToEnd();
|
||||
}
|
||||
|
||||
// else
|
||||
// // we are at the end already
|
||||
|
||||
m_info.m_uEntriesNumber = (WORD)m_headers.GetSize();
|
||||
m_info.m_uSize = 0;
|
||||
bool bDontAllowDiskChange = false;
|
||||
// if there is a disk spanning archive in creation and it is only one-volume,
|
||||
// (current disk 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 non disk spanning archive
|
||||
if (m_pStorage->IsSpanMode() && m_pStorage->GetCurrentDisk() == 0)
|
||||
{
|
||||
DWORD uVolumeFree = m_pStorage->VolumeLeft();
|
||||
// calculate the size of data descriptors already in the buffer or on the disk
|
||||
// (they will be removed in the non disk spanning archive):
|
||||
// multi span signature at the beginnig (4 bytes) + the size of the data
|
||||
// descr. for each file (multi span signature + 12 bytes data)
|
||||
// the number of bytes to add: central dir size - total to remove;
|
||||
DWORD uToGrow = GetSize(true) - (4 + m_info.m_uEntriesNumber * (4 + 12));
|
||||
if (uVolumeFree >= uToGrow)
|
||||
// lets make sure it will be one-disk archive
|
||||
{
|
||||
// can the operation be done only in the buffer?
|
||||
if (!m_pStorage->m_iBytesWritten && // no bytes on the disk yet
|
||||
(m_pStorage->GetFreeInBuffer() >= uToGrow)) // is the buffer big enough?
|
||||
{
|
||||
RemoveDataDescr(true);
|
||||
bDontAllowDiskChange = true; // if the disk change occurs somehow, we'll throw an error later
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pStorage->Flush();
|
||||
if (RemoveDataDescr(false))
|
||||
bDontAllowDiskChange = true; // if the disk change occurs somehow, we'll throw an error later
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
WriteHeaders(pCallback, bDontAllowDiskChange || !m_pStorage->IsSpanMode());
|
||||
|
||||
m_info.m_uThisDisk = (WORD)m_pStorage->GetCurrentDisk();
|
||||
DWORD uSize = WriteCentralEnd();
|
||||
if (bDontAllowDiskChange)
|
||||
{
|
||||
if (m_pStorage->GetCurrentDisk() != 0)
|
||||
ThrowError(CZipException::badZipFile);
|
||||
}
|
||||
// if after adding a central directory there is a disk change,
|
||||
// update the information and write it again
|
||||
if (m_info.m_uThisDisk != m_pStorage->GetCurrentDisk())
|
||||
{
|
||||
m_info.DiskChange(m_pStorage->GetCurrentDisk());
|
||||
|
||||
if (m_pStorage->m_uBytesInWriteBuffer >= uSize)
|
||||
// if the data is still in the buffer, simply remove it
|
||||
m_pStorage->m_uBytesInWriteBuffer -= uSize;
|
||||
else
|
||||
{
|
||||
m_pStorage->Flush();
|
||||
m_pStorage->m_iBytesWritten -= uSize;
|
||||
m_pStorage->m_pFile->SeekToBegin();
|
||||
}
|
||||
|
||||
WriteCentralEnd();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (bDontAllowDiskChange)
|
||||
{
|
||||
m_pStorage->FinalizeSpan();
|
||||
m_info.m_uThisDisk = 0;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
m_info.m_bOnDisk = true;
|
||||
}
|
||||
|
||||
void CZipCentralDir::WriteHeaders(CZipActionCallback* pCallback, bool bOneDisk)
|
||||
{
|
||||
m_info.m_uDiskEntriesNo = 0;
|
||||
m_info.m_uDiskWithCD = (WORD)m_pStorage->GetCurrentDisk();
|
||||
m_info.m_uOffset = m_pStorage->GetPosition() - m_info.m_uBytesBeforeZip;
|
||||
if (!m_info.m_uEntriesNumber)
|
||||
return;
|
||||
|
||||
WORD iDisk = m_info.m_uDiskWithCD;
|
||||
int iStep = 0; // for the compiler
|
||||
|
||||
if (pCallback)
|
||||
{
|
||||
pCallback->Init();
|
||||
pCallback->SetTotal(m_info.m_uEntriesNumber);
|
||||
iStep = CZipActionCallback::m_iStep;// we don't want to wait forever
|
||||
}
|
||||
|
||||
int iAborted = 0;
|
||||
for (int i = 0; i < m_info.m_uEntriesNumber; i++)
|
||||
{
|
||||
CZipFileHeader* pHeader = (*this)[i];
|
||||
|
||||
|
||||
CZipString szRemember;
|
||||
if (m_bConvertAfterOpen)
|
||||
// if CZipArchive::Flush is called we will be still using the archive, so restore changed name
|
||||
szRemember = pHeader->GetFileName();
|
||||
|
||||
ConvertFileName(false, true, pHeader);
|
||||
m_info.m_uSize += pHeader->Write(m_pStorage);
|
||||
|
||||
if (m_bConvertAfterOpen)
|
||||
pHeader->SetFileName(szRemember);
|
||||
|
||||
if (m_pStorage->GetCurrentDisk() != iDisk)
|
||||
{
|
||||
m_info.m_uDiskEntriesNo = 1;
|
||||
iDisk = (WORD)m_pStorage->GetCurrentDisk();
|
||||
// update the information about the offset and starting disk if the
|
||||
// first header was written on the new disk
|
||||
if (i == 0)
|
||||
{
|
||||
m_info.m_uOffset = 0;
|
||||
m_info.m_uDiskWithCD = iDisk;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_info.m_uDiskEntriesNo++;
|
||||
if (pCallback && !(i%iStep))
|
||||
if (!pCallback->Callback(iStep))
|
||||
{
|
||||
|
||||
if (bOneDisk)
|
||||
{
|
||||
if (!m_pStorage->IsSpanMode())
|
||||
m_pStorage->EmptyWriteBuffer();
|
||||
else
|
||||
m_pStorage->Flush(); // must be flush before - flush was not called in span mode
|
||||
|
||||
// remove saved part from the disk
|
||||
m_pStorage->m_pFile->SetLength(m_info.m_uBytesBeforeZip + m_info.m_uOffset);
|
||||
// We can now abort safely
|
||||
iAborted = CZipException::abortedSafely;
|
||||
}
|
||||
else
|
||||
iAborted = CZipException::abortedAction;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pCallback)
|
||||
pCallback->CallbackEnd();
|
||||
|
||||
if (iAborted)
|
||||
ThrowError(iAborted);
|
||||
}
|
||||
|
||||
DWORD CZipCentralDir::WriteCentralEnd()
|
||||
{
|
||||
DWORD uSize = GetSize();
|
||||
CZipAutoBuffer buf(uSize);
|
||||
WORD uCommentSize = (WORD)m_pszComment.GetSize();
|
||||
memcpy(buf, m_gszSignature, 4);
|
||||
memcpy(buf + 4, &m_info.m_uThisDisk, 2);
|
||||
memcpy(buf + 6, &m_info.m_uDiskWithCD, 2);
|
||||
memcpy(buf + 8, &m_info.m_uDiskEntriesNo, 2);
|
||||
memcpy(buf + 10, &m_info.m_uEntriesNumber, 2);
|
||||
memcpy(buf + 12, &m_info.m_uSize, 4);
|
||||
memcpy(buf + 16, &m_info.m_uOffset, 4);
|
||||
memcpy(buf + 20, &uCommentSize, 2);
|
||||
memcpy(buf + 22, m_pszComment, uCommentSize);
|
||||
m_pStorage->Write(buf, uSize, true);
|
||||
return uSize;
|
||||
}
|
||||
|
||||
void CZipCentralDir::RemoveAll()
|
||||
{
|
||||
m_findarray.RemoveAll();
|
||||
RemoveHeaders();
|
||||
}
|
||||
|
||||
void CZipCentralDir::RemoveFile(CZipFileHeader* pHeader, int iIndex, bool bShift)
|
||||
{
|
||||
|
||||
if (iIndex == -1)
|
||||
{
|
||||
int iCount = m_headers.GetSize();
|
||||
for (int i = 0; i < iCount; i++)
|
||||
if (pHeader == m_headers[i])
|
||||
{
|
||||
iIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(iIndex != -1 || pHeader);
|
||||
if (!pHeader)
|
||||
pHeader = m_headers[iIndex];
|
||||
|
||||
if (m_bFindFastEnabled)
|
||||
{
|
||||
int i = FindFileNameIndex(pHeader->GetFileName());
|
||||
ASSERT(i != -1);
|
||||
int uIndex = m_findarray[i].m_uIndex;
|
||||
m_findarray.RemoveAt(i);
|
||||
// shift down the indexes
|
||||
|
||||
if (bShift)
|
||||
{
|
||||
int iSize = m_findarray.GetSize();
|
||||
for (int j = 0; j < iSize; j++)
|
||||
{
|
||||
if (m_findarray[j].m_uIndex > uIndex)
|
||||
m_findarray[j].m_uIndex--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (iIndex != -1)
|
||||
{
|
||||
delete pHeader;
|
||||
m_headers.RemoveAt(iIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
DWORD CZipCentralDir::GetSize(bool bWhole) const
|
||||
{
|
||||
DWORD uHeaders = 0;
|
||||
int iCount = m_headers.GetSize();
|
||||
if (bWhole)
|
||||
{
|
||||
for (int i = 0; i < iCount; i++)
|
||||
{
|
||||
const CZipFileHeader* pHeader = m_headers[i];
|
||||
uHeaders += pHeader->GetSize();
|
||||
}
|
||||
}
|
||||
return CENTRALDIRSIZE + m_pszComment.GetSize() + uHeaders;
|
||||
}
|
||||
|
||||
bool CZipCentralDir::RemoveDataDescr(bool bFromBuffer)
|
||||
{
|
||||
ziparchv::CZipFileMapping fm;
|
||||
char* pFile;
|
||||
DWORD uSize;
|
||||
if (bFromBuffer)
|
||||
{
|
||||
uSize = m_pStorage->m_uBytesInWriteBuffer;
|
||||
pFile = m_pStorage->m_pWriteBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
uSize = m_pStorage->m_pFile->GetLength();
|
||||
// we cannot use CZipMemFile in multidisk archive
|
||||
// so it MUST be CZipFile
|
||||
if (!fm.CreateMapping(static_cast<CZipFile*>(m_pStorage->m_pFile)))
|
||||
return false;
|
||||
pFile = fm.GetMappedMemory();
|
||||
}
|
||||
|
||||
DWORD uOffsetToChange = 4;
|
||||
DWORD uPosInBuffer = 0;
|
||||
DWORD uExtraHeaderLen;
|
||||
int iCount = m_headers.GetSize();
|
||||
for (int i = 0; i < iCount; i++)
|
||||
{
|
||||
// update the flag value in the local and central header
|
||||
// int uDataDescr = (m_headers[i]->m_uFlag & 8) ? (4 + 12) : 0;
|
||||
|
||||
CZipFileHeader* pHeader = m_headers[i];
|
||||
|
||||
|
||||
char* pSour = pFile + pHeader->m_uOffset;
|
||||
|
||||
if (!pHeader->IsEncrypted())
|
||||
{
|
||||
// removing data descriptor
|
||||
pHeader->m_uFlag &= ~8;
|
||||
// update local header:
|
||||
// write modified flag in the local header
|
||||
memcpy(pSour + 6, &pHeader->m_uFlag, 2);
|
||||
uExtraHeaderLen = 4/*ext. header signature*/ + 12/*data descriptor*/;
|
||||
}
|
||||
else
|
||||
// do not remove data descriptors from encrypted files
|
||||
uExtraHeaderLen = 0;
|
||||
|
||||
// update crc32 and sizes' values
|
||||
pHeader->GetCrcAndSizes(pSour+ 14);
|
||||
|
||||
DWORD uToCopy = (i == (iCount - 1) ? uSize : m_headers[i + 1]->m_uOffset)
|
||||
- pHeader->m_uOffset - uExtraHeaderLen;
|
||||
|
||||
memmove(pFile + uPosInBuffer, pSour, uToCopy);
|
||||
|
||||
uPosInBuffer += uToCopy;
|
||||
pHeader->m_uOffset -= uOffsetToChange;
|
||||
uOffsetToChange += uExtraHeaderLen;
|
||||
}
|
||||
|
||||
if (bFromBuffer)
|
||||
m_pStorage->m_uBytesInWriteBuffer = uPosInBuffer;
|
||||
else
|
||||
{
|
||||
m_pStorage->m_iBytesWritten = uPosInBuffer;
|
||||
fm.RemoveMapping();
|
||||
m_pStorage->m_pFile->SetLength(uPosInBuffer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CZipCentralDir::RemoveHeaders()
|
||||
{
|
||||
int iCount = m_headers.GetSize();
|
||||
for (int i = 0; i < iCount; i++)
|
||||
delete m_headers[i];
|
||||
m_headers.RemoveAll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CZipCentralDir::ConvertAll()
|
||||
{
|
||||
ASSERT(!m_bConvertAfterOpen);
|
||||
int iCount = m_headers.GetSize();
|
||||
for (int i = 0; i < iCount; i++)
|
||||
ConvertFileName(true, false, m_headers[i]);
|
||||
m_bConvertAfterOpen = true;
|
||||
}
|
||||
|
||||
void CZipCentralDir::BuildFindFastArray( bool bCaseSensitive )
|
||||
{
|
||||
m_findarray.RemoveAll();
|
||||
m_bCaseSensitive = bCaseSensitive;
|
||||
m_pCompare = GetCZipStrCompFunc(bCaseSensitive);
|
||||
int iCount = m_headers.GetSize();
|
||||
if (!m_bConvertAfterOpen)
|
||||
{
|
||||
for (int i = 0; i < iCount; i++)
|
||||
{
|
||||
CZipFileHeader fh = *m_headers[i];
|
||||
ConvertFileName(true, false, &fh);
|
||||
InsertFindFastElement(&fh, i); // this method requires the name to be already converted
|
||||
}
|
||||
}
|
||||
else
|
||||
for (int i = 0; i < iCount; i++)
|
||||
InsertFindFastElement(m_headers[i], i);
|
||||
}
|
||||
|
||||
void CZipCentralDir::EnableFindFast(bool bEnable, bool bCaseSensitive)
|
||||
{
|
||||
if (m_bFindFastEnabled == bEnable)
|
||||
return;
|
||||
m_bFindFastEnabled = bEnable;
|
||||
if (bEnable)
|
||||
BuildFindFastArray(bCaseSensitive);
|
||||
else
|
||||
m_findarray.RemoveAll();
|
||||
}
|
||||
|
||||
int CZipCentralDir::FindFile(LPCTSTR lpszFileName, bool bCaseSensitive, bool bSporadically, bool bFileNameOnly)
|
||||
{
|
||||
// this is required for fast finding and is done only once
|
||||
if (!m_bConvertAfterOpen)
|
||||
{
|
||||
TRACE(_T("%s(%i) : Converting all the filenames.\n"),__FILE__,__LINE__);
|
||||
ConvertAll();
|
||||
}
|
||||
if (!m_bFindFastEnabled)
|
||||
EnableFindFast(true, bSporadically ? !bCaseSensitive : bCaseSensitive);
|
||||
int iResult = -1;
|
||||
if (bFileNameOnly)
|
||||
{
|
||||
// a non-effective search (treat an array as unsorted)
|
||||
int iSize = m_findarray.GetSize();
|
||||
for (int i = 0; i < iSize; i++)
|
||||
{
|
||||
CZipString sz = GetProperHeaderFileName(m_findarray[i].m_pHeader);
|
||||
CZipPathComponent::RemoveSeparators(sz); // to find a dir
|
||||
CZipPathComponent zpc(sz);
|
||||
sz = zpc.GetFileName();
|
||||
if ((sz.*m_pCompare)(lpszFileName) == 0)
|
||||
{
|
||||
iResult = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bCaseSensitive == m_bCaseSensitive)
|
||||
iResult = FindFileNameIndex(lpszFileName);
|
||||
else
|
||||
{
|
||||
if (bSporadically)
|
||||
{
|
||||
// a non-effective search (treat an array as unsorted)
|
||||
int iSize = m_findarray.GetSize();
|
||||
for (int i = 0; i < iSize; i++)
|
||||
if (CompareElement(lpszFileName, (WORD)i) == 0)
|
||||
{
|
||||
iResult = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildFindFastArray(bCaseSensitive);
|
||||
iResult = FindFileNameIndex(lpszFileName);
|
||||
}
|
||||
}
|
||||
return iResult == -1 ? -1 : m_findarray[iResult].m_uIndex;
|
||||
}
|
||||
|
||||
void CZipCentralDir::InsertFindFastElement(CZipFileHeader* pHeader, WORD uIndex)
|
||||
{
|
||||
CZipString fileName = pHeader->GetFileName();
|
||||
int iSize = m_findarray.GetSize();
|
||||
|
||||
// Our initial binary search range encompasses the entire array of filenames:
|
||||
int start = 0;
|
||||
int end = iSize;
|
||||
|
||||
// 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:
|
||||
int midpoint = ( start + end ) / 2;
|
||||
|
||||
// Compare the filename with the filename at the midpoint of the current search range:
|
||||
int result = CompareElement(fileName, (WORD)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_findarray.InsertAt(start, CZipFindFast(pHeader, WORD(uIndex == WORD(-1) ? iSize : uIndex /* just in case */)));
|
||||
}
|
||||
|
||||
int CZipCentralDir::FindFileNameIndex(LPCTSTR lpszFileName) const
|
||||
{
|
||||
int start = 0;
|
||||
int end = m_findarray.GetUpperBound();
|
||||
|
||||
// Keep halving our search range until we find the given element:
|
||||
while ( start <= end )
|
||||
{
|
||||
// Find the midpoint of the search range:
|
||||
int midpoint = ( start + end ) / 2;
|
||||
|
||||
// Compare the given filename with the filename at the midpoint of the search range:
|
||||
int result = CompareElement(lpszFileName, (WORD)midpoint);
|
||||
|
||||
// If our filename is smaller, it must fall in the first half of the search range:
|
||||
if ( result > 0 )
|
||||
{
|
||||
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 midpoint;
|
||||
}
|
||||
}
|
||||
|
||||
// Signal failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CZipCentralDir::RenameFile(WORD uIndex, LPCTSTR lpszNewName)
|
||||
{
|
||||
CZipFileHeader* pHeader = m_headers[uIndex];
|
||||
pHeader->SetFileName(lpszNewName);
|
||||
if (!m_bConvertAfterOpen)
|
||||
ZipCompatibility::FileNameUpdate(*pHeader, false);
|
||||
if (m_bFindFastEnabled)
|
||||
BuildFindFastArray(m_bCaseSensitive);
|
||||
}
|
||||
214
harbour/contrib/hbzlib/zipcompatibility.cpp
Normal file
214
harbour/contrib/hbzlib/zipcompatibility.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipCompatibility.cpp $
|
||||
// $Archive: /ZipArchive/ZipCompatibility.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#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 0x01C00000
|
||||
#define EXTRACT_USER_PERMISSIONS(x) ((x & USER_PERMISSIONS_MASK) >> 22)
|
||||
#define CREATE_USER_PERMISSIONS(x) ((x & 0x0007) << 22)
|
||||
|
||||
#define GROUP_PERMISSIONS_MASK 0x00380000
|
||||
#define EXTRACT_GROUP_PERMISSIONS ((x & GROUP_PERMISSIONS_MASK) >> 19)
|
||||
#define CREATE_GROUP_PERMISSIONS(x) ((x & 0x0007) << 19)
|
||||
|
||||
#define OTHER_PERMISSIONS_MASK 0x00070000
|
||||
#define EXTRACT_OTHER_PERMISSIONS ((x & OTHER_PERMISSIONS_MASK) >> 16)
|
||||
#define CREATE_OTHER_PERMISSIONS(x) ((x & 0x0007) << 16)
|
||||
|
||||
#define UNIX_DIRECTORY_ATTRIBUTE 0x40000000
|
||||
#define UNIX_FILE_ATTRIBUTE 0x80000000
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
using namespace ZipCompatibility;
|
||||
|
||||
typedef DWORD(*conv_func)(DWORD , bool );
|
||||
|
||||
DWORD AttrDos(DWORD , bool );
|
||||
DWORD AttrUnix(DWORD, bool);
|
||||
DWORD AttrMac(DWORD , bool );
|
||||
|
||||
// more to come...
|
||||
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)
|
||||
{
|
||||
if (uAttr & UNIX_DIRECTORY_ATTRIBUTE)
|
||||
uNewAttr = attDir;
|
||||
|
||||
uAttr = EXTRACT_USER_PERMISSIONS (uAttr);
|
||||
|
||||
// we may set archive attribute if the file hasn't the execute permissions
|
||||
//
|
||||
if (!(uAttr & 1))
|
||||
uNewAttr |= attArch ;
|
||||
|
||||
if (!(uAttr & 2))
|
||||
uNewAttr |= attROnly;
|
||||
|
||||
if (!(uAttr & 4))
|
||||
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 (4) |
|
||||
CREATE_GROUP_PERMISSIONS (4))
|
||||
| CREATE_USER_PERMISSIONS (4);
|
||||
|
||||
if (!(uAttr & attROnly))
|
||||
uNewAttr |= (CREATE_GROUP_PERMISSIONS (2) |
|
||||
CREATE_USER_PERMISSIONS (2));
|
||||
if (uAttr & attDir)
|
||||
uNewAttr |= UNIX_DIRECTORY_ATTRIBUTE | attDir;
|
||||
else
|
||||
uNewAttr |= UNIX_FILE_ATTRIBUTE;
|
||||
|
||||
}
|
||||
|
||||
return uNewAttr;
|
||||
}
|
||||
|
||||
DWORD AttrMac(DWORD uAttr, bool )
|
||||
{
|
||||
DWORD uNewAttr = uAttr & (attDir | attROnly);
|
||||
// if (bFrom)
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
//
|
||||
// }
|
||||
return uNewAttr;
|
||||
}
|
||||
|
||||
// ************************************************************************
|
||||
ZIPINLINE bool ZipCompatibility::IsPlatformSupported(int iCode)
|
||||
{
|
||||
return iCode == zcDosFat || iCode == zcUnix || iCode == zcMacintosh
|
||||
|| iCode == zcNtfs || iCode == zcOs2Hpfs;
|
||||
}
|
||||
|
||||
|
||||
void ZipCompatibility::FileNameUpdate(CZipFileHeader& header, bool bFromZip)
|
||||
{
|
||||
int iSysHeader = header.GetSystemCompatibility();
|
||||
int iCurSystem = ZipPlatform::GetSystemID();
|
||||
if (bFromZip)
|
||||
{
|
||||
if (iCurSystem == zcDosFat)
|
||||
SlashBackslashChg(header.m_pszFileName, true);
|
||||
if (iSysHeader == zcDosFat)
|
||||
ZipPlatform::AnsiOem(header.m_pszFileName, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iSysHeader == zcDosFat)
|
||||
{
|
||||
ZipPlatform::AnsiOem(header.m_pszFileName, true);
|
||||
|
||||
|
||||
}
|
||||
SlashBackslashChg(header.m_pszFileName, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ZipCompatibility::SlashBackslashChg(CZipAutoBuffer& buffer, bool bReplaceSlash)
|
||||
{
|
||||
char t1 = '\\' /*backslash*/, t2 = '/', c1, c2;
|
||||
if (bReplaceSlash)
|
||||
{
|
||||
c1 = t1;
|
||||
c2 = t2;
|
||||
}
|
||||
else
|
||||
{
|
||||
c1 = t2;
|
||||
c2 = t1;
|
||||
}
|
||||
for (DWORD i = 0; i < buffer.GetSize(); i++)
|
||||
{
|
||||
if (buffer[i] == c2)
|
||||
buffer[i] = c1;
|
||||
}
|
||||
|
||||
}
|
||||
280
harbour/contrib/hbzlib/zipexception.cpp
Normal file
280
harbour/contrib/hbzlib/zipexception.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipException.cpp $
|
||||
// $Archive: /ZipArchive/ZipException.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "zipexception.h"
|
||||
#include <errno.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MFC_VER
|
||||
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()
|
||||
#if __GNUC__ >=3
|
||||
CZipException::~CZipException() throw()
|
||||
#else
|
||||
CZipException::~CZipException()
|
||||
#endif
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// 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
|
||||
// }
|
||||
|
||||
int CZipException::ZlibErrToZip(int iZlibError)
|
||||
{
|
||||
switch (iZlibError)
|
||||
{
|
||||
case 2://Z_NEED_DICT:
|
||||
return CZipException::needDict;
|
||||
case 1://Z_STREAM_END:
|
||||
return CZipException::streamEnd;
|
||||
case -1://Z_ERRNO:
|
||||
return CZipException::errNo;
|
||||
case -2://Z_STREAM_ERROR:
|
||||
return CZipException::streamError;
|
||||
case -3://Z_DATA_ERROR:
|
||||
return CZipException::dataError;
|
||||
case -4://Z_MEM_ERROR:
|
||||
return CZipException::memError;
|
||||
case -5://Z_BUF_ERROR:
|
||||
return CZipException::bufError;
|
||||
case -6://Z_VERSION_ERROR:
|
||||
return CZipException::versionError;
|
||||
default:
|
||||
return CZipException::generic;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef ZIP_ENABLE_ERROR_DESCRIPTION
|
||||
|
||||
BOOL 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);
|
||||
#ifdef _UNICODE
|
||||
wcsncpy(lpszError, lpsz, iLen);
|
||||
#else
|
||||
strncpy(lpszError, lpsz, iLen);
|
||||
#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 ? generic : 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 mismatched");
|
||||
break;
|
||||
case noCallback:
|
||||
sz = _T("No disk-spanning callback functor set");
|
||||
break;
|
||||
case aborted:
|
||||
sz = _T("Disk change aborted");
|
||||
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 disk spanning archive is non removable");
|
||||
break;
|
||||
case tooManyVolumes:
|
||||
sz = _T("Limit of the maximum volumes reached (999)");
|
||||
break;
|
||||
case tooLongFileName:
|
||||
sz = _T("The filename of the file being added to the archive is too long");
|
||||
break;
|
||||
case badPassword:
|
||||
sz = _T("Incorrect password set for the file being decrypted");
|
||||
break;
|
||||
case dirWithSize:
|
||||
sz = _T("During testing found the directory with the size greater than 0");
|
||||
break;
|
||||
case internal:
|
||||
sz = _T("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 the 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 disk of a multi-disk archive)");
|
||||
break;
|
||||
case streamEnd:
|
||||
sz = _T("Zlib Library error (end of stream)");
|
||||
break;
|
||||
case errNo:
|
||||
sz = GetInternalErrorDescription(errno != errNo ? errno : generic);
|
||||
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
|
||||
114
harbour/contrib/hbzlib/zipfile.cpp
Normal file
114
harbour/contrib/hbzlib/zipfile.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipFile.cpp $
|
||||
// $Archive: /ZipArchive_STL/ZipFile.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "zipfile.h"
|
||||
#include "zipexception.h"
|
||||
#include "zipplatform.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CZipFile::CZipFile()
|
||||
{
|
||||
m_hFile = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void CZipFile::ThrowError() const
|
||||
{
|
||||
CZipException::Throw(errno, m_szFileName);
|
||||
}
|
||||
|
||||
|
||||
ZIP_ULONGLONG CZipFile::GetLength() const
|
||||
{
|
||||
// cannot use Seek here, Seek is not const
|
||||
long lLen, lCur;
|
||||
lCur = lseek(m_hFile, 0, current);
|
||||
if (lCur == -1)
|
||||
ThrowError();
|
||||
lLen = lseek(m_hFile, 0, end);
|
||||
// first get back
|
||||
lseek(m_hFile, lCur, begin);
|
||||
if (lLen == -1)
|
||||
ThrowError();
|
||||
return lLen;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool CZipFile::Open(LPCTSTR lpszFileName, UINT openFlags, bool bThrow)
|
||||
{
|
||||
if (!IsClosed())
|
||||
Close();
|
||||
#ifndef __GNUC__
|
||||
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)
|
||||
ThrowError();
|
||||
else
|
||||
return false;
|
||||
m_szFileName = lpszFileName;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CZipFile::SetLength(ZIP_ULONGLONG nNewLen)
|
||||
{
|
||||
ZipPlatform::TruncateFile(m_hFile, (DWORD)nNewLen);
|
||||
}
|
||||
|
||||
|
||||
void CZipFile::Flush()
|
||||
{
|
||||
if (!ZipPlatform::FlushFile(m_hFile))
|
||||
ThrowError();
|
||||
}
|
||||
|
||||
CZipFile::operator HANDLE()
|
||||
{
|
||||
int fh = ZipPlatform::GetFileSystemHandle(m_hFile);
|
||||
if (fh == -1)
|
||||
ThrowError();
|
||||
return (HANDLE)fh;
|
||||
}
|
||||
340
harbour/contrib/hbzlib/zipfileheader.cpp
Normal file
340
harbour/contrib/hbzlib/zipfileheader.cpp
Normal file
@@ -0,0 +1,340 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipFileHeader.cpp $
|
||||
// $Archive: /ZipArchive_STL/ZipFileHeader.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "zipfileheader.h"
|
||||
#include "zipautobuffer.h"
|
||||
#include "ziparchive.h"
|
||||
#include "zipplatform.h"
|
||||
#include "zipcompatibility.h"
|
||||
#include <time.h>
|
||||
|
||||
#define FILEHEADERSIZE 46
|
||||
#define LOCALFILEHEADERSIZE 30
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
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 = Z_DEFLATED;
|
||||
// SetSystemCompatibility(ZipPlatform::m_sSystemID);
|
||||
}
|
||||
|
||||
CZipFileHeader::~CZipFileHeader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// read the header from the central dir
|
||||
bool CZipFileHeader::Read(CZipStorage *pStorage)
|
||||
{
|
||||
// // just in case
|
||||
// m_pszComment.Release();
|
||||
// m_pszFileName.Release();
|
||||
WORD uFileNameSize, uCommentSize, uExtraFieldSize;
|
||||
CZipAutoBuffer buf(FILEHEADERSIZE);
|
||||
pStorage->Read(buf, FILEHEADERSIZE, true);
|
||||
memcpy(&m_szSignature, buf, 4);
|
||||
memcpy(&m_uVersionMadeBy, buf + 4, 2);
|
||||
memcpy(&m_uVersionNeeded, buf + 6, 2);
|
||||
memcpy(&m_uFlag, buf + 8, 2);
|
||||
memcpy(&m_uMethod, buf + 10, 2);
|
||||
memcpy(&m_uModTime, buf + 12, 2);
|
||||
memcpy(&m_uModDate, buf + 14, 2);
|
||||
memcpy(&m_uCrc32, buf + 16, 4);
|
||||
memcpy(&m_uComprSize, buf + 20, 4);
|
||||
memcpy(&m_uUncomprSize, buf + 24, 4);
|
||||
memcpy(&uFileNameSize, buf + 28, 2);
|
||||
memcpy(&uExtraFieldSize, buf + 30, 2);
|
||||
memcpy(&uCommentSize, buf + 32, 2);
|
||||
memcpy(&m_uDiskStart, buf + 34, 2);
|
||||
memcpy(&m_uInternalAttr, buf + 36, 2);
|
||||
memcpy(&m_uExternalAttr, buf + 38, 4);
|
||||
memcpy(&m_uOffset, buf + 42, 4);
|
||||
buf.Release();
|
||||
|
||||
if (memcmp(m_szSignature, m_gszSignature, 4) != 0)
|
||||
return false;
|
||||
|
||||
int iCurDsk = pStorage->GetCurrentDisk();
|
||||
m_pszFileName.Allocate(uFileNameSize); // don't add NULL at the end
|
||||
pStorage->Read(m_pszFileName, uFileNameSize, true);
|
||||
if (uExtraFieldSize)
|
||||
{
|
||||
ASSERT(!m_pExtraField.IsAllocated());
|
||||
m_pExtraField.Allocate(uExtraFieldSize);
|
||||
pStorage->Read(m_pExtraField, uExtraFieldSize, true);
|
||||
}
|
||||
if (uCommentSize)
|
||||
{
|
||||
m_pszComment.Allocate(uCommentSize);
|
||||
pStorage->Read(m_pszComment, uCommentSize, true);
|
||||
}
|
||||
|
||||
return pStorage->GetCurrentDisk() == iCurDsk; // check that the whole header is on the one disk
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
WORD uFileNameSize = GetFileNameSize(), uCommentSize = GetCommentSize(),
|
||||
uExtraFieldSize = GetExtraFieldSize();
|
||||
DWORD iSize = FILEHEADERSIZE + uFileNameSize + uCommentSize + uExtraFieldSize;
|
||||
CZipAutoBuffer buf(iSize);
|
||||
memcpy(buf, &m_szSignature, 4);
|
||||
memcpy(buf + 4, &m_uVersionMadeBy, 2);
|
||||
memcpy(buf + 6, &m_uVersionNeeded, 2);
|
||||
memcpy(buf + 8, &m_uFlag, 2);
|
||||
memcpy(buf + 10, &m_uMethod, 2);
|
||||
memcpy(buf + 12, &m_uModTime, 2);
|
||||
memcpy(buf + 14, &m_uModDate, 2);
|
||||
memcpy(buf + 16, &m_uCrc32, 4);
|
||||
memcpy(buf + 20, &m_uComprSize, 4);
|
||||
memcpy(buf + 24, &m_uUncomprSize, 4);
|
||||
memcpy(buf + 28, &uFileNameSize, 2);
|
||||
memcpy(buf + 30, &uExtraFieldSize, 2);
|
||||
memcpy(buf + 32, &uCommentSize, 2);
|
||||
memcpy(buf + 34, &m_uDiskStart, 2);
|
||||
memcpy(buf + 36, &m_uInternalAttr, 2);
|
||||
memcpy(buf + 38, &m_uExternalAttr, 4);
|
||||
memcpy(buf + 42, &m_uOffset, 4);
|
||||
|
||||
memcpy(buf + 46, m_pszFileName, uFileNameSize);
|
||||
|
||||
if (uExtraFieldSize)
|
||||
memcpy(buf + 46 + uFileNameSize, m_pExtraField, uExtraFieldSize);
|
||||
|
||||
if (uCommentSize)
|
||||
memcpy(buf + 46 + uFileNameSize + uExtraFieldSize, m_pszComment, uCommentSize);
|
||||
|
||||
pStorage->Write(buf, iSize, true);
|
||||
return iSize;
|
||||
}
|
||||
|
||||
bool CZipFileHeader::ReadLocal(CZipStorage *pStorage, WORD& iLocExtrFieldSize)
|
||||
{
|
||||
char buf[LOCALFILEHEADERSIZE];
|
||||
pStorage->Read(buf, LOCALFILEHEADERSIZE, true);
|
||||
if (memcmp(buf, m_gszLocalSignature, 4) != 0)
|
||||
return false;
|
||||
|
||||
bool bIsDataDescr = (((WORD)*(buf + 6)) & 8) != 0;
|
||||
|
||||
WORD uFileNameSize = GetFileNameSize();
|
||||
WORD uTemp;
|
||||
memcpy(&uTemp, buf+6, 2); // give the priority to the local flag
|
||||
if ((uTemp & 0xf) != (m_uFlag & 0xf))
|
||||
m_uFlag = uTemp;
|
||||
if ((memcmp(buf + 8, &m_uMethod, 2) != 0)
|
||||
|| (m_uMethod && (m_uMethod != Z_DEFLATED))
|
||||
|| (memcmp(buf + 26, &uFileNameSize, 2) != 0))
|
||||
return false;
|
||||
|
||||
// jeszcze mo¿naby porównaæ nazwy plików
|
||||
|
||||
if (!bIsDataDescr/* || !pStorage->IsSpanMode()*/)
|
||||
if (!CheckCrcAndSizes(buf + 14))
|
||||
return false;
|
||||
|
||||
memcpy(&iLocExtrFieldSize, buf + 28, 2);
|
||||
pStorage->m_pFile->Seek(uFileNameSize, CZipAbstractFile::current);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CZipFileHeader::SetTime(const time_t & ttime)
|
||||
{
|
||||
tm* gt = localtime(&ttime);
|
||||
WORD year = (WORD)(gt->tm_year + 1900);
|
||||
if (year <= 1980)
|
||||
year = 0;
|
||||
else
|
||||
year -= 1980;
|
||||
m_uModDate = (WORD) (gt->tm_mday + ((gt->tm_mon + 1)<< 5) + (year << 9));
|
||||
m_uModTime = (WORD) ((gt->tm_sec >> 1) + (gt->tm_min << 5) +
|
||||
(gt->tm_hour << 11));
|
||||
}
|
||||
// the buffer contains crc32, compressed and uncompressed sizes to be compared
|
||||
// with the actual values
|
||||
bool CZipFileHeader::CheckCrcAndSizes(char *pBuf) const
|
||||
{
|
||||
return (memcmp(pBuf, &m_uCrc32, 4) == 0) && (memcmp(pBuf + 4, &m_uComprSize, 4) == 0)
|
||||
&& (memcmp(pBuf + 8, &m_uUncomprSize, 4) == 0);
|
||||
}
|
||||
|
||||
// write the local header
|
||||
void CZipFileHeader::WriteLocal(CZipStorage& storage)
|
||||
{
|
||||
// extra field is local by now
|
||||
WORD uFileNameSize = GetFileNameSize(), uExtraFieldSize = GetExtraFieldSize();
|
||||
DWORD iLocalSize = LOCALFILEHEADERSIZE + uExtraFieldSize + uFileNameSize;
|
||||
CZipAutoBuffer buf(iLocalSize);
|
||||
memcpy(buf, m_gszLocalSignature, 4);
|
||||
memcpy(buf + 4, &m_uVersionNeeded, 2);
|
||||
memcpy(buf + 6, &m_uFlag, 2);
|
||||
memcpy(buf + 8, &m_uMethod, 2);
|
||||
memcpy(buf + 10, &m_uModTime, 2);
|
||||
memcpy(buf + 12, &m_uModDate, 2);
|
||||
memcpy(buf + 14, &m_uCrc32, 4);
|
||||
memcpy(buf + 18, &m_uComprSize, 4);
|
||||
memcpy(buf + 22, &m_uUncomprSize, 4);
|
||||
memcpy(buf + 26, &uFileNameSize, 2);
|
||||
memcpy(buf + 28, &uExtraFieldSize, 2);
|
||||
memcpy(buf + 30, m_pszFileName, uFileNameSize);
|
||||
memcpy(buf + 30 + uFileNameSize, m_pExtraField, uExtraFieldSize);
|
||||
|
||||
// possible disk change before writing to the file in the disk spanning mode
|
||||
// so write the local header first
|
||||
storage.Write(buf, iLocalSize, true);
|
||||
// it was only local information, use CZipArchive::SetExtraField to set the file extra field in the central directory
|
||||
m_pExtraField.Release();
|
||||
|
||||
m_uDiskStart = (WORD)storage.GetCurrentDisk();
|
||||
m_uOffset = storage.GetPosition() - iLocalSize;
|
||||
}
|
||||
|
||||
// prepare the data before adding a new file
|
||||
bool CZipFileHeader::PrepareData(int iLevel, bool bSpan, bool bEncrypted)
|
||||
{
|
||||
memcpy(m_szSignature, m_gszSignature, 4);
|
||||
m_uInternalAttr = 0;
|
||||
m_uVersionNeeded = IsDirectory() ? 0xa : 0x14; // 1.0 or 2.0
|
||||
SetVersion((WORD)(0x14));
|
||||
|
||||
m_uCrc32 = 0;
|
||||
m_uComprSize = 0;
|
||||
m_uUncomprSize = 0;
|
||||
if (iLevel == 0)
|
||||
m_uMethod = 0;
|
||||
|
||||
if ((m_uMethod != Z_DEFLATED) && (m_uMethod != 0))
|
||||
m_uMethod = Z_DEFLATED;
|
||||
|
||||
m_uFlag = 0;
|
||||
if (m_uMethod == Z_DEFLATED)
|
||||
switch (iLevel)
|
||||
{
|
||||
case 1:
|
||||
m_uFlag |= 6;
|
||||
break;
|
||||
case 2:
|
||||
m_uFlag |= 4;
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
m_uFlag |= 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bSpan || bEncrypted)
|
||||
m_uFlag |= 8; // data descriptor present
|
||||
|
||||
if (bEncrypted)
|
||||
{
|
||||
m_uComprSize = ZIPARCHIVE_ENCR_HEADER_LEN; // encrypted header
|
||||
m_uFlag |= 1; // encrypted file
|
||||
}
|
||||
|
||||
return !(m_pszComment.GetSize() > USHRT_MAX || m_pszFileName.GetSize() > USHRT_MAX
|
||||
|| m_pExtraField.GetSize() > USHRT_MAX);
|
||||
}
|
||||
|
||||
void CZipFileHeader::GetCrcAndSizes(char * pBuffer)const
|
||||
{
|
||||
memcpy(pBuffer, &m_uCrc32, 4);
|
||||
memcpy(pBuffer + 4, &m_uComprSize, 4);
|
||||
memcpy(pBuffer + 8, &m_uUncomprSize, 4);
|
||||
}
|
||||
|
||||
DWORD CZipFileHeader::GetSize(bool bLocal)const
|
||||
{
|
||||
if (bLocal)
|
||||
return LOCALFILEHEADERSIZE + GetExtraFieldSize() + GetFileNameSize();
|
||||
else
|
||||
return FILEHEADERSIZE + GetExtraFieldSize() + GetFileNameSize() + GetCommentSize();
|
||||
}
|
||||
|
||||
|
||||
bool CZipFileHeader::SetComment(LPCTSTR lpszComment)
|
||||
{
|
||||
return CZipArchive::WideToSingle(lpszComment, m_pszComment) != -1;
|
||||
}
|
||||
|
||||
CZipString CZipFileHeader::GetComment() const
|
||||
{
|
||||
CZipString temp;
|
||||
CZipArchive::SingleToWide(m_pszComment, temp);
|
||||
return temp;
|
||||
|
||||
}
|
||||
|
||||
bool CZipFileHeader::SetFileName(LPCTSTR lpszFileName)
|
||||
{
|
||||
|
||||
return CZipArchive::WideToSingle(lpszFileName, m_pszFileName) != -1;
|
||||
}
|
||||
|
||||
CZipString CZipFileHeader::GetFileName()const
|
||||
{
|
||||
CZipString temp;
|
||||
CZipArchive::SingleToWide(m_pszFileName, temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool CZipFileHeader::IsDirectory()const
|
||||
{
|
||||
return ZipPlatform::IsDirectory(GetSystemAttr());
|
||||
}
|
||||
|
||||
DWORD CZipFileHeader::GetSystemAttr()const
|
||||
{
|
||||
int iSystemComp = GetSystemCompatibility();
|
||||
if (ZipCompatibility::IsPlatformSupported(iSystemComp))
|
||||
{
|
||||
if (!m_uExternalAttr && CZipPathComponent::HasEndingSeparator(GetFileName()))
|
||||
return ZipPlatform::GetDefaultDirAttributes(); // can happen
|
||||
else
|
||||
return ZipCompatibility::ConvertToSystem(m_uExternalAttr, iSystemComp, ZipPlatform::GetSystemID());
|
||||
}
|
||||
else
|
||||
return CZipPathComponent::HasEndingSeparator(GetFileName()) ? ZipPlatform::GetDefaultDirAttributes() : ZipPlatform::GetDefaultAttributes();
|
||||
}
|
||||
|
||||
|
||||
void CZipFileHeader::SetSystemAttr(DWORD uAttr)
|
||||
{
|
||||
m_uExternalAttr = ZipCompatibility::ConvertToSystem(uAttr, ZipPlatform::GetSystemID(), GetSystemCompatibility());
|
||||
}
|
||||
98
harbour/contrib/hbzlib/zipmemfile.cpp
Normal file
98
harbour/contrib/hbzlib/zipmemfile.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipMemFile.cpp $
|
||||
// $Archive: /ZipArchive/ZipMemFile.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#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*)hb_xrealloc((void*) m_lpBuf, nNewSize);
|
||||
else
|
||||
lpNew = (BYTE*)hb_xalloc(nNewSize);
|
||||
|
||||
if (!lpNew)
|
||||
CZipException::Throw(CZipException::memError);
|
||||
m_nBufSize = nNewSize;
|
||||
m_lpBuf = lpNew;
|
||||
}
|
||||
}
|
||||
|
||||
void CZipMemFile::SetLength(ZIP_ULONGLONG nNewLen)
|
||||
{
|
||||
if (m_nBufSize < (UINT)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) ? 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_ULONGLONG CZipMemFile::Seek(ZIP_LONGLONG lOff, int nFrom)
|
||||
{
|
||||
ZIP_ULONGLONG lNew = m_nPos;
|
||||
|
||||
if (nFrom == CZipAbstractFile::begin)
|
||||
lNew = lOff;
|
||||
else if (nFrom == CZipAbstractFile::current)
|
||||
lNew += lOff;
|
||||
else if (nFrom == CZipAbstractFile::end)
|
||||
lNew = m_nDataSize + lOff;
|
||||
else
|
||||
return lNew;
|
||||
|
||||
if (lNew< 0)
|
||||
CZipException::Throw(CZipException::memError);
|
||||
|
||||
m_nPos = (size_t)lNew;
|
||||
return lNew;
|
||||
}
|
||||
76
harbour/contrib/hbzlib/zippathcomponent.cpp
Normal file
76
harbour/contrib/hbzlib/zippathcomponent.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipPathComponent.cpp $
|
||||
// $Archive: /ZipArchive/ZipPathComponent.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "zippathcomponent.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CZipPathComponent::~CZipPathComponent()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CZipPathComponent::SetFullPath(LPCTSTR lpszFullPath)
|
||||
{
|
||||
|
||||
TCHAR szDrive[_MAX_DRIVE];
|
||||
TCHAR szDir[_MAX_DIR];
|
||||
TCHAR szFname[_MAX_FNAME];
|
||||
TCHAR szExt[_MAX_EXT];
|
||||
|
||||
|
||||
CZipString szTempPath(lpszFullPath);
|
||||
const CZipString szPrefix = _T("\\\\?\\unc\\");
|
||||
int i = -1, iLen = szPrefix.GetLength();
|
||||
if (iLen > szTempPath.GetLength())
|
||||
iLen = szTempPath.GetLength();
|
||||
CZipString szPossiblePrefix = szTempPath.Left(iLen);
|
||||
szPossiblePrefix.MakeLower(); // must perform case insensitive comparison
|
||||
while (++i < iLen && szPossiblePrefix[i] == szPrefix[i]);
|
||||
if (i == 2 || i == 4 || i == 8) // unc path, unicode path or unc path meeting windows file name conventions
|
||||
{
|
||||
m_szPrefix = szTempPath.Left(i);
|
||||
szTempPath = szTempPath.Mid(i);
|
||||
}
|
||||
else
|
||||
m_szPrefix.Empty();
|
||||
|
||||
_tsplitpath(szTempPath, szDrive , szDir, szFname, szExt);
|
||||
m_szDrive = szDrive;
|
||||
m_szDirectory = szDir;
|
||||
|
||||
m_szDirectory.TrimLeft(m_cSeparator);
|
||||
m_szDirectory.TrimRight(m_cSeparator);
|
||||
SetExtension(szExt);
|
||||
m_szFileTitle = szFname;
|
||||
}
|
||||
|
||||
|
||||
CZipString CZipPathComponent::GetNoDrive() const
|
||||
{
|
||||
CZipString szPath = m_szDirectory;
|
||||
CZipString szFileName = GetFileName();
|
||||
if (!szFileName.IsEmpty() && !szPath.IsEmpty())
|
||||
szPath += m_cSeparator;
|
||||
|
||||
szPath += szFileName;
|
||||
return szPath;
|
||||
}
|
||||
|
||||
351
harbour/contrib/hbzlib/zipplatform.cpp
Normal file
351
harbour/contrib/hbzlib/zipplatform.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipPlatform.cpp $
|
||||
// $Archive: /ZipArchive/ZipPlatform.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "zipplatform.h"
|
||||
#include "zipfileheader.h"
|
||||
#include "zipexception.h"
|
||||
#include "zipautobuffer.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined _MSC_VER && !defined __BORLANDC__ /*_MSC_VER may be defined in Borland after converting the VC project */
|
||||
#include <sys/utime.h>
|
||||
#else
|
||||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <time.h>
|
||||
#include "zippathcomponent.h"
|
||||
#include "zipcompatibility.h"
|
||||
|
||||
const TCHAR CZipPathComponent::m_cSeparator = _T('\\');
|
||||
|
||||
|
||||
#ifndef _UTIMBUF_DEFINED
|
||||
#define _utimbuf utimbuf
|
||||
#endif
|
||||
|
||||
DWORD ZipPlatform::GetDeviceFreeSpace(LPCTSTR lpszPath)
|
||||
{
|
||||
DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters;
|
||||
CZipPathComponent zpc (lpszPath);
|
||||
CZipString szDrive = zpc.GetFileDrive();
|
||||
if (!GetDiskFreeSpace(
|
||||
szDrive,
|
||||
&SectorsPerCluster,
|
||||
&BytesPerSector,
|
||||
&NumberOfFreeClusters,
|
||||
&TotalNumberOfClusters))
|
||||
{
|
||||
CZipPathComponent::AppendSeparator(szDrive); // in spite of what is written in MSDN it is sometimes needed (on fixed disks)
|
||||
if (!GetDiskFreeSpace(
|
||||
szDrive,
|
||||
&SectorsPerCluster,
|
||||
&BytesPerSector,
|
||||
&NumberOfFreeClusters,
|
||||
&TotalNumberOfClusters))
|
||||
|
||||
return 0;
|
||||
}
|
||||
__int64 total = SectorsPerCluster * BytesPerSector * NumberOfFreeClusters;
|
||||
return (DWORD)total;
|
||||
}
|
||||
|
||||
bool ZipPlatform::GetFileSize(LPCTSTR lpszFileName, DWORD& dSize)
|
||||
{
|
||||
HANDLE f = CreateFile(lpszFileName, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (!f)
|
||||
return false;
|
||||
DWORD dwSize;
|
||||
dwSize = ::GetFileSize(f, NULL);
|
||||
CloseHandle(f);
|
||||
if (dwSize == 0xFFFFFFFF)
|
||||
return false;
|
||||
dSize = dwSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
CZipString ZipPlatform::GetTmpFileName(LPCTSTR lpszPath, DWORD iSizeNeeded)
|
||||
{
|
||||
TCHAR empty[] = _T("");
|
||||
CZipString tempPath;
|
||||
bool bCheckTemp = true;
|
||||
if (lpszPath)
|
||||
{
|
||||
tempPath = lpszPath;
|
||||
bCheckTemp = GetDeviceFreeSpace(tempPath) < iSizeNeeded;
|
||||
|
||||
}
|
||||
if (bCheckTemp)
|
||||
{
|
||||
DWORD size = GetTempPath(0, NULL);
|
||||
if (size == 0)
|
||||
return empty;
|
||||
|
||||
GetTempPath(size, tempPath.GetBuffer(size));
|
||||
tempPath.ReleaseBuffer();
|
||||
if (GetDeviceFreeSpace(tempPath) < iSizeNeeded)
|
||||
{
|
||||
if (!GetCurrentDirectory(tempPath) || GetDeviceFreeSpace(tempPath) < iSizeNeeded)
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
CZipString tempName;
|
||||
if (!GetTempFileName(tempPath, _T("ZAR"), 0, tempName.GetBuffer(_MAX_PATH)))
|
||||
return empty;
|
||||
tempName.ReleaseBuffer();
|
||||
return tempName;
|
||||
}
|
||||
|
||||
|
||||
bool ZipPlatform::GetCurrentDirectory(CZipString& sz)
|
||||
{
|
||||
DWORD i = ::GetCurrentDirectory(0, NULL);
|
||||
if (!i)
|
||||
return false;
|
||||
TCHAR* pBuf = new TCHAR[i];
|
||||
bool b = true;
|
||||
if (!::GetCurrentDirectory(i, pBuf))
|
||||
b = false;
|
||||
else
|
||||
sz = pBuf;
|
||||
delete[] pBuf;
|
||||
return b;
|
||||
}
|
||||
|
||||
bool ZipPlatform::SetFileAttr(LPCTSTR lpFileName, DWORD uAttr)
|
||||
{
|
||||
return ::SetFileAttributes(lpFileName, uAttr) != 0;
|
||||
}
|
||||
|
||||
bool ZipPlatform::GetFileAttr(LPCTSTR lpFileName, DWORD& uAttr)
|
||||
{
|
||||
// not using MFC due to MFC bug (attr is one byte there)
|
||||
DWORD temp = ::GetFileAttributes(lpFileName);
|
||||
if (temp == ( DWORD )-1)
|
||||
return false;
|
||||
uAttr = temp;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool ZipPlatform::GetFileModTime(LPCTSTR lpFileName, time_t & ttime)
|
||||
{
|
||||
#if defined _MSC_VER && !defined __BORLANDC__ /*_MSC_VER may be defined in Borland after converting the VC project */
|
||||
struct _stat st;
|
||||
if (_tstat(lpFileName, &st) != 0)
|
||||
#else
|
||||
struct stat st;
|
||||
if (stat(lpFileName, &st) != 0)
|
||||
#endif
|
||||
return false;
|
||||
|
||||
ttime = st.st_mtime;
|
||||
return ttime != -1;
|
||||
}
|
||||
|
||||
bool ZipPlatform::SetFileModTime(LPCTSTR lpFileName, time_t ttime)
|
||||
{
|
||||
struct _utimbuf ub;
|
||||
ub.actime = time(NULL);
|
||||
ub.modtime = ttime == -1 ? time(NULL) : ttime; // if wrong file time, set it to the current
|
||||
return _tutime(lpFileName, &ub) == 0;
|
||||
}
|
||||
|
||||
|
||||
bool ZipPlatform::ChangeDirectory(LPCTSTR lpDirectory)
|
||||
{
|
||||
return _tchdir(lpDirectory) == 0; // returns 0 if ok
|
||||
}
|
||||
int ZipPlatform::FileExists(LPCTSTR lpszName)
|
||||
{
|
||||
if (_taccess(lpszName, 0) == 0)
|
||||
{
|
||||
if (DirectoryExists(lpszName))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
ZIPINLINE bool ZipPlatform::IsDriveRemovable(LPCTSTR lpszFilePath)
|
||||
{
|
||||
CZipPathComponent zpc(lpszFilePath);
|
||||
return ::GetDriveType(zpc.GetFileDrive()) == DRIVE_REMOVABLE;
|
||||
}
|
||||
|
||||
ZIPINLINE bool ZipPlatform::SetVolLabel(LPCTSTR lpszPath, LPCTSTR lpszLabel)
|
||||
{
|
||||
CZipPathComponent zpc(lpszPath);
|
||||
CZipString szDrive = zpc.GetFileDrive();
|
||||
CZipPathComponent::AppendSeparator(szDrive);
|
||||
return ::SetVolumeLabel(szDrive, lpszLabel) != 0;
|
||||
}
|
||||
|
||||
ZIPINLINE void ZipPlatform::AnsiOem(CZipAutoBuffer& buffer, bool bAnsiToOem)
|
||||
{
|
||||
if (bAnsiToOem)
|
||||
CharToOemBuffA(buffer, buffer, buffer.GetSize());
|
||||
else
|
||||
OemToCharBuffA(buffer, buffer, buffer.GetSize());
|
||||
}
|
||||
|
||||
ZIPINLINE bool ZipPlatform::RemoveFile(LPCTSTR lpszFileName, bool bThrow)
|
||||
{
|
||||
if (!::DeleteFile((LPTSTR)lpszFileName))
|
||||
if (bThrow)
|
||||
CZipException::Throw(CZipException::notRemoved, lpszFileName);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
ZIPINLINE bool ZipPlatform::RenameFile( LPCTSTR lpszOldName, LPCTSTR lpszNewName, bool bThrow)
|
||||
{
|
||||
if (!::MoveFile((LPTSTR)lpszOldName, (LPTSTR)lpszNewName))
|
||||
if (bThrow)
|
||||
CZipException::Throw(CZipException::notRenamed, lpszOldName);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
ZIPINLINE bool ZipPlatform::IsDirectory(DWORD uAttr)
|
||||
{
|
||||
return (uAttr & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
}
|
||||
ZIPINLINE bool ZipPlatform::CreateDirectory(LPCTSTR lpDirectory)
|
||||
{
|
||||
return ::CreateDirectory(lpDirectory, NULL) != 0;
|
||||
}
|
||||
|
||||
ZIPINLINE DWORD ZipPlatform::GetDefaultAttributes()
|
||||
{
|
||||
return 0x81a40020; // make it readable under Unix
|
||||
}
|
||||
|
||||
ZIPINLINE DWORD ZipPlatform::GetDefaultDirAttributes()
|
||||
{
|
||||
return 0x41ff0010; // make it readable under Unix
|
||||
}
|
||||
|
||||
ZIPINLINE int ZipPlatform::GetSystemID()
|
||||
{
|
||||
return ZipCompatibility::zcDosFat;
|
||||
}
|
||||
|
||||
ZIPINLINE bool ZipPlatform::GetSystemCaseSensitivity()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _UNICODE
|
||||
int ZipPlatform::WideToSingle(LPCTSTR lpWide, CZipAutoBuffer &szSingle)
|
||||
{
|
||||
size_t wideLen = wcslen(lpWide);
|
||||
if (wideLen == 0)
|
||||
{
|
||||
szSingle.Release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// iLen does not include terminating character
|
||||
int iLen = WideCharToMultiByte(CP_ACP,0, lpWide, wideLen, szSingle,
|
||||
0, NULL, NULL);
|
||||
if (iLen > 0)
|
||||
{
|
||||
szSingle.Allocate(iLen, true);
|
||||
iLen = WideCharToMultiByte(CP_ACP,0, lpWide , wideLen, szSingle,
|
||||
iLen, NULL, NULL);
|
||||
ASSERT(iLen != 0);
|
||||
}
|
||||
else // here it means error
|
||||
{
|
||||
szSingle.Release();
|
||||
iLen --;
|
||||
}
|
||||
return iLen;
|
||||
|
||||
}
|
||||
int ZipPlatform::SingleToWide(const CZipAutoBuffer &szSingle, CZipString& szWide)
|
||||
{
|
||||
int singleLen = szSingle.GetSize();
|
||||
// iLen doesn't include terminating character
|
||||
int iLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSingle.GetBuffer(), singleLen, NULL, 0);
|
||||
if (iLen > 0)
|
||||
{
|
||||
iLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSingle.GetBuffer(), singleLen,
|
||||
szWide.GetBuffer(iLen) , iLen);
|
||||
szWide.ReleaseBuffer(iLen);
|
||||
ASSERT(iLen != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
szWide.Empty();
|
||||
iLen --; // return -1
|
||||
}
|
||||
return iLen;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _MFC_VER
|
||||
#include <io.h>
|
||||
#include <share.h>
|
||||
bool ZipPlatform::TruncateFile(int iDes, DWORD iSize)
|
||||
{
|
||||
int ret = chsize(iDes, iSize);
|
||||
return ret != -1;
|
||||
|
||||
}
|
||||
|
||||
int ZipPlatform::OpenFile(LPCTSTR lpszFileName, UINT iMode, int iShareMode)
|
||||
{
|
||||
switch (iShareMode)
|
||||
{
|
||||
case (CZipFile::shareDenyWrite & CZipFile::shareDenyRead):
|
||||
iShareMode = SH_DENYRW;
|
||||
break;
|
||||
case (CZipFile::shareDenyRead):
|
||||
iShareMode = SH_DENYRD;
|
||||
break;
|
||||
case (CZipFile::shareDenyWrite):
|
||||
iShareMode = SH_DENYWR;
|
||||
break;
|
||||
default:
|
||||
iShareMode = SH_DENYNO;
|
||||
}
|
||||
return _tsopen(lpszFileName, iMode, iShareMode, S_IREAD | S_IWRITE /*required only when O_CREAT mode*/);
|
||||
}
|
||||
|
||||
bool ZipPlatform::FlushFile(int iDes)
|
||||
{
|
||||
return _commit(iDes) == 0;
|
||||
}
|
||||
|
||||
int ZipPlatform::GetFileSystemHandle(int iDes)
|
||||
{
|
||||
return _get_osfhandle(iDes);
|
||||
}
|
||||
|
||||
|
||||
#endif //_MFC_VER
|
||||
48
harbour/contrib/hbzlib/zipplatformcomm.cpp
Normal file
48
harbour/contrib/hbzlib/zipplatformcomm.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipPlatformComm.cpp $
|
||||
// $Archive: /ZipArchive/ZipPlatformComm.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "zipplatform.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() == szDirectory) ||
|
||||
(FileExists(szDirectory) == -1))
|
||||
return true;
|
||||
if (!ForceDirectory(zpc.GetFilePath()))
|
||||
return false;
|
||||
if (!CreateDirectory(szDirectory))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
461
harbour/contrib/hbzlib/zipstorage.cpp
Normal file
461
harbour/contrib/hbzlib/zipstorage.cpp
Normal file
@@ -0,0 +1,461 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// $Workfile: ZipStorage.cpp $
|
||||
// $Archive: /ZipArchive/ZipStorage.cpp $
|
||||
// $Date$ $Author$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is part of the ZipArchive library source distribution and
|
||||
// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/)
|
||||
//
|
||||
// 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 see the file License.txt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "zipstorage.h"
|
||||
#include "ziparchive.h"
|
||||
// #include "ZipPathComponent.h"
|
||||
#include "zipplatform.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// disk spanning objectives:
|
||||
// - sinature at the first disk at the beginning
|
||||
// - headers and central dir records not divided between disks
|
||||
// - each file has a data descriptor preceded by the signature
|
||||
// (bit 3 set in flag);
|
||||
|
||||
int CZipActionCallback::m_iStep = 256;
|
||||
|
||||
char CZipStorage::m_gszExtHeaderSignat[] = {0x50, 0x4b, 0x07, 0x08};
|
||||
CZipStorage::CZipStorage()
|
||||
{
|
||||
m_pChangeDiskFunc = NULL;
|
||||
m_iWriteBufferSize = 65536;
|
||||
m_iCurrentDisk = -1;
|
||||
m_pFile = NULL;
|
||||
}
|
||||
|
||||
CZipStorage::~CZipStorage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
DWORD CZipStorage::Read(void *pBuf, DWORD iSize, bool bAtOnce)
|
||||
{
|
||||
if (iSize == 0)
|
||||
return 0;
|
||||
DWORD iRead = 0;
|
||||
while (!iRead)
|
||||
{
|
||||
iRead = m_pFile->Read(pBuf, iSize);
|
||||
if (!iRead)
|
||||
if (IsSpanMode())
|
||||
ChangeDisk(m_iCurrentDisk + 1);
|
||||
else
|
||||
ThrowError(CZipException::badZipFile);
|
||||
}
|
||||
|
||||
if (iRead == iSize)
|
||||
return iRead;
|
||||
else if (bAtOnce || !IsSpanMode())
|
||||
ThrowError(CZipException::badZipFile);
|
||||
|
||||
while (iRead < iSize)
|
||||
{
|
||||
ChangeDisk(m_iCurrentDisk + 1);
|
||||
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 szPathName, int iMode, int iVolumeSize)
|
||||
{
|
||||
m_pWriteBuffer.Allocate(m_iWriteBufferSize);
|
||||
m_uBytesInWriteBuffer = 0;
|
||||
m_bNewSpan = false;
|
||||
m_pFile = &m_internalfile;
|
||||
m_bInMemory = false;
|
||||
|
||||
if ((iMode == CZipArchive::zipCreate) ||(iMode == CZipArchive::zipCreateSpan)) // create new archive
|
||||
{
|
||||
m_bReadOnly = false;
|
||||
m_iCurrentDisk = 0;
|
||||
if (iMode == CZipArchive::zipCreate)
|
||||
{
|
||||
m_iSpanMode = noSpan;
|
||||
OpenFile(szPathName, CZipFile::modeCreate | CZipFile::modeReadWrite);
|
||||
}
|
||||
else // create disk spanning archive
|
||||
{
|
||||
m_bNewSpan = true;
|
||||
m_iBytesWritten = 0;
|
||||
if (iVolumeSize <= 0) // pkzip span
|
||||
{
|
||||
if (!m_pChangeDiskFunc)
|
||||
ThrowError(CZipException::noCallback);
|
||||
if (!ZipPlatform::IsDriveRemovable(szPathName))
|
||||
ThrowError(CZipException::nonRemovable);
|
||||
m_iSpanMode = pkzipSpan;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iTdSpanData = iVolumeSize;
|
||||
m_iSpanMode = tdSpan;
|
||||
}
|
||||
|
||||
NextDisk(4, szPathName);
|
||||
Write(m_gszExtHeaderSignat, 4, true);
|
||||
}
|
||||
}
|
||||
else // open existing
|
||||
{
|
||||
m_bReadOnly = iMode == CZipArchive::zipOpenReadOnly;
|
||||
OpenFile(szPathName, CZipFile::modeNoTruncate |
|
||||
(m_bReadOnly ? CZipFile::modeRead : CZipFile::modeReadWrite));
|
||||
// m_uData, i m_iSpanMode are automatically set during reading the central dir
|
||||
m_iSpanMode = iVolumeSize == 0 ? suggestedAuto : suggestedTd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CZipStorage::Open(CZipMemFile& mf, int iMode)
|
||||
{
|
||||
m_pWriteBuffer.Allocate(m_iWriteBufferSize);
|
||||
m_uBytesInWriteBuffer = 0;
|
||||
m_bNewSpan = false;
|
||||
m_pFile = &mf;
|
||||
m_bInMemory = true;
|
||||
|
||||
if (iMode == CZipArchive::zipCreate)
|
||||
{
|
||||
m_iCurrentDisk = 0;
|
||||
m_iSpanMode = noSpan;
|
||||
mf.SetLength(0);
|
||||
}
|
||||
else // open existing
|
||||
{
|
||||
mf.SeekToBegin();
|
||||
m_iSpanMode = suggestedAuto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CZipStorage::ChangeDisk(int iNumber)
|
||||
{
|
||||
if (iNumber == m_iCurrentDisk)
|
||||
return;
|
||||
|
||||
ASSERT(m_iSpanMode != noSpan);
|
||||
m_iCurrentDisk = iNumber;
|
||||
OpenFile(m_iSpanMode == pkzipSpan ? ChangePkzipRead() : ChangeTdRead(),
|
||||
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::ChangePkzipRead()
|
||||
{
|
||||
CZipString szTemp = m_pFile->GetFilePath();
|
||||
m_pFile->Close();
|
||||
CallCallback(-1 , szTemp);
|
||||
return szTemp;
|
||||
}
|
||||
|
||||
CZipString CZipStorage::ChangeTdRead()
|
||||
{
|
||||
CZipString szTemp = GetTdVolumeName(m_iCurrentDisk == m_iTdSpanData);
|
||||
m_pFile->Close();
|
||||
return szTemp;
|
||||
}
|
||||
|
||||
CZipString CZipStorage::RenameLastFileInTDSpan()
|
||||
{
|
||||
ASSERT(m_iSpanMode == tdSpan);
|
||||
// give to the last volume the zip extension
|
||||
CZipString szFileName = m_pFile->GetFilePath();
|
||||
CZipString szNewFileName = GetTdVolumeName(true);
|
||||
if (!m_bInMemory)
|
||||
{
|
||||
m_pFile->Flush();
|
||||
m_pFile->Close();
|
||||
}
|
||||
if (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 ((m_iSpanMode == tdSpan) && (m_bNewSpan))
|
||||
{
|
||||
sz = RenameLastFileInTDSpan();
|
||||
bClose = false;// already closed in RenameLastFileInTDSpan
|
||||
}
|
||||
}
|
||||
if (sz.IsEmpty())
|
||||
sz = m_pFile->GetFilePath();
|
||||
if (bClose && !m_bInMemory)
|
||||
{
|
||||
FlushFile();
|
||||
m_pFile->Close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
m_pWriteBuffer.Release();
|
||||
m_iCurrentDisk = -1;
|
||||
m_iSpanMode = noSpan;
|
||||
m_pFile = NULL;
|
||||
return sz;
|
||||
}
|
||||
|
||||
CZipString CZipStorage::GetTdVolumeName(bool bLast, LPCTSTR lpszZipName) const
|
||||
{
|
||||
CZipString szFilePath = lpszZipName ? lpszZipName : (LPCTSTR)m_pFile->GetFilePath();
|
||||
CZipPathComponent zpc(szFilePath);
|
||||
CZipString szExt;
|
||||
if (bLast)
|
||||
szExt = m_szSpanExtension;
|
||||
else
|
||||
szExt.Format(_T("%.3d"), m_iCurrentDisk);
|
||||
zpc.SetExtension(szExt);
|
||||
return zpc.GetFullPath();
|
||||
}
|
||||
|
||||
void CZipStorage::NextDisk(int iNeeded, LPCTSTR lpszFileName)
|
||||
{
|
||||
Flush();
|
||||
ASSERT(m_iSpanMode != noSpan);
|
||||
if (m_iBytesWritten)
|
||||
{
|
||||
m_iBytesWritten = 0;
|
||||
m_iCurrentDisk++;
|
||||
if (m_iCurrentDisk >= 999)
|
||||
ThrowError(CZipException::tooManyVolumes);
|
||||
}
|
||||
CZipString szFileName;
|
||||
bool bPkSpan = (m_iSpanMode == pkzipSpan);
|
||||
if (bPkSpan)
|
||||
szFileName = lpszFileName ? lpszFileName : (LPCTSTR)m_pFile->GetFilePath();
|
||||
else
|
||||
szFileName = GetTdVolumeName(false, lpszFileName);
|
||||
|
||||
if (!m_pFile->IsClosed())
|
||||
{
|
||||
m_pFile->Flush();
|
||||
m_pFile->Close();
|
||||
}
|
||||
|
||||
if (bPkSpan)
|
||||
{
|
||||
int iCode = iNeeded;
|
||||
while (true)
|
||||
{
|
||||
CallCallback(iCode, szFileName);
|
||||
if (ZipPlatform::FileExists(szFileName))
|
||||
iCode = -2;
|
||||
else
|
||||
{
|
||||
CZipString label;
|
||||
label.Format(_T("pkback# %.3d"), m_iCurrentDisk + 1);
|
||||
if (!ZipPlatform::SetVolLabel(szFileName, label))
|
||||
iCode = -3;
|
||||
else if (!OpenFile(szFileName, CZipFile::modeCreate | CZipFile::modeReadWrite, false))
|
||||
iCode = -4;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
m_uCurrentVolSize = GetFreeVolumeSpace();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uCurrentVolSize = m_iTdSpanData;
|
||||
OpenFile(szFileName, CZipFile::modeCreate | CZipFile::modeReadWrite);
|
||||
}
|
||||
}
|
||||
|
||||
void CZipStorage::CallCallback(int iCode, CZipString szTemp)
|
||||
{
|
||||
ASSERT(m_pChangeDiskFunc);
|
||||
m_pChangeDiskFunc->m_szExternalFile = szTemp;
|
||||
m_pChangeDiskFunc->m_uDiskNeeded = m_iCurrentDisk + 1;
|
||||
if (!m_pChangeDiskFunc->Callback(iCode))
|
||||
CZipException::Throw(CZipException::aborted, szTemp);
|
||||
}
|
||||
|
||||
DWORD CZipStorage::GetFreeVolumeSpace() const
|
||||
{
|
||||
ASSERT (m_iSpanMode == pkzipSpan);
|
||||
CZipString szTemp = m_pFile->GetFilePath();
|
||||
if (szTemp.IsEmpty()) // called once when creating a disk spanning archive
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
CZipPathComponent zpc(szTemp);
|
||||
return ZipPlatform::GetDeviceFreeSpace(zpc.GetFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CZipStorage::UpdateSpanMode(WORD uLastDisk)
|
||||
{
|
||||
m_iCurrentDisk = uLastDisk;
|
||||
if (uLastDisk)
|
||||
{
|
||||
// disk spanning detected
|
||||
CZipString szFilePath = m_pFile->GetFilePath();
|
||||
if (m_iSpanMode == suggestedAuto)
|
||||
m_iSpanMode = ZipPlatform::IsDriveRemovable(szFilePath) ?
|
||||
pkzipSpan : tdSpan;
|
||||
else
|
||||
{
|
||||
ASSERT(m_iSpanMode == suggestedTd);
|
||||
m_iSpanMode = tdSpan;
|
||||
}
|
||||
|
||||
if (m_iSpanMode == pkzipSpan)
|
||||
{
|
||||
if (!m_pChangeDiskFunc)
|
||||
ThrowError(CZipException::noCallback);
|
||||
}
|
||||
else /*if (m_iSpanMode == tdSpan)*/
|
||||
m_iTdSpanData = uLastDisk; // disk with .zip extension ( the last one)
|
||||
CZipPathComponent zpc(szFilePath);
|
||||
m_szSpanExtension = zpc.GetFileExt();
|
||||
m_pWriteBuffer.Release(); // no need for this in this case
|
||||
}
|
||||
else
|
||||
m_iSpanMode = noSpan;
|
||||
|
||||
}
|
||||
|
||||
void CZipStorage::Write(const void *pBuf, DWORD iSize, bool bAtOnce)
|
||||
{
|
||||
if (!IsSpanMode())
|
||||
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)
|
||||
{
|
||||
DWORD uFree;
|
||||
while ((uFree = VolumeLeft()) < iNeeded)
|
||||
{
|
||||
if ((m_iSpanMode == tdSpan) && !m_iBytesWritten && !m_uBytesInWriteBuffer)
|
||||
// in the tdSpan 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 = iNeeded;
|
||||
else
|
||||
NextDisk(iNeeded);
|
||||
}
|
||||
|
||||
DWORD uLeftToWrite = iSize - uTotal;
|
||||
DWORD uToWrite = uFree < uLeftToWrite ? 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(m_pWriteBuffer + m_uBytesInWriteBuffer, pBuf + uWritten, uToCopy);
|
||||
uWritten += uToCopy;
|
||||
m_uBytesInWriteBuffer += uToCopy;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD CZipStorage::VolumeLeft() const
|
||||
{
|
||||
// for pkzip span m_uCurrentVolSize is updated after each flush()
|
||||
return m_uCurrentVolSize - m_uBytesInWriteBuffer - ((m_iSpanMode == pkzipSpan) ? 0 : m_iBytesWritten);
|
||||
}
|
||||
|
||||
void CZipStorage::Flush()
|
||||
{
|
||||
if (m_iSpanMode != noSpan)
|
||||
m_iBytesWritten += m_uBytesInWriteBuffer;
|
||||
if (m_uBytesInWriteBuffer)
|
||||
{
|
||||
m_pFile->Write(m_pWriteBuffer, m_uBytesInWriteBuffer);
|
||||
m_uBytesInWriteBuffer = 0;
|
||||
}
|
||||
if (m_iSpanMode == pkzipSpan)
|
||||
// after writing it is difficult to predict the free space due to
|
||||
// not completly written clusters, write operation may start from
|
||||
// the new cluster
|
||||
m_uCurrentVolSize = GetFreeVolumeSpace();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CZipStorage::FinalizeSpan()
|
||||
{
|
||||
ASSERT(IsSpanMode() == 1); // span in creation
|
||||
ASSERT(!m_bInMemory);
|
||||
|
||||
CZipString szFileName;
|
||||
if ((m_iSpanMode == tdSpan) && (m_bNewSpan))
|
||||
szFileName = RenameLastFileInTDSpan();
|
||||
else
|
||||
{
|
||||
szFileName = m_pFile->GetFilePath();
|
||||
// the file is already closed
|
||||
m_pFile->Close();
|
||||
}
|
||||
m_bNewSpan = false;
|
||||
if (m_iCurrentDisk == 0) // one-disk span was converted to normal archive
|
||||
m_iSpanMode = noSpan;
|
||||
else
|
||||
m_iTdSpanData = m_iCurrentDisk;
|
||||
|
||||
OpenFile(szFileName, CZipFile::modeNoTruncate | (m_iSpanMode == noSpan ? CZipFile::modeReadWrite : CZipFile::modeRead));
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user