00001
00002
00003
00004
00006
00007
00008
00009
00010
00011
00012
00013
00014
00016
00023 #if !defined(AFX_CENTRALDIR_H__859029E8_8927_4717_9D4B_E26E5DA12BAE__INCLUDED_)
00024 #define AFX_CENTRALDIR_H__859029E8_8927_4717_9D4B_E26E5DA12BAE__INCLUDED_
00025
00026 #if _MSC_VER > 1000
00027 #pragma once
00028 #endif // _MSC_VER > 1000
00029
00030 #if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
00031 #pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
00032 #endif
00033
00034 #include "ZipException.h"
00035 #include "ZipFileHeader.h"
00036 #include "ZipAutoBuffer.h"
00037 #include "ZipCollections.h"
00038 #include "ZipCompatibility.h"
00039 #include "ZipExport.h"
00040 #define ZIPARCHIVE_DATADESCRIPTOR_LEN 12
00041
00045 class ZIP_API CZipCentralDir
00046 {
00047 public:
00056 struct ZIP_API CZipFindFast
00057 {
00058 CZipFindFast()
00059 {
00060 m_uIndex = 0;
00061 m_pHeader= NULL;
00062 }
00063 CZipFindFast(CZipFileHeader* pHeader, WORD uIndex):m_pHeader(pHeader), m_uIndex(uIndex){}
00067 CZipFileHeader* m_pHeader;
00068
00072 WORD m_uIndex;
00073 };
00074
00075
00079 struct ZIP_API Info
00080 {
00081 DWORD m_uCentrDirPos;
00082 DWORD m_uBytesBeforeZip;
00083 WORD m_uThisDisk;
00084 WORD m_uDiskWithCD;
00085 WORD m_uDiskEntriesNo;
00086 WORD m_uEntriesNumber;
00087 DWORD m_uSize;
00088 DWORD m_uOffset;
00089
00090
00091 bool m_bOnDisk;
00092
00093 protected:
00094 friend class CZipCentralDir;
00095 bool CheckIfOK_1()
00096 {
00097 return ((DWORD)m_uCentrDirPos >= m_uOffset + m_uSize);
00098 }
00099 void SetBytesBeforeZip(bool bIsSpan)
00100 {
00101 m_uBytesBeforeZip = bIsSpan ? 0 : m_uCentrDirPos - m_uSize - m_uOffset;
00102 }
00103 bool CheckIfOK_2()
00104 {
00105 return (m_uSize || !m_uEntriesNumber) && (m_uEntriesNumber || !m_uSize);
00106 }
00107 void DiskChange(int iCurrentDisk)
00108 {
00109 m_uThisDisk = (WORD)iCurrentDisk;
00110 if (m_uEntriesNumber)
00111 {
00112 m_uDiskEntriesNo = 0;
00113 }
00114 else
00115 {
00116 m_uDiskWithCD = m_uThisDisk;
00117 m_uOffset = 0;
00118 }
00119 }
00120 };
00121
00122 CZipCentralDir();
00123 virtual ~CZipCentralDir();
00124
00125 static char m_gszSignature[];
00126
00127 char m_szSignature[4];
00128
00129 CZipAutoBuffer m_pszComment;
00130 CZipAutoBuffer m_pLocalExtraField;
00131 CZipFileHeader* m_pOpenedFile;
00132
00136 void Init();
00137
00142 void Read();
00143
00150 void OpenFile(WORD uIndex);
00151
00159 CZipFileHeader* UpdateLocal(WORD uIndex);
00160
00167 bool IsValidIndex(int uIndex)const;
00168
00177 void RemoveFile(CZipFileHeader* pHeader, int iIndex = -1, bool bShift = true);
00178
00179
00184 void RemoveLastFile(CZipFileHeader* pHeader = NULL, int iIndex = -1)
00185 {
00186 if (iIndex == -1)
00187 {
00188 iIndex = (int)(m_headers.GetSize() - 1);
00189 if (iIndex == -1)
00190 return;
00191 }
00192 if (!pHeader)
00193 pHeader = m_headers[iIndex];
00194 DWORD uNewSize = pHeader->m_uOffset + GetBytesBefore();
00195
00196 RemoveFile(pHeader, iIndex);
00197
00198 m_pStorage->Flush();
00199 m_pStorage->m_pFile->SetLength(uNewSize);
00200 m_info.m_bOnDisk = false;
00201 }
00202
00203
00208 void RemoveAll();
00218 void Clear(bool bEverything = true);
00219
00228 CZipFileHeader* AddNewFile(const CZipFileHeader & header, int iReplaceIndex = -1);
00229
00233 CZipString GetProperHeaderFileName(const CZipFileHeader* pHeader) const
00234 {
00235 if (!m_bConvertAfterOpen)
00236 {
00237 CZipFileHeader fh = *pHeader;
00238 ConvertFileName(true, false, &fh);
00239 return fh.GetFileName();
00240 }
00241 else
00242 return pHeader->GetFileName();
00243 }
00244
00250 void RemoveFromDisk();
00251
00259 DWORD GetSize(bool bWhole = false) const;
00260
00266 void CloseFile(bool bAfterException = false);
00267
00272 void CloseNewFile();
00273
00278 void Write(CZipActionCallback* pCallback);
00279
00283 void EnableFindFast(bool bEnable, bool bCaseSensitive);
00284
00289 int FindFile(LPCTSTR lpszFileName, bool bCaseSensitive, bool bSporadically, bool bFileNameOnly);
00290
00291
00295 int GetFindFastIndex(int iFindFastIndex)const
00296 {
00297 if (!IsValidIndex(iFindFastIndex) || !m_bFindFastEnabled)
00298 {
00299
00300 return -1;
00301 }
00302
00303 return m_findarray[iFindFastIndex].m_uIndex;
00304 }
00305
00309 CZipStorage* m_pStorage;
00310
00311
00319 int m_iBufferSize;
00320
00321
00322
00323
00328 CZipArray<CZipFileHeader*> m_headers;
00329
00330 CZipFileHeader* operator[](int iIndex)
00331 {
00332 return m_headers[iIndex];
00333 }
00334 const CZipFileHeader* operator[](int iIndex) const
00335 {
00336 return m_headers[iIndex];
00337 }
00338
00339
00357 bool m_bConvertAfterOpen;
00358
00359
00367 bool m_bOemConversion;
00368
00369
00370
00371
00386 void ConvertFileName(bool bFromZip, bool bAfterOpen, CZipFileHeader* pHeader = NULL) const
00387 {
00388 if (bAfterOpen != m_bConvertAfterOpen)
00389 return;
00390 if (!pHeader)
00391 {
00392 pHeader = m_pOpenedFile;
00393 ASSERT(pHeader);
00394 }
00395 ZipCompatibility::FileNameUpdate(*pHeader, bFromZip, m_bOemConversion);
00396 }
00397
00403 void ConvertAll();
00404
00413 int FindFileNameIndex(LPCTSTR lpszFileName) const;
00414
00415 DWORD GetBytesBefore() const {return m_info.m_uBytesBeforeZip;}
00419 void GetInfo(Info& info) const {info = m_info;}
00423 bool IsFindFastEnabled(){return m_bFindFastEnabled;}
00427 void RenameFile(WORD uIndex, LPCTSTR lpszNewName);
00428 protected:
00432 void SortHeaders();
00433 static int CompareHeaders(const void *pArg1, const void *pArg2)
00434 {
00435 CZipFileHeader* pw1 = *(CZipFileHeader**)pArg1;
00436 CZipFileHeader* pw2 = *(CZipFileHeader**)pArg2;
00437 if ((pw1->m_uOffset < pw2->m_uOffset && pw1->m_uDiskStart == pw2->m_uDiskStart)
00438 || (pw1->m_uDiskStart < pw2->m_uDiskStart))
00439 return -1;
00440 else if ((pw1->m_uOffset > pw2->m_uOffset && pw1->m_uDiskStart == pw2->m_uDiskStart)
00441 || (pw1->m_uDiskStart > pw2->m_uDiskStart))
00442 return 1;
00443 else
00444 {
00445 ASSERT(FALSE);
00446
00447 CZipException::Throw(CZipException::badZipFile);
00448 return 0;
00449 }
00450 }
00451
00452
00456 void BuildFindFastArray( bool bCaseSensitive );
00457
00464 CZipArray<CZipFindFast> m_findarray;
00465
00476 bool m_bFindFastEnabled;
00477
00478
00479
00493 int CompareElement(LPCTSTR lpszFileName, WORD uIndex) const
00494 {
00495 return (m_findarray[uIndex].m_pHeader->GetFileName().*m_pCompare)(lpszFileName);
00496 }
00501 void InsertFindFastElement(CZipFileHeader* pHeader, WORD uIndex);
00502
00503
00504
00511 ZIPSTRINGCOMPARE m_pCompare;
00512
00516 bool m_bCaseSensitive;
00517
00521 Info m_info;
00522
00527 DWORD Locate();
00532 void ReadHeaders();
00533
00537 void RemoveHeaders();
00549 bool RemoveDataDescr(bool bFromBuffer);
00554 void WriteHeaders(CZipActionCallback* pCallback, bool bOneDisk);
00560 DWORD WriteCentralEnd();
00561
00567 void ThrowError(int err) const;
00568
00569
00570 };
00571
00572
00573 #endif // !defined(AFX_CENTRALDIR_H__859029E8_8927_4717_9D4B_E26E5DA12BAE__INCLUDED_)