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

📄 zipbuilder.cpp

📁 zip算法的源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        {
					MadeOS = FHostNum;
					MadeVer = FHostVer;
        }
  			Name[CEH.FileNameLen] = '\0';
//        Name = ConvertOEM(Name, cpdOEM2ISO);
//  			ConvertOem2Iso( Name, cpdOEM2ISO );
  			// Create a new ZipDirEntry record
  			pzd = new ZipDirEntry;	// These will be deleted in: FreeZipDirEntryRecords().
  			// Copy the information from the central header.
  			memcpy(pzd, &CEH.VersionMadeBy0, LocalDirEntrySize );
       	pzd->FileName  = SetSlash(ConvertOEM(Name, cpdOEM2ISO), false);
//  			pzd->FileName  = ReplaceForwardSlash( Name );
  			pzd->Encrypted = pzd->Flag & 0x01;

  			// Read the extra data if present new v1.6
         pzd->ExtraData = "";  // empty
        if(CEH.ExtraLen)
  			{
          pzd->ExtraData.SetLength(CEH.ExtraLen);
          ReadJoin(pzd->ExtraData.c_str(), CEH.ExtraLen ,LI_ReadZipError);
  			}

  			// Read the FileComment if present and save.
         if(CEH.FileComLen)
        {
          pzd->FileComment.SetLength(CEH.FileComLen);
          ReadJoin(pzd->FileComment.c_str(), CEH.FileComLen ,DS_CECommentLen);
//          pzd->FileComment = ConvertOEM(pzd->FileComment, cpdOEM2ISO);
  			}
  			if(FUseDirOnlyEntries || ExtractFileName( pzd->FileName ) != "" )
  			{
  				// Add it to our contents tabel.
  				FZipContents->Add( pzd );
  				// Notify user of the next entry in the ZipDir.
  				if(FOnNewName) FOnNewName(this, i + 1, *pzd);
  			}
  			else
  			{
  				FDirOnlyCount++;
  				pzd->ExtraData = "";
  				delete pzd;
  			}
  			// Calculate the earliest Local Header start.
  			if(FSFXOffset > (int)CEH.RelOffLocal) FSFXOffset = (int)CEH.RelOffLocal;
  		}
  		FTotalDisks = EOC.ThisDiskNo;			// We need this when we are going to extract.
    }
  	catch (const EZipBuilder &ezl)
  	{		// Catch all Zip List specific errors.
  		ShowExceptionError(ezl);
  		LiE = true;
  	}
  	catch (const MEMEXCEPT &me)
  	{
  		ShowZipMessage(GE_NoMem);
			LiE = true;
     }
  	catch(const Exception &E)
  	{
  		ShowZipMessage(LI_ErrorUnknown, "\n" + E.Message);
			LiE = true;
  	}
  	catch ( ... )
  	{
  		ShowZipMessage(LI_ErrorUnknown);
			LiE = true;
  	}
  }
  __finally
  {
  	StopWaitCursor();
  	if(FInFileHandle != -1 ) FileClose(FInFileHandle);
		if(LiE)
		{
			FZipFileName = "";
			FSFXOffset = 0;
		}
  	else FSFXOffset += (OffsetDiff - EOC.CentralOffset);	// Correct the offset for v1.3, 1.4 and 1.45
  	// Let user's program know we just refreshed the zip dir contents.
    FHostNum = MadeOS;  // if any not dos assume comment not oem
    FHostVer = MadeVer;
    FZipComment = ConvertOEM(FEOCComment, cpdOEM2ISO);
  	if(FOnDirUpdate) FOnDirUpdate(this);
  }
}
// TZipBuilder::_List

/* TZipBuilder::Rename----------------------------------------------------------
1.73.3.2 11 October 2003 RP changed comment variable
1.73.3.2 8 Oct 2003 RA if filename has extended chars change HostVer + extfileattrib
1.73 23 september 2003 RA changeing date/time of protected file is not allowed
1.73 7 August 2003 RA init FOutFileHandle
1.73 (16 July 2003) RP use SetSlash + ConvertOEM
1.73 (14 July 2003) RA convertion/re-convertion of filenames with OEM chars
Function to read a Zip archive and change one or more file specifications.
Source and Destination should be of the same type. (path or file)
If NewDateTime is 0 then no change is made in the date/time fields.
Return values:
0            All Ok.
-7           Rename errors. See ZipMsgXX.rc
-8           Memory allocation error.
-9           General unknown Rename error.
-10          Dest should also be a filename.
*/
int __fastcall TZipBuilder::Rename(TList &RenameList, unsigned long DateTime)
{
	ZipEndOfCentral    EOC;
	ZipCentralHeader   CEH;
	ZipLocalHeader     LOH;
	String             OrigFileName;
	String             MsgStr;
	String             OutFilePath;
	char *Buffer = NULL;
	int				    TotalBytesToRead = 0;
	int				    TotalBytesWrite;
	int				    Result = 0;
	ZipRenameRec		*RenRec;
  TMZipDataList* MDZD = NULL;
	FShowProgress = false;
	FInFileName   = FZipFileName;
	FInFileHandle = -1;
  FOutFileHandle = -1;
  if(Busy()) return BUSY_ERROR;
  FZipBusy = true;
	StartWaitCursor();
	// If we only have a source path make sure the destination is also a path.
	for(int i = 0; i < RenameList.Count; i++)
	{
		RenRec = (ZipRenameRec *)RenameList.Items[i];
		RenRec->Source = SetSlash(RenRec->Source,false);
		RenRec->Dest   = SetSlash(RenRec->Dest,false);
    RemoveDriveSpec(RenRec->Source);
    RemoveDriveSpec(RenRec->Dest);
    if(RenRec->Source.AnsiPos("*") || RenRec->Source.AnsiPos("?") ||
       RenRec->Dest.AnsiPos("*") || RenRec->Dest.AnsiPos("?"))
    {
      ShowZipMessage(AD_InvalidName); // no wildcards allowed
      StopWaitCursor();
      FZipBusy = false;
      return -7;  // Rename error
    }
		if(!ExtractFileName(RenRec->Source).Length())
		{	// Assume it's a path.
			// Make sure destination is a path also.
			RenRec->Dest   = SetSlash(ExtractFilePath(RenRec->Dest),true);
			RenRec->Source = SetSlash(RenRec->Source, true);
		}
		else if(!ExtractFileName(RenRec->Dest).Length())
    	{
	      StopWaitCursor();
        FZipBusy = false;
			  return -10;  // Dest should also be a filename.
      }
	}
	try
	{
    Buffer = new char[BufSize];
		// Check the input file.
		if(!FileExists(FZipFileName))	throw EZipBuilder(GE_NoZipSpecified);
		if((OutFilePath = MakeTempFileName()) == "") throw EZipBuilder(DS_NoTempFile );

		// Create the output file.
		FOutFileHandle = FileCreate(OutFilePath);
		if(FOutFileHandle == -1)	throw EZipBuilder( DS_NoOutFile );

		// The following function will read the EOC and some other stuff:
		OpenEOC(EOC, false);  // do not throw exceptions yet

		// Get the date-time stamp and save for later.
		FDateStamp = FileGetDate(FInFileHandle);

		// Now we now the number of zipped entries in the zip archive
		FTotalDisks = EOC.ThisDiskNo;
		if(EOC.ThisDiskNo) throw EZipBuilder(RN_NoRenOnSpan);

		// Go to the start of the input file.
		if(FileSeek(FInFileHandle, 0, 0) == -1)	throw EZipBuilder(DS_FailedSeek);

		// Write the SFX header if present.
		if(CopyBuffer(FInFileHandle, FOutFileHandle, FSFXOffset))
			throw EZipBuilder(RN_ZipSFXData);

		// Go to the start of the Central directory.
		if(FileSeek(FInFileHandle, (SeekInt)EOC.CentralOffset, 0) == -1)
			throw EZipBuilder(DS_FailedSeek);

		MDZD = new TMZipDataList(EOC.TotalEntries);		// create class

		// Read for every entry: The central header and save information for later use.
		for(int i = 0; i < EOC.TotalEntries; i++)
		{
			// Read a central header.
      ReadJoin(&CEH, sizeof(CEH), DS_CEHBadRead);
			if(CEH.HeaderSig != CentralFileHeaderSig)	throw EZipBuilder(DS_CEHWrongSig);

			// Now the filename.
      ReadJoin( Buffer, CEH.FileNameLen, DS_CENameLen);
			// Save the file name info in the MDZD structure.
			MDZD->Items[i]->FileNameLen = CEH.FileNameLen;
      MDZD->Items[i]->FileName = new char[CEH.FileNameLen + 1];
      StrLCopy(MDZD->Items[i]->FileName, Buffer, CEH.FileNameLen);
      MDZD->Items[i]->FileName[CEH.FileNameLen] = '\0';
			//convert OEM char set in original file else we don't find the file
      FHostNum = CEH.VersionMadeBy1;
      FHostVer = CEH.VersionMadeBy0;
      AnsiString Name = ConvertOEM(MDZD->Items[i]->FileName, cpdOEM2ISO);
      StrCopy(MDZD->Items[i]->FileName,Name.c_str());
      //DiskStart is not used in this function and we need FHostNum later
      MDZD->Items[i]->DiskStart = (FHostNum << 8) + FHostVer;
			MDZD->Items[i]->RelOffLocal = CEH.RelOffLocal;
       // if encrypted use CRC32 as flag
      MDZD->Items[i]->CRC32 = CEH.Flag & 1;
      MDZD->Items[i]->DateTime    = DateTime;
			// We need the total number of bytes we are going to read for the progress event.
			TotalBytesToRead += (int)(CEH.ComprSize + CEH.FileNameLen + CEH.ExtraLen);

			// Seek past the extra field and the file comment.
			if(FileSeek(FInFileHandle, (SeekInt)(CEH.ExtraLen + CEH.FileComLen), 1 ) == -1)
				throw EZipBuilder(DS_FailedSeek);
		}
		FShowProgress = true;
    CallBack(zacCount,0, "", EOC.TotalEntries);
		CallBack(zacSize,0, "", TotalBytesToRead);
		// Read for every zipped entry: The local header, variable data, fixed data
		// and if present the Data descriptor area.
		for(int i = 0; i < EOC.TotalEntries; i++)
		{
			// Seek to the first/next entry.
			FileSeek(FInFileHandle, (SeekInt)MDZD->Items[i]->RelOffLocal, 0);

  		// First the local header.
      ReadJoin(&LOH, sizeof(LOH), DS_LOHBadRead);
			if(LOH.HeaderSig != LocalFileHeaderSig)	throw EZipBuilder(DS_LOHWrongSig);

			// Now the filename.
      ReadJoin( Buffer, LOH.FileNameLen, DS_LONameLen);
			// Set message info on the start of this new fileread now we still have the old filename.
			MsgStr = LoadZipStr(RN_ProcessFile, "Processing: ") + MDZD->Items[i]->FileName;

			// Calculate the bytes we are going to write; we 'forget' the difference
			// between the old and new filespecification length.
			TotalBytesWrite = LOH.FileNameLen + LOH.ExtraLen + LOH.ComprSize;

			// Check if the original path and/or filename needs to be changed.
			OrigFileName = SetSlash(MDZD->Items[i]->FileName,false);
			for(int m = 0; m < RenameList.Count; m++)
      {
				RenRec = (ZipRenameRec *)RenameList.Items[m];
        int k = UpperCase(OrigFileName).Pos(UpperCase(RenRec->Source));
        if(k)
        {
          OrigFileName.Delete(k, RenRec->Source.Length());
          OrigFileName.Insert(RenRec->Dest, k);
          LOH.FileNameLen = MDZD->Items[i]->FileNameLen = (unsigned short)OrigFileName.Length();
          for(k = 1; k <= OrigFileName.Length(); k++)
                  if(OrigFileName[k] == '\\') OrigFileName[k] = '/';
          MsgStr += LoadZipStr(RN_RenameTo, " renamed to: ") + OrigFileName;
          delete[] MDZD->Items[i]->FileName;
          MDZD->Items[i]->FileName = new char[OrigFileName.Length() + 1];
          StrPLCopy(MDZD->Items[i]->FileName, OrigFileName, LOH.FileNameLen + 1);
          //check if new filename has extended chars if it is we need to set FHostVer to NTFS
          if(!(HasExtendedChars(OrigFileName) && !(MDZD->Items[i]->DiskStart & 0xFF00)))
          {
            FHostNum = (MDZD->Items[i]->DiskStart & 0xFF00) >> 8;
            FHostVer = MDZD->Items[i]->DiskStart & 0xFF;
            OrigFileName = ConvertOEM(OrigFileName, cpdISO2OEM);
          }
          StrPLCopy(MDZD->Items[i]->FileName, OrigFileName, OrigFileName.Length() + 1);
          MDZD->Items[i]->FileNameLen = OrigFileName.Length();
        // Change Date and Time if needed.
          try
          {
            if(RenRec->DateTime)
            {
              // not allowed to change date on protected file
              if(MDZD->Items[i]->CRC32)
                  throw EZipBuilder(RN_InvalidDateTime);
              // test if valid date/time will throw error if not
              FileDateToDateTime(RenRec->DateTime);
              MDZD->Items[i]->DateTime = RenRec->DateTime;
            }
          }
          catch(...)
          {
             ShowZipMessage(RN_InvalidDateTime, MDZD->Items[i]->FileName);
          }
        }
			}
      CallBack(zacMessage,0,MsgStr,0);

			// Change Date and/or Time if needed.
			if(MDZD->Items[i]->DateTime)
			{
				LOH.ModifDate = HIWORD(MDZD->Items[i]->DateTime );
				LOH.ModifTime = LOWORD(MDZD->Items[i]->DateTime );
			}
			// Change info for later while writing the central dir.
			MDZD->Items[i]->RelOffLocal = FileSeek(FOutFileHandle, 0, 1);
      CallBack(zacItem,0,SetSlash(MDZD->Items[i]->FileName,false),TotalBytesWrite);

			// Write the local header to the destination.
			WriteJoin(&LOH, sizeof(LOH), DS_LOHBadWrite);

			// Write the filename.
			WriteJoin(MDZD->Items[i]->FileName, LOH.FileNameLen, DS_LOHBadWrite);

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

			// Read and write Zipped data
			if(CopyBuffer(FInFileHandle, FOutFileHandle, LOH.ComprSize))
				throw EZipBuilder(DS_ZipData);

			// Read DataDescriptor if present.
			if(LOH.Flag & 0x0008)
				if(CopyBuffer(FInFileHandle, FOutFileHandle, sizeof(ZipDataDescriptor)))
					throw EZipBuilder(DS_DataDesc);
		}	// Now we have written al entries.

		// Now write the central directory with possibly changed offsets and filename(s).
		FShowProgress = false;
		for(int i = 0; i < EOC.TotalEntries; i++)
		{
			// Read a central header.
      ReadJoin(&CEH, sizeof(CEH), DS_CEHBadRead);
			if(CEH.HeaderSig != CentralFileHeaderSig)	throw EZipBuilder(DS_CEHWrongSig);

			// Change Date and/or Time if needed.
			if(MDZD->Items[i]->DateTime)
			{
				CEH.ModifDate = HIWORD(MDZD->Items[i]->DateTime);
				CEH.ModifTime = LOWORD(MDZD->Items[i]->DateTime);
			}
			// Now the filename.
      ReadJoin( Buffer, CEH.FileNameLen, DS_CENameLen);

			// Save the first Central directory offset for use in EOC record.
			if(!i)	EOC.CentralOffset = FileSeek(FOutFileHandle, 0, 1);

			// Change the central header info with our saved information.

⌨️ 快捷键说明

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