File indexing completed on 2025-01-12 04:19:47
0001 /* 0002 * Copyright (C) 2003-2008 Justin Karneges <justin@affinix.com> 0003 * Copyright (C) 2014 Ivan Romanov <drizt@land.ru> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Lesser General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2.1 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Lesser General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Lesser General Public 0016 * License along with this library; if not, write to the Free Software 0017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 0018 */ 0019 0020 #include "utils.h" 0021 #include "mykeystorelist.h" 0022 #include <QCoreApplication> 0023 #include <QFileInfo> 0024 #include <QStringList> 0025 #ifdef Q_OS_WIN 0026 #include <windows.h> 0027 #endif 0028 0029 using namespace QCA; 0030 0031 namespace gpgQCAPlugin { 0032 0033 void gpg_waitForFinished(GpgOp *gpg) 0034 { 0035 while (true) { 0036 GpgOp::Event e = gpg->waitForEvent(-1); 0037 if (e.type == GpgOp::Event::Finished) 0038 break; 0039 } 0040 } 0041 0042 void gpg_keyStoreLog(const QString &str) 0043 { 0044 MyKeyStoreList *ksl = MyKeyStoreList::instance(); 0045 if (ksl) 0046 ksl->ext_keyStoreLog(str); 0047 } 0048 0049 inline bool check_bin(const QString &bin) 0050 { 0051 QFileInfo fi(bin); 0052 return fi.exists(); 0053 } 0054 0055 #ifdef Q_OS_WIN 0056 static bool get_reg_key(HKEY root, const char *path, QString &value) 0057 { 0058 HKEY hkey = 0; 0059 0060 char szValue[256]; 0061 DWORD dwLen = 256; 0062 0063 bool res = false; 0064 0065 if (RegOpenKeyExA(root, path, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { 0066 if (RegQueryValueExA(hkey, "Install Directory", NULL, NULL, (LPBYTE)szValue, &dwLen) == ERROR_SUCCESS) { 0067 value = QString::fromLocal8Bit(szValue); 0068 res = true; 0069 } 0070 RegCloseKey(hkey); 0071 } 0072 return res; 0073 } 0074 0075 static QString find_reg_gpgProgram() 0076 { 0077 const QStringList bins = {QStringLiteral("gpg.exe"), QStringLiteral("gpg2.exe")}; 0078 0079 HKEY root; 0080 root = HKEY_CURRENT_USER; 0081 0082 const char *path = "Software\\GNU\\GnuPG"; 0083 const char *path2 = "Software\\Wow6432Node\\GNU\\GnuPG"; 0084 0085 QString dir; 0086 // check list of possible places in registry 0087 get_reg_key(HKEY_CURRENT_USER, path, dir) || get_reg_key(HKEY_CURRENT_USER, path2, dir) || 0088 get_reg_key(HKEY_LOCAL_MACHINE, path, dir) || get_reg_key(HKEY_LOCAL_MACHINE, path2, dir); 0089 0090 if (!dir.isEmpty()) { 0091 foreach (const QString &bin, bins) { 0092 if (check_bin(dir + QStringLiteral("\\") + bin)) { 0093 return dir + QStringLiteral("\\") + bin; 0094 } 0095 } 0096 } 0097 return QString(); 0098 } 0099 #endif 0100 0101 QString find_bin() 0102 { 0103 // gpg and gpg2 has identical semantics 0104 // so any from them can be used 0105 QStringList bins; 0106 #ifdef Q_OS_WIN 0107 bins << QStringLiteral("gpg.exe") << QStringLiteral("gpg2.exe"); 0108 #else 0109 bins << QStringLiteral("gpg") << QStringLiteral("gpg2"); 0110 #endif 0111 0112 // Prefer bundled gpg 0113 foreach (const QString &bin, bins) { 0114 if (check_bin(QCoreApplication::applicationDirPath() + QLatin1Char('/') + bin)) { 0115 return QCoreApplication::applicationDirPath() + QLatin1Char('/') + bin; 0116 } 0117 } 0118 0119 #ifdef Q_OS_WIN 0120 // On Windows look up at registry 0121 QString bin = find_reg_gpgProgram(); 0122 if (!bin.isEmpty()) 0123 return bin; 0124 #endif 0125 0126 // Look up at PATH environment 0127 #ifdef Q_OS_WIN 0128 const QString pathSep = QStringLiteral(";"); 0129 #else 0130 const QString pathSep = QStringLiteral(":"); 0131 #endif 0132 0133 QStringList paths = QString::fromLocal8Bit(qgetenv("PATH")).split(pathSep, Qt::SkipEmptyParts); 0134 0135 #ifdef Q_OS_MAC 0136 // On Mac OS bundled always uses system default PATH 0137 // so it need explicity add extra paths which can 0138 // contain gpg 0139 // Mac GPG and brew use /usr/local/bin 0140 // MacPorts uses /opt/local/bin 0141 paths << QStringLiteral("/usr/local/bin") << QStringLiteral("/opt/local/bin"); 0142 #endif 0143 paths.removeDuplicates(); 0144 0145 foreach (const QString &path, paths) { 0146 foreach (const QString &bin, bins) { 0147 if (check_bin(path + QLatin1Char('/') + bin)) { 0148 return path + QLatin1Char('/') + bin; 0149 } 0150 } 0151 } 0152 0153 // Return nothing if gpg not found 0154 return QString(); 0155 } 0156 0157 QString escape_string(const QString &in) 0158 { 0159 QString out; 0160 for (const QChar &c : in) { 0161 if (c == QLatin1Char('\\')) 0162 out += QStringLiteral("\\\\"); 0163 else if (c == QLatin1Char(':')) 0164 out += QStringLiteral("\\c"); 0165 else 0166 out += c; 0167 } 0168 return out; 0169 } 0170 0171 QString unescape_string(const QString &in) 0172 { 0173 QString out; 0174 for (int n = 0; n < in.length(); ++n) { 0175 if (in[n] == QLatin1Char('\\')) { 0176 if (n + 1 < in.length()) { 0177 if (in[n + 1] == QLatin1Char('\\')) 0178 out += QLatin1Char('\\'); 0179 else if (in[n + 1] == QLatin1Char('c')) 0180 out += QLatin1Char(':'); 0181 ++n; 0182 } 0183 } else 0184 out += in[n]; 0185 } 0186 return out; 0187 } 0188 0189 PGPKey publicKeyFromId(const QString &id) 0190 { 0191 MyKeyStoreList *ksl = MyKeyStoreList::instance(); 0192 if (!ksl) 0193 return PGPKey(); 0194 0195 return ksl->publicKeyFromId(id); 0196 } 0197 0198 PGPKey secretKeyFromId(const QString &id) 0199 { 0200 MyKeyStoreList *ksl = MyKeyStoreList::instance(); 0201 if (!ksl) 0202 return PGPKey(); 0203 0204 return ksl->secretKeyFromId(id); 0205 } 0206 0207 } // end namespace gpgQCAPlugin