11acbf544cdf0ce9849c54fb2b3e70accf9aad1b
[gpgme.git] / gpgme / trustlist.c
1 /* trustlist.c -  key listing
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *      Copyright (C) 2001, 2002 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 struct gpgme_trust_item_s
34 {
35   int level;
36   char keyid[16+1];
37   int type;   
38   char ot[2];
39   char val[2];
40   char *name;
41 };
42
43
44 static GpgmeTrustItem
45 trust_item_new (void)
46 {
47   GpgmeTrustItem item;
48
49   item = xtrycalloc (1, sizeof *item);
50   return item;
51 }
52
53
54 static void
55 trustlist_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
56 {
57   if (ctx->out_of_core)
58     return;
59
60   switch (code)
61     {
62     case STATUS_EOF:
63       break;
64
65     default:
66       break;
67     }
68 }
69
70
71 /* 
72  * This handler is used to parse the output of --list-trust-path:
73  * Format:
74  *   level:keyid:type:recno:ot:val:mc:cc:name:
75  * With TYPE = U for a user ID
76  *             K for a key
77  * The RECNO is either the one of the dir record or the one of the uid record.
78  * OT is the the usual trust letter and only availabel on K lines.
79  * VAL is the calcualted validity
80  * MC is the marginal trust counter and only available on U lines
81  * CC is the same for the complete count
82  * NAME ist the username and only printed on U lines
83  */
84 static void
85 trustlist_colon_handler (GpgmeCtx ctx, char *line)
86 {
87   char *p, *pend;
88   int field = 0;
89   GpgmeTrustItem item = NULL;
90   struct trust_queue_item_s *q, *q2;
91
92   if (ctx->out_of_core)
93     return;
94   if (!line)
95     return; /* EOF */
96
97   for (p = line; p; p = pend)
98     {
99       field++;
100       pend = strchr (p, ':');
101       if (pend) 
102         *pend++ = 0;
103
104       switch (field)
105         {
106         case 1: /* level */
107           q = xtrymalloc (sizeof *q);
108           if (!q)
109             {
110               ctx->out_of_core = 1;
111               return;
112             }
113           q->next = NULL;
114           q->item = item = trust_item_new ();
115           if (!q->item)
116             {
117               xfree (q);
118               ctx->out_of_core = 1;
119               return;
120             }
121           /* fixme: lock queue, keep a tail pointer */
122           q2 = ctx->trust_queue;
123           if (!q2)
124             ctx->trust_queue = q;
125           else
126             {
127               while (q2->next)
128                 q2 = q2->next;
129               q2->next = q;
130             }
131           /* fixme: unlock queue */
132           item->level = atoi (p);
133           break;
134         case 2: /* long keyid */
135           if (strlen (p) == DIM(item->keyid) - 1)
136             strcpy (item->keyid, p);
137           break;
138         case 3: /* type */
139           item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0;
140           break;
141         case 5: /* owner trust */
142           item->ot[0] = *p;
143           item->ot[1] = 0;
144           break;
145         case 6: /* validity */
146           item->val[0] = *p;
147           item->val[1] = 0;
148           break;
149         case 9: /* user ID */
150           item->name = xtrystrdup (p);
151           if (!item->name)
152             ctx->out_of_core = 1;
153           break;
154         }
155     }
156
157   if (field)
158     ctx->key_cond = 1;
159 }
160
161
162 GpgmeError
163 gpgme_op_trustlist_start (GpgmeCtx ctx, const char *pattern, int max_level)
164 {
165   GpgmeError err = 0;
166
167   fail_on_pending_request (ctx);
168   if (!pattern || !*pattern)
169     return mk_error (Invalid_Value);
170
171   ctx->pending = 1;
172
173   _gpgme_release_result (ctx);
174   ctx->out_of_core = 0;
175
176   if (ctx->engine)
177     {
178       _gpgme_engine_release (ctx->engine); 
179       ctx->engine = NULL;
180     }
181
182   err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
183                            : GPGME_PROTOCOL_OpenPGP, &ctx->engine);
184   if (err)
185     goto leave;
186
187   _gpgme_engine_set_status_handler (ctx->engine, trustlist_status_handler, ctx);
188   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
189                                               trustlist_colon_handler, ctx);
190   if (err)
191     goto leave;
192
193   err =_gpgme_engine_op_trustlist (ctx->engine, pattern);
194
195   if (!err)     /* And kick off the process.  */
196     err = _gpgme_engine_start (ctx->engine, ctx);
197
198  leave:
199   if (err)
200     {
201       ctx->pending = 0; 
202       _gpgme_engine_release (ctx->engine);
203       ctx->engine = NULL;
204     }
205   return err;
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     {
226       _gpgme_wait_on_condition (c, 1, &c->key_cond);
227       if (c->out_of_core)
228         return mk_error (Out_Of_Core);
229       if (!c->key_cond)
230         return mk_error (EOF);
231       c->key_cond = 0; 
232       assert (c->trust_queue);
233     }
234   q = c->trust_queue;
235   c->trust_queue = q->next;
236
237   *r_item = q->item;
238   xfree (q);
239   return 0;
240 }
241
242
243 /**
244  * gpgme_op_trustlist_end:
245  * @c: Context
246  *
247  * Ends the trustlist operation and allows to use the context for some
248  * other operation next.
249  **/
250 GpgmeError
251 gpgme_op_trustlist_end (GpgmeCtx ctx)
252 {
253   if (!ctx)
254     return mk_error (Invalid_Value);
255   if (!ctx->pending)
256     return mk_error (No_Request);
257   if (ctx->out_of_core)
258     return mk_error (Out_Of_Core);
259
260   ctx->pending = 0;
261   return 0;
262 }
263
264
265 void
266 gpgme_trust_item_release (GpgmeTrustItem item)
267 {
268   if (!item)
269     return;
270   xfree (item->name);
271   xfree (item);
272 }
273
274
275 const char *
276 gpgme_trust_item_get_string_attr (GpgmeTrustItem item, GpgmeAttr what,
277                                   const void *reserved, int idx)
278 {
279   const char *val = NULL;
280
281   if (!item)
282     return NULL;
283   if (reserved)
284     return NULL;
285   if (idx)
286     return NULL;
287
288   switch (what)
289     {
290     case GPGME_ATTR_KEYID:
291       val = item->keyid;
292       break;
293     case GPGME_ATTR_OTRUST:  
294       val = item->ot;
295       break;
296     case GPGME_ATTR_VALIDITY:
297       val = item->val;
298       break;
299     case GPGME_ATTR_USERID:  
300       val = item->name;
301       break;
302     default:
303       break;
304     }
305   return val;
306 }
307
308
309 int
310 gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what,
311                                const void *reserved, int idx)
312 {
313   int val = 0;
314   
315   if (!item)
316     return 0;
317   if (reserved)
318     return 0;
319   if (idx)
320     return 0;
321
322   switch (what)
323     {
324     case GPGME_ATTR_LEVEL:    
325       val = item->level;
326       break;
327     case GPGME_ATTR_TYPE:    
328       val = item->type;
329       break;
330     default:
331       break;
332     }
333   return val;
334 }
335