/[winpt]/trunk/MyGPGME/keylist.c
ViewVC logotype

Annotation of /trunk/MyGPGME/keylist.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (hide annotations)
Wed Aug 10 11:33:35 2005 UTC (19 years, 6 months ago) by twoaday
File MIME type: text/plain
File size: 19720 byte(s)
2005-08-06  Timo Schulz  <twoaday@freakmail.de>
 
        * wptGPGME.cpp (keycache_update): Reload OpenPGP parts
        of the secret key.
        (keycache_init): cache name of secret keyring.
        * wptKeyList.cpp (keylist_upd_key): Do not add long keyid.
        (get_key_type): Do not assume 'ultimate' means key pair.
        * wptKeyEditDlgs.cpp (diff_time): New.
        (keyedit_addsubkey_dlg_proc): Changed design and use
        diff_time. Drop checks for invalid keylength (< 1024, > 4096)
        because the combo box automatically handles this.
        * wptKeyManager.cpp (km_set_implicit_trust): Return error code.
        * wptGPG.cpp (get_backup_name): New.
        (gnupg_backup_keyrings): Rotate backup names, from 0..3.
        * wptClipImportDialog.cpp (clip_import_dlg_proc): Free memory.
        * wptKeyManagerDlg.cpp (keymanager_dlg_proc): Use 0x short keyid and
        not the long keyid.


1 twoaday 2 /* keylist.c - key listing
2     * Copyright (C) 2000, 2001 Werner Koch (dd9jn), g10 Code GmbH
3 twoaday 17 * Copyright (C) 2002-2005 Timo Schulz
4 twoaday 2 *
5     * This file is part of MyGPGME.
6     *
7     * MyGPGME is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * MyGPGME 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
15     * GNU 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20     */
21    
22     #include <stdio.h>
23     #include <stdlib.h>
24     #include <string.h>
25     #include <time.h>
26     #include <ctype.h>
27     #include <assert.h>
28     #include <windows.h>
29    
30     #include "util.h"
31     #include "context.h"
32     #include "ops.h"
33     #include "key.h"
34    
35     static void finish_key ( gpgme_ctx_t ctx );
36    
37    
38     static void
39     keylist_status_handler( gpgme_ctx_t ctx, gpg_status_code_t code, char *args )
40     {
41     if( ctx->out_of_core )
42     return;
43    
44     switch( code ) {
45     case STATUS_EOF:
46     if( ctx->tmp_key )
47     finish_key( ctx );
48     break;
49    
50     default: /* ignore all other codes */
51     break;
52     }
53     }
54    
55    
56    
57     static time_t
58 twoaday 22 parse_timestamp (char * p)
59 twoaday 2 {
60 twoaday 22 return *p ? (time_t)strtoul (p, NULL, 10) : 0;
61 twoaday 2 }
62    
63    
64     static void
65     set_mainkey_trust_info( gpgme_key_t key, const char * s )
66     {
67     /* look at letters and stop at the first digit */
68     for( ; *s && !isdigit( *s ); s++ ) {
69     switch( *s ) {
70     case 'u': key->gloflags.ultimate = 1;
71     key->validity = GPGME_VALIDITY_ULTIMATE; break;
72     case '-':
73     case 'q': key->validity = GPGME_VALIDITY_UNDEFINED; break;
74     case 'm': key->validity = GPGME_VALIDITY_MARGINAL; break;
75     case 'f': key->validity = GPGME_VALIDITY_FULL; break;
76     case 'e': key->keys.flags.expired = 1; break;
77     case 'r': key->keys.flags.revoked = 1;
78     key->validity = GPGME_VALIDITY_REVOKED; break;
79     case 'd': key->keys.flags.disabled = 1; break;
80     case 'i': key->keys.flags.invalid = 1; break;
81     }
82     }
83     }
84    
85    
86     static void
87     set_userid_flags (struct user_id_s * u, const char * s)
88     {
89     /* look at letters and stop at the first digit */
90     for (; *s && !isdigit (*s); s++) {
91     switch( *s ) {
92     case 'r': u->flags.revoked = 1;
93     u->validity = GPGME_VALIDITY_REVOKED; break;
94     case 'i': u->flags.invalid = 1;
95     u->validity = GPGME_VALIDITY_UNDEFINED; break;
96     case 'n': u->validity = GPGME_VALIDITY_NEVER; break;
97     case 'm': u->validity = GPGME_VALIDITY_MARGINAL; break;
98     case 'f': u->validity = GPGME_VALIDITY_FULL; break;
99     case 'u': u->validity = GPGME_VALIDITY_ULTIMATE; break;
100     }
101     }
102     }
103    
104     static void
105     set_subkey_trust_info( struct subkey_s * k, const char * s )
106     {
107     /* look at letters and stop at the first digit */
108     for( ; *s && !isdigit (*s); s++ ) {
109     switch( *s ) {
110     case 'e': k->flags.expired = 1; break;
111     case 'r': k->flags.revoked = 1; break;
112     case 'd': k->flags.disabled = 1; break;
113     case 'i': k->flags.invalid = 1; break;
114     }
115     }
116     }
117    
118     static void
119     set_mainkey_capability( gpgme_key_t key, const char * s )
120     {
121     for( ; *s ; s++ ) {
122     switch( *s ) {
123     case 'a': key->keys.flags.can_auth = 1; break;
124     case 'e': key->keys.flags.can_encrypt = 1; break;
125     case 's': key->keys.flags.can_sign = 1; break;
126     case 'c': key->keys.flags.can_certify = 1; break;
127     case 'E': key->gloflags.can_encrypt = 1; break;
128     case 'S': key->gloflags.can_sign = 1; break;
129     case 'C': key->gloflags.can_certify = 1; break;
130     case 'D': key->gloflags.disabled = 1; break;
131     }
132     }
133     }
134    
135     static void
136     set_subkey_capability (struct subkey_s * k, const char * s)
137     {
138     for (; *s; s++) {
139     switch (*s) {
140     case 'a': k->flags.can_auth = 1; break;
141     case 'e': k->flags.can_encrypt = 1; break;
142     case 's': k->flags.can_sign = 1; break;
143     case 'c': k->flags.can_certify = 1; break;
144     }
145     }
146     }
147    
148     static void
149     set_mainkey_ownertrust( gpgme_key_t key, const char * s )
150     {
151     switch( *s ) {
152     case '-': key->otrust = GPGME_TRUST_UNKNOWN; break;
153     case 'e': key->otrust = GPGME_TRUST_EXPIRED; break;
154     case 'q': key->otrust = GPGME_TRUST_UNDEFINED; break;
155     case 'n': key->otrust = GPGME_TRUST_NEVER; break;
156     case 'm': key->otrust = GPGME_TRUST_MARGINAL; break;
157     case 'f': key->otrust = GPGME_TRUST_FULLY; break;
158     case 'u': key->otrust = GPGME_TRUST_ULTIMATE; break;
159     default: key->otrust = GPGME_TRUST_UNKNOWN; break;
160     }
161     }
162    
163    
164     /* Note: we are allowed to modify line */
165     static void
166 twoaday 22 keylist_colon_handler (gpgme_ctx_t ctx, char *line)
167 twoaday 2 {
168     enum {
169 twoaday 22 RT_NONE,
170     RT_SIG,
171     RT_UID,
172 twoaday 2 RT_SUB,
173     RT_PUB,
174     RT_FPR,
175     RT_SSB,
176     RT_SEC,
177     RT_PKD,
178     } rectype = RT_NONE;
179     gpgme_key_t key = ctx->tmp_key;
180 twoaday 22 struct subkey_s *sk = NULL;
181     struct signature_s *sig = NULL;
182     struct subkey_s *s = NULL;
183     struct user_id_s *u = NULL;
184     struct mpi_s *m = NULL, * mt = NULL;
185     const char *trust_info = NULL;
186     char *p, *pend;
187 twoaday 2 int field = 0;
188     unsigned long val=0;
189     int i;
190    
191 twoaday 22 if (ctx->out_of_core)
192 twoaday 2 return;
193     if( !line ) { /* EOF */
194     if( ctx->tmp_key )
195     finish_key( ctx );
196     return;
197     }
198    
199     for( p = line; p; p = pend ) {
200     field++;
201     pend = strchr( p, ':' );
202     if( pend )
203     *pend++ = 0;
204    
205     if( field == 1 ) {
206     if( !strcmp( p, "sig" ) && key ) {
207     rectype = RT_SIG;
208     sig = _gpgme_key_add_signature( key );
209     if( !sig ) {
210     ctx->out_of_core = 1;
211     break;
212     }
213     }
214     else if( !strcmp( p, "uid" ) && key ) {
215     rectype = RT_UID;
216     key = ctx->tmp_key;
217     sig = _gpgme_key_add_signature( key );
218     if( !sig ) {
219     ctx->out_of_core = 1;
220     break;
221     }
222     }
223     else if( !strcmp( p, "sub" ) && key ) {
224     /* start a new subkey */
225     rectype = RT_SUB;
226     sk = _gpgme_key_add_subkey( key );
227     if( !sk ) {
228     ctx->out_of_core = 1;
229     return;
230     }
231     }
232     else if( !strcmp( p, "ssb" ) && key ) {
233     /* start a new secret subkey */
234     rectype = RT_SSB;
235     sk = _gpgme_key_add_secret_subkey( key );
236     if( !sk ) {
237     ctx->out_of_core = 1;
238     return;
239     }
240     }
241     else if( !strcmp( p, "pub" ) ) {
242     /* start a new keyblock */
243     if( _gpgme_key_new ( &key ) ) {
244     ctx->out_of_core = 1; /* the only kind of error we can get*/
245     return;
246     }
247     rectype = RT_PUB;
248     if ( ctx->tmp_key )
249     finish_key ( ctx );
250     assert ( !ctx->tmp_key );
251     ctx->tmp_key = key;
252     ctx->tmp_i = 0;
253     if (ctx->cb.progress)
254     ctx->cb.progress (ctx->cb.progress_value, "keylist", 0,
255     ctx->cb.progess_tmp,
256     ctx->cb.progress_value_int);
257     ctx->cb.progess_tmp++;
258     }
259     else if( !strcmp ( p, "sec" ) ) {
260     /* start a new keyblock */
261     if ( _gpgme_key_new_secret( &key ) ) {
262     ctx->out_of_core = 1; /* the only kind of error we can get */
263     return;
264     }
265     rectype = RT_SEC;
266     if( ctx->tmp_key )
267     finish_key ( ctx );
268     assert ( !ctx->tmp_key );
269     ctx->tmp_key = key;
270     }
271     else if( !strcmp( p, "fpr" ) && key )
272     rectype = RT_FPR;
273     else if( !strcmp( p, "pkd" ) && key )
274     rectype = RT_PKD;
275     else
276     rectype = RT_NONE;
277     }
278     else if( rectype == RT_PUB || rectype == RT_SEC )
279     {
280     switch( field ) {
281     case 2: /* trust info */
282     trust_info = p;
283     set_mainkey_trust_info( key, trust_info );
284     break;
285     case 3: /* key length */
286 twoaday 22 i = atoi (p);
287 twoaday 2 if( i > 1 ) /* ignore invalid values */
288     key->keys.key_len = i;
289     break;
290     case 4: /* pubkey algo */
291 twoaday 22 i = atoi (p);
292     if (i > 0 && i < 128)
293 twoaday 2 key->keys.key_algo = i;
294     break;
295     case 5: /* long keyid */
296     memset (key->keys.keyid, 0, sizeof key->keys.keyid);
297     strncpy (key->keys.keyid, p, DIM (key->keys.keyid)-1);
298     break;
299     case 6: /* timestamp (1998-02-28) */
300     key->keys.timestamp = parse_timestamp( p );
301     break;
302     case 7: /* valid for n days */
303     key->keys.expires = parse_timestamp( p );
304     break;
305     case 8: /* reserved (LID) */
306     break;
307     case 9: /* ownertrust */
308     set_mainkey_ownertrust( key, p );
309     break;
310     case 10: /* not used due to --fixed-list-mode option */
311     break;
312     case 11: /* signature class */
313     break;
314     case 12: /* capabilities */
315     set_mainkey_capability( key, p );
316     break;
317     case 15:
318     if (p && * p)
319     {
320     key->gloflags.divert_to_card = 1;
321     memset (key->keys.cardno, 0, sizeof key->keys.cardno);
322     strncpy (key->keys.cardno, p, DIM (key->keys.cardno));
323     }
324     pend = NULL; /* we can stop here */
325     break;
326     }
327     }
328 twoaday 22 else if ((rectype == RT_SUB || rectype== RT_SSB) && sk) {
329     switch (field) {
330 twoaday 2 case 2: /* trust info */
331 twoaday 22 set_subkey_trust_info (sk, p);
332 twoaday 2 break;
333 twoaday 22
334 twoaday 2 case 3: /* key length */
335     i = atoi( p );
336     if ( i > 1 ) /* ignore invalid values */
337     sk->key_len = i;
338     break;
339 twoaday 22
340 twoaday 2 case 4: /* pubkey algo */
341 twoaday 22 i = atoi (p);
342     if (i > 0 && i < 128)
343 twoaday 2 sk->key_algo = i;
344     break;
345 twoaday 22
346 twoaday 2 case 5: /* long keyid */
347     memset (sk->keyid, 0, sizeof sk->keyid);
348     strncpy (sk->keyid, p, DIM (sk->keyid)-1);
349     break;
350     case 6: /* timestamp (1998-02-28) */
351     sk->timestamp = parse_timestamp( p );
352     break;
353     case 7: /* valid for n days */
354     sk->expires = parse_timestamp( p );
355     break;
356     case 8: /* reserved (LID) */
357     break;
358     case 9: /* ownertrust */
359     break;
360     case 10:/* user ID n/a for a subkey */
361     break;
362     case 11: /* signature class */
363     break;
364     case 12: /* capability */
365     set_subkey_capability ( sk, p );
366     break;
367     case 15:
368     memset (sk->cardno, 0, sizeof sk->cardno);
369     strncpy (sk->cardno, p, DIM (sk->cardno)-1);
370     pend = NULL; /* we can stop here */
371     break;
372     }
373     }
374     else if (rectype == RT_UID)
375     {
376     switch (field)
377     {
378     case 2: /* trust info */
379     trust_info = p; /* save for later use */
380     break;
381     case 6: /* creation date */
382     if (p)
383     val = parse_timestamp (p);
384     break;
385    
386     case 8: /* hash over name */
387     break;
388    
389     case 10: /* user ID */
390     safe_free (ctx->tmp_id);
391     ctx->tmp_id = strdup (p);
392     if (!ctx->tmp_id) {
393     ctx->out_of_core = 1;
394     break;
395     }
396     if (_gpgme_key_append_name (key, p, &u))
397     ctx->out_of_core = 1;
398     else if (trust_info)
399     set_userid_flags (u, trust_info);
400     if (sig) {
401     safe_free (sig->issuer);
402     sig->issuer = calloc (1, strlen (p) + 1);
403     if (!sig->issuer) {
404     ctx->out_of_core = 1;
405     break;
406     }
407     _gpgme_decode_c_string (p, &sig->issuer, strlen (p)+ 1);
408     }
409     u->created = val;
410     pend = NULL; /* we can stop here */
411     break;
412     }
413     }
414     else if( rectype == RT_FPR ) {
415     int nfpr = ctx->tmp_i;
416     switch( field ) {
417     case 10:
418     for( s = &key->keys; s && nfpr; s = s->next, nfpr-- )
419     ;
420     if( s ) {
421     s->fingerprint = strdup( p );
422     if( !s->fingerprint ) {
423     ctx->out_of_core = 1;
424     break;
425     }
426     }
427     pend = NULL; /* that is all we want */
428     ctx->tmp_i++;
429     break;
430     }
431     }
432     else if( rectype == RT_SIG ) {
433     switch( field ) {
434     case 2: /* signature state */
435     switch( *p ) {
436     case '!': sig->stat = GPGME_SIG_STAT_GOOD; break;
437     case '-': sig->stat = GPGME_SIG_STAT_BAD; break;
438     case '?': sig->stat = GPGME_SIG_STAT_NOKEY; break;
439     case '%': sig->stat = GPGME_SIG_STAT_ERROR; break;
440     default : sig->stat = GPGME_SIG_STAT_NONE; break;
441     }
442     break;
443    
444     case 4: /* pk algorithm */
445     sig->algo = atol (p);
446     break;
447    
448     case 5: /* long keyid */
449     memset (sig->keyid, 0, sizeof sig->keyid);
450     strncpy (sig->keyid, p, DIM (sig->keyid)-1);
451     break;
452    
453     case 6: /* created */
454     sig->created = parse_timestamp( p );
455     break;
456    
457     case 7: /* expires */
458     sig->expires = parse_timestamp( p );
459     break;
460    
461     case 10:
462     if( p ) {
463     sig->issuer = calloc( 1, strlen( p ) + 1 );
464     if( !sig->issuer ) {
465     ctx->out_of_core = 1;
466     break;
467     }
468     _gpgme_decode_c_string( p, &sig->issuer, strlen( p ) + 1 );
469     }
470     break;
471    
472     case 11:
473     sig->sigclass = strtoul( p, NULL, 16 );
474     if (strchr (p, 'l'))
475     sig->is_local = 1;
476     /*if (strchr (p, ' '))
477     sig->is_nonrev = 1;*/
478     if (sig->sigclass < 0x10 || sig->sigclass > 0x13) {
479     /* we only want certificates and no key signatures */
480     pend = NULL;
481     break;
482     }
483     if( ctx->tmp_id ) {
484     sig->user_id = calloc( 1, strlen( ctx->tmp_id ) + 1 );
485     if( !sig->user_id ) {
486     ctx->out_of_core = 1;
487     break;
488     }
489     _gpgme_decode_c_string( ctx->tmp_id, &sig->user_id, strlen( ctx->tmp_id ) +1 );
490     }
491     pend = NULL; /* we can stop here */
492     break;
493     }
494     }
495     else if( rectype == RT_PKD ) {
496     switch( field ) {
497     case 1:
498     m = calloc( 1, sizeof * m );
499     if( !m ) {
500     ctx->out_of_core = 1;
501     return;
502     }
503     for( mt=key->pkey; mt->next; mt=mt->next )
504     ;
505     mt->next = m;
506     break;
507    
508     case 2:
509     if( m )
510     m->bits = atol( p );
511     break;
512    
513     case 3:
514     if( m ) {
515     m->hexval = strdup( p );
516     if( !m->hexval )
517     ctx->out_of_core=1;
518     }
519     break;
520     }
521     }
522     }
523    
524     }
525    
526    
527     /*
528     * We have read an entire key into ctx->tmp_key and should now finish
529     * it. It is assumed that this releases ctx->tmp_key.
530     */
531     static void
532     finish_key( gpgme_ctx_t ctx )
533     {
534     gpgme_key_t key = ctx->tmp_key;
535     struct key_queue_item_s * q, * q2;
536    
537     assert( key );
538     ctx->tmp_key = NULL;
539    
540     q = malloc( sizeof *q );
541     if( !q ) {
542     gpgme_key_release( key );
543     ctx->out_of_core = 1;
544     return;
545     }
546     q->key = key;
547     q->next = NULL;
548     /* fixme: lock queue. Use a tail pointer? */
549     q2 = ctx->key_queue;
550     if( !q2 )
551     ctx->key_queue = q;
552     else {
553     for( ; q2->next; q2 = q2->next )
554     ;
555     q2->next = q;
556     }
557     ctx->key_cond = 1;
558     /* fixme: unlock queue */
559     }
560    
561    
562    
563     /**
564     * gpgme_op_keylist_start:
565     * @c: context
566     * @pattern: a GnuPg user ID or NULL for all
567     * @secret_only: List only keys where the secret part is available
568     *
569     * Note that this function also cancels a pending key listing operaton..
570     *
571     * Return value: 0 on success or an errorcode.
572     **/
573     gpgme_error_t
574 twoaday 22 gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
575 twoaday 2 {
576     gpgme_error_t rc = 0;
577    
578 twoaday 22 if (!ctx)
579     return mk_error (Invalid_Value);
580 twoaday 2 ctx->pending = 1;
581    
582 twoaday 22 _gpgme_release_result (ctx);
583 twoaday 2 ctx->out_of_core = 0;
584     ctx->cb.progess_tmp = 0;
585    
586 twoaday 22 _gpgme_gpg_release (&ctx->gpg);
587     gpgme_key_release (ctx->tmp_key);
588 twoaday 2 ctx->tmp_key = NULL;
589     /* Fixme: release key_queue */
590    
591 twoaday 22 rc = _gpgme_gpg_new (&ctx->gpg);
592     if (rc)
593 twoaday 2 goto leave;
594    
595 twoaday 22 _gpgme_gpg_set_status_handler (ctx->gpg, keylist_status_handler, ctx);
596     rc = _gpgme_gpg_set_colon_line_handler (ctx->gpg, keylist_colon_handler, ctx);
597     if (rc)
598 twoaday 2 goto leave;
599    
600     /* build the commandline */
601     if (ctx->use_logging)
602     _gpgme_gpg_set_logging_handler (ctx->gpg, ctx);
603     _gpgme_gpg_set_list_options (ctx->gpg, ctx->list_opts);
604 twoaday 22 _gpgme_gpg_add_arg (ctx->gpg, "--with-colons");
605     _gpgme_gpg_add_arg (ctx->gpg, "--fixed-list-mode");
606     _gpgme_gpg_add_arg (ctx->gpg, "--with-fingerprint");
607     _gpgme_gpg_add_arg (ctx->gpg, "--with-fingerprint"); /* for the subkey */
608     if (ctx->keylist_mode & 1)
609     _gpgme_gpg_add_arg (ctx->gpg, "--no-expensive-trust-checks");
610     if (ctx->keylist_mode & 2)
611     _gpgme_gpg_add_arg (ctx->gpg, "--with-key-data");
612     if (ctx->keylist_mode & 4)
613     _gpgme_gpg_add_arg (ctx->gpg, "--fast-list-mode");
614     if (secret_only)
615     _gpgme_gpg_add_arg (ctx->gpg, "--list-secret-keys");
616     else {
617     if (ctx->keylist_mode & 8)
618     _gpgme_gpg_add_arg (ctx->gpg, "--check-sigs");
619     else
620     _gpgme_gpg_add_arg (ctx->gpg, "--list-keys");
621     }
622 twoaday 2
623     /* Tell the gpg object about the data */
624     _gpgme_gpg_add_arg ( ctx->gpg, "--" );
625     if( pattern && *pattern )
626     _gpgme_gpg_add_arg ( ctx->gpg, pattern );
627    
628     /* and kick off the process */
629     rc = _gpgme_gpg_spawn ( ctx->gpg, ctx );
630    
631     leave:
632     if( rc ) {
633     ctx->pending = 0;
634     _gpgme_gpg_release ( &ctx->gpg );
635     }
636     return rc;
637     }
638    
639    
640     gpgme_error_t
641     gpgme_op_keylist_next( gpgme_ctx_t ctx, gpgme_key_t * r_key )
642     {
643     struct key_queue_item_s * q;
644    
645     if( !r_key )
646     return mk_error( Invalid_Value );
647     *r_key = NULL;
648     if( !ctx )
649     return mk_error( Invalid_Value );
650     if( !ctx->pending )
651     return mk_error( No_Request );
652     if( ctx->out_of_core )
653     return mk_error( Out_Of_Core );
654    
655     if( !ctx->key_queue ) {
656     _gpgme_wait_on_condition( ctx, 1, &ctx->key_cond );
657     if ( ctx->out_of_core )
658     return mk_error( Out_Of_Core );
659     if( !ctx->key_cond )
660     return mk_error( EOF );
661     ctx->key_cond = 0;
662     assert ( ctx->key_queue );
663     }
664     q = ctx->key_queue;
665     ctx->key_queue = q->next;
666    
667     *r_key = q->key;
668 twoaday 17 safe_free (q);
669 twoaday 2 return 0;
670     }
671 twoaday 17
672    
673     gpgme_error_t
674 twoaday 21 gpgme_op_keylist_getkey (int is_sec, const char *pattern, gpgme_key_t *r_key)
675 twoaday 17 {
676     gpgme_ctx_t listctx;
677     gpgme_error_t err;
678    
679     err = gpgme_new (&listctx);
680     if (err)
681     return err;
682 twoaday 21 err = gpgme_op_keylist_start (listctx, pattern, is_sec);
683 twoaday 17 if (!err)
684     err = gpgme_op_keylist_next (listctx, r_key);
685     gpgme_release (listctx);
686     return err;
687     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26