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