📄 ziparchive.cpp
字号:
m_info.m_stream.opaque = m_bDetectZlibMemoryLeaks ? &m_list : 0;
int err = deflateInit2(&m_info.m_stream, iLevel,
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
CheckForError(err);
}
m_iFileOpened = compress;
return bRet;
}
CString CZipArchive::GetFilePath(LPCTSTR lpszFilePath)
{
TCHAR szDir[_MAX_DIR];
TCHAR szDrive[_MAX_DRIVE];
_tsplitpath(lpszFilePath, szDrive, szDir, NULL, NULL);
return CString(szDrive) + CString(szDir);
}
CString CZipArchive::GetFileExt(LPCTSTR lpszFilePath)
{
TCHAR szExt[_MAX_EXT];
_tsplitpath(lpszFilePath, NULL, NULL, NULL, szExt);
return CString(szExt);
}
CString CZipArchive::GetFileTitle(LPCTSTR lpszFilePath)
{
TCHAR szFname[_MAX_FNAME];
_tsplitpath(lpszFilePath, NULL, NULL, szFname, NULL);
return CString(szFname);
}
CString CZipArchive::GetFileDirAndName(LPCTSTR lpszFilePath)
{
TCHAR szDir[_MAX_DIR];
TCHAR szFname[_MAX_FNAME];
TCHAR szExt[_MAX_EXT];
_tsplitpath(lpszFilePath, NULL , szDir, szFname, szExt);
CString Dir = szDir;
Dir.TrimLeft("\\");
return Dir + szFname + szExt;
}
CString CZipArchive::GetFileName(LPCTSTR lpszFilePath)
{
TCHAR szExt[_MAX_EXT];
TCHAR szName[_MAX_FNAME];
_tsplitpath(lpszFilePath, NULL, NULL, szName, szExt);
return CString(szName) + CString(szExt);
}
bool CZipArchive::ForceDirectory(LPCTSTR lpDirectory)
{
ASSERT(lpDirectory);
CString szDirectory = lpDirectory;
szDirectory.TrimRight("\\");
if ((GetFilePath(szDirectory) == szDirectory) ||
(FileExists(szDirectory) == -1))
return true;
if (!ForceDirectory(GetFilePath(szDirectory)))
return false;
if (!CreateDirectory(szDirectory, NULL))
return false;
return true;
}
int CZipArchive::FileExists(LPCTSTR lpszName)
{
CFileFind fileFind;
if (!fileFind.FindFile(lpszName))
{
if (DirectoryExists(lpszName)) // if root ex. "C:\"
return -1;
return 0;
}
fileFind.FindNextFile();
return fileFind.IsDirectory() ? -1 : 1;
}
bool CZipArchive::DirectoryExists(LPCTSTR lpszDir)
{
char curPath[_MAX_PATH]; /* Get the current working directory: */
if (!_getcwd(curPath, _MAX_PATH))
return false;
if (_chdir(lpszDir)) // retruns 0 if error
return false;
_chdir(curPath);
return true;
}
bool CZipArchive::IsFileDirectory(WORD uIndex)
{
if (IsClosed())
{
TRACE("ZipArchive is closed.\n");
return false;
}
if (!m_centralDir.IsValidIndex(uIndex))
return false;
return IsDirectory(m_centralDir.m_headers[uIndex]->m_uExternalAttr);
}
bool CZipArchive::ExtractFile(WORD uIndex, LPCTSTR lpszPath, DWORD nBufSize)
{
if (!nBufSize)
return false;
CFileHeader header;
GetFileInfo(header, uIndex); // to ensure that slash and oem conversions take place
CString szFile = lpszPath;
szFile.TrimRight("\\");
szFile += "\\" + GetFileDirAndName(header.m_szFileName); // just in case in the archive there are file names with drives
if (IsFileDirectory(uIndex))
{
ForceDirectory(szFile);
SetFileAttributes(szFile, header.m_uExternalAttr);
}
else
{
if (!OpenFile(uIndex))
return false;
ForceDirectory(GetFilePath(szFile));
CFile f(szFile, CFile::modeWrite | CFile::modeCreate | CFile::shareDenyWrite);
DWORD iRead;
CAutoBuffer buf(nBufSize);
do
{
iRead = ReadFile(buf, buf.GetSize());
if (iRead)
f.Write(buf, iRead);
}
while (iRead == buf.GetSize());
CloseFile(f);
}
return true;
}
void CZipArchive::SetExtraField(char *pBuf, WORD iSize)
{
if (m_iFileOpened != compress)
{
TRACE("A new file must be opened.\n");
return;
}
if (!pBuf || !iSize)
return;
CurrentFile()->m_pExtraField.Allocate(iSize);
memcpy(CurrentFile()->m_pExtraField, pBuf, iSize);
CurrentFile()->m_uExtraFieldSize = iSize;
}
bool CZipArchive::WriteNewFile(void *pBuf, DWORD iSize)
{
if (m_iFileOpened != compress)
{
TRACE("A new file must be opened.\n");
return false;
}
m_info.m_stream.next_in = (unsigned char*)pBuf;
m_info.m_stream.avail_in = iSize;
CurrentFile()->m_uCrc32 = crc32(CurrentFile()->m_uCrc32, (unsigned char*)pBuf, iSize);
while (m_info.m_stream.avail_in > 0)
{
if (m_info.m_stream.avail_out == 0)
{
m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false);
m_info.m_uComprLeft = 0;
m_info.m_stream.avail_out = m_info.m_pBuffer.GetSize();
m_info.m_stream.next_out = (unsigned char*)(char*)m_info.m_pBuffer;
}
if (CurrentFile()->m_uMethod == Z_DEFLATED)
{
DWORD uTotal = m_info.m_stream.total_out;
int err = deflate(&m_info.m_stream, Z_NO_FLUSH);
CheckForError(err);
m_info.m_uComprLeft += m_info.m_stream.total_out - uTotal;
}
else
{
DWORD uToCopy = (m_info.m_stream.avail_in < m_info.m_stream.avail_out)
? m_info.m_stream.avail_in : m_info.m_stream.avail_out;
memcpy(m_info.m_stream.next_out, m_info.m_stream.next_in, uToCopy);
m_info.m_stream.avail_in -= uToCopy;
m_info.m_stream.avail_out -= uToCopy;
m_info.m_stream.next_in += uToCopy;
m_info.m_stream.next_out += uToCopy;
m_info.m_stream.total_in += uToCopy;
m_info.m_stream.total_out += uToCopy;
m_info.m_uComprLeft += uToCopy;
}
}
return true;
}
bool CZipArchive::CloseNewFile()
{
if (m_iFileOpened != compress)
{
TRACE("A new file must be opened.\n");
return false;
}
m_info.m_stream.avail_in = 0;
int err = Z_OK;
if (CurrentFile()->m_uMethod == Z_DEFLATED)
while (err == Z_OK)
{
if (m_info.m_stream.avail_out == 0)
{
m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false);
m_info.m_uComprLeft = 0;
m_info.m_stream.avail_out = m_info.m_pBuffer.GetSize();
m_info.m_stream.next_out = (unsigned char*)(char*)m_info.m_pBuffer;
}
DWORD uTotal = m_info.m_stream.total_out;
err = deflate(&m_info.m_stream, Z_FINISH);
m_info.m_uComprLeft += m_info.m_stream.total_out - uTotal;
}
if (err == Z_STREAM_END)
err = Z_OK;
CheckForError(err);
if (m_info.m_uComprLeft > 0)
m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false);
if (CurrentFile()->m_uMethod == Z_DEFLATED)
{
err = deflateEnd(&m_info.m_stream);
CheckForError(err);
}
CurrentFile()->m_uComprSize = m_info.m_stream.total_out;
CurrentFile()->m_uUncomprSize = m_info.m_stream.total_in;
m_centralDir.CloseNewFile();
m_iFileOpened = nothing;
m_info.m_pBuffer.Release();
return true;
}
void CZipArchive::DeleteFiles(CStringArray &aNames)
{
CWordArray indexes;
for (WORD i = 0; i < GetNoEntries(); i++)
{
CFileHeader fh;
GetFileInfo(fh, i);
for (int j = 0; j < aNames.GetSize(); j++)
if (!aNames[j].CollateNoCase(fh.m_szFileName))
{
indexes.Add(i);
break;
}
}
DeleteFiles(indexes);
}
void CZipArchive::DeleteFiles(CWordArray &aIndexes)
{
if (IsClosed())
{
TRACE("ZipArchive is closed.\n");
return;
}
if (m_storage.IsSpanMode())
{
TRACE("You cannot delete files from the disk spannig archive.\n");
return;
}
if (m_iFileOpened)
{
TRACE("You cannot delete files if there is a file opened.\n");
return;
}
// sorting the index table using qsort
int uSize = aIndexes.GetSize();
if (!uSize)
return;
qsort((void*)&aIndexes[0], uSize, sizeof(WORD), CompareWords);
m_centralDir.RemoveFromDisk();
m_info.Init();
// remove in a reverse order
for (int i = uSize - 1; i >= 0; i--)
DeleteInternal(aIndexes[i]);
m_info.m_pBuffer.Release();
}
DWORD CZipArchive::RemovePackedFile(DWORD uStartOffset, DWORD uEndOffset)
{
uStartOffset += m_centralDir.m_uBytesBeforeZip;
uEndOffset += m_centralDir.m_uBytesBeforeZip;
DWORD BytesToCopy = m_storage.m_file.GetLength() - uEndOffset;
char* buf = (char*)m_info.m_pBuffer;
if (BytesToCopy > m_info.m_pBuffer.GetSize())
BytesToCopy = m_info.m_pBuffer.GetSize();
m_storage.m_file.Seek(uStartOffset, CFile::begin);
DWORD TotalWritten = 0;
DWORD size_read;
do
{
m_storage.m_file.Seek(uEndOffset + TotalWritten, CFile::begin);
size_read = m_storage.m_file.Read(buf, BytesToCopy);
if (size_read > 0)
{
m_storage.m_file.Seek(uStartOffset + TotalWritten, CFile::begin);
m_storage.m_file.Write(buf, size_read);
}
TotalWritten += size_read;
}
while (size_read == BytesToCopy);
DWORD uRemoved = (uEndOffset - uStartOffset);
m_storage.m_file.SetLength(m_storage.m_file.GetLength() - uRemoved);
return uRemoved;
}
void CZipArchive::DeleteInternal(WORD uIndex)
{
CFileHeader* pfh = m_centralDir.m_headers[uIndex];
DWORD uOtherOffsetChanged = 0;
if (uIndex == GetNoEntries() - 1) // last entry or the only one entry
m_storage.m_file.SetLength(pfh->m_uOffset + m_centralDir.m_uBytesBeforeZip);
else
uOtherOffsetChanged = RemovePackedFile(pfh->m_uOffset, m_centralDir.m_headers[uIndex + 1]->m_uOffset);
m_centralDir.RemoveFile(uIndex);
// teraz uaktualnij offsety w pozosta硑ch pozycjach central dir
// (update offsets in file headers in the central dir)
if (uOtherOffsetChanged)
for (int i = uIndex; i < GetNoEntries(); i++)
m_centralDir.m_headers[i]->m_uOffset -= uOtherOffsetChanged;
}
bool CZipArchive::IsDriveRemovable(LPCTSTR lpszFilePath)
{
return GetDriveType(GetDrive(lpszFilePath)) == DRIVE_REMOVABLE;
}
CString CZipArchive::GetDrive(LPCTSTR lpszFilePath)
{
TCHAR szDrive[_MAX_DRIVE];
_tsplitpath(lpszFilePath, szDrive, NULL, NULL, NULL);
return szDrive;
}
bool CZipArchive::AddNewFile(LPCTSTR lpszFilePath, int iLevel, unsigned long nBufSize)
{
if (!nBufSize)
return false;
CFileHeader header;
header.m_szFileName = GetFileDirAndName(lpszFilePath);
if (header.m_szFileName.IsEmpty())
return false;
if (!OpenNewFile(header, iLevel, lpszFilePath))
return false;
if (!IsDirectory(header.m_uExternalAttr))
{
CFile f;
CFileException* e = new CFileException;
BOOL bRet = f.Open(lpszFilePath, CFile::modeRead | CFile::shareDenyWrite, e);
e->Delete();
if (!bRet)
return false;
DWORD iRead;
CAutoBuffer buf(nBufSize);
do
{
iRead = f.Read(buf, nBufSize);
if (iRead)
WriteNewFile(buf, iRead);
}
while (iRead == buf.GetSize());
}
CloseNewFile();
return true;
}
int CZipArchive::GetSpanMode()
{
return m_storage.m_iSpanMode * m_storage.IsSpanMode();
}
CString CZipArchive::GetArchivePath()
{
return m_storage.m_file.GetFilePath();
}
CString CZipArchive::GetGlobalComment()
{
if (IsClosed())
{
TRACE("ZipArchive is closed.\n");
return "";
}
return m_centralDir.m_szComment;
}
bool CZipArchive::SetGlobalComment(const CString &szComment)
{
if (IsClosed())
{
TRACE("ZipArchive is closed.\n");
return false;
}
if (m_storage.IsSpanMode() == -1)
{
TRACE("You cannot modify the global comment of the existing disk spanning archive.\n");
return false;
}
m_centralDir.m_szComment = szComment;
m_centralDir.RemoveFromDisk();
return true;
}
bool CZipArchive::IsDirectory(DWORD uAttr)
{
return (uAttr & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
int CZipArchive::GetCurrentDisk()
{
return m_storage.GetCurrentDisk();
}
bool CZipArchive::SetFileComment(WORD uIndex, CString szComment)
{
if (IsClosed())
{
TRACE("ZipArchive is closed.\n");
return false;
}
if (m_storage.IsSpanMode() == -1)
{
TRACE("You cannot modify the global comment of the existing disk spanning archive.\n");
return false;
}
if (!m_centralDir.IsValidIndex(uIndex))
return false;
m_centralDir.m_headers[uIndex]->m_szComment = szComment;
m_centralDir.m_headers[uIndex]->ValidateComment();
m_centralDir.RemoveFromDisk();
return true;
}
int CZipArchive::CompareWords(const void *pArg1, const void *pArg2)
{
WORD w1 = *(WORD*)pArg1;
WORD w2 = *(WORD*)pArg2;
return w1 == w2 ? 0 :(w1 < w2 ? - 1 : 1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -