unit InstallFiles;
interface
uses
{$IFDEF WIN32}
Windows, Classes, IniFiles, SysUtils, Dialogs, PackmanUtils;
{$ENDIF}
{$IFDEF LINUX}
Classes, IniFiles, SysUtils, QDialogs, PackmanUtils;
{$ENDIF}
type
TIconFile = Class
public
FileName: AnsiString;
Target: AnsiString;
Icon: AnsiString;
end;
TInstallFile = Class
public
Source: AnsiString;
Dest: AnsiString;
end;
TInstallFiles = class
private
FAppDir: AnsiString;
FCount: Integer;
FIconCount: Integer;
List, IconList: TList;
FInfoFile: AnsiString;
FMenuName: AnsiString;
function GetFiles(IIndex: Integer): TInstallFile;
function GetIcons(IIndex: Integer): TIconFile;
procedure SetAppDir(Dir: AnsiString);
protected
procedure Clear;
procedure ApplyConstants(var Str: AnsiString);
function ParseLine(Line: AnsiString; var Src, Dest, Flags: AnsiString): Boolean;
public
constructor Create(InfoFile: AnsiString; AppDir: AnsiString; MenuName: AnsiString);
destructor Destroy; override;
procedure Parse;
property InfoFile: AnsiString read FInfoFile;
property AppDir: AnsiString read FAppDir write SetAppDir;
property Count: Integer read FCount;
property IconCount: Integer read FIconCount;
property Files[IIndex: Integer]: TInstallFile read GetFiles;
property Icons[IIndex: Integer]: TIconFile read GetIcons;
end;
TInstallInfo = Class
private
FFileName: AnsiString;
FAppName: AnsiString;
FAppVerName: AnsiString;
FAppVersion: AnsiString;
FDependencies: TStringList;
FDescription: AnsiString;
FLicense: AnsiString;
FLicenseFile: AnsiString;
FMenuName: AnsiString;
FReadme: AnsiString;
FReadmeFile: AnsiString;
FReboot: Boolean;
FFiles: TInstallFiles;
FURL: AnsiString;
FVersion: Integer;
public
constructor Create(AFileName: AnsiString);
destructor Destroy; override;
function Parse: Boolean;
function Files(AppDir: AnsiString): TInstallFiles;
property FileName: AnsiString read FFileName;
property AppName: AnsiString read FAppName;
property AppVerName: AnsiString read FAppVerName;
property AppVersion: AnsiString read FAppVersion;
property Dependencies: TStringList read FDependencies;
property Description: AnsiString read FDescription;
property License: AnsiString read FLicense;
property LicenseFile: AnsiString read FLicenseFile;
property MenuName: AnsiString read FMenuName;
property Readme: AnsiString read FReadme;
property ReadmeFile: AnsiString read FReadmeFile;
property Reboot: Boolean read FReboot;
property URL: AnsiString read FURL;
property Version: Integer read FVersion;
end;
const
SupportedVersion = 2;
implementation
constructor TInstallInfo.Create(AFileName: AnsiString);
begin
inherited Create;
FFileName := AFileName;
FFiles := nil;
if not Parse then
raise Exception.Create('Not a DevPackage file.');
end;
destructor TInstallInfo.Destroy;
begin
if Assigned(FFiles) then
FFiles.Free;
FDependencies.Free;
inherited Destroy;
end;
function TInstallInfo.Parse: Boolean;
var
Ini: TIniFile;
StrList: TStringList;
BaseName: AnsiString;
begin
Result := False;
Ini := TIniFile.Create(FFileName);
FAppName := Ini.ReadString('Setup', 'AppName', 'ThIsNaMeDoEsNoTeXiStS-6.1GoLd');
// this may not be a ini file...
if CompareStr(FAppName, 'ThIsNaMeDoEsNoTeXiStS-6.1GoLd') = 0 then
begin
FAppName := Ini.ReadString('Setup', 'AppName', 'ThIsIsNoTaNiNi');
if CompareStr(FAppName, 'ThIsIsNoTaNiNi') = 0 then
Exit;
end;
FAppVerName := Ini.ReadString('Setup', 'AppVerName', 'MyPackage version 1.0');
FAppVersion := Ini.ReadString('Setup', 'AppVersion', '1.0');
FDescription := Ini.ReadString('Setup', 'Description', '');
FMenuName := Ini.ReadString('Setup', 'MenuName', '');
FReboot := Ini.ReadBool('Setup', 'Reboot', False);
FURL := Ini.ReadString('Setup', 'Url', '');
FVersion := Ini.ReadInteger('Setup', 'Version', 1);
FDependencies := TStringList.Create;
FDependencies.Delimiter := ';';
FDependencies.DelimitedText := Ini.ReadString('Setup', 'Dependencies', '');
BaseName := ExtractFilePath(FFileName);
StrList := TStringList.Create;
FLicenseFile := Ini.ReadString('Setup', 'License', '');
if Length(FLicenseFile) > 0 then
begin
FLicenseFile := ExpandFileName(BaseName + FLicenseFile);
StrList.LoadFromFile(FLicenseFile);
FLicense := StrList.Text;
end else
FLicense := '';
FReadmeFile := Ini.ReadString('Setup', 'Readme', '');
if Length(FReadmeFile) > 0 then
begin
FReadmeFile := ExpandFileName(BaseName + FReadmeFile);
StrList.LoadFromFile(FReadmeFile);
FReadme := StrList.Text;
end else
FReadme := '';
StrList.Free;
Ini.Free;
Result := True;
end;
function TInstallInfo.Files(AppDir: AnsiString): TInstallFiles;
begin
if not Assigned(FFiles) then
FFiles := TInstallFiles.Create(FFileName, AppDir, MenuName)
else if CompareText(FFiles.AppDir, AppDir) <> 0 then
FFiles.AppDir := AppDir;
Result := FFiles;
end;
constructor TInstallFiles.Create(InfoFile: AnsiString; AppDir: AnsiString; MenuName: AnsiString);
begin
inherited Create;
List := TList.Create;
IconList := TList.Create;
FInfoFile := InfoFile;
FMenuName := MenuName;
SetAppDir(AppDir);
end;
destructor TInstallFiles.Destroy;
begin
Clear;
List.Free;
IconList.Free;
inherited Destroy;
end;
function TInstallFiles.GetFiles(IIndex: Integer): TInstallFile;
var
TheFile: TInstallFile;
begin
TheFile := List.Items[IIndex];
Result := TheFile;
end;
function TInstallFiles.GetIcons(IIndex: Integer): TIconFile;
var
TheIcon: TIconFile;
begin
TheIcon := IconList.Items[IIndex];
Result := TheIcon;
end;
procedure TInstallFiles.SetAppDir(Dir: AnsiString);
begin
FAppDir := Dir;
Parse;
end;
procedure TInstallFiles.Clear;
var
i: Integer;
TheFile: TInstallFile;
TheIcon: TIconFile;
begin
for i := 0 to List.Count - 1 do
begin
TheFile := TInstallFile(List.Items[i]);
TheFile.Free;
end;
for i := 0 to IconList.Count - 1 do
begin
TheIcon := TIconFile(IconList.Items[i]);
TheIcon.Free;
end;
FCount := 0;
FIconCount := 0;
List.Clear;
IconList.Clear;
end;
function TInstallFiles.ParseLine(Line: AnsiString; var Src, Dest,
Flags: AnsiString): Boolean;
var
ALine: AnsiString;
Sep, Sep2: Integer;
begin
ALine := Line;
{ Seperate the text before and after the '=' sign }
Sep := Pos('=', ALine);
{ An error occured }
if Sep = 0 then
begin
Result := False;
Exit;
end;
Src := ExtractRelativePath(ExtractFilePath(FInfoFile),
Copy(ALine, 0, Sep - 1));
ALine := Copy(Line, Sep + 1, Length(Line) - Sep);
{ Find out wether there are flags }
Sep2 := Pos(';', ALine);
if Sep2 <> 0 then
begin
Dest := Copy(ALine, 0, Sep2);
Flags := Copy(ALine, Sep2 + 1, Length(ALine) - Sep2);
end else
{ If not, just copy everything after '=' }
Dest := ALine;
Result := True;
end;
procedure ReplaceAll(var Str: AnsiString; SFrom, STo: AnsiString);
var
i: Integer;
begin
{ Pos is case sensitive; workaround }
i := Pos(LowerCase(SFrom), LowerCase(Str));
while i <> 0 do
begin
Delete(Str, i, Length(SFrom));
Insert(STo, Str, i);
i := Pos(LowerCase(SFrom), LowerCase(Str));
end;
end;
procedure TInstallFiles.ApplyConstants(var Str: AnsiString);
var
WinDir, SysDir: array[0..1024] of Char;
begin
GetWindowsDirectory(WinDir, SizeOf(WinDir));
GetSystemDirectory(SysDir, SizeOf(WinDir));
ReplaceAll(Str, '<app>', FAppDir);
ReplaceAll(Str, '<src>', ExtractFileDir(FInfoFile));
ReplaceAll(Str, '<win>', WinDir);
ReplaceAll(Str, '<sys>', SysDir);
end;
procedure TInstallFiles.Parse;
var
FileSection, IconSection: TStringList;
Icon: TIconFile;
i, j: Integer;
OrgSrc, Src, Dest, Flags: AnsiString;
TheFile: TInstallFile;
Files: TStringList;
label
LoadFiles;
begin
Clear;
{ Load all keys from the [Icons] section }
if Length(FMenuName) = 0 then
goto LoadFiles;
IconSection := TStringList.Create;
IconSection.LoadFromFile(FInfoFile);
for i := 0 to IconSection.Count - 1 do
begin
if CompareText(IconSection.Strings[0], '[Icons]') = 0 then
begin
IconSection.Delete(0);
Break;
end else
IconSection.Delete(0);
end;
{ Parse the icon filenames }
for i := 0 to IconSection.Count - 1 do
begin
if (Length(IconSection.Strings[i]) = 0) or
(IconSection.Strings[i][1] = '[') then
Break;
Icon := TIconFile.Create;
Icon.FileName := GetDevcppMenu + '\' + FMenuName + '\' +
IconSection.Names[i];
Icon.Target := IconSection.Values[IconSection.Names[i]];
j := Pos(',', Icon.Target);
if j > 0 then
begin
Icon.Icon := Copy(Icon.Target, j + 1, Length(Icon.Target) - j);
Delete(Icon.Target, j, Length(Icon.Target) - j + 1);
end;
if CompareText(Copy(Icon.Target, 1, 7), 'http://') = 0 then
Icon.FileName := Icon.FileName + '.url'
else
Icon.FileName := Icon.FileName + '.lnk';
ApplyConstants(Icon.Target);
ApplyConstants(Icon.Icon);
IconList.Add(Icon);
end;
LoadFiles:
{ Load all keys from the [Files] section }
FileSection := TStringList.Create;
FileSection.LoadFromFile(FInfoFile);
for i := 0 to FileSection.Count - 1 do
begin
if CompareText(FileSection.Strings[0], '[Files]') = 0 then
begin
FileSection.Delete(0);
Break;
end else
FileSection.Delete(0);
end;
{ Parse the filenames }
for i := 0 to FileSection.Count - 1 do
begin
if (Length(FileSection.Strings[i]) = 0) or
(FileSection.Strings[i][1] = '[') then
Break;
if not ParseLine(FileSection.Strings[i], Src, Dest, Flags) then
Continue;
ApplyConstants(Dest);
OrgSrc := Src;
Src := ExtractFilePath(FInfoFile) + Src;
if DirectoryExists(Src) then
begin
Files := TStringList.Create;
FilesFromWildcard(Src, '*', Files, True, False);
for j := 0 to Files.Count - 1 do
begin
TheFile := TInstallFile.Create;
TheFile.Source := Files.Strings[j];
TheFile.Dest := Dest + Copy(Files.Strings[j], Length(Src) + 2,
Length(Files.Strings[j]) - Length(Src));
List.Add(TheFile);
end;
Files.Free;
end else
begin
TheFile := TInstallFile.Create;
TheFile.Source := Src;
if Dest[Length(Dest)] = '\' then
Dest := Dest + ExtractFileName(Src);
TheFile.Dest := Dest;
List.Add(TheFile);
end;
end;
FCount := List.Count;
FIconCount := IconList.Count;
FileSection.Free;
end;
end.