443 lines
12 KiB
Plaintext
443 lines
12 KiB
Plaintext
{*******************************************************}
|
|
{ }
|
|
{ ProcessDecompress }
|
|
{ }
|
|
{ Copyright (C) 2023 kku }
|
|
{ }
|
|
{*******************************************************}
|
|
|
|
unit ProcessDecompress;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils, System.Classes, AbArcTyp, AbZipTyp, AbUtils;
|
|
|
|
const
|
|
SIG_CANCEL = '*CANCEL$';
|
|
DLL_7Z = '7z.dll';
|
|
|
|
function DecompressFile(sSrcPath, sExportPath: String;
|
|
aEvtProg: TAbArchiveProgressEvent; aEvtNeedPass: TAbNeedPasswordEvent): string;
|
|
|
|
procedure ExtractZip(sSrcPath, sExportPath: String;
|
|
aEvtProg: TAbArchiveProgressEvent; aEvtNeedPass: TAbNeedPasswordEvent);
|
|
procedure ExtractCab(sSrcPath, sExportPath: String; aEvtProg: TAbArchiveProgressEvent);
|
|
procedure ExtractTar(sSrcPath, sExportPath: String; aEvtProg: TAbArchiveProgressEvent);
|
|
function ExtractGzip(sSrcPath, sExportPath: String; IsGzippedTar: Boolean; aEvtProg: TAbArchiveProgressEvent): string;
|
|
function ExtractBzip2(sSrcPath, sExportPath: String; bIsBzippedTar: Boolean; aEvtProg: TAbArchiveProgressEvent): string;
|
|
function Extract7zip(ArcType: TAbArchiveType; sSrcPath, sExportPath: String): string;
|
|
|
|
implementation
|
|
|
|
uses
|
|
AbUnzper, AbCabExt, AbCabTyp, AbGzTyp, AbBzip2Typ, AbTarTyp,
|
|
AbUnzPrc, ProcessAlzip, Process7zip, Tocsg.Exception, Tocsg.Trace, Tocsg.Safe,
|
|
Tocsg.Files, Tocsg.Path;
|
|
|
|
function DecompressFile(sSrcPath, sExportPath: String;
|
|
aEvtProg: TAbArchiveProgressEvent; aEvtNeedPass: TAbNeedPasswordEvent): string;
|
|
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..');
|
|
Result:= 'unable to analysis to 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;
|
|
|
|
TTgTrace.T('[MGKIM].. ArcType : %d', [Integer(ArcType)]);
|
|
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 Result:= Extract7zip(ArcType, sSrcPath, sExportPath);
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
begin
|
|
ETgException.TraceException(E, 'Fail .. DecompressFile() .. DoDecompress');
|
|
Result:= 'unable to analysis to decompress file';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
type
|
|
TZipErrorHelper = class
|
|
public
|
|
HasError: Boolean;
|
|
procedure OnFailure(Sender: TObject; Item: TAbArchiveItem;
|
|
ProcessType: TAbProcessType; ErrorClass: TAbErrorClass; ErrorCode: Integer);
|
|
end;
|
|
|
|
procedure TZipErrorHelper.OnFailure(Sender: TObject; Item: TAbArchiveItem;
|
|
ProcessType: TAbProcessType; ErrorClass: TAbErrorClass; ErrorCode: Integer);
|
|
begin
|
|
if ProcessType = ptExtract then
|
|
HasError := True;
|
|
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('*.*');
|
|
TTgTrace.T('[MGKIM] ExtractZip() .. ok', []);
|
|
except
|
|
on E: Exception do
|
|
// DeleteDir(sExportPath);
|
|
TTgTrace.T('[MGKIM] ExtractZip() .. Fail extract compress file.. Path=%s, E.Message : %s', [sSrcPath, E.Message]);
|
|
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
|
|
on E: Exception do
|
|
// DeleteDir(sExportPath);
|
|
TTgTrace.T('ExtractGzip() .. Fail extract zip file.. Path="%s"', [sSrcPath]);
|
|
end;
|
|
end;
|
|
|
|
function ExtractGzip(sSrcPath, sExportPath: String; IsGzippedTar: Boolean; aEvtProg: TAbArchiveProgressEvent): string;
|
|
var
|
|
gzip: TAbGzipArchive;
|
|
i: Integer;
|
|
sUnknownExt,
|
|
sUnknownName: String;
|
|
zHelper: TZipErrorHelper;
|
|
begin
|
|
Result := '';
|
|
if DirectoryExists(sExportPath) then
|
|
DeleteDir(sExportPath);
|
|
|
|
if not ForceDirectories(sExportPath) then
|
|
exit;
|
|
|
|
sExportPath := IncludeTrailingPathDelimiter(sExportPath);
|
|
|
|
try
|
|
|
|
Guard(gzip, TAbGzipArchive.Create(sSrcPath, WORD(fmOpenRead)));
|
|
zHelper := TZipErrorHelper.Create;
|
|
zHelper.HasError := False;
|
|
|
|
try
|
|
gzip.TarAutoHandle := true;
|
|
gzip.IsGzippedTar := IsGzippedTar;
|
|
gzip.ExtractOptions := [eoCreateDirs, eoRestorePath];
|
|
gzip.BaseDirectory := sExportPath;
|
|
gzip.OnArchiveProgress := aEvtProg;
|
|
gzip.OnProcessItemFailure := zHelper.OnFailure;
|
|
// 파일명 정보가 존재하지 않을때 반디집처럼 압축 파일이름(.gz 제외 한)으로 대체 되도록 보완
|
|
sUnknownName := ExtractFileName(CutFileExt(sSrcPath)); // 경로와 .gz 빼줌
|
|
sUnknownExt := ExtractFileExt(sUnknownName);
|
|
sUnknownName := CutFileExt(sUnknownName);
|
|
|
|
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('*.*');
|
|
|
|
if zHelper.HasError then
|
|
begin
|
|
Result := 'unable to analysis';
|
|
end;
|
|
except
|
|
// DeleteDir(sExportPath);
|
|
TTgTrace.T('ExtractGzip() .. Fail extract zip file.. Path="%s"', [sSrcPath]);
|
|
Result := 'unable to analysis';
|
|
end;
|
|
finally
|
|
zHelper.Free;
|
|
end;
|
|
end;
|
|
|
|
function ExtractBzip2(sSrcPath, sExportPath: String; bIsBzippedTar: Boolean; aEvtProg: TAbArchiveProgressEvent): string;
|
|
var
|
|
bzip2: TAbBzip2Archive;
|
|
zHelper: TZipErrorHelper;
|
|
begin
|
|
Result:= '';
|
|
if DirectoryExists(sExportPath) then
|
|
DeleteDir(sExportPath);
|
|
|
|
if not ForceDirectories(sExportPath) then
|
|
exit;
|
|
sExportPath := IncludeTrailingPathDelimiter(sExportPath);
|
|
|
|
zHelper := TZipErrorHelper.Create;
|
|
zHelper.HasError := False;
|
|
Guard(bzip2, TAbBzip2Archive.Create(sSrcPath, WORD(fmOpenRead)));
|
|
try
|
|
bzip2.TarAutoHandle := true;
|
|
bzip2.IsBzippedTar := bIsBzippedTar;
|
|
bzip2.ExtractOptions := [eoCreateDirs, eoRestorePath];
|
|
bzip2.BaseDirectory := sExportPath;
|
|
bzip2.OnProcessItemFailure := zHelper.OnFailure;
|
|
try
|
|
bzip2.Load;
|
|
bzip2.ExtractFiles('*.*');
|
|
|
|
if zHelper.HasError then
|
|
begin
|
|
Result := 'unable to analysis'; // 에러 상태 반환
|
|
end;
|
|
|
|
except
|
|
// DeleteDir(sExportPath);
|
|
TTgTrace.T('ExtractBzip2() .. Fail extract zip file.. Path="%s"', [sSrcPath]);
|
|
Result := 'unable to analysis';
|
|
end;
|
|
finally
|
|
zHelper.Free;
|
|
end;
|
|
end;
|
|
|
|
function Extract7zip(ArcType: TAbArchiveType; sSrcPath, sExportPath: String): 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;
|
|
state: NExtOperationResult;
|
|
begin
|
|
Result:= '';
|
|
s7zDll := GetRunExePathDir + DLL_7Z;
|
|
if not FileExists(s7zDll) then
|
|
exit;
|
|
|
|
if ArcType = atUnknown then
|
|
begin
|
|
try
|
|
fs := TFileStream.Create(sSrcPath, fmOpenRead);
|
|
except
|
|
on E: Exception do
|
|
begin
|
|
ETgException.TraceException(E, 'Extract7zip() .. Fail .. open file..');
|
|
Result:= 'unalbe to analysis to open file';
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
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;
|
|
end
|
|
else
|
|
begin
|
|
case ArcType of
|
|
// atUnknown : ;
|
|
atZip ,
|
|
atSpannedZip : TId := CLSID_CFormatZip;
|
|
atTar : TId := CLSID_CFormatTar;
|
|
atGzip : TId := CLSID_CFormatGZip;
|
|
atCab : TId := CLSID_CFormatCab;
|
|
else Exit;
|
|
end;
|
|
end;
|
|
|
|
try
|
|
|
|
SvZip := CreateInArchive(Tid, s7zDll);
|
|
SvZip.OpenFile(sSrcPath);
|
|
SvZip.SetPassword('1234');
|
|
state:= SvZip.ExtractTo(sExportPath);
|
|
|
|
if state <> kOK then
|
|
begin
|
|
TTgTrace.T('[MGKIM] Extract7zip() .. Fail, state: %d', [Integer(state)]);
|
|
|
|
case state of
|
|
// kDataError,
|
|
// kUnavailable,
|
|
// kUnexpectedEnd,
|
|
// kDataAfterEnd,
|
|
// kIsNotArc,
|
|
// kHeadersError: Result:= 'unalbe to analysis';
|
|
kWrongPassword: Result:= 'unable to analysis to password';
|
|
else Result:= Format('unable to analysis(%d)', [Integer(state)]);
|
|
end;
|
|
|
|
end;
|
|
|
|
except
|
|
on E: Exception do
|
|
begin
|
|
TTgTrace.T('[MGKIM] Extract7zip() .. Fail extract compress file.. Path=%s, E.Message : %s', [sSrcPath, E.Message]);
|
|
Result:= 'unable to analysis to decompress file';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|