UPD: Initial wcx file source (listing files only).

This commit is contained in:
cobines 2009-07-31 14:34:07 +00:00
commit a23f6a5be4
7 changed files with 1494 additions and 584 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,148 @@
unit uArchiveFile;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
uLocalFile, uFile, uFileProperty;
type
TArchiveFile = class(TLocalFile)
private
FSize: TFileSizeProperty;
FCompressedSize: TFileSizeProperty; // TFileCompressedSizeProperty?
FAttributes: TFileAttributesProperty;
FModificationTime: TFileModificationDateTimeProperty;
procedure AssignProperties;
protected
function GetAttributes: Cardinal; virtual;
procedure SetAttributes(NewAttributes: Cardinal); virtual;
function GetSize: Int64; virtual;
procedure SetSize(NewSize: Int64); virtual;
function GetCompressedSize: Int64; virtual;
procedure SetCompressedSize(NewCompressedSize: Int64); virtual;
function GetModificationTime: TDateTime; virtual;
procedure SetModificationTime(NewTime: TDateTime); virtual;
public
constructor Create; override;
destructor Destroy; override;
{en
Creates an identical copy of the object (as far as object data is concerned).
}
function Clone: TArchiveFile; override;
procedure CloneTo(AFile: TFile); override;
class function GetSupportedProperties: TFilePropertiesTypes; override;
property Size: Int64 read GetSize write SetSize;
property CompressedSize: Int64 read GetCompressedSize write SetCompressedSize;
property Attributes: Cardinal read GetAttributes write SetAttributes;
property ModificationTime: TDateTime read GetModificationTime write SetModificationTime;
end;
implementation
constructor TArchiveFile.Create;
begin
FSize := TFileSizeProperty.Create;
FCompressedSize := TFileSizeProperty.Create;
FAttributes := TNtfsFileAttributesProperty.Create;
FModificationTime := TFileModificationDateTimeProperty.Create;
AssignProperties;
// Set name after assigning Attributes property, because it is used to get extension.
Name := '';
end;
destructor TArchiveFile.Destroy;
begin
if Assigned(FAttributes) then
FreeAndNil(FAttributes);
if Assigned(FSize) then
FreeAndNil(FSize);
if Assigned(FCompressedSize) then
FreeAndNil(FCompressedSize);
if Assigned(FModificationTime) then
FreeAndNil(FModificationTime);
inherited;
end;
function TArchiveFile.Clone: TArchiveFile;
begin
Result := TArchiveFile.Create;
CloneTo(Result);
end;
procedure TArchiveFile.CloneTo(AFile: TFile);
begin
if Assigned(AFile) then
begin
inherited CloneTo(AFile);
// All properties are cloned in base class.
end;
end;
procedure TArchiveFile.AssignProperties;
begin
FProperties[fpSize] := FSize;
FProperties[fpCompressedSize] := FCompressedSize;
FProperties[fpAttributes] := FAttributes;
FProperties[fpModificationTime] := FModificationTime;
end;
class function TArchiveFile.GetSupportedProperties: TFilePropertiesTypes;
begin
Result := [{fpName, }fpSize, fpCompressedSize, fpAttributes, fpModificationTime];
end;
function TArchiveFile.GetAttributes: Cardinal;
begin
Result := FAttributes.Value;
end;
procedure TArchiveFile.SetAttributes(NewAttributes: Cardinal);
begin
FAttributes.Value := NewAttributes;
end;
function TArchiveFile.GetSize: Int64;
begin
Result := FSize.Value;
end;
procedure TArchiveFile.SetSize(NewSize: Int64);
begin
FSize.Value := NewSize;
end;
function TArchiveFile.GetCompressedSize: Int64;
begin
Result := FCompressedSize.Value;
end;
procedure TArchiveFile.SetCompressedSize(NewCompressedSize: Int64);
begin
FCompressedSize.Value := NewCompressedSize;
end;
function TArchiveFile.GetModificationTime: TDateTime;
begin
Result := FModificationTime.Value;
end;
procedure TArchiveFile.SetModificationTime(NewTime: TDateTime);
begin
FModificationTime.Value := NewTime;
end;
end.

View file

@ -0,0 +1,49 @@
unit uArchiveFileSource;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
uLocalFileSource;
type
TArchiveFileSource = class(TLocalFileSource)
private
protected
procedure SetCurrentPath(NewPath: String); override;
property ArchiveFileName: String read FCurrentAddress;
public
constructor Create(anArchiveFileName: String); virtual reintroduce overload;
constructor Create(anArchiveFileName: String; aPath: String); virtual reintroduce overload;
end;
implementation
constructor TArchiveFileSource.Create(anArchiveFileName: String);
begin
Create(anArchiveFileName, '/');
end;
constructor TArchiveFileSource.Create(anArchiveFileName: String; aPath: String);
begin
FCurrentAddress := anArchiveFileName;
SetCurrentPath(aPath);
end;
procedure TArchiveFileSource.SetCurrentPath(NewPath: String);
begin
if (NewPath = '') or (NewPath[1] <> PathDelim) then
begin
; // error - invalid path (throw exception?)
end
else
inherited SetCurrentPath(NewPath);
end;
end.

View file

@ -14,17 +14,24 @@ implementation
uses
uFileSource, uFileSystemFileSource, uGlobs, uShellExecute, uOSUtils,
LCLProc;
uWcxArchiveFileSource, LCLProc;
procedure ChooseFile(aFileView: TFileView; aFile: TFile);
var
sOpenCmd: String;
i: Integer;
FileSource: TFileSource;
begin
// For now work only for FileSystem until temporary file system is done.
if aFileView.FileSource is TFileSystemFileSource then
begin
// Check if it is registered plugin (for archives).
FileSource := TWcxArchiveFileSource.CreateByArchiveName(aFile.Path + aFile.Name);
if Assigned(FileSource) then
begin
aFileView.AddFileSource(FileSource);
Exit;
end;
//now test if exists Open command in doublecmd.ext :)
sOpenCmd:= gExts.GetExtActionCmd(aFile, 'open');
if (sOpenCmd<>'') then

View file

@ -0,0 +1,42 @@
unit uWcxArchiveFile;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
uArchiveFile, uWcxArchiveFileSource;
type
TWcxArchiveFile = class(TArchiveFile)
public
constructor Create(WcxHeader: TWCXHeader); overload;
end;
implementation
constructor TWcxArchiveFile.Create(WcxHeader: TWCXHeader);
begin
inherited Create;
{
FileCRC,
CompressionMethod,
Comment,
}
Size := WcxHeader.UnpSize;
CompressedSize := WcxHeader.PackSize;
Attributes := {TNtfsFileAttributesProperty or Unix?} WcxHeader.FileAttr;
try
ModificationTime := FileDateToDateTime(WcxHeader.FileTime);
except
ModificationTime := 0;
end;
// Set name after assigning Attributes property, because it is used to get extension.
Name := ExtractFileName(WcxHeader.FileName);
end;
end.

View file

@ -0,0 +1,566 @@
unit uWcxArchiveFileSource;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, contnrs, Dialogs, DialogAPI,
uWCXprototypes, uWCXhead, dynlibs, uClassesEx,
StringHashList, uFile, uFileSourceProperty, uFileSourceOperationTypes,
uArchiveFileSource, uFileProperty, uFileSource, uFileSourceOperation;
type
{ Handles THeaderData and THeaderDataEx }
TWCXHeader = class
private
function PCharLToUTF8(CharString: PChar; MaxSize: Integer): UTF8String;
public
ArcName: UTF8String;
FileName: UTF8String;
Flags,
HostOS,
FileCRC,
FileTime,
UnpVer,
Method,
FileAttr: Longint;
PackSize,
UnpSize: Int64;
Cmt: UTF8String;
CmtState: Longint;
constructor Create(const Data: PHeaderData); overload;
constructor Create(const Data: PHeaderDataEx); overload;
constructor Create; overload; // allows creating empty record
end;
TWcxArchiveFileSource = class(TArchiveFileSource)
private
FModuleFileName: String;
FModuleHandle: TLibHandle; // Handle to .DLL or .so
FPluginFlags: PtrInt;
FArcFileList : TObjectList;
// module's functions
//**mandatory:
OpenArchive : TOpenArchive;
ReadHeader : TReadHeader;
ProcessFile : TProcessFile;
CloseArchive : TCloseArchive;
//**optional:
ReadHeaderEx : TReadHeaderEx;
PackFiles : TPackFiles;
DeleteFiles : TDeleteFiles;
GetPackerCaps : TGetPackerCaps;
ConfigurePacker : TConfigurePacker;
SetChangeVolProc : TSetChangeVolProc;
SetProcessDataProc : TSetProcessDataProc;
StartMemPack : TStartMemPack;
PackToMem : TPackToMem;
DoneMemPack : TDoneMemPack;
CanYouHandleThisFile : TCanYouHandleThisFile;
PackSetDefaultParams : TPackSetDefaultParams;
// Dialog API
SetDlgProc: TSetDlgProc;
function LoadModule: Boolean;
procedure UnloadModule;
function ReadArchive(bCanYouHandleThisFile : Boolean = False): Boolean;
{ Reads WCX header using ReadHeaderEx if available or ReadHeader. }
function ReadWCXHeader(hArcData: TArcHandle;
out HeaderData: TWCXHeader): Integer;
protected
class function GetSupportedFileProperties: TFilePropertiesTypes; override;
public
constructor Create(anArchiveFileName: String;
aWcxPluginFileName: String;
aWcxPluginFlags: PtrInt); reintroduce;
destructor Destroy; override;
function Clone: TWcxArchiveFileSource; override;
procedure CloneTo(FileSource: TFileSource); override;
// Retrieve operations permitted on the source. = capabilities?
class function GetOperationsTypes: TFileSourceOperationTypes; override;
// Returns a list of property types supported by this source for each file.
class function GetFilePropertiesDescriptions: TFilePropertiesDescriptions; override;
// Retrieve some properties of the file source.
class function GetProperties: TFileSourceProperties; override;
// These functions create an operation object specific to the file source.
// Each parameter will be owned by the operation (will be freed).
function CreateListOperation: TFileSourceOperation; override;
{ function CreateCopyInOperation(var SourceFileSource: TFileSource;
var SourceFiles: TFiles;
TargetPath: String;
RenameMask: String): TFileSourceOperation; virtual abstract;
function CreateCopyOutOperation(var TargetFileSource: TFileSource;
var SourceFiles: TFiles;
TargetPath: String;
RenameMask: String): TFileSourceOperation; virtual abstract;
function CreateDeleteOperation(var FilesToDelete: TFiles): TFileSourceOperation; virtual abstract;
}
class function CreateByArchiveName(anArchiveFileName: String): TWcxArchiveFileSource;
property ArchiveFileList: TObjectList read FArcFileList;
end;
implementation
uses Forms, Masks, uGlobs, uLog, uOSUtils, LCLProc,
uDCUtils, uLng, Controls, fPackInfoDlg, fDialogBox, uGlobsPaths, FileUtil,
uFileProcs, uFileSystemFile, uWcxArchiveListOperation;
const
WcxIniFileName = 'wcx.ini';
{var
WCXModule : TWCXModule = nil; // used in ProcessDataProc}
class function TWcxArchiveFileSource.CreateByArchiveName(anArchiveFileName: String): TWcxArchiveFileSource;
var
i: Integer;
ModuleFileName: String;
sExtension: String;
begin
Result := nil;
// Check if there is a registered plugin for the extension of the archive file name.
for i := 0 to gWCXPlugins.Count - 1 do
begin
sExtension := ExtractFileExt(anArchiveFileName);
if sExtension <> '' then // delete '.' at the front
Delete(sExtension, 1, 1);
if sExtension = gWCXPlugins.Ext[i] then
begin
ModuleFileName := GetCmdDirFromEnvVar(gWCXPlugins.FileName[I]);
Result := TWcxArchiveFileSource.Create(anArchiveFileName,
ModuleFileName,
gWCXPlugins.Flags[I]);
debugln('Registered plugin ' + ModuleFileName + ' for archive');
break;
end;
end;
end;
// ----------------------------------------------------------------------------
constructor TWcxArchiveFileSource.Create(anArchiveFileName: String;
aWcxPluginFileName: String;
aWcxPluginFlags: PtrInt);
begin
inherited Create(anArchiveFileName);
FModuleFileName := aWcxPluginFileName;
FPluginFlags := aWcxPluginFlags;
FArcFileList := TObjectList.Create(True);
FModuleHandle := 0;
LoadModule;
ReadArchive;
end;
destructor TWcxArchiveFileSource.Destroy;
begin
if Assigned(FArcFileList) then
FreeAndNil(FArcFileList);
UnloadModule;
end;
function TWcxArchiveFileSource.Clone: TWcxArchiveFileSource;
begin
Result := TWcxArchiveFileSource.Create(FCurrentAddress, FModuleFileName, FPluginFlags);
CloneTo(Result);
end;
procedure TWcxArchiveFileSource.CloneTo(FileSource: TFileSource);
begin
if Assigned(FileSource) then
begin
inherited CloneTo(FileSource);
// Clone FArcFileList : TList;
// probably don't copy module handle and function addresses?
end;
end;
class function TWcxArchiveFileSource.GetOperationsTypes: TFileSourceOperationTypes;
begin
Result := [fsoList];
end;
class function TWcxArchiveFileSource.GetFilePropertiesDescriptions: TFilePropertiesDescriptions;
begin
Result := nil;
end;
class function TWcxArchiveFileSource.GetProperties: TFileSourceProperties;
begin
Result := [];
end;
class function TWcxArchiveFileSource.GetSupportedFileProperties: TFilePropertiesTypes;
begin
Result := [];
end;
function TWcxArchiveFileSource.LoadModule: Boolean;
var
PackDefaultParamStruct : TPackDefaultParamStruct;
SetDlgProcInfo: TSetDlgProcInfo;
sPluginDir: WideString;
sPluginConfDir: WideString;
begin
FModuleHandle := mbLoadLibrary(FModuleFileName);
debugln('loaded ' + FModuleFileName + ' at ' + hexStr(Pointer(FModuleHandle)));
if FModuleHandle = 0 then
Exit;
// mandatory functions
OpenArchive:= TOpenArchive(GetProcAddress(FModuleHandle,'OpenArchive'));
ReadHeader:= TReadHeader(GetProcAddress(FModuleHandle,'ReadHeader'));
ReadHeaderEx:= TReadHeaderEx(GetProcAddress(FModuleHandle,'ReadHeaderEx'));
ProcessFile:= TProcessFile(GetProcAddress(FModuleHandle,'ProcessFile'));
CloseArchive:= TCloseArchive(GetProcAddress(FModuleHandle,'CloseArchive'));
if (OpenArchive = nil) or (ReadHeader = nil) or
(ProcessFile = nil) or (CloseArchive = nil) then
begin
OpenArchive := nil;
ReadHeader:= nil;
ProcessFile := nil;
CloseArchive := nil;
Result := False;
Exit;
end;
// optional functions
PackFiles:= TPackFiles(GetProcAddress(FModuleHandle,'PackFiles'));
DeleteFiles:= TDeleteFiles(GetProcAddress(FModuleHandle,'DeleteFiles'));
GetPackerCaps:= TGetPackerCaps(GetProcAddress(FModuleHandle,'GetPackerCaps'));
ConfigurePacker:= TConfigurePacker(GetProcAddress(FModuleHandle,'ConfigurePacker'));
SetChangeVolProc:= TSetChangeVolProc(GetProcAddress(FModuleHandle,'SetChangeVolProc'));
SetProcessDataProc:= TSetProcessDataProc(GetProcAddress(FModuleHandle,'SetProcessDataProc'));
StartMemPack:= TStartMemPack(GetProcAddress(FModuleHandle,'StartMemPack'));
PackToMem:= TPackToMem(GetProcAddress(FModuleHandle,'PackToMem'));
DoneMemPack:= TDoneMemPack(GetProcAddress(FModuleHandle,'DoneMemPack'));
CanYouHandleThisFile:= TCanYouHandleThisFile(GetProcAddress(FModuleHandle,'CanYouHandleThisFile'));
PackSetDefaultParams:= TPackSetDefaultParams(GetProcAddress(FModuleHandle,'PackSetDefaultParams'));
// Dialog API function
SetDlgProc:= TSetDlgProc(GetProcAddress(FModuleHandle,'SetDlgProc'));
if Assigned(PackSetDefaultParams) then
begin
with PackDefaultParamStruct do
begin
Size := SizeOf(PackDefaultParamStruct);
PluginInterfaceVersionLow := 10;
PluginInterfaceVersionHi := 2;
DefaultIniName := gpIniDir + WcxIniFileName;
end;
PackSetDefaultParams(@PackDefaultParamStruct);
end;
// Dialog API
if Assigned(SetDlgProc) then
begin
sPluginDir := UTF8Decode(ExtractFilePath(FModuleFileName));
sPluginConfDir := UTF8Decode(gpIniDir);
with SetDlgProcInfo do
begin
PluginDir:= PWideChar(sPluginDir);
PluginConfDir:= PWideChar(sPluginConfDir);
InputBox:= @fDialogBox.InputBox;
MessageBox:= @fDialogBox.MessageBox;
DialogBox:= @fDialogBox.DialogBox;
DialogBoxEx:= @fDialogBox.DialogBoxEx;
SendDlgMsg:= @fDialogBox.SendDlgMsg;
end;
SetDlgProc(SetDlgProcInfo);
end;
Result := True;
end;
procedure TWcxArchiveFileSource.UnloadModule;
begin
if FModuleHandle <> 0 then
begin
FreeLibrary(FModuleHandle);
FModuleHandle := 0;
end;
OpenArchive:= nil;
ReadHeader:= nil;
ReadHeaderEx:= nil;
ProcessFile:= nil;
CloseArchive:= nil;
PackFiles:= nil;
DeleteFiles:= nil;
GetPackerCaps:= nil;
ConfigurePacker:= nil;
SetChangeVolProc:= nil;
SetProcessDataProc:= nil;
StartMemPack:= nil;
PackToMem:= nil;
DoneMemPack:= nil;
CanYouHandleThisFile:= nil;
PackSetDefaultParams:= nil;
end;
function TWcxArchiveFileSource.CreateListOperation: TFileSourceOperation;
var
TargetFileSource: TWcxArchiveFileSource;
begin
TargetFileSource := Self.Clone;
Result := TWcxArchiveListOperation.Create(TargetFileSource);
end;
function TWcxArchiveFileSource.ReadArchive(bCanYouHandleThisFile : Boolean = False): Boolean;
procedure CollectDirs(Path: PAnsiChar; var DirsList: TStringHashList);
var
I : Integer;
Dir : AnsiString;
begin
// Scan from the second char from the end, to the second char from the beginning.
for I := strlen(Path) - 2 downto 1 do
begin
if Path[I] = PathDelim then
begin
SetString(Dir, Path, I);
if DirsList.Find(Dir) = -1 then
// Add directory and continue scanning for parent directories.
DirsList.Add(Dir)
else
// This directory is already in the list and we assume
// that all parent directories are too.
Exit;
end
end;
end;
var
ArcHandle : TArcHandle;
ArcFile : tOpenArchiveData;
Header: TWCXHeader;
AllDirsList, ExistsDirList : TStringHashList;
I : Integer;
NameLength: Integer;
iResult : Integer;
begin
if not mbFileAccess(ArchiveFileName, fmOpenRead) then
begin
Result := False;
Exit;
end;
if bCanYouHandleThisFile and Assigned(CanYouHandleThisFile) then
begin
Result := CanYouHandleThisFile(PChar(UTF8ToSys(ArchiveFileName)));
if not Result then Exit;
end;
DebugLN('Open Archive');
(*Open Archive*)
FillChar(ArcFile, SizeOf(ArcFile), #0);
ArcFile.ArcName := PChar(UTF8ToSys(ArchiveFileName));
ArcFile.OpenMode := PK_OM_LIST;
try
ArcHandle := OpenArchive(ArcFile);
except
ArcHandle := 0;
end;
if ArcHandle = 0 then
begin
{if not bCanYouHandleThisFile then
ShowErrorMsg(ArcFile.OpenResult);}
Result := False;
Exit;
end;
// WCXModule := Self; // set WCXModule variable to current module
{ SetChangeVolProc(ArcHandle, ChangeVolProc);
SetProcessDataProc(ArcHandle, ProcessDataProc);}
DebugLN('Get File List');
(*Get File List*)
FArcFileList.Clear;
ExistsDirList := TStringHashList.Create(True);
AllDirsList := TStringHashList.Create(True);
try
while (ReadWCXHeader(ArcHandle, Header) = E_SUCCESS) do
begin
// Some plugins end directories with path delimiter. Delete it if present.
if FPS_ISDIR(Header.FileAttr) then
begin
NameLength := Length(Header.FileName);
if (Header.FileName[NameLength] = PathDelim) then
Delete(Header.FileName, NameLength, 1);
//****************************
(* Workaround for plugins that don't give a list of folders
or the list does not include all of the folders. *)
// Collect directories that the plugin supplies.
if (ExistsDirList.Find(Header.FileName) < 0) then
ExistsDirList.Add(Header.FileName);
end;
// Collect all directories.
CollectDirs(PAnsiChar(Header.FileName), AllDirsList);
//****************************
FArcFileList.Add(Header);
// get next file
iResult := ProcessFile(ArcHandle, PK_SKIP, nil, nil);
//Check for errors
{if iResult <> E_SUCCESS then
ShowErrorMessage;}
end; // while
(* if plugin does not give a list of folders *)
for I := 0 to AllDirsList.Count - 1 do
begin
// Add only those directories that were not supplied by the plugin.
if ExistsDirList.Find(AllDirsList.List[I]^.Key) < 0 then
begin
Header := TWCXHeader.Create;
try
Header.FileName := AllDirsList.List[I]^.Key;
Header.ArcName := ArchiveFileName;
Header.FileAttr := faFolder;
Header.FileTime := mbFileAge(ArchiveFileName);
FArcFileList.Add(Header);
except
FreeAndNil(Header);
end;
end;
end;
finally
AllDirsList.Free;
ExistsDirList.Free;
CloseArchive(ArcHandle);
end;
Result := True;
end;
function TWcxArchiveFileSource.ReadWCXHeader(hArcData: TArcHandle;
out HeaderData: TWCXHeader): Integer;
var
ArcHeader : THeaderData;
ArcHeaderEx : THeaderDataEx;
begin
HeaderData := nil;
if Assigned(ReadHeaderEx) then
begin
FillChar(ArcHeaderEx, SizeOf(ArcHeaderEx), #0);
Result := ReadHeaderEx(hArcData, ArcHeaderEx);
if Result = E_SUCCESS then
begin
HeaderData := TWCXHeader.Create(PHeaderDataEx(@ArcHeaderEx));
end;
end
else if Assigned(ReadHeader) then
begin
FillChar(ArcHeader, SizeOf(ArcHeader), #0);
Result := ReadHeader(hArcData, ArcHeader);
if Result = E_SUCCESS then
begin
HeaderData := TWCXHeader.Create(PHeaderData(@ArcHeader));
end;
end
else
begin
Result := E_NOT_SUPPORTED;
end;
end;
{ TWCXHeader }
constructor TWCXHeader.Create(const Data: PHeaderData);
begin
ArcName := PCharLToUTF8(Data^.ArcName, SizeOf(Data^.ArcName));
FileName := PCharLToUTF8(Data^.FileName, SizeOf(Data^.FileName));
Flags := Data^.Flags;
HostOS := Data^.HostOS;
FileCRC := Data^.FileCRC;
FileTime := Data^.FileTime;
UnpVer := Data^.UnpVer;
Method := Data^.Method;
FileAttr := Data^.FileAttr;
PackSize := Data^.PackSize;
UnpSize := Data^.UnpSize;
if Assigned(Data^.CmtBuf) then
Cmt := PCharLToUTF8(Data^.CmtBuf, Data^.CmtSize);
CmtState := Data^.CmtState;
end;
constructor TWCXHeader.Create(const Data: PHeaderDataEx);
function Combine64(High, Low: Longint): Int64;
begin
Result := Int64(High) shl (SizeOf(Int64) shl 2);
Result := Result + Int64(Low);
end;
begin
ArcName := PCharLToUTF8(Data^.ArcName, SizeOf(Data^.ArcName));
FileName := PCharLToUTF8(Data^.FileName, SizeOf(Data^.FileName));
Flags := Data^.Flags;
HostOS := Data^.HostOS;
FileCRC := Data^.FileCRC;
FileTime := Data^.FileTime;
UnpVer := Data^.UnpVer;
Method := Data^.Method;
FileAttr := Data^.FileAttr;
PackSize := Combine64(Data^.PackSizeHigh, Data^.PackSize);
UnpSize := Combine64(Data^.UnpSizeHigh, Data^.UnpSize);
if Assigned(Data^.CmtBuf) then
Cmt := PCharLToUTF8(Data^.CmtBuf, Data^.CmtSize);
CmtState := Data^.CmtState;
end;
constructor TWCXHeader.Create;
begin
end;
function TWCXHeader.PCharLToUTF8(CharString: PChar; MaxSize: Integer): UTF8String;
var
NameLength: Integer;
TempString: AnsiString;
begin
NameLength := strlen(CharString);
if NameLength > MaxSize then
NameLength := MaxSize;
SetString(TempString, CharString, NameLength);
Result := SysToUTF8(TempString);
end;
end.

View file

@ -0,0 +1,68 @@
unit uWcxArchiveListOperation;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
uFileSourceListOperation,
uWcxArchiveFileSource;
type
TWcxArchiveListOperation = class(TFileSourceListOperation)
private
FWcxArchiveFileSource: TWcxArchiveFileSource;
public
constructor Create(var aFileSource: TWcxArchiveFileSource); reintroduce;
procedure Execute; override;
end;
implementation
uses
LCLProc, uFileSystemFile, uFindEx, uOSUtils, uDCUtils, uWcxArchiveFile, uFile;
constructor TWcxArchiveListOperation.Create(var aFileSource: TWcxArchiveFileSource);
begin
FFiles := TFiles.Create;
FWcxArchiveFileSource := aFileSource;
inherited Create(aFileSource);
end;
procedure TWcxArchiveListOperation.Execute;
var
I : Integer;
CurrFileName : String; // Current file name
ArcFileList: TList;
aFile: TWcxArchiveFile;
begin
FFiles.Clear;
FFiles.Path := IncludeTrailingPathDelimiter(FileSource.CurrentPath);
if not FileSource.IsAtRootPath then
begin
aFile := TWcxArchiveFile.Create;
aFile.Path := FileSource.CurrentPath;
aFile.Name := '..';
aFile.Attributes := faFolder;
FFiles.Add(AFile);
end;
ArcFileList := FWcxArchiveFileSource.ArchiveFileList;
for I := 0 to ArcFileList.Count - 1 do
begin
CurrFileName := PathDelim + TWCXHeader(ArcFileList.Items[I]).FileName;
if not IsInPath(FileSource.CurrentPath, CurrFileName, False) then
Continue;
aFile := TWcxArchiveFile.Create(TWCXHeader(ArcFileList.Items[I]));
aFile.Path := FileSource.CurrentPath;
FFiles.Add(AFile);
end;
end;
end.