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

📄 ziparchive.cpp

📁 ZIP压缩代码:基于开源ZipArchive和zlib
💻 CPP
📖 第 1 页 / 共 5 页
字号:

bool CZipArchive::OpenNewFile(CZipFileHeader & header,     
                              int iLevel,                  
                              LPCTSTR lpszFilePath, DWORD uInternal)
{
	if (IsClosed())
	{
		TRACE(_T("%s(%i) : ZipArchive is closed.\n"),__FILE__,__LINE__);
		return false;
	}
	
	if (m_iFileOpened)
	{
		TRACE(_T("%s(%i) : A file already opened.\n"),__FILE__,__LINE__);
		return false;
	}
	
	if (m_storage.IsSpanMode() == -1)
	{
		TRACE(_T("%s(%i) : You cannot add files to the existing disk spannig archive.\n"),__FILE__,__LINE__);
		return false;
	}
	
	if (GetCount() ==(WORD)USHRT_MAX)
	{
		TRACE(_T("%s(%i) : Maximum file count inside archive reached.\n"),__FILE__,__LINE__);
		return false;
	}
	
	DWORD uAttr = 0; // ..compiler
	time_t ttime;
	if (lpszFilePath)
	{

		if (!ZipPlatform::GetFileAttr(lpszFilePath, uAttr))
			// do not continue - if the file was a directory then not recognizing it will cause 
			// serious errors (need uAttr to recognize it)
			return false;
		if (!ZipPlatform::GetFileModTime(lpszFilePath, ttime))
			ttime = time(NULL);
	}

	m_info.Init();
	
	
	if (lpszFilePath)
	{
		header.SetTime(ttime);
		SetFileHeaderAttr(header, uAttr); // set system compatibility as well
	}
	else
		header.SetSystemCompatibility(m_iArchiveSystCompatib);

	CZipString szFileName = header.GetFileName();
	

	bool bIsDirectory = header.IsDirectory();
	if (bIsDirectory)
	{
		int iNameLen = szFileName.GetLength();		
		if (!iNameLen || !CZipPathComponent::IsSeparator(szFileName[iNameLen-1]))
		{
			szFileName += CZipPathComponent::m_cSeparator;
			header.SetFileName(szFileName);
		}
	}

	if (szFileName.IsEmpty())
	{
		szFileName.Format(_T("file%i"), GetCount());
		header.SetFileName(szFileName);
	}
	
	// make sure that all slashes are correct (as the current system default)
	// because AddNewFile calls InsertFindFastElement if necessary and 
	// the find array keeps all the files already converted to the current system standards
	// we do not perform Oem->Ansi here, because who would pass oem values here?
	// 
	ZipCompatibility::SlashBackslashChg(header.m_pszFileName, true);

	bool bEncrypted = m_pszPassword.GetSize() != 0;

#ifdef _DEBUG
	if (bIsDirectory && bEncrypted)
	TRACE(_T("%s(%i) : Encrypting a directory. It's pointless.\n\
	Clear the password before adding a directory.\n"),__FILE__,__LINE__);
#endif
		

	
	int iReplaceIndex = -1;
	bool bReplace = (iLevel & 0xffff) == ZIP_COMPR_REPL_SIGN;
	if (bReplace)
	{
		int iMask = ZIP_COMPR_REPL_MASK;
		iReplaceIndex = (iLevel & iMask) >> 16;
		iLevel = (char)(iLevel & ~iMask);
		ASSERT(iLevel == 0);
	}
	else
		uInternal = 0;

	if (iLevel < -1 || iLevel > 9)
		iLevel = -1;

	if (!header.PrepareData(iLevel, m_storage.IsSpanMode() == 1, bEncrypted))
		ThrowError(CZipException::tooLongFileName);

	if (bReplace)
	{
		uInternal += header.GetSize(true);
		if (header.IsEncrypted())
			uInternal += ZIPARCHIVE_ENCR_HEADER_LEN;
		if (header.IsDataDescr())
			uInternal += ZIPARCHIVE_DATADESCRIPTOR_LEN + 4; // CZipCentralDir::CloseNewFile		
	}
	m_centralDir.AddNewFile(header, iReplaceIndex);
	if (bReplace)
		MakeSpaceForReplace(iReplaceIndex, uInternal, szFileName);

	// this ensures the conversion will take place anyway (must take because we are going 
	// 	to write the local header in a moment
	m_centralDir.ConvertFileName(false, m_centralDir.m_bConvertAfterOpen);

	CurrentFile()->WriteLocal(m_storage);

	// we have written the local header, but if we keep filenames not converted
	// in memory , we have to restore the non-converted value
	if (m_centralDir.m_bConvertAfterOpen)
		CurrentFile()->SetFileName(szFileName);

	if (bEncrypted)
	{
		CZipAutoBuffer buf(ZIPARCHIVE_ENCR_HEADER_LEN);
		// use pseudo-crc since we don't know it yet
		CryptCryptHeader((long)header.m_uModTime << 16, buf);
		m_storage.Write(buf, ZIPARCHIVE_ENCR_HEADER_LEN, false);
	}
	
	
	m_info.m_uComprLeft = 0;
    m_info.m_stream.avail_in = (uInt)0;
    m_info.m_stream.avail_out = (uInt)m_info.m_pBuffer.GetSize();
    m_info.m_stream.next_out = (Bytef*)(char*)m_info.m_pBuffer;
    m_info.m_stream.total_in = 0;
    m_info.m_stream.total_out = 0;
	
	if (bIsDirectory && (CurrentFile()->m_uMethod != 0))
		CurrentFile()->m_uMethod = 0;
	
	if (CurrentFile()->m_uMethod == Z_DEFLATED)
    {
        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 true;
}


bool CZipArchive::ExtractFile(WORD uIndex,                  
                              LPCTSTR lpszPath,             
                              bool bFullPath,              
                              LPCTSTR lpszNewName,          
                              DWORD nBufSize)
{
	
	if (!nBufSize && !lpszPath)
		return false;
	
	CZipFileHeader header;
	GetFileInfo(header, uIndex); // to ensure that slash and oem conversions take place
	CZipString szFileNameInZip = (LPCTSTR)header.GetFileName();
	CZipString szFile = PredictExtractedFileName(szFileNameInZip, lpszPath, bFullPath, lpszNewName);
	CZipActionCallback* pCallback = GetCallback(cbExtract);
	if (pCallback)
		pCallback->Init(szFileNameInZip, szFile);
	

	if (header.IsDirectory())
	{
		if (pCallback)
			pCallback->SetTotal(0); // in case of calling LeftToDo afterwards

		ZipPlatform::ForceDirectory(szFile);
		ZipPlatform::SetFileAttr(szFile, header.GetSystemAttr());

		if (pCallback)
			pCallback->CallbackEnd();
		return true;
	}
	else
	{
		if (pCallback)
			pCallback->SetTotal(header.m_uUncomprSize);

		if (!OpenFile(uIndex))
			return false;

		CZipPathComponent zpc(szFile);
		ZipPlatform::ForceDirectory(zpc.GetFilePath());
		CZipFile f(szFile, CZipFile::modeWrite | 
			CZipFile::modeCreate | CZipFile::shareDenyWrite);
		DWORD iRead;
		CZipAutoBuffer buf(nBufSize);
		int iAborted = 0;
		do
		{
			iRead = ReadFile(buf, buf.GetSize());
			if (iRead)
			{	
				f.Write(buf, iRead);
				if (pCallback)
					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(f) == 1;
		if (!bRet && iAborted == CZipException::abortedSafely)
			iAborted = CZipException::abortedAction; // sorry, finished, but not successfull

		if (pCallback)
			pCallback->CallbackEnd();

		if (iAborted)
			CZipException::Throw(iAborted, szFile); // throw to distuingiush from other return codes
		return bRet;

	}	
}

bool CZipArchive::ExtractFile(WORD uIndex,                  
                              CZipMemFile& mf,
                              DWORD nBufSize)
{
	if (!nBufSize)
		return false;
	
	CZipFileHeader header;
	GetFileInfo(header, uIndex); // to ensure that slash and oem conversions take place
	CZipActionCallback* pCallback = GetCallback(cbExtract);
	if (pCallback)
	{
		pCallback->Init(header.GetFileName());
		pCallback->SetTotal(header.m_uUncomprSize);
	}

	if (header.IsDirectory() || !OpenFile(uIndex))
		return false;

	
	

	CZipAutoBuffer buf(nBufSize);
	mf.SeekToEnd();
	DWORD iRead;
	int iAborted = 0;
	do
	{
		iRead = ReadFile(buf, buf.GetSize());
		if (iRead)
		{	
			mf.Write(buf, iRead);
			if (pCallback)
				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;
}


void CZipArchive::SetExtraField(const char *pBuf, WORD iSize)
{
	if (m_iFileOpened != compress)
	{
		TRACE(_T("%s(%i) : A new file must be opened.\n"),__FILE__,__LINE__);
		return;
	}
	if (!pBuf || !iSize)
		return;
	
	CurrentFile()->m_pExtraField.Allocate(iSize);
	memcpy(CurrentFile()->m_pExtraField, pBuf, iSize);
}

bool CZipArchive::WriteNewFile(const void *pBuf, DWORD iSize)
{
	if (m_iFileOpened != compress)
	{
		TRACE(_T("%s(%i) : A new file must be opened.\n"),__FILE__,__LINE__);
		return false;
	}
	
	
    m_info.m_stream.next_in = (Bytef*)pBuf;
    m_info.m_stream.avail_in = iSize;
    CurrentFile()->m_uCrc32 = crc32(CurrentFile()->m_uCrc32, (Bytef*)pBuf, iSize);
	
	
    while (m_info.m_stream.avail_in > 0)
    {
        if (m_info.m_stream.avail_out == 0)
        {
			CryptEncodeBuffer();
			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 = (Bytef*)(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(bool bAfterException)
{
	if (m_iFileOpened != compress)
	{
		TRACE(_T("%s(%i) : A new file must be opened.\n"),__FILE__,__LINE__);
		return false;
	}
	
    m_info.m_stream.avail_in = 0;
    if (!bAfterException)
	{
		int err = Z_OK;
		if (CurrentFile()->m_uMethod == Z_DEFLATED)
			while (err == Z_OK)
			{
				if (m_info.m_stream.avail_out == 0)
				{
					CryptEncodeBuffer();
					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 = (Bytef*)(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)
		{
			CryptEncodeBuffer();
			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);
		}
		
		
		// it may be increased by the encrypted header size
		CurrentFile()->m_uComprSize += m_info.m_stream.total_out;
		CurrentFile()->m_uUncomprSize = m_info.m_stream.total_in;
		
		m_centralDir.CloseNewFile();
	}
	else
		m_centralDir.m_pOpenedFile = NULL;

	m_iFileOpened = nothing;
	m_info.ReleaseBuf();
	EmptyPtrList();

	if (m_bAutoFlush && !bAfterException)
		Flush();

	return true;
}

void CZipArchive::DeleteFile(WORD uIndex)
{
	CZipWordArray indexes;
	indexes.Add(uIndex);
	DeleteFiles(indexes);
}

void CZipArchive::GetIndexes(const CZipStringArray &aNames, CZipWordArray& aIndexes)
{
	if (IsClosed())
	{
		TRACE(_T("%s(%i) : ZipArchive is closed.\n"),__FILE__,__LINE__);
		return;
	}
	int iSize = aNames.GetSize();
	for (WORD i = 0; i < iSize; i++)
	{
		int idx = FindFile(aNames[i], ffDefault, false);
		if (idx != -1)
			aIndexes.Add((WORD)idx);
	}	
}

void CZipArchive::DeleteFiles(const CZipStringArray &aNames)
{
	CZipWordArray indexes;
	GetIndexes(aNames, indexes);
	DeleteFiles(indexes);
}


void CZipArchive::DeleteFiles(CZipWordArray &aIndexes)
{
	if (IsClosed())
	{
		TRACE(_T("%s(%i) : ZipArchive is closed.\n"),__FILE__,__LINE__);
		return;
	}
	
	if (m_storage.IsSpanMode())
	{
		TRACE(_T("%s(%i) : You cannot delete files from the disk spannig archive.\n"),__FILE__,__LINE__);
		return;
	}
	
	if (m_iFileOpened)
	{
		TRACE(_T("%s(%i) : You cannot delete files if there is a file opened.\n"),__FILE__,__LINE__);
		return;
	}
	
	CZipActionCallback* pCallback = GetCallback(cbDeleteCnt);
	if (pCallback)
		pCallback->Init();

	int uSize = aIndexes.GetSize();
	if (!uSize)
	{
		TRACE(_T("%s(%i) : The indekses array is empty.\n"),__FILE__,__LINE__);
		return;
	}

	// remove all - that's easy so don't waste the time
	if (uSize == GetCount())
	{
		pCallback = GetCallback(cbDelete);
		if (pCallback)
		{
			// do it right and sent the notification
			pCallback->Init();
			pCallback->SetTotal(uSize);
		}

		m_centralDir.RemoveFromDisk();
		m_storage.m_pFile->SetLength(m_centralDir.GetBytesBefore());
		m_centralDir.RemoveAll();
		if (m_bAutoFlush)

⌨️ 快捷键说明

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