1#include "mypgpkeycontext.h"
2#include "gpgop.h"
3#include "utils.h"
4#include <QDir>
5#include <QTemporaryFile>
6
7using namespace QCA;
8
9namespace gpgQCAPlugin {
10
11MyPGPKeyContext::MyPGPKeyContext(Provider *p)
12 : PGPKeyContext(p)
13{
14 // zero out the props
15 _props.isSecret = false;
16 _props.inKeyring = true;
17 _props.isTrusted = false;
18}
19
20Provider::Context *MyPGPKeyContext::clone() const
21{
22 return new MyPGPKeyContext(*this);
23}
24
25const PGPKeyContextProps *MyPGPKeyContext::props() const
26{
27 return &_props;
28}
29
30QByteArray MyPGPKeyContext::toBinary() const
31{
32 if (_props.inKeyring) {
33 GpgOp gpg(find_bin());
34 gpg.setAsciiFormat(false);
35 gpg.doExport(key_id: _props.keyId);
36 gpg_waitForFinished(gpg: &gpg);
37 gpg_keyStoreLog(str: gpg.readDiagnosticText());
38 if (!gpg.success())
39 return QByteArray();
40 return gpg.read();
41 } else
42 return cacheExportBinary;
43}
44
45ConvertResult MyPGPKeyContext::fromBinary(const QByteArray &a)
46{
47 GpgOp::Key key;
48 bool sec = false;
49
50 // temporary keyrings
51 QString pubname, secname;
52
53 QTemporaryFile pubtmp(QDir::tempPath() + QLatin1String("/qca_gnupg_tmp.XXXXXX.gpg"));
54 if (!pubtmp.open())
55 return ErrorDecode;
56
57 QTemporaryFile sectmp(QDir::tempPath() + QLatin1String("/qca_gnupg_tmp.XXXXXX.gpg"));
58 if (!sectmp.open())
59 return ErrorDecode;
60
61 pubname = pubtmp.fileName();
62 secname = sectmp.fileName();
63
64 // we turn off autoRemove so that we can close the files
65 // without them getting deleted
66 pubtmp.setAutoRemove(false);
67 sectmp.setAutoRemove(false);
68 pubtmp.close();
69 sectmp.close();
70
71 // import key into temporary keyring
72 GpgOp gpg(find_bin());
73 gpg.setKeyrings(pubfile: pubname, secfile: secname);
74 gpg.doImport(in: a);
75 gpg_waitForFinished(gpg: &gpg);
76 gpg_keyStoreLog(str: gpg.readDiagnosticText());
77 // comment this out. apparently gpg will report failure for
78 // an import if there are trust issues, even though the
79 // key actually did get imported
80 /*if(!gpg.success())
81 {
82 cleanup_temp_keyring(pubname);
83 cleanup_temp_keyring(secname);
84 return ErrorDecode;
85 }*/
86
87 // now extract the key from gpg like normal
88
89 // is it a public key?
90 gpg.doPublicKeys();
91 gpg_waitForFinished(gpg: &gpg);
92 gpg_keyStoreLog(str: gpg.readDiagnosticText());
93 if (!gpg.success()) {
94 cleanup_temp_keyring(name: pubname);
95 cleanup_temp_keyring(name: secname);
96 return ErrorDecode;
97 }
98
99 const GpgOp::KeyList pubkeys = gpg.keys();
100 if (!pubkeys.isEmpty()) {
101 key = pubkeys.first();
102 } else {
103 // is it a secret key?
104 gpg.doSecretKeys();
105 gpg_waitForFinished(gpg: &gpg);
106 gpg_keyStoreLog(str: gpg.readDiagnosticText());
107 if (!gpg.success()) {
108 cleanup_temp_keyring(name: pubname);
109 cleanup_temp_keyring(name: secname);
110 return ErrorDecode;
111 }
112
113 const GpgOp::KeyList seckeys = gpg.keys();
114 if (!seckeys.isEmpty()) {
115 key = seckeys.first();
116 sec = true;
117 } else {
118 // no keys found
119 cleanup_temp_keyring(name: pubname);
120 cleanup_temp_keyring(name: secname);
121 return ErrorDecode;
122 }
123 }
124
125 // export binary/ascii and cache
126
127 gpg.setAsciiFormat(false);
128 gpg.doExport(key_id: key.keyItems.first().id);
129 gpg_waitForFinished(gpg: &gpg);
130 gpg_keyStoreLog(str: gpg.readDiagnosticText());
131 if (!gpg.success()) {
132 cleanup_temp_keyring(name: pubname);
133 cleanup_temp_keyring(name: secname);
134 return ErrorDecode;
135 }
136 cacheExportBinary = gpg.read();
137
138 gpg.setAsciiFormat(true);
139 gpg.doExport(key_id: key.keyItems.first().id);
140 gpg_waitForFinished(gpg: &gpg);
141 gpg_keyStoreLog(str: gpg.readDiagnosticText());
142 if (!gpg.success()) {
143 cleanup_temp_keyring(name: pubname);
144 cleanup_temp_keyring(name: secname);
145 return ErrorDecode;
146 }
147 cacheExportAscii = QString::fromLocal8Bit(ba: gpg.read());
148
149 // all done
150
151 cleanup_temp_keyring(name: pubname);
152 cleanup_temp_keyring(name: secname);
153
154 set(i: key, isSecret: sec, inKeyring: false, isTrusted: false);
155 return ConvertGood;
156}
157
158QString MyPGPKeyContext::toAscii() const
159{
160 if (_props.inKeyring) {
161 GpgOp gpg(find_bin());
162 gpg.setAsciiFormat(true);
163 gpg.doExport(key_id: _props.keyId);
164 gpg_waitForFinished(gpg: &gpg);
165 gpg_keyStoreLog(str: gpg.readDiagnosticText());
166 if (!gpg.success())
167 return QString();
168 return QString::fromLocal8Bit(ba: gpg.read());
169 } else {
170 return cacheExportAscii;
171 }
172}
173
174ConvertResult MyPGPKeyContext::fromAscii(const QString &s)
175{
176 // GnuPG does ascii/binary detection for imports, so for
177 // simplicity we consider an ascii import to just be a
178 // binary import that happens to be comprised of ascii
179 return fromBinary(a: s.toLocal8Bit());
180}
181
182void MyPGPKeyContext::set(const GpgOp::Key &i, bool isSecret, bool inKeyring, bool isTrusted)
183{
184 const GpgOp::KeyItem &ki = i.keyItems.first();
185
186 _props.keyId = ki.id;
187 _props.userIds = i.userIds;
188 _props.isSecret = isSecret;
189 _props.creationDate = ki.creationDate;
190 _props.expirationDate = ki.expirationDate;
191 _props.fingerprint = ki.fingerprint.toLower();
192 _props.inKeyring = inKeyring;
193 _props.isTrusted = isTrusted;
194}
195
196void MyPGPKeyContext::cleanup_temp_keyring(const QString &name)
197{
198 QFile::remove(fileName: name);
199 QFile::remove(fileName: name + QLatin1Char('~')); // remove possible backup file
200}
201
202} // end namespace gpgQCAPlugin
203

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