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

📄 zipbuilder.cpp

📁 zip算法的源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	delete[] Buffer;
  if(FInFileHandle != -1) FileClose(FInFileHandle);
	if(In2FileHandle != -1) FileClose(In2FileHandle);
  if(FOutFileHandle != -1)
  {
		FileSetDate(FOutFileHandle, FDateStamp);
		FileClose(FOutFileHandle);
		if(Result) DeleteFile(OutFilePath);		// An error somewhere, OutFile is not reliable.
		else
		{
			EraseFile(DestZipBuilder->FZipFileName, DestZipBuilder->HowToDelete);
			if(!RenameFile(OutFilePath, DestZipBuilder->FZipFileName))
				EraseFile(OutFilePath, DestZipBuilder->HowToDelete);
		}
	}
	DestZipBuilder->List();	// Update the old(possibly some entries were added temporarily) or new destination.
	StopWaitCursor();
  FZipBusy = false;
	return Result;
}
// TZipBuilder::CopyZippedFiles

// TZipBuilder::NameOfPart-----------------------------------------------------
//1.73 18 September 2003 RA accept file extension .zip for compat as valid last part
//1.73 16 September 2003 RP new function to avoid negative part numbers
#ifndef NO_SPAN
AnsiString __fastcall TZipBuilder::NameOfPart(AnsiString fn, bool compat)
{
  TSearchRec SRec;
  AnsiString Result = "";
  int n, r;
  if(compat && (r = FindFirst(fn + ".zip", faAnyFile, SRec)) == 0)
     Result = SRec.Name;   // file with .zip extension is alst part for compat
  else
  {
    if(compat) r = FindFirst(fn + ".z??", faAnyFile, SRec);
    else  r = FindFirst(fn + "???.zip", faAnyFile, SRec);
    while(r == 0)
    {
      if(compat) n = StrToIntDef(SRec.Name.SubString(SRec.Name.Length()-1,2), 0);
      else n = StrToIntDef(SRec.Name.SubString(SRec.Name.Length()-6,3), 0);
      if(n > 0)
      {
        Result = SRec.Name; // possible name
        break;
      }
      r = FindNext(SRec);
    }
  }
  FindClose(SRec);
  return Result;
}
#endif
// RTZipBuilder::NameOfPart

// TZipBuilder::ExtExtract------------------------------------------------------
// 1.73 17 September 2003 RA avoid same exception shown twice
// 1.73 6 September 2003 RA throw exception if dll returns negative value
// 1.73 4 August 2003 RA removed loading of dll will be done in Exec
// 1.73 (22 July 2003) RA exception handling for EZipMaster + fUnzBusy := False when dll load error
// 1.73 (16 July 2003) RA catch and display dll load errors
// 1.73 (18 June 2003) RA bug fix UnZipParms->fExtractDir when FExtrBaseDir not used
// 1.73 (14 June 2003) RP new dll handling
// 1.73 (22 May 2003) RA use of DelimitPah
// 1.73 (20 May 2003 RA added ForceDirectories and ExtrForceDir option
// UseStream = 0 ==> Extract file from zip archive file.
// UseStream = 1 ==> Extract stream from zip archive file.
// UseStream = 2 ==> Extract (zipped) stream from another stream.
void __fastcall TZipBuilder::ExtExtract(int UseStream, TMemoryStream *MemStream)
{
	String TmpZipName;
	int	 OldPRC = FPasswordReqCount;

	FSuccessCnt = FErrCode = 0;
	FMessage = "";

  if(UseStream < 2)
  {
    if(FZipFileName == "")
    {
      ShowZipMessage(GE_NoZipSpecified, "");
      return;
    }
    if(FZipContents->Count == 0) _List(); // List was probably aborted try again
    if(FZipContents->Count == 0)
    {
      if(!FErrCode) ShowZipMessage(DS_FileOpen, "");
      return;
    }
  }
   // Make sure we can't get back in here while work is going on
  if(FUnzBusy) return;
	// We have to be carefull doing an unattended Extract when a password is needed
	// for some file in the archive.
	if(FUnattended && FPassword == "" && !FOnPasswordError)
	{
		FPasswordReqCount = 0;
		ShowZipMessage(EX_UnAttPassword, "");
	}
	FCancel  = false;
  FUnzBusy = true;

	// We do a check if we need UnSpanning first, this depends on
	// The number of the disk the EOC record was found on. ( provided by List() )
	// If we have a spanned set consisting of only one disk we don't use ReadSpan().
	if(FTotalDisks)
	{
#ifdef NO_SPAN
		FUnzBusy = false;
		ShowZipMessage(DS_NoDiskSpan, "");
		return;
#else
		if(FTempDir == "")
		{
			char NewName[MAX_PATH];
			::GetTempPath(MAX_PATH, NewName);
			TmpZipName = NewName;
		}
		else TmpZipName = DelimitPath(FTempDir, false);
		if(ReadSpan(FZipFileName, TmpZipName))
		{
      FUnzBusy = false;
			return;
		}
		// We returned without an error, now  TmpZipName contains a real name.
#endif
	}
	else TmpZipName = FZipFileName;
  try
  {
  	try   // Pass in a ptr to parms.
  	{
      UnZipParms = new UnzipDLL::UnZipParms;
  		memset(UnZipParms, 0, sizeof(*UnZipParms));
      SetUnZipSwitches(TmpZipName);
      UnZipParms->fExtractDir = new char[MAX_PATH + 1];
      GetCurrentDirectory(MAX_PATH, UnZipParms->fExtractDir);
      if(!UseStream && (FExtrBaseDir != ""))
      {
        StrLCopy(UnZipParms->fExtractDir, FExtrBaseDir.c_str(), MAX_PATH);
        SetCurrentDir(FExtrBaseDir);
        if(!(DirExists(FExtrBaseDir) ||
            (FExtrOptions.Contains(ExtrForceDirs) && ForceDirectories(FExtrBaseDir))))
           throw EZipBuilder(EX_NoExtrDir,FExtrBaseDir);
      }
  		UnZipParms->fUFDS = new UnzFileData[FFSpecArgs->Count];
  		memset(UnZipParms->fUFDS, 0, sizeof(UnzFileData) * FFSpecArgs->Count);
  		for(int i = 0; i < FFSpecArgs->Count; i++)
  		{
  			UnZipParms->fUFDS[i].fFileSpec = new char[FFSpecArgs->Strings[i].Length() + 1];
  			StrPLCopy(UnZipParms->fUFDS[i].fFileSpec, FFSpecArgs->Strings[i], FFSpecArgs->Strings[i].Length() + 1);
  		}
  		UnZipParms->fArgc = FFSpecArgs->Count;
#ifndef NO_STREAM
  		if(UseStream == 1) for(int i = 0; i < Count; i++)
  		{	// Find the wanted file in the ZipDirEntry list.
  			ZipDirEntry *zde = (ZipDirEntry *)ZipContents->Items[i];
  			if(!AnsiStrIComp(FFSpecArgs->Strings[0].c_str(), zde->FileName.c_str()))
  			{	// Found?
  				FZipStream->SetSize(STRMSIZ(zde->UncompressedSize));//Changed R. Peters for BCB6
  				UnZipParms->fUseOutStream  = true;
  				UnZipParms->fOutStream     = FZipStream->Memory;
  				UnZipParms->fOutStreamSize = zde->UncompressedSize;
  				UnZipParms->fArgc          = 1;
  				break;
  			}
  		}
  		if(UseStream == 2)
  		{
  			UnZipParms->fUseInStream	  = true;
  			UnZipParms->fInStream		  = MemStream->Memory;
  			UnZipParms->fInStreamSize  = MemStream->Size;
  			UnZipParms->fUseOutStream  = true;
  			UnZipParms->fOutStream     = FZipStream->Memory;
  			UnZipParms->fOutStreamSize = FZipStream->Size;
  		}
#endif
  		UnZipParms->fSeven = 7;
  	  	// fArgc is now the no. of filespecs we want extracted.
  	  if(!UseStream || (UseStream && UnZipParms->fUseOutStream))
  			  FSuccessCnt = fUnzDll->Exec(UnZipParms, Min_UnzDll_Vers);
      if(FSuccessCnt < 0)
      {
        ShowZipMessage( EX_FatalUnZip );
        FSuccessCnt = 0;
      }
#ifndef NO_STREAM
  		// Remove from memory if stream is not Ok.
  		if(UseStream && FSuccessCnt != 1) FZipStream->Clear();
#endif
  		// If UnSpanned we still have this temporary file hanging around.
  	  if(FTotalDisks > 0) DeleteFile(TmpZipName);
    }
     catch (const EZipBuilder &ezl)
    {  // Catch all Zip specific errors.
      ShowExceptionError(ezl);
    }
  	catch (...)
  	{
  		ShowZipMessage( EX_FatalUnZip );
  	}
  }
  __finally
  {
		FFSpecArgs->Clear();
		// Free all allocated memory.
    if(UnZipParms)
    {
      delete[] UnZipParms->pZipFN;
      delete[] UnZipParms->pZipPassword;
      if(!UseStream) SetCurrentDir(UnZipParms->fExtractDir);
      delete[] UnZipParms->fExtractDir;
      for(int i = UnZipParms->fArgc - 1; i >= 0; i--)	delete[] UnZipParms->fUFDS[i].fFileSpec;
      delete[] UnZipParms->fUFDS;
      delete UnZipParms;
    }
		UnZipParms = NULL;
	}
	if(FUnattended && FPassword == "" && !FOnPasswordError)
		    PasswordReqCount = OldPRC;

  fUnzDll->Unload(false);
  FUnzBusy = false;
	FCancel  = false;
	// No need to call the List() function contents unchanged.
}
// TZipBuilder::ExtExtract

#ifndef NO_SPAN
// TZipBuilder::GetLastVolume--------------------------------------------------
//1.73 16 September 2003 RA use of NameOfPart function
//1.73 12 September 2003 RA do not accept negative partnumbers
//1.73  (9 July 2003) RA creation of first part name improved
int __fastcall TZipBuilder::GetLastVolume(String FileName,ZipEndOfCentral& EOC, bool AllowNotExists)
// Locate last of multi volume or last disk of spanned
// returns
// 0 = OK
// -1 = error
// 1 = user aborted loop = avoid asking for last disk if not needed
{
  AnsiString TmpFileName;
  AnsiString sName;
  int Result;
  int PartNbr = -1;
  TSearchRec SRec;
  FInFileHandle = -1;
  FDrive = ExtractFileDrive(ExpandFileName(FileName)) + "\\";
  AnsiString Ext = UpperCase(ExtractFileExt(FileName));
  AnsiString Path = ExtractFilePath(FileName);
  FMVolume= false;
  try
  {
    FDriveFixed = IsFixedDrive();
    GetDriveProps();  // check valid drive
    if(!FileExists(FileName)) // if file exsits we have one volume zip file or spanned on removable disks
    {
      TmpFileName = FileName.SubString(1, FileName.Length()
                                         - ExtractFileExt(FileName).Length());// remove extension
      FMVolume = true; // file did not exist maybe it is a multi volume
      if(FDriveFixed) // if file not exists on harddisk then only Multi volume parts are possible
      {  // filename is of type ArchiveXXX.zip
        // MV files are series with consecutive partnbrs in filename, highest number has EOC
        while(FileExists(TmpFileName + IntToStr(1002 + PartNbr).SubString(2, 3) + ".zip"))
         { ++PartNbr; };
        if(PartNbr == -1)
        {
          if (AllowNotExists) return 1;
          throw EZipBuilder(DS_FileOpen); // non found
        }
        FileName = TmpFileName + IntToStr(1001 + PartNbr).SubString(2, 3) + ".zip";
        // check if filename.z01 exists then it is part of MV with compat names and cannot be used
        if(FileExists(ChangeFileExt(FileName, ".z01"))) throw EZipBuilder(DS_FileOpen); // cannot be used
      }
      else // if we have an MV archive copied to a removable disk
      {
        // accept any MV filename on disk
        sName = NameOfPart(TmpFileName, false);
        if(sName == "") sName = NameOfPart(TmpFileName, true);
        if(sName == "") throw EZipBuilder(DS_FileOpen, true);
        FileName = Path + sName;
/*
        if((Result = FindFirst(TmpFileName + "???.zip", faAnyFile, SRec)) == 0)
        {
          PartNbr = StrToIntDef(SRec.Name.SubString(SRec.Name.Length()-6,3), -1);
          FileName = Path + SRec.Name;
          FindClose(SRec);
        }
        else // file name is of type Archive.zXX here the part with central dir is the zip part
        {
          if((Result = FindFirst(TmpFileName + ".z??", faAnyFile, SRec)) == 0) // accept the filename on the disk
          {
            PartNbr = StrToIntDef(SRec.Name.SubString(SRec.Name.Length()-2,2), -1);
            FileName = Path + SRec.Name;
            FindClose(SRec);
          }
          else
          {
            FindClose(SRec);
            throw EZipBuilder(DS_FileOpen);
          }
        }
        if(PartNbr < 0) throw EZipBuilder(DS_FileOpen);
        */
      }
    }
    // zip file exists or we got an acceptable part in multivolume or spanned archive
    FInFileName = FileName; // use class variable for other functions
    while(!OpenEOC(EOC, false)) // does this part contains the central dir
    {  // it is not the disk with central dir so ask for the last disk
      if (FInFileHandle != -1)
      {
        FileClose(FInFileHandle); //each check does FileOpen
        FInFileHandle = -1; // avoid further closing attempts
      }
      CheckForDisk(false); // does the request for new disk
      if(FDriveFixed)
      {
        if(FMVolume) throw EZipBuilder(DS_FileOpen); // it was not a valable part
        AllowNotExists = false; // next error needs to be displayed always
        throw EZipBuilder(DS_NoValidZip); // file with EOC is not on fixed disk
      }
      // for spanned archives on cdrom's or floppies
      if(FOnGetNextDisk)
      {	// v1.60L
        bool Abort = false;
        OnGetNextDisk(this, 0, 0, FDrive.SubString( 1, 1), Abort);
        if(Abort)  // we allow abort by the user
        {
          if (FInFileHandle != -1) FileClose(FInFileHandle);
          return 1;
        }
        GetDriveProps();  // check drive spec and get volume name
      }
      else
      { // if no event handler is used
        FNewDisk = true;
        FDiskNr = -1; // read operation
        CheckForD

⌨️ 快捷键说明

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