From 82f11f1d0b4c9be87758c8512cdd57b1dc8f5358 Mon Sep 17 00:00:00 2001 From: Alexander Shaposhnikov Date: Thu, 29 Jun 2017 14:17:16 +0000 Subject: [PATCH] [RAPPS] Update check, license type * Added LicenseType numeric field in the RAPPS DB files. Values mean: 1 - open source, 2 - freeware, 3 - trial/demo The existing License field will be used to contain the license name itself. * Finished version parser and update check. Now RAPPS can suggest an update. * Added new strings to lang/en-US.rc, lang/ru-RU.rc, lang/uk-UA.rc svn path=/branches/GSoC_2017/rapps/; revision=75233 --- reactos/base/applications/rapps/available.cpp | 54 +++++++-- reactos/base/applications/rapps/lang/en-US.rc | 7 ++ reactos/base/applications/rapps/lang/ru-RU.rc | 7 ++ reactos/base/applications/rapps/lang/uk-UA.rc | 17 +++ reactos/base/applications/rapps/misc.cpp | 112 +++++++++++++----- reactos/base/applications/rapps/rapps.h | 48 +++++--- reactos/base/applications/rapps/resource.h | 4 + 7 files changed, 195 insertions(+), 54 deletions(-) diff --git a/reactos/base/applications/rapps/available.cpp b/reactos/base/applications/rapps/available.cpp index fd26eea79f5..66277d2bb5b 100644 --- a/reactos/base/applications/rapps/available.cpp +++ b/reactos/base/applications/rapps/available.cpp @@ -87,27 +87,59 @@ BOOL ShowAvailableAppInfo(INT Index) { PAPPLICATION_INFO Info = (PAPPLICATION_INFO) ListViewGetlParam(Index); - BOOL bIsInstalled = _AppInstallCheck(Info); - WCHAR szVersion[MAX_PATH]; + WCHAR szVersion[MAX_PATH] = L"\0"; + WCHAR szLicense[MAX_PATH] = L"\0"; + BOOL bIsInstalled = _AppInstallCheck(Info), + bHasVersion = _GetInstalledVersion(Info, szVersion, _countof(szVersion)); if (!Info) return FALSE; NewRichEditText(Info->szName, CFE_BOLD); + //installed status if (bIsInstalled) { - _AddTextNewl(IDS_STATUS_INSTALLED, CFE_ITALIC); - if (_GetInstalledVersion(Info, szVersion, _countof(szVersion))) + if (bHasVersion) { + if (CompareVersionsStrings(Info->szVersion, szVersion)) + _AddTextNewl(IDS_STATUS_UPDATE_AVAILABLE, CFE_ITALIC); + else + _AddTextNewl(IDS_STATUS_INSTALLED, CFE_ITALIC); + _AddText(IDS_AINFO_VERSION, szVersion, CFE_BOLD, 0); - } + } + else + _AddTextNewl(IDS_STATUS_INSTALLED, CFE_ITALIC); + } else - { _AddTextNewl(IDS_STATUS_NOTINSTALLED, CFE_ITALIC); - } + _AddText(IDS_AINFO_AVAILABLEVERSION, Info->szVersion, CFE_BOLD, 0); - _AddText(IDS_AINFO_LICENSE, Info->szLicense, CFE_BOLD, 0); + //license + switch (Info->LicenseType) + { + case LICENSE_TYPE::OpenSource: + LoadStringW(hInst, IDS_LICENSE_OPENSOURCE, szLicense, _countof(szLicense)); + break; + case LICENSE_TYPE::Freeware: + LoadStringW(hInst, IDS_LICENSE_FREEWARE, szLicense, _countof(szLicense)); + break; + case LICENSE_TYPE::Trial: + LoadStringW(hInst, IDS_LICENSE_TRIAL, szLicense, _countof(szLicense)); + break; + default: + break; + } + if (szLicense[0] != '\0') + { + StringCbPrintfW(szLicense, _countof(szLicense), L"%ls (%ls)", szLicense, Info->szLicense); + _AddText(IDS_AINFO_LICENSE, szLicense, CFE_BOLD, 0); + } + else + { + _AddText(IDS_AINFO_LICENSE, Info->szLicense, CFE_BOLD, 0); + } _AddText(IDS_AINFO_SIZE, Info->szSize, CFE_BOLD, 0); _AddText(IDS_AINFO_URLSITE, Info->szUrlSite, CFE_BOLD, CFE_LINK); _AddText(IDS_AINFO_DESCRIPTION, Info->szDesc, CFE_BOLD, 0); @@ -297,6 +329,11 @@ EnumAvailableApplications(INT EnumType, AVAILENUMPROC lpEnumProc) break; Info->Category = ParserGetInt(L"Category", FindFileData.cFileName); + INT IntBuffer = ParserGetInt(L"LicenseType", FindFileData.cFileName); + if (IntBuffer < LICENSE_TYPE::Max) + { + Info->LicenseType = (LICENSE_TYPE) IntBuffer; + } /* copy the cache-related fields for the next time */ RtlCopyMemory(&Info->cFileName, &FindFileData.cFileName, MAX_PATH); @@ -331,6 +368,7 @@ EnumAvailableApplications(INT EnumType, AVAILENUMPROC lpEnumProc) _GetStringNullFailure(L"Size", Info->szSize, FindFileData.cFileName); _GetStringNullFailure(L"URLSite", Info->szUrlSite, FindFileData.cFileName); _GetStringNullFailure(L"CDPath", Info->szCDPath, FindFileData.cFileName); + _GetStringNullFailure(L"Language", Info->szRegName, FindFileData.cFileName); _GetStringNullFailure(L"SHA1", Info->szSHA1, FindFileData.cFileName); } diff --git a/reactos/base/applications/rapps/lang/en-US.rc b/reactos/base/applications/rapps/lang/en-US.rc index 2c31109ba6b..f3431cd078d 100644 --- a/reactos/base/applications/rapps/lang/en-US.rc +++ b/reactos/base/applications/rapps/lang/en-US.rc @@ -217,3 +217,10 @@ BEGIN IDS_STATUS_DOWNLOADING "Downloading…" IDS_STATUS_INSTALLING "Installing…" END + +STRINGTABLE +BEGIN + IDS_LICENSE_OPENSOURCE "Open Source" + IDS_LICENSE_FREEWARE "Freeware" + IDS_LICENSE_TRIAL "Trial/Demo" +END diff --git a/reactos/base/applications/rapps/lang/ru-RU.rc b/reactos/base/applications/rapps/lang/ru-RU.rc index f31acb42dd0..7f95c9ba890 100644 --- a/reactos/base/applications/rapps/lang/ru-RU.rc +++ b/reactos/base/applications/rapps/lang/ru-RU.rc @@ -216,4 +216,11 @@ BEGIN IDS_STATUS_UPDATE_AVAILABLE "Есть обновления" IDS_STATUS_DOWNLOADING "Загружается…" IDS_STATUS_INSTALLING "Установка…" +END + +STRINGTABLE +BEGIN + IDS_LICENSE_OPENSOURCE "Свободное ПО" + IDS_LICENSE_FREEWARE "Бесплатное ПО" + IDS_LICENSE_TRIAL "Пробная версия" END \ No newline at end of file diff --git a/reactos/base/applications/rapps/lang/uk-UA.rc b/reactos/base/applications/rapps/lang/uk-UA.rc index f823c10d739..4f28b3ea518 100644 --- a/reactos/base/applications/rapps/lang/uk-UA.rc +++ b/reactos/base/applications/rapps/lang/uk-UA.rc @@ -215,3 +215,20 @@ BEGIN IDS_INTERRUPTED_DOWNLOAD "The download was interrupted. Check connection to Internet." IDS_UNABLE_TO_WRITE "Unable to write to disk. Disk may be at capacity." END + +STRINGTABLE +BEGIN + IDS_STATUS_INSTALLED "Встановлено" + IDS_STATUS_NOTINSTALLED "Не встановлено" + IDS_STATUS_DOWNLOADED "Завантажено" + IDS_STATUS_UPDATE_AVAILABLE "Є оновлення" + IDS_STATUS_DOWNLOADING "Завантажується…" + IDS_STATUS_INSTALLING "Встановлюється…" +END + +STRINGTABLE +BEGIN + IDS_LICENSE_OPENSOURCE "Вільне ПЗ" + IDS_LICENSE_FREEWARE "Безкоштовне ПЗ" + IDS_LICENSE_TRIAL "Пробна версія" +END \ No newline at end of file diff --git a/reactos/base/applications/rapps/misc.cpp b/reactos/base/applications/rapps/misc.cpp index 0bd0e9a4bcd..159c739600e 100644 --- a/reactos/base/applications/rapps/misc.cpp +++ b/reactos/base/applications/rapps/misc.cpp @@ -20,6 +20,8 @@ WCHAR szCachedINISectionLocale[MAX_PATH] = L"Section."; WCHAR szCachedINISectionLocaleNeutral[MAX_PATH] = {0}; BYTE bCachedSectionStatus = FALSE; +#define STR_VERSION_CURRENT L"CURRENT" + typedef struct { int erfOper; @@ -500,39 +502,58 @@ UINT ParserGetInt(LPCWSTR lpKeyName, LPCWSTR lpFileName) return (UINT)Result; } -//Parses version string that can be formatted as 1.2.3.4-5 +template +inline BOOL IsCharNumeric(XCHAR ch) +{ + return IsCharAlphaNumeric(ch) && !IsCharAlpha(ch); +} + + +//Parses version string that can be formatted as 1.2.3-4b (or CURRENT) //Returns int buffer and it's size BOOL -ParseVersion(_In_z_ LPCWSTR szVersion, _Outptr_ INT* parrVersion, _Out_opt_ UINT iVersionSize) +ParseVersion(_In_z_ LPCWSTR szVersion, _Outptr_ PVERSION_INFO Version) { - ATL::CSimpleArray arrVersionResult; ATL::CStringW szVersionSingleInt = L""; - ATL::CStringW sDelimiters = L".-"; BOOL bHasParsed = TRUE; - INT iVersionCharCount = 0; - //INT iVersionSingleCharCount = 0; - INT iIntResult; - iVersionSize = 0; - while(szVersion[iVersionCharCount] != L'\0') + INT VersionCharCount = 0; + INT VersionLength = lstrlenW(szVersion); + StringCbCopyW(Version->szVersion, VersionLength * sizeof(szVersion), szVersion); + //CURRENT + if (!StrCmpW(szVersion, STR_VERSION_CURRENT)) { - for (;!sDelimiters.Find(szVersion[iVersionCharCount]); ++iVersionCharCount) - { - szVersionSingleInt += szVersion[iVersionCharCount]; - } - szVersionSingleInt += L'\0'; - iIntResult = StrToIntW(szVersionSingleInt.GetBuffer()); - if (iIntResult) + Version->VersionSize = NULL; + return bHasParsed; + } + + Version->VersionSize = 0; + //int expected every iteration, quit the loop if its not a number + while (Version->VersionSize < MAX_VERSION + && IsCharNumeric(szVersion[VersionCharCount]) + && VersionCharCount < VersionLength) + { + for (; IsCharNumeric(szVersion[VersionCharCount]) && VersionCharCount < VersionLength; ++VersionCharCount) { - arrVersionResult.Add(iIntResult); - iVersionSize++; + szVersionSingleInt += szVersion[VersionCharCount]; } - else + if (szVersionSingleInt.IsEmpty()) { bHasParsed = FALSE; + continue; } - ++iVersionCharCount; + INT IntResult = StrToIntW(szVersionSingleInt.GetBuffer()); + Version->arrVersion[Version->VersionSize] = IntResult; + ++Version->VersionSize; + szVersionSingleInt.Empty(); + ++VersionCharCount; + } + + if (IsCharAlphaW(szVersion[VersionCharCount])) + { + Version->cVersionSuffix = szVersion[VersionCharCount]; } - parrVersion = arrVersionResult.GetData(); + else + Version->cVersionSuffix = NULL; return bHasParsed; } @@ -540,27 +561,54 @@ ParseVersion(_In_z_ LPCWSTR szVersion, _Outptr_ INT* parrVersion, _Out_opt_ UINT //In: Zero terminated strings of versions //Out: TRUE if first is bigger than second, FALSE if else BOOL -CompareVersionsBigger(_In_z_ LPCWSTR sczVersion1, _In_z_ LPCWSTR sczVersion2, _Out_ BOOL bResult) +CompareVersionsStrings(_In_z_ LPCWSTR sczVersionLeft, _In_z_ LPCWSTR sczVersionRight) { - UINT iVersionSize1 = 0; - UINT iVersionSize2 = 0; - INT *parrVersion1 = NULL, *parrVersion2 = NULL; - bResult = FALSE; + VERSION_INFO LeftVersion, RightVersion; - if (!ParseVersion(sczVersion1, parrVersion1, iVersionSize1) - || !ParseVersion(sczVersion2, parrVersion2, iVersionSize2)) + if (!ParseVersion(sczVersionLeft, &LeftVersion) + || !ParseVersion(sczVersionRight, &RightVersion)) { return FALSE; } - for (INT i = 0; i < iVersionSize1 && i < iVersionSize2; ++i) + return CompareVersions(&LeftVersion, &RightVersion); +} + +BOOL +CompareVersions(_In_ PVERSION_INFO LeftVersion, _In_ PVERSION_INFO RightVersion) +{ + //CURRENT + if (!LeftVersion->VersionSize || !RightVersion->VersionSize) { - if (parrVersion1[i] > parrVersion2[i]) + return FALSE; + } + //1.2.3 > 1.2 + INT SizeDiff = LeftVersion->VersionSize - RightVersion->VersionSize; + if (SizeDiff > 0) + { + return TRUE; + } + if (SizeDiff < 0) + { + return FALSE; + } + //2.0.0 > 1.9.9 + for (INT i = 0; i < LeftVersion->VersionSize && i < RightVersion->VersionSize && i < MAX_VERSION; ++i) + { + if (LeftVersion->arrVersion[i] > RightVersion->arrVersion[i]) { - bResult = TRUE; return TRUE; } + if (LeftVersion->arrVersion[i] < RightVersion->arrVersion[i]) + { + return FALSE; + } + } + //1.2.3b > 1.2.3 + if (LeftVersion->cVersionSuffix > RightVersion->cVersionSuffix) + { + return TRUE; } - return TRUE; + return FALSE; } \ No newline at end of file diff --git a/reactos/base/applications/rapps/rapps.h b/reactos/base/applications/rapps/rapps.h index 61868ff8e4f..837ef6011e4 100644 --- a/reactos/base/applications/rapps/rapps.h +++ b/reactos/base/applications/rapps/rapps.h @@ -39,7 +39,7 @@ #define SPLIT_WIDTH 4 #define MAX_STR_LEN 256 - +#define MAX_VERSION 10 #define LISTVIEW_ICON_SIZE 24 #define TREEVIEW_ICON_SIZE 24 @@ -73,14 +73,24 @@ #define IS_INSTALLED_ENUM(a) (a >= ENUM_INSTALLED_MIN && a <= ENUM_INSTALLED_MAX) #define IS_AVAILABLE_ENUM(a) (a >= ENUM_AVAILABLE_MIN && a <= ENUM_AVAILABLE_MAX) - -/* aboutdlg.c */ +typedef enum +{ + None, + OpenSource, + Freeware, + Trial, + Max = Trial, + Min = None +} LICENSE_TYPE, *PLICENSE_TYPE; + +/* aboutdlg.cpp */ VOID ShowAboutDialog(VOID); -/* available.c */ +/* available.cpp */ typedef struct { INT Category; + LICENSE_TYPE LicenseType; WCHAR szName[MAX_PATH]; WCHAR szRegName[MAX_PATH]; WCHAR szVersion[MAX_PATH]; @@ -90,6 +100,7 @@ typedef struct WCHAR szUrlSite[MAX_PATH]; WCHAR szUrlDownload[MAX_PATH]; WCHAR szCDPath[MAX_PATH]; + WCHAR szLanguages[MAX_PATH]; /* caching mechanism related entries */ WCHAR cFileName[MAX_PATH]; @@ -129,17 +140,26 @@ typedef struct } SETTINGS_INFO, *PSETTINGS_INFO; -/* available.c */ +typedef struct +{ + INT arrVersion[MAX_VERSION]; + UINT VersionSize; + WCHAR cVersionSuffix = (WCHAR) NULL; + WCHAR szVersion[MAX_PATH]; +} VERSION_INFO, *PVERSION_INFO; + +/* available.cpp */ typedef BOOL (CALLBACK *AVAILENUMPROC)(PAPPLICATION_INFO Info); BOOL EnumAvailableApplications(INT EnumType, AVAILENUMPROC lpEnumProc); BOOL ShowAvailableAppInfo(INT Index); BOOL UpdateAppsDB(VOID); VOID FreeCachedAvailableEntries(VOID); -/* installdlg.c */ + +/* installdlg.cpp */ BOOL InstallApplication(INT Index); -/* installed.c */ +/* installed.cpp */ typedef BOOL (CALLBACK *APPENUMPROC)(INT ItemIndex, LPWSTR lpName, PINSTALLED_INFO Info); BOOL EnumInstalledApplications(INT EnumType, BOOL IsUserKey, APPENUMPROC lpEnumProc); BOOL GetApplicationString(HKEY hKey, LPCWSTR lpKeyName, LPWSTR lpString); @@ -150,7 +170,7 @@ VOID RemoveAppFromRegistry(INT Index); BOOL InstalledVersion(LPWSTR szVersionResult, UINT iVersionResultSize, LPCWSTR lpRegName, BOOL IsUserKey, REGSAM keyWow); -/* winmain.c */ +/* winmain.cpp */ extern HWND hMainWnd; extern HINSTANCE hInst; extern INT SelectedEnumType; @@ -158,11 +178,11 @@ extern SETTINGS_INFO SettingsInfo; VOID SaveSettings(HWND hwnd); VOID FillDefaultSettings(PSETTINGS_INFO pSettingsInfo); -/* loaddlg.c */ +/* loaddlg.cpp */ BOOL DownloadApplication(INT Index); VOID DownloadApplicationsDB(LPCWSTR lpUrl); -/* misc.c */ +/* misc.cpp */ INT GetSystemColorDepth(VOID); int GetWindowWidth(HWND hwnd); int GetWindowHeight(HWND hwnd); @@ -181,11 +201,11 @@ BOOL WriteLogMessage(WORD wType, DWORD dwEventID, LPWSTR lpMsg); UINT ParserGetString(LPCWSTR lpKeyName, LPWSTR lpReturnedString, UINT nSize, LPCWSTR lpFileName); UINT ParserGetInt(LPCWSTR lpKeyName, LPCWSTR lpFileName); -BOOL ParseVersion(_In_z_ LPCWSTR szVersion, _Outptr_ INT* parrVersion, _Out_opt_ UINT iVersionSize); -BOOL FindRegistryKeyByName(_In_ HKEY hKeyBase, _In_ REGSAM keyWow, _In_ LPCWSTR lpcKey, _Out_opt_ PHKEY hKeyResult); -BOOL CompareVersionsBigger(_In_z_ LPCWSTR sczVersion1, _In_z_ LPCWSTR sczVersion2, _Out_ BOOL bResult = FALSE); +BOOL ParseVersion(_In_z_ LPCWSTR szVersion, _Outptr_ PVERSION_INFO parrVersion); +BOOL CompareVersionsStrings(_In_z_ LPCWSTR sczVersionLeft, _In_z_ LPCWSTR sczVersionRight); +BOOL CompareVersions(_In_ PVERSION_INFO LeftVersion, _In_ PVERSION_INFO RightVersion); -/* settingsdlg.c */ +/* settingsdlg.cpp */ VOID CreateSettingsDlg(HWND hwnd); /* gui.cpp */ diff --git a/reactos/base/applications/rapps/resource.h b/reactos/base/applications/rapps/resource.h index de3f21a8226..a89b8cb10bc 100644 --- a/reactos/base/applications/rapps/resource.h +++ b/reactos/base/applications/rapps/resource.h @@ -172,6 +172,10 @@ #define IDS_STATUS_DOWNLOADING 804 #define IDS_STATUS_INSTALLING 805 +/* App license names */ +#define IDS_LICENSE_OPENSOURCE 900 +#define IDS_LICENSE_FREEWARE 901 +#define IDS_LICENSE_TRIAL 902 /* Accelerators */ #define HOTKEYS 715 -- 2.17.1