BSOne.SFC/Tocsg.Module/ContentSearch/EXE_KvCttSch/ProcessDecompress.pas

346 lines
9.7 KiB
Plaintext

{*******************************************************}
{ }
{ ProcessDecompress }
{ }
{ Copyright (C) 2023 kku }
{ }
{*******************************************************}
unit ProcessDecompress;
interface
uses
System.SysUtils, System.Classes, AbArcTyp, AbZipTyp;
const
SIG_CANCEL = '*CANCEL$';
DLL_7Z = '7z.dll';
procedure DecompressFile(sSrcPath, sExportPath: String;
aEvtProg: TAbArchiveProgressEvent; aEvtNeedPass: TAbNeedPasswordEvent);
procedure ExtractZip(sSrcPath, sExportPath: String;
aEvtProg: TAbArchiveProgressEvent; aEvtNeedPass: TAbNeedPasswordEvent);
procedure ExtractCab(sSrcPath, sExportPath: String; aEvtProg: TAbArchiveProgressEvent);
procedure ExtractTar(sSrcPath, sExportPath: String; aEvtProg: TAbArchiveProgressEvent);
procedure ExtractGzip(sSrcPath, sExportPath: String; IsGzippedTar: Boolean; aEvtProg: TAbArchiveProgressEvent);
procedure ExtractBzip2(sSrcPath, sExportPath: String; bIsBzippedTar: Boolean; aEvtProg: TAbArchiveProgressEvent);
procedure Extract7zip(sSrcPath, sExportPath: String);
implementation
uses
AbUnzper, AbCabExt, AbUtils, AbCabTyp, AbGzTyp, AbBzip2Typ, AbTarTyp,
AbUnzPrc, ProcessAlzip, Process7zip, Tocsg.Exception, Tocsg.Trace, Tocsg.Safe,
Tocsg.Files, Tocsg.Path;
procedure DecompressFile(sSrcPath, sExportPath: String;
aEvtProg: TAbArchiveProgressEvent; aEvtNeedPass: TAbNeedPasswordEvent);
var
fs: TFileStream;
ArcType: TAbArchiveType;
nEggType: Integer;
FileList: TStringList;
begin
try
if not FileExists(sSrcPath) then
begin
TTgTrace.T('DecompressFile() .. Not found file.. Path="%s"', [sSrcPath]);
exit;
end;
if EGG_IsValidArchive(PWideChar(sSrcPath), @nEggType) = EGG_ERROR_SUCCESS then
begin
Guard(FileList, TStringList.Create);
ExtractAlzipData(sSrcPath, sExportPath, FileList);
exit;
end;
try
fs := TFileStream.Create(sSrcPath, fmOpenRead);
except
on E: Exception do
begin
ETgException.TraceException(E, 'DecompressFile() .. Fail .. open file..');
exit;
end;
end;
ArcType := atUnknown;
try
fs.Position := 0;
ArcType := VerifyZip(fs);
// if ArcType = atUnknown then
// begin
// fs.Position := 0;
// ArcType := VerifyCab(fs); // 여기서 AV 오류가 발생한다.. 23_0602 10:39:42 kku
// end;
if ArcType = atUnknown then
begin
fs.Position := 0;
try
ArcType := VerifyTar(fs);
except
// ..
end;
end;
if ArcType = atUnknown then
begin
fs.Position := 0;
try
ArcType := VerifyGzip(fs);
except
// ..
end;
end;
if ArcType = atUnknown then
begin
fs.Position := 0;
try
ArcType := VerifyBzip2(fs);
except
// ..
end;
end;
finally
FreeAndNil(fs);
end;
case ArcType of
// atUnknown : ;
atZip : ExtractZip(sSrcPath, sExportPath, aEvtProg, aEvtNeedPass);
atSpannedZip : ExtractZip(sSrcPath, sExportPath, aEvtProg, aEvtNeedPass);
// atSelfExtZip : ;
atTar : ExtractTar(sSrcPath, sExportPath, aEvtProg);
atGzip : ExtractGzip(sSrcPath, sExportPath, false, aEvtProg);
atGzippedTar : ExtractGzip(sSrcPath, sExportPath, true, aEvtProg);
atCab : ExtractCab(sSrcPath, sExportPath, aEvtProg);
atBzip2 : ExtractBzip2(sSrcPath, sExportPath, false, aEvtProg);
atBzippedTar : ExtractBzip2(sSrcPath, sExportPath, true, aEvtProg);
else Extract7zip(sSrcPath, sExportPath);
end;
except
on E: Exception do
ETgException.TraceException(E, 'Fail .. DecompressFile() .. DoDecompress');
end;
end;
procedure ExtractZip(sSrcPath, sExportPath: String;
aEvtProg: TAbArchiveProgressEvent; aEvtNeedPass: TAbNeedPasswordEvent);
var
zip: TAbUnZipper;
begin
if DirectoryExists(sExportPath) then
DeleteDir(sExportPath);
if not ForceDirectories(sExportPath) then
exit;
sExportPath := IncludeTrailingPathDelimiter(sExportPath);
Guard(zip, TAbUnzipper.Create(nil));
zip.FileName := sSrcPath;
zip.ExtractOptions := [eoCreateDirs, eoRestorePath];
zip.BaseDirectory := sExportPath;
zip.OnArchiveProgress := aEvtProg;
zip.OnNeedPassword := aEvtNeedPass;
try
zip.ExtractFiles('*.*');
except
// DeleteDir(sExportPath);
TTgTrace.T('ExtractZip() .. Fail extract zip file.. Path="%s"', [sSrcPath]);
end;
// 패스워드 입력중 취소 할 경우 추출경로 삭제
if zip.Password = SIG_CANCEL then
DeleteDir(sExportPath);
end;
procedure ExtractCab(sSrcPath, sExportPath: String; aEvtProg: TAbArchiveProgressEvent);
var
cab: TAbCabExtractor;
begin
if DirectoryExists(sExportPath) then
DeleteDir(sExportPath);
if not ForceDirectories(sExportPath) then
exit;
sExportPath := IncludeTrailingPathDelimiter(sExportPath);
Guard(cab, TAbCabExtractor.Create(nil));
cab.FileName := sSrcPath;
cab.ExtractOptions := [eoCreateDirs, eoRestorePath];
cab.BaseDirectory := sExportPath;
cab.OnArchiveProgress := aEvtProg;
try
cab.ExtractFiles('*.*');
except
// DeleteDir(sExportPath);
TTgTrace.T('ExtractCab() .. Fail extract zip file.. Path="%s"', [sSrcPath]);
end;
end;
procedure ExtractTar(sSrcPath, sExportPath: String; aEvtProg: TAbArchiveProgressEvent);
var
tar: TAbTarArchive;
begin
if DirectoryExists(sExportPath) then
DeleteDir(sExportPath);
if not ForceDirectories(sExportPath) then
exit;
sExportPath := IncludeTrailingPathDelimiter(sExportPath);
Guard(tar, TAbTarArchive.Create(sSrcPath, WORD(fmOpenRead)));
tar.ExtractOptions := [eoCreateDirs, eoRestorePath];
tar.BaseDirectory := sExportPath;
tar.OnArchiveProgress := aEvtProg;
try
tar.Load;
tar.ExtractFiles('*.*');
except
// DeleteDir(sExportPath);
TTgTrace.T('ExtractGzip() .. Fail extract zip file.. Path="%s"', [sSrcPath]);
end;
end;
procedure ExtractGzip(sSrcPath, sExportPath: String; IsGzippedTar: Boolean; aEvtProg: TAbArchiveProgressEvent);
var
gzip: TAbGzipArchive;
i: Integer;
sUnknownExt,
sUnknownName: String;
begin
if DirectoryExists(sExportPath) then
DeleteDir(sExportPath);
if not ForceDirectories(sExportPath) then
exit;
sExportPath := IncludeTrailingPathDelimiter(sExportPath);
Guard(gzip, TAbGzipArchive.Create(sSrcPath, WORD(fmOpenRead)));
gzip.TarAutoHandle := true;
gzip.IsGzippedTar := IsGzippedTar;
gzip.ExtractOptions := [eoCreateDirs, eoRestorePath];
gzip.BaseDirectory := sExportPath;
gzip.OnArchiveProgress := aEvtProg;
// 파일명 정보가 존재하지 않을때 반디집처럼 압축 파일이름(.gz 제외 한)으로 대체 되도록 보완
sUnknownName := ExtractFileName(CutFileExt(sSrcPath)); // 경로와 .gz 빼줌
sUnknownExt := ExtractFileExt(sUnknownName);
sUnknownName := CutFileExt(sUnknownName);
try
gzip.Load;
for i := 0 to gzip.Count - 1 do
begin
if gzip.Items[i].FileName = 'unknown' then
begin
if i = 0 then
gzip.Items[i].FileName := sUnknownName + sUnknownExt
else
gzip.Items[i].FileName := Format('%s (%d)%s', [sUnknownName, i + 1, sUnknownExt]);
// gzip.Items[i].FileName := gzip.Items[i].FileName + IntToStr(i);
end;
end;
gzip.ExtractFiles('*.*');
except
// DeleteDir(sExportPath);
TTgTrace.T('ExtractGzip() .. Fail extract zip file.. Path="%s"', [sSrcPath]);
end;
end;
procedure ExtractBzip2(sSrcPath, sExportPath: String; bIsBzippedTar: Boolean; aEvtProg: TAbArchiveProgressEvent);
var
bzip2: TAbBzip2Archive;
begin
if DirectoryExists(sExportPath) then
DeleteDir(sExportPath);
if not ForceDirectories(sExportPath) then
exit;
sExportPath := IncludeTrailingPathDelimiter(sExportPath);
Guard(bzip2, TAbBzip2Archive.Create(sSrcPath, WORD(fmOpenRead)));
bzip2.TarAutoHandle := true;
bzip2.IsBzippedTar := bIsBzippedTar;
bzip2.ExtractOptions := [eoCreateDirs, eoRestorePath];
bzip2.BaseDirectory := sExportPath;
try
bzip2.Load;
bzip2.ExtractFiles('*.*');
except
// DeleteDir(sExportPath);
TTgTrace.T('ExtractBzip2() .. Fail extract zip file.. Path="%s"', [sSrcPath]);
end;
end;
procedure Extract7zip(sSrcPath, sExportPath: String);
const
SIG_7Z: array[0..4] of Byte = ($37, $7A, $BC, $AF, $27); // 7z...
SIG_RAR: array[0..4] of Byte = ($52, $61, $72, $21, $1A); // Rar!.
SIG_LZH: array[0..4] of Byte = ($00, $00, $2D, $6C, $68); // Offset: 2 Bytes, Sizet: 3 Bytes
var
s7zDll: String;
fs: TFileStream;
pSigBuf: TBytes;
SvZip: I7zInArchive;
TId: TGUID;
begin
s7zDll := GetRunExePathDir + DLL_7Z;
if not FileExists(s7zDll) then
exit;
try
fs := TFileStream.Create(sSrcPath, fmOpenRead);
except
on E: Exception do
begin
ETgException.TraceException(E, 'Extract7zip() .. Fail .. open file..');
exit;
end;
end;
try
try
if fs.Size < 10 then
exit;
SetLength(pSigBuf, 10);
fs.Read(pSigBuf[0], 10);
finally
fs.Free;
end;
if CompareMem(@pSigBuf[0], @SIG_7Z[0], 5) then
begin
TId := CLSID_CFormat7z;
end else
if CompareMem(@pSigBuf[0], @SIG_RAR[0], 5) then
begin
TId := CLSID_CFormatRar;
end else
if CompareMem(@pSigBuf[2], @SIG_LZH[2], 3) then
begin
TId := CLSID_CFormatLzh;
end else exit;
SvZip := CreateInArchive(Tid, s7zDll);
SvZip.OpenFile(sSrcPath);
SvZip.ExtractTo(sExportPath);
except
TTgTrace.T('Extract7zip() .. Fail extract compress file.. Path="%s"', [sSrcPath]);
end;
end;
end.