1 #include "mypgpkeycontext.h"
2 #include "gpgop.h"
3 #include "utils.h"
4 #include <QDir>
5 #include <QTemporaryFile>
6
7 using namespace QCA;
8
9 namespace gpgQCAPlugin {
10
MyPGPKeyContext(Provider * p)11 MyPGPKeyContext::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
clone() const20 Provider::Context *MyPGPKeyContext::clone() const
21 {
22 return new MyPGPKeyContext(*this);
23 }
24
props() const25 const PGPKeyContextProps *MyPGPKeyContext::props() const
26 {
27 return &_props;
28 }
29
toBinary() const30 QByteArray MyPGPKeyContext::toBinary() const
31 {
32 if (_props.inKeyring) {
33 GpgOp gpg(find_bin());
34 gpg.setAsciiFormat(false);
35 gpg.doExport(_props.keyId);
36 gpg_waitForFinished(&gpg);
37 gpg_keyStoreLog(gpg.readDiagnosticText());
38 if (!gpg.success())
39 return QByteArray();
40 return gpg.read();
41 } else
42 return cacheExportBinary;
43 }
44
fromBinary(const QByteArray & a)45 ConvertResult 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(pubname, secname);
74 gpg.doImport(a);
75 gpg_waitForFinished(&gpg);
76 gpg_keyStoreLog(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);
92 gpg_keyStoreLog(gpg.readDiagnosticText());
93 if (!gpg.success()) {
94 cleanup_temp_keyring(pubname);
95 cleanup_temp_keyring(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);
106 gpg_keyStoreLog(gpg.readDiagnosticText());
107 if (!gpg.success()) {
108 cleanup_temp_keyring(pubname);
109 cleanup_temp_keyring(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(pubname);
120 cleanup_temp_keyring(secname);
121 return ErrorDecode;
122 }
123 }
124
125 // export binary/ascii and cache
126
127 gpg.setAsciiFormat(false);
128 gpg.doExport(key.keyItems.first().id);
129 gpg_waitForFinished(&gpg);
130 gpg_keyStoreLog(gpg.readDiagnosticText());
131 if (!gpg.success()) {
132 cleanup_temp_keyring(pubname);
133 cleanup_temp_keyring(secname);
134 return ErrorDecode;
135 }
136 cacheExportBinary = gpg.read();
137
138 gpg.setAsciiFormat(true);
139 gpg.doExport(key.keyItems.first().id);
140 gpg_waitForFinished(&gpg);
141 gpg_keyStoreLog(gpg.readDiagnosticText());
142 if (!gpg.success()) {
143 cleanup_temp_keyring(pubname);
144 cleanup_temp_keyring(secname);
145 return ErrorDecode;
146 }
147 cacheExportAscii = QString::fromLocal8Bit(gpg.read());
148
149 // all done
150
151 cleanup_temp_keyring(pubname);
152 cleanup_temp_keyring(secname);
153
154 set(key, sec, false, false);
155 return ConvertGood;
156 }
157
toAscii() const158 QString MyPGPKeyContext::toAscii() const
159 {
160 if (_props.inKeyring) {
161 GpgOp gpg(find_bin());
162 gpg.setAsciiFormat(true);
163 gpg.doExport(_props.keyId);
164 gpg_waitForFinished(&gpg);
165 gpg_keyStoreLog(gpg.readDiagnosticText());
166 if (!gpg.success())
167 return QString();
168 return QString::fromLocal8Bit(gpg.read());
169 } else {
170 return cacheExportAscii;
171 }
172 }
173
fromAscii(const QString & s)174 ConvertResult 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(s.toLocal8Bit());
180 }
181
set(const GpgOp::Key & i,bool isSecret,bool inKeyring,bool isTrusted)182 void 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
cleanup_temp_keyring(const QString & name)196 void MyPGPKeyContext::cleanup_temp_keyring(const QString &name)
197 {
198 QFile::remove(name);
199 QFile::remove(name + QLatin1Char('~')); // remove possible backup file
200 }
201
202 } // end namespace gpgQCAPlugin
203