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

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.