certmanager/lib

kpgpkeylistjob.cpp
1/*
2 kpgpkeylistjob.cpp
3
4 This file is part of libkleopatra, the KDE keymanagement library
5 Copyright (c) 2004 Ingo Kloecker <kloecker@kde.org>
6
7 Libkleopatra is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 Libkleopatra is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
21 In addition, as a special exception, the copyright holders give
22 permission to link the code of this program with any edition of
23 the TQt library by Trolltech AS, Norway (or with modified versions
24 of TQt that use the same license as TQt), and distribute linked
25 combinations including the two. You must obey the GNU General
26 Public License in all respects for all of the code used other than
27 TQt. If you modify this file, you may extend this exception to
28 your version of the file, but you are not obligated to do so. If
29 you do not wish to do so, delete this exception statement from
30 your version.
31*/
32
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36
37#include "kpgpkeylistjob.h"
38
39#include <kpgpbase.h>
40#include <kpgpkey.h>
41
42#include <gpgmepp/key.h>
43#include <gpgmepp/keylistresult.h>
44
45#include <gpgme.h>
46
47#include <tqtimer.h>
48
49#include <stdlib.h>
50#include <string.h>
51#include <assert.h>
52
53Kleo::KpgpKeyListJob::KpgpKeyListJob( Kpgp::Base * pgpBase )
54 : KeyListJob( 0, "Kleo::KpgpKeyListJob" ),
55 mPgpBase( pgpBase )
56{
57}
58
59Kleo::KpgpKeyListJob::~KpgpKeyListJob() {
60}
61
62// the following function is a verbatim copy from gpgme/key.c
63static char *
64set_user_id_part (char *tail, const char *buf, size_t len)
65{
66 while (len && (buf[len - 1] == ' ' || buf[len - 1] == '\t'))
67 len--;
68 for (; len; len--)
69 *tail++ = *buf++;
70 *tail++ = 0;
71 return tail;
72}
73
74// the following function is a verbatim copy from gpgme/key.c
75static void
76parse_user_id (char *src, char **name, char **email,
77 char **comment, char *tail)
78{
79 const char *start = NULL;
80 int in_name = 0;
81 int in_email = 0;
82 int in_comment = 0;
83
84 while (*src)
85 {
86 if (in_email)
87 {
88 if (*src == '<')
89 /* Not legal but anyway. */
90 in_email++;
91 else if (*src == '>')
92 {
93 if (!--in_email && !*email)
94 {
95 *email = tail;
96 tail = set_user_id_part (tail, start, src - start);
97 }
98 }
99 }
100 else if (in_comment)
101 {
102 if (*src == '(')
103 in_comment++;
104 else if (*src == ')')
105 {
106 if (!--in_comment && !*comment)
107 {
108 *comment = tail;
109 tail = set_user_id_part (tail, start, src - start);
110 }
111 }
112 }
113 else if (*src == '<')
114 {
115 if (in_name)
116 {
117 if (!*name)
118 {
119 *name = tail;
120 tail = set_user_id_part (tail, start, src - start);
121 }
122 in_name = 0;
123 }
124 in_email = 1;
125 start = src + 1;
126 }
127 else if (*src == '(')
128 {
129 if (in_name)
130 {
131 if (!*name)
132 {
133 *name = tail;
134 tail = set_user_id_part (tail, start, src - start);
135 }
136 in_name = 0;
137 }
138 in_comment = 1;
139 start = src + 1;
140 }
141 else if (!in_name && *src != ' ' && *src != '\t')
142 {
143 in_name = 1;
144 start = src;
145 }
146 src++;
147 }
148
149 if (in_name)
150 {
151 if (!*name)
152 {
153 *name = tail;
154 tail = set_user_id_part (tail, start, src - start);
155 }
156 }
157
158 /* Let unused parts point to an EOS. */
159 tail--;
160 if (!*name)
161 *name = tail;
162 if (!*email)
163 *email = tail;
164 if (!*comment)
165 *comment = tail;
166}
167
168gpgme_user_id_t KpgpUserID2GPGMEUserID( const Kpgp::UserID * kUserId )
169{
170 // inspired by _gpgme_key_append_name
171
172 const TQCString text = kUserId->text().utf8();
173 const int src_len = text.length();
174
175 gpgme_user_id_t uid;
176 /* Allocate enough memory for the _gpgme_user_id struct, for the actual user
177 id (the text) and for the parsed version. */
178 uid = (gpgme_user_id_t) malloc( sizeof( *uid ) + 2 * src_len + 3 );
179 memset( uid, 0, sizeof *uid );
180 uid->revoked = kUserId->revoked();
181 uid->invalid = kUserId->invalid();
182 uid->validity = (gpgme_validity_t) kUserId->validity();
183
184 uid->uid = ((char *) uid) + sizeof (*uid);
185 char *dst = uid->uid;
186 memcpy( dst, text.data(), src_len + 1 );
187
188 dst += src_len + 1;
189 parse_user_id( uid->uid, &uid->name, &uid->email,
190 &uid->comment, dst );
191
192 return uid;
193}
194
195gpgme_subkey_t KpgpSubkey2GPGMESubKey( const Kpgp::Subkey * kSubkey )
196{
197 gpgme_subkey_t subkey;
198
199 const TQCString fpr = kSubkey->fingerprint();
200 const unsigned int fpr_len = fpr.length();
201 const TQCString keyId = kSubkey->longKeyID();
202
203 subkey = (gpgme_subkey_t) calloc( 1, sizeof( *subkey ) + fpr_len + 1 );
204 subkey->revoked = kSubkey->revoked();
205 subkey->expired = kSubkey->expired();
206 subkey->disabled = kSubkey->disabled();
207 subkey->invalid = kSubkey->invalid();
208 subkey->can_encrypt = kSubkey->canEncrypt();
209 subkey->can_sign = kSubkey->canSign();
210 subkey->can_certify = kSubkey->canCertify();
211 subkey->secret = kSubkey->secret();
212 subkey->pubkey_algo = (gpgme_pubkey_algo_t) kSubkey->keyAlgorithm();
213 subkey->length = kSubkey->keyLength();
214 subkey->keyid = subkey->_keyid;
215 memcpy( subkey->_keyid, keyId.data(), keyId.length() + 1 );
216 subkey->fpr = ((char *) subkey) + sizeof( *subkey );
217 memcpy( subkey->fpr, fpr.data(), fpr_len + 1 );
218 subkey->timestamp = kSubkey->creationDate();
219 subkey->expires = kSubkey->expirationDate();
220
221 return subkey;
222}
223
224gpgme_key_t KpgpKey2gpgme_key( const Kpgp::Key * kKey )
225{
226 gpgme_key_t key;
227
228 key = (gpgme_key_t) calloc( 1, sizeof( *key ) );
229 key->revoked = kKey->revoked();
230 key->expired = kKey->expired();
231 key->disabled = kKey->disabled();
232 key->invalid = kKey->invalid();
233 key->can_encrypt = kKey->canEncrypt();
234 key->can_sign = kKey->canSign();
235 key->can_certify = kKey->canCertify();
236 key->secret = kKey->secret();
237 key->protocol = GPGME_PROTOCOL_OpenPGP;
238 key->owner_trust = GPGME_VALIDITY_UNKNOWN; // FIXME?
239
240 Kpgp::UserIDList kUserIDs = kKey->userIDs();
241 for ( Kpgp::UserIDListIterator it( kUserIDs ); it.current(); ++it ) {
242 gpgme_user_id_t uid = KpgpUserID2GPGMEUserID( *it );
243 if ( !key->uids )
244 key->uids = uid;
245 if ( key->_last_uid )
246 key->_last_uid->next = uid;
247 key->_last_uid = uid;
248 }
249
250 Kpgp::SubkeyList kSubkeys = kKey->subkeys();
251 for ( Kpgp::SubkeyListIterator it( kSubkeys ); it.current(); ++it ) {
252 gpgme_subkey_t subkey = KpgpSubkey2GPGMESubKey( *it );
253 if (!key->subkeys)
254 key->subkeys = subkey;
255 if (key->_last_subkey)
256 key->_last_subkey->next = subkey;
257 key->_last_subkey = subkey;
258 }
259
260 return key;
261}
262
263GpgME::Error Kleo::KpgpKeyListJob::start( const TQStringList & patterns,
264 bool secretOnly ) {
265 mPatterns = patterns;
266 mSecretOnly = secretOnly;
267 TQTimer::singleShot( 0, this, TQ_SLOT( slotDoIt() ) );
268 return GpgME::Error( 0 );
269}
270
271void Kleo::KpgpKeyListJob::slotDoIt() {
272 std::vector<GpgME::Key> keys;
273 GpgME::KeyListResult res = exec( mPatterns, mSecretOnly, keys );
274 for ( std::vector<GpgME::Key>::const_iterator it = keys.begin();
275 it != keys.end(); ++it )
276 emit nextKey( *it );
277 emit done();
278 emit result( res );
279 deleteLater();
280}
281
282GpgME::KeyListResult Kleo::KpgpKeyListJob::exec( const TQStringList & patterns,
283 bool secretOnly,
284 std::vector<GpgME::Key> & keys ) {
285 Kpgp::KeyList kKeys;
286 if ( secretOnly )
287 kKeys = mPgpBase->secretKeys( patterns );
288 else
289 kKeys = mPgpBase->publicKeys( patterns );
290
291 keys.clear();
292 for ( Kpgp::KeyListIterator it( kKeys ); it.current(); ++it ) {
293 keys.push_back( GpgME::Key( KpgpKey2gpgme_key(*it), true ) );
294 }
295
296 _gpgme_op_keylist_result res;
297 res.truncated = 0; // key list is not truncated
298 res._unused = 0;
299
300 return GpgME::KeyListResult( GpgME::Error( 0 ), res );
301}
302
303#include "kpgpkeylistjob.moc"