Release 0.2.1
[gpgme.git] / gpgme / trustlist.c
1 /* trustlist.c -  key listing
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *      Copyright (C) 2001 g10 Code GmbH
4  *
5  * This file is part of GPGME.
6  *
7  * GPGME 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  * GPGME 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 <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <assert.h>
28
29 #include "util.h"
30 #include "context.h"
31 #include "ops.h"
32
33 #define my_isdigit(a) ( (a) >='0' && (a) <= '9' )
34
35 struct gpgme_trust_item_s {
36     int level;
37     char keyid[16+1];
38     int type;   
39     char ot[2];
40     char val[2];
41     char *name;
42 };
43
44
45 static GpgmeTrustItem
46 trust_item_new (void)
47 {
48     GpgmeTrustItem item;
49
50     item = xtrycalloc (1, sizeof *item);
51     return item;
52 }
53
54
55
56 static void
57 trustlist_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
58 {
59     if ( ctx->out_of_core )
60         return;
61
62     switch (code) {
63       case STATUS_EOF:
64         break;
65
66       default:
67         break;
68     }
69 }
70
71
72
73 /* 
74  * This handler is used to parse the output of --list-trust-path:
75  * Format:
76  *   level:keyid:type:recno:ot:val:mc:cc:name:
77  * With TYPE = U for a user ID
78  *             K for a key
79  * The RECNO is either the one of the dir record or the one of the uid record.
80  * OT is the the usual trust letter and only availabel on K lines.
81  * VAL is the calcualted validity
82  * MC is the marginal trust counter and only available on U lines
83  * CC is the same for the complete count
84  * NAME ist the username and only printed on U lines
85  */
86 static void
87 trustlist_colon_handler ( GpgmeCtx ctx, char *line )
88 {
89     char *p, *pend;
90     int field = 0;
91     GpgmeTrustItem item = NULL;
92     struct trust_queue_item_s *q, *q2;
93
94     if ( ctx->out_of_core )
95         return;
96     if (!line)
97         return; /* EOF */
98
99     for (p = line; p; p = pend) {
100         field++;
101         pend = strchr (p, ':');
102         if (pend) 
103             *pend++ = 0;
104
105         switch (field) {
106           case 1: /* level */
107             q = xtrymalloc ( sizeof *q );
108             if ( !q ) {
109                 ctx->out_of_core = 1;
110                 return;
111             }
112             q->next = NULL;
113             q->item = item = trust_item_new ();
114             if (!q->item) {
115                 xfree (q);
116                 ctx->out_of_core = 1;
117                 return;
118             }
119             /* fixme: lock queue, keep a tail pointer */
120             if ( !(q2 = ctx->trust_queue) )
121                 ctx->trust_queue = q;
122             else {
123                 for ( ; q2->next; q2 = q2->next )
124                     ;
125                 q2->next = q;
126             }
127             /* fixme: unlock queue */
128             item->level = atoi (p);
129             break;
130           case 2: /* long keyid */
131             if ( strlen (p) == DIM(item->keyid)-1 )
132                 strcpy (item->keyid, p);
133             break;
134           case 3: /* type */
135             item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0;
136             break;
137           case 5: /* owner trust */
138             item->ot[0] = *p;
139             item->ot[1] = 0;
140             break;
141           case 6: /* validity */
142             item->val[0] = *p;
143             item->val[1] = 0;
144             break;
145           case 9: /* user ID */
146             item->name = xtrystrdup (p);
147             if (!item->name)
148                 ctx->out_of_core = 1;
149             break;
150         }
151     }
152
153     if (field)
154         ctx->key_cond = 1;
155 }
156
157
158
159 GpgmeError
160 gpgme_op_trustlist_start ( GpgmeCtx c, const char *pattern, int max_level )
161 {
162     GpgmeError rc = 0;
163
164     fail_on_pending_request( c );
165     if ( !pattern || !*pattern ) {
166         return mk_error (Invalid_Value);
167     }
168
169     c->pending = 1;
170
171     _gpgme_release_result (c);
172     c->out_of_core = 0;
173
174     if ( c->gpg ) {
175         _gpgme_gpg_release ( c->gpg ); 
176         c->gpg = NULL;
177     }
178     
179     rc = _gpgme_gpg_new ( &c->gpg );
180     if (rc)
181         goto leave;
182
183     _gpgme_gpg_set_status_handler ( c->gpg, trustlist_status_handler, c );
184     rc = _gpgme_gpg_set_colon_line_handler ( c->gpg,
185                                              trustlist_colon_handler, c );
186     if (rc)
187         goto leave;
188
189     /* build the commandline */
190     _gpgme_gpg_add_arg ( c->gpg, "--with-colons" );
191     _gpgme_gpg_add_arg ( c->gpg, "--list-trust-path" );
192     
193     /* Tell the gpg object about the data */
194     _gpgme_gpg_add_arg ( c->gpg, "--" );
195     _gpgme_gpg_add_arg ( c->gpg, pattern );
196
197     /* and kick off the process */
198     rc = _gpgme_gpg_spawn ( c->gpg, c );
199
200  leave:
201     if (rc) {
202         c->pending = 0; 
203         _gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
204     }
205     return rc;
206 }
207
208
209 GpgmeError
210 gpgme_op_trustlist_next ( GpgmeCtx c, GpgmeTrustItem *r_item )
211 {
212     struct trust_queue_item_s *q;
213
214     if (!r_item)
215         return mk_error (Invalid_Value);
216     *r_item = NULL;
217     if (!c)
218         return mk_error (Invalid_Value);
219     if ( !c->pending )
220         return mk_error (No_Request);
221     if ( c->out_of_core )
222         return mk_error (Out_Of_Core);
223
224     if ( !c->trust_queue ) {
225         _gpgme_wait_on_condition (c, 1, &c->key_cond );
226         if ( c->out_of_core )
227             return mk_error (Out_Of_Core);
228         if ( !c->key_cond )
229             return mk_error (EOF);
230         c->key_cond = 0; 
231         assert ( c->trust_queue );
232     }
233     q = c->trust_queue;
234     c->trust_queue = q->next;
235
236     *r_item = q->item;
237     xfree (q);
238     return 0;
239 }
240
241
242 void
243 gpgme_trust_item_release ( GpgmeTrustItem item )
244 {
245     if (!item)
246         return;
247     xfree (item->name);
248     xfree (item);
249 }
250
251
252 const char *
253 gpgme_trust_item_get_string_attr ( GpgmeTrustItem item, GpgmeAttr what,
254                                    const void *reserved, int idx )
255 {
256     const char *val = NULL;
257
258     if (!item)
259         return NULL;
260     if (reserved)
261         return NULL;
262     if (idx)
263         return NULL;
264
265     switch (what) {
266       case GPGME_ATTR_KEYID:
267         val = item->keyid;
268         break;
269       case GPGME_ATTR_OTRUST:  
270         val = item->ot;
271         break;
272       case GPGME_ATTR_VALIDITY:
273         val = item->val;
274         break;
275       case GPGME_ATTR_USERID:  
276         val = item->name;
277         break;
278       default:
279         break;
280     }
281     return val;
282 }
283
284
285 int
286 gpgme_trust_item_get_int_attr ( GpgmeTrustItem item, GpgmeAttr what,
287                                 const void *reserved, int idx )
288 {
289     int val = 0;
290
291     if (!item)
292         return 0;
293     if (reserved)
294         return 0;
295     if (idx)
296         return 0;
297
298     switch (what) {
299       case GPGME_ATTR_LEVEL:    
300         val = item->level;
301         break;
302       case GPGME_ATTR_TYPE:    
303         val = item->type;
304         break;
305       default:
306         break;
307     }
308     return val;
309 }
310