From 96e4c85edc09e106631860f823a42440d013e455 Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 12 Jul 2024 20:39:17 +0200 Subject: feat: try using ui and i18n apis from sdk --- CMakeLists.txt | 16 +- include/GFModuleCommonUtils.hpp | 112 +++++ include/GFModuleExport.h | 42 ++ src/CMakeLists.txt | 4 +- src/gpg_info/CMakeLists.txt | 65 --- src/gpg_info/GFModuleExport.h | 42 -- src/gpg_info/GnuPGInfoGatheringModule.cpp | 526 ---------------------- src/gpg_info/GnuPGInfoGatheringModule.h | 56 --- src/gpg_info/GpgInfo.cpp | 79 ---- src/gpg_info/GpgInfo.h | 88 ---- src/gpg_info/QtLoggerFmt.h | 68 --- src/m_gpg_info/CMakeLists.txt | 56 +++ src/m_gpg_info/GnuPGInfoGatheringModule.cpp | 526 ++++++++++++++++++++++ src/m_gpg_info/GnuPGInfoGatheringModule.h | 56 +++ src/m_gpg_info/GpgInfo.cpp | 79 ++++ src/m_gpg_info/GpgInfo.h | 88 ++++ src/m_gpg_info/QtLoggerFmt.h | 68 +++ src/m_ver_check/CMakeLists.txt | 68 +++ src/m_ver_check/QtLoggerFmt.h | 68 +++ src/m_ver_check/SoftwareVersion.cpp | 100 ++++ src/m_ver_check/SoftwareVersion.h | 83 ++++ src/m_ver_check/UpdateTab.cpp | 171 +++++++ src/m_ver_check/UpdateTab.h | 74 +++ src/m_ver_check/VersionCheckTask.cpp | 221 +++++++++ src/m_ver_check/VersionCheckTask.h | 95 ++++ src/m_ver_check/VersionCheckingModule.cpp | 115 +++++ src/m_ver_check/VersionCheckingModule.h | 56 +++ src/m_ver_check/ts/ModuleVersionChecking.de_DE.ts | 68 +++ src/m_ver_check/ts/ModuleVersionChecking.en_US.ts | 68 +++ src/m_ver_check/ts/ModuleVersionChecking.fr_FR.ts | 68 +++ src/m_ver_check/ts/ModuleVersionChecking.zh_CN.ts | 68 +++ src/ver_check/CMakeLists.txt | 64 --- src/ver_check/GFModuleExport.h | 42 -- src/ver_check/QtLoggerFmt.h | 68 --- src/ver_check/SoftwareVersion.cpp | 100 ---- src/ver_check/SoftwareVersion.h | 83 ---- src/ver_check/VersionCheckTask.cpp | 176 -------- src/ver_check/VersionCheckTask.h | 89 ---- src/ver_check/VersionCheckingModule.cpp | 164 ------- src/ver_check/VersionCheckingModule.h | 56 --- 40 files changed, 2366 insertions(+), 1770 deletions(-) create mode 100644 include/GFModuleCommonUtils.hpp create mode 100644 include/GFModuleExport.h delete mode 100644 src/gpg_info/CMakeLists.txt delete mode 100644 src/gpg_info/GFModuleExport.h delete mode 100644 src/gpg_info/GnuPGInfoGatheringModule.cpp delete mode 100644 src/gpg_info/GnuPGInfoGatheringModule.h delete mode 100644 src/gpg_info/GpgInfo.cpp delete mode 100644 src/gpg_info/GpgInfo.h delete mode 100644 src/gpg_info/QtLoggerFmt.h create mode 100644 src/m_gpg_info/CMakeLists.txt create mode 100644 src/m_gpg_info/GnuPGInfoGatheringModule.cpp create mode 100644 src/m_gpg_info/GnuPGInfoGatheringModule.h create mode 100644 src/m_gpg_info/GpgInfo.cpp create mode 100644 src/m_gpg_info/GpgInfo.h create mode 100644 src/m_gpg_info/QtLoggerFmt.h create mode 100644 src/m_ver_check/CMakeLists.txt create mode 100644 src/m_ver_check/QtLoggerFmt.h create mode 100644 src/m_ver_check/SoftwareVersion.cpp create mode 100644 src/m_ver_check/SoftwareVersion.h create mode 100644 src/m_ver_check/UpdateTab.cpp create mode 100644 src/m_ver_check/UpdateTab.h create mode 100644 src/m_ver_check/VersionCheckTask.cpp create mode 100644 src/m_ver_check/VersionCheckTask.h create mode 100644 src/m_ver_check/VersionCheckingModule.cpp create mode 100644 src/m_ver_check/VersionCheckingModule.h create mode 100644 src/m_ver_check/ts/ModuleVersionChecking.de_DE.ts create mode 100644 src/m_ver_check/ts/ModuleVersionChecking.en_US.ts create mode 100644 src/m_ver_check/ts/ModuleVersionChecking.fr_FR.ts create mode 100644 src/m_ver_check/ts/ModuleVersionChecking.zh_CN.ts delete mode 100644 src/ver_check/CMakeLists.txt delete mode 100644 src/ver_check/GFModuleExport.h delete mode 100644 src/ver_check/QtLoggerFmt.h delete mode 100644 src/ver_check/SoftwareVersion.cpp delete mode 100644 src/ver_check/SoftwareVersion.h delete mode 100644 src/ver_check/VersionCheckTask.cpp delete mode 100644 src/ver_check/VersionCheckTask.h delete mode 100644 src/ver_check/VersionCheckingModule.cpp delete mode 100644 src/ver_check/VersionCheckingModule.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e41b045..85ede50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,11 +74,11 @@ link_directories( if(GPGFRONTEND_QT5_BUILD) # Introduce Qt # Support Qt version: 5.15.x - find_package(Qt5 5.15 COMPONENTS Core Widgets PrintSupport Network LinguistTools REQUIRED) + find_package(Qt5 5.15 COMPONENTS Core Widgets Network LinguistTools REQUIRED) else() # Introduce Qt # Support Qt version: 6.x - find_package(Qt6 6 COMPONENTS Core Widgets PrintSupport Network LinguistTools REQUIRED) + find_package(Qt6 6 COMPONENTS Core Widgets Network LinguistTools REQUIRED) endif() # Qt configuration @@ -87,6 +87,18 @@ set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC_OPTIONS "--compress;9") +# rpath config +if (WIN32) + message(STATUS "Configuring for Windows without rpath") +elseif (APPLE) + set(CMAKE_MACOSX_RPATH 1) + set(CMAKE_INSTALL_RPATH "@loader_path/../lib") +else() + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) + set(CMAKE_INSTALL_RPATH "$ORIGIN:$ORIGIN/../lib") +endif() + # third_party add_subdirectory(third_party) diff --git a/include/GFModuleCommonUtils.hpp b/include/GFModuleCommonUtils.hpp new file mode 100644 index 0000000..c318a1c --- /dev/null +++ b/include/GFModuleCommonUtils.hpp @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include + +#include +#include +#include + +#include "GFSDKBasic.h" +#include "GFSDKLog.h" +#include "GFSDKModule.h" + +#define DUP(v) GFModuleStrDup(v) + +inline void MLogDebug(const QString& s) { GFModuleLogDebug(s.toUtf8()); } +inline void MLogInfo(const QString& s) { GFModuleLogInfo(s.toUtf8()); } +inline void MLogWarn(const QString& s) { GFModuleLogWarn(s.toUtf8()); } +inline void MLogError(const QString& s) { GFModuleLogError(s.toUtf8()); } + +#define MLogDebugS(format, ...) \ + MLogDebug(QString::asprintf(format, __VA_ARGS__)) +#define MLogInfoS(format, ...) MLogInfo(QString::asprintf(format, __VA_ARGS__)) +#define MLogWarnS(format, ...) MLogWarn(QString::asprintf(format, __VA_ARGS__)) +#define MLogErrorS(format, ...) \ + MLogError(QString::asprintf(format, __VA_ARGS__)) + +auto QMapToMetaDataArray(const QMap& map) -> MetaData** { + auto** meta_data_array = + static_cast(GFAllocateMemory(sizeof(MetaData*) * map.size())); + + int index = 0; + for (auto it = map.begin(); it != map.end(); ++it) { + meta_data_array[index] = + static_cast(GFAllocateMemory(sizeof(MetaData))); + + QByteArray const key = it.key().toUtf8(); + QByteArray const value = it.value().toUtf8(); + + meta_data_array[index]->key = GFModuleStrDup(key); + + meta_data_array[index]->value = GFModuleStrDup(value); + + ++index; + } + + return meta_data_array; +} + +auto QMapToGFModuleMetaDataList(const QMap& map) + -> GFModuleMetaData* { + GFModuleMetaData* head = nullptr; + GFModuleMetaData* tail = nullptr; + + for (auto it = map.begin(); it != map.end(); ++it) { + auto* new_node = static_cast( + GFAllocateMemory(sizeof(GFModuleMetaData))); + + QByteArray const key = it.key().toUtf8(); + QByteArray const value = it.value().toUtf8(); + + new_node->key = new char[key.size() + 1]; + std::strcpy(const_cast(new_node->key), key.constData()); + + new_node->value = new char[value.size() + 1]; + std::strcpy(const_cast(new_node->value), value.constData()); + + new_node->next = nullptr; + + if (tail != nullptr) { + tail->next = new_node; + } else { + head = new_node; + } + tail = new_node; + } + + return head; +} + +auto AllocBufferAndCopy(const QByteArray& b) -> char* { + auto* p = static_cast(GFAllocateMemory(sizeof(char) * b.size())); + memcpy(p, b.constData(), b.size()); + return p; +} diff --git a/include/GFModuleExport.h b/include/GFModuleExport.h new file mode 100644 index 0000000..2a669cc --- /dev/null +++ b/include/GFModuleExport.h @@ -0,0 +1,42 @@ + +#ifndef GF_MODULE_EXPORT_H +#define GF_MODULE_EXPORT_H + +#ifdef GF_MODULE_STATIC_DEFINE +# define GF_MODULE_EXPORT +# define GF_MODULE_NO_EXPORT +#else +# ifndef GF_MODULE_EXPORT +# ifdef GF_MODULE_EXPORTS + /* We are building this library */ +# define GF_MODULE_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define GF_MODULE_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef GF_MODULE_NO_EXPORT +# define GF_MODULE_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef GF_MODULE_DEPRECATED +# define GF_MODULE_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef GF_MODULE_DEPRECATED_EXPORT +# define GF_MODULE_DEPRECATED_EXPORT GF_MODULE_EXPORT GF_MODULE_DEPRECATED +#endif + +#ifndef GF_MODULE_DEPRECATED_NO_EXPORT +# define GF_MODULE_DEPRECATED_NO_EXPORT GF_MODULE_NO_EXPORT GF_MODULE_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef GF_MODULE_NO_DEPRECATED +# define GF_MODULE_NO_DEPRECATED +# endif +#endif + +#endif /* GF_MODULE_EXPORT_H */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aca2f2e..be2d07d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,5 +24,5 @@ # SPDX-License-Identifier: GPL-3.0-or-later # modules -add_subdirectory(ver_check) -add_subdirectory(gpg_info) \ No newline at end of file +add_subdirectory(m_ver_check) +add_subdirectory(m_gpg_info) \ No newline at end of file diff --git a/src/gpg_info/CMakeLists.txt b/src/gpg_info/CMakeLists.txt deleted file mode 100644 index 63127f5..0000000 --- a/src/gpg_info/CMakeLists.txt +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (C) 2021 Saturneric -# -# This file is part of GpgFrontend. -# -# GpgFrontend is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# GpgFrontend is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GpgFrontend. If not, see . -# -# The initial version of the source code is inherited from -# the gpg4usb project, which is under GPL-3.0-or-later. -# -# All the source code of GpgFrontend was modified and released by -# Saturneric starting on May 12, 2021. -# -# SPDX-License-Identifier: GPL-3.0-or-later - -# com.bktus.gpgfrontend.module.integrated.gnupg_info_gathering - -aux_source_directory(. INTEGRATED_MODULE_SOURCE) - -# define libgpgfrontend_module -add_library(mod_gpg_info SHARED ${INTEGRATED_MODULE_SOURCE}) -set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GFModuleExport.h") -generate_export_header(mod_gpg_info - BASE_NAME "GF_MODULE" - EXPORT_FILE_NAME "${_export_file}") - -target_include_directories(mod_gpg_info PRIVATE - ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) - -# set output directory -set_target_properties(mod_gpg_info PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - -# install dir -install(TARGETS mod_gpg_info - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") - -# link sdk -target_link_libraries(mod_gpg_info PRIVATE - gpgfrontend_module_sdk) - -if(GPGFRONTEND_QT5_BUILD) - # link Qt core - target_link_libraries(mod_gpg_info PRIVATE Qt5::Core) -else() - # link Qt core - target_link_libraries(mod_gpg_info PRIVATE Qt6::Core) -endif() - -# property -set_property(TARGET mod_gpg_info PROPERTY AUTOMOC ON) - -# using std c++ 17 -target_compile_features(mod_gpg_info PRIVATE cxx_std_17) \ No newline at end of file diff --git a/src/gpg_info/GFModuleExport.h b/src/gpg_info/GFModuleExport.h deleted file mode 100644 index a1fc105..0000000 --- a/src/gpg_info/GFModuleExport.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef GF_MODULE_EXPORT_H -#define GF_MODULE_EXPORT_H - -#ifdef GF_MODULE_STATIC_DEFINE -# define GF_MODULE_EXPORT -# define GF_MODULE_NO_EXPORT -#else -# ifndef GF_MODULE_EXPORT -# ifdef mod_gpg_info_EXPORTS - /* We are building this library */ -# define GF_MODULE_EXPORT __attribute__((visibility("default"))) -# else - /* We are using this library */ -# define GF_MODULE_EXPORT __attribute__((visibility("default"))) -# endif -# endif - -# ifndef GF_MODULE_NO_EXPORT -# define GF_MODULE_NO_EXPORT __attribute__((visibility("hidden"))) -# endif -#endif - -#ifndef GF_MODULE_DEPRECATED -# define GF_MODULE_DEPRECATED __attribute__ ((__deprecated__)) -#endif - -#ifndef GF_MODULE_DEPRECATED_EXPORT -# define GF_MODULE_DEPRECATED_EXPORT GF_MODULE_EXPORT GF_MODULE_DEPRECATED -#endif - -#ifndef GF_MODULE_DEPRECATED_NO_EXPORT -# define GF_MODULE_DEPRECATED_NO_EXPORT GF_MODULE_NO_EXPORT GF_MODULE_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef GF_MODULE_NO_DEPRECATED -# define GF_MODULE_NO_DEPRECATED -# endif -#endif - -#endif /* GF_MODULE_EXPORT_H */ diff --git a/src/gpg_info/GnuPGInfoGatheringModule.cpp b/src/gpg_info/GnuPGInfoGatheringModule.cpp deleted file mode 100644 index 8d400c8..0000000 --- a/src/gpg_info/GnuPGInfoGatheringModule.cpp +++ /dev/null @@ -1,526 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "GnuPGInfoGatheringModule.h" - -#include -#include -#include -#include - -// qt -#include -#include -#include -#include - -// c++ -#include - -#include "GpgInfo.h" - -template <> -struct fmt::formatter { - // Parses format specifications. - constexpr auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template - auto format(const QString &qstr, FormatContext &ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - QByteArray utf8_array = qstr.toUtf8(); - return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); - } -}; - -template <> -struct fmt::formatter { - // Parses format specifications. - constexpr auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template - auto format(const QByteArray &qarray, FormatContext &ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - return fmt::format_to(ctx.out(), "{}", qarray.constData()); - } -}; - -extern auto CalculateBinaryChacksum(const QString &path) - -> std::optional; - -extern void GetGpgComponentInfos(void *, int, const char *, const char *); - -extern void GetGpgDirectoryInfos(void *, int, const char *, const char *); - -extern void GetGpgOptionInfos(void *, int, const char *, const char *); - -using Context = struct { - QString gpgme_version; - QString gpgconf_path; - GpgComponentInfo component_info; -}; - -auto GFGetModuleGFSDKVersion() -> const char * { - return GFModuleStrDup(GF_SDK_VERSION_STR); -} - -auto GFGetModuleQtEnvVersion() -> const char * { - return GFModuleStrDup(QT_VERSION_STR); -} - -auto GFGetModuleID() -> const char * { - return GFModuleStrDup("com.bktus.gpgfrontend.module.gnupg_info_gathering"); -} - -auto GFGetModuleVersion() -> const char * { return GFModuleStrDup("1.0.0"); } - -auto GFGetModuleMetaData() -> GFModuleMetaData * { - auto *p_meta = static_cast( - GFAllocateMemory(sizeof(GFModuleMetaData))); - auto *h_meta = p_meta; - - p_meta->key = "Name"; - p_meta->value = "GatherGnupgInfo"; - p_meta->next = static_cast( - GFAllocateMemory(sizeof(GFModuleMetaData))); - p_meta = p_meta->next; - - p_meta->key = "Description"; - p_meta->value = "Try gathering gnupg informations"; - p_meta->next = static_cast( - GFAllocateMemory(sizeof(GFModuleMetaData))); - p_meta = p_meta->next; - - p_meta->key = "Author"; - p_meta->value = "Saturneric"; - p_meta->next = nullptr; - return h_meta; -} - -auto GFRegisterModule() -> int { - GFModuleLogDebug("gnupg info gathering module registering"); - return 0; -} - -auto GFActiveModule() -> int { - GFModuleLogDebug("gnupg info gathering module activating"); - GFModuleListenEvent(GFGetModuleID(), - GFModuleStrDup("REQUEST_GATHERING_GNUPG_INFO")); - return 0; -} - -auto GFExecuteModule(GFModuleEvent *event) -> int { - GFModuleLogDebug( - fmt::format("gnupg info gathering module executing, event id: {}", - event->id) - .c_str()); - - GFModuleLogDebug("start to load extra info at module gnupginfogathering..."); - - const auto *const gpgme_version = GFModuleRetrieveRTValueOrDefault( - GFModuleStrDup("core"), GFModuleStrDup("gpgme.version"), - GFModuleStrDup("0.0.0")); - GFModuleLogDebug( - fmt::format("got gpgme version from rt: {}", gpgme_version).c_str()); - - const auto *const gpgconf_path = GFModuleRetrieveRTValueOrDefault( - GFModuleStrDup("core"), GFModuleStrDup("gpgme.ctx.gpgconf_path"), - GFModuleStrDup("")); - GFModuleLogDebug( - fmt::format("got gpgconf path from rt: {}", gpgconf_path).c_str()); - - auto context = Context{gpgme_version, gpgconf_path}; - - // get all components - const char *argv[] = {GFModuleStrDup("--list-components")}; - GFExecuteCommandSync(gpgconf_path, 1, argv, GetGpgComponentInfos, &context); - GFModuleLogDebug("load gnupg component info done."); - -#ifdef QT5_BUILD - QVector exec_contexts; -#else - QList exec_contexts; -#endif - - const char **argv_0 = - static_cast(GFAllocateMemory(sizeof(const char *))); - argv_0[0] = GFModuleStrDup("--list-dirs"); - - exec_contexts.push_back( - {gpgconf_path, 1, argv_0, GetGpgDirectoryInfos, nullptr}); - - char **components_c_array; - int ret = GFModuleListRTChildKeys( - GFGetModuleID(), GFModuleStrDup("gnupg.components"), &components_c_array); - if (components_c_array == nullptr || ret == 0) return -1; - - QStringList components; - auto *p_a = components_c_array; - for (int i = 0; i < ret; i++) components.append(QString::fromUtf8(p_a[i])); - - for (const auto &component : components) { - const auto *component_info_json = GFModuleRetrieveRTValueOrDefault( - GFGetModuleID(), - GFModuleStrDup(QString("gnupg.components.%1").arg(component).toUtf8()), - nullptr); - - if (component_info_json == nullptr) continue; - - auto jsonlized_component_info = - QJsonDocument::fromJson(component_info_json); - assert(jsonlized_component_info.isObject()); - - auto component_info = GpgComponentInfo(jsonlized_component_info.object()); - GFModuleLogDebug(fmt::format("gpgconf check options ready, " - "component: {}", - component_info.name) - .c_str()); - - if (component_info.name == "gpgme" || component_info.name == "gpgconf") { - continue; - } - - auto *context = new (GFAllocateMemory(sizeof(Context))) - Context{gpgme_version, gpgconf_path, component_info}; - - const char **argv_0 = - static_cast(GFAllocateMemory(sizeof(const char *) * 2)); - argv_0[0] = GFModuleStrDup("--list-options"), - argv_0[1] = GFModuleStrDup(component_info.name.toUtf8()); - exec_contexts.push_back( - {gpgconf_path, 2, argv_0, GetGpgOptionInfos, context}); - } - - GFExecuteCommandBatchSync(static_cast(exec_contexts.size()), - exec_contexts.constData()); - GFModuleUpsertRTValueBool(GFGetModuleID(), - GFModuleStrDup("gnupg.gathering_done"), 1); - - char **event_argv = - static_cast(GFAllocateMemory(sizeof(char **) * 1)); - event_argv[0] = GFModuleStrDup("0"); - - GFModuleTriggerModuleEventCallback(event, GFGetModuleID(), 1, event_argv); - - GFModuleLogDebug("gnupg external info gathering done"); - return 0; -} - -auto GFDeactiveModule() -> int { return 0; } - -auto GFUnregisterModule() -> int { - GFModuleLogDebug("gnupg info gathering module unregistering"); - return 0; -} - -auto CalculateBinaryChacksum(const QString &path) -> std::optional { - // check file info and access rights - QFileInfo info(path); - if (!info.exists() || !info.isFile() || !info.isReadable()) { - GFModuleLogError(fmt::format("get info for file {} error, exists: {}", - info.filePath(), info.exists()) - .c_str()); - return {}; - } - - // open and read file - QFile f(info.filePath()); - if (!f.open(QIODevice::ReadOnly)) { - GFModuleLogError(fmt::format("open {} to calculate checksum error: {}", - path.toStdString(), - f.errorString().toStdString()) - .c_str()); - return {}; - } - - QCryptographicHash hash_sha(QCryptographicHash::Sha256); - - // read data by chunks - const qint64 buffer_size = 8192; // Define a suitable buffer size - while (!f.atEnd()) { - QByteArray const buffer = f.read(buffer_size); - if (buffer.isEmpty()) { - GFModuleLogError(fmt::format("error reading file {} during " - "checksum calculation", - path.toStdString()) - .c_str()); - return {}; - } - hash_sha.addData(buffer); - } - - // close the file - f.close(); - - // return the first 6 characters of the SHA-256 hash - // of the file - return QString(hash_sha.result().toHex()).left(6); -} - -void GetGpgComponentInfos(void *data, int exit_code, const char *out, - const char *err) { - auto *context = reinterpret_cast(data); - auto p_out = QString::fromUtf8(out); - auto p_err = QString::fromUtf8(err); - - GFModuleLogDebug(fmt::format("gpgconf components exit_code: {} " - "process stdout size: {}", - exit_code, p_out.size()) - .c_str()); - - if (exit_code != 0) { - GFModuleLogError(fmt::format("gpgconf execute error, process " - "stderr: {}, " - "process stdout: {}", - p_err, p_out) - .c_str()); - return; - } - - std::vector component_infos; - GpgComponentInfo c_i_gpgme; - c_i_gpgme.name = "gpgme"; - c_i_gpgme.desc = "GPG Made Easy"; - c_i_gpgme.version = context->gpgme_version; - c_i_gpgme.path = "Embedded In"; - c_i_gpgme.binary_checksum = "/"; - - GpgComponentInfo c_i_gpgconf; - c_i_gpgconf.name = "gpgconf"; - c_i_gpgconf.desc = "GPG Configure"; - c_i_gpgconf.version = "/"; - c_i_gpgconf.path = context->gpgconf_path; - auto gpgconf_binary_checksum = CalculateBinaryChacksum(context->gpgconf_path); - c_i_gpgconf.binary_checksum = - (gpgconf_binary_checksum.has_value() ? gpgconf_binary_checksum.value() - : QString("/")); - - component_infos.push_back(c_i_gpgme); - component_infos.push_back(c_i_gpgconf); - - auto const jsonlized_gpgme_component_info = c_i_gpgme.Json(); - auto const jsonlized_gpgconf_component_info = c_i_gpgconf.Json(); - GFModuleUpsertRTValue( - GFGetModuleID(), GFModuleStrDup("gnupg.components.gpgme"), - GFModuleStrDup(QJsonDocument(jsonlized_gpgme_component_info).toJson())); - GFModuleUpsertRTValue( - GFGetModuleID(), GFModuleStrDup("gnupg.components.gpgconf"), - GFModuleStrDup(QJsonDocument(jsonlized_gpgconf_component_info).toJson())); - - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - - if (info_split_list.size() != 3) continue; - - auto component_name = info_split_list[0].trimmed(); - auto component_desc = info_split_list[1].trimmed(); - auto component_path = info_split_list[2].trimmed(); - -#ifdef WINDOWS - // replace some special substrings on windows - // platform - component_path.replace("%3a", ":"); -#endif - - auto binary_checksum = CalculateBinaryChacksum(component_path); - - GFModuleLogDebug( - fmt::format("gnupg component name: {} desc: " - "{} checksum: {} path: {} ", - component_name, component_desc, - binary_checksum.has_value() ? binary_checksum.value() : "/", - component_path) - .c_str()); - - QString version = "/"; - - if (component_name == "gpg") { - version = GFModuleRetrieveRTValueOrDefault( - GFModuleStrDup("core"), GFModuleStrDup("gpgme.ctx.gnupg_version"), - GFModuleStrDup("2.0.0")); - } - if (component_name == "gpg-agent") { - GFModuleUpsertRTValue(GFGetModuleID(), - GFModuleStrDup("gnupg.gpg_agent_path"), - GFModuleStrDup(QString(component_path).toUtf8())); - } - if (component_name == "dirmngr") { - GFModuleUpsertRTValue(GFGetModuleID(), - GFModuleStrDup("gnupg.dirmngr_path"), - GFModuleStrDup(QString(component_path).toUtf8())); - } - if (component_name == "keyboxd") { - GFModuleUpsertRTValue(GFGetModuleID(), - GFModuleStrDup("gnupg.keyboxd_path"), - GFModuleStrDup(QString(component_path).toUtf8())); - } - - { - GpgComponentInfo c_i; - c_i.name = component_name; - c_i.desc = component_desc; - c_i.version = version; - c_i.path = component_path; - c_i.binary_checksum = - (binary_checksum.has_value() ? binary_checksum.value() - : QString("/")); - - auto const jsonlized_component_info = c_i.Json(); - GFModuleUpsertRTValue( - GFGetModuleID(), - GFModuleStrDup( - QString("gnupg.components.%1").arg(component_name).toUtf8()), - GFModuleStrDup(QJsonDocument(jsonlized_component_info).toJson())); - - component_infos.push_back(c_i); - } - - GFModuleLogDebug("load gnupg component info actually done."); - } -} - -void GetGpgDirectoryInfos(void *, int exit_code, const char *out, - const char *err) { - if (exit_code != 0) return; - - auto p_out = QString::fromUtf8(out); - auto p_err = QString::fromUtf8(err); - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - GFModuleLogDebug(fmt::format("gpgconf direcrotries info line: " - "{} info size: {}", - line, info_split_list.size()) - .c_str()); - - if (info_split_list.size() != 2) continue; - - auto configuration_name = info_split_list[0].trimmed(); - auto configuration_value = info_split_list[1].trimmed(); - -#ifdef WINDOWS - // replace some special substrings on windows - // platform - configuration_value.replace("%3a", ":"); -#endif - - // record gnupg home path - if (configuration_name == "homedir") { - GFModuleUpsertRTValue(GFGetModuleID(), GFModuleStrDup("gnupg.home_path"), - GFModuleStrDup(configuration_value.toUtf8())); - } - - GFModuleUpsertRTValue( - GFGetModuleID(), - GFModuleStrDup( - QString("gnupg.dirs.%1").arg(configuration_name).toUtf8()), - GFModuleStrDup(configuration_value.toUtf8())); - } -} - -void GetGpgOptionInfos(void *data, int exit_code, const char *out, - const char *err) { - if (exit_code != 0) return; - - auto p_out = QString::fromUtf8(out); - auto p_err = QString::fromUtf8(err); - auto *context = reinterpret_cast(data); - auto component_name = context->component_info.name; - - GFModuleLogDebug(fmt::format("gpgconf {} avaliable options " - "exit_code: {} process stdout " - "size: {} ", - component_name, exit_code, p_out.size()) - .c_str()); - - std::vector options_infos; - - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - - GFModuleLogDebug(fmt::format("component {} avaliable options " - "line: {} info size: {}", - component_name, line, info_split_list.size()) - .c_str()); - - if (info_split_list.size() < 10) continue; - - // The format of each line is: - // name:flags:level:description:type:alt-type:argname:default:argdef:value - - auto option_name = info_split_list[0].trimmed(); - auto option_flags = info_split_list[1].trimmed(); - auto option_level = info_split_list[2].trimmed(); - auto option_desc = info_split_list[3].trimmed(); - auto option_type = info_split_list[4].trimmed(); - auto option_alt_type = info_split_list[5].trimmed(); - auto option_argname = info_split_list[6].trimmed(); - auto option_default = info_split_list[7].trimmed(); - auto option_argdef = info_split_list[8].trimmed(); - auto option_value = info_split_list[9].trimmed(); - - GpgOptionsInfo info; - info.name = option_name; - info.flags = option_flags; - info.level = option_level; - info.description = option_desc; - info.type = option_type; - info.alt_type = option_alt_type; - info.argname = option_argname; - info.default_value = option_default; - info.argdef = option_argdef; - info.value = option_value; - - auto const jsonlized_option_info = info.Json(); - GFModuleUpsertRTValue( - GFGetModuleID(), - GFModuleStrDup(QString("gnupg.components.%1.options.%2") - .arg(component_name) - .arg(option_name) - .toUtf8()), - GFModuleStrDup(QJsonDocument(jsonlized_option_info).toJson())); - options_infos.push_back(info); - } - - context->~Context(); - GFFreeMemory(context); -} diff --git a/src/gpg_info/GnuPGInfoGatheringModule.h b/src/gpg_info/GnuPGInfoGatheringModule.h deleted file mode 100644 index 35ee4ac..0000000 --- a/src/gpg_info/GnuPGInfoGatheringModule.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include - -#include "GFModuleExport.h" - -extern "C" { - -auto GF_MODULE_EXPORT GFGetModuleGFSDKVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleQtEnvVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleID() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleMetaData() -> GFModuleMetaData *; - -auto GF_MODULE_EXPORT GFRegisterModule() -> int; - -auto GF_MODULE_EXPORT GFActiveModule() -> int; - -auto GF_MODULE_EXPORT GFExecuteModule(GFModuleEvent *) -> int; - -auto GF_MODULE_EXPORT GFDeactiveModule() -> int; - -auto GF_MODULE_EXPORT GFUnregisterModule() -> int; -}; diff --git a/src/gpg_info/GpgInfo.cpp b/src/gpg_info/GpgInfo.cpp deleted file mode 100644 index 680f4a8..0000000 --- a/src/gpg_info/GpgInfo.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "GpgInfo.h" - -GpgOptionsInfo::GpgOptionsInfo(const QJsonObject &j) { - if (const auto v = j["name"]; v.isString()) name = v.toString(); - if (const auto v = j["flags"]; v.isString()) flags = v.toString(); - if (const auto v = j["level"]; v.isString()) level = v.toString(); - if (const auto v = j["description"]; v.isString()) description = v.toString(); - if (const auto v = j["type"]; v.isString()) type = v.toString(); - if (const auto v = j["alt_type"]; v.isString()) alt_type = v.toString(); - if (const auto v = j["argname"]; v.isString()) argname = v.toString(); - if (const auto v = j["default_value"]; v.isString()) { - default_value = v.toString(); - } - if (const auto v = j["argdef"]; v.isString()) argdef = v.toString(); - if (const auto v = j["value"]; v.isString()) value = v.toString(); -} - -auto GpgOptionsInfo::Json() const -> QJsonObject { - QJsonObject j; - j["name"] = name; - j["flags"] = flags; - j["level"] = level; - j["description"] = description; - j["type"] = type; - j["alt_type"] = alt_type; - j["argname"] = argname; - j["default_value"] = default_value; - j["argdef"] = argdef; - j["value"] = value; - return j; -} - -auto GpgComponentInfo::Json() const -> QJsonObject { - QJsonObject j; - j["name"] = name; - j["desc"] = desc; - j["version"] = version; - j["path"] = path; - j["binary_checksum"] = binary_checksum; - return j; -} - -GpgComponentInfo::GpgComponentInfo(const QJsonObject &j) { - if (const auto v = j["name"]; v.isString()) name = v.toString(); - if (const auto v = j["desc"]; v.isString()) desc = v.toString(); - if (const auto v = j["version"]; v.isString()) version = v.toString(); - if (const auto v = j["path"]; v.isString()) path = v.toString(); - if (const auto v = j["binary_checksum"]; v.isString()) { - binary_checksum = v.toString(); - } -} diff --git a/src/gpg_info/GpgInfo.h b/src/gpg_info/GpgInfo.h deleted file mode 100644 index 1aacc20..0000000 --- a/src/gpg_info/GpgInfo.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include -#include -#include - -/** - * @brief Use to record some info about gnupg - * - */ -class GpgInfo { - public: - QString GnuPGHomePath; ///< value of ---homedir - - std::map> ComponentsInfo; ///< - std::map> ConfigurationsInfo; ///< - std::map> OptionsInfo; ///< - std::map> AvailableOptionsInfo; ///< -}; - -/** - * @brief Use to record some info about gnupg components - * - */ -struct GpgComponentInfo { - QString name; - QString desc; - QString version; - QString path; - QString binary_checksum; - - GpgComponentInfo() = default; - - explicit GpgComponentInfo(const QJsonObject &j); - - [[nodiscard]] auto Json() const -> QJsonObject; -}; - -/** - * The format of each line is: - * name:flags:level:description:type:alt-type:argname:default:argdef:value - */ -struct GpgOptionsInfo { - QString name; - QString flags; - QString level; - QString description; - QString type; - QString alt_type; - QString argname; - QString default_value; - QString argdef; - QString value; - - GpgOptionsInfo() = default; - - explicit GpgOptionsInfo(const QJsonObject &j); - - [[nodiscard]] auto Json() const -> QJsonObject; -}; diff --git a/src/gpg_info/QtLoggerFmt.h b/src/gpg_info/QtLoggerFmt.h deleted file mode 100644 index 2399746..0000000 --- a/src/gpg_info/QtLoggerFmt.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include - -#include - -template <> -struct fmt::formatter { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template - auto format(const QString& qstr, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - QByteArray utf8_array = qstr.toUtf8(); - return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); - } -}; - -template <> -struct fmt::formatter { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template - auto format(const QByteArray& qarray, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - return fmt::format_to(ctx.out(), "{}", qarray.constData()); - } -}; diff --git a/src/m_gpg_info/CMakeLists.txt b/src/m_gpg_info/CMakeLists.txt new file mode 100644 index 0000000..1d96a5a --- /dev/null +++ b/src/m_gpg_info/CMakeLists.txt @@ -0,0 +1,56 @@ +# Copyright (C) 2021 Saturneric +# +# This file is part of GpgFrontend. +# +# GpgFrontend is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GpgFrontend is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GpgFrontend. If not, see . +# +# The initial version of the source code is inherited from +# the gpg4usb project, which is under GPL-3.0-or-later. +# +# All the source code of GpgFrontend was modified and released by +# Saturneric starting on May 12, 2021. +# +# SPDX-License-Identifier: GPL-3.0-or-later + +# com.bktus.gpgfrontend.module.integrated.gnupg_info_gathering + +aux_source_directory(. INTEGRATED_MODULE_SOURCE) + +# define libgpgfrontend_module +add_library(mod_gpg_info SHARED ${INTEGRATED_MODULE_SOURCE}) + +target_include_directories(mod_gpg_info PRIVATE + ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) + +# install dir +install(TARGETS mod_gpg_info + LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/modules") + +# link sdk +target_link_libraries(mod_gpg_info PRIVATE + gpgfrontend_module_sdk) + +if(GPGFRONTEND_QT5_BUILD) + # link Qt core + target_link_libraries(mod_gpg_info PRIVATE Qt5::Core) +else() + # link Qt core + target_link_libraries(mod_gpg_info PRIVATE Qt6::Core) +endif() + +# using std c++ 17 +target_compile_features(mod_gpg_info PRIVATE cxx_std_17) + +# ui +set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_AUTOUIC_SEARCH_PATHS} ${CMAKE_CURRENT_SOURCE_DIR}/ui) \ No newline at end of file diff --git a/src/m_gpg_info/GnuPGInfoGatheringModule.cpp b/src/m_gpg_info/GnuPGInfoGatheringModule.cpp new file mode 100644 index 0000000..8d400c8 --- /dev/null +++ b/src/m_gpg_info/GnuPGInfoGatheringModule.cpp @@ -0,0 +1,526 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GnuPGInfoGatheringModule.h" + +#include +#include +#include +#include + +// qt +#include +#include +#include +#include + +// c++ +#include + +#include "GpgInfo.h" + +template <> +struct fmt::formatter { + // Parses format specifications. + constexpr auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template + auto format(const QString &qstr, FormatContext &ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + QByteArray utf8_array = qstr.toUtf8(); + return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); + } +}; + +template <> +struct fmt::formatter { + // Parses format specifications. + constexpr auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template + auto format(const QByteArray &qarray, FormatContext &ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + return fmt::format_to(ctx.out(), "{}", qarray.constData()); + } +}; + +extern auto CalculateBinaryChacksum(const QString &path) + -> std::optional; + +extern void GetGpgComponentInfos(void *, int, const char *, const char *); + +extern void GetGpgDirectoryInfos(void *, int, const char *, const char *); + +extern void GetGpgOptionInfos(void *, int, const char *, const char *); + +using Context = struct { + QString gpgme_version; + QString gpgconf_path; + GpgComponentInfo component_info; +}; + +auto GFGetModuleGFSDKVersion() -> const char * { + return GFModuleStrDup(GF_SDK_VERSION_STR); +} + +auto GFGetModuleQtEnvVersion() -> const char * { + return GFModuleStrDup(QT_VERSION_STR); +} + +auto GFGetModuleID() -> const char * { + return GFModuleStrDup("com.bktus.gpgfrontend.module.gnupg_info_gathering"); +} + +auto GFGetModuleVersion() -> const char * { return GFModuleStrDup("1.0.0"); } + +auto GFGetModuleMetaData() -> GFModuleMetaData * { + auto *p_meta = static_cast( + GFAllocateMemory(sizeof(GFModuleMetaData))); + auto *h_meta = p_meta; + + p_meta->key = "Name"; + p_meta->value = "GatherGnupgInfo"; + p_meta->next = static_cast( + GFAllocateMemory(sizeof(GFModuleMetaData))); + p_meta = p_meta->next; + + p_meta->key = "Description"; + p_meta->value = "Try gathering gnupg informations"; + p_meta->next = static_cast( + GFAllocateMemory(sizeof(GFModuleMetaData))); + p_meta = p_meta->next; + + p_meta->key = "Author"; + p_meta->value = "Saturneric"; + p_meta->next = nullptr; + return h_meta; +} + +auto GFRegisterModule() -> int { + GFModuleLogDebug("gnupg info gathering module registering"); + return 0; +} + +auto GFActiveModule() -> int { + GFModuleLogDebug("gnupg info gathering module activating"); + GFModuleListenEvent(GFGetModuleID(), + GFModuleStrDup("REQUEST_GATHERING_GNUPG_INFO")); + return 0; +} + +auto GFExecuteModule(GFModuleEvent *event) -> int { + GFModuleLogDebug( + fmt::format("gnupg info gathering module executing, event id: {}", + event->id) + .c_str()); + + GFModuleLogDebug("start to load extra info at module gnupginfogathering..."); + + const auto *const gpgme_version = GFModuleRetrieveRTValueOrDefault( + GFModuleStrDup("core"), GFModuleStrDup("gpgme.version"), + GFModuleStrDup("0.0.0")); + GFModuleLogDebug( + fmt::format("got gpgme version from rt: {}", gpgme_version).c_str()); + + const auto *const gpgconf_path = GFModuleRetrieveRTValueOrDefault( + GFModuleStrDup("core"), GFModuleStrDup("gpgme.ctx.gpgconf_path"), + GFModuleStrDup("")); + GFModuleLogDebug( + fmt::format("got gpgconf path from rt: {}", gpgconf_path).c_str()); + + auto context = Context{gpgme_version, gpgconf_path}; + + // get all components + const char *argv[] = {GFModuleStrDup("--list-components")}; + GFExecuteCommandSync(gpgconf_path, 1, argv, GetGpgComponentInfos, &context); + GFModuleLogDebug("load gnupg component info done."); + +#ifdef QT5_BUILD + QVector exec_contexts; +#else + QList exec_contexts; +#endif + + const char **argv_0 = + static_cast(GFAllocateMemory(sizeof(const char *))); + argv_0[0] = GFModuleStrDup("--list-dirs"); + + exec_contexts.push_back( + {gpgconf_path, 1, argv_0, GetGpgDirectoryInfos, nullptr}); + + char **components_c_array; + int ret = GFModuleListRTChildKeys( + GFGetModuleID(), GFModuleStrDup("gnupg.components"), &components_c_array); + if (components_c_array == nullptr || ret == 0) return -1; + + QStringList components; + auto *p_a = components_c_array; + for (int i = 0; i < ret; i++) components.append(QString::fromUtf8(p_a[i])); + + for (const auto &component : components) { + const auto *component_info_json = GFModuleRetrieveRTValueOrDefault( + GFGetModuleID(), + GFModuleStrDup(QString("gnupg.components.%1").arg(component).toUtf8()), + nullptr); + + if (component_info_json == nullptr) continue; + + auto jsonlized_component_info = + QJsonDocument::fromJson(component_info_json); + assert(jsonlized_component_info.isObject()); + + auto component_info = GpgComponentInfo(jsonlized_component_info.object()); + GFModuleLogDebug(fmt::format("gpgconf check options ready, " + "component: {}", + component_info.name) + .c_str()); + + if (component_info.name == "gpgme" || component_info.name == "gpgconf") { + continue; + } + + auto *context = new (GFAllocateMemory(sizeof(Context))) + Context{gpgme_version, gpgconf_path, component_info}; + + const char **argv_0 = + static_cast(GFAllocateMemory(sizeof(const char *) * 2)); + argv_0[0] = GFModuleStrDup("--list-options"), + argv_0[1] = GFModuleStrDup(component_info.name.toUtf8()); + exec_contexts.push_back( + {gpgconf_path, 2, argv_0, GetGpgOptionInfos, context}); + } + + GFExecuteCommandBatchSync(static_cast(exec_contexts.size()), + exec_contexts.constData()); + GFModuleUpsertRTValueBool(GFGetModuleID(), + GFModuleStrDup("gnupg.gathering_done"), 1); + + char **event_argv = + static_cast(GFAllocateMemory(sizeof(char **) * 1)); + event_argv[0] = GFModuleStrDup("0"); + + GFModuleTriggerModuleEventCallback(event, GFGetModuleID(), 1, event_argv); + + GFModuleLogDebug("gnupg external info gathering done"); + return 0; +} + +auto GFDeactiveModule() -> int { return 0; } + +auto GFUnregisterModule() -> int { + GFModuleLogDebug("gnupg info gathering module unregistering"); + return 0; +} + +auto CalculateBinaryChacksum(const QString &path) -> std::optional { + // check file info and access rights + QFileInfo info(path); + if (!info.exists() || !info.isFile() || !info.isReadable()) { + GFModuleLogError(fmt::format("get info for file {} error, exists: {}", + info.filePath(), info.exists()) + .c_str()); + return {}; + } + + // open and read file + QFile f(info.filePath()); + if (!f.open(QIODevice::ReadOnly)) { + GFModuleLogError(fmt::format("open {} to calculate checksum error: {}", + path.toStdString(), + f.errorString().toStdString()) + .c_str()); + return {}; + } + + QCryptographicHash hash_sha(QCryptographicHash::Sha256); + + // read data by chunks + const qint64 buffer_size = 8192; // Define a suitable buffer size + while (!f.atEnd()) { + QByteArray const buffer = f.read(buffer_size); + if (buffer.isEmpty()) { + GFModuleLogError(fmt::format("error reading file {} during " + "checksum calculation", + path.toStdString()) + .c_str()); + return {}; + } + hash_sha.addData(buffer); + } + + // close the file + f.close(); + + // return the first 6 characters of the SHA-256 hash + // of the file + return QString(hash_sha.result().toHex()).left(6); +} + +void GetGpgComponentInfos(void *data, int exit_code, const char *out, + const char *err) { + auto *context = reinterpret_cast(data); + auto p_out = QString::fromUtf8(out); + auto p_err = QString::fromUtf8(err); + + GFModuleLogDebug(fmt::format("gpgconf components exit_code: {} " + "process stdout size: {}", + exit_code, p_out.size()) + .c_str()); + + if (exit_code != 0) { + GFModuleLogError(fmt::format("gpgconf execute error, process " + "stderr: {}, " + "process stdout: {}", + p_err, p_out) + .c_str()); + return; + } + + std::vector component_infos; + GpgComponentInfo c_i_gpgme; + c_i_gpgme.name = "gpgme"; + c_i_gpgme.desc = "GPG Made Easy"; + c_i_gpgme.version = context->gpgme_version; + c_i_gpgme.path = "Embedded In"; + c_i_gpgme.binary_checksum = "/"; + + GpgComponentInfo c_i_gpgconf; + c_i_gpgconf.name = "gpgconf"; + c_i_gpgconf.desc = "GPG Configure"; + c_i_gpgconf.version = "/"; + c_i_gpgconf.path = context->gpgconf_path; + auto gpgconf_binary_checksum = CalculateBinaryChacksum(context->gpgconf_path); + c_i_gpgconf.binary_checksum = + (gpgconf_binary_checksum.has_value() ? gpgconf_binary_checksum.value() + : QString("/")); + + component_infos.push_back(c_i_gpgme); + component_infos.push_back(c_i_gpgconf); + + auto const jsonlized_gpgme_component_info = c_i_gpgme.Json(); + auto const jsonlized_gpgconf_component_info = c_i_gpgconf.Json(); + GFModuleUpsertRTValue( + GFGetModuleID(), GFModuleStrDup("gnupg.components.gpgme"), + GFModuleStrDup(QJsonDocument(jsonlized_gpgme_component_info).toJson())); + GFModuleUpsertRTValue( + GFGetModuleID(), GFModuleStrDup("gnupg.components.gpgconf"), + GFModuleStrDup(QJsonDocument(jsonlized_gpgconf_component_info).toJson())); + + auto line_split_list = p_out.split("\n"); + + for (const auto &line : line_split_list) { + auto info_split_list = line.split(":"); + + if (info_split_list.size() != 3) continue; + + auto component_name = info_split_list[0].trimmed(); + auto component_desc = info_split_list[1].trimmed(); + auto component_path = info_split_list[2].trimmed(); + +#ifdef WINDOWS + // replace some special substrings on windows + // platform + component_path.replace("%3a", ":"); +#endif + + auto binary_checksum = CalculateBinaryChacksum(component_path); + + GFModuleLogDebug( + fmt::format("gnupg component name: {} desc: " + "{} checksum: {} path: {} ", + component_name, component_desc, + binary_checksum.has_value() ? binary_checksum.value() : "/", + component_path) + .c_str()); + + QString version = "/"; + + if (component_name == "gpg") { + version = GFModuleRetrieveRTValueOrDefault( + GFModuleStrDup("core"), GFModuleStrDup("gpgme.ctx.gnupg_version"), + GFModuleStrDup("2.0.0")); + } + if (component_name == "gpg-agent") { + GFModuleUpsertRTValue(GFGetModuleID(), + GFModuleStrDup("gnupg.gpg_agent_path"), + GFModuleStrDup(QString(component_path).toUtf8())); + } + if (component_name == "dirmngr") { + GFModuleUpsertRTValue(GFGetModuleID(), + GFModuleStrDup("gnupg.dirmngr_path"), + GFModuleStrDup(QString(component_path).toUtf8())); + } + if (component_name == "keyboxd") { + GFModuleUpsertRTValue(GFGetModuleID(), + GFModuleStrDup("gnupg.keyboxd_path"), + GFModuleStrDup(QString(component_path).toUtf8())); + } + + { + GpgComponentInfo c_i; + c_i.name = component_name; + c_i.desc = component_desc; + c_i.version = version; + c_i.path = component_path; + c_i.binary_checksum = + (binary_checksum.has_value() ? binary_checksum.value() + : QString("/")); + + auto const jsonlized_component_info = c_i.Json(); + GFModuleUpsertRTValue( + GFGetModuleID(), + GFModuleStrDup( + QString("gnupg.components.%1").arg(component_name).toUtf8()), + GFModuleStrDup(QJsonDocument(jsonlized_component_info).toJson())); + + component_infos.push_back(c_i); + } + + GFModuleLogDebug("load gnupg component info actually done."); + } +} + +void GetGpgDirectoryInfos(void *, int exit_code, const char *out, + const char *err) { + if (exit_code != 0) return; + + auto p_out = QString::fromUtf8(out); + auto p_err = QString::fromUtf8(err); + auto line_split_list = p_out.split("\n"); + + for (const auto &line : line_split_list) { + auto info_split_list = line.split(":"); + GFModuleLogDebug(fmt::format("gpgconf direcrotries info line: " + "{} info size: {}", + line, info_split_list.size()) + .c_str()); + + if (info_split_list.size() != 2) continue; + + auto configuration_name = info_split_list[0].trimmed(); + auto configuration_value = info_split_list[1].trimmed(); + +#ifdef WINDOWS + // replace some special substrings on windows + // platform + configuration_value.replace("%3a", ":"); +#endif + + // record gnupg home path + if (configuration_name == "homedir") { + GFModuleUpsertRTValue(GFGetModuleID(), GFModuleStrDup("gnupg.home_path"), + GFModuleStrDup(configuration_value.toUtf8())); + } + + GFModuleUpsertRTValue( + GFGetModuleID(), + GFModuleStrDup( + QString("gnupg.dirs.%1").arg(configuration_name).toUtf8()), + GFModuleStrDup(configuration_value.toUtf8())); + } +} + +void GetGpgOptionInfos(void *data, int exit_code, const char *out, + const char *err) { + if (exit_code != 0) return; + + auto p_out = QString::fromUtf8(out); + auto p_err = QString::fromUtf8(err); + auto *context = reinterpret_cast(data); + auto component_name = context->component_info.name; + + GFModuleLogDebug(fmt::format("gpgconf {} avaliable options " + "exit_code: {} process stdout " + "size: {} ", + component_name, exit_code, p_out.size()) + .c_str()); + + std::vector options_infos; + + auto line_split_list = p_out.split("\n"); + + for (const auto &line : line_split_list) { + auto info_split_list = line.split(":"); + + GFModuleLogDebug(fmt::format("component {} avaliable options " + "line: {} info size: {}", + component_name, line, info_split_list.size()) + .c_str()); + + if (info_split_list.size() < 10) continue; + + // The format of each line is: + // name:flags:level:description:type:alt-type:argname:default:argdef:value + + auto option_name = info_split_list[0].trimmed(); + auto option_flags = info_split_list[1].trimmed(); + auto option_level = info_split_list[2].trimmed(); + auto option_desc = info_split_list[3].trimmed(); + auto option_type = info_split_list[4].trimmed(); + auto option_alt_type = info_split_list[5].trimmed(); + auto option_argname = info_split_list[6].trimmed(); + auto option_default = info_split_list[7].trimmed(); + auto option_argdef = info_split_list[8].trimmed(); + auto option_value = info_split_list[9].trimmed(); + + GpgOptionsInfo info; + info.name = option_name; + info.flags = option_flags; + info.level = option_level; + info.description = option_desc; + info.type = option_type; + info.alt_type = option_alt_type; + info.argname = option_argname; + info.default_value = option_default; + info.argdef = option_argdef; + info.value = option_value; + + auto const jsonlized_option_info = info.Json(); + GFModuleUpsertRTValue( + GFGetModuleID(), + GFModuleStrDup(QString("gnupg.components.%1.options.%2") + .arg(component_name) + .arg(option_name) + .toUtf8()), + GFModuleStrDup(QJsonDocument(jsonlized_option_info).toJson())); + options_infos.push_back(info); + } + + context->~Context(); + GFFreeMemory(context); +} diff --git a/src/m_gpg_info/GnuPGInfoGatheringModule.h b/src/m_gpg_info/GnuPGInfoGatheringModule.h new file mode 100644 index 0000000..35ee4ac --- /dev/null +++ b/src/m_gpg_info/GnuPGInfoGatheringModule.h @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include + +#include "GFModuleExport.h" + +extern "C" { + +auto GF_MODULE_EXPORT GFGetModuleGFSDKVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleQtEnvVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleID() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleMetaData() -> GFModuleMetaData *; + +auto GF_MODULE_EXPORT GFRegisterModule() -> int; + +auto GF_MODULE_EXPORT GFActiveModule() -> int; + +auto GF_MODULE_EXPORT GFExecuteModule(GFModuleEvent *) -> int; + +auto GF_MODULE_EXPORT GFDeactiveModule() -> int; + +auto GF_MODULE_EXPORT GFUnregisterModule() -> int; +}; diff --git a/src/m_gpg_info/GpgInfo.cpp b/src/m_gpg_info/GpgInfo.cpp new file mode 100644 index 0000000..680f4a8 --- /dev/null +++ b/src/m_gpg_info/GpgInfo.cpp @@ -0,0 +1,79 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GpgInfo.h" + +GpgOptionsInfo::GpgOptionsInfo(const QJsonObject &j) { + if (const auto v = j["name"]; v.isString()) name = v.toString(); + if (const auto v = j["flags"]; v.isString()) flags = v.toString(); + if (const auto v = j["level"]; v.isString()) level = v.toString(); + if (const auto v = j["description"]; v.isString()) description = v.toString(); + if (const auto v = j["type"]; v.isString()) type = v.toString(); + if (const auto v = j["alt_type"]; v.isString()) alt_type = v.toString(); + if (const auto v = j["argname"]; v.isString()) argname = v.toString(); + if (const auto v = j["default_value"]; v.isString()) { + default_value = v.toString(); + } + if (const auto v = j["argdef"]; v.isString()) argdef = v.toString(); + if (const auto v = j["value"]; v.isString()) value = v.toString(); +} + +auto GpgOptionsInfo::Json() const -> QJsonObject { + QJsonObject j; + j["name"] = name; + j["flags"] = flags; + j["level"] = level; + j["description"] = description; + j["type"] = type; + j["alt_type"] = alt_type; + j["argname"] = argname; + j["default_value"] = default_value; + j["argdef"] = argdef; + j["value"] = value; + return j; +} + +auto GpgComponentInfo::Json() const -> QJsonObject { + QJsonObject j; + j["name"] = name; + j["desc"] = desc; + j["version"] = version; + j["path"] = path; + j["binary_checksum"] = binary_checksum; + return j; +} + +GpgComponentInfo::GpgComponentInfo(const QJsonObject &j) { + if (const auto v = j["name"]; v.isString()) name = v.toString(); + if (const auto v = j["desc"]; v.isString()) desc = v.toString(); + if (const auto v = j["version"]; v.isString()) version = v.toString(); + if (const auto v = j["path"]; v.isString()) path = v.toString(); + if (const auto v = j["binary_checksum"]; v.isString()) { + binary_checksum = v.toString(); + } +} diff --git a/src/m_gpg_info/GpgInfo.h b/src/m_gpg_info/GpgInfo.h new file mode 100644 index 0000000..1aacc20 --- /dev/null +++ b/src/m_gpg_info/GpgInfo.h @@ -0,0 +1,88 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include +#include +#include + +/** + * @brief Use to record some info about gnupg + * + */ +class GpgInfo { + public: + QString GnuPGHomePath; ///< value of ---homedir + + std::map> ComponentsInfo; ///< + std::map> ConfigurationsInfo; ///< + std::map> OptionsInfo; ///< + std::map> AvailableOptionsInfo; ///< +}; + +/** + * @brief Use to record some info about gnupg components + * + */ +struct GpgComponentInfo { + QString name; + QString desc; + QString version; + QString path; + QString binary_checksum; + + GpgComponentInfo() = default; + + explicit GpgComponentInfo(const QJsonObject &j); + + [[nodiscard]] auto Json() const -> QJsonObject; +}; + +/** + * The format of each line is: + * name:flags:level:description:type:alt-type:argname:default:argdef:value + */ +struct GpgOptionsInfo { + QString name; + QString flags; + QString level; + QString description; + QString type; + QString alt_type; + QString argname; + QString default_value; + QString argdef; + QString value; + + GpgOptionsInfo() = default; + + explicit GpgOptionsInfo(const QJsonObject &j); + + [[nodiscard]] auto Json() const -> QJsonObject; +}; diff --git a/src/m_gpg_info/QtLoggerFmt.h b/src/m_gpg_info/QtLoggerFmt.h new file mode 100644 index 0000000..2399746 --- /dev/null +++ b/src/m_gpg_info/QtLoggerFmt.h @@ -0,0 +1,68 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include + +#include + +template <> +struct fmt::formatter { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template + auto format(const QString& qstr, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + QByteArray utf8_array = qstr.toUtf8(); + return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); + } +}; + +template <> +struct fmt::formatter { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template + auto format(const QByteArray& qarray, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + return fmt::format_to(ctx.out(), "{}", qarray.constData()); + } +}; diff --git a/src/m_ver_check/CMakeLists.txt b/src/m_ver_check/CMakeLists.txt new file mode 100644 index 0000000..58edcd7 --- /dev/null +++ b/src/m_ver_check/CMakeLists.txt @@ -0,0 +1,68 @@ +# Copyright (C) 2021 Saturneric +# +# This file is part of GpgFrontend. +# +# GpgFrontend is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GpgFrontend is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GpgFrontend. If not, see . +# +# The initial version of the source code is inherited from +# the gpg4usb project, which is under GPL-3.0-or-later. +# +# All the source code of GpgFrontend was modified and released by +# Saturneric starting on May 12, 2021. +# +# SPDX-License-Identifier: GPL-3.0-or-later + +# com.bktus.gpgfrontend.module.integrated.version_checking + +aux_source_directory(. MODULE_SOURCE_FILES) + +# define libgpgfrontend_module +add_library(mod_ver_check SHARED ${MODULE_SOURCE_FILES}) + +target_include_directories(mod_ver_check PRIVATE + ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) + +# install dir +install(TARGETS mod_ver_check + LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/modules") + +# link sdk +target_link_libraries(mod_ver_check PRIVATE + gpgfrontend_module_sdk) + +if(GPGFRONTEND_QT5_BUILD) + # link Qt + target_link_libraries(mod_ver_check PUBLIC Qt5::Core Qt5::Network Qt5::Widgets) +else() + # link Qt + target_link_libraries(mod_ver_check PUBLIC Qt6::Core Qt6::Network Qt6::Widgets) +endif() + +# using std c++ 17 +target_compile_features(mod_ver_check PRIVATE cxx_std_17) + +# ui +set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_AUTOUIC_SEARCH_PATHS} ${CMAKE_CURRENT_SOURCE_DIR}/ui) + +# i18n +set(LOCALE_TS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/ts) +set(TS_FILES "${LOCALE_TS_PATH}/ModuleVersionChecking.en_US.ts" + "${LOCALE_TS_PATH}/ModuleVersionChecking.de_DE.ts" + "${LOCALE_TS_PATH}/ModuleVersionChecking.fr_FR.ts" + "${LOCALE_TS_PATH}/ModuleVersionChecking.zh_CN.ts") +qt_add_translations(mod_ver_check + RESOURCE_PREFIX "/i18n" + TS_FILES ${TS_FILES} + SOURCES ${MODULE_SOURCE_FILES} + INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/src/m_ver_check/QtLoggerFmt.h b/src/m_ver_check/QtLoggerFmt.h new file mode 100644 index 0000000..2399746 --- /dev/null +++ b/src/m_ver_check/QtLoggerFmt.h @@ -0,0 +1,68 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include + +#include + +template <> +struct fmt::formatter { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template + auto format(const QString& qstr, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + QByteArray utf8_array = qstr.toUtf8(); + return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); + } +}; + +template <> +struct fmt::formatter { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template + auto format(const QByteArray& qarray, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + return fmt::format_to(ctx.out(), "{}", qarray.constData()); + } +}; diff --git a/src/m_ver_check/SoftwareVersion.cpp b/src/m_ver_check/SoftwareVersion.cpp new file mode 100644 index 0000000..cd86419 --- /dev/null +++ b/src/m_ver_check/SoftwareVersion.cpp @@ -0,0 +1,100 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "SoftwareVersion.h" + +#include +#include +#include +#include + +#include + +template <> +struct fmt::formatter { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template + auto format(const QString& qstr, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + QByteArray utf8_array = qstr.toUtf8(); + return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); + } +}; + +template <> +struct fmt::formatter { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template + auto format(const QByteArray& qarray, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + return fmt::format_to(ctx.out(), "{}", qarray.constData()); + } +}; + +auto SoftwareVersion::NeedUpgrade() const -> bool { + GFModuleLogDebug( + fmt::format( + "compair version current {} latest {}, result {}", current_version, + latest_version, + GFCompareSoftwareVersion(GFModuleStrDup(current_version.toUtf8()), + GFModuleStrDup(latest_version.toUtf8()))) + .c_str()); + + GFModuleLogDebug(fmt::format("load done: {}, pre-release: {}, draft: {}", + loading_done, + latest_prerelease_version_from_remote, + latest_draft_from_remote) + .c_str()); + return loading_done && !latest_prerelease_version_from_remote && + !latest_draft_from_remote && + GFCompareSoftwareVersion(GFModuleStrDup(current_version.toUtf8()), + GFModuleStrDup(latest_version.toUtf8())) < 0; +} + +auto SoftwareVersion::VersionWithdrawn() const -> bool { + return loading_done && !current_version_publish_in_remote && + current_version_is_a_prerelease && !current_version_is_drafted; +} + +auto SoftwareVersion::CurrentVersionReleased() const -> bool { + return loading_done && current_version_publish_in_remote; +} \ No newline at end of file diff --git a/src/m_ver_check/SoftwareVersion.h b/src/m_ver_check/SoftwareVersion.h new file mode 100644 index 0000000..6b05d41 --- /dev/null +++ b/src/m_ver_check/SoftwareVersion.h @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include + +/** + * @brief + * + */ +struct SoftwareVersion { + QString latest_version; ///< + QString current_version; ///< + bool latest_prerelease_version_from_remote = false; ///< + bool latest_draft_from_remote = false; ///< + bool current_version_is_a_prerelease = false; ///< + bool current_version_is_drafted = false; ///< + bool loading_done = false; ///< + bool current_version_publish_in_remote = false; ///< + QString publish_date; ///< + QString release_note; ///< + + /** + * @brief + * + * @return true + * @return false + */ + [[nodiscard]] auto InfoValid() const -> bool { return loading_done; } + + /** + * @brief + * + * @return true + * @return false + */ + [[nodiscard]] auto NeedUpgrade() const -> bool; + + /** + * @brief + * + * @return true + * @return false + */ + [[nodiscard]] auto VersionWithdrawn() const -> bool; + + /** + * @brief + * + * @return true + * @return false + */ + [[nodiscard]] auto CurrentVersionReleased() const -> bool; + + private: + static auto version_compare(const QString& a, const QString& b) -> int; +}; diff --git a/src/m_ver_check/UpdateTab.cpp b/src/m_ver_check/UpdateTab.cpp new file mode 100644 index 0000000..ea38780 --- /dev/null +++ b/src/m_ver_check/UpdateTab.cpp @@ -0,0 +1,171 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "UpdateTab.h" + +#include "GFSDKBasic.h" +#include "GFSDKLog.h" +#include "GFSDKModule.h" +#include "VersionCheckTask.h" +#include "VersionCheckingModule.h" + +UpdateTab::UpdateTab(QWidget* parent) : QWidget(parent) { + auto* layout = new QGridLayout(); + + current_version_ = GFProjectVersion(); + + auto* tips_label = new QLabel(); + tips_label->setText( + "
" + + tr("It is recommended that you always check the version " + "of GpgFrontend and upgrade to the latest version.") + + "
" + + tr("New versions not only represent new features, but " + "also often represent functional and security fixes.") + + "
"); + tips_label->setWordWrap(true); + + current_version_label_ = new QLabel(); + current_version_label_->setText("
" + tr("Current Version") + + tr(": ") + "" + current_version_ + + "
"); + current_version_label_->setWordWrap(true); + + latest_version_label_ = new QLabel(); + latest_version_label_->setWordWrap(true); + + upgrade_label_ = new QLabel(); + upgrade_label_->setWordWrap(true); + upgrade_label_->setOpenExternalLinks(true); + upgrade_label_->setHidden(true); + + pb_ = new QProgressBar(); + pb_->setRange(0, 0); + pb_->setTextVisible(false); + + layout->addWidget(tips_label, 1, 0, 1, -1); + layout->addWidget(current_version_label_, 2, 0, 1, -1); + layout->addWidget(latest_version_label_, 3, 0, 1, -1); + layout->addWidget(upgrade_label_, 4, 0, 1, -1); + layout->addWidget(pb_, 5, 0, 1, -1); + layout->addItem( + new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Fixed), 2, 1, + 1, 1); + + setLayout(layout); +} + +void UpdateTab::showEvent(QShowEvent* event) { + QWidget::showEvent(event); + GFModuleLogDebug("loading version loading info from rt"); + + auto is_loading_done = GFModuleRetrieveRTValueOrDefaultBool( + GFGetModuleID(), GFModuleStrDup("version.loading_done"), 0); + + if (is_loading_done == 0) { + auto* task = new VersionCheckTask(); + QObject::connect( + task, &VersionCheckTask::SignalUpgradeVersion, QThread::currentThread(), + [this](const SoftwareVersion&) { slot_show_version_status(); }); + QObject::connect(task, &VersionCheckTask::SignalUpgradeVersion, task, + &QObject::deleteLater); + task->Run(); + + } else { + slot_show_version_status(); + } +} + +void UpdateTab::slot_show_version_status() { + GFModuleLogDebug("loading version info from rt"); + this->pb_->setHidden(true); + + auto is_loading_done = GFModuleRetrieveRTValueOrDefaultBool( + GFGetModuleID(), GFModuleStrDup("version.loading_done"), 0); + + if (is_loading_done == 0) { + GFModuleLogDebug("version info loading haven't been done yet."); + return; + } + + auto is_need_upgrade = GFModuleRetrieveRTValueOrDefaultBool( + GFGetModuleID(), GFModuleStrDup("version.need_upgrade"), 0); + + auto is_current_a_withdrawn_version = GFModuleRetrieveRTValueOrDefaultBool( + GFGetModuleID(), GFModuleStrDup("version.current_a_withdrawn_version"), + 0); + + auto is_current_version_released = GFModuleRetrieveRTValueOrDefaultBool( + GFGetModuleID(), GFModuleStrDup("version.current_version_released"), 0); + + QString const latest_version = GFModuleRetrieveRTValueOrDefault( + GFGetModuleID(), GFModuleStrDup("version.latest_version"), + GFModuleStrDup("")); + + latest_version_label_->setText("
" + + tr("Latest Version From Github") + ": " + + latest_version + "
"); + + if (is_need_upgrade != 0) { + upgrade_label_->setText( + "
" + + tr("The current version is less than the latest version on " + "github.") + + "
" + tr("Please click") + + " " + + tr("Here") + " " + tr("to download the latest stable version.") + + "
"); + upgrade_label_->show(); + } else if (is_current_a_withdrawn_version != 0) { + upgrade_label_->setText( + "
" + + tr("This version has serious problems and has been withdrawn. " + "Please stop using it immediately.") + + "
" + tr("Please click") + + " " + + tr("Here") + " " + tr("to download the latest stable version.") + + "
"); + upgrade_label_->show(); + } else if (is_current_version_released == 0) { + upgrade_label_->setText( + "
" + + tr("This version has not been released yet, it may be a beta " + "version. If you are not a tester and care about version " + "stability, please do not use this version.") + + "
" + tr("Please click") + + " " + + tr("Here") + " " + tr("to download the latest stable version.") + + "
"); + upgrade_label_->show(); + } +} + +auto UpdateTabFactory(const char* id) -> void* { return new UpdateTab(); } \ No newline at end of file diff --git a/src/m_ver_check/UpdateTab.h b/src/m_ver_check/UpdateTab.h new file mode 100644 index 0000000..fd48f05 --- /dev/null +++ b/src/m_ver_check/UpdateTab.h @@ -0,0 +1,74 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include + +/** + * @brief Class containing the main tab of about dialog + * + */ +class UpdateTab : public QWidget { + Q_OBJECT + + QLabel* current_version_label_; ///< + QLabel* latest_version_label_; ///< + QLabel* upgrade_label_; ///< + QProgressBar* pb_; ///< + QString current_version_; ///< + + public: + /** + * @brief Construct a new Update Tab object + * + * @param parent + */ + explicit UpdateTab(QWidget* parent = nullptr); + + protected: + void showEvent(QShowEvent* event) override; + + private slots: + /** + * @brief + * + * @param version + */ + void slot_show_version_status(); + + signals: + /** + * @brief + * + * @param data + */ + void SignalReplyFromUpdateServer(QByteArray data); +}; + +auto UpdateTabFactory(const char* id) -> void*; \ No newline at end of file diff --git a/src/m_ver_check/VersionCheckTask.cpp b/src/m_ver_check/VersionCheckTask.cpp new file mode 100644 index 0000000..3455ddc --- /dev/null +++ b/src/m_ver_check/VersionCheckTask.cpp @@ -0,0 +1,221 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "VersionCheckTask.h" + +#include +#include +#include + +#include +#include + +// spdlog +#include + +#include "LogFormatter.h" +#include "SoftwareVersion.h" +#include "VersionCheckingModule.h" + +VersionCheckTask::VersionCheckTask() + : network_manager_(new QNetworkAccessManager(this)), + current_version_(GFProjectVersion()) { + qRegisterMetaType("SoftwareVersion"); + version_.current_version = current_version_; +} + +auto VersionCheckTask::Run() -> int { + GFModuleLogDebug( + fmt::format("current project version: {}", current_version_).c_str()); + QString latest_version_url = + "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; + + QNetworkRequest latest_request(latest_version_url); + latest_request.setHeader(QNetworkRequest::UserAgentHeader, + GFHttpRequestUserAgent()); + + latest_reply_ = network_manager_->get(latest_request); + connect(latest_reply_, &QNetworkReply::finished, this, + &VersionCheckTask::slot_parse_latest_version_info); + return 0; +} + +void VersionCheckTask::slot_parse_latest_version_info() { + if (latest_reply_ == nullptr) { + version_.latest_version = current_version_; + version_.loading_done = false; + } else if (latest_reply_->error() != QNetworkReply::NoError) { + GFModuleLogError(fmt::format("latest version request error: ", + latest_reply_->errorString()) + .c_str()); + version_.latest_version = current_version_; + } else { + latest_reply_bytes_ = latest_reply_->readAll(); + auto latest_reply_json = QJsonDocument::fromJson(latest_reply_bytes_); + + if (latest_reply_json.isObject()) { + QString latest_version = latest_reply_json["tag_name"].toString(); + + QRegularExpression re(R"(^[vV](\d+\.)?(\d+\.)?(\*|\d+))"); + auto version_match = re.match(latest_version); + if (version_match.hasMatch()) { + latest_version = version_match.captured(0); + GFModuleLogInfo(fmt::format("latest released version from github: {}", + latest_version) + .c_str()); + } else { + latest_version = current_version_; + GFModuleLogWarn( + fmt::format("latest version unknown, set to current version: {}", + current_version_) + .c_str()); + } + + bool prerelease = latest_reply_json["prerelease"].toBool(); + bool draft = latest_reply_json["draft"].toBool(); + auto publish_date = latest_reply_json["published_at"].toString(); + auto release_note = latest_reply_json["body"].toString(); + version_.latest_version = latest_version; + version_.latest_prerelease_version_from_remote = prerelease; + version_.latest_draft_from_remote = draft; + version_.publish_date = publish_date; + version_.release_note = release_note; + } else { + GFModuleLogWarn(fmt::format("cannot parse data got from github: {}", + latest_reply_bytes_) + .c_str()); + } + } + + if (latest_reply_ != nullptr) { + latest_reply_->deleteLater(); + } + + try { + QString current_version_url = + "https://api.github.com/repos/saturneric/gpgfrontend/releases/tags/" + + current_version_; + GFModuleLogDebug( + fmt::format("current version info query url: {}", current_version_url) + .c_str()); + + QNetworkRequest current_request(current_version_url); + current_request.setHeader(QNetworkRequest::UserAgentHeader, + GFHttpRequestUserAgent()); + + current_reply_ = network_manager_->get(current_request); + + connect(current_reply_, &QNetworkReply::finished, this, + &VersionCheckTask::slot_parse_current_version_info); + } catch (...) { + GFModuleLogError("current version request create error"); + } +} + +void VersionCheckTask::slot_parse_current_version_info() { + if (current_reply_ == nullptr) { + // loading done + version_.loading_done = false; + + } else if (current_reply_->error() != QNetworkReply::NoError) { + GFModuleLogError(fmt::format("current version request network error: {}", + current_reply_->errorString()) + .c_str()); + + // loading done + version_.loading_done = true; + version_.current_version_publish_in_remote = false; + } else { + version_.current_version_publish_in_remote = true; + current_reply_bytes_ = current_reply_->readAll(); + auto current_reply_json = QJsonDocument::fromJson(current_reply_bytes_); + + if (current_reply_json.isObject()) { + bool current_prerelease = current_reply_json["prerelease"].toBool(); + bool current_draft = current_reply_json["draft"].toBool(); + version_.latest_prerelease_version_from_remote = current_prerelease; + version_.latest_draft_from_remote = current_draft; + // loading done + version_.loading_done = true; + } else { + GFModuleLogWarn(fmt::format("cannot parse data got from github: {}", + current_reply_bytes_) + .c_str()); + } + } + + GFModuleLogDebug(fmt::format("current version parse done: {}", + version_.current_version_publish_in_remote) + .c_str()); + + if (current_reply_ != nullptr) current_reply_->deleteLater(); + + slot_fill_grt_with_version_info(version_); + emit SignalUpgradeVersion(version_); +} + +void VersionCheckTask::slot_fill_grt_with_version_info( + const SoftwareVersion &version) { + GFModuleLogDebug("filling software information info in rt..."); + + GFModuleUpsertRTValue(GFGetModuleID(), + GFModuleStrDup("version.current_version"), + GFModuleStrDup(version.current_version.toUtf8())); + GFModuleUpsertRTValue(GFGetModuleID(), + GFModuleStrDup("version.latest_version"), + GFModuleStrDup(version.latest_version.toUtf8())); + GFModuleUpsertRTValueBool( + GFGetModuleID(), GFModuleStrDup("version.current_version_is_drafted"), + version.current_version_is_drafted ? 1 : 0); + GFModuleUpsertRTValueBool( + GFGetModuleID(), + GFModuleStrDup("version.current_version_is_a_prerelease"), + version.current_version_is_a_prerelease ? 1 : 0); + GFModuleUpsertRTValueBool( + GFGetModuleID(), + GFModuleStrDup("version.current_version_publish_in_remote"), + version.current_version_publish_in_remote ? 1 : 0); + GFModuleUpsertRTValueBool( + GFGetModuleID(), + GFModuleStrDup("version.latest_prerelease_version_from_remote"), + version.latest_prerelease_version_from_remote ? 1 : 0); + GFModuleUpsertRTValueBool(GFGetModuleID(), + GFModuleStrDup("version.need_upgrade"), + version.NeedUpgrade() ? 1 : 0); + GFModuleUpsertRTValueBool(GFGetModuleID(), + GFModuleStrDup("version.current_version_released"), + version.CurrentVersionReleased() ? 1 : 0); + GFModuleUpsertRTValueBool( + GFGetModuleID(), GFModuleStrDup("version.current_a_withdrawn_version"), + version.VersionWithdrawn() ? 1 : 0); + GFModuleUpsertRTValueBool(GFGetModuleID(), + GFModuleStrDup("version.loading_done"), + version.loading_done ? 1 : 0); + + GFModuleLogDebug("software information filled in rt"); +} diff --git a/src/m_ver_check/VersionCheckTask.h b/src/m_ver_check/VersionCheckTask.h new file mode 100644 index 0000000..b915be6 --- /dev/null +++ b/src/m_ver_check/VersionCheckTask.h @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include + +#include "SoftwareVersion.h" + +class QNetworkReply; +class QNetworkAccessManager; + +/** + * @brief + * + */ +class VersionCheckTask : public QObject { + Q_OBJECT + public: + /** + * @brief Construct a new Version Check Thread object + * + */ + VersionCheckTask(); + + /** + * @brief + * + * @return int + */ + auto Run() -> int; + + signals: + + /** + * @brief + * + * @param version + */ + void SignalUpgradeVersion(SoftwareVersion version); + + private slots: + + /** + * @brief + * + */ + void slot_parse_latest_version_info(); + + /** + * @brief + * + */ + void slot_parse_current_version_info(); + + /** + * @brief + * + */ + void slot_fill_grt_with_version_info(const SoftwareVersion&); + + private: + QByteArray latest_reply_bytes_; ///< + QByteArray current_reply_bytes_; ///< + QNetworkReply* latest_reply_ = nullptr; ///< latest version info reply + QNetworkReply* current_reply_ = nullptr; ///< current version info reply + QNetworkAccessManager* network_manager_; ///< + QString current_version_; + SoftwareVersion version_; +}; diff --git a/src/m_ver_check/VersionCheckingModule.cpp b/src/m_ver_check/VersionCheckingModule.cpp new file mode 100644 index 0000000..0b57a25 --- /dev/null +++ b/src/m_ver_check/VersionCheckingModule.cpp @@ -0,0 +1,115 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "VersionCheckingModule.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "GFModuleCommonUtils.hpp" +#include "SoftwareVersion.h" +#include "UpdateTab.h" +#include "VersionCheckTask.h" + +auto GFGetModuleGFSDKVersion() -> const char* { + return DUP(GF_SDK_VERSION_STR); +} + +auto GFGetModuleQtEnvVersion() -> const char* { return DUP(QT_VERSION_STR); } + +auto GFGetModuleID() -> const char* { + return DUP("com.bktus.gpgfrontend.module.version_checking"); +} + +auto GFGetModuleVersion() -> const char* { return DUP("1.0.0"); } + +auto GFGetModuleMetaData() -> GFModuleMetaData* { + return QMapToGFModuleMetaDataList( + {{"Name", "VersionChecking"}, + {"Description", "Try checking GpgFrontend version."}, + {"Author", "Saturneric"}}); +} + +auto GFRegisterModule() -> int { + MLogInfo("version checking module registering"); + return 0; +} + +auto GFActiveModule() -> int { + MLogInfo("version checking module activating"); + + GFModuleListenEvent(GFGetModuleID(), DUP("APPLICATION_LOADED")); + GFModuleListenEvent(GFGetModuleID(), DUP("CHECK_APPLICATION_VERSION")); + + GFUIMountEntry(DUP("AboutDialogTabs"), + QMapToMetaDataArray({{"TabTitle", "Update"}}), 1, + UpdateTabFactory); + + // load translations + QFile f( + QString(":/i18n/ModuleVersionChecking.%1.qm").arg(GFAppActiveLocale())); + if (f.exists() && f.open(QIODevice::ReadOnly)) { + auto f_n = f.fileName().toUtf8(); + MLogInfoS("version checking module loading, locale: %s, path: %s", + GFAppActiveLocale(), f_n.data()); + auto b = f.readAll(); + GFAppRegisterTranslator(AllocBufferAndCopy(b), b.size()); + } + return 0; +} + +auto GFExecuteModule(GFModuleEvent* event) -> int { + MLogInfoS("version checking module executing, event id: %s", event->id); + + auto* task = new VersionCheckTask(); + QObject::connect(task, &VersionCheckTask::SignalUpgradeVersion, + QThread::currentThread(), [event](const SoftwareVersion&) { + char** event_argv = static_cast( + GFAllocateMemory(sizeof(char**) * 1)); + event_argv[0] = DUP("0"); + + GFModuleTriggerModuleEventCallback(event, GFGetModuleID(), + 1, event_argv); + }); + QObject::connect(task, &VersionCheckTask::SignalUpgradeVersion, task, + &QObject::deleteLater); + task->Run(); + + return 0; +} + +auto GFDeactiveModule() -> int { return 0; } + +auto GFUnregisterModule() -> int { return 0; } \ No newline at end of file diff --git a/src/m_ver_check/VersionCheckingModule.h b/src/m_ver_check/VersionCheckingModule.h new file mode 100644 index 0000000..35ee4ac --- /dev/null +++ b/src/m_ver_check/VersionCheckingModule.h @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include + +#include "GFModuleExport.h" + +extern "C" { + +auto GF_MODULE_EXPORT GFGetModuleGFSDKVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleQtEnvVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleID() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleMetaData() -> GFModuleMetaData *; + +auto GF_MODULE_EXPORT GFRegisterModule() -> int; + +auto GF_MODULE_EXPORT GFActiveModule() -> int; + +auto GF_MODULE_EXPORT GFExecuteModule(GFModuleEvent *) -> int; + +auto GF_MODULE_EXPORT GFDeactiveModule() -> int; + +auto GF_MODULE_EXPORT GFUnregisterModule() -> int; +}; diff --git a/src/m_ver_check/ts/ModuleVersionChecking.de_DE.ts b/src/m_ver_check/ts/ModuleVersionChecking.de_DE.ts new file mode 100644 index 0000000..ad113a5 --- /dev/null +++ b/src/m_ver_check/ts/ModuleVersionChecking.de_DE.ts @@ -0,0 +1,68 @@ + + + + + UpdateTab + + + It is recommended that you always check the version of GpgFrontend and upgrade to the latest version. + Es wird empfohlen, immer die Version von GpgFrontend zu überprüfen und auf die neueste Version zu aktualisieren. + + + + New versions not only represent new features, but also often represent functional and security fixes. + Neue Versionen beinhalten nicht nur neue Funktionen, sondern stellen oft auch Funktions- und Sicherheitskorrekturen dar. + + + + Current Version + Aktuelle Version + + + + : + : + + + + Latest Version From Github + Neueste Version von Github + + + + The current version is less than the latest version on github. + + + + + + + Please click + + + + + + + Here + + + + + + + to download the latest stable version. + + + + + This version has serious problems and has been withdrawn. Please stop using it immediately. + + + + + This version has not been released yet, it may be a beta version. If you are not a tester and care about version stability, please do not use this version. + + + + diff --git a/src/m_ver_check/ts/ModuleVersionChecking.en_US.ts b/src/m_ver_check/ts/ModuleVersionChecking.en_US.ts new file mode 100644 index 0000000..6e4afc5 --- /dev/null +++ b/src/m_ver_check/ts/ModuleVersionChecking.en_US.ts @@ -0,0 +1,68 @@ + + + + + UpdateTab + + + It is recommended that you always check the version of GpgFrontend and upgrade to the latest version. + + + + + New versions not only represent new features, but also often represent functional and security fixes. + + + + + Current Version + + + + + : + + + + + Latest Version From Github + + + + + The current version is less than the latest version on github. + + + + + + + Please click + + + + + + + Here + + + + + + + to download the latest stable version. + + + + + This version has serious problems and has been withdrawn. Please stop using it immediately. + + + + + This version has not been released yet, it may be a beta version. If you are not a tester and care about version stability, please do not use this version. + + + + diff --git a/src/m_ver_check/ts/ModuleVersionChecking.fr_FR.ts b/src/m_ver_check/ts/ModuleVersionChecking.fr_FR.ts new file mode 100644 index 0000000..6e4afc5 --- /dev/null +++ b/src/m_ver_check/ts/ModuleVersionChecking.fr_FR.ts @@ -0,0 +1,68 @@ + + + + + UpdateTab + + + It is recommended that you always check the version of GpgFrontend and upgrade to the latest version. + + + + + New versions not only represent new features, but also often represent functional and security fixes. + + + + + Current Version + + + + + : + + + + + Latest Version From Github + + + + + The current version is less than the latest version on github. + + + + + + + Please click + + + + + + + Here + + + + + + + to download the latest stable version. + + + + + This version has serious problems and has been withdrawn. Please stop using it immediately. + + + + + This version has not been released yet, it may be a beta version. If you are not a tester and care about version stability, please do not use this version. + + + + diff --git a/src/m_ver_check/ts/ModuleVersionChecking.zh_CN.ts b/src/m_ver_check/ts/ModuleVersionChecking.zh_CN.ts new file mode 100644 index 0000000..6e4afc5 --- /dev/null +++ b/src/m_ver_check/ts/ModuleVersionChecking.zh_CN.ts @@ -0,0 +1,68 @@ + + + + + UpdateTab + + + It is recommended that you always check the version of GpgFrontend and upgrade to the latest version. + + + + + New versions not only represent new features, but also often represent functional and security fixes. + + + + + Current Version + + + + + : + + + + + Latest Version From Github + + + + + The current version is less than the latest version on github. + + + + + + + Please click + + + + + + + Here + + + + + + + to download the latest stable version. + + + + + This version has serious problems and has been withdrawn. Please stop using it immediately. + + + + + This version has not been released yet, it may be a beta version. If you are not a tester and care about version stability, please do not use this version. + + + + diff --git a/src/ver_check/CMakeLists.txt b/src/ver_check/CMakeLists.txt deleted file mode 100644 index 30a6faf..0000000 --- a/src/ver_check/CMakeLists.txt +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (C) 2021 Saturneric -# -# This file is part of GpgFrontend. -# -# GpgFrontend is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# GpgFrontend is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GpgFrontend. If not, see . -# -# The initial version of the source code is inherited from -# the gpg4usb project, which is under GPL-3.0-or-later. -# -# All the source code of GpgFrontend was modified and released by -# Saturneric starting on May 12, 2021. -# -# SPDX-License-Identifier: GPL-3.0-or-later - -# com.bktus.gpgfrontend.module.integrated.version_checking - -aux_source_directory(. INTEGRATED_MODULE_SOURCE) - -# define libgpgfrontend_module -add_library(mod_ver_check SHARED ${INTEGRATED_MODULE_SOURCE}) -set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GFModuleExport.h") -generate_export_header(mod_ver_check - BASE_NAME "GF_MODULE" - EXPORT_FILE_NAME "${_export_file}") - -target_include_directories(mod_ver_check PRIVATE - ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) - -# set output directory -set_target_properties(mod_ver_check PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - -install(TARGETS mod_ver_check - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") - -# link sdk -target_link_libraries(mod_ver_check PRIVATE - gpgfrontend_module_sdk) - -if(GPGFRONTEND_QT5_BUILD) - # link Qt - target_link_libraries(mod_ver_check PUBLIC Qt5::Core Qt5::Network) -else() - # link Qt - target_link_libraries(mod_ver_check PUBLIC Qt6::Core Qt6::Network) -endif() - -# property -set_property(TARGET mod_ver_check PROPERTY AUTOMOC ON) - -# using std c++ 17 -target_compile_features(mod_ver_check PRIVATE cxx_std_17) \ No newline at end of file diff --git a/src/ver_check/GFModuleExport.h b/src/ver_check/GFModuleExport.h deleted file mode 100644 index ce663b5..0000000 --- a/src/ver_check/GFModuleExport.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef GF_MODULE_EXPORT_H -#define GF_MODULE_EXPORT_H - -#ifdef GF_MODULE_STATIC_DEFINE -# define GF_MODULE_EXPORT -# define GF_MODULE_NO_EXPORT -#else -# ifndef GF_MODULE_EXPORT -# ifdef mod_ver_check_EXPORTS - /* We are building this library */ -# define GF_MODULE_EXPORT __attribute__((visibility("default"))) -# else - /* We are using this library */ -# define GF_MODULE_EXPORT __attribute__((visibility("default"))) -# endif -# endif - -# ifndef GF_MODULE_NO_EXPORT -# define GF_MODULE_NO_EXPORT __attribute__((visibility("hidden"))) -# endif -#endif - -#ifndef GF_MODULE_DEPRECATED -# define GF_MODULE_DEPRECATED __attribute__ ((__deprecated__)) -#endif - -#ifndef GF_MODULE_DEPRECATED_EXPORT -# define GF_MODULE_DEPRECATED_EXPORT GF_MODULE_EXPORT GF_MODULE_DEPRECATED -#endif - -#ifndef GF_MODULE_DEPRECATED_NO_EXPORT -# define GF_MODULE_DEPRECATED_NO_EXPORT GF_MODULE_NO_EXPORT GF_MODULE_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef GF_MODULE_NO_DEPRECATED -# define GF_MODULE_NO_DEPRECATED -# endif -#endif - -#endif /* GF_MODULE_EXPORT_H */ diff --git a/src/ver_check/QtLoggerFmt.h b/src/ver_check/QtLoggerFmt.h deleted file mode 100644 index 2399746..0000000 --- a/src/ver_check/QtLoggerFmt.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include - -#include - -template <> -struct fmt::formatter { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template - auto format(const QString& qstr, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - QByteArray utf8_array = qstr.toUtf8(); - return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); - } -}; - -template <> -struct fmt::formatter { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template - auto format(const QByteArray& qarray, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - return fmt::format_to(ctx.out(), "{}", qarray.constData()); - } -}; diff --git a/src/ver_check/SoftwareVersion.cpp b/src/ver_check/SoftwareVersion.cpp deleted file mode 100644 index cd86419..0000000 --- a/src/ver_check/SoftwareVersion.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "SoftwareVersion.h" - -#include -#include -#include -#include - -#include - -template <> -struct fmt::formatter { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template - auto format(const QString& qstr, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - QByteArray utf8_array = qstr.toUtf8(); - return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); - } -}; - -template <> -struct fmt::formatter { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template - auto format(const QByteArray& qarray, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - return fmt::format_to(ctx.out(), "{}", qarray.constData()); - } -}; - -auto SoftwareVersion::NeedUpgrade() const -> bool { - GFModuleLogDebug( - fmt::format( - "compair version current {} latest {}, result {}", current_version, - latest_version, - GFCompareSoftwareVersion(GFModuleStrDup(current_version.toUtf8()), - GFModuleStrDup(latest_version.toUtf8()))) - .c_str()); - - GFModuleLogDebug(fmt::format("load done: {}, pre-release: {}, draft: {}", - loading_done, - latest_prerelease_version_from_remote, - latest_draft_from_remote) - .c_str()); - return loading_done && !latest_prerelease_version_from_remote && - !latest_draft_from_remote && - GFCompareSoftwareVersion(GFModuleStrDup(current_version.toUtf8()), - GFModuleStrDup(latest_version.toUtf8())) < 0; -} - -auto SoftwareVersion::VersionWithdrawn() const -> bool { - return loading_done && !current_version_publish_in_remote && - current_version_is_a_prerelease && !current_version_is_drafted; -} - -auto SoftwareVersion::CurrentVersionReleased() const -> bool { - return loading_done && current_version_publish_in_remote; -} \ No newline at end of file diff --git a/src/ver_check/SoftwareVersion.h b/src/ver_check/SoftwareVersion.h deleted file mode 100644 index 6b05d41..0000000 --- a/src/ver_check/SoftwareVersion.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include - -/** - * @brief - * - */ -struct SoftwareVersion { - QString latest_version; ///< - QString current_version; ///< - bool latest_prerelease_version_from_remote = false; ///< - bool latest_draft_from_remote = false; ///< - bool current_version_is_a_prerelease = false; ///< - bool current_version_is_drafted = false; ///< - bool loading_done = false; ///< - bool current_version_publish_in_remote = false; ///< - QString publish_date; ///< - QString release_note; ///< - - /** - * @brief - * - * @return true - * @return false - */ - [[nodiscard]] auto InfoValid() const -> bool { return loading_done; } - - /** - * @brief - * - * @return true - * @return false - */ - [[nodiscard]] auto NeedUpgrade() const -> bool; - - /** - * @brief - * - * @return true - * @return false - */ - [[nodiscard]] auto VersionWithdrawn() const -> bool; - - /** - * @brief - * - * @return true - * @return false - */ - [[nodiscard]] auto CurrentVersionReleased() const -> bool; - - private: - static auto version_compare(const QString& a, const QString& b) -> int; -}; diff --git a/src/ver_check/VersionCheckTask.cpp b/src/ver_check/VersionCheckTask.cpp deleted file mode 100644 index a0a3dfe..0000000 --- a/src/ver_check/VersionCheckTask.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "VersionCheckTask.h" - -#include -#include -#include - -#include -#include - -// spdlog -#include - -#include "LogFormatter.h" - -VersionCheckTask::VersionCheckTask() - : network_manager_(new QNetworkAccessManager(this)), - current_version_(GFProjectVersion()) { - qRegisterMetaType("SoftwareVersion"); - version_.current_version = current_version_; -} - -auto VersionCheckTask::Run() -> int { - GFModuleLogDebug( - fmt::format("current project version: {}", current_version_).c_str()); - QString latest_version_url = - "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; - - QNetworkRequest latest_request(latest_version_url); - latest_request.setHeader(QNetworkRequest::UserAgentHeader, - GFHttpRequestUserAgent()); - - latest_reply_ = network_manager_->get(latest_request); - connect(latest_reply_, &QNetworkReply::finished, this, - &VersionCheckTask::slot_parse_latest_version_info); - return 0; -} - -void VersionCheckTask::slot_parse_latest_version_info() { - if (latest_reply_ == nullptr) { - version_.latest_version = current_version_; - version_.loading_done = false; - } else if (latest_reply_->error() != QNetworkReply::NoError) { - GFModuleLogError(fmt::format("latest version request error: ", - latest_reply_->errorString()) - .c_str()); - version_.latest_version = current_version_; - } else { - latest_reply_bytes_ = latest_reply_->readAll(); - auto latest_reply_json = QJsonDocument::fromJson(latest_reply_bytes_); - - if (latest_reply_json.isObject()) { - QString latest_version = latest_reply_json["tag_name"].toString(); - - QRegularExpression re(R"(^[vV](\d+\.)?(\d+\.)?(\*|\d+))"); - auto version_match = re.match(latest_version); - if (version_match.hasMatch()) { - latest_version = version_match.captured(0); - GFModuleLogInfo(fmt::format("latest released version from github: {}", - latest_version) - .c_str()); - } else { - latest_version = current_version_; - GFModuleLogWarn( - fmt::format("latest version unknown, set to current version: {}", - current_version_) - .c_str()); - } - - bool prerelease = latest_reply_json["prerelease"].toBool(); - bool draft = latest_reply_json["draft"].toBool(); - auto publish_date = latest_reply_json["published_at"].toString(); - auto release_note = latest_reply_json["body"].toString(); - version_.latest_version = latest_version; - version_.latest_prerelease_version_from_remote = prerelease; - version_.latest_draft_from_remote = draft; - version_.publish_date = publish_date; - version_.release_note = release_note; - } else { - GFModuleLogWarn(fmt::format("cannot parse data got from github: {}", - latest_reply_bytes_) - .c_str()); - } - } - - if (latest_reply_ != nullptr) { - latest_reply_->deleteLater(); - } - - try { - QString current_version_url = - "https://api.github.com/repos/saturneric/gpgfrontend/releases/tags/" + - current_version_; - GFModuleLogDebug( - fmt::format("current version info query url: {}", current_version_url) - .c_str()); - - QNetworkRequest current_request(current_version_url); - current_request.setHeader(QNetworkRequest::UserAgentHeader, - GFHttpRequestUserAgent()); - - current_reply_ = network_manager_->get(current_request); - - connect(current_reply_, &QNetworkReply::finished, this, - &VersionCheckTask::slot_parse_current_version_info); - } catch (...) { - GFModuleLogError("current version request create error"); - } -} - -void VersionCheckTask::slot_parse_current_version_info() { - if (current_reply_ == nullptr) { - // loading done - version_.loading_done = false; - - } else if (current_reply_->error() != QNetworkReply::NoError) { - GFModuleLogError(fmt::format("current version request network error: {}", - current_reply_->errorString()) - .c_str()); - - // loading done - version_.loading_done = true; - version_.current_version_publish_in_remote = false; - } else { - version_.current_version_publish_in_remote = true; - current_reply_bytes_ = current_reply_->readAll(); - auto current_reply_json = QJsonDocument::fromJson(current_reply_bytes_); - - if (current_reply_json.isObject()) { - bool current_prerelease = current_reply_json["prerelease"].toBool(); - bool current_draft = current_reply_json["draft"].toBool(); - version_.latest_prerelease_version_from_remote = current_prerelease; - version_.latest_draft_from_remote = current_draft; - // loading done - version_.loading_done = true; - } else { - GFModuleLogWarn(fmt::format("cannot parse data got from github: {}", - current_reply_bytes_) - .c_str()); - } - } - - GFModuleLogDebug(fmt::format("current version parse done: {}", - version_.current_version_publish_in_remote) - .c_str()); - - if (current_reply_ != nullptr) current_reply_->deleteLater(); - emit SignalUpgradeVersion(version_); -} diff --git a/src/ver_check/VersionCheckTask.h b/src/ver_check/VersionCheckTask.h deleted file mode 100644 index 2d42b36..0000000 --- a/src/ver_check/VersionCheckTask.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include - -#include "SoftwareVersion.h" - -class QNetworkReply; -class QNetworkAccessManager; - -/** - * @brief - * - */ -class VersionCheckTask : public QObject { - Q_OBJECT - public: - /** - * @brief Construct a new Version Check Thread object - * - */ - VersionCheckTask(); - - /** - * @brief - * - * @return int - */ - auto Run() -> int; - - signals: - - /** - * @brief - * - * @param version - */ - void SignalUpgradeVersion(SoftwareVersion version); - - private slots: - - /** - * @brief - * - */ - void slot_parse_latest_version_info(); - - /** - * @brief - * - */ - void slot_parse_current_version_info(); - - private: - QByteArray latest_reply_bytes_; ///< - QByteArray current_reply_bytes_; ///< - QNetworkReply *latest_reply_ = nullptr; ///< latest version info reply - QNetworkReply *current_reply_ = nullptr; ///< current version info reply - QNetworkAccessManager *network_manager_; ///< - QString current_version_; - SoftwareVersion version_; -}; diff --git a/src/ver_check/VersionCheckingModule.cpp b/src/ver_check/VersionCheckingModule.cpp deleted file mode 100644 index 35d3b82..0000000 --- a/src/ver_check/VersionCheckingModule.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "VersionCheckingModule.h" - -#include -#include -#include -#include -#include - -#include -#include - -#include "SoftwareVersion.h" -#include "VersionCheckTask.h" - -extern void VersionCheckDone(const SoftwareVersion& version); - -auto GFGetModuleGFSDKVersion() -> const char* { - return GFModuleStrDup(GF_SDK_VERSION_STR); -} - -auto GFGetModuleQtEnvVersion() -> const char* { - return GFModuleStrDup(QT_VERSION_STR); -} - -auto GFGetModuleID() -> const char* { - return GFModuleStrDup("com.bktus.gpgfrontend.module.version_checking"); -} - -auto GFGetModuleVersion() -> const char* { return GFModuleStrDup("1.0.0"); } - -auto GFGetModuleMetaData() -> GFModuleMetaData* { - auto* p_meta = static_cast( - GFAllocateMemory(sizeof(GFModuleMetaData))); - auto* h_meta = p_meta; - - p_meta->key = "Name"; - p_meta->value = "VersionChecking"; - p_meta->next = static_cast( - GFAllocateMemory(sizeof(GFModuleMetaData))); - p_meta = p_meta->next; - - p_meta->key = "Description"; - p_meta->value = "Try checking gpgfrontend version"; - p_meta->next = static_cast( - GFAllocateMemory(sizeof(GFModuleMetaData))); - p_meta = p_meta->next; - - p_meta->key = "Author"; - p_meta->value = "Saturneric"; - p_meta->next = nullptr; - - return h_meta; -} - -auto GFRegisterModule() -> int { - GFModuleLogInfo("version checking module registering"); - return 0; -} - -auto GFActiveModule() -> int { - GFModuleLogInfo("version checking module activating"); - - GFModuleListenEvent(GFGetModuleID(), GFModuleStrDup("APPLICATION_LOADED")); - GFModuleListenEvent(GFGetModuleID(), - GFModuleStrDup("CHECK_APPLICATION_VERSION")); - return 0; -} - -auto GFExecuteModule(GFModuleEvent* event) -> int { - GFModuleLogInfo( - fmt::format("version checking module executing, event id: {}", event->id) - .c_str()); - - auto* task = new VersionCheckTask(); - QObject::connect( - task, &VersionCheckTask::SignalUpgradeVersion, QThread::currentThread(), - [event](const SoftwareVersion& version) { - VersionCheckDone(version); - - char** event_argv = - static_cast(GFAllocateMemory(sizeof(char**) * 1)); - event_argv[0] = GFModuleStrDup("0"); - - GFModuleTriggerModuleEventCallback(event, GFGetModuleID(), 1, - event_argv); - }); - QObject::connect(task, &VersionCheckTask::SignalUpgradeVersion, task, - &QObject::deleteLater); - task->Run(); - - return 0; -} - -auto GFDeactiveModule() -> int { return 0; } - -auto GFUnregisterModule() -> int { return 0; } - -void VersionCheckDone(const SoftwareVersion& version) { - GFModuleLogDebug("filling software information info in rt..."); - - GFModuleUpsertRTValue(GFGetModuleID(), - GFModuleStrDup("version.current_version"), - GFModuleStrDup(version.current_version.toUtf8())); - GFModuleUpsertRTValue(GFGetModuleID(), - GFModuleStrDup("version.latest_version"), - GFModuleStrDup(version.latest_version.toUtf8())); - GFModuleUpsertRTValueBool( - GFGetModuleID(), GFModuleStrDup("version.current_version_is_drafted"), - version.current_version_is_drafted ? 1 : 0); - GFModuleUpsertRTValueBool( - GFGetModuleID(), - GFModuleStrDup("version.current_version_is_a_prerelease"), - version.current_version_is_a_prerelease ? 1 : 0); - GFModuleUpsertRTValueBool( - GFGetModuleID(), - GFModuleStrDup("version.current_version_publish_in_remote"), - version.current_version_publish_in_remote ? 1 : 0); - GFModuleUpsertRTValueBool( - GFGetModuleID(), - GFModuleStrDup("version.latest_prerelease_version_from_remote"), - version.latest_prerelease_version_from_remote ? 1 : 0); - GFModuleUpsertRTValueBool(GFGetModuleID(), - GFModuleStrDup("version.need_upgrade"), - version.NeedUpgrade() ? 1 : 0); - GFModuleUpsertRTValueBool(GFGetModuleID(), - GFModuleStrDup("version.current_version_released"), - version.CurrentVersionReleased() ? 1 : 0); - GFModuleUpsertRTValueBool( - GFGetModuleID(), GFModuleStrDup("version.current_a_withdrawn_version"), - version.VersionWithdrawn() ? 1 : 0); - GFModuleUpsertRTValueBool(GFGetModuleID(), - GFModuleStrDup("version.loading_done"), - version.loading_done ? 1 : 0); - - GFModuleLogDebug("software information filled in rt"); -} diff --git a/src/ver_check/VersionCheckingModule.h b/src/ver_check/VersionCheckingModule.h deleted file mode 100644 index 35ee4ac..0000000 --- a/src/ver_check/VersionCheckingModule.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include - -#include "GFModuleExport.h" - -extern "C" { - -auto GF_MODULE_EXPORT GFGetModuleGFSDKVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleQtEnvVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleID() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleMetaData() -> GFModuleMetaData *; - -auto GF_MODULE_EXPORT GFRegisterModule() -> int; - -auto GF_MODULE_EXPORT GFActiveModule() -> int; - -auto GF_MODULE_EXPORT GFExecuteModule(GFModuleEvent *) -> int; - -auto GF_MODULE_EXPORT GFDeactiveModule() -> int; - -auto GF_MODULE_EXPORT GFUnregisterModule() -> int; -}; -- cgit v1.2.3