├── Logo.png
├── Binaries
├── Updater.exe
├── libeay32.dll
├── ssleay32.dll
├── Documentation.pdf
├── UpdaterWizard.exe
├── Snapshots
│ ├── Alpha
│ │ ├── AuthoringTool.exe
│ │ └── Alpha.json
│ ├── Beta
│ │ ├── AuthoringTool.exe
│ │ └── Beta.json
│ ├── Nightly
│ │ ├── AuthoringTool.exe
│ │ └── Nightly.json
│ ├── Stable
│ │ ├── AuthoringTool.exe
│ │ └── Stable.json
│ └── Channels.json
├── Preferences.json
├── WebUpdate.wup
├── WebUpdate
│ ├── Beta.json
│ ├── Alpha.json
│ ├── Stable.json
│ ├── Nightly.json
│ └── Channels.json
└── AuthoringTool.json
├── Glyphs
├── WebUpdate.ico
└── WebUpdate.png
├── Packages
├── WebUpdateD.dcr
├── RX
│ ├── WebUpdateD.dpk
│ ├── WebUpdateR.dpk
│ └── Packages.groupproj
├── RX1
│ ├── WebUpdateD.dpk
│ ├── WebUpdateR.dpk
│ └── Packages.groupproj
├── RX2
│ ├── WebUpdateD.dpk
│ ├── WebUpdateR.dpk
│ ├── Packages.groupproj
│ ├── WebUpdateD.dproj
│ └── WebUpdateR.dproj
├── XE2
│ ├── WebUpdateD.dpk
│ ├── WebUpdateR.dpk
│ └── Packages.groupproj
├── XE3
│ ├── WebUpdateD.dpk
│ └── WebUpdateR.dpk
├── XE4
│ ├── WebUpdateD.dpk
│ └── WebUpdateR.dpk
├── XE5
│ ├── WebUpdateD.dpk
│ └── WebUpdateR.dpk
├── XE6
│ ├── WebUpdateD.dpk
│ └── WebUpdateR.dpk
├── XE7
│ ├── WebUpdateD.dpk
│ ├── WebUpdateR.dpk
│ └── Packages.groupproj
└── XE8
│ ├── WebUpdateD.dpk
│ ├── WebUpdateR.dpk
│ └── Packages.groupproj
├── Delphinus.Info.json
├── Source
├── Common
│ ├── README.md
│ ├── WebUpdate.Tools.pas
│ ├── WebUpdate.JSON.Channels.pas
│ ├── WebUpdate.JSON.Serializer.pas
│ ├── WebUpdate.JSON.Channel.pas
│ ├── WebUpdate.Classes.WebUpdate.pas
│ ├── WebUpdate.JSON.Project.pas
│ └── WebUpdate.Classes.Updater.pas
├── Authoring Tool
│ ├── README.md
│ ├── WebUpdate.GUI.CommandLine.pas
│ ├── AuthoringTool.dpr
│ ├── WebUpdate.GUI.CommandLine.dfm
│ ├── WebUpdate.GUI.About.pas
│ ├── WebUpdate.JSON.Preferences.pas
│ ├── WebUpdate.GUI.Options.pas
│ └── WebUpdate.GUI.Options.dfm
├── Package
│ ├── WebUpdate.Package.Reg.pas
│ └── WebUpdate.Package.Component.pas
├── Update Helper Wizard
│ ├── README.md
│ ├── UpdaterWizard.dpr
│ └── WebUpdate.GUI.Updater.pas
├── Example Application
│ ├── ExampleApp.dpr
│ ├── MainUnit.dfm
│ └── MainUnit.pas
├── Web Update Tools.groupproj
├── Update Helper (Command-line)
│ ├── Updater.dpr
│ └── Updater.dproj
└── Snapshot Tool (Command Line)
│ └── SnapshotTool.dpr
├── Delphinus.Install.json
└── README.md
/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Logo.png
--------------------------------------------------------------------------------
/Binaries/Updater.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Binaries/Updater.exe
--------------------------------------------------------------------------------
/Glyphs/WebUpdate.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Glyphs/WebUpdate.ico
--------------------------------------------------------------------------------
/Glyphs/WebUpdate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Glyphs/WebUpdate.png
--------------------------------------------------------------------------------
/Binaries/libeay32.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Binaries/libeay32.dll
--------------------------------------------------------------------------------
/Binaries/ssleay32.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Binaries/ssleay32.dll
--------------------------------------------------------------------------------
/Packages/WebUpdateD.dcr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Packages/WebUpdateD.dcr
--------------------------------------------------------------------------------
/Binaries/Documentation.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Binaries/Documentation.pdf
--------------------------------------------------------------------------------
/Binaries/UpdaterWizard.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Binaries/UpdaterWizard.exe
--------------------------------------------------------------------------------
/Delphinus.Info.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "{E132F855-C717-46E1-98F0-AFBB8EE573A6}",
3 | "picture": "Logo.png"
4 | }
--------------------------------------------------------------------------------
/Binaries/Snapshots/Alpha/AuthoringTool.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Binaries/Snapshots/Alpha/AuthoringTool.exe
--------------------------------------------------------------------------------
/Binaries/Snapshots/Beta/AuthoringTool.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Binaries/Snapshots/Beta/AuthoringTool.exe
--------------------------------------------------------------------------------
/Binaries/Snapshots/Nightly/AuthoringTool.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Binaries/Snapshots/Nightly/AuthoringTool.exe
--------------------------------------------------------------------------------
/Binaries/Snapshots/Stable/AuthoringTool.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CWBudde/WebUpdate/HEAD/Binaries/Snapshots/Stable/AuthoringTool.exe
--------------------------------------------------------------------------------
/Source/Common/README.md:
--------------------------------------------------------------------------------
1 | Common
2 | ======
3 |
4 | This directory contains commonly used units containing procedures, functions and classes used across the different projects.
--------------------------------------------------------------------------------
/Binaries/Preferences.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Preferences",
3 | "Left" : 1389,
4 | "Top" : 758,
5 | "ViewFiles" : true,
6 | "RecentProject" : "C:\\Users\\Public\\Code\\WebUpdate\\Binaries\\WebUpdate.wup"
7 | }
--------------------------------------------------------------------------------
/Binaries/WebUpdate.wup:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Project",
3 | "ChannelFilename" : "WebUpdate\\Channels.json",
4 | "CurrentChannel" : "Nightly",
5 | "Copy" : {
6 | "Path" : ".\\Snapshots",
7 | "Enabled" : true
8 | }
9 | }
--------------------------------------------------------------------------------
/Source/Authoring Tool/README.md:
--------------------------------------------------------------------------------
1 | Authoring Tool
2 | ==============
3 |
4 | The authoring tool is used to create and manage channels and to take snapshots. The snapshots can be copied to a certain path or uploaded to an FTP client directly.
--------------------------------------------------------------------------------
/Binaries/WebUpdate/Beta.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channel",
3 | "Modified" : "2014-11-20T14:48:01.000",
4 | "Name" : "Beta",
5 | "Files" : [
6 | {
7 | "FileName" : "AuthoringTool.exe",
8 | "Size" : 1068032,
9 | "Modified" : "2014-11-20T14:48:01.000"
10 | }
11 | ],
12 | "AppName" : "AuthoringTool.exe"
13 | }
--------------------------------------------------------------------------------
/Binaries/AuthoringTool.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channel",
3 | "Modified" : "2014-11-20T12:51:42.000",
4 | "Name" : "Stable",
5 | "Files" : [
6 | {
7 | "FileName" : "AuthoringTool.exe",
8 | "Size" : 1068032,
9 | "Modified" : "2014-11-20T12:51:42.000"
10 | }
11 | ],
12 | "AppName" : "AuthoringTool.exe"
13 | }
--------------------------------------------------------------------------------
/Binaries/Snapshots/Beta/Beta.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channel",
3 | "Modified" : "2014-11-20T14:48:01.000",
4 | "Name" : "Beta",
5 | "Files" : [
6 | {
7 | "FileName" : "AuthoringTool.exe",
8 | "Size" : 1068032,
9 | "Modified" : "2014-11-20T14:48:01.000"
10 | }
11 | ],
12 | "AppName" : "AuthoringTool.exe"
13 | }
--------------------------------------------------------------------------------
/Binaries/WebUpdate/Alpha.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channel",
3 | "Modified" : "2014-11-20T14:48:01.000",
4 | "Name" : "Alpha",
5 | "Files" : [
6 | {
7 | "FileName" : "AuthoringTool.exe",
8 | "Size" : 1068032,
9 | "Modified" : "2014-11-20T14:48:01.000"
10 | }
11 | ],
12 | "AppName" : "AuthoringTool.exe"
13 | }
--------------------------------------------------------------------------------
/Binaries/WebUpdate/Stable.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channel",
3 | "Modified" : "2014-11-20T14:48:01.000",
4 | "Name" : "Stable",
5 | "Files" : [
6 | {
7 | "FileName" : "AuthoringTool.exe",
8 | "Size" : 1068032,
9 | "Modified" : "2014-11-20T14:48:01.000"
10 | }
11 | ],
12 | "AppName" : "AuthoringTool.exe"
13 | }
--------------------------------------------------------------------------------
/Binaries/Snapshots/Alpha/Alpha.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channel",
3 | "Modified" : "2014-11-20T14:48:01.000",
4 | "Name" : "Alpha",
5 | "Files" : [
6 | {
7 | "FileName" : "AuthoringTool.exe",
8 | "Size" : 1068032,
9 | "Modified" : "2014-11-20T14:48:01.000"
10 | }
11 | ],
12 | "AppName" : "AuthoringTool.exe"
13 | }
--------------------------------------------------------------------------------
/Binaries/WebUpdate/Nightly.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channel",
3 | "Modified" : "2014-11-20T14:48:01.000",
4 | "Name" : "Nightly",
5 | "Files" : [
6 | {
7 | "FileName" : "AuthoringTool.exe",
8 | "Size" : 1068032,
9 | "Modified" : "2014-11-20T14:48:01.000"
10 | }
11 | ],
12 | "AppName" : "AuthoringTool.exe"
13 | }
--------------------------------------------------------------------------------
/Binaries/Snapshots/Nightly/Nightly.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channel",
3 | "Modified" : "2014-11-20T14:48:01.000",
4 | "Name" : "Nightly",
5 | "Files" : [
6 | {
7 | "FileName" : "AuthoringTool.exe",
8 | "Size" : 1068032,
9 | "Modified" : "2014-11-20T14:48:01.000"
10 | }
11 | ],
12 | "AppName" : "AuthoringTool.exe"
13 | }
--------------------------------------------------------------------------------
/Binaries/Snapshots/Stable/Stable.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channel",
3 | "Modified" : "2014-11-20T14:48:01.000",
4 | "Name" : "Stable",
5 | "Files" : [
6 | {
7 | "FileName" : "AuthoringTool.exe",
8 | "Size" : 1068032,
9 | "Modified" : "2014-11-20T14:48:01.000"
10 | }
11 | ],
12 | "AppName" : "AuthoringTool.exe"
13 | }
--------------------------------------------------------------------------------
/Source/Package/WebUpdate.Package.Reg.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.Package.Reg;
2 |
3 | interface
4 |
5 | uses
6 | System.Classes, WebUpdate.Package.Component;
7 |
8 | procedure Register;
9 |
10 | implementation
11 |
12 | procedure Register;
13 | begin
14 | RegisterComponents('WebUpdate', [TWebUpdateComponent]);
15 | end;
16 |
17 | end.
18 |
--------------------------------------------------------------------------------
/Binaries/Snapshots/Channels.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channels",
3 | "Modified" : "2014-11-20T14:49:37.121",
4 | "Channels" : [
5 | {
6 | "Name" : "Stable",
7 | "Modified" : "2014-11-20T14:48:01.000"
8 | },
9 | {
10 | "Name" : "Beta",
11 | "Modified" : "2014-11-20T14:48:01.000"
12 | },
13 | {
14 | "Name" : "Alpha",
15 | "Modified" : "2014-11-20T14:48:01.000"
16 | },
17 | {
18 | "Name" : "Nightly",
19 | "Modified" : "2014-11-20T14:48:01.000"
20 | }
21 | ]
22 | }
--------------------------------------------------------------------------------
/Binaries/WebUpdate/Channels.json:
--------------------------------------------------------------------------------
1 | {
2 | "ID" : "Channels",
3 | "Modified" : "2014-11-20T14:49:37.121",
4 | "Channels" : [
5 | {
6 | "Name" : "Stable",
7 | "Modified" : "2014-11-20T14:48:01.000"
8 | },
9 | {
10 | "Name" : "Beta",
11 | "Modified" : "2014-11-20T14:48:01.000"
12 | },
13 | {
14 | "Name" : "Alpha",
15 | "Modified" : "2014-11-20T14:48:01.000"
16 | },
17 | {
18 | "Name" : "Nightly",
19 | "Modified" : "2014-11-20T14:48:01.000"
20 | }
21 | ]
22 | }
--------------------------------------------------------------------------------
/Source/Update Helper Wizard/README.md:
--------------------------------------------------------------------------------
1 | Update Helper Wizard
2 | ====================
3 |
4 | In order to perform a web update from a running application, the application must be closed first while a helper tool is started to perform the download and replacement of files.
5 | Since this helper tool must exists along with the main executable file, it can also serve as a stand-alone wizard to update the application while not running.
6 |
7 | The source code, which can be found in this directory is meant to produce both: An update helper and a stand-alone update wizard.
--------------------------------------------------------------------------------
/Source/Example Application/ExampleApp.dpr:
--------------------------------------------------------------------------------
1 | program ExampleApp;
2 |
3 | uses
4 | Vcl.Forms,
5 | WebUpdate.JSON.Channel in '..\Common\WebUpdate.JSON.Channel.pas',
6 | WebUpdate.JSON.Channels in '..\Common\WebUpdate.JSON.Channels.pas',
7 | WebUpdate.JSON.Serializer in '..\Common\WebUpdate.JSON.Serializer.pas',
8 | WebUpdate.Classes.WebUpdate in '..\Common\WebUpdate.Classes.WebUpdate.pas',
9 | MainUnit in 'MainUnit.pas' {FormExample};
10 |
11 | {$R *.res}
12 |
13 | begin
14 | Application.Initialize;
15 | Application.MainFormOnTaskbar := True;
16 | Application.CreateForm(TFormExample, FormExample);
17 | Application.Run;
18 | end.
19 |
20 |
--------------------------------------------------------------------------------
/Source/Update Helper Wizard/UpdaterWizard.dpr:
--------------------------------------------------------------------------------
1 | program UpdaterWizard;
2 |
3 | uses
4 | Vcl.Forms,
5 | WebUpdate.Classes.Updater in '..\Common\WebUpdate.Classes.Updater.pas',
6 | WebUpdate.JSON.Serializer in '..\Common\WebUpdate.JSON.Serializer.pas',
7 | WebUpdate.JSON.Channel in '..\Common\WebUpdate.JSON.Channel.pas',
8 | WebUpdate.JSON.Channels in '..\Common\WebUpdate.JSON.Channels.pas',
9 | WebUpdate.GUI.Updater in 'WebUpdate.GUI.Updater.pas' {FormWebUpdate},
10 | WebUpdate.Tools in '..\Common\WebUpdate.Tools.pas';
11 |
12 | {$R *.res}
13 |
14 | begin
15 | Application.Initialize;
16 | Application.MainFormOnTaskbar := True;
17 | Application.CreateForm(TFormWebUpdate, FormWebUpdate);
18 | Application.Run;
19 | end.
20 |
21 |
--------------------------------------------------------------------------------
/Source/Authoring Tool/WebUpdate.GUI.CommandLine.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.GUI.CommandLine;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes,
7 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
8 |
9 | type
10 | TFormCommandLine = class(TForm)
11 | MemoCommandLine: TMemo;
12 | procedure FormCreate(Sender: TObject);
13 | end;
14 |
15 | implementation
16 |
17 | uses
18 | System.Types;
19 |
20 | {$R *.dfm}
21 |
22 | procedure TFormCommandLine.FormCreate(Sender: TObject);
23 | begin
24 | MemoCommandLine.Lines[3] := Format(MemoCommandLine.Lines[3],
25 | [ExtractFileName(ParamStr(0))]);
26 | MemoCommandLine.Lines[26] := Format(MemoCommandLine.Lines[26],
27 | [ExtractFileName(ParamStr(0))]);
28 | MemoCommandLine.CaretPos := Point(0, MemoCommandLine.Lines.Count);
29 | end;
30 |
31 | end.
32 |
33 |
--------------------------------------------------------------------------------
/Packages/RX/WebUpdateD.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateD;
2 |
3 | {$R *.res}
4 | {$R '..\WebUpdateD.dcr'}
5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
6 | {$ALIGN 8}
7 | {$ASSERTIONS ON}
8 | {$BOOLEVAL OFF}
9 | {$DEBUGINFO OFF}
10 | {$EXTENDEDSYNTAX ON}
11 | {$IMPORTEDDATA ON}
12 | {$IOCHECKS ON}
13 | {$LOCALSYMBOLS ON}
14 | {$LONGSTRINGS ON}
15 | {$OPENSTRINGS ON}
16 | {$OPTIMIZATION OFF}
17 | {$OVERFLOWCHECKS OFF}
18 | {$RANGECHECKS OFF}
19 | {$REFERENCEINFO ON}
20 | {$SAFEDIVIDE OFF}
21 | {$STACKFRAMES ON}
22 | {$TYPEDADDRESS OFF}
23 | {$VARSTRINGCHECKS ON}
24 | {$WRITEABLECONST OFF}
25 | {$MINENUMSIZE 1}
26 | {$IMAGEBASE $400000}
27 | {$DEFINE DEBUG}
28 | {$ENDIF IMPLICITBUILDING}
29 | {$DESCRIPTION 'WebUpdate Non-Visual'}
30 | {$LIBSUFFIX '230'}
31 | {$DESIGNONLY}
32 | {$IMPLICITBUILD OFF}
33 |
34 | requires
35 | DesignIDE,
36 | WebUpdateR;
37 |
38 | contains
39 | WebUpdate.Package.Reg in '..\..\Source\Package\WebUpdate.Package.Reg.pas';
40 |
41 | end.
42 |
43 |
--------------------------------------------------------------------------------
/Packages/RX1/WebUpdateD.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateD;
2 |
3 | {$R *.res}
4 | {$R '..\WebUpdateD.dcr'}
5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
6 | {$ALIGN 8}
7 | {$ASSERTIONS ON}
8 | {$BOOLEVAL OFF}
9 | {$DEBUGINFO OFF}
10 | {$EXTENDEDSYNTAX ON}
11 | {$IMPORTEDDATA ON}
12 | {$IOCHECKS ON}
13 | {$LOCALSYMBOLS ON}
14 | {$LONGSTRINGS ON}
15 | {$OPENSTRINGS ON}
16 | {$OPTIMIZATION OFF}
17 | {$OVERFLOWCHECKS OFF}
18 | {$RANGECHECKS OFF}
19 | {$REFERENCEINFO ON}
20 | {$SAFEDIVIDE OFF}
21 | {$STACKFRAMES ON}
22 | {$TYPEDADDRESS OFF}
23 | {$VARSTRINGCHECKS ON}
24 | {$WRITEABLECONST OFF}
25 | {$MINENUMSIZE 1}
26 | {$IMAGEBASE $400000}
27 | {$DEFINE DEBUG}
28 | {$ENDIF IMPLICITBUILDING}
29 | {$DESCRIPTION 'WebUpdate Non-Visual'}
30 | {$LIBSUFFIX '240'}
31 | {$DESIGNONLY}
32 | {$IMPLICITBUILD OFF}
33 |
34 | requires
35 | DesignIDE,
36 | WebUpdateR;
37 |
38 | contains
39 | WebUpdate.Package.Reg in '..\..\Source\Package\WebUpdate.Package.Reg.pas';
40 |
41 | end.
42 |
43 |
--------------------------------------------------------------------------------
/Packages/RX2/WebUpdateD.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateD;
2 |
3 | {$R *.res}
4 | {$R '..\WebUpdateD.dcr'}
5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
6 | {$ALIGN 8}
7 | {$ASSERTIONS ON}
8 | {$BOOLEVAL OFF}
9 | {$DEBUGINFO OFF}
10 | {$EXTENDEDSYNTAX ON}
11 | {$IMPORTEDDATA ON}
12 | {$IOCHECKS ON}
13 | {$LOCALSYMBOLS ON}
14 | {$LONGSTRINGS ON}
15 | {$OPENSTRINGS ON}
16 | {$OPTIMIZATION OFF}
17 | {$OVERFLOWCHECKS OFF}
18 | {$RANGECHECKS OFF}
19 | {$REFERENCEINFO ON}
20 | {$SAFEDIVIDE OFF}
21 | {$STACKFRAMES ON}
22 | {$TYPEDADDRESS OFF}
23 | {$VARSTRINGCHECKS ON}
24 | {$WRITEABLECONST OFF}
25 | {$MINENUMSIZE 1}
26 | {$IMAGEBASE $400000}
27 | {$DEFINE DEBUG}
28 | {$ENDIF IMPLICITBUILDING}
29 | {$DESCRIPTION 'WebUpdate Non-Visual'}
30 | {$LIBSUFFIX '250'}
31 | {$DESIGNONLY}
32 | {$IMPLICITBUILD OFF}
33 |
34 | requires
35 | DesignIDE,
36 | WebUpdateR;
37 |
38 | contains
39 | WebUpdate.Package.Reg in '..\..\Source\Package\WebUpdate.Package.Reg.pas';
40 |
41 | end.
42 |
43 |
--------------------------------------------------------------------------------
/Packages/XE2/WebUpdateD.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateD;
2 |
3 | {$R *.res}
4 | {$R '..\WebUpdateD.dcr'}
5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
6 | {$ALIGN 8}
7 | {$ASSERTIONS ON}
8 | {$BOOLEVAL OFF}
9 | {$DEBUGINFO ON}
10 | {$EXTENDEDSYNTAX ON}
11 | {$IMPORTEDDATA ON}
12 | {$IOCHECKS ON}
13 | {$LOCALSYMBOLS ON}
14 | {$LONGSTRINGS ON}
15 | {$OPENSTRINGS ON}
16 | {$OPTIMIZATION OFF}
17 | {$OVERFLOWCHECKS OFF}
18 | {$RANGECHECKS OFF}
19 | {$REFERENCEINFO ON}
20 | {$SAFEDIVIDE OFF}
21 | {$STACKFRAMES ON}
22 | {$TYPEDADDRESS OFF}
23 | {$VARSTRINGCHECKS ON}
24 | {$WRITEABLECONST OFF}
25 | {$MINENUMSIZE 1}
26 | {$IMAGEBASE $400000}
27 | {$DEFINE DEBUG}
28 | {$ENDIF IMPLICITBUILDING}
29 | {$DESCRIPTION 'WebUpdate Non-Visual'}
30 | {$LIBSUFFIX '160'}
31 | {$DESIGNONLY}
32 | {$IMPLICITBUILD OFF}
33 |
34 | requires
35 | DesignIDE,
36 | WebUpdateR;
37 |
38 | contains
39 | WebUpdate.Package.Reg in '..\..\Source\Package\WebUpdate.Package.Reg.pas';
40 |
41 | end.
42 |
43 |
--------------------------------------------------------------------------------
/Packages/XE3/WebUpdateD.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateD;
2 |
3 | {$R *.res}
4 | {$R '..\WebUpdateD.dcr'}
5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
6 | {$ALIGN 8}
7 | {$ASSERTIONS ON}
8 | {$BOOLEVAL OFF}
9 | {$DEBUGINFO ON}
10 | {$EXTENDEDSYNTAX ON}
11 | {$IMPORTEDDATA ON}
12 | {$IOCHECKS ON}
13 | {$LOCALSYMBOLS ON}
14 | {$LONGSTRINGS ON}
15 | {$OPENSTRINGS ON}
16 | {$OPTIMIZATION OFF}
17 | {$OVERFLOWCHECKS OFF}
18 | {$RANGECHECKS OFF}
19 | {$REFERENCEINFO ON}
20 | {$SAFEDIVIDE OFF}
21 | {$STACKFRAMES ON}
22 | {$TYPEDADDRESS OFF}
23 | {$VARSTRINGCHECKS ON}
24 | {$WRITEABLECONST OFF}
25 | {$MINENUMSIZE 1}
26 | {$IMAGEBASE $400000}
27 | {$DEFINE DEBUG}
28 | {$ENDIF IMPLICITBUILDING}
29 | {$DESCRIPTION 'WebUpdate Non-Visual'}
30 | {$LIBSUFFIX '170'}
31 | {$DESIGNONLY}
32 | {$IMPLICITBUILD OFF}
33 |
34 | requires
35 | DesignIDE,
36 | WebUpdateR;
37 |
38 | contains
39 | WebUpdate.Package.Reg in '..\..\Source\Package\WebUpdate.Package.Reg.pas';
40 |
41 | end.
42 |
43 |
--------------------------------------------------------------------------------
/Packages/XE4/WebUpdateD.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateD;
2 |
3 | {$R *.res}
4 | {$R '..\WebUpdateD.dcr'}
5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
6 | {$ALIGN 8}
7 | {$ASSERTIONS ON}
8 | {$BOOLEVAL OFF}
9 | {$DEBUGINFO ON}
10 | {$EXTENDEDSYNTAX ON}
11 | {$IMPORTEDDATA ON}
12 | {$IOCHECKS ON}
13 | {$LOCALSYMBOLS ON}
14 | {$LONGSTRINGS ON}
15 | {$OPENSTRINGS ON}
16 | {$OPTIMIZATION OFF}
17 | {$OVERFLOWCHECKS OFF}
18 | {$RANGECHECKS OFF}
19 | {$REFERENCEINFO ON}
20 | {$SAFEDIVIDE OFF}
21 | {$STACKFRAMES ON}
22 | {$TYPEDADDRESS OFF}
23 | {$VARSTRINGCHECKS ON}
24 | {$WRITEABLECONST OFF}
25 | {$MINENUMSIZE 1}
26 | {$IMAGEBASE $400000}
27 | {$DEFINE DEBUG}
28 | {$ENDIF IMPLICITBUILDING}
29 | {$DESCRIPTION 'WebUpdate Non-Visual'}
30 | {$LIBSUFFIX '180'}
31 | {$DESIGNONLY}
32 | {$IMPLICITBUILD OFF}
33 |
34 | requires
35 | DesignIDE,
36 | WebUpdateR;
37 |
38 | contains
39 | WebUpdate.Package.Reg in '..\..\Source\Package\WebUpdate.Package.Reg.pas';
40 |
41 | end.
42 |
43 |
--------------------------------------------------------------------------------
/Packages/XE5/WebUpdateD.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateD;
2 |
3 | {$R *.res}
4 | {$R '..\WebUpdateD.dcr'}
5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
6 | {$ALIGN 8}
7 | {$ASSERTIONS ON}
8 | {$BOOLEVAL OFF}
9 | {$DEBUGINFO ON}
10 | {$EXTENDEDSYNTAX ON}
11 | {$IMPORTEDDATA ON}
12 | {$IOCHECKS ON}
13 | {$LOCALSYMBOLS ON}
14 | {$LONGSTRINGS ON}
15 | {$OPENSTRINGS ON}
16 | {$OPTIMIZATION OFF}
17 | {$OVERFLOWCHECKS OFF}
18 | {$RANGECHECKS OFF}
19 | {$REFERENCEINFO ON}
20 | {$SAFEDIVIDE OFF}
21 | {$STACKFRAMES ON}
22 | {$TYPEDADDRESS OFF}
23 | {$VARSTRINGCHECKS ON}
24 | {$WRITEABLECONST OFF}
25 | {$MINENUMSIZE 1}
26 | {$IMAGEBASE $400000}
27 | {$DEFINE DEBUG}
28 | {$ENDIF IMPLICITBUILDING}
29 | {$DESCRIPTION 'WebUpdate Non-Visual'}
30 | {$LIBSUFFIX '190'}
31 | {$DESIGNONLY}
32 | {$IMPLICITBUILD OFF}
33 |
34 | requires
35 | DesignIDE,
36 | WebUpdateR;
37 |
38 | contains
39 | WebUpdate.Package.Reg in '..\..\Source\Package\WebUpdate.Package.Reg.pas';
40 |
41 | end.
42 |
43 |
--------------------------------------------------------------------------------
/Packages/XE6/WebUpdateD.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateD;
2 |
3 | {$R *.res}
4 | {$R '..\WebUpdateD.dcr'}
5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
6 | {$ALIGN 8}
7 | {$ASSERTIONS ON}
8 | {$BOOLEVAL OFF}
9 | {$DEBUGINFO ON}
10 | {$EXTENDEDSYNTAX ON}
11 | {$IMPORTEDDATA ON}
12 | {$IOCHECKS ON}
13 | {$LOCALSYMBOLS ON}
14 | {$LONGSTRINGS ON}
15 | {$OPENSTRINGS ON}
16 | {$OPTIMIZATION OFF}
17 | {$OVERFLOWCHECKS OFF}
18 | {$RANGECHECKS OFF}
19 | {$REFERENCEINFO ON}
20 | {$SAFEDIVIDE OFF}
21 | {$STACKFRAMES ON}
22 | {$TYPEDADDRESS OFF}
23 | {$VARSTRINGCHECKS ON}
24 | {$WRITEABLECONST OFF}
25 | {$MINENUMSIZE 1}
26 | {$IMAGEBASE $400000}
27 | {$DEFINE DEBUG}
28 | {$ENDIF IMPLICITBUILDING}
29 | {$DESCRIPTION 'WebUpdate Non-Visual'}
30 | {$LIBSUFFIX '200'}
31 | {$DESIGNONLY}
32 | {$IMPLICITBUILD OFF}
33 |
34 | requires
35 | DesignIDE,
36 | WebUpdateR;
37 |
38 | contains
39 | WebUpdate.Package.Reg in '..\..\Source\Package\WebUpdate.Package.Reg.pas';
40 |
41 | end.
42 |
43 |
--------------------------------------------------------------------------------
/Packages/XE7/WebUpdateD.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateD;
2 |
3 | {$R *.res}
4 | {$R '..\WebUpdateD.dcr'}
5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
6 | {$ALIGN 8}
7 | {$ASSERTIONS ON}
8 | {$BOOLEVAL OFF}
9 | {$DEBUGINFO OFF}
10 | {$EXTENDEDSYNTAX ON}
11 | {$IMPORTEDDATA ON}
12 | {$IOCHECKS ON}
13 | {$LOCALSYMBOLS ON}
14 | {$LONGSTRINGS ON}
15 | {$OPENSTRINGS ON}
16 | {$OPTIMIZATION OFF}
17 | {$OVERFLOWCHECKS OFF}
18 | {$RANGECHECKS OFF}
19 | {$REFERENCEINFO ON}
20 | {$SAFEDIVIDE OFF}
21 | {$STACKFRAMES ON}
22 | {$TYPEDADDRESS OFF}
23 | {$VARSTRINGCHECKS ON}
24 | {$WRITEABLECONST OFF}
25 | {$MINENUMSIZE 1}
26 | {$IMAGEBASE $400000}
27 | {$DEFINE DEBUG}
28 | {$ENDIF IMPLICITBUILDING}
29 | {$DESCRIPTION 'WebUpdate Non-Visual'}
30 | {$LIBSUFFIX '210'}
31 | {$DESIGNONLY}
32 | {$IMPLICITBUILD OFF}
33 |
34 | requires
35 | DesignIDE,
36 | WebUpdateR;
37 |
38 | contains
39 | WebUpdate.Package.Reg in '..\..\Source\Package\WebUpdate.Package.Reg.pas';
40 |
41 | end.
42 |
43 |
--------------------------------------------------------------------------------
/Packages/XE8/WebUpdateD.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateD;
2 |
3 | {$R *.res}
4 | {$R '..\WebUpdateD.dcr'}
5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
6 | {$ALIGN 8}
7 | {$ASSERTIONS ON}
8 | {$BOOLEVAL OFF}
9 | {$DEBUGINFO OFF}
10 | {$EXTENDEDSYNTAX ON}
11 | {$IMPORTEDDATA ON}
12 | {$IOCHECKS ON}
13 | {$LOCALSYMBOLS ON}
14 | {$LONGSTRINGS ON}
15 | {$OPENSTRINGS ON}
16 | {$OPTIMIZATION OFF}
17 | {$OVERFLOWCHECKS OFF}
18 | {$RANGECHECKS OFF}
19 | {$REFERENCEINFO ON}
20 | {$SAFEDIVIDE OFF}
21 | {$STACKFRAMES ON}
22 | {$TYPEDADDRESS OFF}
23 | {$VARSTRINGCHECKS ON}
24 | {$WRITEABLECONST OFF}
25 | {$MINENUMSIZE 1}
26 | {$IMAGEBASE $400000}
27 | {$DEFINE DEBUG}
28 | {$ENDIF IMPLICITBUILDING}
29 | {$DESCRIPTION 'WebUpdate Non-Visual'}
30 | {$LIBSUFFIX '220'}
31 | {$DESIGNONLY}
32 | {$IMPLICITBUILD OFF}
33 |
34 | requires
35 | DesignIDE,
36 | WebUpdateR;
37 |
38 | contains
39 | WebUpdate.Package.Reg in '..\..\Source\Package\WebUpdate.Package.Reg.pas';
40 |
41 | end.
42 |
43 |
--------------------------------------------------------------------------------
/Source/Authoring Tool/AuthoringTool.dpr:
--------------------------------------------------------------------------------
1 | program AuthoringTool;
2 |
3 | uses
4 | Vcl.Forms,
5 | WebUpdate.Classes.WebUpdate in '..\Common\WebUpdate.Classes.WebUpdate.pas',
6 | WebUpdate.GUI.About in 'WebUpdate.GUI.About.pas' {FormAbout},
7 | WebUpdate.GUI.AuthorTool in 'WebUpdate.GUI.AuthorTool.pas' {FormWebUpdateTool},
8 | WebUpdate.GUI.Options in 'WebUpdate.GUI.Options.pas' {FormOptions},
9 | WebUpdate.GUI.CommandLine in 'WebUpdate.GUI.CommandLine.pas' {FormCommandLine},
10 | WebUpdate.JSON.Channel in '..\Common\WebUpdate.JSON.Channel.pas',
11 | WebUpdate.JSON.Channels in '..\Common\WebUpdate.JSON.Channels.pas',
12 | WebUpdate.JSON.Preferences in 'WebUpdate.JSON.Preferences.pas',
13 | WebUpdate.JSON.Project in '..\Common\WebUpdate.JSON.Project.pas',
14 | WebUpdate.JSON.Serializer in '..\Common\WebUpdate.JSON.Serializer.pas',
15 | WebUpdate.Tools in '..\Common\WebUpdate.Tools.pas';
16 |
17 | {$R *.res}
18 |
19 | begin
20 | Application.Initialize;
21 | Application.MainFormOnTaskbar := True;
22 | Application.CreateForm(TFormWebUpdateTool, FormWebUpdateTool);
23 | Application.Run;
24 | end.
25 |
26 |
--------------------------------------------------------------------------------
/Packages/RX/WebUpdateR.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateR;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO OFF}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$LIBSUFFIX '230'}
29 | {$RUNONLY}
30 | {$IMPLICITBUILD OFF}
31 |
32 | requires
33 | vcl,
34 | IndyCore,
35 | IndySystem,
36 | IndyProtocols,
37 | dwsLibRuntime;
38 |
39 | contains
40 | WebUpdate.Tools in '..\..\Source\Common\WebUpdate.Tools.pas',
41 | WebUpdate.Classes.Updater in '..\..\Source\Common\WebUpdate.Classes.Updater.pas',
42 | WebUpdate.Classes.WebUpdate in '..\..\Source\Common\WebUpdate.Classes.WebUpdate.pas',
43 | WebUpdate.JSON.Channels in '..\..\Source\Common\WebUpdate.JSON.Channels.pas',
44 | WebUpdate.JSON.Channel in '..\..\Source\Common\WebUpdate.JSON.Channel.pas',
45 | WebUpdate.JSON.Serializer in '..\..\Source\Common\WebUpdate.JSON.Serializer.pas',
46 | WebUpdate.Package.Component in '..\..\Source\Package\WebUpdate.Package.Component.pas';
47 |
48 | end.
49 |
50 |
--------------------------------------------------------------------------------
/Packages/XE3/WebUpdateR.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateR;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO ON}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$LIBSUFFIX '170'}
29 | {$RUNONLY}
30 | {$IMPLICITBUILD OFF}
31 |
32 | requires
33 | vcl,
34 | IndyCore,
35 | IndySystem,
36 | IndyProtocols,
37 | dwsLibRuntime;
38 |
39 | contains
40 | WebUpdate.Tools in '..\..\Source\Common\WebUpdate.Tools.pas',
41 | WebUpdate.Classes.Updater in '..\..\Source\Common\WebUpdate.Classes.Updater.pas',
42 | WebUpdate.Classes.WebUpdate in '..\..\Source\Common\WebUpdate.Classes.WebUpdate.pas',
43 | WebUpdate.JSON.Channels in '..\..\Source\Common\WebUpdate.JSON.Channels.pas',
44 | WebUpdate.JSON.Channel in '..\..\Source\Common\WebUpdate.JSON.Channel.pas',
45 | WebUpdate.JSON.Serializer in '..\..\Source\Common\WebUpdate.JSON.Serializer.pas',
46 | WebUpdate.Package.Component in '..\..\Source\Package\WebUpdate.Package.Component.pas';
47 |
48 | end.
49 |
50 |
--------------------------------------------------------------------------------
/Packages/XE4/WebUpdateR.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateR;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO ON}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$LIBSUFFIX '180'}
29 | {$RUNONLY}
30 | {$IMPLICITBUILD OFF}
31 |
32 | requires
33 | vcl,
34 | IndyCore,
35 | IndySystem,
36 | IndyProtocols,
37 | dwsLibRuntime;
38 |
39 | contains
40 | WebUpdate.Tools in '..\..\Source\Common\WebUpdate.Tools.pas',
41 | WebUpdate.Classes.Updater in '..\..\Source\Common\WebUpdate.Classes.Updater.pas',
42 | WebUpdate.Classes.WebUpdate in '..\..\Source\Common\WebUpdate.Classes.WebUpdate.pas',
43 | WebUpdate.JSON.Channels in '..\..\Source\Common\WebUpdate.JSON.Channels.pas',
44 | WebUpdate.JSON.Channel in '..\..\Source\Common\WebUpdate.JSON.Channel.pas',
45 | WebUpdate.JSON.Serializer in '..\..\Source\Common\WebUpdate.JSON.Serializer.pas',
46 | WebUpdate.Package.Component in '..\..\Source\Package\WebUpdate.Package.Component.pas';
47 |
48 | end.
49 |
50 |
--------------------------------------------------------------------------------
/Packages/XE5/WebUpdateR.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateR;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO ON}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$LIBSUFFIX '190'}
29 | {$RUNONLY}
30 | {$IMPLICITBUILD OFF}
31 |
32 | requires
33 | vcl,
34 | IndyCore,
35 | IndySystem,
36 | IndyProtocols,
37 | dwsLibRuntime;
38 |
39 | contains
40 | WebUpdate.Tools in '..\..\Source\Common\WebUpdate.Tools.pas',
41 | WebUpdate.Classes.Updater in '..\..\Source\Common\WebUpdate.Classes.Updater.pas',
42 | WebUpdate.Classes.WebUpdate in '..\..\Source\Common\WebUpdate.Classes.WebUpdate.pas',
43 | WebUpdate.JSON.Channels in '..\..\Source\Common\WebUpdate.JSON.Channels.pas',
44 | WebUpdate.JSON.Channel in '..\..\Source\Common\WebUpdate.JSON.Channel.pas',
45 | WebUpdate.JSON.Serializer in '..\..\Source\Common\WebUpdate.JSON.Serializer.pas',
46 | WebUpdate.Package.Component in '..\..\Source\Package\WebUpdate.Package.Component.pas';
47 |
48 | end.
49 |
50 |
--------------------------------------------------------------------------------
/Packages/XE6/WebUpdateR.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateR;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO ON}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$LIBSUFFIX '200'}
29 | {$RUNONLY}
30 | {$IMPLICITBUILD OFF}
31 |
32 | requires
33 | vcl,
34 | IndyCore,
35 | IndySystem,
36 | IndyProtocols,
37 | dwsLibRuntime;
38 |
39 | contains
40 | WebUpdate.Tools in '..\..\Source\Common\WebUpdate.Tools.pas',
41 | WebUpdate.Classes.Updater in '..\..\Source\Common\WebUpdate.Classes.Updater.pas',
42 | WebUpdate.Classes.WebUpdate in '..\..\Source\Common\WebUpdate.Classes.WebUpdate.pas',
43 | WebUpdate.JSON.Channels in '..\..\Source\Common\WebUpdate.JSON.Channels.pas',
44 | WebUpdate.JSON.Channel in '..\..\Source\Common\WebUpdate.JSON.Channel.pas',
45 | WebUpdate.JSON.Serializer in '..\..\Source\Common\WebUpdate.JSON.Serializer.pas',
46 | WebUpdate.Package.Component in '..\..\Source\Package\WebUpdate.Package.Component.pas';
47 |
48 | end.
49 |
50 |
--------------------------------------------------------------------------------
/Packages/RX1/WebUpdateR.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateR;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO OFF}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$LIBSUFFIX '240'}
29 | {$RUNONLY}
30 | {$IMPLICITBUILD OFF}
31 |
32 | requires
33 | vcl,
34 | IndyCore,
35 | IndySystem,
36 | IndyProtocols,
37 | dwsLibRuntime;
38 |
39 | contains
40 | WebUpdate.Tools in '..\..\Source\Common\WebUpdate.Tools.pas',
41 | WebUpdate.Classes.Updater in '..\..\Source\Common\WebUpdate.Classes.Updater.pas',
42 | WebUpdate.Classes.WebUpdate in '..\..\Source\Common\WebUpdate.Classes.WebUpdate.pas',
43 | WebUpdate.JSON.Channels in '..\..\Source\Common\WebUpdate.JSON.Channels.pas',
44 | WebUpdate.JSON.Channel in '..\..\Source\Common\WebUpdate.JSON.Channel.pas',
45 | WebUpdate.JSON.Serializer in '..\..\Source\Common\WebUpdate.JSON.Serializer.pas',
46 | WebUpdate.Package.Component in '..\..\Source\Package\WebUpdate.Package.Component.pas';
47 |
48 | end.
49 |
50 |
--------------------------------------------------------------------------------
/Packages/RX2/WebUpdateR.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateR;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO OFF}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$LIBSUFFIX '250'}
29 | {$RUNONLY}
30 | {$IMPLICITBUILD OFF}
31 |
32 | requires
33 | vcl,
34 | IndyCore,
35 | IndySystem,
36 | IndyProtocols,
37 | dwsLibRuntime;
38 |
39 | contains
40 | WebUpdate.Tools in '..\..\Source\Common\WebUpdate.Tools.pas',
41 | WebUpdate.Classes.Updater in '..\..\Source\Common\WebUpdate.Classes.Updater.pas',
42 | WebUpdate.Classes.WebUpdate in '..\..\Source\Common\WebUpdate.Classes.WebUpdate.pas',
43 | WebUpdate.JSON.Channels in '..\..\Source\Common\WebUpdate.JSON.Channels.pas',
44 | WebUpdate.JSON.Channel in '..\..\Source\Common\WebUpdate.JSON.Channel.pas',
45 | WebUpdate.JSON.Serializer in '..\..\Source\Common\WebUpdate.JSON.Serializer.pas',
46 | WebUpdate.Package.Component in '..\..\Source\Package\WebUpdate.Package.Component.pas';
47 |
48 | end.
49 |
50 |
--------------------------------------------------------------------------------
/Packages/XE7/WebUpdateR.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateR;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO OFF}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$LIBSUFFIX '210'}
29 | {$RUNONLY}
30 | {$IMPLICITBUILD OFF}
31 |
32 | requires
33 | vcl,
34 | IndyCore,
35 | IndySystem,
36 | IndyProtocols,
37 | dwsLibRuntime;
38 |
39 | contains
40 | WebUpdate.Tools in '..\..\Source\Common\WebUpdate.Tools.pas',
41 | WebUpdate.Classes.Updater in '..\..\Source\Common\WebUpdate.Classes.Updater.pas',
42 | WebUpdate.Classes.WebUpdate in '..\..\Source\Common\WebUpdate.Classes.WebUpdate.pas',
43 | WebUpdate.JSON.Channels in '..\..\Source\Common\WebUpdate.JSON.Channels.pas',
44 | WebUpdate.JSON.Channel in '..\..\Source\Common\WebUpdate.JSON.Channel.pas',
45 | WebUpdate.JSON.Serializer in '..\..\Source\Common\WebUpdate.JSON.Serializer.pas',
46 | WebUpdate.Package.Component in '..\..\Source\Package\WebUpdate.Package.Component.pas';
47 |
48 | end.
49 |
50 |
--------------------------------------------------------------------------------
/Packages/XE8/WebUpdateR.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateR;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO OFF}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$LIBSUFFIX '220'}
29 | {$RUNONLY}
30 | {$IMPLICITBUILD OFF}
31 |
32 | requires
33 | vcl,
34 | IndyCore,
35 | IndySystem,
36 | IndyProtocols,
37 | dwsLibRuntime;
38 |
39 | contains
40 | WebUpdate.Tools in '..\..\Source\Common\WebUpdate.Tools.pas',
41 | WebUpdate.Classes.Updater in '..\..\Source\Common\WebUpdate.Classes.Updater.pas',
42 | WebUpdate.Classes.WebUpdate in '..\..\Source\Common\WebUpdate.Classes.WebUpdate.pas',
43 | WebUpdate.JSON.Channels in '..\..\Source\Common\WebUpdate.JSON.Channels.pas',
44 | WebUpdate.JSON.Channel in '..\..\Source\Common\WebUpdate.JSON.Channel.pas',
45 | WebUpdate.JSON.Serializer in '..\..\Source\Common\WebUpdate.JSON.Serializer.pas',
46 | WebUpdate.Package.Component in '..\..\Source\Package\WebUpdate.Package.Component.pas';
47 |
48 | end.
49 |
50 |
--------------------------------------------------------------------------------
/Packages/XE2/WebUpdateR.dpk:
--------------------------------------------------------------------------------
1 | package WebUpdateR;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO ON}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$DESCRIPTION 'WebUpdate Non-Visual runtime'}
29 | {$LIBSUFFIX '160'}
30 | {$RUNONLY}
31 | {$IMPLICITBUILD OFF}
32 |
33 | requires
34 | vcl,
35 | IndyCore,
36 | IndySystem,
37 | IndyProtocols,
38 | dwsLibRuntime;
39 |
40 | contains
41 | WebUpdate.Tools in '..\..\Source\Common\WebUpdate.Tools.pas',
42 | WebUpdate.Classes.Updater in '..\..\Source\Common\WebUpdate.Classes.Updater.pas',
43 | WebUpdate.Classes.WebUpdate in '..\..\Source\Common\WebUpdate.Classes.WebUpdate.pas',
44 | WebUpdate.JSON.Channels in '..\..\Source\Common\WebUpdate.JSON.Channels.pas',
45 | WebUpdate.JSON.Channel in '..\..\Source\Common\WebUpdate.JSON.Channel.pas',
46 | WebUpdate.JSON.Serializer in '..\..\Source\Common\WebUpdate.JSON.Serializer.pas',
47 | WebUpdate.Package.Component in '..\..\Source\Package\WebUpdate.Package.Component.pas';
48 |
49 | end.
50 |
51 |
--------------------------------------------------------------------------------
/Source/Example Application/MainUnit.dfm:
--------------------------------------------------------------------------------
1 | object FormExample: TFormExample
2 | Left = 0
3 | Top = 0
4 | Caption = 'Example Application'
5 | ClientHeight = 128
6 | ClientWidth = 201
7 | Color = clBtnFace
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -11
11 | Font.Name = 'Tahoma'
12 | Font.Style = []
13 | OldCreateOrder = False
14 | OnCreate = FormCreate
15 | OnDestroy = FormDestroy
16 | OnShow = FormShow
17 | PixelsPerInch = 96
18 | TextHeight = 13
19 | object LabelChannel: TLabel
20 | Left = 8
21 | Top = 11
22 | Width = 43
23 | Height = 13
24 | Caption = 'Channel:'
25 | end
26 | object ButtonCheckUpdates: TButton
27 | Left = 8
28 | Top = 35
29 | Width = 185
30 | Height = 25
31 | Caption = '&Check for Updates'
32 | Default = True
33 | TabOrder = 0
34 | OnClick = ButtonCheckUpdatesClick
35 | end
36 | object ButtonExit: TButton
37 | Left = 8
38 | Top = 97
39 | Width = 185
40 | Height = 25
41 | Caption = 'E&xit'
42 | TabOrder = 1
43 | OnClick = ButtonExitClick
44 | end
45 | object ButtonPerformUpdate: TButton
46 | Left = 8
47 | Top = 66
48 | Width = 185
49 | Height = 25
50 | Caption = 'Perform &Update'
51 | TabOrder = 2
52 | OnClick = ButtonPerformUpdateClick
53 | end
54 | object ComboBoxChannels: TComboBox
55 | Left = 57
56 | Top = 8
57 | Width = 136
58 | Height = 21
59 | Style = csDropDownList
60 | TabOrder = 3
61 | OnChange = ComboBoxChannelsChange
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/Packages/XE2/Packages.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {B0BE1F5A-716F-458F-A2E9-1E695A5535D7}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Default.Personality.12
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Delphinus.Install.json:
--------------------------------------------------------------------------------
1 | {
2 | "search_pathes":
3 | [
4 | {
5 | "pathes": "Common;Package",
6 | "platforms": "Win32;Win64;OSX32"
7 | }
8 | ],
9 | "browsing_pathes":
10 | [
11 | {
12 | "pathes": "Common;Package",
13 | "platforms": "Win32;Win64;OSX32"
14 | }
15 | ],
16 |
17 | "source_folders":
18 | [
19 | {
20 | "folder": "Source",
21 | "base": "Source",
22 | "recursive": true,
23 | "filter": "*;*.*"
24 | }
25 | ],
26 |
27 | "projects":
28 | [
29 | {
30 | "project": "Packages\\XE2\\Packages.groupproj",
31 | "compiler_min": 23,
32 | "compiler_max": 23
33 | },
34 | {
35 | "project": "Packages\\XE3\\Packages.groupproj",
36 | "compiler_min": 24,
37 | "compiler_max": 24
38 | },
39 | {
40 | "project": "Packages\\XE4\\Packages.groupproj",
41 | "compiler_min": 25,
42 | "compiler_max": 25
43 | },
44 | {
45 | "project": "Packages\\XE5\\Packages.groupproj",
46 | "compiler_min": 26,
47 | "compiler_max": 26
48 | },
49 | {
50 | "project": "Packages\\XE6\\Packages.groupproj",
51 | "compiler_min": 27,
52 | "compiler_max": 27
53 | },
54 | {
55 | "project": "Packages\\XE7\\Packages.groupproj",
56 | "compiler_min": 28,
57 | "compiler_max": 28
58 | },
59 | {
60 | "project": "Packages\\XE8\\Packages.groupproj",
61 | "compiler_min": 29,
62 | "compiler_max": 29
63 | },
64 | {
65 | "project": "Packages\\RX\\Packages.groupproj",
66 | "compiler_min": 30,
67 | "compiler_max": 30
68 | },
69 | {
70 | "project": "Packages\\RX1\\Packages.groupproj",
71 | "compiler_min": 31,
72 | "compiler_max": 31
73 | }
74 | ]
75 | }
--------------------------------------------------------------------------------
/Packages/RX/Packages.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {B0BE1F5A-716F-458F-A2E9-1E695A5535D7}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Default.Personality.12
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Packages/RX1/Packages.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {B0BE1F5A-716F-458F-A2E9-1E695A5535D7}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Default.Personality.12
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Packages/RX2/Packages.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {F6F4CE59-8301-44FE-9E78-A17DA3D8B97D}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Default.Personality.12
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Packages/XE7/Packages.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {B0BE1F5A-716F-458F-A2E9-1E695A5535D7}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Default.Personality.12
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Packages/XE8/Packages.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {B0BE1F5A-716F-458F-A2E9-1E695A5535D7}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Default.Personality.12
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Source/Authoring Tool/WebUpdate.GUI.CommandLine.dfm:
--------------------------------------------------------------------------------
1 | object FormCommandLine: TFormCommandLine
2 | Left = 0
3 | Top = 0
4 | BorderStyle = bsDialog
5 | Caption = 'Command-line switches'
6 | ClientHeight = 353
7 | ClientWidth = 624
8 | Color = clBtnFace
9 | Font.Charset = DEFAULT_CHARSET
10 | Font.Color = clWindowText
11 | Font.Height = -11
12 | Font.Name = 'Tahoma'
13 | Font.Style = []
14 | OldCreateOrder = False
15 | Position = poMainFormCenter
16 | OnCreate = FormCreate
17 | PixelsPerInch = 96
18 | TextHeight = 13
19 | object MemoCommandLine: TMemo
20 | Left = 0
21 | Top = 0
22 | Width = 624
23 | Height = 353
24 | Align = alClient
25 | Color = clBlack
26 | Font.Charset = DEFAULT_CHARSET
27 | Font.Color = clSilver
28 | Font.Height = -16
29 | Font.Name = 'Terminal_Hex'
30 | Font.Style = []
31 | Lines.Strings = (
32 | 'Command-line switches'
33 | '---------------------'
34 | ''
35 | 'Syntax: %s project.wup command [more commands] [-options]'
36 | ''
37 | ' project.wup must be replaced by your project name'
38 | ''
39 | 'Commands:'
40 | '---------'
41 | ''
42 | ' s or S or Snapshot (take snapshot)'
43 | ' c or C or Copy (copy to path)'
44 | ' u or U or Upload (upload to server)'
45 | ''
46 | 'Options:'
47 | '---------'
48 | ''
49 |
50 | ' -Channel="channel name" (with/without quotes, default: "N' +
51 | 'ightly")'
52 |
53 | ' -FtpHost=host (FTP host name, overrides project' +
54 | #39's default)'
55 |
56 | ' -FtpUser=username (FTP user name, overrides project' +
57 | #39's default)'
58 |
59 | ' -FtpPassword=password (FTP password, overrides project'#39 +
60 | 's default)'
61 | ' -CopyPath=path (Path of snapshot copies)'
62 | ''
63 | 'Example:'
64 | '--------'
65 | ''
66 | ' %s project.wup scu -Channel=Beta')
67 | ParentFont = False
68 | ReadOnly = True
69 | TabOrder = 0
70 | end
71 | end
72 |
--------------------------------------------------------------------------------
/Source/Authoring Tool/WebUpdate.GUI.About.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.GUI.About;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes,
7 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
8 | Vcl.ExtCtrls;
9 |
10 | type
11 | TFormAbout = class(TForm)
12 | ImageHeader: TImage;
13 | LabelAnd: TLabel;
14 | LabelComma1: TLabel;
15 | LabelComma2: TLabel;
16 | LabelCopyright: TLabel;
17 | LabelDualLicenses: TLabel;
18 | LabelDWS: TLabel;
19 | LabelIndy: TLabel;
20 | LabelJEDI: TLabel;
21 | LabelSubTitle: TLabel;
22 | LabelTitle: TLabel;
23 | LabelVirtualTreeview: TLabel;
24 | MemoLGPL: TMemo;
25 | MemoMIT: TMemo;
26 | PanelHeader: TPanel;
27 | RadioButtonLicenseLGPL: TRadioButton;
28 | RadioButtonLicenseMIT: TRadioButton;
29 | procedure LabelDWSClick(Sender: TObject);
30 | procedure LabelIndyClick(Sender: TObject);
31 | procedure LabelJEDIClick(Sender: TObject);
32 | procedure LabelVirtualTreeviewClick(Sender: TObject);
33 | procedure RadioButtonLicenseLGPLClick(Sender: TObject);
34 | procedure RadioButtonLicenseMITClick(Sender: TObject);
35 | end;
36 |
37 | implementation
38 |
39 | {$R *.dfm}
40 |
41 | uses
42 | WinApi.ShellApi;
43 |
44 | procedure OpenLink(const URL: string);
45 | begin
46 | ShellExecute(0, 'open', PChar(URL), nil, nil, SW_SHOWDEFAULT)
47 | end;
48 |
49 | procedure TFormAbout.LabelDWSClick(Sender: TObject);
50 | begin
51 | OpenLink('http://www.delphitools.info/dwscript/');
52 | end;
53 |
54 | procedure TFormAbout.LabelIndyClick(Sender: TObject);
55 | begin
56 | OpenLink('http://www.indyproject.org/');
57 | end;
58 |
59 | procedure TFormAbout.LabelJEDIClick(Sender: TObject);
60 | begin
61 | OpenLink('http://www.delphi-jedi.org/');
62 | end;
63 |
64 | procedure TFormAbout.LabelVirtualTreeviewClick(Sender: TObject);
65 | begin
66 | OpenLink('http://www.jam-software.com/virtual-treeview/');
67 | end;
68 |
69 | procedure TFormAbout.RadioButtonLicenseLGPLClick(Sender: TObject);
70 | begin
71 | MemoLGPL.BringToFront;
72 | end;
73 |
74 | procedure TFormAbout.RadioButtonLicenseMITClick(Sender: TObject);
75 | begin
76 | MemoMIT.BringToFront;
77 | end;
78 |
79 | end.
80 |
--------------------------------------------------------------------------------
/Source/Common/WebUpdate.Tools.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.Tools;
2 |
3 | interface
4 |
5 | uses
6 | {$IFDEF MSWINDOWS} Winapi.Windows, {$ENDIF}
7 | System.Classes, System.SysUtils, IdHashMessageDigest, IdGlobal;
8 |
9 | {$IFDEF MSWINDOWS}
10 | function FileTimeToDateTime(Time: TFileTime): TDateTime;
11 | {$ENDIF}
12 | function MD5(const FileName: string): string; overload;
13 | function MD5(Stream: TStream): string; overload;
14 |
15 | function WebToLocalFileName(const WebFileName: string): string;
16 | function LocalToWebFileName(const LocalFileName: string): string;
17 |
18 | implementation
19 |
20 | {$IFDEF MSWINDOWS}
21 | function FileTimeToDateTime(Time: TFileTime): TDateTime;
22 |
23 | function InternalEncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond,
24 | AMilliSecond: Word): TDateTime;
25 | var
26 | LTime: TDateTime;
27 | Success: Boolean;
28 | begin
29 | Result := 0;
30 | Success := TryEncodeDate(AYear, AMonth, ADay, Result);
31 | if Success then
32 | begin
33 | Success := TryEncodeTime(AHour, AMinute, ASecond, AMilliSecond, LTime);
34 | if Success then
35 | if Result >= 0 then
36 | Result := Result + LTime
37 | else
38 | Result := Result - LTime
39 | end;
40 | end;
41 |
42 | var
43 | LFileTime: TFileTime;
44 | SysTime: TSystemTime;
45 | begin
46 | Result := 0;
47 | FileTimeToLocalFileTime(Time, LFileTime);
48 |
49 | if FileTimeToSystemTime(LFileTime, SysTime) then
50 | with SysTime do
51 | begin
52 | Result := InternalEncodeDateTime(wYear, wMonth, wDay, wHour, wMinute,
53 | wSecond, wMilliseconds);
54 | end;
55 | end;
56 | {$ENDIF}
57 |
58 | function MD5(Stream: TStream): string;
59 | var
60 | IdMD5: TIdHashMessageDigest5;
61 | begin
62 | IdMD5 := TIdHashMessageDigest5.Create;
63 | try
64 | Result := IdMD5.HashStreamAsHex(Stream);
65 | finally
66 | IdMD5.Free;
67 | end;
68 | end;
69 |
70 | function MD5(const FileName: string): string;
71 | var
72 | FS: TFileStream;
73 | begin
74 | FS := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
75 | try
76 | Result := MD5(FS);
77 | finally
78 | FS.Free;
79 | end;
80 | end;
81 |
82 | function WebToLocalFileName(const WebFileName: string): string;
83 | begin
84 | Result := StringReplace(WebFileName, '/', '\', [rfReplaceAll]);
85 | end;
86 |
87 | function LocalToWebFileName(const LocalFileName: string): string;
88 | begin
89 | Result := StringReplace(LocalFileName, '\', '/', [rfReplaceAll]);
90 | end;
91 |
92 | end.
93 |
--------------------------------------------------------------------------------
/Source/Example Application/MainUnit.pas:
--------------------------------------------------------------------------------
1 | unit MainUnit;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes,
7 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
8 | WebUpdate.Classes.WebUpdate;
9 |
10 | type
11 | TFormExample = class(TForm)
12 | ButtonCheckUpdates: TButton;
13 | ButtonExit: TButton;
14 | ButtonPerformUpdate: TButton;
15 | LabelChannel: TLabel;
16 | ComboBoxChannels: TComboBox;
17 | procedure FormCreate(Sender: TObject);
18 | procedure ButtonCheckUpdatesClick(Sender: TObject);
19 | procedure ButtonExitClick(Sender: TObject);
20 | procedure FormDestroy(Sender: TObject);
21 | procedure FormShow(Sender: TObject);
22 | procedure ButtonPerformUpdateClick(Sender: TObject);
23 | procedure ComboBoxChannelsChange(Sender: TObject);
24 | private
25 | FWebUpdate: TWebUpdate;
26 | end;
27 |
28 | var
29 | FormExample: TFormExample;
30 |
31 | implementation
32 |
33 | {$R *.dfm}
34 |
35 | { TFormExample }
36 |
37 | procedure TFormExample.FormCreate(Sender: TObject);
38 | begin
39 | FWebUpdate := TWebUpdate.Create;
40 | FWebUpdate.BaseURL := 'http://www.savioursofsoul.de/Christian/WebUpdate/';
41 | FWebUpdate.ChannelName := 'Stable';
42 | end;
43 |
44 | procedure TFormExample.FormDestroy(Sender: TObject);
45 | begin
46 | FWebUpdate.Free;
47 | end;
48 |
49 | procedure TFormExample.FormShow(Sender: TObject);
50 | var
51 | Index: Integer;
52 | begin
53 | FWebUpdate.GetChannels(ComboBoxChannels.Items);
54 | FWebUpdate.GetLocalChannelInformation;
55 | Index := ComboBoxChannels.Items.IndexOf(FWebUpdate.ChannelName);
56 | if Index >= 0 then
57 | ComboBoxChannels.ItemIndex := Index
58 | else
59 | ComboBoxChannels.ItemIndex := 0;
60 | end;
61 |
62 | procedure TFormExample.ButtonCheckUpdatesClick(Sender: TObject);
63 | begin
64 | if FWebUpdate.CheckForUpdate then
65 | begin
66 | ButtonPerformUpdate.Default := True;
67 | ButtonPerformUpdate.SetFocus;
68 | if MessageDlg('A new update is available!'#13#10#13#10'Update now?',
69 | mtConfirmation, [mbYes, mbNo], 0) = mrYes then
70 | ButtonPerformUpdateClick(Self);
71 | end
72 | else
73 | MessageDlg('No update is available!', mtInformation, [mbOK], 0);
74 | end;
75 |
76 | procedure TFormExample.ButtonPerformUpdateClick(Sender: TObject);
77 | begin
78 | FWebUpdate.PerformUpdate;
79 | end;
80 |
81 | procedure TFormExample.ComboBoxChannelsChange(Sender: TObject);
82 | begin
83 | FWebUpdate.ChannelName := ComboBoxChannels.Text;
84 | end;
85 |
86 | procedure TFormExample.ButtonExitClick(Sender: TObject);
87 | begin
88 | Close;
89 | end;
90 |
91 | end.
92 |
--------------------------------------------------------------------------------
/Source/Authoring Tool/WebUpdate.JSON.Preferences.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.JSON.Preferences;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, dwsJSON, WebUpdate.JSON.Serializer;
7 |
8 | type
9 | TWebUpdatePreferences = class(TJsonSerializer)
10 | private
11 | FFileName: TFileName;
12 | FRecentProject: TFileName;
13 | FTop: Integer;
14 | FLeft: Integer;
15 | FViewFiles: Boolean;
16 | procedure Load;
17 | procedure Save;
18 | protected
19 | procedure Read(Root: TdwsJSONObject); override;
20 | procedure Write(Root: TdwsJSONObject); override;
21 | public
22 | constructor Create(FileName: TFileName);
23 | destructor Destroy; override;
24 |
25 | class function GetID: string; override;
26 |
27 | property Left: Integer read FLeft write FLeft;
28 | property Top: Integer read FTop write FTop;
29 | property RecentProject: TFileName read FRecentProject write FRecentProject;
30 | property ViewFiles: Boolean read FViewFiles write FViewFiles;
31 | end;
32 |
33 | implementation
34 |
35 | uses
36 | dwsXPlatform;
37 |
38 | { TWebUpdatePreferences }
39 |
40 | constructor TWebUpdatePreferences.Create(FileName: TFileName);
41 | begin
42 | FLeft := 16;
43 | FTop := 16;
44 | FFileName := FileName;
45 | if FileExists(FFileName) then
46 | Load;
47 | end;
48 |
49 | destructor TWebUpdatePreferences.Destroy;
50 | begin
51 | Save;
52 | inherited;
53 | end;
54 |
55 | class function TWebUpdatePreferences.GetID: string;
56 | begin
57 | Result := 'Preferences';
58 | end;
59 |
60 | procedure TWebUpdatePreferences.Load;
61 | begin
62 | LoadFromFile(FFileName);
63 | end;
64 |
65 | procedure TWebUpdatePreferences.Save;
66 | begin
67 | SaveToFile(FFileName);
68 | end;
69 |
70 | procedure TWebUpdatePreferences.Read(Root: TdwsJSONObject);
71 | var
72 | Value: TdwsJSONValue;
73 | begin
74 | inherited;
75 |
76 | // read window position
77 | Value := Root.Items['Left'];
78 | if Assigned(Value) then
79 | FLeft := Value.AsInteger;
80 | Value := Root.Items['Top'];
81 | if Assigned(Value) then
82 | FTop := Value.AsInteger;
83 |
84 | // read view files
85 | Value := Root.Items['ViewFiles'];
86 | if Assigned(Value) then
87 | FViewFiles := Value.AsBoolean;
88 |
89 | // read recent project
90 | Value := Root.Items['RecentProject'];
91 | if Assigned(Value) then
92 | FRecentProject := Value.AsString;
93 | end;
94 |
95 | procedure TWebUpdatePreferences.Write(Root: TdwsJSONObject);
96 | begin
97 | inherited;
98 |
99 | // write window position
100 | Root.AddValue('Left').AsInteger := FLeft;
101 | Root.AddValue('Top').AsInteger := FTop;
102 |
103 | // write view files
104 | Root.AddValue('ViewFiles').AsBoolean := FViewFiles;
105 |
106 | // write recent project
107 | if FRecentProject <> '' then
108 | Root.AddValue('RecentProject').AsString := FRecentProject;
109 | end;
110 |
111 | end.
112 |
--------------------------------------------------------------------------------
/Source/Package/WebUpdate.Package.Component.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.Package.Component;
2 |
3 | interface
4 |
5 | uses
6 | System.Classes, System.SysUtils, WebUpdate.Classes.Updater,
7 | WebUpdate.Classes.WebUpdate;
8 |
9 | type
10 | TWebUpdateComponent = class(TComponent)
11 | private
12 | FWebUpdate: TWebUpdate;
13 | function GetBaseURL: string;
14 | function GetChannelName: string;
15 | function GetDownloadUpdater: Boolean;
16 | procedure SetBaseURL(const Value: string);
17 | procedure SetChannelName(const Value: string);
18 | procedure SetDownloadUpdater(const Value: Boolean);
19 | public
20 | constructor Create(AOwner: TComponent); override;
21 | destructor Destroy; override;
22 |
23 | function CheckForUpdate: Boolean;
24 | procedure GetLocalChannelInformation;
25 | procedure GetChannelsInformationFromServer;
26 | procedure PerformUpdate;
27 | procedure PerformDownloadUpdater;
28 |
29 | property WebUpdate: TWebUpdate read FWebUpdate;
30 | published
31 | property BaseURL: string read GetBaseURL write SetBaseURL;
32 | property ChannelName: string read GetChannelName write SetChannelName;
33 | property DownloadUpdater: Boolean read GetDownloadUpdater write SetDownloadUpdater default False;
34 | end;
35 |
36 | implementation
37 |
38 | resourcestring
39 | RStrURLNotSpecified = 'URL not specified!';
40 |
41 | { TWebUpdateComponent }
42 |
43 | constructor TWebUpdateComponent.Create(AOwner: TComponent);
44 | begin
45 | inherited;
46 | FWebUpdate := TWebUpdate.Create;
47 | FWebUpdate.BaseURL := '';
48 | end;
49 |
50 | destructor TWebUpdateComponent.Destroy;
51 | begin
52 | FWebUpdate.Free;
53 | inherited;
54 | end;
55 |
56 | function TWebUpdateComponent.CheckForUpdate: Boolean;
57 | begin
58 | Result := FWebUpdate.CheckForUpdate;
59 | end;
60 |
61 | function TWebUpdateComponent.GetBaseURL: string;
62 | begin
63 | Result := FWebUpdate.BaseURL;
64 | end;
65 |
66 | function TWebUpdateComponent.GetChannelName: string;
67 | begin
68 | Result := FWebUpdate.ChannelName;
69 | end;
70 |
71 | procedure TWebUpdateComponent.GetChannelsInformationFromServer;
72 | begin
73 | FWebUpdate.GetChannelsInformationFromServer;
74 | end;
75 |
76 | procedure TWebUpdateComponent.GetLocalChannelInformation;
77 | begin
78 | FWebUpdate.GetLocalChannelInformation
79 | end;
80 |
81 | function TWebUpdateComponent.GetDownloadUpdater: Boolean;
82 | begin
83 | Result := FWebUpdate.DownloadUpdater;
84 | end;
85 |
86 | procedure TWebUpdateComponent.PerformDownloadUpdater;
87 | begin
88 | if FWebUpdate.BaseURL = '' then
89 | raise Exception.Create(RStrURLNotSpecified);
90 |
91 | FWebUpdate.PerformDownloadUpdater;
92 | end;
93 |
94 | procedure TWebUpdateComponent.PerformUpdate;
95 | begin
96 | if FWebUpdate.BaseURL = '' then
97 | raise Exception.Create(RStrURLNotSpecified);
98 |
99 | FWebUpdate.PerformUpdate;
100 | end;
101 |
102 | procedure TWebUpdateComponent.SetBaseURL(const Value: string);
103 | begin
104 | FWebUpdate.BaseURL := Value;
105 | end;
106 |
107 | procedure TWebUpdateComponent.SetChannelName(const Value: string);
108 | begin
109 | FWebUpdate.ChannelName := Value;
110 | end;
111 |
112 | procedure TWebUpdateComponent.SetDownloadUpdater(const Value: Boolean);
113 | begin
114 | FWebUpdate.DownloadUpdater := Value;
115 | end;
116 |
117 | end.
118 |
--------------------------------------------------------------------------------
/Source/Authoring Tool/WebUpdate.GUI.Options.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.GUI.Options;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes,
7 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
8 | Vcl.ExtCtrls, Vcl.ComCtrls, Vcl.Mask,
9 | VirtualTrees, JvExMask, JvToolEdit;
10 |
11 | type
12 | TOptionsItem = record
13 | TabSheet: TTabSheet;
14 | end;
15 | POptionsItem = ^TOptionsItem;
16 |
17 | TFormOptions = class(TForm)
18 | ButtonCancel: TButton;
19 | ButtonOK: TButton;
20 | CheckBoxAutoCopyUpload: TCheckBox;
21 | CheckBoxCopyTo: TCheckBox;
22 | EditBaseDirectory: TJvDirectoryEdit;
23 | EditChannelFileName: TJvFilenameEdit;
24 | EditCopyPath: TEdit;
25 | EditFtpPassword: TEdit;
26 | EditFtpServer: TEdit;
27 | EditFtpUsername: TEdit;
28 | GroupBoxCopy: TGroupBox;
29 | GroupBoxFTP: TGroupBox;
30 | LabelChannelFileName: TLabel;
31 | LabelFileName: TLabel;
32 | LabelPassword: TLabel;
33 | LabelServer: TLabel;
34 | LabelUsername: TLabel;
35 | PageControl: TPageControl;
36 | Panel: TPanel;
37 | TabSheetFTP: TTabSheet;
38 | TabSheetMain: TTabSheet;
39 | TreeOptions: TVirtualStringTree;
40 | CheckBoxMD5: TCheckBox;
41 | procedure FormCreate(Sender: TObject);
42 | procedure EditChannelFileNameAfterDialog(Sender: TObject; var AName: string;
43 | var AAction: Boolean);
44 | procedure TreeOptionsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
45 | Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
46 | procedure TreeOptionsChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
47 | private
48 | procedure SetupTree;
49 | end;
50 |
51 | implementation
52 |
53 | {$R *.dfm}
54 |
55 | { TFormOptions }
56 |
57 | procedure TFormOptions.EditChannelFileNameAfterDialog(Sender: TObject;
58 | var AName: string; var AAction: Boolean);
59 | begin
60 | // try to make the path relative
61 | AName := ExtractRelativePath(IncludeTrailingPathDelimiter(
62 | EditBaseDirectory.Directory), AName);
63 | end;
64 |
65 | procedure TFormOptions.FormCreate(Sender: TObject);
66 | begin
67 | TreeOptions.NodeDataSize := SizeOf(TOptionsItem);
68 | SetupTree;
69 | PageControl.ActivePageIndex := 0;
70 | end;
71 |
72 | procedure TFormOptions.TreeOptionsChange(Sender: TBaseVirtualTree;
73 | Node: PVirtualNode);
74 | var
75 | NodeData: POptionsItem;
76 | begin
77 | if Assigned(Node) then
78 | begin
79 | NodeData := TreeOptions.GetNodeData(Node);
80 | PageControl.ActivePage := NodeData^.TabSheet;
81 | end;
82 | end;
83 |
84 | procedure TFormOptions.TreeOptionsGetText(Sender: TBaseVirtualTree;
85 | Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
86 | var CellText: string);
87 | var
88 | NodeData: POptionsItem;
89 | begin
90 | NodeData := TreeOptions.GetNodeData(Node);
91 | CellText := NodeData^.TabSheet.Caption;
92 | end;
93 |
94 | procedure TFormOptions.SetupTree;
95 | var
96 | Node: PVirtualNode;
97 | NodeData: POptionsItem;
98 | Index: Integer;
99 | begin
100 | // build tree
101 | for Index := 0 to PageControl.PageCount - 1 do
102 | begin
103 | Node := TreeOptions.AddChild(TreeOptions.RootNode);
104 | NodeData := TreeOptions.GetNodeData(Node);
105 | NodeData^.TabSheet := PageControl.Pages[Index];
106 | end;
107 | end;
108 |
109 | end.
110 |
--------------------------------------------------------------------------------
/Source/Web Update Tools.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {0F76F6EF-5669-4EF1-AB45-2FC4E56B085A}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Default.Personality.12
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | WebUpdate
2 | =========
3 |
4 | WebUpdate is a bunch of code that can be included into any application to add some simple JSON based WebUpdate. The contained authoring tool allows to create snapshots with a single click. These snapshots can be copied to a dedicated location or uploaded to an FTP server. This can also be done automatically when taking a snapshot. Once uploaded the WebUpdate only needs a simple HTTP connection in order to perform a web update.
5 |
6 | The tool was created after thinking about how a modern, lightweight web update tool could work without the need of an extra server (only file serving is required). It is not yet used and thus mostly untested beyond the used in the tool itself.
7 |
8 | In order to use this tool in your project there are a few prerequisites. First the source code is licensed under a dual license of MPL or LGPL, which means you can use this either under the conditions of MPL or under the conditions of LGPL. Both have advantages and disadvantages, however the essence of these libraries is that you mention the use of this library and to allow integration of changes to the original project. If you need to license this under a different license, feel free to contact me.
9 |
10 | Beyond the license, there are at least 4 dependencies to other libraries namely:
11 | * [DWS](http://www.delphitools.info/dwscript/)
12 | * [Virtual Treeview](http://www.jam-software.com/virtual-treeview/)
13 | * [JEDI](http://www.delphi-jedi.org/)
14 | * [Indy](http://www.indyproject.org/)
15 |
16 | Please make sure you have these libraries accessible from your Delphi environment. So far all modern Delphi XE versions are supported. Older versions might work as well, but probably need some refactoring in order to run out of the box.
17 |
18 | Beyond this a basic Delphinus-Support has been added, which should make installation easier in the future.
19 |
20 | Command-line switches (Authoring tool)
21 | --------------------------------------
22 |
23 | In case you want to automate the authoring tool, you can use the following command-line switches. In fact the tool will still be a GUI-tool, but with a hidden user interface, so don't expect any output of the tool. Following, all commands and options are listed:
24 |
25 | Syntax: AuthoringTool.exe project.wup command [more commands] [-options]
26 |
27 | project.wup must be replaced by your project name
28 |
29 | Commands:
30 | ---------
31 |
32 | s or S or Snapshot (take snapshot)
33 | c or C or Copy (copy to path)
34 | u or U or Upload (upload to server)
35 |
36 | Options:
37 | ---------
38 |
39 | -Channel="channel name" (with/without quotes, default: "Nightly")
40 | -FtpHost=host (FTP host name, overrides project's default)
41 | -FtpUser=username (FTP user name, overrides project's default)
42 | -FtpPassword=password (FTP password, overrides project's default)
43 | -CopyPath=path (Path of snapshot copies)
44 |
45 | Example:
46 | --------
47 |
48 | AuthoringTool.exe project.wup scu -Channel=Beta
49 |
50 |
51 | Command-line switches (Updater)
52 | -------------------------------
53 |
54 | While the 'Updater' tool can be started as stand-alone tool, it is supposed to work as a helper for a main application. It is required because a running application can't replace itself.
55 |
56 | Syntax: Updater.exe [-options]
57 |
58 | Options:
59 | --------
60 |
61 | -u=URL (Base URL for JSON files)
62 | -c=Channel (Update Channel, default is 'Stable')
63 | -f=FileName (Channels) (Filename of channels definition file)
64 | -d=Delay (Integer) (Time in milliseconds before updating starts)
65 | -l=FileName (Local filename of current setup)
66 | -e=ExeFileName (Name of main application executable)
67 | -w=WindowCaption (Caption of main application window)
68 | -v (Verbose)
69 |
70 | Example:
71 | --------
72 |
73 | Updater.exe -c=Nightly
74 |
75 |
76 |
--------------------------------------------------------------------------------
/Source/Common/WebUpdate.JSON.Channels.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.JSON.Channels;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, System.Generics.Collections, dwsJSON,
7 | WebUpdate.JSON.Serializer;
8 |
9 | type
10 | TWebUpdateChannelItem = class
11 | Name: string;
12 | FileName: TFileName;
13 | Modified: TDateTime;
14 | MD5: string;
15 | end;
16 | TWebUpdateChannelItems = TObjectList;
17 |
18 | TWebUpdateChannels = class(TJsonSerializer)
19 | private
20 | FItems: TWebUpdateChannelItems;
21 | protected
22 | procedure Read(Root: TdwsJSONObject); override;
23 | procedure Write(Root: TdwsJSONObject); override;
24 | public
25 | constructor Create;
26 | destructor Destroy; override;
27 | class function GetID: string; override;
28 |
29 | function GetItemForChannel(ChannelName: string): TWebUpdateChannelItem;
30 |
31 | property Items: TWebUpdateChannelItems read FItems;
32 | end;
33 |
34 | implementation
35 |
36 | { TWebUpdateChannels }
37 |
38 | constructor TWebUpdateChannels.Create;
39 | begin
40 | inherited;
41 | FItems := TWebUpdateChannelItems.Create;
42 | end;
43 |
44 | destructor TWebUpdateChannels.Destroy;
45 | begin
46 | FItems.Free;
47 | inherited;
48 | end;
49 |
50 | class function TWebUpdateChannels.GetID: string;
51 | begin
52 | Result := 'Channels';
53 | end;
54 |
55 | function TWebUpdateChannels.GetItemForChannel(
56 | ChannelName: string): TWebUpdateChannelItem;
57 | var
58 | Index: Integer;
59 | begin
60 | Result := nil;
61 | for Index := 0 to FItems.Count - 1 do
62 | if SameText(FItems[Index].Name, ChannelName) then
63 | Exit(FItems[Index]);
64 | end;
65 |
66 | procedure TWebUpdateChannels.Read(Root: TdwsJSONObject);
67 | var
68 | Value: TdwsJSONValue;
69 | Channels: TdwsJSONArray;
70 | Index: Integer;
71 | Item: TWebUpdateChannelItem;
72 | begin
73 | inherited;
74 |
75 | Value := Root.Items['Channels'];
76 |
77 | // try the older 'Files' [deprecated!]
78 | if not (Value is TdwsJSONArray) then
79 | Value := Root.Items['Files'];
80 |
81 | if not (Value is TdwsJSONArray) then
82 | raise Exception.Create('Array expected!');
83 |
84 | // clear existing items
85 | FItems.Clear;
86 |
87 | Channels := TdwsJSONArray(Value);
88 | for Index := 0 to Channels.ElementCount - 1 do
89 | begin
90 | Item := TWebUpdateChannelItem.Create;
91 |
92 | // get name
93 | Value := Channels.Elements[Index].Items['Name'];
94 | Item.Name := Value.AsString;
95 |
96 | // get filename
97 | Value := Channels.Elements[Index].Items['FileName'];
98 | if Assigned(Value) then
99 | Item.FileName := Value.AsString
100 | else
101 | Item.FileName := Item.Name + '/' + Item.Name + '.json';
102 |
103 | // get file modified
104 | Value := Channels.Elements[Index].Items['Modified'];
105 | if Assigned(Value) then
106 | Item.Modified := ISO8601ToDateTime(Value.AsString)
107 | else
108 | Item.Modified := 0;
109 |
110 | // get MD5 hash
111 | Value := Channels.Elements[Index].Items['MD5'];
112 | if Assigned(Value) then
113 | Item.MD5 := Value.AsString;
114 |
115 | FItems.Add(Item);
116 | end;
117 | end;
118 |
119 | procedure TWebUpdateChannels.Write(Root: TdwsJSONObject);
120 | var
121 | Value: TdwsJSONObject;
122 | Channels: TdwsJSONArray;
123 | Item: TWebUpdateChannelItem;
124 | begin
125 | inherited;
126 |
127 | Root.AddValue('Modified').AsString := DateTimeToISO8601(Now);
128 | Channels := Root.AddArray('Channels');
129 | for Item in FItems do
130 | begin
131 | Value := TdwsJSONObject(Channels.AddObject);
132 | Value.AddValue('Name').AsString := Item.Name;
133 |
134 | // eventually store file name (if not identical to Name + '.json')
135 | if not (Item.FileName = Item.Name + '/' + Item.Name + '.json') then
136 | if not (Item.FileName = '') then
137 | Value.AddValue('FileName').AsString := Item.FileName;
138 |
139 | // eventually store file modification date
140 | if Item.Modified > 0 then
141 | Value.AddValue('Modified').AsString := DateTimeToISO8601(Item.Modified);
142 |
143 | // eventually store MD5 hash
144 | if Item.MD5 <> '' then
145 | Value.AddValue('MD5').AsString := Item.MD5;
146 | end;
147 | end;
148 |
149 | end.
150 |
--------------------------------------------------------------------------------
/Source/Common/WebUpdate.JSON.Serializer.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.JSON.Serializer;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, dwsJSON;
7 |
8 | type
9 | EJsonSerializer = class(Exception);
10 |
11 | TJsonSerializer = class
12 | protected
13 | procedure Read(Root: TdwsJSONObject); virtual;
14 | procedure Write(Root: TdwsJSONObject); virtual;
15 | public
16 | class function GetID: string; virtual;
17 |
18 | procedure LoadFromFile(const FileName: TFileName);
19 | procedure SaveToFile(const FileName: TFileName);
20 |
21 | procedure LoadFromString(const Text: string);
22 | function SaveToString: string;
23 | end;
24 |
25 | function DateTimeToISO8601(DateTime: TDateTime): string;
26 | function ISO8601ToDateTime(const Value: string): TDateTime;
27 |
28 | implementation
29 |
30 | uses
31 | dwsXPlatform;
32 |
33 | function DateTimeToISO8601(DateTime: TDateTime): string;
34 | begin
35 | Result := FormatDateTime('yyyy-mm-dd"' + 'T' + '"hh":"mm":"ss.zzz', DateTime);
36 | end;
37 |
38 | function ISO8601ToDateTime(const Value: string): TDateTime;
39 |
40 | function Str2Time(s: string): TDateTime;
41 | var
42 | Hour, Minute, MSec, Second: Word;
43 | Temp: Integer;
44 | begin
45 | s := Trim(s);
46 | if s = '' then
47 | Result := 0
48 | else
49 | begin
50 | Temp := Pos(':', s);
51 | Hour := StrToInt(Copy(s, 1, Temp - 1));
52 | Delete(s, 1, Temp);
53 | Temp := Pos(':', s);
54 | Minute := StrToInt(Copy(s, 1, Temp - 1));
55 | Delete(s, 1, Temp);
56 | Temp := Pos('.', s);
57 | if Temp > 0 then
58 | begin
59 | MSec := StrToInt(Copy(s, Temp + 1, Length(s) - Temp));
60 | Delete(s, Temp, Length(s) - Temp + 1);
61 | end
62 | else
63 | MSec := 0;
64 | Second := StrToInt(s);
65 | Result := EncodeTime(Hour, Minute, Second, MSec);
66 | end;
67 | end;
68 |
69 | var
70 | Day, Month, Year: Word;
71 | Temp: Integer;
72 | DateStr, TimeStr: string;
73 | begin
74 | // check for a value (At all)
75 | if Value = '' then
76 | Exit(0);
77 |
78 | Temp := Pos ('T', Value);
79 | // detect all known date/time formats
80 | if (Temp = 0) and (Pos('-', Value) > 0) then
81 | Temp := Length(Value) + 1;
82 | DateStr := Trim(Copy(Value, 1, Temp - 1));
83 | TimeStr := Trim(Copy(Value, Temp + 1, Length(Value) - Temp));
84 | Result := 0;
85 | if DateStr <> '' then
86 | begin
87 | Temp := Pos ('-', DateStr);
88 | Year := StrToInt(Copy(DateStr, 1, Temp - 1));
89 | Delete(DateStr, 1, Temp);
90 | Temp := Pos ('-', DateStr);
91 | Month := StrToInt(Copy(DateStr, 1, Temp - 1));
92 | Day := StrToInt(Copy(DateStr, Temp + 1, Length(DateStr) - Temp));
93 | Result := EncodeDate(Year, Month, Day);
94 | end;
95 | Result := Result + Frac(Str2Time(TimeStr));
96 | end;
97 |
98 |
99 | { TJsonSerializer }
100 |
101 | class function TJsonSerializer.GetID: string;
102 | begin
103 | Result := '';
104 | end;
105 |
106 | procedure TJsonSerializer.LoadFromFile(const FileName: TFileName);
107 | var
108 | Root: TdwsJSONValue;
109 | begin
110 | // check if file exists
111 | if not FileExists(FileName) then
112 | raise Exception.CreateFmt('File %s does not exist!', [FileName]);
113 |
114 | // parse JSON file
115 | Root := TdwsJSONValue.ParseFile(FileName);
116 |
117 | // ensure the JSON file is an object
118 | if not (Root is TdwsJSONObject) then
119 | raise EJsonSerializer.Create('Object expected');
120 |
121 | try
122 | Read(TdwsJSONObject(Root));
123 | finally
124 | Root.Free;
125 | end;
126 | end;
127 |
128 | procedure TJsonSerializer.SaveToFile(const FileName: TFileName);
129 | var
130 | Root: TdwsJSONObject;
131 | begin
132 | Root := TdwsJSONObject.Create;
133 | Write(Root);
134 |
135 | SaveTextToUTF8File(FileName, Root.ToBeautifiedString);
136 | end;
137 |
138 | procedure TJsonSerializer.LoadFromString(const Text: string);
139 | var
140 | Root: TdwsJSONValue;
141 | begin
142 | Root := TdwsJSONValue.ParseString(Text);
143 |
144 | if not (Root is TdwsJSONObject) then
145 | raise EJsonSerializer.Create('Object expected');
146 |
147 | try
148 | Read(TdwsJSONObject(Root));
149 | finally
150 | Root.Free;
151 | end;
152 | end;
153 |
154 | function TJsonSerializer.SaveToString: string;
155 | var
156 | Root: TdwsJSONObject;
157 | begin
158 | Root := TdwsJSONObject.Create;
159 | Write(Root);
160 |
161 | Result := Root.ToBeautifiedString;
162 | end;
163 |
164 | procedure TJsonSerializer.Read(Root: TdwsJSONObject);
165 | begin
166 | // eventually check ID
167 | if GetID <> '' then
168 | if not (Root.Items['ID'].AsString = GetID) then
169 | raise EJsonSerializer.Create('ID mismatch');
170 | end;
171 |
172 | procedure TJsonSerializer.Write(Root: TdwsJSONObject);
173 | begin
174 | // eventually set ID
175 | if GetID <> '' then
176 | Root.AddValue('ID').AsString := GetID;
177 | end;
178 |
179 | end.
180 |
--------------------------------------------------------------------------------
/Packages/RX2/WebUpdateD.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {B84A8AED-6387-4DEF-9F94-0D9A5040ACB7}
4 | WebUpdateD.dpk
5 | True
6 | Debug
7 | 1
8 | Package
9 | None
10 | 18.2
11 | Win32
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | false
33 | false
34 | false
35 | false
36 | false
37 | 00400000
38 | true
39 | true
40 | WebUpdateD
41 | WebUpdate Non-Visual
42 | 250
43 | true
44 | true
45 | 1031
46 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
47 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
48 |
49 |
50 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
51 | true
52 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
53 | 1033
54 | WebUpdateR;$(DCC_UsePackage)
55 |
56 |
57 | RELEASE;$(DCC_Define)
58 | 0
59 | false
60 | 0
61 |
62 |
63 | DEBUG;$(DCC_Define)
64 | false
65 | true
66 |
67 |
68 |
69 | MainSource
70 |
71 |
72 |
73 |
74 |
75 |
76 | Cfg_2
77 | Base
78 |
79 |
80 | Base
81 |
82 |
83 | Cfg_1
84 | Base
85 |
86 |
87 |
88 | Delphi.Personality.12
89 | Package
90 |
91 |
92 |
93 | WebUpdateD.dpk
94 |
95 |
96 |
97 | False
98 | False
99 | False
100 | False
101 | False
102 | True
103 |
104 |
105 | 12
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/Packages/RX2/WebUpdateR.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {AF3F4B4E-F9D1-4108-987F-28BCAEB0F0C6}
4 | WebUpdateR.dpk
5 | True
6 | Debug
7 | 1
8 | Package
9 | VCL
10 | 18.2
11 | Win32
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | false
33 | false
34 | false
35 | false
36 | false
37 | 00400000
38 | true
39 | true
40 | WebUpdateR
41 | 250
42 | true
43 | true
44 | Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
45 | 1031
46 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
47 |
48 |
49 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
50 | true
51 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
52 | 1033
53 |
54 |
55 | RELEASE;$(DCC_Define)
56 | 0
57 | false
58 | 0
59 |
60 |
61 | DEBUG;$(DCC_Define)
62 | false
63 | true
64 |
65 |
66 |
67 | MainSource
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | Cfg_2
83 | Base
84 |
85 |
86 | Base
87 |
88 |
89 | Cfg_1
90 | Base
91 |
92 |
93 |
94 | Delphi.Personality.12
95 | Package
96 |
97 |
98 |
99 | WebUpdateR.dpk
100 |
101 |
102 |
103 | False
104 | False
105 | False
106 | True
107 |
108 |
109 | 12
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/Source/Authoring Tool/WebUpdate.GUI.Options.dfm:
--------------------------------------------------------------------------------
1 | object FormOptions: TFormOptions
2 | Left = 0
3 | Top = 0
4 | BorderStyle = bsDialog
5 | Caption = 'Options'
6 | ClientHeight = 305
7 | ClientWidth = 525
8 | Color = clBtnFace
9 | Font.Charset = DEFAULT_CHARSET
10 | Font.Color = clWindowText
11 | Font.Height = -11
12 | Font.Name = 'Tahoma'
13 | Font.Style = []
14 | OldCreateOrder = False
15 | Position = poMainFormCenter
16 | OnCreate = FormCreate
17 | PixelsPerInch = 96
18 | TextHeight = 13
19 | object PageControl: TPageControl
20 | Left = 208
21 | Top = 0
22 | Width = 317
23 | Height = 272
24 | ActivePage = TabSheetMain
25 | Align = alClient
26 | Style = tsButtons
27 | TabOrder = 0
28 | object TabSheetMain: TTabSheet
29 | Caption = 'Main'
30 | TabVisible = False
31 | DesignSize = (
32 | 309
33 | 262)
34 | object LabelFileName: TLabel
35 | Left = 3
36 | Top = 11
37 | Width = 74
38 | Height = 13
39 | Caption = 'Base Directory:'
40 | end
41 | object LabelChannelFileName: TLabel
42 | Left = 3
43 | Top = 59
44 | Width = 88
45 | Height = 13
46 | Caption = 'Channel Filename:'
47 | end
48 | object EditChannelFileName: TJvFilenameEdit
49 | Left = 3
50 | Top = 75
51 | Width = 303
52 | Height = 21
53 | OnAfterDialog = EditChannelFileNameAfterDialog
54 | Filter = 'JSON files (*.json)|*.json'
55 | Anchors = [akLeft, akTop, akRight]
56 | TabOrder = 0
57 | end
58 | object EditBaseDirectory: TJvDirectoryEdit
59 | Left = 3
60 | Top = 27
61 | Width = 303
62 | Height = 21
63 | DialogKind = dkWin32
64 | Anchors = [akLeft, akTop, akRight]
65 | TabOrder = 1
66 | end
67 | object CheckBoxMD5: TCheckBox
68 | Left = 3
69 | Top = 112
70 | Width = 118
71 | Height = 17
72 | Caption = 'Use MD5 Checksums'
73 | TabOrder = 2
74 | end
75 | end
76 | object TabSheetFTP: TTabSheet
77 | Caption = 'Copy / Upload'
78 | ImageIndex = 1
79 | TabVisible = False
80 | object CheckBoxAutoCopyUpload: TCheckBox
81 | Left = 0
82 | Top = 0
83 | Width = 309
84 | Height = 22
85 | Align = alTop
86 | Caption = 'Automatically Copy/Upload on Snapshot'
87 | TabOrder = 0
88 | end
89 | object GroupBoxFTP: TGroupBox
90 | AlignWithMargins = True
91 | Left = 3
92 | Top = 82
93 | Width = 303
94 | Height = 169
95 | Align = alTop
96 | Caption = 'FTP'
97 | TabOrder = 1
98 | DesignSize = (
99 | 303
100 | 169)
101 | object LabelPassword: TLabel
102 | Left = 11
103 | Top = 115
104 | Width = 50
105 | Height = 13
106 | Caption = 'Password:'
107 | end
108 | object LabelUsername: TLabel
109 | Left = 11
110 | Top = 67
111 | Width = 52
112 | Height = 13
113 | Caption = 'Username:'
114 | end
115 | object LabelServer: TLabel
116 | Left = 11
117 | Top = 19
118 | Width = 36
119 | Height = 13
120 | Caption = 'Server:'
121 | end
122 | object EditFtpPassword: TEdit
123 | Left = 11
124 | Top = 131
125 | Width = 282
126 | Height = 21
127 | Anchors = [akLeft, akTop, akRight]
128 | TabOrder = 0
129 | end
130 | object EditFtpUsername: TEdit
131 | Left = 11
132 | Top = 83
133 | Width = 282
134 | Height = 21
135 | Anchors = [akLeft, akTop, akRight]
136 | TabOrder = 1
137 | end
138 | object EditFtpServer: TEdit
139 | Left = 11
140 | Top = 35
141 | Width = 282
142 | Height = 21
143 | Anchors = [akLeft, akTop, akRight]
144 | TabOrder = 2
145 | end
146 | end
147 | object GroupBoxCopy: TGroupBox
148 | AlignWithMargins = True
149 | Left = 3
150 | Top = 25
151 | Width = 303
152 | Height = 51
153 | Align = alTop
154 | Caption = 'Copy'
155 | TabOrder = 2
156 | DesignSize = (
157 | 303
158 | 51)
159 | object CheckBoxCopyTo: TCheckBox
160 | Left = 11
161 | Top = 18
162 | Width = 63
163 | Height = 23
164 | Caption = 'Copy to:'
165 | TabOrder = 0
166 | end
167 | object EditCopyPath: TEdit
168 | Left = 80
169 | Top = 19
170 | Width = 213
171 | Height = 21
172 | Anchors = [akLeft, akTop, akRight]
173 | TabOrder = 1
174 | end
175 | end
176 | end
177 | end
178 | object TreeOptions: TVirtualStringTree
179 | AlignWithMargins = True
180 | Left = 4
181 | Top = 4
182 | Width = 200
183 | Height = 264
184 | Margins.Left = 4
185 | Margins.Top = 4
186 | Margins.Right = 4
187 | Margins.Bottom = 4
188 | Align = alLeft
189 | Header.AutoSizeIndex = 0
190 | Header.Font.Charset = DEFAULT_CHARSET
191 | Header.Font.Color = clWindowText
192 | Header.Font.Height = -11
193 | Header.Font.Name = 'Tahoma'
194 | Header.Font.Style = []
195 | Header.MainColumn = -1
196 | TabOrder = 1
197 | OnChange = TreeOptionsChange
198 | OnGetText = TreeOptionsGetText
199 | Columns = <>
200 | end
201 | object Panel: TPanel
202 | Left = 0
203 | Top = 272
204 | Width = 525
205 | Height = 33
206 | Align = alBottom
207 | BevelOuter = bvNone
208 | TabOrder = 2
209 | object ButtonOK: TButton
210 | AlignWithMargins = True
211 | Left = 363
212 | Top = 4
213 | Width = 75
214 | Height = 25
215 | Margins.Left = 4
216 | Margins.Top = 4
217 | Margins.Right = 4
218 | Margins.Bottom = 4
219 | Align = alRight
220 | Caption = '&OK'
221 | Default = True
222 | ModalResult = 1
223 | TabOrder = 0
224 | end
225 | object ButtonCancel: TButton
226 | AlignWithMargins = True
227 | Left = 446
228 | Top = 4
229 | Width = 75
230 | Height = 25
231 | Margins.Left = 4
232 | Margins.Top = 4
233 | Margins.Right = 4
234 | Margins.Bottom = 4
235 | Align = alRight
236 | Caption = '&Cancel'
237 | ModalResult = 2
238 | TabOrder = 1
239 | end
240 | end
241 | end
242 |
--------------------------------------------------------------------------------
/Source/Common/WebUpdate.JSON.Channel.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.JSON.Channel;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, System.Types, System.Generics.Collections, dwsJSON,
7 | WebUpdate.JSON.Serializer;
8 |
9 | type
10 | TWebUpdateFileAction = (iaAdd, iaDelete);
11 |
12 | TWebUpdateFileItem = class
13 | private
14 | FFileName: TFileName;
15 | FFileSize: Integer;
16 | FModified: TDateTime;
17 | FMD5Hash: string;
18 | FAction: TWebUpdateFileAction;
19 | public
20 | constructor Create;
21 |
22 | property Action: TWebUpdateFileAction read FAction write FAction;
23 | property FileName: TFileName read FFileName write FFileName;
24 | property FileSize: Integer read FFileSize write FFileSize;
25 | property Modified: TDateTime read FModified write FModified;
26 | property MD5Hash: string read FMD5Hash write FMD5Hash;
27 | end;
28 | TWebUpdateFileItems = TObjectList;
29 |
30 | TWebUpdateChannelSetup = class(TJsonSerializer)
31 | private
32 | FItems: TWebUpdateFileItems;
33 | FModified: TDateTime;
34 | FChannelName: string;
35 | FAppName: TFileName;
36 | FPreUpdateScript: string;
37 | FPostUpdateScript: string;
38 | protected
39 | procedure Read(Root: TdwsJSONObject); override;
40 | procedure Write(Root: TdwsJSONObject); override;
41 | public
42 | constructor Create;
43 | destructor Destroy; override;
44 | class function GetID: string; override;
45 |
46 | property Modified: TDateTime read FModified write FModified;
47 | property Items: TWebUpdateFileItems read FItems;
48 | property AppName: TFileName read FAppName write FAppName;
49 | property PreUpdateScript: string read FPreUpdateScript write FPreUpdateScript;
50 | property PostUpdateScript: string read FPostUpdateScript write FPostUpdateScript;
51 | property ChannelName: string read FChannelName write FChannelName;
52 | end;
53 |
54 | implementation
55 |
56 | uses
57 | System.StrUtils;
58 |
59 | { TWebUpdateFileItem }
60 |
61 | constructor TWebUpdateFileItem.Create;
62 | begin
63 | FFileName := '';
64 | FFileSize := 0;
65 | FModified := 0;
66 | FMD5Hash := '';
67 | FAction := iaAdd;
68 | end;
69 |
70 |
71 | { TWebUpdateChannelSetup }
72 |
73 | constructor TWebUpdateChannelSetup.Create;
74 | begin
75 | inherited;
76 | FItems := TWebUpdateFileItems.Create;
77 | FAppName := '';
78 | FModified := 0;
79 | end;
80 |
81 | destructor TWebUpdateChannelSetup.Destroy;
82 | begin
83 | FItems.Free;
84 | inherited;
85 | end;
86 |
87 | class function TWebUpdateChannelSetup.GetID: string;
88 | begin
89 | Result := 'Channel';
90 | end;
91 |
92 | procedure TWebUpdateChannelSetup.Read(Root: TdwsJSONObject);
93 | var
94 | Value: TdwsJSONValue;
95 | FileValue: TdwsJSONObject;
96 | Files: TdwsJSONArray;
97 | Index: Integer;
98 | Item: TWebUpdateFileItem;
99 | begin
100 | inherited;
101 |
102 | // get channel name
103 | Value := Root.Items['Name'];
104 | if Assigned(Value) then
105 | FChannelName := Value.AsString;
106 |
107 | // get modification date
108 | Value := Root.Items['Modified'];
109 | if Assigned(Value) then
110 | FModified := ISO8601ToDateTime(Value.AsString);
111 |
112 | // get pre-build script
113 | Value := Root.Items['PreUpdateScript'];
114 | if Assigned(Value) then
115 | FPreUpdateScript := Value.AsString;
116 |
117 | // get files
118 | Value := Root.Items['Files'];
119 | if not (Value is TdwsJSONArray) then
120 | raise Exception.Create('Array expected!');
121 |
122 | // clear existing items
123 | FItems.Clear;
124 |
125 | Files := TdwsJSONArray(Value);
126 | for Index := 0 to Files.ElementCount - 1 do
127 | begin
128 | Value := Files.Elements[Index];
129 | if not (Value is TdwsJSONObject) then
130 | raise Exception.Create('Object expected!');
131 |
132 | // get file item
133 | FileValue := TdwsJSONObject(Value);
134 | Item := TWebUpdateFileItem.Create;
135 |
136 | // get file name
137 | Value := FileValue.Items['FileName'];
138 | if not Assigned(Value) then
139 | raise Exception.Create('FileName not specified!');
140 | Item.FileName := Value.AsString;
141 |
142 | // get file size
143 | Value := FileValue.Items['Size'];
144 | if Assigned(Value) then
145 | Item.FileSize := Value.AsInteger;
146 |
147 | // get modification date/time
148 | Value := FileValue.Items['Modified'];
149 | if Assigned(Value) then
150 | Item.Modified := ISO8601ToDateTime(Value.AsString);
151 |
152 | // get MD5 hash
153 | Value := FileValue.Items['MD5'];
154 | if Assigned(Value) then
155 | Item.MD5Hash := Value.AsString;
156 |
157 | // get action
158 | Value := FileValue.Items['Action'];
159 | if Assigned(Value) then
160 | if SameText(Value.AsString, 'delete') then
161 | Item.Action := iaDelete
162 | else if SameText(Value.AsString, 'add') then
163 | Item.Action := iaAdd
164 | else
165 | raise Exception.Create('Unknown action');
166 |
167 | // add item to file items
168 | FItems.Add(Item);
169 | end;
170 |
171 | // get post-build script
172 | Value := Root.Items['PostUpdateScript'];
173 | if Assigned(Value) then
174 | FPostUpdateScript := Value.AsString;
175 |
176 | // get application name
177 | Value := Root.Items['AppName'];
178 | if Assigned(Value) then
179 | FAppName := Value.AsString;
180 | end;
181 |
182 | procedure TWebUpdateChannelSetup.Write(Root: TdwsJSONObject);
183 | var
184 | Files: TdwsJSONArray;
185 | FileValue: TdwsJSONObject;
186 | Item: TWebUpdateFileItem;
187 | begin
188 | inherited;
189 |
190 | // write modification data
191 | Root.AddValue('Modified').AsString := DateTimeToISO8601(FModified);
192 |
193 | // eventually write channel name (if present)
194 | if FChannelName <> '' then
195 | Root.AddValue('Name').AsString := FChannelName;
196 |
197 | // get pre-build script
198 | if FPreUpdateScript <> '' then
199 | Root.AddValue('PreUpdateScript').AsString := FPreUpdateScript;
200 |
201 | // create files array
202 | Files := Root.AddArray('Files');
203 |
204 | for Item in FItems do
205 | begin
206 | FileValue := Files.AddObject;
207 | FileValue.AddValue('FileName').AsString := Item.FileName;
208 |
209 | // eventually store file size
210 | if Item.FileSize <> 0 then
211 | FileValue.AddValue('Size').AsInteger := Item.FileSize;
212 |
213 | // eventually store file modification time stamp
214 | if Item.Modified <> 0 then
215 | FileValue.AddValue('Modified').AsString := DateTimeToISO8601(Item.Modified);
216 |
217 | // eventually store MD5 hash
218 | if Item.MD5Hash <> '' then
219 | FileValue.AddValue('MD5').AsString := Item.MD5Hash;
220 |
221 | // eventually store action (default is 'add')
222 | case Item.Action of
223 | iaDelete:
224 | FileValue.AddValue('Action').AsString := 'Delete';
225 | end;
226 | end;
227 |
228 | // get post-build script
229 | if FPostUpdateScript <> '' then
230 | Root.AddValue('PostUpdateScript').AsString := FPostUpdateScript;
231 |
232 | // write app name
233 | if FAppName <> '' then
234 | Root.AddValue('AppName').AsString := FAppName;
235 | end;
236 |
237 | end.
238 |
--------------------------------------------------------------------------------
/Source/Common/WebUpdate.Classes.WebUpdate.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.Classes.WebUpdate;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, System.Classes, WebUpdate.JSON.Channels,
7 | WebUpdate.JSON.Channel;
8 |
9 | type
10 | TWebUpdate = class
11 | private
12 | FAutoGet: Boolean;
13 | FBaseURL: string;
14 | FChannelName: string;
15 | FChannels: TWebUpdateChannels;
16 | FChannelsFile: TFileName;
17 | FDownloadUpdater: Boolean;
18 | FLastModified: TDateTime;
19 | FLocalFileName: TFileName;
20 | FUpdaterFileName: TFileName;
21 | procedure SetChannelName(const Value: string);
22 | public
23 | constructor Create; overload;
24 | constructor Create(BaseURL: string; ChannelsFileName: TFileName = ''); overload;
25 | destructor Destroy; override;
26 |
27 | function CheckForUpdate: Boolean;
28 | procedure GetLocalChannelInformation;
29 | procedure GetChannelsInformationFromServer;
30 | procedure GetChannels(Channels: TStrings);
31 | procedure PerformUpdate;
32 | procedure PerformDownloadUpdater;
33 |
34 | property AutoGetLocalChannelInformation: Boolean read FAutoGet write FAutoGet;
35 | property BaseURL: string read FBaseURL write FBaseURL;
36 | property ChannelName: string read FChannelName write SetChannelName;
37 | property ChannelsFileName: TFileName read FChannelsFile write FChannelsFile;
38 | property LocalChannelFileName: TFileName read FLocalFileName write FLocalFileName;
39 | property LastModified: TDateTime read FLastModified;
40 | property DownloadUpdater: Boolean read FDownloadUpdater write FDownloadUpdater;
41 | property UpdaterFileName: TFileName read FUpdaterFileName write FUpdaterFileName;
42 | end;
43 |
44 | implementation
45 |
46 | uses
47 | System.StrUtils, WinApi.ShellApi, WinApi.Windows, Vcl.Forms,
48 | IdSSLOpenSSL, IdHTTP;
49 |
50 | { TWebUpdate }
51 |
52 | constructor TWebUpdate.Create;
53 | begin
54 | FAutoGet := False;
55 | FBaseURL := '';
56 | FChannelsFile := 'Channels.json';
57 | FChannelName := 'Stable';
58 | FChannels := TWebUpdateChannels.Create;
59 | FLocalFileName := 'WebUpdate.json';
60 | FUpdaterFileName := 'UpdaterWizard.exe';
61 | end;
62 |
63 | constructor TWebUpdate.Create(BaseURL: string; ChannelsFileName: TFileName = '');
64 | begin
65 | Create;
66 | FBaseURL := BaseURL;
67 | if ChannelsFileName <> '' then
68 | FChannelsFile := ChannelsFileName;
69 | end;
70 |
71 | destructor TWebUpdate.Destroy;
72 | begin
73 | FChannels.Free;
74 | inherited;
75 | end;
76 |
77 | procedure TWebUpdate.PerformDownloadUpdater;
78 | var
79 | Http: TIdHTTP;
80 | Text: string;
81 | Success: Boolean;
82 | begin
83 | // get channels file (JSON) text
84 | if StartsText('http://', FBaseURL) or StartsText('https://', FBaseURL) then
85 | begin
86 | Http := TIdHTTP.Create(nil);
87 | try
88 | // eventually create SSL IO handler
89 | if FileExists(ExtractFilePath(ParamStr(0)) + 'ssleay32.dll') and
90 | FileExists(ExtractFilePath(ParamStr(0)) + 'libeay32.dll') then
91 | Http.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
92 |
93 | try
94 | // get text from URI
95 | Text := Http.Get(FBaseURL + FUpdaterFileName);
96 |
97 | // check if text is available (might need check for JSON format)
98 | Success := Text <> '';
99 | except
100 | Success := False;
101 | end;
102 |
103 | // ignore errors here!
104 | if not Success then
105 | Exit;
106 | finally
107 | Http.IOHandler.Free;
108 | Http.Free;
109 | end;
110 | end
111 | else
112 | raise Exception.Create('Protocol not supported');
113 | end;
114 |
115 | procedure TWebUpdate.GetChannelsInformationFromServer;
116 | var
117 | Http: TIdHTTP;
118 | Text: string;
119 | Success: Boolean;
120 | begin
121 | // get channels file (JSON) text
122 | if StartsText('http://', FBaseURL) or StartsText('https://', FBaseURL) then
123 | begin
124 | Http := TIdHTTP.Create(nil);
125 | try
126 | // eventually create SSL IO handler
127 | if FileExists(ExtractFilePath(ParamStr(0)) + 'ssleay32.dll') and
128 | FileExists(ExtractFilePath(ParamStr(0)) + 'libeay32.dll') then
129 | Http.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
130 |
131 | try
132 | // get text from URI
133 | Text := Http.Get(FBaseURL + FChannelsFile);
134 |
135 | // check if text is available (might need check for JSON format)
136 | Success := Text <> '';
137 | except
138 | Success := False;
139 | end;
140 |
141 | // ignore errors here!
142 | if not Success then
143 | Exit;
144 | finally
145 | Http.IOHandler.Free;
146 | Http.Free;
147 | end;
148 | end
149 | else
150 | raise Exception.Create('Protocol not supported');
151 |
152 | FChannels.LoadFromString(Text);
153 | end;
154 |
155 | procedure TWebUpdate.GetChannels(Channels: TStrings);
156 | var
157 | Item: TWebUpdateChannelItem;
158 | begin
159 | // first get channels information from server
160 | GetChannelsInformationFromServer;
161 |
162 | Channels.Clear;
163 | for Item in FChannels.Items do
164 | Channels.Add(Item.Name)
165 | end;
166 |
167 | procedure TWebUpdate.GetLocalChannelInformation;
168 | var
169 | FullLocalFileName: TFileName;
170 | LocalSetup: TWebUpdateChannelSetup;
171 | begin
172 | FullLocalFileName := FLocalFileName;
173 | if IsRelativePath(FullLocalFileName) then
174 | FullLocalFileName := ExtractFilePath(ParamStr(0)) + FullLocalFileName;
175 |
176 | LocalSetup := TWebUpdateChannelSetup.Create;
177 | try
178 | LocalSetup.LoadFromFile(FullLocalFileName);
179 |
180 | FChannelName := LocalSetup.ChannelName;
181 | FLastModified := LocalSetup.Modified;
182 | finally
183 | LocalSetup.Free;
184 | end;
185 | end;
186 |
187 | function TWebUpdate.CheckForUpdate: Boolean;
188 | var
189 | ChannelItem: TWebUpdateChannelItem;
190 | begin
191 | Result := False;
192 |
193 | // eventually get information about local channel
194 | if FAutoGet then
195 | GetLocalChannelInformation;
196 |
197 | // locate local channel
198 | for ChannelItem in FChannels.Items do
199 | if ChannelItem.Name = FChannelName then
200 | if ChannelItem.Modified > FLastModified then
201 | Exit(True);
202 | end;
203 |
204 | procedure TWebUpdate.PerformUpdate;
205 | var
206 | LocalPath: string;
207 | Parameters: string;
208 | begin
209 | // eventually download updater
210 | if FDownloadUpdater then
211 | PerformDownloadUpdater;
212 |
213 | LocalPath := ExtractFilePath(ParamStr(0));
214 | if FileExists(LocalPath + FUpdaterFileName) then
215 | begin
216 | Parameters := Format('-u="%s" -d=%d -c="%s" -l="%s"', [BaseURL, 1000,
217 | ChannelName, ExtractRelativePath(LocalPath, FLocalFileName)]);
218 | ShellExecute(Application.Handle, 'open', PChar(LocalPath + FUpdaterFileName),
219 | PChar(Parameters), PChar(LocalPath), SW_SHOW);
220 | Application.Terminate;
221 | end;
222 | end;
223 |
224 | procedure TWebUpdate.SetChannelName(const Value: string);
225 | begin
226 | if FChannelName <> Value then
227 | begin
228 | FChannelName := Value;
229 | FLastModified := 0;
230 | end;
231 | end;
232 |
233 | end.
234 |
--------------------------------------------------------------------------------
/Source/Update Helper (Command-line)/Updater.dpr:
--------------------------------------------------------------------------------
1 | program Updater;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | System.SysUtils,
9 | System.Classes,
10 | System.StrUtils,
11 | {$IFDEF MSWINDOWS}
12 | WinApi.Windows,
13 | WinApi.TlHelp32,
14 | {$ENDIF}
15 | WebUpdate.Classes.Updater in '..\Common\WebUpdate.Classes.Updater.pas',
16 | WebUpdate.JSON.Serializer in '..\Common\WebUpdate.JSON.Serializer.pas',
17 | WebUpdate.JSON.Channel in '..\Common\WebUpdate.JSON.Channel.pas',
18 | WebUpdate.JSON.Channels in '..\Common\WebUpdate.JSON.Channels.pas',
19 | WebUpdate.Tools in '..\Common\WebUpdate.Tools.pas';
20 |
21 | resourcestring
22 | RStrMD5MismatchUpdate = 'Error: MD5 mismatch, update might be corrupt!';
23 | RStrUnknownOption = 'Error: Unknown option: %s!';
24 | RStrUnknownCommand = 'Error: Unknown command: %s';
25 | RStrChannelDefinitionError = 'Error: Could not load channel definition!';
26 | RStrSetupLoadError = 'Error: Could not load setup!';
27 | RStrNoURLSpecified = 'Error: No URL specified!';
28 |
29 | var
30 | Delay: Integer;
31 | WebUpdater: TWebUpdater;
32 | MainAppExecutable: string;
33 | MainAppWindowCaption: string;
34 |
35 | {$IFDEF MSWINDOWS}
36 | procedure KillProcess(ProcessID: Integer);
37 | var
38 | ProcessHandle: THandle;
39 | ExitCode: Integer;
40 | begin
41 | // get process handle
42 | ProcessHandle := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION
43 | or PROCESS_VM_WRITE or PROCESS_VM_READ or PROCESS_TERMINATE, False,
44 | ProcessID);
45 |
46 | // eventually close process
47 | if (ProcessHandle > 0) then
48 | try
49 | ExitCode := 0;
50 | GetExitCodeProcess(ProcessHandle, DWORD(ExitCode));
51 | TerminateProcess(ProcessHandle, ExitCode);
52 | finally
53 | CloseHandle(ProcessHandle);
54 | end;
55 | end;
56 |
57 | function GetProcessIDForExecutable(ExecutableFileName: string): Cardinal;
58 | var
59 | ContinueLoop: Boolean;
60 | SnapshotHandle: THandle;
61 | ProcessEntry32: TProcessEntry32;
62 | Found: Boolean;
63 | begin
64 | // initialization
65 | ProcessEntry32.dwSize := SizeOf(TProcessEntry32);
66 | Found := False;
67 |
68 | // get snapshot
69 | SnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
70 | if SnapshotHandle > 0 then
71 | try
72 | ContinueLoop := Process32First(SnapshotHandle, ProcessEntry32);
73 | while Integer(ContinueLoop) <> 0 do
74 | begin
75 | if SameText(ExtractFileName(ProcessEntry32.szExeFile), ExecutableFileName) then
76 | begin
77 | Found := True;
78 | Break;
79 | end;
80 | ContinueLoop := Process32Next(SnapshotHandle, ProcessEntry32);
81 | end;
82 | if not Found then
83 | Exit(0);
84 | finally
85 | CloseHandle(SnapshotHandle);
86 | end;
87 |
88 | Result := ProcessEntry32.th32ProcessID;
89 | end;
90 |
91 | function GetProcessIDForWindow(Caption: string): Cardinal;
92 | var
93 | WinHwnd: HWND;
94 | begin
95 | Result := 0;
96 |
97 | // check for opened main application
98 | WinHwnd := FindWindow(nil, PWideChar(Caption));
99 | if not (IsWindow(WinHwnd)) then
100 | Exit;
101 |
102 | // get process ID
103 | GetWindowThreadProcessID(WinHwnd, @Result);
104 | end;
105 |
106 | procedure CloseMainApplication;
107 | var
108 | ProcessID: Integer;
109 | Counter: Integer;
110 | begin
111 | Counter := 0;
112 | repeat
113 | ProcessID := 0;
114 | if MainAppExecutable <> '' then
115 | ProcessID := GetProcessIDForExecutable(MainAppExecutable)
116 | else if MainAppWindowCaption <> '' then
117 | ProcessID := GetProcessIDForWindow(MainAppWindowCaption);
118 |
119 | // check if process has been found
120 | if ProcessID = 0 then
121 | Exit;
122 |
123 | Sleep(1 + Delay);
124 | Inc(Counter);
125 | until Counter >= 10;
126 |
127 | KillProcess(ProcessID);
128 | end;
129 | {$ENDIF}
130 |
131 | procedure WriteUsage;
132 | begin
133 | WriteLn('Syntax: Updater.exe [-options]');
134 | WriteLn('');
135 | WriteLn('Options:');
136 | WriteLn('--------');
137 | WriteLn('');
138 | WriteLn(' -u=URL (Base URL for JSON files)');
139 | WriteLn(' -c=Channel (Update Channel, default is ''Stable'')');
140 | WriteLn(' -f=FileName (Channels) (Filename of channels definition file)');
141 | WriteLn(' -d=Delay (Integer) (Time in milliseconds before updating starts)');
142 | WriteLn(' -l=FileName (Local filename of current setup)');
143 | WriteLn(' -e=ExeFileName (Name of main application executable)');
144 | WriteLn(' -w=WindowCaption (Caption of main application window)');
145 | WriteLn('');
146 | WriteLn('Example:');
147 | WriteLn('--------');
148 | WriteLn('');
149 | WriteLn(' Updater.exe -c=Nightly');
150 | WriteLn('');
151 | end;
152 |
153 | procedure ScanParameters;
154 | var
155 | Index: Integer;
156 | Text: string;
157 | EqPos: Integer;
158 | begin
159 | Delay := 99;
160 | for Index := 1 to ParamCount do
161 | begin
162 | Text := ParamStr(Index);
163 | if Text[1] = '-' then
164 | begin
165 | // remove options identifier and get colon pos
166 | Delete(Text, 1, 1);
167 | EqPos := Pos('=', Text);
168 |
169 | if StartsText('u=', Text) then
170 | WebUpdater.BaseURL := Copy(Text, EqPos, Length(Text) - EqPos)
171 | else if StartsText('f=', Text) then
172 | WebUpdater.ChannelsFileName := Copy(Text, EqPos, Length(Text) - EqPos)
173 | else if StartsText('c=', Text) then
174 | WebUpdater.ChannelName := Copy(Text, EqPos, Length(Text) - EqPos)
175 | else if StartsText('d=', Text) then
176 | Delay := StrToInt(Copy(Text, EqPos, Length(Text) - EqPos))
177 | else if StartsText('l=', Text) then
178 | WebUpdater.LocalChannelFileName := Copy(Text, EqPos, Length(Text) - EqPos)
179 | {$IFDEF MSWINDOWS}
180 | else if StartsText('e=', Text) then
181 | MainAppExecutable := Copy(Text, EqPos, Length(Text) - EqPos)
182 | else if StartsText('w=', Text) then
183 | MainAppWindowCaption := Copy(Text, EqPos, Length(Text) - EqPos)
184 | {$ENDIF}
185 | else
186 | begin
187 | WriteLn(Format(RStrUnknownOption, [Text]));
188 | WriteLn('');
189 | WriteUsage;
190 | Halt(100);
191 | end;
192 | end
193 | else
194 | WriteLn(Format(RStrUnknownCommand, [Text]));
195 | WriteLn('');
196 | WriteUsage;
197 | Halt(101);
198 | end;
199 |
200 | if WebUpdater.BaseURL = '' then
201 | begin
202 | WriteLn(RStrNoURLSpecified);
203 | WriteLn('');
204 | WriteUsage;
205 | Halt(102);
206 | end;
207 |
208 | if WebUpdater.ChannelsFileName = '' then
209 | begin
210 | WriteLn('Error: No file name for channels definition specified!');
211 | WriteLn('');
212 | WriteUsage;
213 | Halt(103);
214 | end;
215 | end;
216 |
217 | begin
218 | try
219 | WebUpdater := TWebUpdater.Create;
220 | try
221 | ScanParameters;
222 |
223 | // give main application some time to close
224 | Sleep(1 + Delay);
225 |
226 | {$IFDEF MSWINDOWS}
227 | // close main application
228 | CloseMainApplication;
229 | {$ENDIF}
230 |
231 | // perform web update
232 | WebUpdater.PerformWebUpdate;
233 | finally
234 | WebUpdater.Free;
235 | end;
236 | except
237 | on E: Exception do
238 | Writeln(E.ClassName, ': ', E.Message);
239 | end;
240 | end.
241 |
--------------------------------------------------------------------------------
/Source/Common/WebUpdate.JSON.Project.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.JSON.Project;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, dwsJSON, WebUpdate.JSON.Serializer;
7 |
8 | type
9 | TWebUpdateProject = class(TJsonSerializer)
10 | type
11 | TFTPOptions = class(TJsonSerializer)
12 | private
13 | FPassword: string;
14 | FUsername: string;
15 | FServer: string;
16 | protected
17 | procedure Read(Root: TdwsJSONObject); override;
18 | procedure Write(Root: TdwsJSONObject); override;
19 | public
20 | constructor Create;
21 |
22 | property Server: string read FServer write FServer;
23 | property Username: string read FUsername write FUsername;
24 | property Password: string read FPassword write FPassword;
25 | end;
26 |
27 | TCopyOptions = class(TJsonSerializer)
28 | private
29 | FPath: string;
30 | FEnabled: Boolean;
31 | protected
32 | procedure Read(Root: TdwsJSONObject); override;
33 | procedure Write(Root: TdwsJSONObject); override;
34 | public
35 | constructor Create;
36 |
37 | property Path: string read FPath write FPath;
38 | property Enabled: Boolean read FEnabled write FEnabled;
39 | end;
40 |
41 | private
42 | FApplicationName: string;
43 | FAutoCopyUpload: Boolean;
44 | FBaseDirectory: string;
45 | FChannelsFilename: TFileName;
46 | FCopyOptions: TCopyOptions;
47 | FCurrentChannel: string;
48 | FFtpOptions: TFTPOptions;
49 | FUseMD5: Boolean;
50 | function GetFullChannelsFilename: TFileName;
51 | function GetBasePath: string;
52 | function GetChannelsPath: string;
53 | protected
54 | procedure Read(Root: TdwsJSONObject); override;
55 | procedure Write(Root: TdwsJSONObject); override;
56 | public
57 | constructor Create;
58 | destructor Destroy; override;
59 |
60 | class function GetID: string; override;
61 |
62 | property AutoCopyUpload: Boolean read FAutoCopyUpload write FAutoCopyUpload;
63 | property ApplicationName: string read FApplicationName write FApplicationName;
64 | property BaseDirectory: string read FBaseDirectory write FBaseDirectory;
65 | property BasePath: string read GetBasePath;
66 | property ChannelsFilename: TFileName read FChannelsFilename write FChannelsFilename;
67 | property ChannelsPath: string read GetChannelsPath;
68 | property Copy: TCopyOptions read FCopyOptions;
69 | property ChannelName: string read FCurrentChannel write FCurrentChannel;
70 | property FullChannelsFilename: TFileName read GetFullChannelsFilename;
71 | property FTP: TFTPOptions read FFtpOptions;
72 | property UseMD5: Boolean read FUseMD5 write FUseMD5;
73 | end;
74 |
75 | implementation
76 |
77 | { TWebUpdateProject.TFTPOptions }
78 |
79 | constructor TWebUpdateProject.TFTPOptions.Create;
80 | begin
81 | FServer := '';
82 | FUsername := '';
83 | FPassword := '';
84 | end;
85 |
86 | procedure TWebUpdateProject.TFTPOptions.Read(Root: TdwsJSONObject);
87 | var
88 | Value: TdwsJSONValue;
89 | begin
90 | inherited;
91 |
92 | Value := Root.Items['Server'];
93 | if Assigned(Value) then
94 | FServer := Value.AsString;
95 |
96 | Value := Root.Items['Username'];
97 | if Assigned(Value) then
98 | FUsername := Value.AsString;
99 |
100 | Value := Root.Items['Password'];
101 | if Assigned(Value) then
102 | FPassword := Value.AsString;
103 | end;
104 |
105 | procedure TWebUpdateProject.TFTPOptions.Write(Root: TdwsJSONObject);
106 | begin
107 | inherited;
108 |
109 | if FServer <> '' then
110 | Root.AddValue('Server').AsString := FServer;
111 |
112 | if FUsername <> '' then
113 | Root.AddValue('Username').AsString := FUsername;
114 |
115 | if FPassword <> '' then
116 | Root.AddValue('Password').AsString := FPassword;
117 | end;
118 |
119 |
120 | { TWebUpdateProject.TCopyOptions }
121 |
122 | constructor TWebUpdateProject.TCopyOptions.Create;
123 | begin
124 | FPath := '';
125 | FEnabled := False;
126 | end;
127 |
128 | procedure TWebUpdateProject.TCopyOptions.Read(Root: TdwsJSONObject);
129 | var
130 | Value: TdwsJSONValue;
131 | begin
132 | inherited;
133 |
134 | Value := Root.Items['Path'];
135 | if Assigned(Value) then
136 | FPath := Value.AsString;
137 |
138 | Value := Root.Items['Enabled'];
139 | if Assigned(Value) then
140 | FEnabled := Value.AsBoolean;
141 | end;
142 |
143 | procedure TWebUpdateProject.TCopyOptions.Write(Root: TdwsJSONObject);
144 | begin
145 | inherited;
146 |
147 | if FPath <> '' then
148 | Root.AddValue('Path').AsString := FPath;
149 |
150 | if FEnabled then
151 | Root.AddValue('Enabled').AsBoolean := FEnabled;
152 | end;
153 |
154 |
155 | { TWebUpdateProject }
156 |
157 | constructor TWebUpdateProject.Create;
158 | begin
159 | FFtpOptions := TFTPOptions.Create;
160 | FCopyOptions := TCopyOptions.Create;
161 | FCurrentChannel := 'Nightly';
162 | end;
163 |
164 | destructor TWebUpdateProject.Destroy;
165 | begin
166 | FCopyOptions.Free;
167 | FFtpOptions.Free;
168 | inherited;
169 | end;
170 |
171 | function TWebUpdateProject.GetBasePath: string;
172 | begin
173 | if FBaseDirectory = '' then
174 | Exit('');
175 |
176 | Result := IncludeTrailingPathDelimiter(FBaseDirectory)
177 | end;
178 |
179 | function TWebUpdateProject.GetChannelsPath: string;
180 | begin
181 | Result := ExtractFilePath(FChannelsFilename);
182 | end;
183 |
184 | function TWebUpdateProject.GetFullChannelsFilename: TFileName;
185 | begin
186 | if FChannelsFilename <> '' then
187 | if FBaseDirectory <> '' then
188 | Result := IncludeTrailingPathDelimiter(FBaseDirectory) + FChannelsFilename
189 | else
190 | Result := FChannelsFilename
191 | else
192 | Result := '';
193 | end;
194 |
195 | class function TWebUpdateProject.GetID: string;
196 | begin
197 | Result := 'Project';
198 | end;
199 |
200 | procedure TWebUpdateProject.Read(Root: TdwsJSONObject);
201 | var
202 | Value: TdwsJSONValue;
203 | begin
204 | inherited;
205 |
206 | Value := Root.Items['BaseDirectory'];
207 | if Assigned(Value) then
208 | FBaseDirectory := Value.AsString;
209 |
210 | Value := Root.Items['ChannelFilename'];
211 | if Assigned(Value) then
212 | FChannelsFilename := Value.AsString;
213 |
214 | Value := Root.Items['CurrentChannel'];
215 | if Assigned(Value) then
216 | FCurrentChannel := Value.AsString;
217 |
218 | Value := Root.Items['AutoCopyUpload'];
219 | if Assigned(Value) then
220 | FAutoCopyUpload := Value.AsBoolean;
221 |
222 | Value := Root.Items['ApplicationName'];
223 | if Assigned(Value) then
224 | FApplicationName := Value.AsString;
225 |
226 | Value := Root.Items['UseMD5'];
227 | if Assigned(Value) then
228 | FUseMD5 := Value.AsBoolean;
229 |
230 | Value := Root.Items['FTP'];
231 | if Value is TdwsJSONObject then
232 | FFtpOptions.Read(TdwsJSONObject(Value));
233 |
234 | Value := Root.Items['Copy'];
235 | if Value is TdwsJSONObject then
236 | FCopyOptions.Read(TdwsJSONObject(Value));
237 | end;
238 |
239 | procedure TWebUpdateProject.Write(Root: TdwsJSONObject);
240 | var
241 | ObjVal: TdwsJSONObject;
242 | begin
243 | inherited;
244 |
245 | if FBaseDirectory <> '' then
246 | Root.AddValue('BaseDirectory').AsString := FBaseDirectory;
247 |
248 | if FChannelsFilename <> '' then
249 | Root.AddValue('ChannelFilename').AsString := FChannelsFilename;
250 |
251 | if FCurrentChannel <> '' then
252 | Root.AddValue('CurrentChannel').AsString := FCurrentChannel;
253 |
254 | if FAutoCopyUpload = True then
255 | Root.AddValue('AutoCopyUpload').AsBoolean := FAutoCopyUpload;
256 |
257 | if FApplicationName <> '' then
258 | Root.AddValue('ApplicationName').AsString := FApplicationName;
259 |
260 | if FUseMD5 = True then
261 | Root.AddValue('UseMD5').AsBoolean := FUseMD5;
262 |
263 | // write FTP options (and add if it contains any data)
264 | ObjVal := TdwsJSONObject.Create;
265 | try
266 | FFtpOptions.Write(ObjVal);
267 | if ObjVal.ElementCount > 0 then
268 | Root.Add('FTP', ObjVal.Clone);
269 | finally
270 | ObjVal.Free;
271 | end;
272 |
273 | // write copy options (and add if it contains any data)
274 | ObjVal := TdwsJSONObject.Create;
275 | try
276 | FCopyOptions.Write(ObjVal);
277 | if ObjVal.ElementCount > 0 then
278 | Root.Add('Copy', ObjVal.Clone);
279 | finally
280 | ObjVal.Free;
281 | end;
282 | end;
283 |
284 | end.
285 |
--------------------------------------------------------------------------------
/Source/Snapshot Tool (Command Line)/SnapshotTool.dpr:
--------------------------------------------------------------------------------
1 | program SnapshotTool;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | System.IOUtils,
9 | System.SysUtils,
10 | System.StrUtils,
11 | WinApi.Windows,
12 | WebUpdate.Classes.WebUpdate in '..\Common\WebUpdate.Classes.WebUpdate.pas',
13 | WebUpdate.JSON.Channel in '..\Common\WebUpdate.JSON.Channel.pas',
14 | WebUpdate.JSON.Channels in '..\Common\WebUpdate.JSON.Channels.pas',
15 | WebUpdate.JSON.Project in '..\Common\WebUpdate.JSON.Project.pas',
16 | WebUpdate.JSON.Serializer in '..\Common\WebUpdate.JSON.Serializer.pas',
17 | WebUpdate.Tools in '..\Common\WebUpdate.Tools.pas';
18 |
19 | procedure WriteUsage;
20 | begin
21 | WriteLn(Format('Syntax: %s project.wup command [more commands] [-options]',
22 | [ExtractFileName(ParamStr(0))]));
23 | WriteLn('');
24 | WriteLn(' project.wup must be replaced by your project name');
25 | WriteLn('');
26 | WriteLn('Commands:');
27 | WriteLn('---------');
28 | WriteLn('');
29 | WriteLn(' s or S or Snapshot (take snapshot)');
30 | WriteLn(' c or C or Copy (copy to path)');
31 | WriteLn(' u or U or Upload (upload to server)');
32 | WriteLn('');
33 | WriteLn('Options:');
34 | WriteLn('---------');
35 | WriteLn('');
36 | WriteLn(' -Channel="channel name" (with/without quotes, default: "Nightly")');
37 | WriteLn(' -FtpHost=host (FTP host name, overrides project''s default)');
38 | WriteLn(' -FtpUser=username (FTP user name, overrides project''s default)');
39 | WriteLn(' -FtpPassword=password (FTP password, overrides project''s default)');
40 | WriteLn(' -CopyPath=path (Path of snapshot copies)');
41 | WriteLn('');
42 | WriteLn('Example:');
43 | WriteLn('--------');
44 | WriteLn('');
45 | WriteLn(Format(' %s project.wup scu -Channel=Beta',
46 | [ExtractFileName(ParamStr(0))]));
47 | WriteLn('');
48 | end;
49 |
50 | procedure UploadSnapshot(Project: TWebUpdateProject);
51 | begin
52 |
53 | end;
54 |
55 | procedure CopySnapshot(Project: TWebUpdateProject);
56 | var
57 | Path: string;
58 | ChannelSetup: TWebUpdateChannelSetup;
59 | FileItem: TWebUpdateFileItem;
60 | RealFileName, ChannelFileName, DestFileName: TFileName;
61 | begin
62 | Path := IncludeTrailingPathDelimiter(Project.Copy.Path);
63 | if IsRelativePath(Path) then
64 | Path := Project.BasePath + Path;
65 |
66 | ChannelFileName := Project.ChannelsPath + Project.ChannelName + '.json';
67 |
68 | // upload files
69 | ChannelSetup := TWebUpdateChannelSetup.Create;
70 | try
71 | // load channel setup
72 | ChannelSetup.LoadFromFile(ChannelFileName);
73 |
74 | for FileItem in ChannelSetup.Items do
75 | begin
76 | WriteLn('Copying file ', FileItem.FileName, '...');
77 |
78 | RealFileName := Project.BasePath + WebToLocalFileName(FileItem.FileName);
79 |
80 | // copy file
81 | DestFileName := ExpandFileName(Path + Project.ChannelName + '\' + FileItem.FileName);
82 | ForceDirectories(ExtractFileDir(DestFileName));
83 | TFile.Copy(RealFileName, DestFileName, True);
84 |
85 | // set file date/time according to the JSON file
86 | FileSetDate(DestFileName, DateTimeToFileDate(FileItem.Modified));
87 | end;
88 |
89 | // copy channel setup
90 | WriteLn('Copying channel setup...');
91 | DestFileName := ExpandFileName(Path + Project.ChannelName + '\' +
92 | Project.ChannelName + '.json');
93 | ForceDirectories(ExtractFileDir(DestFileName));
94 | TFile.Copy(ChannelFileName, DestFileName, True);
95 |
96 | // set file date/time according to the JSON file
97 | FileSetDate(DestFileName, DateTimeToFileDate(ChannelSetup.Modified));
98 | finally
99 | ChannelSetup.Free;
100 | end;
101 |
102 | // copy channel file
103 | WriteLn('Copying channels list...');
104 | DestFileName := ExpandFileName(Path + ExtractFileName(Project.ChannelsFilename));
105 | TFile.Copy(Project.FullChannelsFilename, DestFileName, True);
106 | end;
107 |
108 | procedure TakeSnapshot(Project: TWebUpdateProject);
109 | var
110 | Item: TWebUpdateFileItem;
111 | ChannelItem: TWebUpdateChannelItem;
112 | Fad: TWin32FileAttributeData;
113 | LastModified: TDateTime;
114 | FileName: TFileName;
115 | Channels: TWebUpdateChannels;
116 | ChannelSetup: TWebUpdateChannelSetup;
117 | begin
118 | // update status
119 | WriteLn('Taking snapshot...');
120 |
121 | Channels := TWebUpdateChannels.Create;
122 | try
123 | // load
124 | Channels.LoadFromFile(Project.ChannelsPath + Project.ChannelsFilename);
125 | ChannelItem := Channels.GetItemForChannel(Project.ChannelName);
126 |
127 | // create selected channels
128 | ChannelSetup := TWebUpdateChannelSetup.Create;
129 | try
130 | // get filename for currently selected channel
131 | FileName := Project.ChannelsPath + Project.ChannelName + '\' +
132 | Project.ChannelName + '.json';
133 |
134 | ChannelSetup.LoadFromFile(FileName);
135 |
136 | // store current channel name
137 | ChannelSetup.AppName := Project.ApplicationName;
138 | ChannelSetup.ChannelName := Project.ChannelName;
139 | LastModified := 0;
140 | for Item in ChannelSetup.Items do
141 | begin
142 | // get file attribute
143 | if not GetFileAttributesEx(PChar(Item.FileName), GetFileExInfoStandard, @Fad) then
144 | RaiseLastOSError;
145 |
146 | // create (& update) file item
147 | Item.Modified := FileTimeToDateTime(Fad.ftLastWriteTime);
148 | Item.FileSize := Fad.nFileSizeLow;
149 | if Project.UseMD5 then
150 | Item.MD5Hash := MD5(Item.FileName)
151 | else
152 | Item.MD5Hash := '';
153 |
154 | if Item.Modified > LastModified then
155 | LastModified := Item.Modified;
156 |
157 | // add item to file items list
158 | ChannelSetup.Items.Add(Item);
159 | end;
160 |
161 | ChannelSetup.Modified := LastModified;
162 | ChannelItem.Modified := LastModified;
163 |
164 | // save channel setup
165 | ChannelSetup.SaveToFile(FileName);
166 | finally
167 | ChannelSetup.Free;
168 | end;
169 |
170 | // save channels to file
171 | Channels.SaveToFile(Project.ChannelsPath + Project.ChannelsFilename);
172 | finally
173 | Channels.Free;
174 | end;
175 | end;
176 |
177 | type
178 | TWebUpdateCommand = (wuSnapshot, wuUpload, wuCopy);
179 | TWebUpdateCommands = set of TWebUpdateCommand;
180 | var
181 | Project: TWebUpdateProject;
182 | ParamIndex, CharIndex: Integer;
183 | Commands: TWebUpdateCommands;
184 | Text: string;
185 | EqPos: Integer;
186 | begin
187 | try
188 | // check for parameters
189 | if ParamCount = 0 then
190 | begin
191 | WriteUsage;
192 | Halt(100);
193 | end;
194 |
195 | // check if project file exists
196 | if not FileExists(ParamStr(1)) then
197 | begin
198 | WriteLn('File %s does not exist!', ParamStr(1));
199 | Halt(101);
200 | end;
201 |
202 | Project := TWebUpdateProject.Create;
203 | try
204 | // now load project
205 | Project.LoadFromFile(ParamStr(1));
206 |
207 | Commands := [];
208 | for ParamIndex := 2 to ParamCount do
209 | begin
210 | Text := ParamStr(ParamIndex);
211 | if Text[1] = '-' then
212 | begin
213 | // remove options identifier and get colon pos
214 | Delete(Text, 1, 1);
215 | EqPos := Pos('=', Text);
216 |
217 | if StartsText('Channel:', Text) then
218 | Project.ChannelName := Copy(Text, EqPos, Length(Text) - EqPos)
219 | else if StartsText('FtpHost:', Text) then
220 | Project.FTP.Server := Copy(Text, EqPos, Length(Text) - EqPos)
221 | else if StartsText('FtpUser:', Text) then
222 | Project.FTP.Username := Copy(Text, EqPos, Length(Text) - EqPos)
223 | else if StartsText('FtpPassword:', Text) then
224 | Project.FTP.Password := Copy(Text, EqPos, Length(Text) - EqPos)
225 | else if StartsText('CopyPath:', Text) then
226 | Project.Copy.Path := Copy(Text, EqPos, Length(Text) - EqPos)
227 | else
228 | begin
229 | WriteLn('Unknown option: %s!', Text);
230 | Halt(102);
231 | end;
232 | end
233 | else
234 | begin
235 | if SameText(Text, 'Snapshot') then
236 | Commands := Commands + [wuSnapshot]
237 | else if SameText(Text, 'Copy') then
238 | Commands := Commands + [wuCopy]
239 | else if SameText(Text, 'Upload') then
240 | Commands := Commands + [wuUpload]
241 | else
242 | for CharIndex := 1 to Length(Text) do
243 | case Text[CharIndex] of
244 | 's', 'S':
245 | Commands := Commands + [wuSnapshot];
246 | 'c', 'C':
247 | Commands := Commands + [wuCopy];
248 | 'u', 'U':
249 | Commands := Commands + [wuUpload];
250 | else
251 | begin
252 | WriteLn('Unknown command %s', Text[CharIndex]);
253 | Halt(103);
254 | end;
255 | end;
256 | end;
257 | end;
258 |
259 | if Project.AutoCopyUpload then
260 | begin
261 | if Project.Copy.Enabled then
262 | Commands := Commands + [wuCopy];
263 |
264 | if Project.FTP.Server <> '' then
265 | Commands := Commands + [wuUpload];
266 | end;
267 |
268 | if wuSnapshot in Commands then
269 | TakeSnapshot(Project);
270 |
271 | // eventually copy to path
272 | if wuCopy in Commands then
273 | CopySnapshot(Project);
274 |
275 | // eventually upload to a server
276 | if wuUpload in Commands then
277 | UploadSnapshot(Project);
278 | finally
279 | Project.Free;
280 | end;
281 | except
282 | on E: Exception do
283 | Writeln(E.ClassName, ': ', E.Message);
284 | end;
285 | end.
286 |
--------------------------------------------------------------------------------
/Source/Update Helper Wizard/WebUpdate.GUI.Updater.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.GUI.Updater;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes,
7 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
8 | Vcl.ComCtrls, Vcl.ExtCtrls, Vcl.ImgList, VirtualTrees,
9 | WebUpdate.Classes.Updater;
10 |
11 | type
12 | TNodeFileItem = record
13 | FileItem: TFileItem;
14 | end;
15 | PNodeFileItem = ^TNodeFileItem;
16 |
17 | TFormWebUpdate = class(TForm)
18 | ButtonClose: TButton;
19 | ButtonNext: TButton;
20 | CheckBoxStartApplication: TCheckBox;
21 | ComboBoxChannels: TComboBox;
22 | ImageHeader: TImage;
23 | ImageList: TImageList;
24 | LabelCurrentFile: TLabel;
25 | LabelFileList: TLabel;
26 | LabelHeader: TLabel;
27 | LabelRemainingTime: TLabel;
28 | LabelSelectChannel: TLabel;
29 | LabelSpeed: TLabel;
30 | LabelSummary: TLabel;
31 | LabelTotalStatus: TLabel;
32 | PageControl: TPageControl;
33 | PanelControl: TPanel;
34 | PanelHeader: TPanel;
35 | ProgressBarCurrent: TProgressBar;
36 | ProgressBarTotal: TProgressBar;
37 | RadioButtonAlternative: TRadioButton;
38 | RadioButtonStable: TRadioButton;
39 | TabFileList: TTabSheet;
40 | TabProgress: TTabSheet;
41 | TabSelectChannel: TTabSheet;
42 | TabSummary: TTabSheet;
43 | TreeFiles: TVirtualStringTree;
44 | procedure FormCreate(Sender: TObject);
45 | procedure FormDestroy(Sender: TObject);
46 | procedure ButtonAbortClick(Sender: TObject);
47 | procedure ButtonFinishClick(Sender: TObject);
48 | procedure ButtonNextClick(Sender: TObject);
49 | procedure ButtonStartClick(Sender: TObject);
50 | procedure RadioButtonChannelClick(Sender: TObject);
51 | procedure TabProgressShow(Sender: TObject);
52 | procedure TabSelectChannelShow(Sender: TObject);
53 | procedure TabFileListShow(Sender: TObject);
54 | procedure TabSummaryShow(Sender: TObject);
55 | procedure TreeFilesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
56 | Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
57 | procedure TreeFilesGetImageIndex(Sender: TBaseVirtualTree;
58 | Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
59 | var Ghosted: Boolean; var ImageIndex: Integer);
60 | private
61 | FWebUpdater: TWebUpdater;
62 | FCommandLine: Boolean;
63 | FMainAppWindowCaption: string;
64 | FMainAppExecutable: string;
65 | FDelay: Integer;
66 | FVerbose: Boolean;
67 |
68 | procedure ProgressEventHandler(Sender: TObject; Progress: Integer;
69 | ByteCount: Integer; KBPS: Single; RemainingTime: TDateTime);
70 | procedure FileNameProgressEventHandler(Sender: TObject; const FileName: TFileName);
71 | procedure WebUpdateCompleteEventHandler(Sender: TObject);
72 | procedure ErrorHandler(Sender: TObject; ErrorType: TWebUpdateErrorType;
73 | const FileName: TFileName; var Ignore: Boolean);
74 | public
75 | procedure ScanCommandLineParameters;
76 | procedure PerformWebUpdate;
77 | function CloseMainApplication: Boolean;
78 | end;
79 |
80 | var
81 | FormWebUpdate: TFormWebUpdate;
82 |
83 | implementation
84 |
85 | {$R *.dfm}
86 |
87 | uses
88 | System.StrUtils, WinAPI.ShellAPI, WinAPI.TlHelp32, dwsUtils;
89 |
90 | resourcestring
91 | RStrBaseURL = 'https://raw.githubusercontent.com/CWBudde/WebUpdate/master/Binaries/Snapshots/';
92 |
93 | resourcestring
94 | RStrMD5MismatchUpdate = 'MD5 mismatch, update might be corrupt!';
95 | RStrUnknownOption = 'Unknown option: %s!';
96 | RStrUnknownCommand = 'Unknown command: %s';
97 | RStrChannelDefinitionError = 'Could not load channel definition!';
98 | RStrSetupLoadError = 'Could not load setup!';
99 |
100 | procedure KillProcess(ProcessID: Integer);
101 | var
102 | ProcessHandle: THandle;
103 | ExitCode: Integer;
104 | begin
105 | // get process handle
106 | ProcessHandle := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION
107 | or PROCESS_VM_WRITE or PROCESS_VM_READ or PROCESS_TERMINATE, False,
108 | ProcessID);
109 |
110 | // eventually close process
111 | if (ProcessHandle > 0) then
112 | try
113 | ExitCode := 0;
114 | GetExitCodeProcess(ProcessHandle, DWORD(ExitCode));
115 | TerminateProcess(ProcessHandle, ExitCode);
116 | finally
117 | CloseHandle(ProcessHandle);
118 | end;
119 | end;
120 |
121 | function GetProcessIDForExecutable(ExecutableFileName: string): Cardinal;
122 | var
123 | ContinueLoop: Boolean;
124 | SnapshotHandle: THandle;
125 | ProcessEntry32: TProcessEntry32;
126 | Found: Boolean;
127 | begin
128 | // initialization
129 | ProcessEntry32.dwSize := SizeOf(TProcessEntry32);
130 | Found := False;
131 |
132 | // get snapshot
133 | SnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
134 | if SnapshotHandle > 0 then
135 | try
136 | ContinueLoop := Process32First(SnapshotHandle, ProcessEntry32);
137 | while Integer(ContinueLoop) <> 0 do
138 | begin
139 | if UnicodeSameText(ExtractFileName(ProcessEntry32.szExeFile), ExecutableFileName) then
140 | begin
141 | Found := True;
142 | Break;
143 | end;
144 | ContinueLoop := Process32Next(SnapshotHandle, ProcessEntry32);
145 | end;
146 | if not Found then
147 | Exit(0);
148 | finally
149 | CloseHandle(SnapshotHandle);
150 | end;
151 |
152 | Result := ProcessEntry32.th32ProcessID;
153 | end;
154 |
155 | function GetProcessIDForWindow(Caption: string): Cardinal;
156 | var
157 | WinHwnd: HWND;
158 | begin
159 | Result := 0;
160 |
161 | // check for opened main application
162 | WinHwnd := FindWindow(nil, PWideChar(Caption));
163 | if not (IsWindow(WinHwnd)) then
164 | Exit;
165 |
166 | // get process ID
167 | GetWindowThreadProcessID(WinHwnd, @Result);
168 | end;
169 |
170 |
171 | { TFormWebUpdate }
172 |
173 | procedure TFormWebUpdate.FormCreate(Sender: TObject);
174 | begin
175 | PageControl.ActivePage := TabSelectChannel;
176 | TreeFiles.NodeDataSize := SizeOf(TNodeFileItem);
177 |
178 | FMainAppWindowCaption := '';
179 | FMainAppExecutable := '';
180 |
181 | // create WebUpdater
182 | FWebUpdater := TWebUpdater.Create;
183 | FWebUpdater.BaseURL := RStrBaseURL;
184 | FWebUpdater.OnProgress := ProgressEventHandler;
185 | FWebUpdater.OnFileNameProgress := FileNameProgressEventHandler;
186 | FWebUpdater.OnDone := WebUpdateCompleteEventHandler;
187 | FWebUpdater.OnError := ErrorHandler;
188 |
189 | ScanCommandLineParameters;
190 | end;
191 |
192 | procedure TFormWebUpdate.FormDestroy(Sender: TObject);
193 | begin
194 | FWebUpdater.Free;
195 | end;
196 |
197 | procedure TFormWebUpdate.ButtonAbortClick(Sender: TObject);
198 | begin
199 | if Assigned(FWebUpdater) then
200 | FWebUpdater.Abort;
201 | Close;
202 | end;
203 |
204 | procedure TFormWebUpdate.ButtonFinishClick(Sender: TObject);
205 | var
206 | AppName: TFileName;
207 | begin
208 | // now eventually execute specified application
209 | if CheckBoxStartApplication.Visible and CheckBoxStartApplication.Checked then
210 | begin
211 | AppName := FWebUpdater.MainAppFileName;
212 | if AppName <> '' then
213 | ShellExecute(Application.Handle, 'open', PChar(AppName), nil,
214 | PChar(ExtractFileDir(AppName)), SW_SHOW);
215 | end;
216 |
217 | Close;
218 | end;
219 |
220 | procedure TFormWebUpdate.ButtonNextClick(Sender: TObject);
221 | begin
222 | if RadioButtonStable.Checked then
223 | FWebUpdater.ChannelName := 'Stable'
224 | else
225 | FWebUpdater.ChannelName := ComboBoxChannels.Text;
226 |
227 | // switch pages to file list / progress tab
228 | if FVerbose then
229 | PageControl.ActivePage := TabFileList
230 | else
231 | begin
232 | PerformWebUpdate;
233 |
234 | PageControl.ActivePage := TabProgress;
235 | Update;
236 | end;
237 | end;
238 |
239 | procedure TFormWebUpdate.ButtonStartClick(Sender: TObject);
240 | begin
241 | PerformWebUpdate;
242 |
243 | // switch pages to progress tab
244 | PageControl.ActivePage := TabProgress;
245 | Update;
246 | end;
247 |
248 | procedure TFormWebUpdate.FileNameProgressEventHandler(Sender: TObject;
249 | const FileName: TFileName);
250 | begin
251 | LabelCurrentFile.Caption := 'Current File: ' + FileName;
252 | end;
253 |
254 | procedure TFormWebUpdate.ProgressEventHandler(Sender: TObject;
255 | Progress: Integer; ByteCount: Integer; KBPS: Single; RemainingTime: TDateTime);
256 | begin
257 | ProgressBarCurrent.Position := Progress;
258 | ProgressBarTotal.Position := ProgressBarTotal.Position + ByteCount;
259 |
260 | LabelRemainingTime.Caption := 'Time remaining: ' + TimeToStr(RemainingTime);
261 | LabelRemainingTime.Visible := True;
262 | LabelSpeed.Caption := 'Speed: ' + IntToStr(Round(KBPS)) + ' kb/s';
263 | LabelSpeed.Visible := True;
264 | end;
265 |
266 | procedure TFormWebUpdate.WebUpdateCompleteEventHandler(Sender: TObject);
267 | begin
268 | // allow starting the application, if an (existing!) app is specified
269 | CheckBoxStartApplication.Visible := FileExists(FWebUpdater.MainAppFileName);
270 | CheckBoxStartApplication.Checked := CheckBoxStartApplication.Visible;
271 |
272 | // switch pages to summary tab
273 | PageControl.ActivePage := TabSummary;
274 | end;
275 |
276 | procedure TFormWebUpdate.ErrorHandler(Sender: TObject;
277 | ErrorType: TWebUpdateErrorType; const FileName: TFileName; var Ignore: Boolean);
278 | begin
279 | if ErrorType = etChecksum then
280 | case MessageDlg(RStrMD5MismatchUpdate,
281 | mtWarning, [mbAbort, mbIgnore], 0) of
282 | mrAbort:
283 | Ignore := False;
284 | mrIgnore:
285 | Ignore := True;
286 | end
287 | else
288 | Ignore := False;
289 | end;
290 |
291 | procedure TFormWebUpdate.RadioButtonChannelClick(Sender: TObject);
292 | begin
293 | ComboBoxChannels.Visible := RadioButtonAlternative.Checked;
294 | end;
295 |
296 | procedure TFormWebUpdate.ScanCommandLineParameters;
297 | var
298 | Index: Integer;
299 | Text: string;
300 | EqPos: Integer;
301 | ChannelNames: TStringList;
302 | begin
303 | FVerbose := False;
304 | FCommandLine := ParamCount >= 1;
305 |
306 | for Index := 1 to ParamCount do
307 | begin
308 | Text := ParamStr(Index);
309 | if Text[1] = '-' then
310 | begin
311 | // remove options identifier and get colon pos
312 | Delete(Text, 1, 1);
313 | EqPos := Pos('=', Text);
314 |
315 | if StartsText('u=', Text) then
316 | FWebUpdater.BaseURL := Copy(Text, EqPos + 1, Length(Text) - EqPos)
317 | else if StartsText('f=', Text) then
318 | FWebUpdater.ChannelsFileName := Copy(Text, EqPos + 1, Length(Text) - EqPos)
319 | else if StartsText('c=', Text) then
320 | FWebUpdater.ChannelName := Copy(Text, EqPos + 1, Length(Text) - EqPos)
321 | else if StartsText('d=', Text) then
322 | FDelay := StrToInt(Copy(Text, EqPos + 1, Length(Text) - EqPos))
323 | else if StartsText('l=', Text) then
324 | FWebUpdater.LocalChannelFileName := Copy(Text, EqPos + 1, Length(Text) - EqPos)
325 | else if StartsText('e=', Text) then
326 | FMainAppExecutable := Copy(Text, EqPos + 1, Length(Text) - EqPos)
327 | else if StartsText('w=', Text) then
328 | FMainAppWindowCaption := Copy(Text, EqPos + 1, Length(Text) - EqPos)
329 | else if StartsText('verbose', Text) then
330 | FVerbose := True
331 | else
332 | begin
333 | MessageDlg(Format(RStrUnknownOption, [Text]), mtError, [mbOK], 0);
334 | Exit;
335 | end;
336 | end
337 | else
338 | MessageDlg(Format(RStrUnknownCommand, [Text]), mtError, [mbOK], 0);
339 | end;
340 |
341 | // check for command-line calling
342 | if FCommandLine then
343 | begin
344 | PerformWebUpdate;
345 |
346 | // switch pages to progress tab
347 | PageControl.ActivePage := TabProgress;
348 | Update;
349 | end
350 | else
351 | begin
352 | FVerbose := True;
353 | ChannelNames := TStringList.Create;
354 | try
355 | ComboBoxChannels.Clear;
356 | FWebUpdater.GetChannelNames(ChannelNames);
357 | for Index := 0 to ChannelNames.Count - 1 do
358 | if not SameText(ChannelNames[Index], 'Stable') then
359 | ComboBoxChannels.Items.Add(ChannelNames[Index]);
360 | ComboBoxChannels.ItemIndex := 0;
361 | finally
362 | ChannelNames.Free;
363 | end;
364 | end;
365 | end;
366 |
367 | procedure TFormWebUpdate.TabProgressShow(Sender: TObject);
368 | begin
369 | ProgressBarTotal.Max := FWebUpdater.TotalBytes;
370 | ProgressBarTotal.Position := 0;
371 |
372 | ButtonNext.Visible := False;
373 | ButtonClose.Caption := '&Abort';
374 | ButtonClose.OnClick := ButtonAbortClick;
375 | end;
376 |
377 | procedure TFormWebUpdate.TabSelectChannelShow(Sender: TObject);
378 | begin
379 | ButtonNext.Visible := True;
380 | if FVerbose then
381 | ButtonNext.Caption := '&Next >'
382 | else
383 | ButtonNext.Caption := '&Start >';
384 | ButtonNext.OnClick := ButtonNextClick;
385 | ButtonClose.Caption := '&Abort';
386 | ButtonClose.OnClick := ButtonAbortClick;
387 | end;
388 |
389 | procedure TFormWebUpdate.TabFileListShow(Sender: TObject);
390 | var
391 | FileList: TFileItemList;
392 | FileItem: TFileItem;
393 | Node: PVirtualNode;
394 | NodeData: PNodeFileItem;
395 | begin
396 | ButtonNext.Visible := True;
397 | ButtonNext.Caption := '&Start >';
398 | ButtonNext.OnClick := ButtonStartClick;
399 | ButtonClose.Caption := '&Abort';
400 | ButtonClose.OnClick := ButtonAbortClick;
401 |
402 | TreeFiles.BeginUpdate;
403 | TreeFiles.Clear;
404 | try
405 | FileList := FWebUpdater.FileItemList;
406 | for FileItem in FileList do
407 | begin
408 | Node := TreeFiles.AddChild(TreeFiles.RootNode);
409 | NodeData := TreeFiles.GetNodeData(Node);
410 | NodeData^.FileItem := FileItem;
411 | end;
412 | finally
413 | TreeFiles.EndUpdate
414 | end;
415 | end;
416 |
417 | procedure TFormWebUpdate.TabSummaryShow(Sender: TObject);
418 | begin
419 | ButtonNext.Visible := False;
420 | ButtonClose.Caption := '&Finish';
421 | ButtonClose.OnClick := ButtonFinishClick;
422 | end;
423 |
424 | procedure TFormWebUpdate.TreeFilesGetImageIndex(Sender: TBaseVirtualTree;
425 | Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
426 | var Ghosted: Boolean; var ImageIndex: Integer);
427 | var
428 | NodeData: PNodeFileItem;
429 | begin
430 | // Ignore overlay and other columns
431 | if (Kind = ikOverlay) or (Column <> 0) then
432 | Exit;
433 |
434 | NodeData := TreeFiles.GetNodeData(Node);
435 |
436 | case NodeData.FileItem.Action of
437 | faAdd:
438 | ImageIndex := 0;
439 | faChange:
440 | ImageIndex := 1;
441 | faDelete:
442 | ImageIndex := 2;
443 | faVerify:
444 | ImageIndex := 3;
445 | end;
446 | end;
447 |
448 | procedure TFormWebUpdate.TreeFilesGetText(Sender: TBaseVirtualTree;
449 | Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
450 | var CellText: string);
451 | var
452 | NodeData: PNodeFileItem;
453 | begin
454 | CellText := '';
455 | NodeData := TreeFiles.GetNodeData(Node);
456 | case Column of
457 | 0:
458 | CellText := NodeData^.FileItem.FileName;
459 | 1:
460 | if NodeData^.FileItem.Modified > 0 then
461 | CellText := DateTimeToStr(NodeData^.FileItem.Modified);
462 | 2:
463 | if NodeData^.FileItem.FileSize > 0 then
464 | CellText := IntToStr(NodeData^.FileItem.FileSize);
465 | end;
466 | end;
467 |
468 | function TFormWebUpdate.CloseMainApplication: Boolean;
469 | var
470 | ProcessID: Integer;
471 | Counter: Integer;
472 | begin
473 | Result := False;
474 | Counter := 0;
475 | repeat
476 | ProcessID := 0;
477 | if FMainAppExecutable <> '' then
478 | ProcessID := GetProcessIDForExecutable(FMainAppExecutable)
479 | else if FMainAppWindowCaption <> '' then
480 | ProcessID := GetProcessIDForWindow(FMainAppWindowCaption);
481 |
482 | // check if process has been found
483 | if ProcessID = 0 then
484 | Exit(True);
485 |
486 | // show dialog
487 | case MessageDlg('Main application is already running!' + #13#10#13#10 +
488 | 'Force closing the main application?', mtWarning, [mbYes, mbAbort,
489 | mbRetry, mbIgnore], 0) of
490 | mrRetry:
491 | Sleep(1 + FDelay);
492 | mrYes:
493 | KillProcess(ProcessID);
494 | mrAbort:
495 | Exit(False);
496 | mrIgnore:
497 | Exit(True);
498 | end;
499 | Inc(Counter);
500 | until Counter >= 10;
501 | end;
502 |
503 | procedure TFormWebUpdate.PerformWebUpdate;
504 | begin
505 | // give other applications time to close
506 | Sleep(1 + FDelay);
507 |
508 | // first check if main application is still running
509 | if CloseMainApplication then
510 | FWebUpdater.PerformWebUpdate;
511 | end;
512 |
513 | end.
514 |
--------------------------------------------------------------------------------
/Source/Common/WebUpdate.Classes.Updater.pas:
--------------------------------------------------------------------------------
1 | unit WebUpdate.Classes.Updater;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, System.Classes, System.Generics.Collections,
7 | IdHTTP, IdComponent, dwsComp, dwsExprs, dwsErrors, dwsClassesLibModule,
8 | WebUpdate.JSON.Channels, WebUpdate.JSON.Channel;
9 |
10 | type
11 | EHttpDownload = class(Exception);
12 |
13 | TFileItem = class
14 | type
15 | TFileAction = (faAdd, faChange, faDelete, faVerify);
16 | private
17 | FFileName: TFileName;
18 | FLocalFileName: TFileName;
19 | FMD5Hash: string;
20 | FAction: TFileAction;
21 | FModified: TDateTime;
22 | FFileSize: Integer;
23 | procedure SetFileName(const Value: TFileName);
24 | protected
25 | procedure UpdateLocalFileName;
26 | public
27 | constructor Create(const FileName: TFileName; MD5Hash: string = '';
28 | FileSize: Integer = 0; Modified: TDateTime = 0);
29 |
30 | property FileName: TFileName read FFileName write SetFileName;
31 | property LocalFileName: TFileName read FLocalFileName;
32 | property MD5Hash: string read FMD5Hash write FMD5Hash;
33 | property Action: TFileAction read FAction write FAction;
34 | property Modified: TDateTime read FModified write FModified;
35 | property FileSize: Integer read FFileSize write FFileSize;
36 | end;
37 |
38 | TFileItemList = class(TList)
39 | public
40 | function LocateItemByFileName(const FileName: TFileName): TFileItem;
41 | end;
42 |
43 | TWebUpdateErrorType = (etDownload, etChecksum);
44 |
45 | TUpdaterThread = class(TThread)
46 | type
47 | TProgressEvent = procedure (Sender: TObject; Progress: Integer;
48 | ByteCount: Integer; KBPS: Single; ProgressTime: TDateTime) of object;
49 | TFileNameProgressEvent = procedure (Sender: TObject; const FileName: TFileName) of object;
50 | TErrorEvent = procedure (Sender: TObject; ErrorType: TWebUpdateErrorType;
51 | const FileName: TFileName; var Ignore: Boolean) of object;
52 | TScriptErrorsEvent = procedure (Sender: TObject; const MessageList: TdwsMessageList) of object;
53 | private
54 | FFiles: TFileItemList;
55 | FHttp: TIdHttp;
56 | FLocalPath: string;
57 | FBasePath: string;
58 | FStartTimeStamp: TDateTime;
59 | FLastTimeStamp: TDateTime;
60 | FLastWorkCount: Integer;
61 |
62 | FOnFileNameProgress: TFileNameProgressEvent;
63 | FOnProgress: TProgressEvent;
64 | FOnDone: TNotifyEvent;
65 | FOnScriptErrors: TScriptErrorsEvent;
66 | FOnError: TErrorEvent;
67 | procedure HttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
68 | protected
69 | procedure Execute; override;
70 | public
71 | constructor Create(const Files: TFileItemList); reintroduce;
72 |
73 | property Files: TFileItemList read FFiles;
74 | property BasePath: string read FBasePath write FBasePath;
75 | property LocalPath: string read FLocalPath write FLocalPath;
76 |
77 | property OnProgress: TProgressEvent read FOnProgress write FOnProgress;
78 | property OnFileNameProgress: TFileNameProgressEvent read FOnFileNameProgress write FOnFileNameProgress;
79 | property OnDone: TNotifyEvent read FOnDone write FOnDone;
80 | property OnError: TErrorEvent read FOnError write FOnError;
81 | property OnScriptErrors: TScriptErrorsEvent read FOnScriptErrors write FOnScriptErrors;
82 | end;
83 |
84 | TWebUpdater = class
85 | private
86 | FBaseURL: string;
87 | FChannelName: string;
88 | FChannels: TWebUpdateChannels;
89 | FChannelPath: string;
90 | FChannelsFileName: TFileName;
91 | FLocalChannelFileName: TFileName;
92 | FNewSetup: TWebUpdateChannelSetup;
93 | FThread: TUpdaterThread;
94 | FFileItemListCache: TFileItemList;
95 | FTotalSize: Int64;
96 | FCurrentSize: Int64;
97 | FDownloadSpeedAverage: Single;
98 | FScriptCompiler: TDelphiWebScript;
99 | FClassesLib: TdwsClassesLib;
100 |
101 | FOnFileNameProgress: TUpdaterThread.TFileNameProgressEvent;
102 | FOnScriptErrors: TUpdaterThread.TScriptErrorsEvent;
103 | FOnDone: TNotifyEvent;
104 | FOnError: TUpdaterThread.TErrorEvent;
105 | FOnProgress: TUpdaterThread.TProgressEvent;
106 |
107 | function GetFileItemList: TFileItemList;
108 | function GetLocalChannelFileName: TFileName;
109 | function GetMainAppFileName: TFileName;
110 | function GetTotalSize: Int64;
111 | procedure SetBaseURL(Value: string);
112 | procedure SetChannelName(const Value: string);
113 | procedure SetChannelsFileName(const Value: TFileName);
114 | procedure SetLocalChannelFileName(const Value: TFileName);
115 | protected
116 | procedure ErrorHandler(Sender: TObject; ErrorType: TWebUpdateErrorType;
117 | const FileName: TFileName; var Ignore: Boolean);
118 | procedure ProgressEventHandler(Sender: TObject; Progress: Integer;
119 | ByteCount: Integer; KBPS: Single; PassedTime: TDateTime);
120 | procedure FileChangedEventHandler(Sender: TObject; const FileName: TFileName);
121 | procedure ScriptErrorsEventHandler(Sender: TObject; const MessageList: TdwsMessageList);
122 | procedure DoneEventHandler(Sender: TObject);
123 |
124 | procedure RunScript(SourceCode: string);
125 |
126 | procedure BuildFileListCache;
127 | procedure ResetFileListCache;
128 | procedure LoadSetupFromFile(const FileName: TFileName);
129 | procedure LoadChannels;
130 | public
131 | constructor Create;
132 | destructor Destroy; override;
133 |
134 | procedure Abort;
135 | procedure PerformWebUpdate;
136 | procedure GetChannelNames(const ChannelNames: TStringList);
137 |
138 | property BaseURL: string read FBaseURL write SetBaseURL;
139 | property ChannelName: string read FChannelName write SetChannelName;
140 | property Channels: TWebUpdateChannels read FChannels;
141 | property ChannelsFileName: TFileName read FChannelsFileName write SetChannelsFileName;
142 | property LocalChannelFileName: TFileName read GetLocalChannelFileName write SetLocalChannelFileName;
143 | property MainAppFileName: TFileName read GetMainAppFileName;
144 | property FileItemList: TFileItemList read GetFileItemList;
145 | property TotalBytes: Int64 read GetTotalSize;
146 |
147 | property OnProgress: TUpdaterThread.TProgressEvent read FOnProgress write FOnProgress;
148 | property OnFileNameProgress: TUpdaterThread.TFileNameProgressEvent read FOnFileNameProgress write FOnFileNameProgress;
149 | property OnDone: TNotifyEvent read FOnDone write FOnDone;
150 | property OnScriptErrors: TUpdaterThread.TScriptErrorsEvent read FOnScriptErrors write FOnScriptErrors;
151 | property OnError: TUpdaterThread.TErrorEvent read FOnError write FOnError;
152 | end;
153 |
154 | implementation
155 |
156 | uses
157 | dwsUtils, IdSSLOpenSSL, WebUpdate.Tools;
158 |
159 | { TFileItem }
160 |
161 | constructor TFileItem.Create(const FileName: TFileName; MD5Hash: string = '';
162 | FileSize: Integer = 0; Modified: TDateTime = 0);
163 | begin
164 | FFileName := FileName;
165 | FMD5Hash := MD5Hash;
166 | FFileSize := FileSize;
167 | FModified := Modified;
168 | FAction := faAdd;
169 | UpdateLocalFileName;
170 | end;
171 |
172 | procedure TFileItem.SetFileName(const Value: TFileName);
173 | begin
174 | if FFileName <> Value then
175 | begin
176 | FFileName := Value;
177 | UpdateLocalFileName;
178 | end;
179 | end;
180 |
181 | procedure TFileItem.UpdateLocalFileName;
182 | begin
183 | FLocalFileName := WebToLocalFileName(FFileName);
184 | end;
185 |
186 |
187 | { TFileItemList }
188 |
189 | function TFileItemList.LocateItemByFileName(
190 | const FileName: TFileName): TFileItem;
191 | var
192 | Index: Integer;
193 | begin
194 | Result := nil;
195 | for Index := 0 to Count - 1 do
196 | if UnicodeSameText(Items[Index].FileName, FileName) then
197 | Exit(Items[Index]);
198 | end;
199 |
200 |
201 | { TUpdaterThread }
202 |
203 | constructor TUpdaterThread.Create(const Files: TFileItemList);
204 | begin
205 | FFiles := Files;
206 |
207 | FLastWorkCount := 0;
208 |
209 | inherited Create(False);
210 | end;
211 |
212 | procedure TUpdaterThread.HttpWork(ASender: TObject; AWorkMode: TWorkMode;
213 | AWorkCount: Int64);
214 | var
215 | ContentLength: Int64;
216 | Encoding: string;
217 | begin
218 | // check whether a HTTP client is assigned
219 | if not Assigned(FHttp) then
220 | Exit;
221 |
222 | // check whether a progress event is assigned
223 | if not Assigned(FOnProgress) then
224 | Exit;
225 |
226 | Encoding := FHttp.Response.TransferEncoding;
227 | ContentLength := FHttp.Response.ContentLength;
228 |
229 | if (Pos('chunked', LowerCase(Encoding)) = 0) and (ContentLength > 0) then
230 | begin
231 | Synchronize(procedure
232 | var
233 | KBPS: Single;
234 | begin
235 | KBPS := 0.001 * (AWorkCount - FLastWorkCount) / (86400 * (Now - FLastTimeStamp));
236 | FLastTimeStamp := Now;
237 | FOnProgress(Self, 100 * AWorkCount div ContentLength,
238 | AWorkCount - FLastWorkCount, KBPS, Now - FStartTimeStamp);
239 | end);
240 | FLastWorkCount := AWorkCount;
241 | end;
242 | end;
243 |
244 | procedure TUpdaterThread.Execute;
245 | var
246 | MS: TMemoryStream;
247 | Item: TFileItem;
248 | Hash: string;
249 | IgnoreError: Boolean;
250 | begin
251 | FStartTimeStamp := Now;
252 | FHttp := TIdHTTP.Create(nil);
253 | try
254 | // eventually create SSL IO handler
255 | if FileExists(ExtractFilePath(ParamStr(0)) + 'ssleay32.dll') and
256 | FileExists(ExtractFilePath(ParamStr(0)) + 'libeay32.dll') then
257 | FHttp.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
258 |
259 | FHttp.OnWork := HttpWork;
260 | MS := TMemoryStream.Create;
261 | try
262 | for Item in FFiles do
263 | begin
264 | // eventually call 'file changed' event
265 | if Assigned(FOnFileNameProgress) then
266 | Synchronize(procedure
267 | begin
268 | FOnFileNameProgress(Self, Item.FileName);
269 | end);
270 |
271 | // eventually delete file and continue with next file
272 | if Item.Action = faDelete then
273 | begin
274 | DeleteFile(FLocalPath + Item.LocalFileName);
275 | Continue;
276 | end;
277 |
278 | // clear buffer / reset last work count
279 | MS.Clear;
280 | FLastWorkCount := 0;
281 | FLastTimeStamp := Now;
282 |
283 | // check if terminated
284 | if Terminated then
285 | Exit;
286 |
287 | try
288 | // download file
289 | FHttp.Get(FBasePath + Item.FileName, MS);
290 | except
291 | IgnoreError := False;
292 | if Assigned(FOnError) then
293 | FOnError(Self, etDownload, FBasePath + Item.FileName, IgnoreError);
294 | if not IgnoreError then
295 | Exit;
296 | end;
297 |
298 | // check if terminated
299 | if Terminated then
300 | Exit;
301 |
302 | // eventually check MD5 hash
303 | if Item.MD5Hash <> '' then
304 | begin
305 | Hash := MD5(MS);
306 | if Hash <> Item.MD5Hash then
307 | begin
308 | IgnoreError := False;
309 | if Assigned(FOnError) then
310 | FOnError(Self, etChecksum, Item.FileName, IgnoreError);
311 | if not IgnoreError then
312 | Exit;
313 | end;
314 | end;
315 |
316 | // save downloaded file
317 | MS.SaveToFile(FLocalPath + Item.LocalFileName);
318 |
319 | // eventually update modification date/time
320 | if Item.Modified > 0 then
321 | FileSetDate(FLocalPath + Item.LocalFileName, DateTimeToFileDate(Item.Modified));
322 |
323 | // check if terminated
324 | if Terminated then
325 | Exit;
326 | end;
327 | finally
328 | MS.Free;
329 | end;
330 | finally
331 | FHttp.IOHandler.Free;
332 | FreeAndNil(FHttp);
333 | end;
334 |
335 | // check if terminated
336 | if Terminated then
337 | Exit;
338 |
339 | // check if terminated
340 | if Terminated then
341 | Exit;
342 |
343 | // check if terminated
344 | if Terminated then
345 | Exit;
346 |
347 | // eventually call 'done' event
348 | if Assigned(FOnDone) then
349 | Synchronize(procedure
350 | begin
351 | FOnDone(Self);
352 | end);
353 | end;
354 |
355 |
356 | { TWebUpdater }
357 |
358 | constructor TWebUpdater.Create;
359 | begin
360 | FChannels := TWebUpdateChannels.Create;
361 | FNewSetup := TWebUpdateChannelSetup.Create;
362 |
363 | FScriptCompiler := TDelphiWebScript.Create(nil);
364 | FClassesLib := TdwsClassesLib.Create(nil);
365 | FClassesLib.Script := FScriptCompiler;
366 |
367 | // specify default values
368 | FBaseURL := '';
369 | FCurrentSize := 0;
370 | FChannelPath := '';
371 | FDownloadSpeedAverage := 0;
372 |
373 | FChannelsFileName := 'Channels.json';
374 | FLocalChannelFileName := 'WebUpdate.json';
375 | end;
376 |
377 | destructor TWebUpdater.Destroy;
378 | begin
379 | // eventually terminate file download thread
380 | if Assigned(FThread) then
381 | FThread.Terminate;
382 |
383 | // free objects
384 | FFileItemListCache.Free;
385 | FClassesLib.Free;
386 | FScriptCompiler.Free;
387 | FChannels.Free;
388 | FNewSetup.Free;
389 | if Assigned(FThread) then
390 | FThread.WaitFor;
391 | FThread.Free;
392 |
393 | inherited;
394 | end;
395 |
396 | procedure TWebUpdater.Abort;
397 | begin
398 | if Assigned(FThread) then
399 | FThread.Terminate;
400 | ResetFileListCache;
401 | end;
402 |
403 | procedure TWebUpdater.BuildFileListCache;
404 | var
405 | ChannelItem: TWebUpdateChannelItem;
406 | Item: TWebUpdateFileItem;
407 | FileItem: TFileItem;
408 | PathDelimPos: Integer;
409 | LocalSetup: TWebUpdateChannelSetup;
410 | begin
411 | LoadChannels;
412 |
413 | for ChannelItem in FChannels.Items do
414 | if UnicodeSameText(ChannelItem.Name, ChannelName) then
415 | begin
416 | PathDelimPos := LastDelimiter('/', ChannelItem.FileName);
417 | FChannelPath := Copy(ChannelItem.FileName, 1, PathDelimPos);
418 | LoadSetupFromFile(ChannelItem.FileName);
419 | Break;
420 | end;
421 |
422 | FTotalSize := 0;
423 |
424 | // eventually load existing setup
425 | if FileExists(FLocalChannelFileName) then
426 | begin
427 | LocalSetup := TWebUpdateChannelSetup.Create;
428 | try
429 | LocalSetup.LoadFromFile(FLocalChannelFileName);
430 |
431 | // assume deletion of all files currently present
432 | for Item in LocalSetup.Items do
433 | begin
434 | FileItem := TFileItem.Create(Item.FileName, Item.MD5Hash, Item.FileSize,
435 | Item.Modified);
436 | FileItem.Action := faDelete;
437 | FFileItemListCache.Add(FileItem);
438 | end;
439 | finally
440 | LocalSetup.Free;
441 | end;
442 | end;
443 |
444 | // add all files (and eventually mark as
445 | for Item in FNewSetup.Items do
446 | begin
447 | // now check if file is already present (from local setup)
448 | FileItem := FFileItemListCache.LocateItemByFileName(Item.FileName);
449 |
450 | if Assigned(FileItem) then
451 | begin
452 | // check if file is marked for explicit deletion
453 | if Item.Action = iaDelete then
454 | begin
455 | FileItem.Action := faDelete;
456 |
457 | // set MD5 hash, size and modification date to 0 => always delete!
458 | FileItem.MD5Hash := '';
459 | FileItem.Modified := 0;
460 | FileItem.FileSize := 0;
461 |
462 | Continue;
463 | end;
464 |
465 | // check if file is (supposed to be) identical to previous version
466 | if (FileItem.Modified = Item.Modified) and
467 | (FileItem.FileSize = Item.FileSize) and
468 | (FileItem.MD5Hash = Item.MD5Hash) then
469 | FileItem.Action := faVerify
470 | else
471 | begin
472 | // set action to 'change' and update properties
473 | FileItem.Action := faChange;
474 | FileItem.MD5Hash := Item.MD5Hash;
475 | FileItem.Modified := Item.Modified;
476 | FileItem.FileSize := Item.FileSize;
477 | end;
478 | end
479 | else
480 | begin
481 | FileItem := TFileItem.Create(Item.FileName, Item.MD5Hash, Item.FileSize,
482 | Item.Modified);
483 | FFileItemListCache.Add(FileItem);
484 |
485 | // check if the item action is to delete the file
486 | if Item.Action = iaDelete then
487 | begin
488 | FileItem.Action := faDelete;
489 | Continue;
490 | end;
491 | end;
492 |
493 | // inc total file size (if item is about to be added
494 | if Item.Action <> iaDelete then
495 | FTotalSize := FTotalSize + Item.FileSize;
496 | end;
497 |
498 | // eventually run pre script
499 | if FNewSetup.PreUpdateScript <> '' then
500 | RunScript(FNewSetup.PreUpdateScript);
501 | end;
502 |
503 | procedure TWebUpdater.DoneEventHandler(Sender: TObject);
504 | begin
505 | // save new setup
506 | FNewSetup.SaveToFile(FLocalChannelFileName);
507 |
508 | // eventually run post script
509 | if FNewSetup.PostUpdateScript <> '' then
510 | RunScript(FNewSetup.PostUpdateScript);
511 |
512 | FThread := nil;
513 |
514 | if Assigned(FOnDone) then
515 | FOnDone(Sender);
516 | end;
517 |
518 | procedure TWebUpdater.FileChangedEventHandler(Sender: TObject;
519 | const FileName: TFileName);
520 | begin
521 | if Assigned(OnFileNameProgress) then
522 | OnFileNameProgress(Sender, FileName);
523 | end;
524 |
525 | procedure TWebUpdater.ScriptErrorsEventHandler(Sender: TObject;
526 | const MessageList: TdwsMessageList);
527 | begin
528 | if Assigned(OnScriptErrors) then
529 | OnScriptErrors(Sender, MessageList);
530 | end;
531 |
532 | procedure TWebUpdater.SetBaseURL(Value: string);
533 | begin
534 | if not StrEndsWith(Value, '/') then
535 | Value := Value + '/';
536 |
537 | if FBaseURL <> Value then
538 | begin
539 | FBaseURL := Value;
540 |
541 | ResetFileListCache;
542 | end;
543 | end;
544 |
545 | procedure TWebUpdater.SetChannelName(const Value: string);
546 | begin
547 | if FChannelName <> Value then
548 | begin
549 | FChannelName := Value;
550 | ResetFileListCache;
551 | end;
552 | end;
553 |
554 | procedure TWebUpdater.SetChannelsFileName(const Value: TFileName);
555 | begin
556 | if FChannelsFileName <> Value then
557 | begin
558 | FChannelsFileName := Value;
559 | ResetFileListCache;
560 | end;
561 | end;
562 |
563 | procedure TWebUpdater.SetLocalChannelFileName(const Value: TFileName);
564 | begin
565 | if FLocalChannelFileName <> Value then
566 | begin
567 | FLocalChannelFileName := Value;
568 | ResetFileListCache;
569 | end;
570 | end;
571 |
572 | procedure TWebUpdater.GetChannelNames(const ChannelNames: TStringList);
573 | var
574 | Item: TWebUpdateChannelItem;
575 | begin
576 | // load channels setup from URI
577 | LoadChannels;
578 |
579 | // get channel names
580 | ChannelNames.Clear;
581 | for Item in Channels.Items do
582 | ChannelNames.Add(Item.Name);
583 | end;
584 |
585 | function TWebUpdater.GetFileItemList: TFileItemList;
586 | begin
587 | // eventually create file item list (if not already created)
588 | if Assigned(FFileItemListCache) then
589 | Exit(FFileItemListCache);
590 |
591 | FFileItemListCache := TFileItemList.Create;
592 | BuildFileListCache;
593 | Result := FFileItemListCache;
594 | end;
595 |
596 | function TWebUpdater.GetLocalChannelFileName: TFileName;
597 | begin
598 | Result := FLocalChannelFileName;
599 | if IsRelativePath(Result) then
600 | Result := ExtractFilePath(ParamStr(0)) + Result;
601 | end;
602 |
603 | function TWebUpdater.GetMainAppFileName: TFileName;
604 | begin
605 | Result := '';
606 | if FNewSetup.AppName <> '' then
607 | begin
608 | // get application name
609 | Result := WebToLocalFileName(FNewSetup.AppName);
610 |
611 | // now add local path information
612 | Result := ExtractFilePath(FLocalChannelFileName) + Result;
613 | end;
614 | end;
615 |
616 | function TWebUpdater.GetTotalSize: Int64;
617 | begin
618 | GetFileItemList;
619 | Result := FTotalSize;
620 | end;
621 |
622 | procedure TWebUpdater.PerformWebUpdate;
623 | begin
624 | // eventually kill thread
625 | if Assigned(FThread) then
626 | begin
627 | FThread.Terminate;
628 | FThread.WaitFor;
629 | FThread.Free;
630 | end;
631 |
632 | FThread := TUpdaterThread.Create(FileItemList);
633 |
634 | // specify event handlers
635 | FThread.OnProgress := ProgressEventHandler;
636 | FThread.OnFileNameProgress := FileChangedEventHandler;
637 | FThread.OnDone := DoneEventHandler;
638 | FThread.OnScriptErrors := ScriptErrorsEventHandler;
639 | FThread.OnError := ErrorHandler;
640 |
641 | FThread.BasePath := FBaseURL + FChannelPath;
642 | FThread.LocalPath := ExtractFilePath(FLocalChannelFileName);
643 |
644 | FThread.Suspended := False;
645 | end;
646 |
647 | procedure TWebUpdater.RunScript(SourceCode: string);
648 | var
649 | CompiledProgram: IdwsProgram;
650 | begin
651 | // compile script
652 | CompiledProgram := FScriptCompiler.Compile(SourceCode);
653 |
654 | // check for errors
655 | if CompiledProgram.Msgs.HasErrors then
656 | begin
657 | if Assigned(OnScriptErrors) then
658 | OnScriptErrors(Self, CompiledProgram.Msgs);
659 |
660 | Exit;
661 | end;
662 |
663 | // execute script
664 | CompiledProgram.Execute;
665 | end;
666 |
667 | procedure TWebUpdater.LoadSetupFromFile(const FileName: TFileName);
668 | var
669 | Http: TIdHTTP;
670 | Text: string;
671 | Success: Boolean;
672 | begin
673 | Http := TIdHTTP.Create(nil);
674 | try
675 | try
676 | // eventually create SSL IO handler
677 | if FileExists(ExtractFilePath(ParamStr(0)) + 'ssleay32.dll') and
678 | FileExists(ExtractFilePath(ParamStr(0)) + 'libeay32.dll') then
679 | Http.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
680 |
681 | // get text from URI
682 | Text := Http.Get(FBaseURL + FileName);
683 |
684 | // check if text is available (might need check for JSON format)
685 | Success := Text <> '';
686 | except
687 | Success := False;
688 | end;
689 |
690 | // handle errors
691 | if not Success then
692 | raise EHttpDownload.CreateFmt('Error downloading from URL %s',
693 | [FBaseURL + FileName]);
694 | finally
695 | Http.IOHandler.Free;
696 | Http.Free;
697 | end;
698 |
699 | // now load setup from string
700 | FNewSetup.LoadFromString(Text);
701 | end;
702 |
703 | procedure TWebUpdater.ErrorHandler(Sender: TObject;
704 | ErrorType: TWebUpdateErrorType; const FileName: TFileName; var Ignore: Boolean);
705 | begin
706 | // event redirection
707 | if Assigned(FOnError) then
708 | FOnError(Sender, ErrorType, FileName, Ignore);
709 | end;
710 |
711 | procedure TWebUpdater.ProgressEventHandler(Sender: TObject; Progress,
712 | ByteCount: Integer; KBPS: Single; PassedTime: TDateTime);
713 | var
714 | TotalTime: TDateTime;
715 | begin
716 | FCurrentSize := FCurrentSize + ByteCount;
717 | TotalTime := PassedTime * FTotalSize / FCurrentSize;
718 |
719 | // average download speed
720 | if FDownloadSpeedAverage = 0 then
721 | FDownloadSpeedAverage := KBPS
722 | else
723 | FDownloadSpeedAverage := 0.5 * (FDownloadSpeedAverage + KBPS);
724 |
725 | // event redirection
726 | if Assigned(OnProgress) then
727 | OnProgress(Sender, Progress, ByteCount, FDownloadSpeedAverage,
728 | TotalTime - PassedTime);
729 | end;
730 |
731 | procedure TWebUpdater.ResetFileListCache;
732 | begin
733 | FreeAndNil(FFileItemListCache);
734 | end;
735 |
736 | procedure TWebUpdater.LoadChannels;
737 | var
738 | Http: TIdHTTP;
739 | Text: string;
740 | Success: Boolean;
741 | begin
742 | Http := TIdHTTP.Create(nil);
743 | try
744 | try
745 | // eventually create SSL IO handler
746 | if FileExists(ExtractFilePath(ParamStr(0)) + 'ssleay32.dll') and
747 | FileExists(ExtractFilePath(ParamStr(0)) + 'libeay32.dll') then
748 | Http.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
749 |
750 | // get text from URL
751 | Text := Http.Get(BaseURL + ChannelsFileName);
752 |
753 | // check if text is available (might need check for JSON format)
754 | Success := Text <> '';
755 | except
756 | Success := False;
757 | end;
758 |
759 | // handle errors
760 | if not Success then
761 | raise EHttpDownload.CreateFmt('Error downloading from URL %s',
762 | [BaseURL + ChannelsFileName]);
763 | finally
764 | Http.IOHandler.Free;
765 | Http.Free;
766 | end;
767 |
768 | // load channels from string
769 | FChannels.LoadFromString(Text);
770 | end;
771 |
772 | end.
773 |
--------------------------------------------------------------------------------
/Source/Update Helper (Command-line)/Updater.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {14BD67DA-2875-471A-8356-7C0BBF43AFDA}
4 | 13.4
5 | None
6 | Updater.dpr
7 | True
8 | Debug
9 | Win32
10 | 7
11 | Console
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Base
34 | true
35 |
36 |
37 | true
38 | Cfg_1
39 | true
40 | true
41 |
42 |
43 | true
44 | Base
45 | true
46 |
47 |
48 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
49 | fmx;IndySystem;CustomIPTransport;dsnap;IndyCore;fmxase;FmxTeeUI;inetdbxpress;bindcompfmx;rtl;dbrtl;bindcomp;inetdb;xmlrtl;IndyProtocols;bindengine;FMXTee;soaprtl;inet;fmxobj;fmxdae;$(DCC_UsePackage)
50 | ..\..\DCU
51 | ..\..\Binaries
52 |
53 |
54 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
55 | 1033
56 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
57 | AbbreviaVCL;TeeDB;vclimg;vcldb;vcldsnap;vclribbon;EasyListviewD16;vcl;webdsnap;OmniThreadLibraryRuntimeXE2;GR32_RSXE2;Tee;SynEdit_RXE2;O408_r;vclactnband;TeeUI;bindcompvcl;vclie;vcltouch;websnap;VclSmp;dsnapcon;vclx;MPCommonLibD16;VirtualTreesR;O408br;$(DCC_UsePackage)
58 |
59 |
60 | CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName)
61 |
62 |
63 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
64 | 1033
65 | JvBDE;JvGlobus;fsADO16;AggPasRunXE2;JvMM;JvManagedThreads;AbbreviaVCL;USBDeviceTreePkg;JvDlgs;Alcinoe_d2007;TeeDB;JvCrypt;frxTee16;inetdbbde;frxBDE16;ColorPickerButtonD16;GLScene_RunTime;JvNet;JvDotNetCtrls;PrintPreview;ECXMLParserD160;DIHtmlParser_DXE2;vclimg;fmi;JvXPCtrls;GeckoSDK;vcldb;GLS_Computing_RunTime;vcldsnap;mbColorLibD16;DeHL_Package;ChromeTabs_XE2_R;MetaGraphics_D16;GR32_AddOn_RSXE2;DCEF_XE2;dwsLibRuntime;JvCore;frxADO16;vclribbon;frxe16;EasyListviewD16;vcl;ewbrun;fsTee16;GeckoComponents;JvAppFrm;JvDB;hexlicensemgr;DAV_ASIOHost_D16;webdsnap;JvRuntimeDesign;OmniThreadLibraryRuntimeXE2;JclDeveloperTools;GR32_RSXE2;BMSpinEdit;GR32_DSGN_RSXE2;JvDocking;JvWizards;madBasic_;GR32_FreeType_XE2;OpenWirePkgD16;JvHMI;frxDBX16;JvBands;vcldbx;GR32_Controls_D16;frx16;DAV_Common_D16;JvPluginSystem;mrMath;DAV_DSP_D16;MFControls;Tee;JclContainers;dhcomps;JvCmp;madDisAsm_;JvSystem;svnui;JvTimeFramework;SynEdit_RXE2;JvControls;Mitov.Runtime.D16;fsBDE16;frxDB16;DAV_GUI_D16;O408_r;vclactnband;TeeUI;JvJans;bindcompvcl;JvStdCtrls;JvCustom;Jcl;vclie;JvPageComps;JvPrintPreview;fs16;madExcept_;frxcs16;vcltouch;websnap;ExceptionExpert16;CrossFPC_XE2;VclSmp;fsDB16;WebUpdateR;DAV_SEHost_D16;DScintillaRuntime;dsnapcon;FlatControls;JclVcl;JvPascalInterpreter;GR32_Charts_D16;vclx;MPCommonLibD16;SuperTrackbar_D16;svn;OPDE;CPortLibDXE2;bdertl;RemObjects_Synapse_D16;ExpertTools;VirtualTreesR;DAV_VSTHost_D16;O408br;$(DCC_UsePackage)
66 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
67 |
68 |
69 | DEBUG;$(DCC_Define)
70 | false
71 | true
72 | true
73 | true
74 |
75 |
76 | false
77 |
78 |
79 | false
80 | RELEASE;$(DCC_Define)
81 | 0
82 | false
83 |
84 |
85 |
86 | MainSource
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | Cfg_2
95 | Base
96 |
97 |
98 | Base
99 |
100 |
101 | Cfg_1
102 | Base
103 |
104 |
105 |
106 | Delphi.Personality.12
107 |
108 |
109 |
110 |
111 | Updater.dpr
112 |
113 |
114 | False
115 | False
116 | 1
117 | 0
118 | 0
119 | 0
120 | False
121 | False
122 | False
123 | False
124 | False
125 | 1031
126 | 1252
127 |
128 |
129 |
130 |
131 | 1.0.0.0
132 |
133 |
134 |
135 |
136 |
137 | 1.0.0.0
138 |
139 |
140 |
141 |
142 |
143 | True
144 | True
145 | True
146 |
147 |
148 | 12
149 |
150 |
151 |
152 |
153 |
154 |
638 |
--------------------------------------------------------------------------------