From f4d1856695caee4eb62fd7df90067fdb0555e8a0 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 15 Feb 2018 10:35:12 +0700 Subject: [PATCH] Refactor of JSON response processing. Full refactor of the update check comes in a later version --- windows/src/desktop/kmshell/kmshell.dpr | 3 +- windows/src/desktop/kmshell/kmshell.dproj | 13 +-- windows/src/desktop/kmshell/kmshell.res | Bin 7040 -> 7040 bytes .../kmshell/main/OnlineUpdateCheck.pas | 94 +++++++----------- windows/src/desktop/setup/RunTools.pas | 26 ++--- windows/src/desktop/setup/setup.dpr | 3 +- windows/src/desktop/setup/setup.dproj | 1 + windows/src/developer/TIKE/Tike.dpr | 3 +- windows/src/developer/TIKE/Tike.dproj | 1 + windows/src/developer/setup/UfrmRun.pas | 29 ++---- windows/src/developer/setup/setup.dpr | 3 +- windows/src/developer/setup/setup.dproj | 2 +- .../Keyman.System.UpdateCheckResponse.pas | 53 ++++++++-- .../delphi/online/OnlineUpdateCheck.pas | 9 +- 14 files changed, 124 insertions(+), 116 deletions(-) diff --git a/windows/src/desktop/kmshell/kmshell.dpr b/windows/src/desktop/kmshell/kmshell.dpr index 74a77dc203..0461b72630 100644 --- a/windows/src/desktop/kmshell/kmshell.dpr +++ b/windows/src/desktop/kmshell/kmshell.dpr @@ -150,7 +150,8 @@ uses JsonUtil in '..\..\global\delphi\general\JsonUtil.pas', Keyman.System.LanguageCodeUtils in '..\..\global\delphi\general\Keyman.System.LanguageCodeUtils.pas', Keyman.System.Standards.ISO6393ToBCP47Registry in '..\..\global\delphi\standards\Keyman.System.Standards.ISO6393ToBCP47Registry.pas', - Keyman.System.Standards.LCIDToBCP47Registry in '..\..\global\delphi\standards\Keyman.System.Standards.LCIDToBCP47Registry.pas'; + Keyman.System.Standards.LCIDToBCP47Registry in '..\..\global\delphi\standards\Keyman.System.Standards.LCIDToBCP47Registry.pas' {$R VERSION.RES}, + Keyman.System.UpdateCheckResponse in '..\..\global\delphi\general\Keyman.System.UpdateCheckResponse.pas'; {$R VERSION.RES} {$R manifest.res} diff --git a/windows/src/desktop/kmshell/kmshell.dproj b/windows/src/desktop/kmshell/kmshell.dproj index 6db584ddfd..00af2e81ab 100644 --- a/windows/src/desktop/kmshell/kmshell.dproj +++ b/windows/src/desktop/kmshell/kmshell.dproj @@ -295,6 +295,7 @@
$R VERSION.RES
+ Cfg_2 @@ -390,18 +391,18 @@ true - - - .\ - true - - kmshell.exe true + + + .\ + true + + 1 diff --git a/windows/src/desktop/kmshell/kmshell.res b/windows/src/desktop/kmshell/kmshell.res index cdb58670b5d88b2e89c4da1ef5e0d84f64f98314..b11549b1ca89cb4530a84be764903a3b008d4a2a 100644 GIT binary patch delta 14 VcmZoLZ!n)w!dy1x&c= 0 then begin pkg := kmcom.Packages[n]; j := Length(FParams.Packages); SetLength(FParams.Packages, j+1); - FParams.Packages[j].NewID := node.Values['id'].Value; - FParams.Packages[j].ID := nodes.Pairs[i].JsonString.Value; - FParams.Packages[j].Description := node.Values['name'].Value; + FParams.Packages[j].NewID := ucr.Packages[i].NewID; + FParams.Packages[j].ID := ucr.Packages[i].ID; + FParams.Packages[j].Description := ucr.Packages[i].Name; FParams.Packages[j].OldVersion := pkg.Version; - FParams.Packages[j].NewVersion := node.Values['version'].Value; - FParams.Packages[j].DownloadSize := (node.Values['packageFileSize'] as TJSONNumber).AsInt64; - FParams.Packages[j].DownloadURL := node.Values['url'].Value; + FParams.Packages[j].NewVersion := ucr.Packages[i].NewVersion; + FParams.Packages[j].DownloadSize := ucr.Packages[i].DownloadSize; + FParams.Packages[j].DownloadURL := ucr.Packages[i].DownloadURL; pkg := nil; end else - FErrorMessage := 'Unable to find package '+node.Pairs[i].JsonString.Value; + FErrorMessage := 'Unable to find package '+ucr.Packages[i].ID; end; - end; - if doc.Values['windows'] is TJSONObject then - begin - node := doc.Values['windows'] as TJSONObject; - if CompareVersions(node.Values['version'].Value, FCurrentVersion) < 0 then - begin - FParams.Keyman.OldVersion := FCurrentVersion; - FParams.Keyman.NewVersion := node.Values['version'].Value; - FParams.Keyman.DownloadURL := node.Values['url'].Value; - FParams.Keyman.DownloadSize := (node.Values['size'] as TJSONNumber).AsInt64; + case ucr.Status of + ucrsNoUpdate: + begin + FErrorMessage := ucr.ErrorMessage; + end; + ucrsUpdateReady: + begin + FParams.Keyman.OldVersion := ucr.CurrentVersion; + FParams.Keyman.NewVersion := ucr.NewVersion; + FParams.Keyman.DownloadURL := ucr.InstallURL; + FParams.Keyman.DownloadSize := ucr.InstallSize; + end; end; - end; - if (Length(FParams.Packages) > 0) or (FParams.Keyman.DownloadURL <> '') then - begin - if not FSilent then - ShowUpdateForm - else + if (Length(FParams.Packages) > 0) or (FParams.Keyman.DownloadURL <> '') then begin - ShowUpdateIcon; + if not FSilent then + ShowUpdateForm + else + begin + ShowUpdateIcon; + end; + Result := FParams.Result; end; - Result := FParams.Result; - end - else if doc.Values['message'] <> nil then - begin - Result := oucFailure; - FErrorMessage := doc.Values['message'].Value; end else begin - FErrorMessage := 'No updates are currently available.'; - Result := oucNoUpdates; + FErrorMessage := ucr.ErrorMessage; + Result := oucFailure; end; end else diff --git a/windows/src/desktop/setup/RunTools.pas b/windows/src/desktop/setup/RunTools.pas index 641d4f5feb..0a44efc8cc 100644 --- a/windows/src/desktop/setup/RunTools.pas +++ b/windows/src/desktop/setup/RunTools.pas @@ -123,7 +123,7 @@ implementation uses Vcl.Forms, - System.JSON, + Keyman.System.UpdateCheckResponse, bootstrapmain, comobj, @@ -323,8 +323,7 @@ end; procedure TRunTools.CheckNewVersion; var - doc: TJSONObject; - node: TJSONObject; + ucr: TUpdateCheckResponse; begin with THTTPUploader.Create(nil) do try @@ -334,26 +333,23 @@ begin Request.HostName := API_Server; Request.Protocol := API_Protocol; - Request.UrlPath := API_Path_UpdateCheck; + Request.UrlPath := API_Path_UpdateCheck_Desktop; Upload; if Response.StatusCode = 200 then begin - doc := TJSONObject.ParseJSONValue(UTF8String(Response.MessageBodyAsString)) as TJSONObject; - if doc = nil then - raise Exception.Create('Invalid response:'#13#10+string(Response.MessageBodyAsString)); - - if doc.Values['windows'] is TJSONObject then + if ucr.Parse(Response.MessageBodyAsString, 'windows', FInstallInfo.Version) then begin - node := doc.Values['windows'] as TJSONObject; - if CompareVersions(node.Values['version'].Value, FInstallInfo.Version) < 0 then + if ucr.Status = ucrsUpdateReady then begin - FNewVersion.Version := node.Values['version'].Value; - FNewVersion.InstallURL := node.Values['url'].Value; - FNewVersion.InstallSize := (node.Values['size'] as TJSONNumber).AsInt64; + FNewVersion.Version := ucr.NewVersion; + FNewVersion.InstallURL := ucr.InstallURL; + FNewVersion.InstallSize := ucr.InstallSize; FNewVersion.Filename := ExtractFileName(StringReplace(FNewVersion.InstallURL, '/', '\', [rfReplaceAll])); // I1917 end; - end; + end + else + raise Exception.Create(ucr.ErrorMessage); end else raise Exception.Create('Error '+IntToStr(Response.StatusCode)); diff --git a/windows/src/desktop/setup/setup.dpr b/windows/src/desktop/setup/setup.dpr index 2acabc84d7..f613c8a6fd 100644 --- a/windows/src/desktop/setup/setup.dpr +++ b/windows/src/desktop/setup/setup.dpr @@ -36,7 +36,8 @@ uses Unicode in '..\..\global\delphi\general\Unicode.pas', KeymanVersion in '..\..\global\delphi\general\KeymanVersion.pas', KeymanPaths in '..\..\global\delphi\general\KeymanPaths.pas', - SFX in '..\..\global\delphi\setup\SFX.pas'; + SFX in '..\..\global\delphi\setup\SFX.pas', + Keyman.System.UpdateCheckResponse in '..\..\global\delphi\general\Keyman.System.UpdateCheckResponse.pas'; {$R icons.res} {$R version.res} diff --git a/windows/src/desktop/setup/setup.dproj b/windows/src/desktop/setup/setup.dproj index eedbcb8845..2df3a4f3c1 100644 --- a/windows/src/desktop/setup/setup.dproj +++ b/windows/src/desktop/setup/setup.dproj @@ -136,6 +136,7 @@ + Cfg_2 Base diff --git a/windows/src/developer/TIKE/Tike.dpr b/windows/src/developer/TIKE/Tike.dpr index b313964a7e..794be230ad 100644 --- a/windows/src/developer/TIKE/Tike.dpr +++ b/windows/src/developer/TIKE/Tike.dpr @@ -262,7 +262,8 @@ uses BCP47Tag in '..\..\global\delphi\general\BCP47Tag.pas', Keyman.System.KMXFileLanguages in '..\..\global\delphi\keyboards\Keyman.System.KMXFileLanguages.pas', Keyman.System.LanguageCodeUtils in '..\..\global\delphi\general\Keyman.System.LanguageCodeUtils.pas', - Keyman.System.RegExGroupHelperRSP19902 in '..\..\global\delphi\general\Keyman.System.RegExGroupHelperRSP19902.pas'; + Keyman.System.RegExGroupHelperRSP19902 in '..\..\global\delphi\general\Keyman.System.RegExGroupHelperRSP19902.pas', + Keyman.System.UpdateCheckResponse in '..\..\global\delphi\general\Keyman.System.UpdateCheckResponse.pas'; {$R *.RES} {$R ICONS.RES} diff --git a/windows/src/developer/TIKE/Tike.dproj b/windows/src/developer/TIKE/Tike.dproj index f3f61efba6..7172b6c60a 100644 --- a/windows/src/developer/TIKE/Tike.dproj +++ b/windows/src/developer/TIKE/Tike.dproj @@ -503,6 +503,7 @@ + Cfg_2 diff --git a/windows/src/developer/setup/UfrmRun.pas b/windows/src/developer/setup/UfrmRun.pas index 573935ce36..3252076d4c 100644 --- a/windows/src/developer/setup/UfrmRun.pas +++ b/windows/src/developer/setup/UfrmRun.pas @@ -123,13 +123,13 @@ implementation {R *.dfm} uses - System.JSON, Unicode, utilexecute, utilsystem, shlobj, OnlineConstants, TntDialogHelp, types, upload_settings, httpuploader, + Keyman.System.UpdateCheckResponse, VersionInfo, GetOSVersion, SFX, bootstrapmain, jwawintype, jwamsi, ErrorControlledRegistry, RegistryKeys; @@ -277,40 +277,33 @@ end; procedure TfrmRun.CheckNewVersion; var - doc: TJSONObject; - node: TJSONObject; + ucr: TUpdateCheckResponse; begin with THTTPUploader.Create(nil) do try - // TODO: Eliminate Raw parameter and use 'setup' instead - Fields.Add('OnlineProductID', AnsiString(IntToStr(OnlineProductID_KeymanDeveloper_100))); // I2856 // I3377 if FInstalledVersion.Version = '' then Fields.Add('Version', AnsiString(FInstallInfo.Version)) else Fields.Add('Version', AnsiString(FInstalledVersion.Version)); - Fields.Add('Raw', '1'); Request.HostName := API_Server; Request.Protocol := API_Protocol; - Request.UrlPath := API_Path_UpdateCheck; + Request.UrlPath := API_Path_UpdateCheck_Developer; Upload; if Response.StatusCode = 200 then begin - doc := TJSONObject.ParseJSONValue(UTF8String(Response.MessageBodyAsString)) as TJSONObject; - if doc = nil then - raise Exception.Create('Invalid response:'#13#10+string(Response.MessageBodyAsString)); - - if doc.Values['windows'] is TJSONObject then + if ucr.Parse(Response.MessageBodyAsString, 'developer', FInstallInfo.Version) then begin - node := doc.Values['windows'] as TJSONObject; - if CompareVersions(node.Values['version'].Value, FInstallInfo.Version) < 0 then + if ucr.Status = ucrsUpdateReady then begin - FNewVersion.Version := node.Values['version'].Value; - FNewVersion.InstallURL := node.Values['url'].Value; - FNewVersion.InstallSize := (node.Values['size'] as TJSONNumber).AsInt64; + FNewVersion.Version := ucr.NewVersion; + FNewVersion.InstallURL := ucr.InstallURL; + FNewVersion.InstallSize := ucr.InstallSize; FNewVersion.Filename := ExtractFileName(StringReplace(FNewVersion.InstallURL, '/', '\', [rfReplaceAll])); // I1917 end; - end; + end + else + raise Exception.Create(ucr.ErrorMessage); end else raise Exception.Create('Error '+IntToStr(Response.StatusCode)); diff --git a/windows/src/developer/setup/setup.dpr b/windows/src/developer/setup/setup.dpr index d4d9df9efa..51c515d53f 100644 --- a/windows/src/developer/setup/setup.dpr +++ b/windows/src/developer/setup/setup.dpr @@ -26,7 +26,8 @@ uses Unicode in '..\..\global\delphi\general\Unicode.pas', utilexecute in '..\..\global\delphi\general\utilexecute.pas', KeymanVersion in '..\..\global\delphi\general\KeymanVersion.pas', - SFX in '..\..\global\delphi\setup\SFX.pas'; + SFX in '..\..\global\delphi\setup\SFX.pas', + Keyman.System.UpdateCheckResponse in '..\..\global\delphi\general\Keyman.System.UpdateCheckResponse.pas'; {$R icons.res} {$R version.res} diff --git a/windows/src/developer/setup/setup.dproj b/windows/src/developer/setup/setup.dproj index e4c9e0c00a..8f476f3029 100644 --- a/windows/src/developer/setup/setup.dproj +++ b/windows/src/developer/setup/setup.dproj @@ -108,6 +108,7 @@ + Cfg_2 Base @@ -160,7 +161,6 @@ - False True False diff --git a/windows/src/global/delphi/general/Keyman.System.UpdateCheckResponse.pas b/windows/src/global/delphi/general/Keyman.System.UpdateCheckResponse.pas index 1c535c250b..7e81e7ba0d 100644 --- a/windows/src/global/delphi/general/Keyman.System.UpdateCheckResponse.pas +++ b/windows/src/global/delphi/general/Keyman.System.UpdateCheckResponse.pas @@ -3,12 +3,26 @@ unit Keyman.System.UpdateCheckResponse; interface uses + System.JSON, System.SysUtils; type EUpdateCheckResponse = class(Exception); - TUpdateCheckResponseStatus = (ucrsNoUpdate, ucrsUpdateReady, ucrsError); + TUpdateCheckResponseStatus = (ucrsNoUpdate, ucrsUpdateReady); + + TUpdateCheckResponsePackage = record + ID: string; + NewID: string; + Name: string; + OldVersion, NewVersion: string; + DownloadURL: string; + SavePath: string; + DownloadSize: Integer; + Install: Boolean; + end; + + TUpdateCheckResponsePackages = TArray; TUpdateCheckResponse = record private @@ -18,6 +32,8 @@ type FStatus: TUpdateCheckResponseStatus; FErrorMessage: string; FCurrentVersion: string; + FPackages: TUpdateCheckResponsePackages; + function ParseKeyboards(nodes: TJSONObject): Boolean; public function Parse(const message: AnsiString; const app, currentVersion: string): Boolean; @@ -27,13 +43,13 @@ type property InstallSize: Int64 read FInstallSize; property ErrorMessage: string read FErrorMessage; property Status: TUpdateCheckResponseStatus read FStatus; + property Packages: TUpdateCheckResponsePackages read FPackages; end; implementation uses - versioninfo, - System.JSON; + versioninfo; { TUpdateCheckResponse } @@ -42,12 +58,12 @@ var node, doc: TJSONObject; begin FCurrentVersion := currentVersion; + FStatus := ucrsNoUpdate; // TODO: test with UTF8 characters in response doc := TJSONObject.ParseJSONValue(UTF8String(message)) as TJSONObject; if doc = nil then begin - FStatus := ucrsError; FErrorMessage := Format('Invalid response:'#13#10'%s', [string(message)]); Exit(False); end; @@ -70,11 +86,32 @@ begin end else if doc.Values['message'] <> nil then begin - FStatus := ucrsError; FErrorMessage := doc.Values['message'].Value; - end - else - FStatus := ucrsNoUpdate; + Exit(False); + end; + + if doc.Values['keyboards'] is TJSONObject + then Result := ParseKeyboards(doc.Values['keyboards'] as TJSONObject) + else Result := True; +end; + +function TUpdateCheckResponse.ParseKeyboards(nodes: TJSONObject): Boolean; +var + node: TJSONObject; + i: Integer; +begin + SetLength(FPackages,nodes.Count); + for i := 0 to nodes.Count - 1 do + begin + node := nodes.Pairs[i].JsonValue as TJSONObject; + FPackages[i].NewID := node.Values['id'].Value; + FPackages[i].ID := nodes.Pairs[i].JsonString.Value; + FPackages[i].Name := node.Values['name'].Value; + //FPackages[j].OldVersion := pkg.Version; + FPackages[i].NewVersion := node.Values['version'].Value; + FPackages[i].DownloadSize := (node.Values['packageFileSize'] as TJSONNumber).AsInt64; + FPackages[i].DownloadURL := node.Values['url'].Value; + end; Result := True; end; diff --git a/windows/src/global/delphi/online/OnlineUpdateCheck.pas b/windows/src/global/delphi/online/OnlineUpdateCheck.pas index 6e8866cb03..1b6a613c60 100644 --- a/windows/src/global/delphi/online/OnlineUpdateCheck.pas +++ b/windows/src/global/delphi/online/OnlineUpdateCheck.pas @@ -168,9 +168,7 @@ begin Proxy.Username := FProxyUsername; Proxy.Password := FProxyPassword; Request.Agent := API_UserAgent; - //Request.Protocol := Upload_Protocol; - //Request.HostName := Upload_Server; - Request.SetURL(DownloadUpdate_URL);// UrlPath := URL; + Request.SetURL(DownloadUpdate_URL); Upload; if Response.StatusCode = 200 then begin @@ -357,11 +355,6 @@ begin Synchronize(SyncShowUpdateForm); Result := FParams.Result; end; - ucrsError: - begin - FErrorMessage := ucr.ErrorMessage; - Result := oucFailure; - end; end; end else