358 lines
12 KiB
Plaintext
358 lines
12 KiB
Plaintext
{*******************************************************}
|
|
{ }
|
|
{ ProcessAlzip }
|
|
{ }
|
|
{ Copyright (C) 2023 kku }
|
|
{ }
|
|
{*******************************************************}
|
|
|
|
unit ProcessAlzip;
|
|
|
|
(********************************************************************************************************************
|
|
Egg.pas
|
|
- Egg.pas는 이스트소프트사에서 공개한 EGG/ALZ의 해제 모듈의 헤더파일인 unegg.h를 델파이 언어로 번역한 것 입니다.
|
|
- 이스트소프트사는 EGG/ALZ 해제 모듈을 상용프로그램에 이용할 때에는 허가를 받을 것을 요구하고 있으므로 주의하십시오.
|
|
- EGG/ALZ 해제 모듈은 32비트와 64비트가 따로 있습니다.(UnEGG32.dll, UnEGG64.dll)
|
|
- Egg.pas는 32비트인 UnEGG32.dll만을 사용합니다.
|
|
- unegg.h를 번역하여 이 유닛을 만든 양병규에게 저작인접권이 있지만 양병규는 저작인접권을 모두 포기합니다.
|
|
- 그러나 원본이 이스트소프트에 권리가 있으므로 이스트소프트가 제시한 라이센스를 그대로 따라야합니다.
|
|
- 즉, Egg.pas와 UnEGG32.dll, UnEGG64.dll를 이용하는 경우에는 이스트소프트사의 라이센스를 따라야합니다.
|
|
- 이스트소프트사가 공개한 자료와 라이센스는 http://www.altools.co.kr/Product/ALZip_Egg.aspx 에 있습니다.
|
|
- 양병규 delmadang@hanmail.net
|
|
*********************************************************************************************************************)
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, System.Classes, System.SysUtils;
|
|
|
|
const
|
|
GG_TYPE_INVALID = 0; // 지원하지 않는 파일
|
|
EGG_TYPE_ALZ = 1; // ALZ파일을 의미합니다.
|
|
EGG_TYPE_EGG = 2; // EGG파일을 의미합니다.
|
|
|
|
EGG_ERROR_SUCCESS = 1; // 성공
|
|
EGG_ERROR_FAIL = 0; // 실패
|
|
EGG_ERROR_SKIP = 2; // 건너뛰기
|
|
EGG_ERROR_CANCEL = 3; // 취소
|
|
EGG_ERROR_IO = 4; // I/O 오류
|
|
EGG_ERROR_TYPEMISMATCH = 5; // 형식이 일치하지 않음
|
|
EGG_ERROR_FILE = 6; // File관련 작업 오류
|
|
EGG_ERROR_FORMAT = 7; // Format관련 오류
|
|
EGG_ERROR_ALGORITHM = 8; // Algorithm 오류
|
|
EGG_ERROR_WRONGPASSWORD = 9; // Password 오류
|
|
|
|
EGG_WORKCODE_NONE = 0; // 기본값
|
|
EGG_WORKCODE_SCAN = 1; // 현재 헤더를 추출하는 중입니다.
|
|
EGG_WORKCODE_EXTRACT = 2; // 현재 압축해제 작업 중입니다.
|
|
EGG_WORKCODE_TEST = 3; // 현재 테스트 작업 중입니다.
|
|
|
|
CODE_Extract = 1;
|
|
CODE_Progress = 2;
|
|
CODE_Start = 3;
|
|
CODE_Finish = 4;
|
|
CODE_ActivityStart = 5;
|
|
CODE_ActivityFinish = 6;
|
|
CODE_QueryPassword = 7;
|
|
CODE_Error = 8;
|
|
CODE_Test = 9;
|
|
|
|
{$IFDEF WIN64}
|
|
// DLL_EGG = 'UnEGG64.dll';
|
|
DLL_EGG = 'Bs1Ugcp.dll';
|
|
{$ELSE}
|
|
DLL_EGG = 'UnEGG32.dll';
|
|
{$ENDIF}
|
|
|
|
type
|
|
size_t = NativeUInt; // DWORD;
|
|
time_t = LONGLONG;
|
|
|
|
egg_handle = THandle; // size_t;
|
|
egg_type = Integer;
|
|
|
|
Psize_t = ^size_t;
|
|
Pegg_type = ^egg_type;
|
|
Pegg_handle = ^egg_handle;
|
|
|
|
PExtract = ^Extract;
|
|
Extract = packed record
|
|
index: size_t;
|
|
nameInArchive: PWideChar;
|
|
fileName: array[0..MAX_PATH-1] of WideChar;
|
|
end;
|
|
|
|
PProgress = ^Progress;
|
|
Progress = packed record
|
|
total: SHORT;
|
|
current: SHORT;
|
|
end;
|
|
|
|
PStart = ^Start;
|
|
Start = packed record
|
|
code: UINT;
|
|
end;
|
|
|
|
PFinish = ^Finish;
|
|
Finish = packed record
|
|
code: UINT;
|
|
result: UINT;
|
|
end;
|
|
|
|
PActivityStart = ^ActivityStart;
|
|
ActivityStart = packed record
|
|
index: size_t;
|
|
code: UINT;
|
|
end;
|
|
|
|
PActivityFinish = ^ActivityFinish;
|
|
ActivityFinish = packed record
|
|
index: size_t;
|
|
code: UINT;
|
|
result: UINT;
|
|
end;
|
|
|
|
PQueryPassword = ^QueryPassword;
|
|
QueryPassword = packed record
|
|
index: size_t;
|
|
queryCount: size_t;
|
|
password: array[0..1023] of WideChar;
|
|
end;
|
|
|
|
PError = ^Error;
|
|
Error = packed record
|
|
index: size_t;
|
|
code: UINT;
|
|
end;
|
|
|
|
PTest = ^Test;
|
|
Test = packed record
|
|
index: size_t;
|
|
nameInArchive: PWideChar;
|
|
skipThisFile: BOOL;
|
|
end;
|
|
|
|
TFileSize = packed record
|
|
SizeHigh: Cardinal;
|
|
SizeLow: Cardinal;
|
|
end;
|
|
|
|
PEGGFileHeader = ^TEGGFileHeader;
|
|
TEGGFileHeader = packed record
|
|
size: size_t;
|
|
fileName: PWideChar;
|
|
comment: PWideChar;
|
|
llPackedSize,
|
|
llUnpackedSize: ULONGLONG;
|
|
nAttr: DWORD;
|
|
crc: DWORD;
|
|
dwMethod: DWORD;
|
|
lastModified: time_t;
|
|
bEnc: Boolean;
|
|
end;
|
|
|
|
PEggExtractUserData = ^TEggExtractUserData;
|
|
TEggExtractUserData = record
|
|
bExistsFail: Boolean;
|
|
sExportDir: String;
|
|
arrFiles: array of String;
|
|
ExtrFileList: TStrings;
|
|
end;
|
|
|
|
TProcAlzipWork = function(pUserData: PEggExtractUserData; code: UINT; extractData: PExtract): UINT; cdecl;
|
|
// TProcAlzipWork = function(pUserData: Pointer; code: UINT; extractData: Pointer): UINT; cdecl;
|
|
|
|
TEGG_CreateEgg = function(handle: Pegg_handle; eventProc: TProcAlzipWork; user: Pointer): UINT; cdecl;
|
|
TEGG_DestroyEgg = function(handle: Pegg_handle): UINT; cdecl;
|
|
TEGG_IsValidArchive = function(fileName: PWideChar; result: Pegg_type): UINT; cdecl;
|
|
TEGG_OpenArchive = function(handle: egg_handle; fileName: PWideChar): UINT; cdecl;
|
|
TEGG_CloseArchive = function(handle: egg_handle): UINT; cdecl;
|
|
TEGG_Extract = function(handle: egg_handle): UINT; cdecl;
|
|
TEGG_Test = function(handle: egg_handle): UINT; cdecl;
|
|
TEGG_GetFileCount = function(handle: egg_handle; count: Psize_t): UINT; cdecl;
|
|
TEGG_GetFileHeader = function(handle: egg_handle; index: size_t; header: PEGGFileHeader): UINT; cdecl;
|
|
|
|
function EGG_CreateEgg(handle: Pegg_handle; eventProc: TProcAlzipWork; user: Pointer): UINT;
|
|
function EGG_DestroyEgg(handle: Pegg_handle): UINT;
|
|
function EGG_IsValidArchive(fileName: PWideChar; eggType: Pegg_type): UINT;
|
|
function EGG_OpenArchive(handle: egg_handle; fileName: PWideChar): UINT;
|
|
//function EGG_OpenArchive(handle: egg_handle; fileName: PUTF8Char): UINT;
|
|
function EGG_CloseArchive(handle: egg_handle): UINT;
|
|
function EGG_Extract(handle: egg_handle): UINT;
|
|
function EGG_Test(handle: egg_handle): UINT;
|
|
function EGG_GetFileCount(handle: egg_handle; count: Psize_t): UINT;
|
|
function EGG_GetFileHeader(handle: egg_handle; index: size_t; header: PEGGFileHeader): UINT;
|
|
|
|
function ExtractAlzipData(sPath, sExportDir: String; ExtrFileList: TStrings; bExistsFail: Boolean = false): Boolean;
|
|
|
|
implementation
|
|
|
|
var
|
|
hEggLib: THandle = 0;
|
|
_fnEGG_CreateEgg: TEGG_CreateEgg = nil;
|
|
_fnEGG_DestroyEgg: TEGG_DestroyEgg = nil;
|
|
_fnEGG_IsValidArchive: TEGG_IsValidArchive = nil;
|
|
_fnEGG_OpenArchive: TEGG_OpenArchive = nil;
|
|
_fnEGG_CloseArchive: TEGG_CloseArchive = nil;
|
|
_fnEGG_Extract: TEGG_Extract = nil;
|
|
_fnEGG_Test: TEGG_Test = nil;
|
|
_fnEGG_GetFileCount: TEGG_GetFileCount = nil;
|
|
_fnEGG_GetFileHeader: TEGG_GetFileHeader = nil;
|
|
|
|
function InitEggLib: Boolean;
|
|
begin
|
|
if hEggLib = 0 then
|
|
begin
|
|
hEggLib := LoadLibrary(DLL_EGG);
|
|
if hEggLib <> 0 then
|
|
begin
|
|
@_fnEGG_CreateEgg := GetProcAddress(hEggLib, 'EGG_CreateEgg');
|
|
@_fnEGG_DestroyEgg := GetProcAddress(hEggLib, 'EGG_DestroyEgg');
|
|
@_fnEGG_IsValidArchive := GetProcAddress(hEggLib, 'EGG_IsValidArchive');
|
|
@_fnEGG_OpenArchive := GetProcAddress(hEggLib, 'EGG_OpenArchive');
|
|
@_fnEGG_CloseArchive := GetProcAddress(hEggLib, 'EGG_CloseArchive');
|
|
@_fnEGG_Extract := GetProcAddress(hEggLib, 'EGG_Extract');
|
|
@_fnEGG_Test := GetProcAddress(hEggLib, 'EGG_Test');
|
|
@_fnEGG_GetFileCount := GetProcAddress(hEggLib, 'EGG_GetFileCount');
|
|
@_fnEGG_GetFileHeader := GetProcAddress(hEggLib, 'EGG_GetFileHeader');
|
|
end;
|
|
end;
|
|
Result := hEggLib <> 0;
|
|
end;
|
|
|
|
function EGG_CreateEgg(handle: Pegg_handle; eventProc: TProcAlzipWork; user: Pointer): UINT;
|
|
begin
|
|
Result := EGG_ERROR_FAIL;
|
|
if InitEggLib and Assigned(_fnEGG_CreateEgg) then
|
|
Result := _fnEGG_CreateEgg(handle, eventProc, user);
|
|
end;
|
|
|
|
function EGG_DestroyEgg(handle: Pegg_handle): UINT;
|
|
begin
|
|
Result := EGG_ERROR_FAIL;
|
|
if InitEggLib and Assigned(_fnEGG_DestroyEgg) then
|
|
Result := _fnEGG_DestroyEgg(handle);
|
|
end;
|
|
|
|
function EGG_IsValidArchive(fileName: PWideChar; eggType: Pegg_type): UINT;
|
|
begin
|
|
Result := EGG_ERROR_FAIL;
|
|
if InitEggLib and Assigned(_fnEGG_IsValidArchive) then
|
|
Result := _fnEGG_IsValidArchive(fileName, eggType);
|
|
end;
|
|
|
|
function EGG_OpenArchive(handle: egg_handle; fileName: PWideChar): UINT;
|
|
begin
|
|
Result := EGG_ERROR_FAIL;
|
|
if InitEggLib and Assigned(_fnEGG_OpenArchive) then
|
|
Result := _fnEGG_OpenArchive(handle, fileName);
|
|
end;
|
|
|
|
function EGG_CloseArchive(handle: egg_handle): UINT;
|
|
begin
|
|
Result := EGG_ERROR_FAIL;
|
|
if InitEggLib and Assigned(_fnEGG_CloseArchive) then
|
|
Result := _fnEGG_CloseArchive(handle);
|
|
end;
|
|
|
|
function EGG_Extract(handle: egg_handle): UINT;
|
|
begin
|
|
Result := EGG_ERROR_FAIL;
|
|
if InitEggLib and Assigned(_fnEGG_Extract) then
|
|
Result := _fnEGG_Extract(handle);
|
|
end;
|
|
|
|
function EGG_Test(handle: egg_handle): UINT;
|
|
begin
|
|
Result := EGG_ERROR_FAIL;
|
|
if InitEggLib and Assigned(_fnEGG_Test) then
|
|
Result := _fnEGG_Test(handle);
|
|
end;
|
|
|
|
function EGG_GetFileCount(handle: egg_handle; count: Psize_t): UINT;
|
|
begin
|
|
Result := EGG_ERROR_FAIL;
|
|
if InitEggLib and Assigned(_fnEGG_GetFileCount) then
|
|
Result := _fnEGG_GetFileCount(handle, count);
|
|
end;
|
|
|
|
function EGG_GetFileHeader(handle: egg_handle; index: size_t; header: PEGGFileHeader): UINT;
|
|
begin
|
|
Result := EGG_ERROR_FAIL;
|
|
if InitEggLib and Assigned(_fnEGG_GetFileHeader) then
|
|
Result := _fnEGG_GetFileHeader(handle, index, header);
|
|
end;
|
|
|
|
function ProcessAlzipWork(pUserData: PEggExtractUserData; code: UINT; extractData: PExtract): UINT; cdecl;
|
|
var
|
|
sExtractPath: String;
|
|
begin
|
|
Result := EGG_ERROR_SUCCESS;
|
|
|
|
case code of
|
|
CODE_Extract :
|
|
begin
|
|
sExtractPath := pUserData.sExportDir + pUserData.arrFiles[extractData.index];
|
|
if ForceDirectories(ExtractFilePath(sExtractPath)) then
|
|
begin
|
|
if not pUserData.bExistsFail and FileExists(sExtractPath) then
|
|
DeleteFile(PChar(sExtractPath));
|
|
|
|
StrCopy(@extractData.fileName, PWideChar(sExtractPath));
|
|
pUserData.ExtrFileList.Add(sExtractPath);
|
|
end;
|
|
end;
|
|
CODE_QueryPassword : ;
|
|
CODE_Error : Result := EGG_ERROR_CANCEL;
|
|
end;
|
|
end;
|
|
|
|
function ExtractAlzipData(sPath, sExportDir: String; ExtrFileList: TStrings; bExistsFail: Boolean = false): Boolean;
|
|
var
|
|
EggType: egg_type;
|
|
hEgg: egg_handle;
|
|
EggUserData: TEggExtractUserData;
|
|
nFileCnt: size_t;
|
|
i: Integer;
|
|
EggFileHeader: TEGGFileHeader;
|
|
bExtract: Boolean;
|
|
begin
|
|
Result := false;
|
|
if EGG_IsValidArchive(PChar(sPath), @EggType) = EGG_ERROR_SUCCESS then
|
|
begin
|
|
hEgg := 0;
|
|
ExtrFileList.Clear;
|
|
ZeroMemory(@EggUserData, SizeOf(EggUserData));
|
|
EggUserData.bExistsFail := bExistsFail;
|
|
EggUserData.ExtrFileList := ExtrFileList;
|
|
|
|
if EGG_CreateEgg(@hEgg, ProcessAlzipWork, @EggUserData) = EGG_ERROR_SUCCESS then
|
|
begin
|
|
if EGG_OpenArchive(hEgg, PChar(sPath)) = EGG_ERROR_SUCCESS then
|
|
begin
|
|
if EGG_GetFileCount(hEgg, @nFileCnt) = EGG_ERROR_SUCCESS then
|
|
if nFileCnt > 0 then
|
|
begin
|
|
bExtract := true;
|
|
EggUserData.sExportDir := IncludeTrailingPathDelimiter(sExportDir);
|
|
SetLength(EggUserData.arrFiles, nFileCnt);
|
|
for i := 0 to nFileCnt - 1 do
|
|
if EGG_GetFileHeader(hEgg, i, @EggFileHeader) = EGG_ERROR_SUCCESS then
|
|
begin
|
|
EggUserData.arrFiles[i] := StringReplace(EggFileHeader.fileName, '/', '\', [rfReplaceAll]);
|
|
end else begin
|
|
bExtract := false;
|
|
break;
|
|
end;
|
|
|
|
if bExtract then Result := EGG_Extract(hEgg) = EGG_ERROR_SUCCESS;
|
|
end;
|
|
EGG_CloseArchive(hEgg);
|
|
end;
|
|
EGG_DestroyEgg(@hEgg);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|