diff options
author | Saturn&Eric <[email protected]> | 2022-05-20 19:13:55 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2022-05-20 19:13:55 +0000 |
commit | 306cc5b41af9596875c2999af638eaa35899e404 (patch) | |
tree | 6d8d5b3cdb35e79527d33c63d4e69995f9c3f2df /src | |
parent | Merge pull request #65 from saturneric/develop-2.0.8 (diff) | |
parent | fix(ui): there is possible null pointer dereference (diff) | |
download | GpgFrontend-306cc5b41af9596875c2999af638eaa35899e404.tar.gz GpgFrontend-306cc5b41af9596875c2999af638eaa35899e404.zip |
Merge pull request #66 from saturneric/develop-2.0.8
Develop 2.0.8.2
Diffstat (limited to 'src')
42 files changed, 871 insertions, 573 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c69c325d..f9c354a2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -40,9 +40,6 @@ add_library(gpgfrontend_core SHARED ${GPG_SOURCE}) set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GpgFrontendCoreExport.h") generate_export_header(gpgfrontend_core EXPORT_FILE_NAME "${_export_file}") -set(UTILS_DIR ${CMAKE_SOURCE_DIR}/utils) -set(GPGME_LIB_DIR ${UTILS_DIR}/gpgme/lib) - # link third-party libraries target_link_libraries(gpgfrontend_core PUBLIC config++) if (NOT LINUX) @@ -75,7 +72,7 @@ else () endif () # link gnupg libraries -target_link_libraries(gpgfrontend_core PUBLIC gpgme assuan gpg-error) +target_link_libraries(gpgfrontend_core PRIVATE gpgme assuan gpg-error) # link openssl target_link_libraries(gpgfrontend_core PUBLIC OpenSSL::SSL OpenSSL::Crypto) # link boost libraries @@ -97,7 +94,8 @@ target_link_libraries(gpgfrontend_core PUBLIC Qt5::Core) # set up pch target_precompile_headers(gpgfrontend_core PUBLIC ${CMAKE_SOURCE_DIR}/src/GpgFrontend.h - PUBLIC GpgFrontendCore.h) + PUBLIC GpgFrontendCore.h + PUBLIC GpgConstants.h) # using std c++ 17 target_compile_features(gpgfrontend_core PUBLIC cxx_std_17) diff --git a/src/core/GpgConstants.cpp b/src/core/GpgConstants.cpp index 88068f37..ff783872 100644 --- a/src/core/GpgConstants.cpp +++ b/src/core/GpgConstants.cpp @@ -28,10 +28,7 @@ #include "core/GpgConstants.h" -#include <gpg-error.h> - #include <boost/algorithm/string/predicate.hpp> -#include <string> #include "function/FileOperator.h" @@ -56,9 +53,9 @@ const char* GpgFrontend::GpgConstants::GPG_FRONTEND_SHORT_CRYPTO_HEAD = gpgme_error_t GpgFrontend::check_gpg_error(gpgme_error_t err) { if (gpg_err_code(err) != GPG_ERR_NO_ERROR) { - LOG(ERROR) << "[" << _("Error") << " " << gpg_err_code(err) << "] " - << _("Source: ") << gpgme_strsource(err) << " " - << _("Description: ") << gpgme_strerror(err); + LOG(ERROR) << "[" << _("Error") << gpg_err_code(err) << "]" << _("Source: ") + << gpgme_strsource(err) << _("Description: ") + << gpgme_strerror(err); } return err; } @@ -66,10 +63,16 @@ gpgme_error_t GpgFrontend::check_gpg_error(gpgme_error_t err) { gpg_err_code_t GpgFrontend::check_gpg_error_2_err_code(gpgme_error_t err, gpgme_error_t predict) { auto err_code = gpg_err_code(err); - if (err_code != predict) { - LOG(ERROR) << "[" << _("Error") << " " << gpg_err_code(err) << "] " - << _("Source: ") << gpgme_strsource(err) << " " - << _("Description: ") << gpgme_strerror(err); + if (err_code != gpg_err_code(predict)) { + if (err_code == GPG_ERR_NO_ERROR) + LOG(WARNING) << "[" << _("Warning") << gpg_err_code(err) << "]" + << _("Source: ") << gpgme_strsource(err) + << _("Description: ") << gpgme_strerror(err) << _("Predict") + << gpgme_strerror(err); + else + LOG(ERROR) << "[" << _("Error") << gpg_err_code(err) << "]" + << _("Source: ") << gpgme_strsource(err) << _("Description: ") + << gpgme_strerror(err) << _("Predict") << gpgme_strerror(err); } return err_code; } @@ -77,9 +80,9 @@ gpg_err_code_t GpgFrontend::check_gpg_error_2_err_code(gpgme_error_t err, gpgme_error_t GpgFrontend::check_gpg_error(gpgme_error_t err, const std::string& comment) { if (gpg_err_code(err) != GPG_ERR_NO_ERROR) { - LOG(ERROR) << "[" << _("Error") << " " << gpg_err_code(err) << "] " - << _("Source: ") << gpgme_strsource(err) << " " - << _("Description: ") << gpgme_strerror(err); + LOG(ERROR) << "[" << _("Error") << gpg_err_code(err) << "]" << _("Source: ") + << gpgme_strsource(err) << _("Description: ") + << gpgme_strerror(err); } return err; } diff --git a/src/core/GpgConstants.h b/src/core/GpgConstants.h index f3f0c6e6..06f8e20d 100644 --- a/src/core/GpgConstants.h +++ b/src/core/GpgConstants.h @@ -29,14 +29,7 @@ #ifndef GPG_CONSTANTS_H #define GPG_CONSTANTS_H -#include <GpgFrontend.h> -#include <gpgme.h> - -#include <cassert> -#include <functional> - -// dll export macro -#include "GpgFrontendCoreExport.h" +#include "GpgFrontendCore.h" const int RESTART_CODE = 1000; ///< diff --git a/src/core/GpgContext.cpp b/src/core/GpgContext.cpp index 733354fc..7e656dfb 100644 --- a/src/core/GpgContext.cpp +++ b/src/core/GpgContext.cpp @@ -87,13 +87,13 @@ GpgContext::GpgContext(const GpgContextInitArgs &args) : args_(args) { continue; } - DLOG(INFO) << gpgme_get_protocol_name(engine_info->protocol) - << std::string(engine_info->file_name == nullptr - ? "null" - : engine_info->file_name) - << std::string(engine_info->home_dir == nullptr - ? "null" - : engine_info->home_dir); + LOG(INFO) << gpgme_get_protocol_name(engine_info->protocol) + << std::string(engine_info->file_name == nullptr + ? "null" + : engine_info->file_name) + << std::string(engine_info->home_dir == nullptr + ? "null" + : engine_info->home_dir); switch (engine_info->protocol) { case GPGME_PROTOCOL_OpenPGP: @@ -136,7 +136,7 @@ GpgContext::GpgContext(const GpgContextInitArgs &args) : args_(args) { LOG(ERROR) << "Env check failed"; return; } else { - DLOG(INFO) << "gnupg version" << info_.GnupgVersion; + LOG(INFO) << "gnupg version" << info_.GnupgVersion; init_ctx(); good_ = true; } @@ -146,7 +146,7 @@ void GpgContext::init_ctx() { // Set Independent Database if (info_.GnupgVersion <= "2.0.0" && args_.independent_database) { info_.DatabasePath = args_.db_path; - DLOG(INFO) << "custom key db path" << info_.DatabasePath; + LOG(INFO) << "custom key db path" << info_.DatabasePath; auto err = gpgme_ctx_set_engine_info(_ctx_ref.get(), GPGME_PROTOCOL_OpenPGP, info_.AppPath.c_str(), info_.DatabasePath.c_str()); diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp index 41cf99cb..f1664b2a 100644 --- a/src/core/GpgCoreInit.cpp +++ b/src/core/GpgCoreInit.cpp @@ -28,8 +28,6 @@ #include "GpgCoreInit.h" -#include <memory> - #include "GpgFunctionObject.h" #include "core/GpgContext.h" #include "core/function/GlobalSettingStation.h" @@ -43,28 +41,37 @@ namespace GpgFrontend { * @brief setup logging system and do proper initialization * */ -void init_logging() { +void InitLoggingSystem() { using namespace boost::posix_time; using namespace boost::gregorian; - ptime now = second_clock::local_time(); - el::Loggers::addFlag(el::LoggingFlag::AutoSpacing); + el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput); + el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck); el::Configurations defaultConf; defaultConf.setToDefault(); - el::Loggers::reconfigureLogger("default", defaultConf); // apply settings defaultConf.setGlobally(el::ConfigurationType::Format, - "%datetime %level %func %msg"); + "%datetime %level [core] {%func} -> %msg"); + + // apply settings no written to file + defaultConf.setGlobally(el::ConfigurationType::ToFile, "false"); + + // set the logger + el::Loggers::reconfigureLogger("default", defaultConf); // get the log directory - auto logfile_path = - (GlobalSettingStation::GetInstance().GetLogDir() / to_iso_string(now)); + auto logfile_path = (GlobalSettingStation::GetInstance().GetLogDir() / + to_iso_string(second_clock::local_time())); logfile_path.replace_extension(".log"); defaultConf.setGlobally(el::ConfigurationType::Filename, logfile_path.u8string()); + // apply settings written to file + defaultConf.setGlobally(el::ConfigurationType::ToFile, "true"); + + // set the logger el::Loggers::reconfigureLogger("default", defaultConf); LOG(INFO) << _("log file path") << logfile_path; diff --git a/src/core/GpgCoreInit.h b/src/core/GpgCoreInit.h index 752fe4c3..150e85e9 100644 --- a/src/core/GpgCoreInit.h +++ b/src/core/GpgCoreInit.h @@ -37,7 +37,7 @@ namespace GpgFrontend { * @brief * */ -void init_logging(); +void GPGFRONTEND_CORE_EXPORT InitLoggingSystem(); /** * @brief diff --git a/src/core/GpgFrontendCore.h b/src/core/GpgFrontendCore.h index 90bc36be..0b433b96 100644 --- a/src/core/GpgFrontendCore.h +++ b/src/core/GpgFrontendCore.h @@ -1,29 +1,29 @@ /** -* 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 <https://www.gnu.org/licenses/>. -* -* 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<[email protected]> starting on May 12, 2021. -* -* SPDX-License-Identifier: GPL-3.0-or-later -* + * 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 <https://www.gnu.org/licenses/>. + * + * 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<[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * */ #ifndef GPGFRONTEND_GPGFRONTENDCORE_H @@ -31,11 +31,29 @@ #include "GpgFrontend.h" +// gnupg +#include <gpgme.h> + // std includes -#include <random> +#include <cassert> #include <filesystem> +#include <functional> +#include <map> +#include <memory> +#include <mutex> +#include <random> +#include <shared_mutex> +#include <stdexcept> +#include <string> +#include <typeinfo> +#include <utility> +#include <vector> // boost includes +#include <boost/date_time.hpp> +#include <boost/date_time/posix_time/conversion.hpp> +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> #include <boost/format.hpp> // Qt includes @@ -48,7 +66,10 @@ #include <libarchive/libarchive/archive.h> #include <libarchive/libarchive/archive_entry.h> -#include "GpgConstants.h" +// json includes +#include <nlohmann/json.hpp> +// dll export macro +#include "GpgFrontendCoreExport.h" #endif // GPGFRONTEND_GPGFRONTENDCORE_H diff --git a/src/core/GpgFunctionObject.cpp b/src/core/GpgFunctionObject.cpp index 9fb55247..1289d72f 100644 --- a/src/core/GpgFunctionObject.cpp +++ b/src/core/GpgFunctionObject.cpp @@ -51,19 +51,16 @@ void GpgFrontend::SingletonStorage::ReleaseChannel(int channel) { _it = instances_map_.find(channel); } if (_it != instances_map_.end()) instances_map_.erase(_it); - DLOG(INFO) << "channel" << channel << "released"; } GpgFrontend::ChannelObject* GpgFrontend::SingletonStorage::FindObjectInChannel( int channel) { - LOG(INFO) << "channel:" << channel << "instance address:" << &instances_map_; // read instances_map_ decltype(instances_map_.end()) _it; { std::shared_lock<std::shared_mutex> lock(instances_mutex_); _it = instances_map_.find(channel); if (_it == instances_map_.end()) { - LOG(INFO) << "channel:" << channel << "not found"; return nullptr; } else { return _it->second.get(); @@ -82,8 +79,8 @@ std::vector<int> GpgFrontend::SingletonStorage::GetAllChannelId() { GpgFrontend::ChannelObject* GpgFrontend::SingletonStorage::SetObjectInChannel( int channel, std::unique_ptr<ChannelObject> p_obj) { { - LOG(INFO) << "channel:" << channel - << "instance address:" << &instances_map_; + LOG(TRACE) << "set channel:" << channel + << "instance address:" << &instances_map_; assert(p_obj != nullptr); if (p_obj == nullptr) return nullptr; @@ -102,7 +99,6 @@ GpgFrontend::SingletonStorage* GpgFrontend::SingletonStorageCollection::GetSingletonStorage( const std::type_info& type_id) { const auto hash = type_id.hash_code(); - LOG(INFO) << "hash" << hash << "type_name:" << type_id.name(); while (true) { decltype(storages_map_.end()) _it; @@ -111,16 +107,15 @@ GpgFrontend::SingletonStorageCollection::GetSingletonStorage( _it = storages_map_.find(hash); } if (_it == storages_map_.end()) { - LOG(INFO) << "hash:" << hash << "not found"; { std::unique_lock<std::shared_mutex> lock(storages_mutex_); storages_map_.insert({hash, std::make_unique<SingletonStorage>()}); - LOG(INFO) << "hash:" << hash << "created" - << "storage address:" << &storages_map_; } + LOG(TRACE) << "hash:" << hash << "created" + << "storage address:" << &storages_map_ + << "type_name : " << type_id.name(); continue; } else { - LOG(INFO) << "hash:" << hash << "found"; return _it->second.get(); } } @@ -137,7 +132,4 @@ GpgFrontend::SingletonStorageCollection::GetInstance() { GpgFrontend::ChannelObject::ChannelObject() noexcept = default; -GpgFrontend::ChannelObject::ChannelObject(int channel) : channel_(channel) { - LOG(INFO) << "called" - << "channel:" << channel; -} +GpgFrontend::ChannelObject::ChannelObject(int channel) : channel_(channel) {} diff --git a/src/core/GpgFunctionObject.h b/src/core/GpgFunctionObject.h index f16e4cae..de27ea42 100644 --- a/src/core/GpgFunctionObject.h +++ b/src/core/GpgFunctionObject.h @@ -29,18 +29,7 @@ #ifndef GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H #define GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H -#include <map> -#include <memory> -#include <mutex> -#include <shared_mutex> -#include <stdexcept> -#include <string> -#include <typeinfo> -#include <utility> -#include <vector> - #include "GpgConstants.h" -#include "easylogging++.h" namespace GpgFrontend { @@ -189,14 +178,12 @@ class SingletonFunctionObject : public ChannelObject { auto* _p_pbj = (T*)(p_storage->FindObjectInChannel(channel)); - LOG(INFO) << "object address" << _p_pbj; - if (_p_pbj == nullptr) { auto new_obj = std::unique_ptr<ChannelObject>(new T(channel)); - LOG(INFO) << "create new object"; return *(T*)(p_storage->SetObjectInChannel(channel, std::move(new_obj))); - } else + } else { return *_p_pbj; + } } /** @@ -292,10 +279,7 @@ class SingletonFunctionObject : public ChannelObject { * * @param channel */ - explicit SingletonFunctionObject(int channel) : ChannelObject(channel) { - LOG(INFO) << "called" - << "channel:" << channel; - } + explicit SingletonFunctionObject(int channel) : ChannelObject(channel) {} /** * @brief Destroy the Singleton Function Object object diff --git a/src/core/function/CharsetOperator.h b/src/core/function/CharsetOperator.h index c04430f2..41ce62f4 100644 --- a/src/core/function/CharsetOperator.h +++ b/src/core/function/CharsetOperator.h @@ -29,8 +29,6 @@ #ifndef GPGFRONTEND_CHARSETDETECTOR_H #define GPGFRONTEND_CHARSETDETECTOR_H -#include <string> - #include "core/GpgFrontendCore.h" namespace GpgFrontend { diff --git a/src/core/function/DataObjectOperator.h b/src/core/function/DataObjectOperator.h index 1b52ec32..97abc607 100644 --- a/src/core/function/DataObjectOperator.h +++ b/src/core/function/DataObjectOperator.h @@ -29,8 +29,6 @@ #ifndef GPGFRONTEND_DATAOBJECTOPERATOR_H #define GPGFRONTEND_DATAOBJECTOPERATOR_H -#include <json/single_include/nlohmann/json.hpp> - #include "core/GpgFrontendCore.h" #include "core/GpgFunctionObject.h" #include "core/function/GlobalSettingStation.h" @@ -38,7 +36,7 @@ namespace GpgFrontend { class GPGFRONTEND_CORE_EXPORT DataObjectOperator - : public SingletonFunctionObject<DataObjectOperator> { + : public SingletonFunctionObject<DataObjectOperator> { public: /** * @brief DataObjectOperator constructor diff --git a/src/core/function/GlobalSettingStation.h b/src/core/function/GlobalSettingStation.h index 0df6bd21..ccf8e8f0 100644 --- a/src/core/function/GlobalSettingStation.h +++ b/src/core/function/GlobalSettingStation.h @@ -29,11 +29,6 @@ #ifndef GPGFRONTEND_GLOBALSETTINGSTATION_H #define GPGFRONTEND_GLOBALSETTINGSTATION_H -#include <openssl/x509.h> - -#include <boost/filesystem/operations.hpp> -#include <boost/filesystem/path.hpp> - #include "GpgFrontendBuildInstallInfo.h" #include "core/GpgFrontendCore.h" #include "core/GpgFunctionObject.h" @@ -148,7 +143,7 @@ class GPGFRONTEND_CORE_EXPORT GlobalSettingStation private: std::filesystem::path app_path_ = - qApp->applicationDirPath().toStdString(); ///< Program Location + QCoreApplication::applicationDirPath().toStdString(); ///< Program Location std::filesystem::path app_data_path_ = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) .toStdString(); ///< Program Data Location diff --git a/src/core/function/gpg/GpgBasicOperator.cpp b/src/core/function/gpg/GpgBasicOperator.cpp index 97399b4e..a2c5d81b 100644 --- a/src/core/function/gpg/GpgBasicOperator.cpp +++ b/src/core/function/gpg/GpgBasicOperator.cpp @@ -86,7 +86,7 @@ GpgFrontend::GpgError GpgFrontend::GpgBasicOperator::Verify( GpgData data_in(in_buffer.data(), in_buffer.size()); GpgData data_out; - if (sig_buffer != nullptr) { + if (sig_buffer != nullptr && sig_buffer->size() > 0) { GpgData sig_data(sig_buffer->data(), sig_buffer->size()); err = check_gpg_error(gpgme_op_verify(ctx_, sig_data, data_in, nullptr)); } else diff --git a/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp b/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp index 44031e67..79eb5282 100644 --- a/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp +++ b/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp @@ -34,8 +34,8 @@ #include "core/GpgConstants.h" #include "function/gpg/GpgKeyGetter.h" -GpgFrontend::GpgVerifyResultAnalyse::GpgVerifyResultAnalyse(GpgError error, - GpgVerifyResult result) +GpgFrontend::GpgVerifyResultAnalyse::GpgVerifyResultAnalyse( + GpgError error, GpgVerifyResult result) : error_(error), result_(std::move(result)) {} void GpgFrontend::GpgVerifyResultAnalyse::do_analyse() { @@ -104,6 +104,7 @@ void GpgFrontend::GpgVerifyResultAnalyse::do_analyse() { stream_ << _("Signature Fully Valid.") << std::endl; } else { stream_ << _("Signature Not Fully Valid.") << std::endl; + stream_ << _("(May used a subkey to sign)") << std::endl; } if (!(sign->status & GPGME_SIGSUM_KEY_MISSING)) { @@ -172,8 +173,8 @@ void GpgFrontend::GpgVerifyResultAnalyse::do_analyse() { } } -bool GpgFrontend::GpgVerifyResultAnalyse::print_signer(std::stringstream &stream, - gpgme_signature_t sign) { +bool GpgFrontend::GpgVerifyResultAnalyse::print_signer( + std::stringstream &stream, gpgme_signature_t sign) { bool keyFound = true; auto key = GpgFrontend::GpgKeyGetter::GetInstance().GetKey(sign->fpr); diff --git a/src/core/model/GpgKey.h b/src/core/model/GpgKey.h index 457b6540..4761f8a5 100644 --- a/src/core/model/GpgKey.h +++ b/src/core/model/GpgKey.h @@ -29,9 +29,6 @@ #ifndef GPGFRONTEND_GPGKEY_H #define GPGFRONTEND_GPGKEY_H -#include <boost/date_time.hpp> -#include <boost/date_time/posix_time/conversion.hpp> - #include "GpgSubKey.h" #include "GpgUID.h" diff --git a/src/core/thread/CtxCheckTask.cpp b/src/core/thread/CtxCheckTask.cpp index ee170fbc..997dd341 100644 --- a/src/core/thread/CtxCheckTask.cpp +++ b/src/core/thread/CtxCheckTask.cpp @@ -38,9 +38,6 @@ GpgFrontend::Thread::CtxCheckTask::CtxCheckTask() { } void GpgFrontend::Thread::CtxCheckTask::Run() { - // init logging - init_logging(); - // Init GpgFrontend Core init_gpgfrontend_core(); diff --git a/src/core/thread/Task.cpp b/src/core/thread/Task.cpp index 7b8423b2..6b1a27a1 100644 --- a/src/core/thread/Task.cpp +++ b/src/core/thread/Task.cpp @@ -37,7 +37,7 @@ #include "easylogging++.h" GpgFrontend::Thread::Task::Task() : uuid_(generate_uuid()) { - LOG(INFO) << "Task" << uuid_ << "created"; + LOG(TRACE) << "Task" << uuid_ << "created"; init(); } @@ -47,8 +47,8 @@ GpgFrontend::Thread::Task::Task(TaskCallback callback, callback_(std::move(callback)), callback_thread_(QThread::currentThread()), data_object_(data_object) { - LOG(INFO) << "Task" << uuid_ << "created with callback" - << "callback_thread_: " << callback_thread_; + LOG(TRACE) << "Task" << uuid_ << "created with callback" + << "callback_thread_: " << callback_thread_; init(); } @@ -60,11 +60,13 @@ GpgFrontend::Thread::Task::Task(TaskRunnable runnable, TaskCallback callback, callback_thread_(QThread::currentThread()), data_object_(data_object) { init(); - LOG(INFO) << "Task" << uuid_ << "created with runnable and callback" - << "callback_thread_: " << callback_thread_; + LOG(TRACE) << "Task" << uuid_ << "created with runnable and callback" + << "callback_thread_: " << callback_thread_; } -GpgFrontend::Thread::Task::~Task() = default; +GpgFrontend::Thread::Task::~Task() { + LOG(TRACE) << "Task" << uuid_ << "destroyed"; +} std::string GpgFrontend::Thread::Task::GetUUID() const { return uuid_; } @@ -76,25 +78,31 @@ void GpgFrontend::Thread::Task::SetRTN(int rtn) { this->rtn_ = rtn; } void GpgFrontend::Thread::Task::init() { connect(this, &Task::SignalTaskFinished, this, &Task::before_finish_task); - connect(this, &Task::SignalTaskFinished, this, &Task::deleteLater); } void GpgFrontend::Thread::Task::before_finish_task() { - LOG(INFO) << "Task" << uuid_ << "finished"; - if (callback_) { - bool if_invoke = QMetaObject::invokeMethod( - callback_thread_, - [callback = callback_, rtn = rtn_, data_object = data_object_]() { - callback(rtn, data_object); - }); - if (!if_invoke) { - LOG(ERROR) << "failed to invoke callback"; + LOG(TRACE) << "Task" << uuid_ << "finished"; + try { + if (callback_) { + bool if_invoke = QMetaObject::invokeMethod( + callback_thread_, + [callback = callback_, rtn = rtn_, data_object = data_object_]() { + callback(rtn, data_object); + }); + if (!if_invoke) { + LOG(ERROR) << "failed to invoke callback"; + } } + } catch (std::exception &e) { + LOG(ERROR) << "exception caught: " << e.what(); + } catch (...) { + LOG(ERROR) << "unknown exception caught"; } + emit SignalTaskPostFinishedDone(); } void GpgFrontend::Thread::Task::run() { - LOG(INFO) << "Task" << uuid_ << "started"; + LOG(TRACE) << "Task" << uuid_ << "started"; Run(); if (finish_after_run_) emit SignalTaskFinished(); } @@ -104,7 +112,7 @@ void GpgFrontend::Thread::Task::Run() { bool if_invoke = QMetaObject::invokeMethod( this, [=]() { return runnable_(data_object_); }, &rtn_); if (!if_invoke) { - LOG(ERROR) << "invokeMethod failed"; + LOG(ERROR) << "Qt invokeMethod failed"; } } } @@ -131,8 +139,8 @@ size_t GpgFrontend::Thread::Task::DataObject::GetObjectSize() { } void GpgFrontend::Thread::Task::DataObject::free_heap_ptr(Destructor *ptr) { - LOG(INFO) << "p_obj: " << ptr->p_obj << "destructor: " << ptr->destroy - << "DataObject:" << this; + DLOG(TRACE) << "p_obj: " << ptr->p_obj << "destructor: " << ptr->destroy + << "DataObject:" << this; if (ptr->destroy != nullptr) { ptr->destroy(ptr->p_obj); } diff --git a/src/core/thread/Task.h b/src/core/thread/Task.h index 468a04b8..c94baea6 100644 --- a/src/core/thread/Task.h +++ b/src/core/thread/Task.h @@ -78,7 +78,7 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable { */ template <typename T> void AppendObject(T &&obj) { - LOG(INFO) << "called:" << this; + DLOG(TRACE) << "called:" << this; auto *obj_dstr = this->get_heap_ptr(sizeof(T)); auto *ptr_heap = new ((void *)obj_dstr->p_obj) T(std::move(obj)); if (std::is_class_v<T>) { @@ -100,10 +100,11 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable { */ template <typename T> void AppendObject(T *obj) { - LOG(INFO) << "called:" << this; + DLOG(TRACE) << "called:" << this; auto *obj_dstr = this->get_heap_ptr(sizeof(T)); auto *ptr_heap = new ((void *)obj_dstr->p_obj) T(std::move(*obj)); if (std::is_class_v<T>) { + LOG(TRACE) << "is class"; auto destructor = [](const void *x) { static_cast<const T *>(x)->~T(); }; @@ -122,7 +123,7 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable { */ template <typename T> T PopObject() { - LOG(INFO) << "called:" << this; + DLOG(TRACE) << "called:" << this; if (data_objects_.empty()) throw std::runtime_error("No object to pop"); auto *obj_dstr = data_objects_.top(); auto *heap_ptr = (T *)obj_dstr->p_obj; @@ -206,6 +207,12 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable { */ void SignalTaskFinished(); + /** + * @brief + * + */ + void SignalTaskPostFinishedDone(); + protected: /** * @brief Set the Finish After Run object diff --git a/src/core/thread/TaskRunner.cpp b/src/core/thread/TaskRunner.cpp index 3b565abb..7116ca71 100644 --- a/src/core/thread/TaskRunner.cpp +++ b/src/core/thread/TaskRunner.cpp @@ -36,12 +36,23 @@ GpgFrontend::Thread::TaskRunner::TaskRunner() = default; GpgFrontend::Thread::TaskRunner::~TaskRunner() = default; void GpgFrontend::Thread::TaskRunner::PostTask(Task* task) { - LOG(INFO) << "called" - << "Post Task" << task->GetUUID(); + LOG(TRACE) << "Post Task" << task->GetUUID(); if (task == nullptr) return; task->setParent(nullptr); task->moveToThread(this); + + connect(task, &Task::SignalTaskPostFinishedDone, this, [=]() { + auto it = pending_tasks_.find(task->GetUUID()); + if (it == pending_tasks_.end()) { + LOG(ERROR) << "Task" << task->GetUUID() << "not found in pending tasks"; + return; + } else { + LOG(TRACE) << "Task" << task->GetUUID() << "found in pending tasks"; + it->second->deleteLater(); + pending_tasks_.erase(it); + } + }); { std::lock_guard<std::mutex> lock(tasks_mutex_); tasks.push(task); @@ -50,33 +61,43 @@ void GpgFrontend::Thread::TaskRunner::PostTask(Task* task) { } void GpgFrontend::Thread::TaskRunner::run() { - LOG(INFO) << "called" - << "thread id:" << QThread::currentThreadId(); + LOG(TRACE) << "called" + << "thread id:" << QThread::currentThreadId(); while (true) { + LOG(TRACE) << "TaskRunner: A new cycle start"; if (tasks.empty()) { - LOG(INFO) << "TaskRunner: No tasks to run."; + LOG(TRACE) << "TaskRunner: No tasks to run, trapping into event loop..."; exec(); } else { - LOG(INFO) << "TaskRunner: Queue size:" << tasks.size(); + LOG(TRACE) << "TaskRunner: Task queue size:" << tasks.size(); Task* task = nullptr; { std::lock_guard<std::mutex> lock(tasks_mutex_); task = std::move(tasks.front()); tasks.pop(); + pending_tasks_.insert({task->GetUUID(), task}); } if (task != nullptr) { // Run the task - LOG(INFO) << "TaskRunner: Running Task" << task->GetUUID(); + LOG(TRACE) << "TaskRunner: Running Task" << task->GetUUID(); try { task->run(); } catch (const std::exception& e) { LOG(ERROR) << "TaskRunner: Exception in Task" << task->GetUUID() << "Exception: " << e.what(); + + // destroy the task, remove the task from the pending tasks + task->deleteLater(); + pending_tasks_.erase(task->GetUUID()); } catch (...) { LOG(ERROR) << "TaskRunner: Unknwon Exception in Task" << task->GetUUID(); + + // destroy the task, remove the task from the pending tasks + task->deleteLater(); + pending_tasks_.erase(task->GetUUID()); } } } diff --git a/src/core/thread/TaskRunner.h b/src/core/thread/TaskRunner.h index 14eaeae7..f18efca6 100644 --- a/src/core/thread/TaskRunner.h +++ b/src/core/thread/TaskRunner.h @@ -67,8 +67,9 @@ class GPGFRONTEND_CORE_EXPORT TaskRunner : public QThread { void PostTask(Task* task); private: - std::queue<Task*> tasks; ///< The task queue - std::mutex tasks_mutex_; ///< The task queue mutex + std::queue<Task*> tasks; ///< The task queue + std::map<std::string, Task*> pending_tasks_; ///< The pending tasks + std::mutex tasks_mutex_; ///< The task queue mutex }; } // namespace GpgFrontend::Thread diff --git a/src/core/thread/TaskRunnerGetter.h b/src/core/thread/TaskRunnerGetter.h index 722484b5..afbf63af 100644 --- a/src/core/thread/TaskRunnerGetter.h +++ b/src/core/thread/TaskRunnerGetter.h @@ -40,6 +40,7 @@ class GPGFRONTEND_CORE_EXPORT TaskRunnerGetter kTaskRunnerType_Default, kTaskRunnerType_GPG, kTaskRunnerType_IO, + kTaskRunnerType_Network, }; TaskRunnerGetter(int channel = SingletonFunctionObject::GetDefaultChannel()); diff --git a/src/init.cpp b/src/init.cpp index 2f4955f5..c872170e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -26,25 +26,21 @@ * */ +#include "GpgFrontend.h" +#include "GpgFrontendBuildInfo.h" #include "core/function/GlobalSettingStation.h" -/** - * @brief Get the files of a given directory - * - * @param _path target directory - * @return std::vector<std::filesystem::path> - */ -std::vector<std::filesystem::path> get_files_of_directory( - const std::filesystem::path& _path) { - namespace fs = std::filesystem; - std::vector<fs::path> path_list; - if (!_path.empty()) { - fs::recursive_directory_iterator end; +void init_logging_system() { + el::Loggers::addFlag(el::LoggingFlag::AutoSpacing); + el::Configurations defaultConf; + defaultConf.setToDefault(); + + // apply settings + defaultConf.setGlobally(el::ConfigurationType::Format, + "%datetime %level [main] %func %msg"); + // apply settings no written to file + defaultConf.setGlobally(el::ConfigurationType::ToFile, "false"); - for (fs::recursive_directory_iterator i(_path); i != end; ++i) { - const fs::path cp = (*i); - path_list.push_back(cp); - } - } - return path_list; -}
\ No newline at end of file + // set the logger + el::Loggers::reconfigureLogger("default", defaultConf); +} diff --git a/src/main.cpp b/src/main.cpp index fd20a664..b51c44ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,16 +32,11 @@ #include <csetjmp> #include <csignal> -#include <cstdlib> +#include <cstddef> -#include "GpgFrontendBuildInfo.h" -#include "core/GpgFunctionObject.h" +#include "core/GpgCoreInit.h" +#include "ui/GpgFrontendApplication.h" #include "ui/GpgFrontendUIInit.h" -#include "ui/main_window/MainWindow.h" - -#if !defined(RELEASE) && defined(WINDOWS) -#include "core/function/GlobalSettingStation.h" -#endif /** * \brief initialize the easylogging++ library. @@ -53,20 +48,28 @@ INITIALIZE_EASYLOGGINGPP */ jmp_buf recover_env; +constexpr int CRASH_CODE = ~0; ///< + /** - * @brief + * @brief handle the signal SIGSEGV * * @param sig */ extern void handle_signal(int sig); /** - * @brief + * @brief processes before exit the program. * */ extern void before_exit(); /** + * @brief initialize the logging system. + * + */ +extern void init_logging_system(); + +/** * * @param argc * @param argv @@ -85,38 +88,14 @@ int main(int argc, char* argv[]) { Q_INIT_RESOURCE(gpgfrontend); // create qt application - QApplication app(argc, argv); - -#ifndef MACOS - QApplication::setWindowIcon(QIcon(":gpgfrontend.png")); -#endif + auto* app = + GpgFrontend::UI::GpgFrontendApplication::GetInstance(argc, argv, true); -#ifdef MACOS - // support retina screen - QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); -#endif + // init the logging system + init_logging_system(); - // set the extra information of the build - QApplication::setApplicationVersion(BUILD_VERSION); - QApplication::setApplicationName(PROJECT_NAME); - - // don't show icons in menus - QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); - - // unicode in source - QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf-8")); - -#if !defined(RELEASE) && defined(WINDOWS) - // css - std::filesystem::path css_path = - GpgFrontend::GlobalSettingStation::GetInstance().GetResourceDir() / - "css" / "default.qss"; - QFile file(css_path.u8string().c_str()); - file.open(QFile::ReadOnly); - QString styleSheet = QLatin1String(file.readAll()); - qApp->setStyleSheet(styleSheet); - file.close(); -#endif + // init the logging system for core + GpgFrontend::InitLoggingSystem(); /** * internationalisation. loop to restart main window @@ -131,45 +110,33 @@ int main(int argc, char* argv[]) { int r = setjmp(recover_env); #endif if (!r) { -#ifdef RELEASE - try { -#endif - QApplication::setQuitOnLastWindowClosed(true); - - // init ui library - GpgFrontend::UI::InitGpgFrontendUI(); - - // create main window - return_from_event_loop_code = GpgFrontend::UI::RunGpgFrontendUI(); -#ifdef RELEASE - } catch (...) { - // catch all unhandled exceptions and notify the user - QMessageBox::information( - nullptr, _("Unhandled Exception Thrown"), - _("Oops, an unhandled exception was thrown " - "during the running of the " - "program, and now it needs to be restarted. This is not a " - "serious problem, it may be the negligence of the programmer, " - "please report this problem if you can.")); - return_from_event_loop_code = RESTART_CODE; - continue; - } -#endif + // init ui library + GpgFrontend::UI::InitGpgFrontendUI(app); + // create main window + return_from_event_loop_code = GpgFrontend::UI::RunGpgFrontendUI(app); } else { + LOG(ERROR) << "recover from a crash"; // when signal is caught, restart the main window - QMessageBox::information( - nullptr, _("A serious error has occurred"), - _("Oh no! GpgFrontend caught a serious error in the software, so it " - "needs to be restarted. If the problem recurs, please manually " - "terminate the program and report the problem to the developer.")); - QCoreApplication::quit(); - return_from_event_loop_code = RESTART_CODE; - LOG(INFO) << "return_from_event_loop_code" << return_from_event_loop_code; - continue; + auto* message_box = new QMessageBox( + QMessageBox::Critical, _("A serious error has occurred"), + _("Oh no! GpgFrontend caught a serious error in the software, so " + "it needs to be restarted. If the problem recurs, please " + "manually terminate the program and report the problem to the " + "developer."), + QMessageBox::Ok, nullptr); + message_box->exec(); + return_from_event_loop_code = CRASH_CODE; + } + + if (return_from_event_loop_code == CRASH_CODE) { + app = GpgFrontend::UI::GpgFrontendApplication::GetInstance(argc, argv, + true); } + LOG(INFO) << "loop refresh"; - } while (return_from_event_loop_code == RESTART_CODE); + } while (return_from_event_loop_code == RESTART_CODE || + return_from_event_loop_code == CRASH_CODE); // exit the program return return_from_event_loop_code; diff --git a/src/ui/GpgFrontendApplication.cpp b/src/ui/GpgFrontendApplication.cpp new file mode 100644 index 00000000..4cb50b43 --- /dev/null +++ b/src/ui/GpgFrontendApplication.cpp @@ -0,0 +1,94 @@ +/** + * 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 <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * The source code version of this software was modified and released + * by Saturneric<[email protected]><[email protected]> starting on May 12, 2021. + * + */ + +#include "ui/GpgFrontendApplication.h" + +#include "GpgFrontendBuildInfo.h" + +namespace GpgFrontend::UI { + +GpgFrontendApplication::GpgFrontendApplication(int &argc, char **argv) + : QApplication(argc, argv) { +#ifndef MACOS + this->setWindowIcon(QIcon(":gpgfrontend.png")); +#endif + +#ifdef MACOS + // support retina screen + this->setAttribute(Qt::AA_UseHighDpiPixmaps); +#endif + + // set the extra information of the build + this->setApplicationVersion(BUILD_VERSION); + this->setApplicationName(PROJECT_NAME); + this->setQuitOnLastWindowClosed(true); + + // don't show icons in menus + this->setAttribute(Qt::AA_DontShowIconsInMenus); + + // unicode in source + QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf-8")); +} + +GpgFrontendApplication *GpgFrontendApplication::GetInstance(int argc, + char *argv[], + bool new_instance) { + static GpgFrontendApplication *instance = nullptr; + if (new_instance || !instance) { + if (instance != nullptr) { + instance->quit(); + delete instance; + } + instance = new GpgFrontendApplication(argc, argv); + } + return instance; +} + +bool GpgFrontendApplication::notify(QObject *receiver, QEvent *event) { + bool app_done = true; + try { + app_done = QApplication::notify(receiver, event); + } catch (const std::exception &ex) { + LOG(INFO) << "Exception caught in notify: " << ex.what(); + QMessageBox::information(nullptr, _("Standard Exception Thrown"), + _("Oops, an standard exception was thrown " + "during the running of the " + "program. This is not a serious problem, it may " + "be the negligence of the programmer, " + "please report this problem if you can.")); + } catch (...) { + LOG(INFO) << "Unknown exception caught in notify"; + QMessageBox::information( + nullptr, _("Unhandled Exception Thrown"), + _("Oops, an unhandled exception was thrown " + "during the running of the program. This is not a " + "serious problem, it may be the negligence of the programmer, " + "please report this problem if you can.")); + } + return app_done; +} + +} // namespace GpgFrontend::UI diff --git a/src/ui/GpgFrontendApplication.h b/src/ui/GpgFrontendApplication.h new file mode 100644 index 00000000..52a0a610 --- /dev/null +++ b/src/ui/GpgFrontendApplication.h @@ -0,0 +1,72 @@ +/** + * 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 <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * The source code version of this software was modified and released + * by Saturneric<[email protected]><[email protected]> starting on May 12, 2021. + * + */ + +#include "ui/GpgFrontendUI.h" + +#ifndef GPGFRONTEND_GPGFRONTENDAPPLICATION_H +#define GPGFRONTEND_GPGFRONTENDAPPLICATION_H + +namespace GpgFrontend::UI { + +class GPGFRONTEND_UI_EXPORT GpgFrontendApplication : public QApplication { + Q_OBJECT + public: + /** + * @brief Construct a new GpgFrontend Application object + * + * @param argc + * @param argv + */ + explicit GpgFrontendApplication(int &argc, char **argv); + + /** + * @brief Destroy the GpgFrontend Application object + * + */ + ~GpgFrontendApplication() override = default; + + /** + * @brief Get the GpgFrontend Application object + * + * @return GpgFrontendApplication* + */ + static GpgFrontendApplication *GetInstance(int argc = 0, + char *argv[] = nullptr, + bool new_instance = false); + + protected: + /** + * @brief + * + * @param event + * @return bool + */ + bool notify(QObject *receiver, QEvent *event) override; +}; + +} // namespace GpgFrontend::UI + +#endif // GPGFRONTEND_GPGFRONTENDAPPLICATION_H
\ No newline at end of file diff --git a/src/ui/GpgFrontendUIInit.cpp b/src/ui/GpgFrontendUIInit.cpp index e7751ee6..022f0748 100644 --- a/src/ui/GpgFrontendUIInit.cpp +++ b/src/ui/GpgFrontendUIInit.cpp @@ -35,18 +35,41 @@ #include "ui/UserInterfaceUtils.h" #include "ui/main_window/MainWindow.h" +#if !defined(RELEASE) && defined(WINDOWS) +#include "core/function/GlobalSettingStation.h" +#endif + // init easyloggingpp library INITIALIZE_EASYLOGGINGPP namespace GpgFrontend::UI { -extern void init_logging(); +extern void init_logging_system(); extern void init_locale(); -void InitGpgFrontendUI() { +void InitGpgFrontendUI(QApplication* app) { + // init logging system + init_logging_system(); + + // init locale init_locale(); - init_logging(); + +#if !defined(RELEASE) && defined(WINDOWS) + // css + std::filesystem::path css_path = + GpgFrontend::GlobalSettingStation::GetInstance().GetResourceDir() / + "css" / "default.qss"; + QFile file(css_path.u8string().c_str()); + file.open(QFile::ReadOnly); + QString styleSheet = QLatin1String(file.readAll()); + qApp->setStyleSheet(styleSheet); + file.close(); +#endif + + // init signal station SignalStation::GetInstance(); + + // init common utils CommonUtils::GetInstance(); // create the thread to load the gpg context @@ -65,17 +88,16 @@ void InitGpgFrontendUI() { waiting_dialog_label->setWordWrap(true); waiting_dialog->setLabel(waiting_dialog_label); waiting_dialog->resize(420, 120); - QApplication::connect(init_ctx_task, - &Thread::CtxCheckTask::SignalTaskFinished, - waiting_dialog, [=]() { - LOG(INFO) << "Gpg context loaded"; - waiting_dialog->finished(0); - waiting_dialog->deleteLater(); - }); - - QApplication::connect(waiting_dialog, &QProgressDialog::canceled, [=]() { + app->connect(init_ctx_task, &Thread::CtxCheckTask::SignalTaskFinished, + waiting_dialog, [=]() { + LOG(INFO) << "Gpg context loaded"; + waiting_dialog->finished(0); + waiting_dialog->deleteLater(); + }); + + app->connect(waiting_dialog, &QProgressDialog::canceled, [=]() { LOG(INFO) << "cancel clicked"; - QCoreApplication::quit(); + app->quit(); exit(0); }); @@ -86,9 +108,8 @@ void InitGpgFrontendUI() { // new local event looper QEventLoop looper; - QApplication::connect(init_ctx_task, - &Thread::CtxCheckTask::SignalTaskFinished, &looper, - &QEventLoop::quit); + app->connect(init_ctx_task, &Thread::CtxCheckTask::SignalTaskFinished, + &looper, &QEventLoop::quit); // start the thread to load the gpg context Thread::TaskRunnerGetter::GetInstance().GetTaskRunner()->PostTask( @@ -98,36 +119,47 @@ void InitGpgFrontendUI() { looper.exec(); } -int RunGpgFrontendUI() { +int RunGpgFrontendUI(QApplication* app) { // create main window and show it auto main_window = std::make_unique<GpgFrontend::UI::MainWindow>(); main_window->Init(); + LOG(INFO) << "Main window inited"; main_window->show(); - return QApplication::exec(); + // start the main event loop + return app->exec(); } -void init_logging() { +void init_logging_system() { using namespace boost::posix_time; using namespace boost::gregorian; - ptime now = second_clock::local_time(); - el::Loggers::addFlag(el::LoggingFlag::AutoSpacing); + el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput); + el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck); + el::Configurations defaultConf; defaultConf.setToDefault(); - el::Loggers::reconfigureLogger("default", defaultConf); // apply settings defaultConf.setGlobally(el::ConfigurationType::Format, - "%datetime %level %func %msg"); + "%datetime %level [ui] {%func} -> %msg"); + + // apply settings no written to file + defaultConf.setGlobally(el::ConfigurationType::ToFile, "false"); + + // apply settings + el::Loggers::reconfigureLogger("default", defaultConf)->reconfigure(); // get the log directory - auto logfile_path = - (GlobalSettingStation::GetInstance().GetLogDir() / to_iso_string(now)); + auto logfile_path = (GlobalSettingStation::GetInstance().GetLogDir() / + to_iso_string(second_clock::local_time())); logfile_path.replace_extension(".log"); defaultConf.setGlobally(el::ConfigurationType::Filename, logfile_path.u8string()); + // apply settings written to file + defaultConf.setGlobally(el::ConfigurationType::ToFile, "false"); + el::Loggers::reconfigureLogger("default", defaultConf); LOG(INFO) << _("log file path") << logfile_path; diff --git a/src/ui/GpgFrontendUIInit.h b/src/ui/GpgFrontendUIInit.h index d7b6390d..9b490c0f 100644 --- a/src/ui/GpgFrontendUIInit.h +++ b/src/ui/GpgFrontendUIInit.h @@ -37,12 +37,12 @@ namespace GpgFrontend::UI { * @brief init the UI library * */ -void GPGFRONTEND_UI_EXPORT InitGpgFrontendUI(); +void GPGFRONTEND_UI_EXPORT InitGpgFrontendUI(QApplication *); /** * @brief run main window */ -int GPGFRONTEND_UI_EXPORT RunGpgFrontendUI(); +int GPGFRONTEND_UI_EXPORT RunGpgFrontendUI(QApplication *); }; // namespace GpgFrontend::UI diff --git a/src/ui/KeyMgmt.h b/src/ui/KeyMgmt.h index ad58a5aa..25ee80c5 100755 --- a/src/ui/KeyMgmt.h +++ b/src/ui/KeyMgmt.h @@ -29,9 +29,9 @@ #ifndef __KEYMGMT_H__ #define __KEYMGMT_H__ -#include "import_export/KeyImportDetailDialog.h" -#include "import_export/KeyServerImportDialog.h" #include "ui/GpgFrontendUI.h" +#include "ui/import_export/KeyImportDetailDialog.h" +#include "ui/import_export/KeyServerImportDialog.h" #include "ui/key_generate/KeygenDialog.h" #include "ui/keypair_details/KeyDetailsDialog.h" #include "ui/widgets/KeyList.h" diff --git a/src/ui/details/VerifyDetailsDialog.cpp b/src/ui/details/VerifyDetailsDialog.cpp index 14407396..d2af4ee1 100644 --- a/src/ui/details/VerifyDetailsDialog.cpp +++ b/src/ui/details/VerifyDetailsDialog.cpp @@ -52,10 +52,8 @@ void VerifyDetailsDialog::slot_refresh() { // Button Box for close button button_box_ = new QDialogButtonBox(QDialogButtonBox::Close); - connect(button_box_, &QDialogButtonBox::rejected, this, &VerifyDetailsDialog::close); - - mVboxLayout->addWidget(new QLabel(QString::fromStdString( - std::string(_("Status")) + ": " + gpgme_strerror(error_)))); + connect(button_box_, &QDialogButtonBox::rejected, this, + &VerifyDetailsDialog::close); auto sign = m_result_->signatures; diff --git a/src/ui/help/AboutDialog.cpp b/src/ui/help/AboutDialog.cpp index bcb397cc..e8fbeb1b 100644 --- a/src/ui/help/AboutDialog.cpp +++ b/src/ui/help/AboutDialog.cpp @@ -30,7 +30,8 @@ #include "GpgFrontendBuildInfo.h" #include "core/function/GlobalSettingStation.h" -#include "ui/thread/VersionCheckThread.h" +#include "core/thread/TaskRunnerGetter.h" +#include "ui/thread/VersionCheckTask.h" namespace GpgFrontend::UI { @@ -115,7 +116,7 @@ TranslatorsTab::TranslatorsTab(QWidget* parent) : QWidget(parent) { GlobalSettingStation::GetInstance().GetResourceDir() / "TRANSLATORS"; translators_qfile.setFileName(translators_file.u8string().c_str()); #ifdef LINUX - if(!translators_qfile.exists()) { + if (!translators_qfile.exists()) { translators_qfile.setFileName("/usr/local/share/GpgFrontend/TRANSLATORS"); } #endif @@ -198,14 +199,14 @@ void UpdateTab::getLatestVersion() { LOG(INFO) << _("try to get latest version"); - auto version_thread = new VersionCheckThread(); + auto* version_task = new VersionCheckTask(); - connect(version_thread, &VersionCheckThread::finished, version_thread, - &VersionCheckThread::deleteLater); - connect(version_thread, &VersionCheckThread::SignalUpgradeVersion, this, + connect(version_task, &VersionCheckTask::SignalUpgradeVersion, this, &UpdateTab::slot_show_version_status); - version_thread->start(); + Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Network) + ->PostTask(version_task); } void UpdateTab::slot_show_version_status(const SoftwareVersion& version) { @@ -221,7 +222,7 @@ void UpdateTab::slot_show_version_status(const SoftwareVersion& version) { "github.")) + "</center><center>" + _("Please click") + " <a " - "href=\"https://github.com/saturneric/GpgFrontend/releases\">" + + "href=\"https://www.gpgfrontend.pub/#/downloads\">" + _("Here") + "</a> " + _("to download the latest stable version.") + "</center>"); upgrade_label_->show(); @@ -244,7 +245,7 @@ void UpdateTab::slot_show_version_status(const SoftwareVersion& version) { "stability, please do not use this version.")) + "</center><center>" + _("Please click") + " <a " - "href=\"https://github.com/saturneric/GpgFrontend/releases\">" + + "href=\"https://www.gpgfrontend.pub/#/downloads\">" + _("Here") + "</a> " + _("to download the latest stable version.") + "</center>"); upgrade_label_->show(); diff --git a/src/ui/key_generate/KeygenDialog.cpp b/src/ui/key_generate/KeygenDialog.cpp index 676539c7..d5ca801d 100644 --- a/src/ui/key_generate/KeygenDialog.cpp +++ b/src/ui/key_generate/KeygenDialog.cpp @@ -160,7 +160,7 @@ void KeyGenDialog::slot_key_gen_accept() { emit SignalKeyGenerated(); this->close(); } else { - QMessageBox::critical(this, _("Failure"), _(gpgme_strerror(error))); + QMessageBox::critical(this, _("Failure"), _("Key generation failed.")); } } else { diff --git a/src/ui/key_generate/SubkeyGenerateDialog.cpp b/src/ui/key_generate/SubkeyGenerateDialog.cpp index 451c6521..2b9e076d 100644 --- a/src/ui/key_generate/SubkeyGenerateDialog.cpp +++ b/src/ui/key_generate/SubkeyGenerateDialog.cpp @@ -285,7 +285,7 @@ void SubkeyGenerateDialog::slot_key_gen_accept() { emit SignalSubKeyGenerated(); this->close(); } else - QMessageBox::critical(this, _("Failure"), _(gpgme_strerror(error))); + QMessageBox::critical(this, _("Failure"), _("Failed to generate key.")); } else { /** diff --git a/src/ui/keypair_details/KeySetExpireDateDialog.cpp b/src/ui/keypair_details/KeySetExpireDateDialog.cpp index 785dce14..f2ccc240 100644 --- a/src/ui/keypair_details/KeySetExpireDateDialog.cpp +++ b/src/ui/keypair_details/KeySetExpireDateDialog.cpp @@ -84,7 +84,9 @@ void KeySetExpireDateDialog::slot_confirm() { this->close(); } else { - QMessageBox::critical(this, _("Failure"), _(gpgme_strerror(err))); + QMessageBox::critical( + this, _("Failure"), + _("Failed to update the expire date of the key pair.")); } } diff --git a/src/ui/main_window/MainWindow.cpp b/src/ui/main_window/MainWindow.cpp index 368c5630..d04e3dbd 100644 --- a/src/ui/main_window/MainWindow.cpp +++ b/src/ui/main_window/MainWindow.cpp @@ -28,13 +28,11 @@ #include "MainWindow.h" -#include "ui/UserInterfaceUtils.h" -#ifdef RELEASE -#include "ui/thread/VersionCheckThread.h" -#endif #include "core/function/GlobalSettingStation.h" #include "ui/SignalStation.h" +#include "ui/UserInterfaceUtils.h" #include "ui/struct/SettingsObject.h" +#include "ui/thread/VersionCheckTask.h" namespace GpgFrontend::UI { @@ -85,14 +83,6 @@ void MainWindow::Init() noexcept { restore_settings(); - // open filename if provided as first command line parameter - QStringList args = qApp->arguments(); - if (args.size() > 1) { - if (!args[1].startsWith("-")) { - if (QFile::exists(args[1])) - edit_->LoadFile(args[1]); - } - } edit_->CurTextPage()->setFocus(); auto &settings = GlobalSettingStation::GetInstance().GetUISettings(); @@ -122,16 +112,14 @@ void MainWindow::Init() noexcept { // if not prohibit update checking if (!prohibit_update_checking_) { -#ifdef RELEASE - auto version_thread = new VersionCheckThread(); + auto *version_task = new VersionCheckTask(); - connect(version_thread, &VersionCheckThread::finished, version_thread, - &VersionCheckThread::deleteLater); - connect(version_thread, &VersionCheckThread::SignalUpgradeVersion, this, + connect(version_task, &VersionCheckTask::SignalUpgradeVersion, this, &MainWindow::slot_version_upgrade); - version_thread->start(); -#endif + Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Network) + ->PostTask(version_task); } } catch (...) { @@ -147,7 +135,6 @@ void MainWindow::restore_settings() { LOG(INFO) << _("Called"); try { - LOG(INFO) << "restore settings main_windows_state"; SettingsObject main_windows_state("main_windows_state"); @@ -230,7 +217,6 @@ void MainWindow::restore_settings() { general.lookupValue("save_key_checked", save_key_checked); try { - LOG(INFO) << "restore settings default_key_checked"; // Checked Keys @@ -248,11 +234,6 @@ void MainWindow::restore_settings() { LOG(ERROR) << "restore default_key_checked failed"; } - LOG(INFO) << "restore settings smtp_passport"; - - SettingsObject smtp_passport("smtp_passport"); - smtp_passport.Check("enable", false); - prohibit_update_checking_ = false; try { prohibit_update_checking_ = @@ -267,6 +248,7 @@ void MainWindow::restore_settings() { } GlobalSettingStation::GetInstance().SyncSettings(); + LOG(INFO) << _("settings restored"); } void MainWindow::save_settings() { @@ -329,4 +311,4 @@ void MainWindow::closeEvent(QCloseEvent *event) { // GpgContext::GetInstance().clearPasswordCache(); } -} // namespace GpgFrontend::UI +} // namespace GpgFrontend::UI diff --git a/src/ui/main_window/MainWindow.h b/src/ui/main_window/MainWindow.h index c5ba02a2..a0f1a5d4 100644 --- a/src/ui/main_window/MainWindow.h +++ b/src/ui/main_window/MainWindow.h @@ -53,15 +53,14 @@ class MainWindow : public QMainWindow { Q_OBJECT public: - - struct CryptoMenu{ + struct CryptoMenu { using OperationType = unsigned int; static constexpr OperationType None = 0; static constexpr OperationType Encrypt = 1 << 0; static constexpr OperationType Sign = 1 << 1; static constexpr OperationType Decrypt = 1 << 2; - static constexpr OperationType Verify = 1 << 3; + static constexpr OperationType Verify = 1 << 3; static constexpr OperationType EncryptAndSign = 1 << 4; static constexpr OperationType DecryptAndVerify = 1 << 5; }; @@ -89,7 +88,6 @@ class MainWindow : public QMainWindow { */ void SignalLoaded(); - public slots: /** @@ -371,26 +369,26 @@ class MainWindow : public QMainWindow { append_selected_keys_act_{}; ///< Action to append selected keys to edit QAction* copy_mail_address_to_clipboard_act_{}; ///< Action to copy mail to ///< clipboard - QAction* open_key_management_act_{}; ///< Action to open key management - QAction* copy_act_{}; ///< Action to copy text - QAction* quote_act_{}; ///< Action to quote text - QAction* cut_act_{}; ///< Action to cut text - QAction* paste_act_{}; ///< Action to paste text - QAction* select_all_act_{}; ///< Action to select whole text - QAction* find_act_{}; ///< Action to find text - QAction* undo_act_{}; ///< Action to undo last action - QAction* redo_act_{}; ///< Action to redo last action - QAction* zoom_in_act_{}; ///< Action to zoom in - QAction* zoom_out_act_{}; ///< Action to zoom out - QAction* about_act_{}; ///< Action to open about dialog - QAction* check_update_act_{}; ///< Action to open about dialog - QAction* translate_act_{}; ///< Action to open about dialog - QAction* open_settings_act_{}; ///< Action to open settings dialog - QAction* show_key_details_act_{}; ///< Action to open key-details dialog - QAction* start_wizard_act_{}; ///< Action to open the wizard - QAction* cut_pgp_header_act_{}; ///< Action for cutting the PGP header - QAction* add_pgp_header_act_{}; ///< Action for adding the PGP header - QAction* import_key_from_file_act_{}; ///< + QAction* open_key_management_act_{}; ///< Action to open key management + QAction* copy_act_{}; ///< Action to copy text + QAction* quote_act_{}; ///< Action to quote text + QAction* cut_act_{}; ///< Action to cut text + QAction* paste_act_{}; ///< Action to paste text + QAction* select_all_act_{}; ///< Action to select whole text + QAction* find_act_{}; ///< Action to find text + QAction* undo_act_{}; ///< Action to undo last action + QAction* redo_act_{}; ///< Action to redo last action + QAction* zoom_in_act_{}; ///< Action to zoom in + QAction* zoom_out_act_{}; ///< Action to zoom out + QAction* about_act_{}; ///< Action to open about dialog + QAction* check_update_act_{}; ///< Action to open about dialog + QAction* translate_act_{}; ///< Action to open about dialog + QAction* open_settings_act_{}; ///< Action to open settings dialog + QAction* show_key_details_act_{}; ///< Action to open key-details dialog + QAction* start_wizard_act_{}; ///< Action to open the wizard + QAction* cut_pgp_header_act_{}; ///< Action for cutting the PGP header + QAction* add_pgp_header_act_{}; ///< Action for adding the PGP header + QAction* import_key_from_file_act_{}; ///< QAction* import_key_from_clipboard_act_{}; ///< QAction* import_key_from_key_server_act_{}; ///< diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp index 910a7bf2..0ad52248 100644 --- a/src/ui/main_window/MainWindowSlotFunction.cpp +++ b/src/ui/main_window/MainWindowSlotFunction.cpp @@ -324,56 +324,71 @@ void MainWindow::slot_decrypt() { std::move(result_callback), data_object); } -void MainWindow::slot_find() { - if (edit_->TabCount() == 0 || edit_->CurTextPage() == nullptr) { - return; - } - - // At first close verifynotification, if existing - edit_->SlotCurPageTextEdit()->CloseNoteByClass("findwidget"); - - auto* fw = new FindWidget(this, edit_->CurTextPage()); - edit_->SlotCurPageTextEdit()->ShowNotificationWidget(fw, "findWidget"); -} - void MainWindow::slot_verify() { if (edit_->TabCount() == 0 || edit_->SlotCurPageTextEdit() == nullptr) { if (edit_->SlotCurPageFileTreeView() != nullptr) this->SlotFileVerify(); return; } - auto text = edit_->CurTextPage()->GetTextPage()->toPlainText().toUtf8(); - // TODO(Saturneric) PreventNoDataErr - - auto sig_buffer = std::make_unique<ByteArray>(); - sig_buffer.reset(); - - GpgVerifyResult result = nullptr; - GpgError error; - bool if_error = false; - process_operation( - this, _("Verifying"), [&](Thread::Task::DataObjectPtr) -> int { - try { - auto buffer = text.toStdString(); - error = GpgFrontend::GpgBasicOperator::GetInstance().Verify( - buffer, sig_buffer, result); - } catch (const std::runtime_error& e) { - if_error = true; - } - return 0; - }); - - if (!if_error) { - auto result_analyse = GpgVerifyResultAnalyse(error, result); - result_analyse.Analyse(); - process_result_analyse(edit_, info_board_, result_analyse); - - if (result_analyse.GetStatus() == -2) - import_unknown_key_from_keyserver(this, result_analyse); - - if (result_analyse.GetStatus() >= 0) - show_verify_details(this, info_board_, error, result); - } + // data to transfer into task + auto data_object = std::make_shared<Thread::Task::DataObject>(); + + // set input buffer + auto buffer = + edit_->CurTextPage()->GetTextPage()->toPlainText().toStdString(); + data_object->AppendObject(std::move(buffer)); + + auto verify_runner = [](Thread::Task::DataObjectPtr data_object) -> int { + // check the size of the data object + if (data_object == nullptr || data_object->GetObjectSize() != 1) + throw std::runtime_error("Invalid data object size"); + + auto buffer = data_object->PopObject<std::string>(); + + LOG(INFO) << "Verify buffer: " << buffer.size(); + + try { + GpgVerifyResult verify_result = nullptr; + auto sig_buffer = std::unique_ptr<ByteArray>(nullptr); + GpgError error = GpgFrontend::GpgBasicOperator::GetInstance().Verify( + buffer, sig_buffer, verify_result); + + data_object->AppendObject(std::move(verify_result)); + data_object->AppendObject(std::move(error)); + } catch (const std::runtime_error& e) { + return -1; + } + return 0; + }; + + auto result_callback = [this](int rtn, + Thread::Task::DataObjectPtr data_object) { + if (!rtn) { + if (data_object == nullptr || data_object->GetObjectSize() != 2) + throw std::runtime_error("Invalid data object size"); + auto error = data_object->PopObject<GpgError>(); + auto verify_result = data_object->PopObject<GpgVerifyResult>(); + + auto result_analyse = GpgVerifyResultAnalyse(error, verify_result); + result_analyse.Analyse(); + process_result_analyse(edit_, info_board_, result_analyse); + + if (check_gpg_error_2_err_code(error) == GPG_ERR_NO_ERROR) { + if (result_analyse.GetStatus() == -2) + import_unknown_key_from_keyserver(this, result_analyse); + + if (result_analyse.GetStatus() >= 0) + show_verify_details(this, info_board_, error, verify_result); + } + } else { + QMessageBox::critical(this, _("Error"), + _("An error occurred during operation.")); + return; + } + }; + + process_operation(this, _("Verifying"), verify_runner, result_callback, + data_object); } void MainWindow::slot_encrypt_sign() { @@ -423,59 +438,77 @@ void MainWindow::slot_encrypt_sign() { LOG(INFO) << "Signers " << signer.GetEmail(); } - GpgEncrResult encr_result = nullptr; - GpgSignResult sign_result = nullptr; - GpgError error; - bool if_error = false; - - auto tmp = std::make_unique<ByteArray>(); - process_operation( - this, _("Encrypting and Signing"), - [&](Thread::Task::DataObjectPtr) -> int { - try { - auto buffer = edit_->CurTextPage() - ->GetTextPage() - ->toPlainText() - .toUtf8() - .toStdString(); - error = GpgFrontend::GpgBasicOperator::GetInstance().EncryptSign( - std::move(keys), std::move(signer_keys), buffer, tmp, encr_result, - sign_result); - } catch (const std::runtime_error& e) { - if_error = true; - } - return 0; - }); - - if (!if_error) { -#ifdef ADVANCE_SUPPORT - if (settings.value("advanced/autoPubkeyExchange").toBool()) { - PubkeyUploader pubkeyUploader(mCtx, signerKeys); - pubkeyUploader.start(); - if (!pubkeyUploader.result()) { - QMessageBox::warning(nullptr, _("Automatic Key Exchange Warning"), - _("Part of the automatic key exchange failed, " - "which may be related to your key.") + - _("If possible, try to use the RSA algorithm " - "compatible with the server for signing.")); - } + // data to transfer into task + auto data_object = std::make_shared<Thread::Task::DataObject>(); + + // set input buffer + auto buffer = + edit_->CurTextPage()->GetTextPage()->toPlainText().toStdString(); + data_object->AppendObject(std::move(buffer)); + // push the keys into data object + data_object->AppendObject(std::move(keys)); + data_object->AppendObject(std::move(signer_keys)); + + auto encrypt_sign_runner = + [](Thread::Task::DataObjectPtr data_object) -> int { + // check the size of the data object + if (data_object == nullptr || data_object->GetObjectSize() != 3) + throw std::runtime_error("Invalid data object size"); + + auto signer_keys = data_object->PopObject<KeyListPtr>(); + auto keys = data_object->PopObject<KeyListPtr>(); + auto buffer = data_object->PopObject<std::string>(); + try { + GpgEncrResult encr_result = nullptr; + GpgSignResult sign_result = nullptr; + auto tmp = std::make_unique<ByteArray>(); + GpgError error = GpgFrontend::GpgBasicOperator::GetInstance().EncryptSign( + std::move(keys), std::move(signer_keys), buffer, tmp, encr_result, + sign_result); + + data_object->AppendObject(std::move(tmp)); + data_object->AppendObject(std::move(sign_result)); + data_object->AppendObject(std::move(encr_result)); + data_object->AppendObject(std::move(error)); + + } catch (const std::runtime_error& e) { + return -1; } -#endif - LOG(INFO) << "GpgResultAnalyse Started"; - auto encrypt_res = GpgEncryptResultAnalyse(error, std::move(encr_result)); - auto sign_res = GpgSignResultAnalyse(error, std::move(sign_result)); - encrypt_res.Analyse(); - sign_res.Analyse(); - process_result_analyse(edit_, info_board_, encrypt_res, sign_res); - if (check_gpg_error_2_err_code(error) == GPG_ERR_NO_ERROR) - edit_->SlotFillTextEditWithText(QString::fromStdString(*tmp)); - - info_board_->ResetOptionActionsMenu(); - } else { - QMessageBox::critical(this, _("Error"), - _("An error occurred during operation.")); - return; - } + return 0; + }; + + auto result_callback = [this](int rtn, + Thread::Task::DataObjectPtr data_object) { + if (!rtn) { + if (data_object == nullptr || data_object->GetObjectSize() != 4) + throw std::runtime_error("Invalid data object size"); + auto error = data_object->PopObject<GpgError>(); + auto encrypt_result = data_object->PopObject<GpgEncrResult>(); + auto sign_result = data_object->PopObject<GpgSignResult>(); + auto tmp = data_object->PopObject<std::unique_ptr<ByteArray>>(); + + LOG(INFO) << "GpgResultAnalyse Started"; + auto encrypt_result_analyse = + GpgEncryptResultAnalyse(error, std::move(encrypt_result)); + auto sign_result_analyse = + GpgSignResultAnalyse(error, std::move(sign_result)); + encrypt_result_analyse.Analyse(); + sign_result_analyse.Analyse(); + process_result_analyse(edit_, info_board_, encrypt_result_analyse, + sign_result_analyse); + if (check_gpg_error_2_err_code(error) == GPG_ERR_NO_ERROR) + edit_->SlotFillTextEditWithText(QString::fromStdString(*tmp)); + + info_board_->ResetOptionActionsMenu(); + } else { + QMessageBox::critical(this, _("Error"), + _("An error occurred during operation.")); + return; + } + }; + + process_operation(this, _("Encrypting and Signing"), encrypt_sign_runner, + result_callback, data_object); } void MainWindow::slot_decrypt_verify() { @@ -485,72 +518,87 @@ void MainWindow::slot_decrypt_verify() { return; } - QString plainText = edit_->CurTextPage()->GetTextPage()->toPlainText(); + // data to transfer into task + auto data_object = std::make_shared<Thread::Task::DataObject>(); -#ifdef ADVANCE_SUPPORT - if (plainText.trimmed().startsWith( - GpgConstants::GPG_FRONTEND_SHORT_CRYPTO_HEAD)) { - auto cryptoText = getCryptText(plainText); - if (!cryptoText.isEmpty()) { - plainText = cryptoText; + // set input buffer + auto buffer = + edit_->CurTextPage()->GetTextPage()->toPlainText().toStdString(); + data_object->AppendObject(std::move(buffer)); + + auto decrypt_verify_runner = + [](Thread::Task::DataObjectPtr data_object) -> int { + // check the size of the data object + if (data_object == nullptr || data_object->GetObjectSize() != 1) + throw std::runtime_error("Invalid data object size"); + + auto buffer = data_object->PopObject<std::string>(); + try { + GpgDecrResult decrypt_result = nullptr; + GpgVerifyResult verify_result = nullptr; + auto decrypted_buffer = std::make_unique<ByteArray>(); + GpgError error = GpgBasicOperator::GetInstance().DecryptVerify( + buffer, decrypted_buffer, decrypt_result, verify_result); + + data_object->AppendObject(std::move(decrypted_buffer)); + data_object->AppendObject(std::move(verify_result)); + data_object->AppendObject(std::move(decrypt_result)); + data_object->AppendObject(std::move(error)); + } catch (const std::runtime_error& e) { + LOG(ERROR) << e.what(); + return -1; } - } -#endif + return 0; + }; - QByteArray text = plainText.toUtf8(); + auto result_callback = [this](int rtn, + Thread::Task::DataObjectPtr data_object) { + if (!rtn) { + if (data_object == nullptr || data_object->GetObjectSize() != 4) + throw std::runtime_error("Invalid data object size"); - GpgDecrResult d_result = nullptr; - GpgVerifyResult v_result = nullptr; - gpgme_error_t error; - bool if_error = false; + auto error = data_object->PopObject<GpgError>(); + auto decrypt_result = data_object->PopObject<GpgDecrResult>(); + auto verify_result = data_object->PopObject<GpgVerifyResult>(); + auto decrypted = data_object->PopObject<std::unique_ptr<ByteArray>>(); -#ifdef ADVANCE_SUPPORT - // Automatically import public keys that are not stored locally - if (settings.value("advanced/autoPubkeyExchange").toBool()) { - gpgme_verify_result_t tmp_v_result = nullptr; - auto thread = QThread::create([&](Thread::Task::DataObjectPtr) -> int { - mCtx->verify(&text, nullptr, &tmp_v_result); - }); - thread->start(); - while (thread->isRunning()) QApplication::processEvents(); - auto* checker = new UnknownSignersChecker(mCtx, tmp_v_result); - checker->start(); - checker->deleteLater(); - } -#endif - auto decrypted = std::make_unique<ByteArray>(); - process_operation(this, _("Decrypting and Verifying"), - [&](Thread::Task::DataObjectPtr) -> int { - try { - auto buffer = text.toStdString(); - error = GpgBasicOperator::GetInstance().DecryptVerify( - buffer, decrypted, d_result, v_result); - } catch (const std::runtime_error& e) { - if_error = true; - } - return 0; - }); - - if (!if_error) { - auto decrypt_res = GpgDecryptResultAnalyse(error, std::move(d_result)); - auto verify_res = GpgVerifyResultAnalyse(error, v_result); - decrypt_res.Analyse(); - verify_res.Analyse(); - process_result_analyse(edit_, info_board_, decrypt_res, verify_res); - if (check_gpg_error_2_err_code(error) == GPG_ERR_NO_ERROR) - edit_->SlotFillTextEditWithText(QString::fromStdString(*decrypted)); - - if (verify_res.GetStatus() == -2) - import_unknown_key_from_keyserver(this, verify_res); - - if (verify_res.GetStatus() >= 0) - show_verify_details(this, info_board_, error, v_result); + auto decrypt_result_analyse = + GpgDecryptResultAnalyse(error, std::move(decrypt_result)); + auto verify_result_analyse = GpgVerifyResultAnalyse(error, verify_result); + decrypt_result_analyse.Analyse(); + verify_result_analyse.Analyse(); + process_result_analyse(edit_, info_board_, decrypt_result_analyse, + verify_result_analyse); + if (check_gpg_error_2_err_code(error) == GPG_ERR_NO_ERROR) + edit_->SlotFillTextEditWithText(QString::fromStdString(*decrypted)); - } else { - QMessageBox::critical(this, _("Error"), - _("An error occurred during operation.")); + if (verify_result_analyse.GetStatus() == -2) + import_unknown_key_from_keyserver(this, verify_result_analyse); + + if (verify_result_analyse.GetStatus() >= 0) + show_verify_details(this, info_board_, error, verify_result); + + } else { + QMessageBox::critical(this, _("Error"), + _("An error occurred during operation.")); + return; + } + }; + + process_operation(this, _("Decrypting and Verifying"), decrypt_verify_runner, + result_callback, data_object); +} + +void MainWindow::slot_find() { + if (edit_->TabCount() == 0 || edit_->CurTextPage() == nullptr) { return; } + + // At first close verifynotification, if existing + edit_->SlotCurPageTextEdit()->CloseNoteByClass("findwidget"); + + auto* fw = new FindWidget(this, edit_->CurTextPage()); + edit_->SlotCurPageTextEdit()->ShowNotificationWidget(fw, "findWidget"); } /* @@ -613,7 +661,13 @@ void MainWindow::upload_key_to_server() { void MainWindow::SlotOpenFile(QString& path) { edit_->SlotOpenFile(path); } void MainWindow::slot_version_upgrade(const SoftwareVersion& version) { - LOG(INFO) << _("called"); + LOG(INFO) << _("Called"); + + if (!version.InfoVaild()) { + LOG(INFO) << "Invalid version info"; + return; + } + if (version.NeedUpgrade()) { statusBar()->showMessage( QString(_("GpgFrontend Upgradeable (New Version: %1).")) diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp index fa5e6de3..7d798c8b 100644 --- a/src/ui/main_window/MainWindowUI.cpp +++ b/src/ui/main_window/MainWindowUI.cpp @@ -53,7 +53,8 @@ void MainWindow::create_actions() { browser_act_->setIcon(QIcon(":file-browser.png")); browser_act_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); browser_act_->setToolTip(_("Open a file browser")); - connect(browser_act_, &QAction::triggered, this, &MainWindow::slot_open_file_tab); + connect(browser_act_, &QAction::triggered, this, + &MainWindow::slot_open_file_tab); save_act_ = new QAction(_("Save File"), this); save_act_->setIcon(QIcon(":filesave.png")); @@ -135,7 +136,8 @@ void MainWindow::create_actions() { select_all_act_->setIcon(QIcon(":edit.png")); select_all_act_->setShortcut(QKeySequence::SelectAll); select_all_act_->setToolTip(_("Select the whole text")); - connect(select_all_act_, &QAction::triggered, edit_, &TextEdit::SlotSelectAll); + connect(select_all_act_, &QAction::triggered, edit_, + &TextEdit::SlotSelectAll); find_act_ = new QAction(_("Find"), this); find_act_->setShortcut(QKeySequence::Find); @@ -153,6 +155,7 @@ void MainWindow::create_actions() { open_settings_act_ = new QAction(_("Settings"), this); open_settings_act_->setToolTip(_("Open settings dialog")); + open_settings_act_->setMenuRole(QAction::PreferencesRole); open_settings_act_->setShortcut(QKeySequence::Preferences); connect(open_settings_act_, &QAction::triggered, this, &MainWindow::slot_open_settings_dialog); @@ -244,6 +247,7 @@ void MainWindow::create_actions() { about_act_ = new QAction(_("About"), this); about_act_->setIcon(QIcon(":help.png")); about_act_->setToolTip(_("Show the application's About box")); + about_act_->setMenuRole(QAction::AboutRole); connect(about_act_, &QAction::triggered, this, [=]() { new AboutDialog(0, this); }); @@ -269,8 +273,7 @@ void MainWindow::create_actions() { /* Popup-Menu-Action for KeyList */ - append_selected_keys_act_ = - new QAction(_("Append To Text Editor"), this); + append_selected_keys_act_ = new QAction(_("Append To Text Editor"), this); append_selected_keys_act_->setToolTip( _("Append The Selected Public Key To Text in Editor")); connect(append_selected_keys_act_, &QAction::triggered, this, diff --git a/src/ui/settings/SettingsDialog.cpp b/src/ui/settings/SettingsDialog.cpp index bf3ce6a8..eefdd3c7 100644 --- a/src/ui/settings/SettingsDialog.cpp +++ b/src/ui/settings/SettingsDialog.cpp @@ -29,12 +29,12 @@ #include "SettingsDialog.h" #include "core/function/GlobalSettingStation.h" +#include "ui/main_window/MainWindow.h" #include "ui/settings/SettingsAdvanced.h" #include "ui/settings/SettingsAppearance.h" #include "ui/settings/SettingsGeneral.h" #include "ui/settings/SettingsKeyServer.h" #include "ui/settings/SettingsNetwork.h" -#include "ui/main_window/MainWindow.h" namespace GpgFrontend::UI { @@ -45,31 +45,39 @@ SettingsDialog::SettingsDialog(QWidget* parent) : QDialog(parent) { key_server_tab_ = new KeyserverTab(); network_tab_ = new NetworkTab(); + auto* mainLayout = new QVBoxLayout; + mainLayout->addWidget(tab_widget_); + mainLayout->stretch(0); + tab_widget_->addTab(general_tab_, _("General")); tab_widget_->addTab(appearance_tab_, _("Appearance")); tab_widget_->addTab(key_server_tab_, _("Key Server")); tab_widget_->addTab(network_tab_, _("Network")); +#ifndef MACOS button_box_ = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - - connect(button_box_, &QDialogButtonBox::accepted, this, &SettingsDialog::SlotAccept); - connect(button_box_, &QDialogButtonBox::rejected, this, &SettingsDialog::reject); - - auto* mainLayout = new QVBoxLayout; - mainLayout->addWidget(tab_widget_); - mainLayout->stretch(0); + connect(button_box_, &QDialogButtonBox::accepted, this, + &SettingsDialog::SlotAccept); + connect(button_box_, &QDialogButtonBox::rejected, this, + &SettingsDialog::reject); mainLayout->addWidget(button_box_); mainLayout->stretch(0); - setLayout(mainLayout); - setWindowTitle(_("Settings")); +#else + connect(this, &QDialog::finished, this, &SettingsDialog::SlotAccept); + connect(this, &QDialog::finished, this, &SettingsDialog::deleteLater); + setWindowTitle(_("Preference")); +#endif + + setLayout(mainLayout); // slots for handling the restart needed member this->slot_set_restart_needed(false); connect(general_tab_, &GeneralTab::SignalRestartNeeded, this, &SettingsDialog::slot_set_restart_needed); - connect(this, &SettingsDialog::SignalRestartNeeded, qobject_cast<MainWindow *>(parent), &MainWindow::SlotSetRestartNeeded); + connect(this, &SettingsDialog::SignalRestartNeeded, + qobject_cast<MainWindow*>(parent), &MainWindow::SlotSetRestartNeeded); this->setMinimumSize(480, 680); this->adjustSize(); diff --git a/src/ui/struct/SoftwareVersion.h b/src/ui/struct/SoftwareVersion.h index 04300053..da93f8c6 100644 --- a/src/ui/struct/SoftwareVersion.h +++ b/src/ui/struct/SoftwareVersion.h @@ -54,6 +54,14 @@ struct SoftwareVersion { * @return true * @return false */ + [[nodiscard]] bool InfoVaild() const { return load_info_done; } + + /** + * @brief + * + * @return true + * @return false + */ [[nodiscard]] bool NeedUpgrade() const { return load_info_done && !latest_prerelease && !latest_draft && current_version < latest_version; diff --git a/src/ui/thread/VersionCheckThread.cpp b/src/ui/thread/VersionCheckTask.cpp index 6d73417d..7de3b511 100644 --- a/src/ui/thread/VersionCheckThread.cpp +++ b/src/ui/thread/VersionCheckTask.cpp @@ -26,45 +26,58 @@ * */ -#include "VersionCheckThread.h" +#include "VersionCheckTask.h" #include <QMetaType> -#include <nlohmann/json.hpp> +#include <memory> #include "GpgFrontendBuildInfo.h" namespace GpgFrontend::UI { -void VersionCheckThread::run() { - auto current_version = std::string("v") + std::to_string(VERSION_MAJOR) + - "." + std::to_string(VERSION_MINOR) + "." + - std::to_string(VERSION_PATCH); - - SoftwareVersion version; - version.current_version = current_version; +VersionCheckTask::VersionCheckTask() + : network_manager_(new QNetworkAccessManager(this)), + current_version_(std::string("v") + std::to_string(VERSION_MAJOR) + "." + + std::to_string(VERSION_MINOR) + "." + + std::to_string(VERSION_PATCH)) { + qRegisterMetaType<SoftwareVersion>("SoftwareVersion"); + version_.current_version = current_version_; +} - auto manager = std::make_unique<QNetworkAccessManager>(nullptr); +void VersionCheckTask::Run() { + SetFinishAfterRun(false); try { using namespace nlohmann; - LOG(INFO) << "current version" << current_version; - + LOG(INFO) << "current version" << current_version_; std::string latest_version_url = "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; - std::string current_version_url = - "https://api.github.com/repos/saturneric/gpgfrontend/releases/tags/" + - current_version; - QNetworkRequest latest_request, current_request; + QNetworkRequest latest_request; latest_request.setUrl(QUrl(latest_version_url.c_str())); - current_request.setUrl(QUrl(current_version_url.c_str())); - auto _reply = manager->get(latest_request); - while (_reply->isRunning()) QApplication::processEvents(); - if (_reply->error() != QNetworkReply::NoError) { - LOG(ERROR) << "current version request error"; - version.latest_version = current_version; + latest_reply_ = network_manager_->get(latest_request); + connect(latest_reply_, &QNetworkReply::finished, this, + &VersionCheckTask::slot_parse_latest_version_info); + + // loading done + version_.load_info_done = true; + + } catch (...) { + emit SignalTaskFinished(); + } +} + +void VersionCheckTask::slot_parse_latest_version_info() { + version_.current_version = current_version_; + + try { + if (latest_reply_ == nullptr || + latest_reply_->error() != QNetworkReply::NoError) { + LOG(ERROR) << "latest version request error"; + version_.latest_version = current_version_; } else { - latest_reply_bytes_ = _reply->readAll(); + latest_reply_bytes_ = latest_reply_->readAll(); + auto latest_reply_json = nlohmann::json::parse(latest_reply_bytes_.toStdString()); @@ -78,7 +91,7 @@ void VersionCheckThread::run() { latest_version = version_match.captured(0).toStdString(); LOG(INFO) << "latest version matched" << latest_version; } else { - latest_version = current_version; + latest_version = current_version_; LOG(WARNING) << "latest version unknown"; } @@ -86,44 +99,69 @@ void VersionCheckThread::run() { draft = latest_reply_json["draft"]; std::string publish_date = latest_reply_json["published_at"]; std::string release_note = latest_reply_json["body"]; - version.latest_version = latest_version; - version.latest_prerelease = prerelease; - version.latest_draft = draft; - version.publish_date = publish_date; - version.release_note = release_note; + version_.latest_version = latest_version; + version_.latest_prerelease = prerelease; + version_.latest_draft = draft; + version_.publish_date = publish_date; + version_.release_note = release_note; } + } catch (...) { + LOG(INFO) << "error occurred"; + version_.load_info_done = false; + } - _reply->deleteLater(); + if (latest_reply_ != nullptr) { + latest_reply_->deleteLater(); + } - _reply = manager->get(current_request); - while (_reply->isRunning()) QApplication::processEvents(); - current_reply_bytes_ = _reply->readAll(); - if (_reply->error() != QNetworkReply::NoError) { + try { + std::string current_version_url = + "https://api.github.com/repos/saturneric/gpgfrontend/releases/tags/" + + current_version_; + + QNetworkRequest current_request; + current_request.setUrl(QUrl(current_version_url.c_str())); + current_reply_ = network_manager_->get(current_request); + + connect(current_reply_, &QNetworkReply::finished, this, + &VersionCheckTask::slot_parse_current_version_info); + } catch (...) { + LOG(ERROR) << "current version request create error"; + emit SignalTaskFinished(); + } +} + +void VersionCheckTask::slot_parse_current_version_info() { + try { + if (current_reply_ == nullptr || + current_reply_->error() != QNetworkReply::NoError) { LOG(ERROR) << "current version request network error"; - version.current_version_found = false; + version_.current_version_found = false; } else { - version.current_version_found = true; + version_.current_version_found = true; + current_reply_bytes_ = current_reply_->readAll(); + LOG(INFO) << "current version" << current_reply_bytes_.size(); auto current_reply_json = nlohmann::json::parse(current_reply_bytes_.toStdString()); bool current_prerelease = current_reply_json["prerelease"], current_draft = current_reply_json["draft"]; - version.latest_prerelease = current_prerelease; - version.latest_draft = current_draft; + version_.latest_prerelease = current_prerelease; + version_.latest_draft = current_draft; + version_.load_info_done = true; } - _reply->deleteLater(); - - // loading done - version.load_info_done = true; - } catch (...) { LOG(INFO) << "error occurred"; - version.load_info_done = false; + version_.load_info_done = false; } - emit SignalUpgradeVersion(version); -} -VersionCheckThread::VersionCheckThread() : QThread(nullptr) { - qRegisterMetaType<SoftwareVersion>("SoftwareVersion"); -}; + LOG(INFO) << "current version parse done" << version_.current_version_found; + + if (current_reply_ != nullptr) { + current_reply_->deleteLater(); + } + + emit SignalUpgradeVersion(version_); + emit SignalTaskFinished(); +} } // namespace GpgFrontend::UI diff --git a/src/ui/thread/VersionCheckThread.h b/src/ui/thread/VersionCheckTask.h index 6ad35afe..0dbce17f 100644 --- a/src/ui/thread/VersionCheckThread.h +++ b/src/ui/thread/VersionCheckTask.h @@ -29,6 +29,10 @@ #ifndef GPGFRONTEND_VERSIONCHECKTHREAD_H #define GPGFRONTEND_VERSIONCHECKTHREAD_H +#include <memory> +#include <string> + +#include "core/thread/Task.h" #include "ui/GpgFrontendUI.h" #include "ui/struct/SoftwareVersion.h" @@ -38,7 +42,7 @@ namespace GpgFrontend::UI { * @brief * */ -class VersionCheckThread : public QThread { +class VersionCheckTask : public Thread::Task { Q_OBJECT public: @@ -46,7 +50,7 @@ class VersionCheckThread : public QThread { * @brief Construct a new Version Check Thread object * */ - explicit VersionCheckThread(); + explicit VersionCheckTask(); signals: @@ -63,11 +67,30 @@ class VersionCheckThread : public QThread { * */ - void run() override; + void Run() override; + + 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_; ///< + 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_; ///< + std::string current_version_; + SoftwareVersion version_; }; } // namespace GpgFrontend::UI diff --git a/src/ui/widgets/VerifyKeyDetailBox.h b/src/ui/widgets/VerifyKeyDetailBox.h index 18fa7963..57f133d5 100644 --- a/src/ui/widgets/VerifyKeyDetailBox.h +++ b/src/ui/widgets/VerifyKeyDetailBox.h @@ -65,7 +65,7 @@ class VerifyKeyDetailBox : public QGroupBox { */ QGridLayout* create_key_info_grid(const GpgSignature& signature); - std::string fpr_; ///< + std::string fpr_; ///< fingerprint of the key }; } // namespace GpgFrontend::UI |