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

📄 zipbuilder.cpp

📁 zip算法的源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			CEH.RelOffLocal = MDZD->Items[i]->RelOffLocal;
			EOC.CentralSize = EOC.CentralSize - CEH.FileNameLen + MDZD->Items[i]->FileNameLen;
			CEH.FileNameLen = MDZD->Items[i]->FileNameLen;
        //check if new filename has extended chars if it is we need to set ExtFileAttributes
        // and update version made by
      if(HasExtendedChars(MDZD->Items[i]->FileName) && !(MDZD->Items[i]->DiskStart & 0xFF00))
      {
        CEH.VersionMadeBy0 = DEF_HOST_VER & 0xFF;
        CEH.VersionMadeBy1 = (DEF_HOST_VER & 0xFF00) >> 8;
        CEH.ExtFileAtt = ((CEH.ExtFileAtt & FILE_ATTRIBUTE_DIRECTORY ? S_IFDIR + S_IEXEC : S_IFREG) +
                      S_IREAD +
                      (CEH.ExtFileAtt & FILE_ATTRIBUTE_READONLY ? 0 : S_IWRITE)) << 16 +
                      CEH.ExtFileAtt;
      }
      else
      {
        CEH.VersionMadeBy0 = MDZD->Items[i]->DiskStart & 0xFF ;
        CEH.VersionMadeBy1 = (MDZD->Items[i]->DiskStart & 0xFF00) >> 8;
      }
			// Write this changed central header to disk
			WriteJoin(&CEH, sizeof(CEH), DS_CEHBadWrite);

			// Write to destination the central filename.
			WriteJoin(MDZD->Items[i]->FileName, CEH.FileNameLen, DS_CEHBadWrite);

			// And the extra field
			if(CopyBuffer(FInFileHandle, FOutFileHandle, CEH.ExtraLen))
				throw EZipBuilder(DS_CEExtraLen);

			// And the file comment.
			if(CopyBuffer(FInFileHandle, FOutFileHandle, CEH.FileComLen))
				throw EZipBuilder(DS_CECommentLen);
		}
		// Write the changed EndOfCentral directory record.
		EOC.CentralDiskNo = 0;
		EOC.ThisDiskNo = 0;
		WriteJoin(&EOC, sizeof(EOC), DS_EOCBadWrite);

		// Skip past the original EOC to get to the ZipComment if present. v1.52m
		if(FileSeek(FInFileHandle, (int)sizeof( EOC ), 1) == -1)
			throw EZipBuilder(DS_FailedSeek);

		// And finally the archive comment
		// ==================Changed By Jim Turner=======
		if((FEOCComment != "") &&
        (FileWrite(FOutFileHandle, FEOCComment.c_str(),FEOCComment.Length()) < 0))
//		{
//			if(CopyBuffer(FInFileHandle, FOutFileHandle, EOC.ZipCommentLen))
					throw EZipBuilder(DS_EOArchComLen, true);
//		}
	}
	catch (const EZipBuilder &ers)
	{	// All Rename specific errors..
		ShowExceptionError(ers);
		Result = -7;
	}
	catch (const MEMEXCEPT &me)
	{		// All memory allocation errors.
		ShowZipMessage(GE_NoMem);
		Result = -8;
	}
	catch(const Exception &E)
	{
		ShowZipMessage(DS_ErrorUnknown, "\n" + E.Message );
		Result = -9;
	}
	catch ( ... )
	{							// The remaining errors, should not occur.
		ShowZipMessage(DS_ErrorUnknown);
		Result = -9;
	}
	delete[] Buffer;
	if(MDZD) delete MDZD;

	// Give final progress info at the end.
  CallBack(zacEndOfBatch,0,"",0);

	if(FInFileHandle != -1) FileClose(FInFileHandle);
	if(FOutFileHandle != -1)
	{
		FileSetDate(FOutFileHandle, FDateStamp);
		FileClose(FOutFileHandle);
		if(Result) DeleteFile(OutFilePath);  // An error somewhere, OutFile is not reliable.
		else
		{
			EraseFile(FZipFileName, FHowToDelete);
			RenameFile(OutFilePath, FZipFileName);
			_List();
		}
	}
  FZipBusy = false;
	StopWaitCursor();
	return Result;
}
// TZipBuilder::Rename

// TZipBuidler::Setup_extend-------------------------------------------------------
// 1.73.3.2 10 Oct 2003 RA New function to init upper table
void __fastcall TZipBuilder::Setup_extend(void)
{
  unsigned char* p = (unsigned char *)extend;
  for(int i = 0;i < 256; ++i)
     *p++ = (unsigned char)i;
  CharToOemBuff(extend+1,(unsigned char *)extend+1,255);
  p = (unsigned char *)extend;
  for(int i = 0; i < 256; ++i)
       *p = *p++ != i;
}
//TZipBuidler::Setup_extend

// TZipBuilder::TZipBuilder-----------------------------------------------------
// 1.73.3.2 10 Oct 2003 RA added setup_extend
// 1.73( 30 July 2003) RA TInternalSFX class added
// 1.73 (24 June 2003) RA set default value TargetHostVer
// 1.73 (17 May 2003) - RP clear event variables
__fastcall TZipBuilder::TZipBuilder(Classes::TComponent *AOwner) : TComponent(AOwner)
{
	FHandle					= Application->Handle;
	FZipContents 			= new TList();
	FFSpecArgs  			= new TStringList();
	FFSpecArgsExcl			= new TStringList();	//New v1.6
  fZipDll = new TZipDll(this);		// new 1.73
	fUnzDll = new TUnzDll(this);		// new 1.73
	fIsDestroying = false;					// new 1.73
#ifdef INTERNAL_SFX
  FIntSFX = new TInternalSFX(this); // new 1.73
#endif
  Setup_extend(); // init extend table
	ZipParms				= NULL;
	UnZipParms = NULL;
	FZipFileName			= "";
	FPassword				= "";
	FPasswordReqCount 	=  1;		// New v1.6
	FEncrypt					= false;
	FSuccessCnt 			=  0;
	FAddCompLevel			=  9;		// Default to tightest compression.
	FDLLDirectory			= "";
	AutoExeViaAdd = false;
	FUnattended				= false;
	FRealFileSize			=  0;
	FSFXOffset				=  0;
	FZipSOC					=  0;
	FFreeOnDisk1			=  0;			// Don't leave anything free.
  FFreeOnAllDisks = 0;         // 1.72  use all space
	FMaxVolumeSize			=  0;			// Use the maximum disk size.
	FMinFreeVolSize		= 65536;		// Reject disks with less bytes than...
	FCodePage         	= cpAuto;
	FIsSpanned        	= false;
  FDriveFixed = false;
	FZipComment = "";
	FHowToDelete			= htdAllowUndo;
	FAddStoreSuffixes 	= AddStoreExts() << assGIF << assPNG << assZ << assZIP << assZOO << assARC
														<< assLZH << assARJ << assTAZ << assTGZ << assLHA
														<< assRAR << assACE << assCAB << assGZ << assGZIP << assJAR;
	FUseDirOnlyEntries	= false;
	FDirOnlyCount			= 0;
	FVersionInfo			= ZIPBUILDERVERSION;
	FCurWaitCount			= 0;
  BufSize  = 8192;		 // Keep under 12K to avoid Winsock problems on Win95.
                       // If chunks are too large, the Winsock stack can lose bytes being sent or received.
  // 1.73 clear event variables
  FOnDirUpdate = NULL;
  FOnProgress = NULL;
  FOnMessage = NULL;
  FOnSetNewName = NULL;
  FOnNewName = NULL;
  FOnPasswordError = NULL;
  FOnCRC32Error = NULL;
  FOnExtractOverwrite = NULL;
  FOnExtractSkipped = NULL;
  FOnCopyZipOverwrite = NULL;
  FOnFileComment = NULL;
  FOnTicker = NULL;
  FOnAfterCallBack = NULL;
  FOnFileExtra = NULL;
  FOnItemProgress = NULL;
  FOnTotalProgress = NULL;
#ifndef NO_SPAN
  FOnGetNextDisk = NULL;
  FOnStatusDisk = NULL;
  SpanOptions.Clear();
	FConfirmErase			= true;
#endif
#ifndef NO_SFX
	FSFXIcon					= new TIcon();
	FSFXOverWriteMode		= OvrConfirm;
	FSFXCaption				= "Self-extracting Archive";
	FSFXDefaultDir			= "";
	FSFXCommandLine			= "";
	FSFXOptions				= SfxOpts() << SFXCheckSize;
	FSFXPath					= "ZipSFX.bin";
#endif
#ifndef NO_STREAM
  FZipStream				= new TZipStream();
#endif
}
// TZipBuilder::TZipBuilder

// TZipBuilder::HasExtendedChars ------------------------------------------------
// 1.73.3.2 8 Oct 2003 RA New function to test if file name has extended chars
bool __fastcall TZipBuilder::HasExtendedChars(const AnsiString FileName)
{
  for(int i = 1; i < FileName.Length(); ++i)
      if(extend[FileName[i]]) return true;
  return false;
}
// TZipBuilder::HasExtendedChars

#ifndef NO_SPAN
// TZipBuilder::WriteSplit------------------------------------------------------
// 1.73.3.2 9 Oct 2003 RA set KeepFreeOnDisk1 and KeepFreeOnAlldisk to sector boundaries
// 1.73 11 July 2003 RP corrected asking disk status
// 1.73 (7 July 2003) RA changed OnMessage and OnProgress to Callback calls
// 1.73 (18 May 2003) RP changed to use ZipAbort
// This function actually writes the zipped file to the destination while taking care
// of disk changes and disk boundary crossings.
// In case of an write error or user abort an EZipBuilder Exception is thrown.
void __fastcall TZipBuilder::WriteSplit(const void *Buffer, int Len, int MinSize)
{
	int Res, MaxLen;
	char *Buf = (char *)Buffer;  // Used if Buffer doesn't fit on the present disk.
  CallBack(zacTick,0,"",0);
	while(true)
	{	// Keep writing until error or buffer is empty.
		// Check if we have an output file already opened, if not: create one, do checks gather info.
		if(FOutFileHandle == -1)
		{
			String DiskFile = FOutFileName, MsgQ;
      FDriveFixed = IsFixedDrive();
      CheckForDisk(true);
			// If we write on a fixed disk the filename must change.
			// We will get something like: FileNamexxx.zip where xxx is 001,002 etc.
      // if CompatNames are used we get FileName.zxx wher xx is 01, 02 etc..
			if(FDriveFixed || FSpanOptions.Contains(spNoVolumeName))
                                  CreateMVFileName(DiskFile, false);
			if(!FDriveFixed && SpanOptions.Contains(spWipeFiles))
			{
				if(!FOnGetNextDisk || (FOnGetNextDisk && FZipDiskAction == zdaErase))
				{	// Added v1.60L
	 				// Do we want a format first? To be save we don't do this on a harddisk.
					FDriveNr = FDrive.UpperCase()[1] - 'A';
          if(SpanOptions.Contains(spNoVolumeName))
              FVolumeName = "ZipSet_" + IntToStr(FDiskNr); //default name
          else FVolumeName = "PKBACK# " + IntToStr(1001 + FDiskNr).SubString(2, 3);
					// Ok=6, NoFormat=-3
					switch(ZipFormat())
					{   // Start the format and wait until finished...
						case -1:  throw EZipBuilder(DS_Canceled, true);			// Error
						case -2:  throw EZipAbort();	// Canceled
            default: DiskFreeAndSize(3); // reread disksize values after format
					}
				}
			}
			// Do we want to overwrite an existing file
      int DiskSeq;
      if(FSpanOptions.Contains(spNoVolumeName)) DiskSeq = FDiskNr + 1;
    	else DiskSeq =  StrToIntDef(FVolumeName.SubString(9, 3), 1);
      FZipDiskStatus.Clear();
      if(FileExists(DiskFile))
      {
				if(Unattended) throw EZipBuilder(DS_NoUnattSpan);	// we assume we don't.
				// A more specific check if we have a previous disk from this set. Not too smart but...
				if(FileAge(DiskFile) == FDateStamp && DiskSeq - 1 < FDiskNr && !FDriveFixed) // don't ask for fixed drive
				{
					MsgQ = Format(LoadZipStr(DS_AskPrevFile, "Overwrite previous disk no %d"),
																			ARRAYOFCONST((DiskSeq)));
					FZipDiskStatus << zdsPreviousDisk;
				}
				else
				{
					MsgQ = Format(LoadZipStr(DS_AskDeleteFile, "Overwrite previous file %s"),
					              ARRAYOFCONST((DiskFile)));
					FZipDiskStatus << zdsSameFileName;
				}
			}
      else
      {
        if(FSizeOfDisk - FFreeOnDisk) FZipDiskStatus << zdsHasFiles;		// But not the same name
        else FZipDiskStatus << zdsEmpty;
      }
      if(FOnStatusDisk)
      {
        FZipDiskAction = zdaOk;					// The default action
        OnStatusDisk(this, DiskSeq, DiskFile, FZipDiskStatus, FZipDiskAction);
        switch(FZipDiskAction)
        {
          case zdaCancel: Res = IDCANCEL;	break;
          case zdaReject: Res = IDNO;		break;
          case zdaErase:
          case zdaOk:		 Res = IDOK;
          default : Res = IDOK;
        }
      }
      else
        if(!FZipDiskStatus.Contains(zdsEmpty) && !FZipDiskStatus.Contains(zdsHasFiles))
        {  // if no OnStatusDisk event
          Res = Application->MessageBox(MsgQ.c_str(),
          										LoadZipStr(FM_Confirm,"Confirm").c_str(),
                             MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_ICONWARNING );
        }
        else Res = IDOK;
      if(!Res) throw EZipBuilder( DS_NoMem);
      if(Res == IDCANCEL) throw EZipBuilder(DS_Canceled, false);
      if(Res == IDNO)
      {		// we will try again...
        FDiskWritten = 0;
        FNewDisk = true;
        continue;
      }
			// Create the output file.
			if((FOutFileHandle = FileCreate(DiskFile)) == -1)
      {//change proposed by Pedro Araujo
        MsgQ = LoadZipStr( DS_NoOutFile, "Creation of output file failed" );
        Res = Application->MessageBox(MsgQ.c_str(), Application->Title.c_str(),
                           MB_RETRYCANCEL | MB_ICONERROR );
        if(!Res) throw EZipBuilder( DS_NoMem );
				if(Res != IDRETRY ) throw EZipAbort();
				FDiskWritten = 0;
				FNewDisk = true;
				continue;
      }
			// Get the free space on this disk, correct later if neccessary.
			DiskFreeAndSize(1);
			// Set the maximum number of bytes that can be written to this disk(file).
			if(FMaxVolumeSize) FFreeOnDisk = min(FMaxVolumeSize, FFreeOnDisk);
      // Set the maximum number of bytes that can be written to this disk(file).
      // Reserve space on/in all the disk/file.
      if(!FDiskNr && (KeepFreeOnDisk1 || KeepFreeOnAllDisks)) // only one calculation if needed
      {  // set these properties on sector boundaries
        DWORD	SectorsPCluster, BytesPSector, FreeClusters, TotalClusters;
        if(GetDiskFreeSpace(FDrive.c_str(), &SectorsPCluster, &BytesPSector, &FreeClusters, &TotalClusters))
        {
          if(KeepFreeOnDisk1  % BytesPSector)
            KeepFreeOnDisk1 = ((KeepFreeOnDisk1 / BytesPSector) + 1) * BytesPSector;
          if(KeepFreeOnAllDisks  % BytesPSector)
            KeepFreeOnAllDisks = ((KeepFreeOnAllDisks / BytesPSector) + 1) * BytesPSector;
        }
      }
      FFreeOnDisk -= KeepFreeOnAllDisks;
			// Reserve space on/in the first disk(file).
			if(!FDiskNr) FFreeOnDisk -= KeepFreeOnDisk1;

⌨️ 快捷键说明

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