1
0

Merge pull request #66 from saturneric/develop-2.0.8

Develop 2.0.8.2
This commit is contained in:
Saturn&Eric 2022-05-21 03:13:55 +08:00 committed by GitHub
commit 306cc5b41a
43 changed files with 861 additions and 563 deletions

View File

@ -1,8 +1,8 @@
<!-- _navbar.md --> <!-- _navbar.md -->
* [Source Code(Global CDN)](https://global.git.codesdream.com/GpgFrontend.git) * [Source Code(Global CDN)](https://global.git.codesdream.com/main/GpgFrontend.git)
* [Document](https://doxygen.gpgfrontend.pub) * [Document](https://doxygen.gpgfrontend.pub)
* [Manual](overview.md) * [Manual](overview.md)
* [Download](download.md) * [Downloads](downloads.md)
* [Contract](contract.md) * [Contract](contract.md)

View File

@ -40,9 +40,6 @@ add_library(gpgfrontend_core SHARED ${GPG_SOURCE})
set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GpgFrontendCoreExport.h") set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GpgFrontendCoreExport.h")
generate_export_header(gpgfrontend_core EXPORT_FILE_NAME "${_export_file}") 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 # link third-party libraries
target_link_libraries(gpgfrontend_core PUBLIC config++) target_link_libraries(gpgfrontend_core PUBLIC config++)
if (NOT LINUX) if (NOT LINUX)
@ -75,7 +72,7 @@ else ()
endif () endif ()
# link gnupg libraries # 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 # link openssl
target_link_libraries(gpgfrontend_core PUBLIC OpenSSL::SSL OpenSSL::Crypto) target_link_libraries(gpgfrontend_core PUBLIC OpenSSL::SSL OpenSSL::Crypto)
# link boost libraries # link boost libraries
@ -97,7 +94,8 @@ target_link_libraries(gpgfrontend_core PUBLIC Qt5::Core)
# set up pch # set up pch
target_precompile_headers(gpgfrontend_core target_precompile_headers(gpgfrontend_core
PUBLIC ${CMAKE_SOURCE_DIR}/src/GpgFrontend.h PUBLIC ${CMAKE_SOURCE_DIR}/src/GpgFrontend.h
PUBLIC GpgFrontendCore.h) PUBLIC GpgFrontendCore.h
PUBLIC GpgConstants.h)
# using std c++ 17 # using std c++ 17
target_compile_features(gpgfrontend_core PUBLIC cxx_std_17) target_compile_features(gpgfrontend_core PUBLIC cxx_std_17)

View File

@ -28,10 +28,7 @@
#include "core/GpgConstants.h" #include "core/GpgConstants.h"
#include <gpg-error.h>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <string>
#include "function/FileOperator.h" #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) { gpgme_error_t GpgFrontend::check_gpg_error(gpgme_error_t err) {
if (gpg_err_code(err) != GPG_ERR_NO_ERROR) { if (gpg_err_code(err) != GPG_ERR_NO_ERROR) {
LOG(ERROR) << "[" << _("Error") << " " << gpg_err_code(err) << "] " LOG(ERROR) << "[" << _("Error") << gpg_err_code(err) << "]" << _("Source: ")
<< _("Source: ") << gpgme_strsource(err) << " " << gpgme_strsource(err) << _("Description: ")
<< _("Description: ") << gpgme_strerror(err); << gpgme_strerror(err);
} }
return 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, gpg_err_code_t GpgFrontend::check_gpg_error_2_err_code(gpgme_error_t err,
gpgme_error_t predict) { gpgme_error_t predict) {
auto err_code = gpg_err_code(err); auto err_code = gpg_err_code(err);
if (err_code != predict) { if (err_code != gpg_err_code(predict)) {
LOG(ERROR) << "[" << _("Error") << " " << gpg_err_code(err) << "] " if (err_code == GPG_ERR_NO_ERROR)
<< _("Source: ") << gpgme_strsource(err) << " " LOG(WARNING) << "[" << _("Warning") << gpg_err_code(err) << "]"
<< _("Description: ") << gpgme_strerror(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; 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, gpgme_error_t GpgFrontend::check_gpg_error(gpgme_error_t err,
const std::string& comment) { const std::string& comment) {
if (gpg_err_code(err) != GPG_ERR_NO_ERROR) { if (gpg_err_code(err) != GPG_ERR_NO_ERROR) {
LOG(ERROR) << "[" << _("Error") << " " << gpg_err_code(err) << "] " LOG(ERROR) << "[" << _("Error") << gpg_err_code(err) << "]" << _("Source: ")
<< _("Source: ") << gpgme_strsource(err) << " " << gpgme_strsource(err) << _("Description: ")
<< _("Description: ") << gpgme_strerror(err); << gpgme_strerror(err);
} }
return err; return err;
} }

View File

@ -29,14 +29,7 @@
#ifndef GPG_CONSTANTS_H #ifndef GPG_CONSTANTS_H
#define GPG_CONSTANTS_H #define GPG_CONSTANTS_H
#include <GpgFrontend.h> #include "GpgFrontendCore.h"
#include <gpgme.h>
#include <cassert>
#include <functional>
// dll export macro
#include "GpgFrontendCoreExport.h"
const int RESTART_CODE = 1000; ///< const int RESTART_CODE = 1000; ///<

View File

@ -87,7 +87,7 @@ GpgContext::GpgContext(const GpgContextInitArgs &args) : args_(args) {
continue; continue;
} }
DLOG(INFO) << gpgme_get_protocol_name(engine_info->protocol) LOG(INFO) << gpgme_get_protocol_name(engine_info->protocol)
<< std::string(engine_info->file_name == nullptr << std::string(engine_info->file_name == nullptr
? "null" ? "null"
: engine_info->file_name) : engine_info->file_name)
@ -136,7 +136,7 @@ GpgContext::GpgContext(const GpgContextInitArgs &args) : args_(args) {
LOG(ERROR) << "Env check failed"; LOG(ERROR) << "Env check failed";
return; return;
} else { } else {
DLOG(INFO) << "gnupg version" << info_.GnupgVersion; LOG(INFO) << "gnupg version" << info_.GnupgVersion;
init_ctx(); init_ctx();
good_ = true; good_ = true;
} }
@ -146,7 +146,7 @@ void GpgContext::init_ctx() {
// Set Independent Database // Set Independent Database
if (info_.GnupgVersion <= "2.0.0" && args_.independent_database) { if (info_.GnupgVersion <= "2.0.0" && args_.independent_database) {
info_.DatabasePath = args_.db_path; 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, auto err = gpgme_ctx_set_engine_info(_ctx_ref.get(), GPGME_PROTOCOL_OpenPGP,
info_.AppPath.c_str(), info_.AppPath.c_str(),
info_.DatabasePath.c_str()); info_.DatabasePath.c_str());

View File

@ -28,8 +28,6 @@
#include "GpgCoreInit.h" #include "GpgCoreInit.h"
#include <memory>
#include "GpgFunctionObject.h" #include "GpgFunctionObject.h"
#include "core/GpgContext.h" #include "core/GpgContext.h"
#include "core/function/GlobalSettingStation.h" #include "core/function/GlobalSettingStation.h"
@ -43,28 +41,37 @@ namespace GpgFrontend {
* @brief setup logging system and do proper initialization * @brief setup logging system and do proper initialization
* *
*/ */
void init_logging() { void InitLoggingSystem() {
using namespace boost::posix_time; using namespace boost::posix_time;
using namespace boost::gregorian; using namespace boost::gregorian;
ptime now = second_clock::local_time();
el::Loggers::addFlag(el::LoggingFlag::AutoSpacing); el::Loggers::addFlag(el::LoggingFlag::AutoSpacing);
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
el::Configurations defaultConf; el::Configurations defaultConf;
defaultConf.setToDefault(); defaultConf.setToDefault();
el::Loggers::reconfigureLogger("default", defaultConf);
// apply settings // apply settings
defaultConf.setGlobally(el::ConfigurationType::Format, 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 // get the log directory
auto logfile_path = auto logfile_path = (GlobalSettingStation::GetInstance().GetLogDir() /
(GlobalSettingStation::GetInstance().GetLogDir() / to_iso_string(now)); to_iso_string(second_clock::local_time()));
logfile_path.replace_extension(".log"); logfile_path.replace_extension(".log");
defaultConf.setGlobally(el::ConfigurationType::Filename, defaultConf.setGlobally(el::ConfigurationType::Filename,
logfile_path.u8string()); logfile_path.u8string());
// apply settings written to file
defaultConf.setGlobally(el::ConfigurationType::ToFile, "true");
// set the logger
el::Loggers::reconfigureLogger("default", defaultConf); el::Loggers::reconfigureLogger("default", defaultConf);
LOG(INFO) << _("log file path") << logfile_path; LOG(INFO) << _("log file path") << logfile_path;

View File

@ -37,7 +37,7 @@ namespace GpgFrontend {
* @brief * @brief
* *
*/ */
void init_logging(); void GPGFRONTEND_CORE_EXPORT InitLoggingSystem();
/** /**
* @brief * @brief

View File

@ -31,11 +31,29 @@
#include "GpgFrontend.h" #include "GpgFrontend.h"
// gnupg
#include <gpgme.h>
// std includes // std includes
#include <random> #include <cassert>
#include <filesystem> #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 // 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> #include <boost/format.hpp>
// Qt includes // Qt includes
@ -48,7 +66,10 @@
#include <libarchive/libarchive/archive.h> #include <libarchive/libarchive/archive.h>
#include <libarchive/libarchive/archive_entry.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 #endif // GPGFRONTEND_GPGFRONTENDCORE_H

View File

@ -51,19 +51,16 @@ void GpgFrontend::SingletonStorage::ReleaseChannel(int channel) {
_it = instances_map_.find(channel); _it = instances_map_.find(channel);
} }
if (_it != instances_map_.end()) instances_map_.erase(_it); if (_it != instances_map_.end()) instances_map_.erase(_it);
DLOG(INFO) << "channel" << channel << "released";
} }
GpgFrontend::ChannelObject* GpgFrontend::SingletonStorage::FindObjectInChannel( GpgFrontend::ChannelObject* GpgFrontend::SingletonStorage::FindObjectInChannel(
int channel) { int channel) {
LOG(INFO) << "channel:" << channel << "instance address:" << &instances_map_;
// read instances_map_ // read instances_map_
decltype(instances_map_.end()) _it; decltype(instances_map_.end()) _it;
{ {
std::shared_lock<std::shared_mutex> lock(instances_mutex_); std::shared_lock<std::shared_mutex> lock(instances_mutex_);
_it = instances_map_.find(channel); _it = instances_map_.find(channel);
if (_it == instances_map_.end()) { if (_it == instances_map_.end()) {
LOG(INFO) << "channel:" << channel << "not found";
return nullptr; return nullptr;
} else { } else {
return _it->second.get(); return _it->second.get();
@ -82,7 +79,7 @@ std::vector<int> GpgFrontend::SingletonStorage::GetAllChannelId() {
GpgFrontend::ChannelObject* GpgFrontend::SingletonStorage::SetObjectInChannel( GpgFrontend::ChannelObject* GpgFrontend::SingletonStorage::SetObjectInChannel(
int channel, std::unique_ptr<ChannelObject> p_obj) { int channel, std::unique_ptr<ChannelObject> p_obj) {
{ {
LOG(INFO) << "channel:" << channel LOG(TRACE) << "set channel:" << channel
<< "instance address:" << &instances_map_; << "instance address:" << &instances_map_;
assert(p_obj != nullptr); assert(p_obj != nullptr);
@ -102,7 +99,6 @@ GpgFrontend::SingletonStorage*
GpgFrontend::SingletonStorageCollection::GetSingletonStorage( GpgFrontend::SingletonStorageCollection::GetSingletonStorage(
const std::type_info& type_id) { const std::type_info& type_id) {
const auto hash = type_id.hash_code(); const auto hash = type_id.hash_code();
LOG(INFO) << "hash" << hash << "type_name:" << type_id.name();
while (true) { while (true) {
decltype(storages_map_.end()) _it; decltype(storages_map_.end()) _it;
@ -111,16 +107,15 @@ GpgFrontend::SingletonStorageCollection::GetSingletonStorage(
_it = storages_map_.find(hash); _it = storages_map_.find(hash);
} }
if (_it == storages_map_.end()) { if (_it == storages_map_.end()) {
LOG(INFO) << "hash:" << hash << "not found";
{ {
std::unique_lock<std::shared_mutex> lock(storages_mutex_); std::unique_lock<std::shared_mutex> lock(storages_mutex_);
storages_map_.insert({hash, std::make_unique<SingletonStorage>()}); 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; continue;
} else { } else {
LOG(INFO) << "hash:" << hash << "found";
return _it->second.get(); return _it->second.get();
} }
} }
@ -137,7 +132,4 @@ GpgFrontend::SingletonStorageCollection::GetInstance() {
GpgFrontend::ChannelObject::ChannelObject() noexcept = default; GpgFrontend::ChannelObject::ChannelObject() noexcept = default;
GpgFrontend::ChannelObject::ChannelObject(int channel) : channel_(channel) { GpgFrontend::ChannelObject::ChannelObject(int channel) : channel_(channel) {}
LOG(INFO) << "called"
<< "channel:" << channel;
}

View File

@ -29,18 +29,7 @@
#ifndef GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H #ifndef GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H
#define 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 "GpgConstants.h"
#include "easylogging++.h"
namespace GpgFrontend { namespace GpgFrontend {
@ -189,15 +178,13 @@ class SingletonFunctionObject : public ChannelObject {
auto* _p_pbj = (T*)(p_storage->FindObjectInChannel(channel)); auto* _p_pbj = (T*)(p_storage->FindObjectInChannel(channel));
LOG(INFO) << "object address" << _p_pbj;
if (_p_pbj == nullptr) { if (_p_pbj == nullptr) {
auto new_obj = std::unique_ptr<ChannelObject>(new T(channel)); 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))); return *(T*)(p_storage->SetObjectInChannel(channel, std::move(new_obj)));
} else } else {
return *_p_pbj; return *_p_pbj;
} }
}
/** /**
* @brief Create a Instance object * @brief Create a Instance object
@ -292,10 +279,7 @@ class SingletonFunctionObject : public ChannelObject {
* *
* @param channel * @param channel
*/ */
explicit SingletonFunctionObject(int channel) : ChannelObject(channel) { explicit SingletonFunctionObject(int channel) : ChannelObject(channel) {}
LOG(INFO) << "called"
<< "channel:" << channel;
}
/** /**
* @brief Destroy the Singleton Function Object object * @brief Destroy the Singleton Function Object object

View File

@ -29,8 +29,6 @@
#ifndef GPGFRONTEND_CHARSETDETECTOR_H #ifndef GPGFRONTEND_CHARSETDETECTOR_H
#define GPGFRONTEND_CHARSETDETECTOR_H #define GPGFRONTEND_CHARSETDETECTOR_H
#include <string>
#include "core/GpgFrontendCore.h" #include "core/GpgFrontendCore.h"
namespace GpgFrontend { namespace GpgFrontend {

View File

@ -29,8 +29,6 @@
#ifndef GPGFRONTEND_DATAOBJECTOPERATOR_H #ifndef GPGFRONTEND_DATAOBJECTOPERATOR_H
#define GPGFRONTEND_DATAOBJECTOPERATOR_H #define GPGFRONTEND_DATAOBJECTOPERATOR_H
#include <json/single_include/nlohmann/json.hpp>
#include "core/GpgFrontendCore.h" #include "core/GpgFrontendCore.h"
#include "core/GpgFunctionObject.h" #include "core/GpgFunctionObject.h"
#include "core/function/GlobalSettingStation.h" #include "core/function/GlobalSettingStation.h"

View File

@ -29,11 +29,6 @@
#ifndef GPGFRONTEND_GLOBALSETTINGSTATION_H #ifndef GPGFRONTEND_GLOBALSETTINGSTATION_H
#define 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 "GpgFrontendBuildInstallInfo.h"
#include "core/GpgFrontendCore.h" #include "core/GpgFrontendCore.h"
#include "core/GpgFunctionObject.h" #include "core/GpgFunctionObject.h"
@ -148,7 +143,7 @@ class GPGFRONTEND_CORE_EXPORT GlobalSettingStation
private: private:
std::filesystem::path app_path_ = std::filesystem::path app_path_ =
qApp->applicationDirPath().toStdString(); ///< Program Location QCoreApplication::applicationDirPath().toStdString(); ///< Program Location
std::filesystem::path app_data_path_ = std::filesystem::path app_data_path_ =
QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)
.toStdString(); ///< Program Data Location .toStdString(); ///< Program Data Location

View File

@ -86,7 +86,7 @@ GpgFrontend::GpgError GpgFrontend::GpgBasicOperator::Verify(
GpgData data_in(in_buffer.data(), in_buffer.size()); GpgData data_in(in_buffer.data(), in_buffer.size());
GpgData data_out; GpgData data_out;
if (sig_buffer != nullptr) { if (sig_buffer != nullptr && sig_buffer->size() > 0) {
GpgData sig_data(sig_buffer->data(), sig_buffer->size()); GpgData sig_data(sig_buffer->data(), sig_buffer->size());
err = check_gpg_error(gpgme_op_verify(ctx_, sig_data, data_in, nullptr)); err = check_gpg_error(gpgme_op_verify(ctx_, sig_data, data_in, nullptr));
} else } else

View File

@ -34,8 +34,8 @@
#include "core/GpgConstants.h" #include "core/GpgConstants.h"
#include "function/gpg/GpgKeyGetter.h" #include "function/gpg/GpgKeyGetter.h"
GpgFrontend::GpgVerifyResultAnalyse::GpgVerifyResultAnalyse(GpgError error, GpgFrontend::GpgVerifyResultAnalyse::GpgVerifyResultAnalyse(
GpgVerifyResult result) GpgError error, GpgVerifyResult result)
: error_(error), result_(std::move(result)) {} : error_(error), result_(std::move(result)) {}
void GpgFrontend::GpgVerifyResultAnalyse::do_analyse() { void GpgFrontend::GpgVerifyResultAnalyse::do_analyse() {
@ -104,6 +104,7 @@ void GpgFrontend::GpgVerifyResultAnalyse::do_analyse() {
stream_ << _("Signature Fully Valid.") << std::endl; stream_ << _("Signature Fully Valid.") << std::endl;
} else { } else {
stream_ << _("Signature Not Fully Valid.") << std::endl; stream_ << _("Signature Not Fully Valid.") << std::endl;
stream_ << _("(May used a subkey to sign)") << std::endl;
} }
if (!(sign->status & GPGME_SIGSUM_KEY_MISSING)) { if (!(sign->status & GPGME_SIGSUM_KEY_MISSING)) {
@ -172,8 +173,8 @@ void GpgFrontend::GpgVerifyResultAnalyse::do_analyse() {
} }
} }
bool GpgFrontend::GpgVerifyResultAnalyse::print_signer(std::stringstream &stream, bool GpgFrontend::GpgVerifyResultAnalyse::print_signer(
gpgme_signature_t sign) { std::stringstream &stream, gpgme_signature_t sign) {
bool keyFound = true; bool keyFound = true;
auto key = GpgFrontend::GpgKeyGetter::GetInstance().GetKey(sign->fpr); auto key = GpgFrontend::GpgKeyGetter::GetInstance().GetKey(sign->fpr);

View File

@ -29,9 +29,6 @@
#ifndef GPGFRONTEND_GPGKEY_H #ifndef GPGFRONTEND_GPGKEY_H
#define GPGFRONTEND_GPGKEY_H #define GPGFRONTEND_GPGKEY_H
#include <boost/date_time.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
#include "GpgSubKey.h" #include "GpgSubKey.h"
#include "GpgUID.h" #include "GpgUID.h"

View File

@ -38,9 +38,6 @@ GpgFrontend::Thread::CtxCheckTask::CtxCheckTask() {
} }
void GpgFrontend::Thread::CtxCheckTask::Run() { void GpgFrontend::Thread::CtxCheckTask::Run() {
// init logging
init_logging();
// Init GpgFrontend Core // Init GpgFrontend Core
init_gpgfrontend_core(); init_gpgfrontend_core();

View File

@ -37,7 +37,7 @@
#include "easylogging++.h" #include "easylogging++.h"
GpgFrontend::Thread::Task::Task() : uuid_(generate_uuid()) { GpgFrontend::Thread::Task::Task() : uuid_(generate_uuid()) {
LOG(INFO) << "Task" << uuid_ << "created"; LOG(TRACE) << "Task" << uuid_ << "created";
init(); init();
} }
@ -47,7 +47,7 @@ GpgFrontend::Thread::Task::Task(TaskCallback callback,
callback_(std::move(callback)), callback_(std::move(callback)),
callback_thread_(QThread::currentThread()), callback_thread_(QThread::currentThread()),
data_object_(data_object) { data_object_(data_object) {
LOG(INFO) << "Task" << uuid_ << "created with callback" LOG(TRACE) << "Task" << uuid_ << "created with callback"
<< "callback_thread_: " << callback_thread_; << "callback_thread_: " << callback_thread_;
init(); init();
} }
@ -60,11 +60,13 @@ GpgFrontend::Thread::Task::Task(TaskRunnable runnable, TaskCallback callback,
callback_thread_(QThread::currentThread()), callback_thread_(QThread::currentThread()),
data_object_(data_object) { data_object_(data_object) {
init(); init();
LOG(INFO) << "Task" << uuid_ << "created with runnable and callback" LOG(TRACE) << "Task" << uuid_ << "created with runnable and callback"
<< "callback_thread_: " << callback_thread_; << "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_; } std::string GpgFrontend::Thread::Task::GetUUID() const { return uuid_; }
@ -76,11 +78,11 @@ void GpgFrontend::Thread::Task::SetRTN(int rtn) { this->rtn_ = rtn; }
void GpgFrontend::Thread::Task::init() { void GpgFrontend::Thread::Task::init() {
connect(this, &Task::SignalTaskFinished, this, &Task::before_finish_task); connect(this, &Task::SignalTaskFinished, this, &Task::before_finish_task);
connect(this, &Task::SignalTaskFinished, this, &Task::deleteLater);
} }
void GpgFrontend::Thread::Task::before_finish_task() { void GpgFrontend::Thread::Task::before_finish_task() {
LOG(INFO) << "Task" << uuid_ << "finished"; LOG(TRACE) << "Task" << uuid_ << "finished";
try {
if (callback_) { if (callback_) {
bool if_invoke = QMetaObject::invokeMethod( bool if_invoke = QMetaObject::invokeMethod(
callback_thread_, callback_thread_,
@ -91,10 +93,16 @@ void GpgFrontend::Thread::Task::before_finish_task() {
LOG(ERROR) << "failed to invoke callback"; 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() { void GpgFrontend::Thread::Task::run() {
LOG(INFO) << "Task" << uuid_ << "started"; LOG(TRACE) << "Task" << uuid_ << "started";
Run(); Run();
if (finish_after_run_) emit SignalTaskFinished(); if (finish_after_run_) emit SignalTaskFinished();
} }
@ -104,7 +112,7 @@ void GpgFrontend::Thread::Task::Run() {
bool if_invoke = QMetaObject::invokeMethod( bool if_invoke = QMetaObject::invokeMethod(
this, [=]() { return runnable_(data_object_); }, &rtn_); this, [=]() { return runnable_(data_object_); }, &rtn_);
if (!if_invoke) { if (!if_invoke) {
LOG(ERROR) << "invokeMethod failed"; LOG(ERROR) << "Qt invokeMethod failed";
} }
} }
} }
@ -131,7 +139,7 @@ size_t GpgFrontend::Thread::Task::DataObject::GetObjectSize() {
} }
void GpgFrontend::Thread::Task::DataObject::free_heap_ptr(Destructor *ptr) { void GpgFrontend::Thread::Task::DataObject::free_heap_ptr(Destructor *ptr) {
LOG(INFO) << "p_obj: " << ptr->p_obj << "destructor: " << ptr->destroy DLOG(TRACE) << "p_obj: " << ptr->p_obj << "destructor: " << ptr->destroy
<< "DataObject:" << this; << "DataObject:" << this;
if (ptr->destroy != nullptr) { if (ptr->destroy != nullptr) {
ptr->destroy(ptr->p_obj); ptr->destroy(ptr->p_obj);

View File

@ -78,7 +78,7 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable {
*/ */
template <typename T> template <typename T>
void AppendObject(T &&obj) { void AppendObject(T &&obj) {
LOG(INFO) << "called:" << this; DLOG(TRACE) << "called:" << this;
auto *obj_dstr = this->get_heap_ptr(sizeof(T)); auto *obj_dstr = this->get_heap_ptr(sizeof(T));
auto *ptr_heap = new ((void *)obj_dstr->p_obj) T(std::move(obj)); auto *ptr_heap = new ((void *)obj_dstr->p_obj) T(std::move(obj));
if (std::is_class_v<T>) { if (std::is_class_v<T>) {
@ -100,10 +100,11 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable {
*/ */
template <typename T> template <typename T>
void AppendObject(T *obj) { void AppendObject(T *obj) {
LOG(INFO) << "called:" << this; DLOG(TRACE) << "called:" << this;
auto *obj_dstr = this->get_heap_ptr(sizeof(T)); auto *obj_dstr = this->get_heap_ptr(sizeof(T));
auto *ptr_heap = new ((void *)obj_dstr->p_obj) T(std::move(*obj)); auto *ptr_heap = new ((void *)obj_dstr->p_obj) T(std::move(*obj));
if (std::is_class_v<T>) { if (std::is_class_v<T>) {
LOG(TRACE) << "is class";
auto destructor = [](const void *x) { auto destructor = [](const void *x) {
static_cast<const T *>(x)->~T(); static_cast<const T *>(x)->~T();
}; };
@ -122,7 +123,7 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable {
*/ */
template <typename T> template <typename T>
T PopObject() { T PopObject() {
LOG(INFO) << "called:" << this; DLOG(TRACE) << "called:" << this;
if (data_objects_.empty()) throw std::runtime_error("No object to pop"); if (data_objects_.empty()) throw std::runtime_error("No object to pop");
auto *obj_dstr = data_objects_.top(); auto *obj_dstr = data_objects_.top();
auto *heap_ptr = (T *)obj_dstr->p_obj; auto *heap_ptr = (T *)obj_dstr->p_obj;
@ -206,6 +207,12 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable {
*/ */
void SignalTaskFinished(); void SignalTaskFinished();
/**
* @brief
*
*/
void SignalTaskPostFinishedDone();
protected: protected:
/** /**
* @brief Set the Finish After Run object * @brief Set the Finish After Run object

View File

@ -36,12 +36,23 @@ GpgFrontend::Thread::TaskRunner::TaskRunner() = default;
GpgFrontend::Thread::TaskRunner::~TaskRunner() = default; GpgFrontend::Thread::TaskRunner::~TaskRunner() = default;
void GpgFrontend::Thread::TaskRunner::PostTask(Task* task) { void GpgFrontend::Thread::TaskRunner::PostTask(Task* task) {
LOG(INFO) << "called" LOG(TRACE) << "Post Task" << task->GetUUID();
<< "Post Task" << task->GetUUID();
if (task == nullptr) return; if (task == nullptr) return;
task->setParent(nullptr); task->setParent(nullptr);
task->moveToThread(this); 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_); std::lock_guard<std::mutex> lock(tasks_mutex_);
tasks.push(task); tasks.push(task);
@ -50,33 +61,43 @@ void GpgFrontend::Thread::TaskRunner::PostTask(Task* task) {
} }
void GpgFrontend::Thread::TaskRunner::run() { void GpgFrontend::Thread::TaskRunner::run() {
LOG(INFO) << "called" LOG(TRACE) << "called"
<< "thread id:" << QThread::currentThreadId(); << "thread id:" << QThread::currentThreadId();
while (true) { while (true) {
LOG(TRACE) << "TaskRunner: A new cycle start";
if (tasks.empty()) { if (tasks.empty()) {
LOG(INFO) << "TaskRunner: No tasks to run."; LOG(TRACE) << "TaskRunner: No tasks to run, trapping into event loop...";
exec(); exec();
} else { } else {
LOG(INFO) << "TaskRunner: Queue size:" << tasks.size(); LOG(TRACE) << "TaskRunner: Task queue size:" << tasks.size();
Task* task = nullptr; Task* task = nullptr;
{ {
std::lock_guard<std::mutex> lock(tasks_mutex_); std::lock_guard<std::mutex> lock(tasks_mutex_);
task = std::move(tasks.front()); task = std::move(tasks.front());
tasks.pop(); tasks.pop();
pending_tasks_.insert({task->GetUUID(), task});
} }
if (task != nullptr) { if (task != nullptr) {
// Run the task // Run the task
LOG(INFO) << "TaskRunner: Running Task" << task->GetUUID(); LOG(TRACE) << "TaskRunner: Running Task" << task->GetUUID();
try { try {
task->run(); task->run();
} catch (const std::exception& e) { } catch (const std::exception& e) {
LOG(ERROR) << "TaskRunner: Exception in Task" << task->GetUUID() LOG(ERROR) << "TaskRunner: Exception in Task" << task->GetUUID()
<< "Exception: " << e.what(); << "Exception: " << e.what();
// destroy the task, remove the task from the pending tasks
task->deleteLater();
pending_tasks_.erase(task->GetUUID());
} catch (...) { } catch (...) {
LOG(ERROR) << "TaskRunner: Unknwon Exception in Task" LOG(ERROR) << "TaskRunner: Unknwon Exception in Task"
<< task->GetUUID(); << task->GetUUID();
// destroy the task, remove the task from the pending tasks
task->deleteLater();
pending_tasks_.erase(task->GetUUID());
} }
} }
} }

View File

@ -68,6 +68,7 @@ class GPGFRONTEND_CORE_EXPORT TaskRunner : public QThread {
private: private:
std::queue<Task*> tasks; ///< The task queue 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 std::mutex tasks_mutex_; ///< The task queue mutex
}; };
} // namespace GpgFrontend::Thread } // namespace GpgFrontend::Thread

View File

@ -40,6 +40,7 @@ class GPGFRONTEND_CORE_EXPORT TaskRunnerGetter
kTaskRunnerType_Default, kTaskRunnerType_Default,
kTaskRunnerType_GPG, kTaskRunnerType_GPG,
kTaskRunnerType_IO, kTaskRunnerType_IO,
kTaskRunnerType_Network,
}; };
TaskRunnerGetter(int channel = SingletonFunctionObject::GetDefaultChannel()); TaskRunnerGetter(int channel = SingletonFunctionObject::GetDefaultChannel());

View File

@ -26,25 +26,21 @@
* *
*/ */
#include "GpgFrontend.h"
#include "GpgFrontendBuildInfo.h"
#include "core/function/GlobalSettingStation.h" #include "core/function/GlobalSettingStation.h"
/** void init_logging_system() {
* @brief Get the files of a given directory el::Loggers::addFlag(el::LoggingFlag::AutoSpacing);
* el::Configurations defaultConf;
* @param _path target directory defaultConf.setToDefault();
* @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;
for (fs::recursive_directory_iterator i(_path); i != end; ++i) { // apply settings
const fs::path cp = (*i); defaultConf.setGlobally(el::ConfigurationType::Format,
path_list.push_back(cp); "%datetime %level [main] %func %msg");
} // apply settings no written to file
} defaultConf.setGlobally(el::ConfigurationType::ToFile, "false");
return path_list;
// set the logger
el::Loggers::reconfigureLogger("default", defaultConf);
} }

View File

@ -32,16 +32,11 @@
#include <csetjmp> #include <csetjmp>
#include <csignal> #include <csignal>
#include <cstdlib> #include <cstddef>
#include "GpgFrontendBuildInfo.h" #include "core/GpgCoreInit.h"
#include "core/GpgFunctionObject.h" #include "ui/GpgFrontendApplication.h"
#include "ui/GpgFrontendUIInit.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. * \brief initialize the easylogging++ library.
@ -53,19 +48,27 @@ INITIALIZE_EASYLOGGINGPP
*/ */
jmp_buf recover_env; jmp_buf recover_env;
constexpr int CRASH_CODE = ~0; ///<
/** /**
* @brief * @brief handle the signal SIGSEGV
* *
* @param sig * @param sig
*/ */
extern void handle_signal(int sig); extern void handle_signal(int sig);
/** /**
* @brief * @brief processes before exit the program.
* *
*/ */
extern void before_exit(); extern void before_exit();
/**
* @brief initialize the logging system.
*
*/
extern void init_logging_system();
/** /**
* *
* @param argc * @param argc
@ -85,38 +88,14 @@ int main(int argc, char* argv[]) {
Q_INIT_RESOURCE(gpgfrontend); Q_INIT_RESOURCE(gpgfrontend);
// create qt application // create qt application
QApplication app(argc, argv); auto* app =
GpgFrontend::UI::GpgFrontendApplication::GetInstance(argc, argv, true);
#ifndef MACOS // init the logging system
QApplication::setWindowIcon(QIcon(":gpgfrontend.png")); init_logging_system();
#endif
#ifdef MACOS // init the logging system for core
// support retina screen GpgFrontend::InitLoggingSystem();
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
// 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
/** /**
* internationalisation. loop to restart main window * internationalisation. loop to restart main window
@ -131,45 +110,33 @@ int main(int argc, char* argv[]) {
int r = setjmp(recover_env); int r = setjmp(recover_env);
#endif #endif
if (!r) { if (!r) {
#ifdef RELEASE
try {
#endif
QApplication::setQuitOnLastWindowClosed(true);
// init ui library // init ui library
GpgFrontend::UI::InitGpgFrontendUI(); GpgFrontend::UI::InitGpgFrontendUI(app);
// create main window // create main window
return_from_event_loop_code = GpgFrontend::UI::RunGpgFrontendUI(); return_from_event_loop_code = GpgFrontend::UI::RunGpgFrontendUI(app);
#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
} else { } else {
LOG(ERROR) << "recover from a crash";
// when signal is caught, restart the main window // when signal is caught, restart the main window
QMessageBox::information( auto* message_box = new QMessageBox(
nullptr, _("A serious error has occurred"), QMessageBox::Critical, _("A serious error has occurred"),
_("Oh no! GpgFrontend caught a serious error in the software, so it " _("Oh no! GpgFrontend caught a serious error in the software, so "
"needs to be restarted. If the problem recurs, please manually " "it needs to be restarted. If the problem recurs, please "
"terminate the program and report the problem to the developer.")); "manually terminate the program and report the problem to the "
QCoreApplication::quit(); "developer."),
return_from_event_loop_code = RESTART_CODE; QMessageBox::Ok, nullptr);
LOG(INFO) << "return_from_event_loop_code" << return_from_event_loop_code; message_box->exec();
continue; 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"; 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 // exit the program
return return_from_event_loop_code; return return_from_event_loop_code;

View File

@ -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<eric@bktus.com><eric@bktus.com> 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

View File

@ -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<eric@bktus.com><eric@bktus.com> 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

View File

@ -35,18 +35,41 @@
#include "ui/UserInterfaceUtils.h" #include "ui/UserInterfaceUtils.h"
#include "ui/main_window/MainWindow.h" #include "ui/main_window/MainWindow.h"
#if !defined(RELEASE) && defined(WINDOWS)
#include "core/function/GlobalSettingStation.h"
#endif
// init easyloggingpp library // init easyloggingpp library
INITIALIZE_EASYLOGGINGPP INITIALIZE_EASYLOGGINGPP
namespace GpgFrontend::UI { namespace GpgFrontend::UI {
extern void init_logging(); extern void init_logging_system();
extern void init_locale(); extern void init_locale();
void InitGpgFrontendUI() { void InitGpgFrontendUI(QApplication* app) {
// init logging system
init_logging_system();
// init locale
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(); SignalStation::GetInstance();
// init common utils
CommonUtils::GetInstance(); CommonUtils::GetInstance();
// create the thread to load the gpg context // create the thread to load the gpg context
@ -65,17 +88,16 @@ void InitGpgFrontendUI() {
waiting_dialog_label->setWordWrap(true); waiting_dialog_label->setWordWrap(true);
waiting_dialog->setLabel(waiting_dialog_label); waiting_dialog->setLabel(waiting_dialog_label);
waiting_dialog->resize(420, 120); waiting_dialog->resize(420, 120);
QApplication::connect(init_ctx_task, app->connect(init_ctx_task, &Thread::CtxCheckTask::SignalTaskFinished,
&Thread::CtxCheckTask::SignalTaskFinished,
waiting_dialog, [=]() { waiting_dialog, [=]() {
LOG(INFO) << "Gpg context loaded"; LOG(INFO) << "Gpg context loaded";
waiting_dialog->finished(0); waiting_dialog->finished(0);
waiting_dialog->deleteLater(); waiting_dialog->deleteLater();
}); });
QApplication::connect(waiting_dialog, &QProgressDialog::canceled, [=]() { app->connect(waiting_dialog, &QProgressDialog::canceled, [=]() {
LOG(INFO) << "cancel clicked"; LOG(INFO) << "cancel clicked";
QCoreApplication::quit(); app->quit();
exit(0); exit(0);
}); });
@ -86,9 +108,8 @@ void InitGpgFrontendUI() {
// new local event looper // new local event looper
QEventLoop looper; QEventLoop looper;
QApplication::connect(init_ctx_task, app->connect(init_ctx_task, &Thread::CtxCheckTask::SignalTaskFinished,
&Thread::CtxCheckTask::SignalTaskFinished, &looper, &looper, &QEventLoop::quit);
&QEventLoop::quit);
// start the thread to load the gpg context // start the thread to load the gpg context
Thread::TaskRunnerGetter::GetInstance().GetTaskRunner()->PostTask( Thread::TaskRunnerGetter::GetInstance().GetTaskRunner()->PostTask(
@ -98,36 +119,47 @@ void InitGpgFrontendUI() {
looper.exec(); looper.exec();
} }
int RunGpgFrontendUI() { int RunGpgFrontendUI(QApplication* app) {
// create main window and show it // create main window and show it
auto main_window = std::make_unique<GpgFrontend::UI::MainWindow>(); auto main_window = std::make_unique<GpgFrontend::UI::MainWindow>();
main_window->Init(); main_window->Init();
LOG(INFO) << "Main window inited";
main_window->show(); 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::posix_time;
using namespace boost::gregorian; using namespace boost::gregorian;
ptime now = second_clock::local_time();
el::Loggers::addFlag(el::LoggingFlag::AutoSpacing); el::Loggers::addFlag(el::LoggingFlag::AutoSpacing);
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
el::Configurations defaultConf; el::Configurations defaultConf;
defaultConf.setToDefault(); defaultConf.setToDefault();
el::Loggers::reconfigureLogger("default", defaultConf);
// apply settings // apply settings
defaultConf.setGlobally(el::ConfigurationType::Format, 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 // get the log directory
auto logfile_path = auto logfile_path = (GlobalSettingStation::GetInstance().GetLogDir() /
(GlobalSettingStation::GetInstance().GetLogDir() / to_iso_string(now)); to_iso_string(second_clock::local_time()));
logfile_path.replace_extension(".log"); logfile_path.replace_extension(".log");
defaultConf.setGlobally(el::ConfigurationType::Filename, defaultConf.setGlobally(el::ConfigurationType::Filename,
logfile_path.u8string()); logfile_path.u8string());
// apply settings written to file
defaultConf.setGlobally(el::ConfigurationType::ToFile, "false");
el::Loggers::reconfigureLogger("default", defaultConf); el::Loggers::reconfigureLogger("default", defaultConf);
LOG(INFO) << _("log file path") << logfile_path; LOG(INFO) << _("log file path") << logfile_path;

View File

@ -37,12 +37,12 @@ namespace GpgFrontend::UI {
* @brief init the UI library * @brief init the UI library
* *
*/ */
void GPGFRONTEND_UI_EXPORT InitGpgFrontendUI(); void GPGFRONTEND_UI_EXPORT InitGpgFrontendUI(QApplication *);
/** /**
* @brief run main window * @brief run main window
*/ */
int GPGFRONTEND_UI_EXPORT RunGpgFrontendUI(); int GPGFRONTEND_UI_EXPORT RunGpgFrontendUI(QApplication *);
}; // namespace GpgFrontend::UI }; // namespace GpgFrontend::UI

View File

@ -29,9 +29,9 @@
#ifndef __KEYMGMT_H__ #ifndef __KEYMGMT_H__
#define __KEYMGMT_H__ #define __KEYMGMT_H__
#include "import_export/KeyImportDetailDialog.h"
#include "import_export/KeyServerImportDialog.h"
#include "ui/GpgFrontendUI.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/key_generate/KeygenDialog.h"
#include "ui/keypair_details/KeyDetailsDialog.h" #include "ui/keypair_details/KeyDetailsDialog.h"
#include "ui/widgets/KeyList.h" #include "ui/widgets/KeyList.h"

View File

@ -52,10 +52,8 @@ void VerifyDetailsDialog::slot_refresh() {
// Button Box for close button // Button Box for close button
button_box_ = new QDialogButtonBox(QDialogButtonBox::Close); button_box_ = new QDialogButtonBox(QDialogButtonBox::Close);
connect(button_box_, &QDialogButtonBox::rejected, this, &VerifyDetailsDialog::close); connect(button_box_, &QDialogButtonBox::rejected, this,
&VerifyDetailsDialog::close);
mVboxLayout->addWidget(new QLabel(QString::fromStdString(
std::string(_("Status")) + ": " + gpgme_strerror(error_))));
auto sign = m_result_->signatures; auto sign = m_result_->signatures;

View File

@ -30,7 +30,8 @@
#include "GpgFrontendBuildInfo.h" #include "GpgFrontendBuildInfo.h"
#include "core/function/GlobalSettingStation.h" #include "core/function/GlobalSettingStation.h"
#include "ui/thread/VersionCheckThread.h" #include "core/thread/TaskRunnerGetter.h"
#include "ui/thread/VersionCheckTask.h"
namespace GpgFrontend::UI { namespace GpgFrontend::UI {
@ -198,14 +199,14 @@ void UpdateTab::getLatestVersion() {
LOG(INFO) << _("try to get latest version"); LOG(INFO) << _("try to get latest version");
auto version_thread = new VersionCheckThread(); auto* version_task = new VersionCheckTask();
connect(version_thread, &VersionCheckThread::finished, version_thread, connect(version_task, &VersionCheckTask::SignalUpgradeVersion, this,
&VersionCheckThread::deleteLater);
connect(version_thread, &VersionCheckThread::SignalUpgradeVersion, this,
&UpdateTab::slot_show_version_status); &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) { void UpdateTab::slot_show_version_status(const SoftwareVersion& version) {
@ -221,7 +222,7 @@ void UpdateTab::slot_show_version_status(const SoftwareVersion& version) {
"github.")) + "github.")) +
"</center><center>" + _("Please click") + "</center><center>" + _("Please click") +
" <a " " <a "
"href=\"https://github.com/saturneric/GpgFrontend/releases\">" + "href=\"https://www.gpgfrontend.pub/#/downloads\">" +
_("Here") + "</a> " + _("to download the latest stable version.") + _("Here") + "</a> " + _("to download the latest stable version.") +
"</center>"); "</center>");
upgrade_label_->show(); upgrade_label_->show();
@ -244,7 +245,7 @@ void UpdateTab::slot_show_version_status(const SoftwareVersion& version) {
"stability, please do not use this version.")) + "stability, please do not use this version.")) +
"</center><center>" + _("Please click") + "</center><center>" + _("Please click") +
" <a " " <a "
"href=\"https://github.com/saturneric/GpgFrontend/releases\">" + "href=\"https://www.gpgfrontend.pub/#/downloads\">" +
_("Here") + "</a> " + _("to download the latest stable version.") + _("Here") + "</a> " + _("to download the latest stable version.") +
"</center>"); "</center>");
upgrade_label_->show(); upgrade_label_->show();

View File

@ -160,7 +160,7 @@ void KeyGenDialog::slot_key_gen_accept() {
emit SignalKeyGenerated(); emit SignalKeyGenerated();
this->close(); this->close();
} else { } else {
QMessageBox::critical(this, _("Failure"), _(gpgme_strerror(error))); QMessageBox::critical(this, _("Failure"), _("Key generation failed."));
} }
} else { } else {

View File

@ -285,7 +285,7 @@ void SubkeyGenerateDialog::slot_key_gen_accept() {
emit SignalSubKeyGenerated(); emit SignalSubKeyGenerated();
this->close(); this->close();
} else } else
QMessageBox::critical(this, _("Failure"), _(gpgme_strerror(error))); QMessageBox::critical(this, _("Failure"), _("Failed to generate key."));
} else { } else {
/** /**

View File

@ -84,7 +84,9 @@ void KeySetExpireDateDialog::slot_confirm() {
this->close(); this->close();
} else { } else {
QMessageBox::critical(this, _("Failure"), _(gpgme_strerror(err))); QMessageBox::critical(
this, _("Failure"),
_("Failed to update the expire date of the key pair."));
} }
} }

View File

@ -28,13 +28,11 @@
#include "MainWindow.h" #include "MainWindow.h"
#include "ui/UserInterfaceUtils.h"
#ifdef RELEASE
#include "ui/thread/VersionCheckThread.h"
#endif
#include "core/function/GlobalSettingStation.h" #include "core/function/GlobalSettingStation.h"
#include "ui/SignalStation.h" #include "ui/SignalStation.h"
#include "ui/UserInterfaceUtils.h"
#include "ui/struct/SettingsObject.h" #include "ui/struct/SettingsObject.h"
#include "ui/thread/VersionCheckTask.h"
namespace GpgFrontend::UI { namespace GpgFrontend::UI {
@ -85,14 +83,6 @@ void MainWindow::Init() noexcept {
restore_settings(); 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(); edit_->CurTextPage()->setFocus();
auto &settings = GlobalSettingStation::GetInstance().GetUISettings(); auto &settings = GlobalSettingStation::GetInstance().GetUISettings();
@ -122,16 +112,14 @@ void MainWindow::Init() noexcept {
// if not prohibit update checking // if not prohibit update checking
if (!prohibit_update_checking_) { if (!prohibit_update_checking_) {
#ifdef RELEASE auto *version_task = new VersionCheckTask();
auto version_thread = new VersionCheckThread();
connect(version_thread, &VersionCheckThread::finished, version_thread, connect(version_task, &VersionCheckTask::SignalUpgradeVersion, this,
&VersionCheckThread::deleteLater);
connect(version_thread, &VersionCheckThread::SignalUpgradeVersion, this,
&MainWindow::slot_version_upgrade); &MainWindow::slot_version_upgrade);
version_thread->start(); Thread::TaskRunnerGetter::GetInstance()
#endif .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Network)
->PostTask(version_task);
} }
} catch (...) { } catch (...) {
@ -147,7 +135,6 @@ void MainWindow::restore_settings() {
LOG(INFO) << _("Called"); LOG(INFO) << _("Called");
try { try {
LOG(INFO) << "restore settings main_windows_state"; LOG(INFO) << "restore settings main_windows_state";
SettingsObject main_windows_state("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); general.lookupValue("save_key_checked", save_key_checked);
try { try {
LOG(INFO) << "restore settings default_key_checked"; LOG(INFO) << "restore settings default_key_checked";
// Checked Keys // Checked Keys
@ -248,11 +234,6 @@ void MainWindow::restore_settings() {
LOG(ERROR) << "restore default_key_checked failed"; 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; prohibit_update_checking_ = false;
try { try {
prohibit_update_checking_ = prohibit_update_checking_ =
@ -267,6 +248,7 @@ void MainWindow::restore_settings() {
} }
GlobalSettingStation::GetInstance().SyncSettings(); GlobalSettingStation::GetInstance().SyncSettings();
LOG(INFO) << _("settings restored");
} }
void MainWindow::save_settings() { void MainWindow::save_settings() {

View File

@ -53,7 +53,6 @@ class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
public: public:
struct CryptoMenu { struct CryptoMenu {
using OperationType = unsigned int; using OperationType = unsigned int;
@ -89,7 +88,6 @@ class MainWindow : public QMainWindow {
*/ */
void SignalLoaded(); void SignalLoaded();
public slots: public slots:
/** /**

View File

@ -324,56 +324,71 @@ void MainWindow::slot_decrypt() {
std::move(result_callback), data_object); 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() { void MainWindow::slot_verify() {
if (edit_->TabCount() == 0 || edit_->SlotCurPageTextEdit() == nullptr) { if (edit_->TabCount() == 0 || edit_->SlotCurPageTextEdit() == nullptr) {
if (edit_->SlotCurPageFileTreeView() != nullptr) this->SlotFileVerify(); if (edit_->SlotCurPageFileTreeView() != nullptr) this->SlotFileVerify();
return; return;
} }
auto text = edit_->CurTextPage()->GetTextPage()->toPlainText().toUtf8(); // data to transfer into task
// TODO(Saturneric) PreventNoDataErr auto data_object = std::make_shared<Thread::Task::DataObject>();
auto sig_buffer = std::make_unique<ByteArray>(); // set input buffer
sig_buffer.reset(); 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();
GpgVerifyResult result = nullptr;
GpgError error;
bool if_error = false;
process_operation(
this, _("Verifying"), [&](Thread::Task::DataObjectPtr) -> int {
try { try {
auto buffer = text.toStdString(); GpgVerifyResult verify_result = nullptr;
error = GpgFrontend::GpgBasicOperator::GetInstance().Verify( auto sig_buffer = std::unique_ptr<ByteArray>(nullptr);
buffer, sig_buffer, result); 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) { } catch (const std::runtime_error& e) {
if_error = true; return -1;
} }
return 0; return 0;
}); };
if (!if_error) { auto result_callback = [this](int rtn,
auto result_analyse = GpgVerifyResultAnalyse(error, result); 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(); result_analyse.Analyse();
process_result_analyse(edit_, info_board_, result_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) if (result_analyse.GetStatus() == -2)
import_unknown_key_from_keyserver(this, result_analyse); import_unknown_key_from_keyserver(this, result_analyse);
if (result_analyse.GetStatus() >= 0) if (result_analyse.GetStatus() >= 0)
show_verify_details(this, info_board_, error, result); 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() { void MainWindow::slot_encrypt_sign() {
@ -423,50 +438,64 @@ void MainWindow::slot_encrypt_sign() {
LOG(INFO) << "Signers " << signer.GetEmail(); LOG(INFO) << "Signers " << signer.GetEmail();
} }
// 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; GpgEncrResult encr_result = nullptr;
GpgSignResult sign_result = nullptr; GpgSignResult sign_result = nullptr;
GpgError error;
bool if_error = false;
auto tmp = std::make_unique<ByteArray>(); auto tmp = std::make_unique<ByteArray>();
process_operation( GpgError error = GpgFrontend::GpgBasicOperator::GetInstance().EncryptSign(
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, std::move(keys), std::move(signer_keys), buffer, tmp, encr_result,
sign_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) { } catch (const std::runtime_error& e) {
if_error = true; return -1;
} }
return 0; 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>>();
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."));
}
}
#endif
LOG(INFO) << "GpgResultAnalyse Started"; LOG(INFO) << "GpgResultAnalyse Started";
auto encrypt_res = GpgEncryptResultAnalyse(error, std::move(encr_result)); auto encrypt_result_analyse =
auto sign_res = GpgSignResultAnalyse(error, std::move(sign_result)); GpgEncryptResultAnalyse(error, std::move(encrypt_result));
encrypt_res.Analyse(); auto sign_result_analyse =
sign_res.Analyse(); GpgSignResultAnalyse(error, std::move(sign_result));
process_result_analyse(edit_, info_board_, encrypt_res, sign_res); 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) if (check_gpg_error_2_err_code(error) == GPG_ERR_NO_ERROR)
edit_->SlotFillTextEditWithText(QString::fromStdString(*tmp)); edit_->SlotFillTextEditWithText(QString::fromStdString(*tmp));
@ -476,6 +505,10 @@ void MainWindow::slot_encrypt_sign() {
_("An error occurred during operation.")); _("An error occurred during operation."));
return; return;
} }
};
process_operation(this, _("Encrypting and Signing"), encrypt_sign_runner,
result_callback, data_object);
} }
void MainWindow::slot_decrypt_verify() { void MainWindow::slot_decrypt_verify() {
@ -485,72 +518,87 @@ void MainWindow::slot_decrypt_verify() {
return; return;
} }
QString plainText = edit_->CurTextPage()->GetTextPage()->toPlainText(); // data to transfer into task
auto data_object = std::make_shared<Thread::Task::DataObject>();
#ifdef ADVANCE_SUPPORT // set input buffer
if (plainText.trimmed().startsWith( auto buffer =
GpgConstants::GPG_FRONTEND_SHORT_CRYPTO_HEAD)) { edit_->CurTextPage()->GetTextPage()->toPlainText().toStdString();
auto cryptoText = getCryptText(plainText); data_object->AppendObject(std::move(buffer));
if (!cryptoText.isEmpty()) {
plainText = cryptoText;
}
}
#endif
QByteArray text = plainText.toUtf8(); 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");
GpgDecrResult d_result = nullptr; auto buffer = data_object->PopObject<std::string>();
GpgVerifyResult v_result = nullptr;
gpgme_error_t error;
bool if_error = false;
#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 { try {
auto buffer = text.toStdString(); GpgDecrResult decrypt_result = nullptr;
error = GpgBasicOperator::GetInstance().DecryptVerify( GpgVerifyResult verify_result = nullptr;
buffer, decrypted, d_result, v_result); 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) { } catch (const std::runtime_error& e) {
if_error = true; LOG(ERROR) << e.what();
return -1;
} }
return 0; return 0;
}); };
if (!if_error) { auto result_callback = [this](int rtn,
auto decrypt_res = GpgDecryptResultAnalyse(error, std::move(d_result)); Thread::Task::DataObjectPtr data_object) {
auto verify_res = GpgVerifyResultAnalyse(error, v_result); if (!rtn) {
decrypt_res.Analyse(); if (data_object == nullptr || data_object->GetObjectSize() != 4)
verify_res.Analyse(); throw std::runtime_error("Invalid data object size");
process_result_analyse(edit_, info_board_, decrypt_res, verify_res);
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>>();
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) if (check_gpg_error_2_err_code(error) == GPG_ERR_NO_ERROR)
edit_->SlotFillTextEditWithText(QString::fromStdString(*decrypted)); edit_->SlotFillTextEditWithText(QString::fromStdString(*decrypted));
if (verify_res.GetStatus() == -2) if (verify_result_analyse.GetStatus() == -2)
import_unknown_key_from_keyserver(this, verify_res); import_unknown_key_from_keyserver(this, verify_result_analyse);
if (verify_res.GetStatus() >= 0) if (verify_result_analyse.GetStatus() >= 0)
show_verify_details(this, info_board_, error, v_result); show_verify_details(this, info_board_, error, verify_result);
} else { } else {
QMessageBox::critical(this, _("Error"), QMessageBox::critical(this, _("Error"),
_("An error occurred during operation.")); _("An error occurred during operation."));
return; 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::SlotOpenFile(QString& path) { edit_->SlotOpenFile(path); }
void MainWindow::slot_version_upgrade(const SoftwareVersion& version) { 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()) { if (version.NeedUpgrade()) {
statusBar()->showMessage( statusBar()->showMessage(
QString(_("GpgFrontend Upgradeable (New Version: %1).")) QString(_("GpgFrontend Upgradeable (New Version: %1)."))

View File

@ -53,7 +53,8 @@ void MainWindow::create_actions() {
browser_act_->setIcon(QIcon(":file-browser.png")); browser_act_->setIcon(QIcon(":file-browser.png"));
browser_act_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); browser_act_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B));
browser_act_->setToolTip(_("Open a file browser")); 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_ = new QAction(_("Save File"), this);
save_act_->setIcon(QIcon(":filesave.png")); save_act_->setIcon(QIcon(":filesave.png"));
@ -135,7 +136,8 @@ void MainWindow::create_actions() {
select_all_act_->setIcon(QIcon(":edit.png")); select_all_act_->setIcon(QIcon(":edit.png"));
select_all_act_->setShortcut(QKeySequence::SelectAll); select_all_act_->setShortcut(QKeySequence::SelectAll);
select_all_act_->setToolTip(_("Select the whole text")); 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_ = new QAction(_("Find"), this);
find_act_->setShortcut(QKeySequence::Find); find_act_->setShortcut(QKeySequence::Find);
@ -153,6 +155,7 @@ void MainWindow::create_actions() {
open_settings_act_ = new QAction(_("Settings"), this); open_settings_act_ = new QAction(_("Settings"), this);
open_settings_act_->setToolTip(_("Open settings dialog")); open_settings_act_->setToolTip(_("Open settings dialog"));
open_settings_act_->setMenuRole(QAction::PreferencesRole);
open_settings_act_->setShortcut(QKeySequence::Preferences); open_settings_act_->setShortcut(QKeySequence::Preferences);
connect(open_settings_act_, &QAction::triggered, this, connect(open_settings_act_, &QAction::triggered, this,
&MainWindow::slot_open_settings_dialog); &MainWindow::slot_open_settings_dialog);
@ -244,6 +247,7 @@ void MainWindow::create_actions() {
about_act_ = new QAction(_("About"), this); about_act_ = new QAction(_("About"), this);
about_act_->setIcon(QIcon(":help.png")); about_act_->setIcon(QIcon(":help.png"));
about_act_->setToolTip(_("Show the application's About box")); about_act_->setToolTip(_("Show the application's About box"));
about_act_->setMenuRole(QAction::AboutRole);
connect(about_act_, &QAction::triggered, this, connect(about_act_, &QAction::triggered, this,
[=]() { new AboutDialog(0, this); }); [=]() { new AboutDialog(0, this); });
@ -269,8 +273,7 @@ void MainWindow::create_actions() {
/* Popup-Menu-Action for KeyList /* Popup-Menu-Action for KeyList
*/ */
append_selected_keys_act_ = append_selected_keys_act_ = new QAction(_("Append To Text Editor"), this);
new QAction(_("Append To Text Editor"), this);
append_selected_keys_act_->setToolTip( append_selected_keys_act_->setToolTip(
_("Append The Selected Public Key To Text in Editor")); _("Append The Selected Public Key To Text in Editor"));
connect(append_selected_keys_act_, &QAction::triggered, this, connect(append_selected_keys_act_, &QAction::triggered, this,

View File

@ -29,12 +29,12 @@
#include "SettingsDialog.h" #include "SettingsDialog.h"
#include "core/function/GlobalSettingStation.h" #include "core/function/GlobalSettingStation.h"
#include "ui/main_window/MainWindow.h"
#include "ui/settings/SettingsAdvanced.h" #include "ui/settings/SettingsAdvanced.h"
#include "ui/settings/SettingsAppearance.h" #include "ui/settings/SettingsAppearance.h"
#include "ui/settings/SettingsGeneral.h" #include "ui/settings/SettingsGeneral.h"
#include "ui/settings/SettingsKeyServer.h" #include "ui/settings/SettingsKeyServer.h"
#include "ui/settings/SettingsNetwork.h" #include "ui/settings/SettingsNetwork.h"
#include "ui/main_window/MainWindow.h"
namespace GpgFrontend::UI { namespace GpgFrontend::UI {
@ -45,31 +45,39 @@ SettingsDialog::SettingsDialog(QWidget* parent) : QDialog(parent) {
key_server_tab_ = new KeyserverTab(); key_server_tab_ = new KeyserverTab();
network_tab_ = new NetworkTab(); network_tab_ = new NetworkTab();
auto* mainLayout = new QVBoxLayout;
mainLayout->addWidget(tab_widget_);
mainLayout->stretch(0);
tab_widget_->addTab(general_tab_, _("General")); tab_widget_->addTab(general_tab_, _("General"));
tab_widget_->addTab(appearance_tab_, _("Appearance")); tab_widget_->addTab(appearance_tab_, _("Appearance"));
tab_widget_->addTab(key_server_tab_, _("Key Server")); tab_widget_->addTab(key_server_tab_, _("Key Server"));
tab_widget_->addTab(network_tab_, _("Network")); tab_widget_->addTab(network_tab_, _("Network"));
#ifndef MACOS
button_box_ = button_box_ =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(button_box_, &QDialogButtonBox::accepted, this,
connect(button_box_, &QDialogButtonBox::accepted, this, &SettingsDialog::SlotAccept); &SettingsDialog::SlotAccept);
connect(button_box_, &QDialogButtonBox::rejected, this, &SettingsDialog::reject); connect(button_box_, &QDialogButtonBox::rejected, this,
&SettingsDialog::reject);
auto* mainLayout = new QVBoxLayout;
mainLayout->addWidget(tab_widget_);
mainLayout->stretch(0);
mainLayout->addWidget(button_box_); mainLayout->addWidget(button_box_);
mainLayout->stretch(0); mainLayout->stretch(0);
setLayout(mainLayout);
setWindowTitle(_("Settings")); 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 // slots for handling the restart needed member
this->slot_set_restart_needed(false); this->slot_set_restart_needed(false);
connect(general_tab_, &GeneralTab::SignalRestartNeeded, this, connect(general_tab_, &GeneralTab::SignalRestartNeeded, this,
&SettingsDialog::slot_set_restart_needed); &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->setMinimumSize(480, 680);
this->adjustSize(); this->adjustSize();

View File

@ -48,6 +48,14 @@ struct SoftwareVersion {
std::string publish_date; ///< std::string publish_date; ///<
std::string release_note; ///< std::string release_note; ///<
/**
* @brief
*
* @return true
* @return false
*/
[[nodiscard]] bool InfoVaild() const { return load_info_done; }
/** /**
* @brief * @brief
* *

View File

@ -26,45 +26,58 @@
* *
*/ */
#include "VersionCheckThread.h" #include "VersionCheckTask.h"
#include <QMetaType> #include <QMetaType>
#include <nlohmann/json.hpp> #include <memory>
#include "GpgFrontendBuildInfo.h" #include "GpgFrontendBuildInfo.h"
namespace GpgFrontend::UI { namespace GpgFrontend::UI {
void VersionCheckThread::run() { VersionCheckTask::VersionCheckTask()
auto current_version = std::string("v") + std::to_string(VERSION_MAJOR) + : network_manager_(new QNetworkAccessManager(this)),
"." + std::to_string(VERSION_MINOR) + "." + current_version_(std::string("v") + std::to_string(VERSION_MAJOR) + "." +
std::to_string(VERSION_PATCH); std::to_string(VERSION_MINOR) + "." +
std::to_string(VERSION_PATCH)) {
qRegisterMetaType<SoftwareVersion>("SoftwareVersion");
version_.current_version = current_version_;
}
SoftwareVersion version; void VersionCheckTask::Run() {
version.current_version = current_version; SetFinishAfterRun(false);
auto manager = std::make_unique<QNetworkAccessManager>(nullptr);
try { try {
using namespace nlohmann; using namespace nlohmann;
LOG(INFO) << "current version" << current_version; LOG(INFO) << "current version" << current_version_;
std::string latest_version_url = std::string latest_version_url =
"https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; "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())); latest_request.setUrl(QUrl(latest_version_url.c_str()));
current_request.setUrl(QUrl(current_version_url.c_str())); latest_reply_ = network_manager_->get(latest_request);
auto _reply = manager->get(latest_request); connect(latest_reply_, &QNetworkReply::finished, this,
while (_reply->isRunning()) QApplication::processEvents(); &VersionCheckTask::slot_parse_latest_version_info);
if (_reply->error() != QNetworkReply::NoError) {
LOG(ERROR) << "current version request error"; // loading done
version.latest_version = current_version; 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 { } else {
latest_reply_bytes_ = _reply->readAll(); latest_reply_bytes_ = latest_reply_->readAll();
auto latest_reply_json = auto latest_reply_json =
nlohmann::json::parse(latest_reply_bytes_.toStdString()); nlohmann::json::parse(latest_reply_bytes_.toStdString());
@ -78,7 +91,7 @@ void VersionCheckThread::run() {
latest_version = version_match.captured(0).toStdString(); latest_version = version_match.captured(0).toStdString();
LOG(INFO) << "latest version matched" << latest_version; LOG(INFO) << "latest version matched" << latest_version;
} else { } else {
latest_version = current_version; latest_version = current_version_;
LOG(WARNING) << "latest version unknown"; LOG(WARNING) << "latest version unknown";
} }
@ -86,44 +99,69 @@ void VersionCheckThread::run() {
draft = latest_reply_json["draft"]; draft = latest_reply_json["draft"];
std::string publish_date = latest_reply_json["published_at"]; std::string publish_date = latest_reply_json["published_at"];
std::string release_note = latest_reply_json["body"]; std::string release_note = latest_reply_json["body"];
version.latest_version = latest_version; version_.latest_version = latest_version;
version.latest_prerelease = prerelease; version_.latest_prerelease = prerelease;
version.latest_draft = draft; version_.latest_draft = draft;
version.publish_date = publish_date; version_.publish_date = publish_date;
version.release_note = release_note; 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); try {
while (_reply->isRunning()) QApplication::processEvents(); std::string current_version_url =
current_reply_bytes_ = _reply->readAll(); "https://api.github.com/repos/saturneric/gpgfrontend/releases/tags/" +
if (_reply->error() != QNetworkReply::NoError) { 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"; LOG(ERROR) << "current version request network error";
version.current_version_found = false; version_.current_version_found = false;
} else { } 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 = auto current_reply_json =
nlohmann::json::parse(current_reply_bytes_.toStdString()); nlohmann::json::parse(current_reply_bytes_.toStdString());
bool current_prerelease = current_reply_json["prerelease"], bool current_prerelease = current_reply_json["prerelease"],
current_draft = current_reply_json["draft"]; current_draft = current_reply_json["draft"];
version.latest_prerelease = current_prerelease; version_.latest_prerelease = current_prerelease;
version.latest_draft = current_draft; version_.latest_draft = current_draft;
version_.load_info_done = true;
} }
_reply->deleteLater();
// loading done
version.load_info_done = true;
} catch (...) { } catch (...) {
LOG(INFO) << "error occurred"; LOG(INFO) << "error occurred";
version.load_info_done = false; version_.load_info_done = false;
}
emit SignalUpgradeVersion(version);
} }
VersionCheckThread::VersionCheckThread() : QThread(nullptr) { LOG(INFO) << "current version parse done" << version_.current_version_found;
qRegisterMetaType<SoftwareVersion>("SoftwareVersion");
}; if (current_reply_ != nullptr) {
current_reply_->deleteLater();
}
emit SignalUpgradeVersion(version_);
emit SignalTaskFinished();
}
} // namespace GpgFrontend::UI } // namespace GpgFrontend::UI

View File

@ -29,6 +29,10 @@
#ifndef GPGFRONTEND_VERSIONCHECKTHREAD_H #ifndef GPGFRONTEND_VERSIONCHECKTHREAD_H
#define GPGFRONTEND_VERSIONCHECKTHREAD_H #define GPGFRONTEND_VERSIONCHECKTHREAD_H
#include <memory>
#include <string>
#include "core/thread/Task.h"
#include "ui/GpgFrontendUI.h" #include "ui/GpgFrontendUI.h"
#include "ui/struct/SoftwareVersion.h" #include "ui/struct/SoftwareVersion.h"
@ -38,7 +42,7 @@ namespace GpgFrontend::UI {
* @brief * @brief
* *
*/ */
class VersionCheckThread : public QThread { class VersionCheckTask : public Thread::Task {
Q_OBJECT Q_OBJECT
public: public:
@ -46,7 +50,7 @@ class VersionCheckThread : public QThread {
* @brief Construct a new Version Check Thread object * @brief Construct a new Version Check Thread object
* *
*/ */
explicit VersionCheckThread(); explicit VersionCheckTask();
signals: 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: private:
QByteArray latest_reply_bytes_; ///< QByteArray latest_reply_bytes_; ///<
QByteArray current_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 } // namespace GpgFrontend::UI

View File

@ -65,7 +65,7 @@ class VerifyKeyDetailBox : public QGroupBox {
*/ */
QGridLayout* create_key_info_grid(const GpgSignature& signature); QGridLayout* create_key_info_grid(const GpgSignature& signature);
std::string fpr_; ///< std::string fpr_; ///< fingerprint of the key
}; };
} // namespace GpgFrontend::UI } // namespace GpgFrontend::UI