⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ziparchive.cpp

📁 ZIP压缩代码:基于开源ZipArchive和zlib
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	WideToSingle(lpszComment, m_centralDir.m_pszComment);
	m_centralDir.RemoveFromDisk();
	if (m_bAutoFlush)
		Flush();

	return true;
}



int CZipArchive::GetCurrentDisk() const 
{
	return m_storage.GetCurrentDisk() + 1;
}

bool CZipArchive::SetFileComment(WORD uIndex, LPCTSTR lpszComment)
{
	if (IsClosed())
	{
		TRACE(_T("%s(%i) : ZipArchive is closed.\n"),__FILE__,__LINE__);
		return false;
	}
	if (m_storage.IsSpanMode() == -1)
	{
		TRACE(_T("%s(%i) : You cannot modify the file comment in the existing disk spanning archive.\n"),__FILE__,__LINE__);
		return false;
	}
	
	if (!m_centralDir.IsValidIndex(uIndex))
	{
		ASSERT(FALSE);
		return false;
	}
	m_centralDir[uIndex]->SetComment(lpszComment);
	m_centralDir.RemoveFromDisk();
	if (m_bAutoFlush)
		Flush();
	return true;
}


void CZipArchive::CryptInitKeys()
{
	ASSERT(m_pszPassword.GetSize());
	m_keys[0] = 305419896L;
	m_keys[1] = 591751049L;
	m_keys[2] = 878082192L;
	for (DWORD i = 0; i < m_pszPassword.GetSize(); i++)
		CryptUpdateKeys(m_pszPassword[i]);
}

void CZipArchive::CryptUpdateKeys(char c)
{
	
	m_keys[0] = CryptCRC32(m_keys[0], c);
	m_keys[1] += m_keys[0] & 0xff;
	m_keys[1] = m_keys[1] * 134775813L + 1;
	c = char(m_keys[1] >> 24);
	m_keys[2] = CryptCRC32(m_keys[2], c);
}

bool CZipArchive::CryptCheck()
{
	CZipAutoBuffer buf(ZIPARCHIVE_ENCR_HEADER_LEN);
	m_storage.Read(buf, ZIPARCHIVE_ENCR_HEADER_LEN, false);
	BYTE b = 0;
	for (int i = 0; i < ZIPARCHIVE_ENCR_HEADER_LEN; i++)
	{
		b = buf[i]; // only temporary
		CryptDecode((char&)b);
	}
	// check the last byte
	return CurrentFile()->IsDataDescr() ?
		(BYTE(CurrentFile()->m_uModTime >> 8) == b) : (BYTE(CurrentFile()->m_uCrc32 >> 24) == b);
}

char CZipArchive::CryptDecryptByte()
{
	int temp = (m_keys[2] & 0xffff) | 2;
	return (char)(((temp * (temp ^ 1)) >> 8) & 0xff);
}

void CZipArchive::CryptDecode(char &c)
{
	c ^= CryptDecryptByte();
	CryptUpdateKeys(c);
}

bool CZipArchive::SetPassword(LPCTSTR lpszPassword)
{
	if (m_iFileOpened != nothing)
	{
		TRACE(_T("%s(%i) : You cannot change the password when the file is opened.\n"),__FILE__,__LINE__);
		return false; // it's important not to change the password when the file inside archive is opened
	}
	if (IsClosed())
	{
		TRACE(_T("%s(%i) : Setting the password for a closed archive has no effect.\n"),__FILE__,__LINE__);
	}
	if (lpszPassword)
	{
		int iLen = WideToSingle(lpszPassword, m_pszPassword);
		if (iLen == -1)
			return false;
		for (size_t i = 0; (int)i < iLen; i++)
			if (m_pszPassword[i] <= 0)
			{
				m_pszPassword.Release();
				TRACE(_T("%s(%i) : The password contains forbidden characters. Password cleared.\n"),__FILE__,__LINE__);
				return false;
			}
	}
	else
		m_pszPassword.Release();
	return true;
}

CZipString CZipArchive::GetPassword()const 
{
	CZipString temp;
	CZipArchive::SingleToWide(m_pszPassword, temp);
	return temp;
}

DWORD CZipArchive::CryptCRC32(DWORD l, char c)
{
	const DWORD *CRC_TABLE = get_crc_table();
	return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
}

void CZipArchive::CryptCryptHeader(long iCrc, CZipAutoBuffer &buf)
{
	CryptInitKeys();
	srand(UINT(time(NULL)));
	// genereate pseudo-random sequence
	char c;
	for (int i = 0; i < ZIPARCHIVE_ENCR_HEADER_LEN - 2; i++)
	{
		int t1 = rand();
		c = (char)(t1 >> 6);
		if (!c)
			c = (char)t1;
		CryptEncode(c);
		buf[i] = c;

	}
	c = (char)((iCrc >> 16) & 0xff);
	CryptEncode(c);
	buf[ZIPARCHIVE_ENCR_HEADER_LEN - 2] = c;
	c = (char)((iCrc >> 24) & 0xff);
	CryptEncode(c);
	buf[ZIPARCHIVE_ENCR_HEADER_LEN - 1] = c;
}

void CZipArchive::CryptEncode(char &c)
{
	char t = CryptDecryptByte();
	CryptUpdateKeys(c);
	c ^= t;
}

void CZipArchive::CryptEncodeBuffer()
{
	if (CurrentFile()->IsEncrypted())
		for (DWORD i = 0; i < m_info.m_uComprLeft; i++)
			CryptEncode(m_info.m_pBuffer[i]);
}

void CZipArchive::CloseFileAfterTestFailed()
{
	if (m_iFileOpened != extract)
	{
		TRACE(_T("%s(%i) : No file opened.\n"),__FILE__,__LINE__);
		return;
	}
	m_info.ReleaseBuf();
	m_centralDir.Clear(false);
	m_iFileOpened = nothing;
}

bool CZipArchive::TestFile(WORD uIndex, DWORD uBufSize)
{
	if (m_storage.IsSpanMode() == 1)
	{
		TRACE(_T("%s(%i) : You cannot test the spanning archive in creation.\n"),__FILE__,__LINE__);
		return false;
	}
	if (!uBufSize)
		return false;
	
	CZipFileHeader* pHeader = m_centralDir[uIndex];
	CZipActionCallback* pCallback = GetCallback(cbTest);
	if (pCallback)
	{
		pCallback->Init(m_centralDir.GetProperHeaderFileName(pHeader));
	}

	if (pHeader->IsDirectory())
	{
		if (pCallback)
			pCallback->SetTotal(0);

		// we do not test whether the password for the encrypted directory
		// is correct, since it seems to be senseless (anyway password 
		// encrypted directories should be avoided - it adds 12 bytes)
		DWORD iSize = pHeader->m_uComprSize;
		if ((iSize != 0 || iSize != pHeader->m_uUncomprSize)
			// different treating compressed directories
			&& !(pHeader->IsEncrypted() && iSize == 12 && !pHeader->m_uUncomprSize))
			CZipException::Throw(CZipException::dirWithSize);

		if (pCallback)
			pCallback->CallbackEnd();

		return true;
	}
	else
	{
		try
		{			
			if (pCallback)
				pCallback->SetTotal(pHeader->m_uUncomprSize);
			
			if (!OpenFile(uIndex))
				return false;
			CZipAutoBuffer buf(uBufSize);
			DWORD iRead;
			int iAborted = 0;
			do
			{	
				iRead = ReadFile(buf, buf.GetSize());
				if (pCallback && iRead)
					if (!(*pCallback)(iRead))
					{
						if (iRead == buf.GetSize() && ReadFile(buf, 1) != 0) // test one byte if there is something left
							iAborted = CZipException::abortedAction; 
						else
							iAborted = CZipException::abortedSafely; // we did it!
						break;
					}
			}
			while (iRead == buf.GetSize());
			bool bRet = CloseFile() != -1;
			if (!bRet && iAborted == CZipException::abortedSafely)
				iAborted = CZipException::abortedAction; // sorry, finished, but not successfull

			if (pCallback)
				pCallback->CallbackEnd();

			if (iAborted)
				CZipException::Throw(iAborted); // throw to distuingiush from other return codes
			return bRet;
		}
		catch(...)
		{
			CloseFileAfterTestFailed();
			throw;
		}
	}
}

int CZipArchive::WideToSingle(LPCTSTR lpWide, CZipAutoBuffer &szSingle)
{
#ifdef _UNICODE
	return ZipPlatform::WideToSingle(lpWide, szSingle);
#else
	
	size_t iLen = strlen(lpWide);
	// if not UNICODE just copy
	// 	iLen does not include the NULL character
	szSingle.Allocate(iLen);
	memcpy(szSingle, lpWide, iLen);
	return iLen;
#endif

}

int CZipArchive::SingleToWide(const CZipAutoBuffer &szSingle, CZipString& szWide)
{
	
#ifdef _UNICODE	
	return ZipPlatform::SingleToWide(szSingle, szWide);
#else // if not UNICODE just copy
	int singleLen = szSingle.GetSize();
	// 	iLen does not include the NULL character
	memcpy(szWide.GetBuffer(singleLen),szSingle.GetBuffer(), singleLen);
	szWide.ReleaseBuffer(singleLen);
	return singleLen;
#endif
}

void CZipArchive::CryptDecodeBuffer(DWORD uCount)
{
	if (CurrentFile()->IsEncrypted())
		for (DWORD i = 0; i < uCount; i++)
			CryptDecode(m_info.m_pBuffer[i]);
}

void CZipArchive::EmptyPtrList()
{
	if (m_list.GetCount())
	{
		// if some memory hasn't been freed due to an error in zlib, so free it now
		CZipPtrListIter iter = m_list.GetHeadPosition();
		while (m_list.IteratorValid(iter))
			delete[] (char*) m_list.GetNext(iter);
	}
	m_list.RemoveAll();
}



void CZipArchive::SetFileHeaderAttr(CZipFileHeader& header, DWORD uAttr)
{
	header.SetSystemCompatibility(m_iArchiveSystCompatib);
	header.SetSystemAttr(uAttr);
}

void CZipArchive::EnableFindFast(bool bEnable)
{
	if (IsClosed())
	{
		TRACE(_T("%s(%i) : Set it after opening the archive.\n"),__FILE__,__LINE__);
		return;
	}
	m_centralDir.EnableFindFast(bEnable, m_bCaseSensitive);

}

bool CZipArchive::SetSystemCompatibility(int iSystemComp)
{
	if (IsClosed())
	{
		TRACE(_T("%s(%i) : Set it after opening the archive.\n"),__FILE__,__LINE__);
		return false;
	}

	if (m_iFileOpened == compress)
	{
		TRACE(_T("%s(%i) : Set it before opening a file inside archive.\n"),__FILE__,__LINE__);
		return false;
	}

	if (!ZipCompatibility::IsPlatformSupported(iSystemComp))
		return false;
	m_iArchiveSystCompatib = iSystemComp;
	return true;
}

void CZipArchive::SetRootPath(LPCTSTR szPath)
{
	if (IsClosed())
	{
		TRACE(_T("%s(%i) : Set it after opening the archive.\n"),__FILE__,__LINE__);
		return;
	}

	if (m_iFileOpened != nothing)
	{
		TRACE(_T("%s(%i) : Set it before opening a file inside archive.\n"),__FILE__,__LINE__);
		return;
	}

	if (szPath)
	{
		m_szRootPath = szPath;
		CZipPathComponent::RemoveSeparators(m_szRootPath);
	}
	else
		m_szRootPath.Empty();
}

CZipString CZipArchive::TrimRootPath(CZipPathComponent &zpc)const 
{
	if (m_szRootPath.IsEmpty())
		return zpc.GetFileName();
	CZipString szPath = zpc.GetFullPath();
	return RemovePathBeginning(m_szRootPath, szPath, m_pZipCompare) ? szPath : zpc.GetFileName();
}

bool CZipArchive::RemovePathBeginning(LPCTSTR lpszBeginning, CZipString& szPath, ZIPSTRINGCOMPARE pCompareFunction)
{
	CZipString szBeginning(lpszBeginning);
	CZipPathComponent::RemoveSeparators(szBeginning);
	int iRootPathLength = szBeginning.GetLength();
	if (iRootPathLength && szPath.GetLength() >= iRootPathLength &&
		(szPath.Left(iRootPathLength).*pCompareFunction)(szBeginning) == 0)
	{		
		// the beginning is the same
		if (szPath.GetLength() == iRootPathLength)
		{
			szPath.Empty();
			return true;
		}
		// is the end of m_szPathRoot only a beginning of a directory name? 
		// check for a separator
		// we know the length is larger, so we can write:
		if (CZipPathComponent::IsSeparator(szPath[iRootPathLength]))
		{			
			szPath = szPath.Mid(iRootPathLength);
			CZipPathComponent::RemoveSeparatorsLeft(szPath);
			return true;
		}
	}
	return false;
}

void CZipArchive::SetTempPath(LPCTSTR lpszPath, bool bForce)
{
	m_szTempPath = lpszPath;
	if (lpszPath && bForce)
		ZipPlatform::ForceDirectory(lpszPath);
	CZipPathComponent::RemoveSeparators(m_szTempPath);
}

CZipString CZipArchive::PredictFileNameInZip(LPCTSTR lpszFilePath, 
						 bool bFullPath, int iWhat, bool bExactly)const 
{
	CZipString sz = lpszFilePath;
	if (sz.IsEmpty())
		return _T("");
	bool bAppend;
	switch (iWhat)
	{
	case prFile:
		bAppend = false;
		break;
	case prDir:
		bAppend = true;
		break;
	default:
		bAppend = CZipPathComponent::IsSeparator(sz[sz.GetLength() - 1]);
	}
	
	// remove for CZipPathComponent treating last name as a file even if dir
	CZipPathComponent::RemoveSeparators(sz);
	CZipPathComponent zpc(sz);

	if (bFullPath)
	{
		if (m_bRemoveDriveLetter)
			sz = zpc.GetNoDrive();
	}
	else
		sz = TrimRootPath(zpc);

	if (bAppend && !sz.IsEmpty())
		CZipPathComponent::AppendSeparator(sz);
	CZipFileHeader fh; // create a temporary object to convert 
	fh.SetFileName(sz);
	if (bExactly)
	{
		fh.SetSystemCompatibility(m_iArchiveSystCompatib);
		ZipCompatibility::FileNameUpdate(fh, false);
	}
	else
	{
		fh.SetSystemCompatibility(-1); // non existing system to prevent ansi oem conversion
		ZipCompatibility::FileNameUpdate(fh, true);// update only path separators
	}

	return fh.GetFileName();
}

CZipString CZipArchive::PredictExtractedFileName(LPCTSTR lpszFileNameInZip, LPCTSTR lpszPath, bool bFullPath, LPCTSTR lpszNewName)const 
{
	CZipString szFile = lpszPath;
	CZipString sz = lpszNewName ? lpszNewName : lpszFileNameInZip;
	if (sz.IsEmpty())
		return szFile;
	if (!szFile.IsEmpty())
		CZipPathComponent::AppendSeparator(szFile);
	
	
	// remove for CZipPathComponent treating last name as a file even if dir
	CZipPathComponent::RemoveSeparators(sz);
	CZipPathComponent zpc(sz);
	szFile += bFullPath ? (m_bRemoveDriveLetter ? zpc.GetNoDrive() : sz) 
						  : TrimRootPath(zpc);	
	return szFile;
}


void CZipArchive::SetAutoFlush(bool bAutoFlush)
{
	if (IsClosed())
	{
		TRACE(_T("%s(%i) : ZipArchive not yet opened.\n"),__FILE__,__LINE__);
		return;
	}
	if (m_storage.IsSpanMode() != 0)
	{
		TRACE(_T("%s(%i) : Cannot set auto-flush for the disk spanning archive.\n"),__FILE__,__LINE__);
		return;
	}
	m_bAutoFlush = bAutoFlush;
}

void CZipArchive::Flush()
{
	if (IsClosed())
	{
		TRACE(_T("%s(%i) : ZipArchive not yet opened.\n"),__FILE__,__LINE__);
		return;
	}

	if (m_storage.IsSpanMode() < 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -