1/*
2 * Copyright (C) 2003-2008 Justin Karneges <justin@affinix.com>
3 * Copyright (C) 2014 Ivan Romanov <drizt@land.ru>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20#include "utils.h"
21#include "mykeystorelist.h"
22#include <QCoreApplication>
23#include <QFileInfo>
24#include <QStringList>
25#ifdef Q_OS_WIN
26#include <windows.h>
27#endif
28
29using namespace QCA;
30
31namespace gpgQCAPlugin {
32
33void gpg_waitForFinished(GpgOp *gpg)
34{
35 while (true) {
36 GpgOp::Event e = gpg->waitForEvent(msecs: -1);
37 if (e.type == GpgOp::Event::Finished)
38 break;
39 }
40}
41
42void gpg_keyStoreLog(const QString &str)
43{
44 MyKeyStoreList *ksl = MyKeyStoreList::instance();
45 if (ksl)
46 ksl->ext_keyStoreLog(str);
47}
48
49inline bool check_bin(const QString &bin)
50{
51 QFileInfo fi(bin);
52 return fi.exists();
53}
54
55#ifdef Q_OS_WIN
56static bool get_reg_key(HKEY root, const char *path, QString &value)
57{
58 HKEY hkey = 0;
59
60 char szValue[256];
61 DWORD dwLen = 256;
62
63 bool res = false;
64
65 if (RegOpenKeyExA(root, path, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) {
66 if (RegQueryValueExA(hkey, "Install Directory", NULL, NULL, (LPBYTE)szValue, &dwLen) == ERROR_SUCCESS) {
67 value = QString::fromLocal8Bit(szValue);
68 res = true;
69 }
70 RegCloseKey(hkey);
71 }
72 return res;
73}
74
75static QString find_reg_gpgProgram()
76{
77 const QStringList bins = {QStringLiteral("gpg.exe"), QStringLiteral("gpg2.exe")};
78
79 HKEY root;
80 root = HKEY_CURRENT_USER;
81
82 const char *path = "Software\\GNU\\GnuPG";
83 const char *path2 = "Software\\Wow6432Node\\GNU\\GnuPG";
84
85 QString dir;
86 // check list of possible places in registry
87 get_reg_key(HKEY_CURRENT_USER, path, dir) || get_reg_key(HKEY_CURRENT_USER, path2, dir) ||
88 get_reg_key(HKEY_LOCAL_MACHINE, path, dir) || get_reg_key(HKEY_LOCAL_MACHINE, path2, dir);
89
90 if (!dir.isEmpty()) {
91 foreach (const QString &bin, bins) {
92 if (check_bin(dir + QStringLiteral("\\") + bin)) {
93 return dir + QStringLiteral("\\") + bin;
94 }
95 }
96 }
97 return QString();
98}
99#endif
100
101QString find_bin()
102{
103 // gpg and gpg2 has identical semantics
104 // so any from them can be used
105 QStringList bins;
106#ifdef Q_OS_WIN
107 bins << QStringLiteral("gpg.exe") << QStringLiteral("gpg2.exe");
108#else
109 bins << QStringLiteral("gpg") << QStringLiteral("gpg2");
110#endif
111
112 // Prefer bundled gpg
113 foreach (const QString &bin, bins) {
114 if (check_bin(bin: QCoreApplication::applicationDirPath() + QLatin1Char('/') + bin)) {
115 return QCoreApplication::applicationDirPath() + QLatin1Char('/') + bin;
116 }
117 }
118
119#ifdef Q_OS_WIN
120 // On Windows look up at registry
121 QString bin = find_reg_gpgProgram();
122 if (!bin.isEmpty())
123 return bin;
124#endif
125
126 // Look up at PATH environment
127#ifdef Q_OS_WIN
128 const QString pathSep = QStringLiteral(";");
129#else
130 const QString pathSep = QStringLiteral(":");
131#endif
132
133 QStringList paths = QString::fromLocal8Bit(ba: qgetenv(varName: "PATH")).split(sep: pathSep, behavior: Qt::SkipEmptyParts);
134
135#ifdef Q_OS_MAC
136 // On Mac OS bundled always uses system default PATH
137 // so it need explicity add extra paths which can
138 // contain gpg
139 // Mac GPG and brew use /usr/local/bin
140 // MacPorts uses /opt/local/bin
141 paths << QStringLiteral("/usr/local/bin") << QStringLiteral("/opt/local/bin");
142#endif
143 paths.removeDuplicates();
144
145 foreach (const QString &path, paths) {
146 foreach (const QString &bin, bins) {
147 if (check_bin(bin: path + QLatin1Char('/') + bin)) {
148 return path + QLatin1Char('/') + bin;
149 }
150 }
151 }
152
153 // Return nothing if gpg not found
154 return QString();
155}
156
157QString escape_string(const QString &in)
158{
159 QString out;
160 for (const QChar &c : in) {
161 if (c == QLatin1Char('\\'))
162 out += QStringLiteral("\\\\");
163 else if (c == QLatin1Char(':'))
164 out += QStringLiteral("\\c");
165 else
166 out += c;
167 }
168 return out;
169}
170
171QString unescape_string(const QString &in)
172{
173 QString out;
174 for (int n = 0; n < in.length(); ++n) {
175 if (in[n] == QLatin1Char('\\')) {
176 if (n + 1 < in.length()) {
177 if (in[n + 1] == QLatin1Char('\\'))
178 out += QLatin1Char('\\');
179 else if (in[n + 1] == QLatin1Char('c'))
180 out += QLatin1Char(':');
181 ++n;
182 }
183 } else
184 out += in[n];
185 }
186 return out;
187}
188
189PGPKey publicKeyFromId(const QString &id)
190{
191 MyKeyStoreList *ksl = MyKeyStoreList::instance();
192 if (!ksl)
193 return PGPKey();
194
195 return ksl->publicKeyFromId(keyId: id);
196}
197
198PGPKey secretKeyFromId(const QString &id)
199{
200 MyKeyStoreList *ksl = MyKeyStoreList::instance();
201 if (!ksl)
202 return PGPKey();
203
204 return ksl->secretKeyFromId(keyId: id);
205}
206
207} // end namespace gpgQCAPlugin
208

source code of qca/plugins/qca-gnupg/utils.cpp