/[winpt]/trunk/Src/wptKeyCache.cpp
ViewVC logotype

Annotation of /trunk/Src/wptKeyCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 133 - (hide annotations)
Mon Jan 9 09:15:29 2006 UTC (19 years, 1 month ago) by twoaday
File size: 18177 byte(s)
A lot of minor bug fixes.
New icons.

For a complete history, see the ChangeLog entries.


1 werner 36 /* wptKeyCache.cpp- Caching for the pub- and the secring
2 twoaday 133 * Copyright (C) 2001-2006 Timo Schulz
3 werner 36 *
4     * This file is part of MyGPGME.
5     *
6     * MyGPGME is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * MyGPGME is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19     */
20 twoaday 121
21 werner 42 #ifdef HAVE_CONFIG_H
22     #include <config.h>
23     #endif
24    
25 werner 36 #include <windows.h>
26     #include <stdio.h>
27     #include <string.h>
28     #include <malloc.h>
29     #include <ctype.h>
30     #include <assert.h>
31 twoaday 121 #include <gpgme.h>
32 werner 36
33     #include "wptKeyCache.h"
34     #include "openpgp.h"
35     #include "wptNLS.h"
36     #include "wptErrors.h"
37     #include "wptW32API.h"
38 twoaday 133 #include "wptGPG.h"
39 werner 36
40    
41 twoaday 133 /* Attribute list which holds the image data. */
42     struct attr_list_s {
43     struct attr_list_s *next;
44     char *fpr; /* fingerprint of the key */
45     unsigned char *d; /* actual JPEG data. */
46     unsigned long octets; /* length of the data. */
47     unsigned int flags; /* status of the attribute. */
48     };
49     typedef struct attr_list_s *attr_list_t;
50    
51    
52     void
53     free_attr_list (attr_list_t ctx)
54 werner 36 {
55 twoaday 133 attr_list_t n;
56     while (ctx) {
57     n = ctx->next;
58     free (ctx->fpr);
59     free (ctx->d);
60     ctx = n;
61     }
62     }
63    
64     /* Parse the attribute list in @fp and store it into @ctx.
65     Return value: number of parsed items. */
66     int
67     parse_attr_list (FILE *fp, const BYTE *data, DWORD datlen, attr_list_t *ctx)
68     {
69     attr_list_t c, t;
70     char buf[512], *p, *buffer;
71     int pos, n=0;
72    
73     *ctx = NULL;
74     while (fgets (buf, 511, fp)) {
75     if (strstr (buf, "\r\n"))
76     buf[strlen (buf)-2]=0;
77     if (strstr (buf, "\n"))
78     buf[strlen (buf)-1]=0;
79     if (strlen (buf) < 2 || !strstr (buf, "ATTRIBUTE"))
80     continue;
81     buffer = buf+9+10;
82     pos = 0;
83     c = (attr_list_t)calloc (1, sizeof *c);
84     p = strtok (buffer, " ");
85     while (p != NULL) {
86     switch (pos) {
87     case 0:
88     c->fpr = strdup (p);
89     break;
90    
91     case 1:
92     c->octets = strtoul (p, NULL, 10);
93     break;
94    
95     case 7:
96     c->flags = strtoul (p, NULL, 10);
97     break;
98    
99     default:
100     break;
101     }
102     pos++;
103     p = strtok (NULL, " ");
104     }
105     /*printf ("id=%s octets=%d flags=%d\n", c->fpr, c->octets, c->flags);*/
106     if (!*ctx)
107     *ctx = c;
108     else {
109     for (t = *ctx; t->next; t=t->next)
110     ;
111     t->next = c;
112     }
113     c->d = (unsigned char*)malloc (c->octets);
114     memcpy (c->d, data, c->octets);
115     data += c->octets;
116     datlen -= c->octets;
117     n++;
118     }
119     /*assert (datlen == 0); */
120     return n;
121     }
122 werner 36
123 twoaday 133
124     static int
125     parse_attr_data (const char *keyid, attr_list_t *list)
126     {
127     gpgme_error_t err;
128     FILE *tmp;
129     char *status;
130     BYTE *data;
131     DWORD ndata;
132    
133     err = gpg_get_photoid_data (keyid, &status, &data, &ndata);
134     if (err)
135     return err;
136    
137     if (ndata > 0) {
138     tmp = tmpfile ();
139     fwrite (status, 1, strlen (status), tmp);
140     fflush (tmp);
141     rewind (tmp);
142    
143     ndata = parse_attr_list (tmp, data, ndata, list);
144     fclose (tmp);
145 werner 36 }
146 twoaday 133 else
147     *list = NULL;
148    
149     safe_free (status);
150     safe_free (data);
151     return ndata;
152 werner 36 }
153    
154 twoaday 121
155 werner 36 /* Parse the secret keyring and retrieve some additional information
156     for each key which was found. */
157     static void
158     parse_secring (gpg_keycache_t cache, const char *kid, const char *secring)
159     {
160 twoaday 133 PACKET *pkt;
161 werner 36 PKT_secret_key *sk;
162     gpg_iobuf_t inp;
163     gpgme_error_t err;
164     gpgme_key_t key;
165     struct keycache_s *c=NULL;
166     char keyid[16+1];
167    
168     inp = gpg_iobuf_open (secring);
169 twoaday 133 if (!inp)
170 werner 36 return;
171 twoaday 133
172 werner 36 gpg_iobuf_ioctl (inp, 3, 1, NULL);
173 twoaday 133 pkt = (PACKET*)calloc (1, sizeof *pkt);
174 werner 36 gpg_init_packet (pkt);
175     while (gpg_parse_packet (inp, pkt) != -1) {
176     if (pkt->pkttype == PKT_SECRET_KEY) {
177     sk = pkt->pkt.secret_key;
178     /* XXX: key IDs of card public keys are wrong! */
179     _snprintf (keyid, sizeof (keyid)-1, "%08lX",
180     gpg_keyid_from_sk (sk, NULL));
181     if (kid && strcmp (kid, keyid) != 0)
182     goto next;
183     err = gpg_keycache_find_key2 (cache, keyid, 0, &key, &c);
184     if (err)
185     goto next;
186     c->gloflags.is_protected = sk->is_protected;
187     c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
188     if (c->pubpart != NULL) {
189     c->pubpart->gloflags.is_protected = sk->is_protected;
190     c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0;
191     }
192     }
193     next:
194     gpg_free_packet (pkt);
195     gpg_init_packet (pkt);
196     }
197     safe_free (pkt);
198     gpg_iobuf_close (inp);
199     }
200    
201    
202 twoaday 133 /* Update the photo image of a single key with the fingerprint
203     @fpr. The @dat struct contains the new item data. */
204     static gpgme_error_t
205     keycache_update_photo (gpg_keycache_t ctx, const char *fpr, attr_list_t dat)
206     {
207     struct keycache_s *fnd = NULL;
208     gpgme_key_t key;
209    
210     gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd);
211     if (!fnd)
212     return gpg_error (GPG_ERR_NOT_FOUND);
213     safe_free (fnd->attrib.d);
214     fnd->attrib.flags = dat->flags;
215     fnd->attrib.len = dat->octets;
216     fnd->attrib.d = (unsigned char*)malloc (dat->octets);
217     memcpy (fnd->attrib.d, dat->d, dat->octets);
218     return 0;
219     }
220    
221    
222     /* Update all photo images in the cache. */
223     static gpgme_error_t
224     keycache_update_photos (gpg_keycache_t ctx)
225     {
226     attr_list_t list=NULL, n;
227     DWORD ndata;
228    
229     ndata = parse_attr_data (NULL, &list);
230     if (ndata < 1) {
231     free_attr_list (list);
232     return 0;
233     }
234    
235     for (n=list; n; n=n->next)
236     keycache_update_photo (ctx, n->fpr, n);
237     free_attr_list (list);
238     return 0;
239     }
240    
241    
242 werner 36 /* Merge the information from the keyrings into the key cache structure. */
243     gpgme_error_t
244     keycache_prepare2 (gpg_keycache_t ctx, const char *kid,
245     const char *pubring, const char *secring)
246     {
247 twoaday 69 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
248 werner 36 gpgme_key_t key = NULL;
249     gpg_iobuf_t inp;
250 twoaday 133 PACKET *pkt;
251 werner 36 struct keycache_s *c;
252     const byte *sym_prefs;
253 twoaday 133 char keyid[16+1];
254 werner 36 int key_seen = 0;
255 twoaday 65 size_t nsym =0;
256 werner 36
257     if (secring) {
258     parse_secring (ctx, kid, secring);
259 twoaday 133 if (!pubring)
260 werner 36 return 0;
261     }
262     inp = gpg_iobuf_open (pubring);
263 twoaday 133 if (!inp)
264 werner 36 return gpg_error (GPG_ERR_KEYRING_OPEN);
265 twoaday 123 gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
266 werner 36
267 twoaday 133 pkt = (PACKET*)calloc (1, sizeof * pkt);
268 twoaday 123 gpg_init_packet (pkt);
269 werner 36 while (gpg_parse_packet (inp, pkt) != -1) {
270     if (pkt->pkttype == PKT_PUBLIC_KEY) {
271     strcpy (keyid, "");
272     key_seen = 1;
273     }
274    
275 twoaday 133 if (pkt->pkttype == PKT_SIGNATURE &&
276     pkt->pkt.signature->sig_class == 0x1F) {
277 werner 36 if (pkt->pkt.signature->numrevkeys == 0)
278     goto next;
279 twoaday 133 _snprintf (keyid, sizeof (keyid) -1, "%08X",
280     pkt->pkt.signature->keyid[1]);
281 werner 36 if (kid && strcmp (kid, keyid) != 0)
282     goto next;
283     err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
284     if (err)
285     goto next;
286     c->gloflags.has_desig_rev = 1;
287     }
288     if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 ) {
289 twoaday 133 sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed,
290     SIGSUBPKT_PREF_SYM, &nsym);
291     if (!sym_prefs)
292 werner 36 goto next;
293 twoaday 133 _snprintf (keyid, sizeof (keyid) - 1, "%08X",
294     pkt->pkt.signature->keyid[1]);
295 werner 36 if (kid && strcmp (kid, keyid) != 0)
296     goto next;
297     err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c);
298     if (err)
299     goto next;
300     else if (nsym > 0) {
301     c->sym_prefs = (unsigned char*)calloc (1, nsym+1);
302     if (!c->sym_prefs)
303     return gpg_error (GPG_ERR_ENOMEM);
304     memcpy (c->sym_prefs, sym_prefs, nsym);
305     }
306     }
307     next:
308     gpg_free_packet (pkt);
309     gpg_init_packet(pkt);
310     }
311    
312     safe_free (pkt);
313     gpg_iobuf_close (inp);
314     return err;
315     }
316    
317    
318     gpgme_error_t
319     gpg_keycache_prepare (gpg_keycache_t ctx, const char *pubr, const char *secr)
320     {
321     return keycache_prepare2 (ctx, NULL, pubr, secr);
322     }
323    
324     gpgme_error_t
325     gpg_keycache_prepare_single (gpg_keycache_t ctx, const char *keyid,
326     const char *pubr, const char *secr)
327     {
328     if (!strncmp (keyid, "0x", 2))
329     keyid += 2;
330     return keycache_prepare2 (ctx, keyid, pubr, secr);
331     }
332    
333    
334     /* Create new keycache object and return it in @r_ctx.
335     Return value: 0 on success. */
336     gpgme_error_t
337     gpg_keycache_new (gpg_keycache_t *r_ctx)
338     {
339     gpg_keycache_t ctx;
340    
341     if (!r_ctx)
342     return gpg_error (GPG_ERR_INV_ARG);
343     ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);
344     if (!ctx)
345     return gpg_error (GPG_ERR_ENOMEM);
346     ctx->secret = 0;
347     ctx->pos = 0;
348     *r_ctx = ctx;
349     return 0;
350     }
351    
352    
353     /* Release keycache object @ctx. */
354     void
355     gpg_keycache_release (gpg_keycache_t ctx)
356     {
357     struct keycache_s *c, *c2;
358    
359     if (!ctx)
360     return;
361    
362     for (c = ctx->item; c; c = c2) {
363     c2 = c->next;
364     gpgme_key_release (c->key);
365     c->key = NULL;
366 twoaday 133 safe_free (c->sym_prefs);
367     safe_free (c->attrib.d);
368     safe_free (c->card_type);
369 werner 36 free (c);
370     }
371 twoaday 133 safe_free (ctx);
372 werner 36 }
373    
374    
375     /* Set (progress) callback for the given keycache object.
376     @ctx the keycache
377     @cb the callback function
378     @cb_value1 opaque value which is passed to the callback.
379     @cb_value2 see @cb_value1. */
380     void
381     gpg_keycache_set_cb (gpg_keycache_t ctx,
382     void (*cb)(void *, const char *, int, int, int),
383     void * cb_value1, int cb_value2)
384     {
385     if (!ctx)
386     return;
387     ctx->cb = cb;
388     ctx->cb_value = cb_value1;
389     ctx->cb_value2 = cb_value2;
390     }
391    
392    
393     /* Add @key to the cache @ctx. @opaque return the key cache context as a void*.
394     Return value: 0 on success. */
395     gpgme_error_t
396     gpg_keycache_add_key (gpg_keycache_t ctx, gpgme_key_t key, void **opaque)
397     {
398 twoaday 41 struct keycache_s *c, *n1;
399 werner 36
400     if (!ctx)
401     return gpg_error (GPG_ERR_INV_ARG);
402    
403     c = (struct keycache_s*)calloc (1, sizeof *c);
404     if (!c)
405     return gpg_error (GPG_ERR_ENOMEM);
406     c->gloflags.is_protected = 1; /*default: assume protection. */
407     c->key = key;
408     if (!ctx->item)
409     ctx->item = c;
410     else {
411     for (n1 = ctx->item; n1 && n1->next; n1 = n1->next)
412     ;
413     n1->next = c;
414     }
415     if (opaque)
416     *opaque = c;
417     return 0;
418     }
419    
420    
421    
422     #define has_keyid_len(pattern) (\
423     strlen (pattern) == 8 || strlen (pattern) == 10 || \
424     strlen (pattern) == 16 || strlen (pattern) == 18)
425    
426    
427     gpgme_error_t
428     gpg_keycache_find_key2 (gpg_keycache_t ctx, const char *pattern, int flags,
429     gpgme_key_t *r_key, struct keycache_s **r_item)
430     {
431     struct keycache_s *c;
432     gpgme_subkey_t s;
433     gpgme_user_id_t u;
434     gpgme_key_t key;
435     const char *kid;
436    
437     if (!ctx || !r_key)
438     return gpg_error (GPG_ERR_INV_ARG);
439    
440     if (strstr (pattern, "0x"))
441     pattern += 2;
442    
443     /* Sometimes a subkey has no valid fpr. As a kludge we convert v4
444     fingerprints into the 64-bit keyid. */
445     if (strlen (pattern) == 40 && isxdigit (*pattern))
446     pattern += 32;
447    
448     /* XXX: this code is very slow, revamp it and use hash tables whenever
449     it is possible. */
450     for (c = ctx->item; c; c = c->next) {
451     key = c->key;
452     assert (key->_refs >= 1);
453     for (s = key->subkeys; s; s = s->next) {
454     for (u = key->uids; u; u = u->next) {
455     if (u->name && stristr (u->name, pattern)) {
456     if (r_item)
457     *r_item = c;
458     *r_key = flags? c->pubpart->key : c->key;
459     return 0;
460     }
461     }
462     if (has_keyid_len (pattern))
463     kid = s->keyid;
464     else
465     kid = s->fpr;
466     if (kid && stristr (kid, pattern)) {
467     if (r_item)
468     *r_item = c;
469     *r_key = flags? c->pubpart->key : c->key;
470     return 0;
471     }
472     }
473     }
474     *r_key = NULL;
475     return gpg_error (GPG_ERR_INTERNAL);
476 twoaday 133 }
477 werner 36
478    
479     gpgme_error_t
480     gpg_keycache_find_key (gpg_keycache_t ctx, const char *pattern,
481     int flags, gpgme_key_t *r_key)
482     {
483     return gpg_keycache_find_key2 (ctx, pattern, flags, r_key, NULL);
484     }
485    
486    
487 twoaday 133 /* Reload a photo image of a single key with the keyid @keyid.
488     Return value: 0 on success. */
489     static gpgme_error_t
490     keycache_reload_photo (gpg_keycache_t ctx, const char *keyid)
491     {
492     attr_list_t list;
493    
494     if (parse_attr_data (keyid, &list) < 1) {
495     free_attr_list (list);
496     return 0;
497     }
498     keycache_update_photo (ctx, list->fpr, list);
499     free_attr_list (list);
500     return 0;
501     }
502    
503    
504 werner 36 gpgme_error_t
505     gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec,
506     void *opaque, const char *keyid)
507     {
508     struct keycache_s *c = NULL, *c_new=NULL;
509     gpgme_key_t key=NULL, fndkey=NULL;
510     gpgme_error_t err;
511     gpgme_ctx_t gctx;
512     gpg_keycache_t pub = (gpg_keycache_t)opaque;
513    
514     err = gpgme_new (&gctx);
515     if (err)
516     return err;
517     err = gpgme_get_key (gctx, keyid, &key, is_sec);
518     gpgme_release (gctx);
519     if (err)
520     return err;
521     err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c);
522     if (!err && c != NULL) {
523     log_debug ("keycache update: keyid=%s %p\r\n", keyid, pub);
524     gpgme_key_release (fndkey);
525     c->key = key;
526     c->flags = 0;
527     if (is_sec && pub != NULL &&
528     !gpg_keycache_find_key (pub, keyid, 0, &fndkey)) {
529     log_debug ("keycache update: set public part %p\r\n", fndkey);
530     c->pubpart->key = fndkey;
531     }
532 twoaday 133 /* XXX: this is also called for keys without a photo-id. */
533     keycache_reload_photo (ctx, keyid);
534 werner 36 }
535     else {
536     log_debug ("keycache add: sync public part\r\n");
537     if (is_sec)
538     gpg_keycache_find_key2 (pub, keyid, 0, &fndkey, &c_new);
539     gpg_keycache_add_key (ctx, key, (void **)&c);
540     if (c != NULL && is_sec) {
541     log_debug ("keycache add: keyid=%s %p %p\r\n", keyid, c, fndkey);
542     c->pubpart = c_new;
543     if (c_new != NULL) {
544     c->pubpart->key = fndkey;
545     c->gloflags.is_protected = c_new->gloflags.is_protected;
546     c->gloflags.divert_to_card = c_new->gloflags.divert_to_card;
547     }
548     }
549     }
550     return 0;
551     }
552    
553    
554     /* Delete a key from the cache @ctx with the pattern @pattern.
555     Return value: 0 on success. */
556     gpgme_error_t
557     gpg_keycache_delete_key (gpg_keycache_t ctx, const char *pattern)
558     {
559     struct keycache_s *itm = NULL, *c;
560     gpgme_key_t key;
561     gpgme_error_t rc;
562    
563     if (!ctx)
564     return gpg_error (GPG_ERR_INV_ARG);
565     rc = gpg_keycache_find_key2 (ctx, pattern, 0, &key, &itm);
566     if (rc)
567     return rc;
568    
569     c = ctx->item;
570     if (c->next == NULL) {
571     gpgme_key_release (itm->key);
572     if (itm)
573     free (itm);
574     ctx->item = NULL;
575     }
576     else {
577     while (c && c->next != itm)
578     c = c->next;
579     c->next = c->next->next;
580     gpgme_key_release (itm->key);
581     if (itm)
582     free (itm);
583     }
584     return 0;
585     }
586    
587    
588     /* Initialize the given cache @ctx. If @pattern is NULL, the entire keyring
589     will be added to the cache. @secret is 1 if the source is the secret keyring.
590     Return value: 0 on success. */
591     gpgme_error_t
592     gpg_keycache_init (gpg_keycache_t ctx, const char *pattern, int secret)
593     {
594     gpgme_error_t err;
595     gpgme_ctx_t c;
596     gpgme_key_t key;
597     int count = 0;
598    
599     if (!ctx)
600     return gpg_error (GPG_ERR_INV_ARG);
601    
602     err = gpgme_new (&c);
603     if (err)
604     return err;
605    
606     gpgme_set_keylist_mode (c, GPGME_KEYLIST_MODE_SIGS);
607     err = gpgme_op_keylist_start (c, pattern, secret);
608     while(!err) {
609     err = gpgme_op_keylist_next (c, &key);
610     if (!err)
611     err = gpg_keycache_add_key (ctx, key, NULL);
612     if (ctx->cb)
613     ctx->cb (ctx->cb_value, _("Load GPG Keyrings..."), 0,
614     count++, ctx->cb_value2);
615     }
616     if (gpgme_err_code (err) == GPG_ERR_EOF)
617     err = gpg_error (GPG_ERR_NO_ERROR);
618 twoaday 133 keycache_update_photos (ctx);
619 werner 36 /* XXX: make sure the progress dialog is closed. */
620     gpgme_op_keylist_end (c);
621     gpgme_release (c);
622     return err;
623     }
624    
625    
626     /* XXX: kludge to see if the key is stored on a card. */
627     static int
628     key_divert_to_card (gpgme_key_t key)
629     {
630     gpgme_subkey_t k;
631     int n=0, n_alg=0, can_auth = 0;
632    
633     for (k = key->subkeys; k; k = k->next) {
634     n++;
635     if (k->pubkey_algo == GPGME_PK_RSA && k->length == 1024)
636     n_alg++;
637     if (k->can_authenticate)
638     can_auth++;
639     }
640     if (n == 3 && n_alg == 3 && can_auth == 1)
641     return 1;
642     return 0;
643     }
644    
645    
646 twoaday 123 static unsigned char*
647     copy_uid_prefs (const unsigned char *prefs)
648     {
649     unsigned char *p;
650     size_t pos=0;
651    
652     while (prefs[pos] != 0)
653     pos++;
654     p = (unsigned char*)calloc (1, pos+1);
655     if (!p)
656     abort ();
657     memcpy (p, prefs, pos);
658     return p;
659     }
660    
661    
662 werner 36 gpgme_error_t
663     gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec)
664     {
665     struct keycache_s *c, *c_sec;
666     gpgme_key_t key;
667    
668     if (!pub || !sec)
669     return gpg_error (GPG_ERR_INV_ARG);
670    
671     for (c=sec->item; c; c=c->next) {
672     if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, &key, &c_sec)) {
673     c_sec->gloflags.is_protected = c->gloflags.is_protected;
674     c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card;
675     if (!c->gloflags.divert_to_card)
676     c->gloflags.divert_to_card = key_divert_to_card (key);
677 twoaday 123 c->sym_prefs = copy_uid_prefs (c_sec->sym_prefs);
678 werner 36 c->pubpart = c_sec;
679     c->pubpart->key = key;
680     }
681     }
682     return 0;
683     }
684    
685    
686     /* Rewind the given cache @ctx to the begin. */
687     void
688     gpg_keycache_rewind (gpg_keycache_t ctx)
689     {
690     if (ctx)
691     ctx->pos = 0;
692     }
693    
694    
695    
696     /* Return the number of elements in the cache @ctx. */
697     int
698     gpg_keycache_get_size (gpg_keycache_t ctx)
699     {
700     struct keycache_s *c;
701     int count = 0;
702    
703     if (!ctx)
704     return 0;
705     for (c = ctx->item; c; c = c->next)
706     count++;
707     return count;
708     }
709    
710    
711     static gpgme_error_t
712     keycache_next_key (gpg_keycache_t ctx, int flags,
713     struct keycache_s **c, gpgme_key_t *r_key)
714     {
715     if (!ctx || !r_key)
716     return gpg_error (GPG_ERR_INV_ARG);
717    
718     if (!ctx->pos)
719     ctx->tmp = ctx->item;
720    
721     if (!ctx->tmp || !ctx->tmp->key) {
722     ctx->pos = 0;
723     *r_key = NULL;
724     return gpg_error (GPG_ERR_EOF);
725     }
726    
727     *r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key;
728     *c = ctx->tmp = ctx->tmp->next;
729     ctx->pos++;
730    
731     return 0;
732     }
733    
734    
735     /* Return the next key from the cache @ctx. The key will be returned
736     in @r_key. @flags can contain additional flags.
737     Return value: 0 on success. */
738     gpgme_error_t
739     gpg_keycache_next_key (gpg_keycache_t ctx, int flags, gpgme_key_t *r_key)
740     {
741     struct keycache_s *c=NULL;
742     gpgme_error_t err = 0;
743    
744     err = keycache_next_key (ctx, flags, &c, r_key);
745     return err;
746     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26