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

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.