Skip to content

Commit a7ea8e6

Browse files
committed
Merge branch 'develop'
2 parents 0261c78 + 2686fad commit a7ea8e6

52 files changed

Lines changed: 3801 additions & 3187 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/testing-nightly.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ jobs:
276276
- name: Build GpgFrontend (Linux)
277277
# Build your GpgFrontend with the given configuration
278278
run: |
279-
cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DDGPGFRONTEND_BUILD_TYPE_ONLY_APPLICATION=ON
279+
cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DGPGFRONTEND_BUILD_TYPE_ONLY_APPLICATION=ON
280280
cmake --build ${{github.workspace}}/build --config {{$env.BUILD_TYPE}} -- -v
281281
if: runner.os == 'Linux'
282282

resource/lfs/locale/ts/GpgFrontend.de_DE.ts

Lines changed: 463 additions & 442 deletions
Large diffs are not rendered by default.

resource/lfs/locale/ts/GpgFrontend.en_US.ts

Lines changed: 450 additions & 431 deletions
Large diffs are not rendered by default.

resource/lfs/locale/ts/GpgFrontend.fr_FR.ts

Lines changed: 455 additions & 440 deletions
Large diffs are not rendered by default.

resource/lfs/locale/ts/GpgFrontend.it_IT.ts

Lines changed: 457 additions & 442 deletions
Large diffs are not rendered by default.

resource/lfs/locale/ts/GpgFrontend.zh_CN.ts

Lines changed: 463 additions & 442 deletions
Large diffs are not rendered by default.

resource/lfs/locale/ts/GpgFrontend.zh_TW.ts

Lines changed: 455 additions & 436 deletions
Large diffs are not rendered by default.

src/core/GpgCoreInit.cpp

Lines changed: 85 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -225,17 +225,17 @@ auto InitGpgME() -> bool {
225225
"core", "gpgme.ctx.gnupg_version", QString{});
226226

227227
if (!has_gpgconf) {
228-
FLOG_E() << "cannot get gpgconf backend engine, abort...";
228+
LOG_E() << "cannot get gpgconf backend engine, abort...";
229229
return false;
230230
}
231231

232232
if (!has_openpgp) {
233-
FLOG_E() << "cannot get openpgp backend engine, abort...";
233+
LOG_E() << "cannot get openpgp backend engine, abort...";
234234
return false;
235235
}
236236

237237
if (!has_cms) {
238-
FLOG_E() << "cannot get cms backend engine, abort...";
238+
LOG_E() << "cannot get cms backend engine, abort...";
239239
return false;
240240
}
241241

@@ -387,6 +387,56 @@ auto DecideGnuPGPath(const QString& default_gnupg_path) -> QString {
387387
return default_gnupg_path;
388388
}
389389

390+
void EnsureGpgAgentConfHasPinentry(GpgContext& ctx) {
391+
auto pinentry_path = DecidePinentry();
392+
if (pinentry_path.isEmpty()) {
393+
LOG_W() << "no suitable pinentry found.";
394+
return;
395+
}
396+
397+
QDir gnupg_dir(ctx.HomeDirectory());
398+
if (!gnupg_dir.exists()) {
399+
gnupg_dir.mkpath(".");
400+
}
401+
402+
QString config_path = gnupg_dir.filePath("gpg-agent.conf");
403+
QFile config_file(config_path);
404+
QStringList lines;
405+
406+
LOG_D() << "checking pinentry config at:" << gnupg_dir;
407+
408+
bool has_pinentry_line = false;
409+
if (config_file.exists()) {
410+
if (config_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
411+
QTextStream in(&config_file);
412+
while (!in.atEnd()) {
413+
QString line = in.readLine();
414+
if (line.trimmed().startsWith("pinentry-program")) {
415+
has_pinentry_line = true;
416+
}
417+
lines.append(line);
418+
}
419+
config_file.close();
420+
}
421+
}
422+
423+
if (!has_pinentry_line) {
424+
lines.append(QString("pinentry-program %1").arg(pinentry_path));
425+
if (config_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
426+
QTextStream out(&config_file);
427+
for (const QString& line : lines) {
428+
out << line << '\n';
429+
}
430+
config_file.close();
431+
LOG_D() << "updated gpg-agent.conf with pinentry:" << pinentry_path;
432+
} else {
433+
LOG_W() << "failed to write to gpg-agent.conf";
434+
}
435+
} else {
436+
LOG_D() << "gpg-agent.conf already contains pinentry-program";
437+
}
438+
}
439+
390440
auto InitBasicPath() -> bool {
391441
auto default_gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>(
392442
"core", "gpgme.ctx.gpgconf_path", QString{});
@@ -520,8 +570,8 @@ auto InitGpgFrontendCore(CoreInitArgs args) -> int {
520570
assert(!key_dbs.isEmpty());
521571

522572
if (key_dbs.isEmpty()) {
523-
FLOG_E() << "Cannot find any valid key database!"
524-
<< "GpgFrontend cannot start under this situation!";
573+
LOG_E() << "Cannot find any valid key database!"
574+
<< "GpgFrontend cannot start under this situation!";
525575
Module::UpsertRTValue("core", "env.state.ctx", -1);
526576
CoreSignalStation::GetInstance()->SignalBadGnupgEnv(
527577
QCoreApplication::tr("No valid Key Database"));
@@ -548,20 +598,26 @@ auto InitGpgFrontendCore(CoreInitArgs args) -> int {
548598
return ConvertToChannelObjectPtr<>(SecureCreateUniqueObject<GpgContext>(
549599
args, kGpgFrontendDefaultChannel));
550600
});
601+
551602
if (!default_ctx.Good()) {
552-
FLOG_E() << "Init GpgME Default Context failed!"
553-
<< "GpgFrontend cannot start under this situation!";
603+
LOG_E() << "Init GpgME Default Context failed!"
604+
<< "GpgFrontend cannot start under this situation!";
554605
Module::UpsertRTValue("core", "env.state.ctx", -1);
555606
CoreSignalStation::GetInstance()->SignalBadGnupgEnv(
556607
QCoreApplication::tr("GpgME Default Context Initiation Failed"));
557608
return -1;
558609
}
559610

611+
#if !(defined(_WIN32) || defined(WIN32))
612+
// auto config pinentry-program
613+
EnsureGpgAgentConfHasPinentry(default_ctx);
614+
#endif
615+
560616
Module::UpsertRTValue("core", "env.state.ctx", 1);
561617

562618
if (!GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel).FlushKeyCache()) {
563-
FLOG_E() << "Init GpgME Default Key Database failed!"
564-
<< "GpgFrontend cannot start under this situation!";
619+
LOG_E() << "Init GpgME Default Key Database failed!"
620+
<< "GpgFrontend cannot start under this situation!";
565621
Module::UpsertRTValue("core", "env.state.ctx", -1);
566622
CoreSignalStation::GetInstance()->SignalBadGnupgEnv(
567623
QCoreApplication::tr("Gpg Default Key Database Initiation Failed"));
@@ -602,13 +658,21 @@ auto InitGpgFrontendCore(CoreInitArgs args) -> int {
602658
});
603659

604660
if (!ctx.Good()) {
605-
FLOG_E() << "gpgme context init failed, index:" << channel_index;
661+
LOG_E() << "gpgme context init failed, index:" << channel_index;
606662
continue;
607663
}
608664

665+
#if defined(__linux__)
666+
EnsureGpgAgentConfHasPinentry(ctx);
667+
#endif
668+
669+
#if defined(__APPLE__) && defined(__MACH__)
670+
EnsureGpgAgentConfHasPinentry(ctx);
671+
#endif
672+
609673
if (!GpgKeyGetter::GetInstance(ctx.GetChannel()).FlushKeyCache()) {
610-
FLOG_E() << "gpgme context init key cache failed, index:"
611-
<< channel_index;
674+
LOG_E() << "gpgme context init key cache failed, index:"
675+
<< channel_index;
612676
continue;
613677
}
614678

@@ -631,9 +695,16 @@ auto InitGpgFrontendCore(CoreInitArgs args) -> int {
631695
.GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default)
632696
->PostTask(task);
633697

634-
if (!args.unit_test_mode && restart_all_gnupg_components_on_start) {
635-
GpgAdvancedOperator::RestartGpgComponents(nullptr);
698+
const auto size = GpgContext::GetAllChannelId().size();
699+
for (auto i = 0; i < size; i++) {
700+
if (!args.unit_test_mode && restart_all_gnupg_components_on_start) {
701+
assert(GpgAdvancedOperator::GetInstance().RestartGpgComponents());
702+
} else {
703+
// ensure gpg-agent is running
704+
assert(GpgAdvancedOperator::GetInstance().LaunchAllGpgComponents());
705+
}
636706
}
707+
637708
return 0;
638709
}
639710

src/core/function/gpg/GpgAdvancedOperator.cpp

Lines changed: 20 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -33,91 +33,38 @@
3333
#include "GpgAdvancedOperator.h"
3434

3535
#include "core/function/gpg/GpgCommandExecutor.h"
36-
#include "core/module/ModuleManager.h"
37-
#include "core/utils/GpgUtils.h"
38-
3936
namespace GpgFrontend {
4037

41-
void ExecuteGpgCommand(const QString &operation, const QStringList &extra_args,
42-
OperationCallback cb) {
43-
const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>(
44-
"core", "gpgme.ctx.gpgconf_path", QString{});
45-
46-
if (gpgconf_path.isEmpty()) {
47-
FLOG_W("cannot get valid gpgconf path from rt, abort.");
48-
if (cb) cb(-1, TransferParams());
49-
return;
50-
}
51-
52-
auto key_dbs = GetGpgKeyDatabaseInfos();
53-
auto total_tasks = static_cast<int>(key_dbs.size());
54-
std::atomic<int> completed_tasks{0};
55-
std::vector<int> results(total_tasks, 0);
56-
57-
// kill default gpg-agent
58-
key_dbs.push_back({});
59-
60-
int task_index = 0;
61-
for (const auto &key_db : key_dbs) {
62-
const int current_index = task_index++;
63-
const auto target_home_dir =
64-
QDir::toNativeSeparators(QFileInfo(key_db.path).canonicalFilePath());
65-
66-
QStringList arguments = !target_home_dir.isEmpty()
67-
? QStringList{"--homedir", target_home_dir}
68-
: QStringList{};
69-
arguments.append(extra_args);
70-
71-
GpgCommandExecutor::ExecuteSync(
72-
{gpgconf_path, arguments,
73-
[=, &completed_tasks, &results](int exit_code, const QString &,
74-
const QString &) {
75-
FLOG_D("%s exit code: %d", qPrintable(operation), exit_code);
76-
77-
results[current_index] = exit_code;
78-
79-
if (++completed_tasks == total_tasks && cb) {
80-
int final_result =
81-
std::all_of(results.begin(), results.end(),
82-
[](int result) { return result >= 0; })
83-
? 0
84-
: -1;
85-
cb(final_result, TransferParams());
86-
}
87-
}});
88-
}
89-
}
90-
91-
void GpgAdvancedOperator::ClearGpgPasswordCache(OperationCallback cb) {
92-
ExecuteGpgCommand("Clear GPG Password Cache", {"--reload", "gpg-agent"},
93-
std::move(cb));
38+
auto GpgAdvancedOperator::ClearGpgPasswordCache() -> bool {
39+
auto [ret, out] = exec_.GpgConfExecuteSync({{"--reload", "gpg-agent"}});
40+
return ret == 0;
9441
}
9542

96-
void GpgAdvancedOperator::ReloadGpgComponents(OperationCallback cb) {
97-
const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>(
98-
"core", "gpgme.ctx.gpgconf_path", QString{});
99-
ExecuteGpgCommand("Reload GPG Components", {"--reload", "all"},
100-
std::move(cb));
43+
auto GpgAdvancedOperator::ReloadAllGpgComponents() -> bool {
44+
auto [ret, out] = exec_.GpgConfExecuteSync({{"--reload", "all"}});
45+
return ret == 0;
10146
}
10247

103-
void GpgAdvancedOperator::KillAllGpgComponents(OperationCallback cb) {
104-
ExecuteGpgCommand("Kill All GPG Components", {"--kill", "all"},
105-
std::move(cb));
48+
auto GpgAdvancedOperator::KillAllGpgComponents() -> bool {
49+
auto [ret, out] = exec_.GpgConfExecuteSync({{"--kill", "all"}});
50+
return ret == 0;
10651
}
10752

108-
void GpgAdvancedOperator::ResetConfigures(OperationCallback cb) {
109-
ExecuteGpgCommand("Reset Gnupg Configures", {"--apply-defaults"},
110-
std::move(cb));
53+
auto GpgAdvancedOperator::ResetConfigures() -> bool {
54+
auto [ret, out] = exec_.GpgConfExecuteSync({{"--apply-defaults"}});
55+
return ret == 0;
11156
}
11257

113-
void GpgAdvancedOperator::LaunchGpgComponents(OperationCallback cb) {
114-
ExecuteGpgCommand("Launch All GPG Components", {"--launch", "all"},
115-
std::move(cb));
58+
auto GpgAdvancedOperator::LaunchAllGpgComponents() -> bool {
59+
auto [ret, out] = exec_.GpgConfExecuteSync({{"--launch", "all"}});
60+
return ret == 0;
11661
}
11762

118-
void GpgAdvancedOperator::RestartGpgComponents(OperationCallback cb) {
119-
KillAllGpgComponents(nullptr);
120-
LaunchGpgComponents(std::move(cb));
63+
auto GpgAdvancedOperator::RestartGpgComponents() -> bool {
64+
if (!KillAllGpgComponents()) return false;
65+
return LaunchAllGpgComponents();
12166
}
12267

68+
GpgAdvancedOperator::GpgAdvancedOperator(int channel)
69+
: SingletonFunctionObject<GpgAdvancedOperator>(channel) {}
12370
} // namespace GpgFrontend

src/core/function/gpg/GpgAdvancedOperator.h

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,57 +32,71 @@
3232

3333
#pragma once
3434

35+
#include "core/function/basic/GpgFunctionObject.h"
36+
#include "core/function/gpg/GpgCommandExecutor.h"
3537
#include "core/model/DataObject.h"
3638

3739
namespace GpgFrontend {
3840

39-
class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator {
41+
class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator
42+
: public SingletonFunctionObject<GpgAdvancedOperator> {
4043
public:
44+
/**
45+
* @brief Construct a new Gpg Advanced Operator object
46+
*
47+
* @param channel
48+
*/
49+
explicit GpgAdvancedOperator(int channel);
50+
4151
/**
4252
* @brief
4353
*
4454
* @return true
4555
* @return false
4656
*/
47-
static void ClearGpgPasswordCache(OperationCallback);
57+
auto ClearGpgPasswordCache() -> bool;
4858

4959
/**
5060
* @brief
5161
*
5262
* @return true
5363
* @return false
5464
*/
55-
static void ReloadGpgComponents(OperationCallback);
65+
auto ReloadAllGpgComponents() -> bool;
5666

5767
/**
5868
* @brief
5969
*
6070
* @return true
6171
* @return false
6272
*/
63-
static void RestartGpgComponents(OperationCallback);
73+
auto RestartGpgComponents() -> bool;
6474

6575
/**
6676
* @brief
6777
*
6878
* @return true
6979
* @return false
7080
*/
71-
static void ResetConfigures(OperationCallback);
81+
auto ResetConfigures() -> bool;
7282

7383
/**
7484
* @brief
7585
*
7686
* @return true
7787
* @return false
7888
*/
79-
static void LaunchGpgComponents(OperationCallback);
89+
auto LaunchAllGpgComponents() -> bool;
8090

8191
/**
8292
* @brief
8393
*
8494
*/
85-
static void KillAllGpgComponents(OperationCallback);
95+
auto KillAllGpgComponents() -> bool;
96+
97+
private:
98+
GpgCommandExecutor& exec_ =
99+
GpgCommandExecutor::GetInstance(SingletonFunctionObject::GetChannel());
86100
};
87101

88102
} // namespace GpgFrontend

0 commit comments

Comments
 (0)