📄 zipbuilder.cpp
字号:
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 + -