2003-02-04 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / trustlist.c
1 /* trustlist.c - Trust item listing.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003 g10 Code GmbH
4
5    This file is part of GPGME.
6  
7    GPGME is free software; you can redistribute it and/or modify it
8    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, but
13    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 GPGME; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 #include <assert.h>
29
30 #include "util.h"
31 #include "context.h"
32 #include "ops.h"
33
34 struct gpgme_trust_item_s
35 {
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 = calloc (1, sizeof *item);
51   return item;
52 }
53
54
55 static GpgmeError
56 trustlist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
57 {
58   switch (code)
59     {
60     case GPGME_STATUS_EOF:
61       break;
62
63     default:
64       break;
65     }
66   return 0;
67 }
68
69
70 /* This handler is used to parse the output of --list-trust-path:
71    Format:
72    level:keyid:type:recno:ot:val:mc:cc:name:
73    With TYPE = U for a user ID
74                K for a key
75    The RECNO is either the one of the dir record or the one of the uid
76    record.  OT is the the usual trust letter and only availabel on K
77    lines.  VAL is the calcualted validity MC is the marginal trust
78    counter and only available on U lines CC is the same for the
79    complete count NAME ist the username and only printed on U
80    lines.  */
81 static GpgmeError
82 trustlist_colon_handler (GpgmeCtx ctx, char *line)
83 {
84   char *p, *pend;
85   int field = 0;
86   GpgmeTrustItem item = NULL;
87
88   if (!line)
89     return 0; /* EOF */
90
91   for (p = line; p; p = pend)
92     {
93       field++;
94       pend = strchr (p, ':');
95       if (pend) 
96         *pend++ = 0;
97
98       switch (field)
99         {
100         case 1: /* level */
101           item = trust_item_new ();
102           if (!item)
103             return GPGME_Out_Of_Core;
104           item->level = atoi (p);
105           break;
106         case 2: /* long keyid */
107           if (strlen (p) == DIM(item->keyid) - 1)
108             strcpy (item->keyid, p);
109           break;
110         case 3: /* type */
111           item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0;
112           break;
113         case 5: /* owner trust */
114           item->ot[0] = *p;
115           item->ot[1] = 0;
116           break;
117         case 6: /* validity */
118           item->val[0] = *p;
119           item->val[1] = 0;
120           break;
121         case 9: /* user ID */
122           item->name = strdup (p);
123           if (!item->name) {
124             gpgme_trust_item_release (item);
125             return GPGME_Out_Of_Core;
126           }
127           break;
128         }
129     }
130
131   if (item)
132     _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_TRUSTITEM, item);
133   return 0;
134 }
135
136
137 void
138 _gpgme_op_trustlist_event_cb (void *data, GpgmeEventIO type, void *type_data)
139 {
140   GpgmeCtx ctx = (GpgmeCtx) data;
141   GpgmeTrustItem item = (GpgmeTrustItem) type_data;
142   struct trust_queue_item_s *q, *q2;
143
144   assert (type == GPGME_EVENT_NEXT_TRUSTITEM);
145
146   q = malloc (sizeof *q);
147   if (!q)
148     {
149       gpgme_trust_item_release (item);
150       /* FIXME */
151       /* ctx->error = GPGME_Out_Of_Core; */
152       return;
153     }
154   q->item = item;
155   q->next = NULL;
156   /* FIXME: lock queue, keep a tail pointer */
157   q2 = ctx->trust_queue;
158   if (!q2)
159     ctx->trust_queue = q;
160   else
161     {
162       while (q2->next)
163         q2 = q2->next;
164       q2->next = q;
165     }
166   /* FIXME: unlock queue */
167   ctx->key_cond = 1;
168 }
169
170
171 GpgmeError
172 gpgme_op_trustlist_start (GpgmeCtx ctx, const char *pattern, int max_level)
173 {
174   GpgmeError err = 0;
175
176   if (!pattern || !*pattern)
177     return GPGME_Invalid_Value;
178
179   err = _gpgme_op_reset (ctx, 2);
180   if (err)
181     goto leave;
182
183   _gpgme_engine_set_status_handler (ctx->engine,
184                                     trustlist_status_handler, ctx);
185   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
186                                               trustlist_colon_handler, ctx);
187   if (err)
188     goto leave;
189
190   err =_gpgme_engine_op_trustlist (ctx->engine, pattern);
191
192  leave:
193   if (err)
194     {
195       ctx->pending = 0; 
196       _gpgme_engine_release (ctx->engine);
197       ctx->engine = NULL;
198     }
199   return err;
200 }
201
202
203 GpgmeError
204 gpgme_op_trustlist_next (GpgmeCtx ctx, GpgmeTrustItem *r_item)
205 {
206   struct trust_queue_item_s *q;
207
208   if (!r_item)
209     return GPGME_Invalid_Value;
210   *r_item = NULL;
211   if (!ctx)
212     return GPGME_Invalid_Value;
213   if (!ctx->pending)
214     return GPGME_No_Request;
215
216   if (!ctx->trust_queue)
217     {
218       GpgmeError err = _gpgme_wait_on_condition (ctx, &ctx->key_cond);
219       if (err)
220         {
221           ctx->pending = 0;
222           return err;
223         }
224       if (!ctx->pending)
225         {
226           /* The operation finished.  Because not all keys might have
227              been returned to the caller yet, we just reset the
228              pending flag to 1.  This will cause us to call
229              _gpgme_wait_on_condition without any active file
230              descriptors, but that is a no-op, so it is safe.  */
231           ctx->pending = 1;
232         }
233       if (!ctx->key_cond)
234         {
235           ctx->pending = 0;
236           return GPGME_EOF;
237         }
238       ctx->key_cond = 0; 
239       assert (ctx->trust_queue);
240     }
241   q = ctx->trust_queue;
242   ctx->trust_queue = q->next;
243
244   *r_item = q->item;
245   free (q);
246   return 0;
247 }
248
249
250 /**
251  * gpgme_op_trustlist_end:
252  * @c: Context
253  *
254  * Ends the trustlist operation and allows to use the context for some
255  * other operation next.
256  **/
257 GpgmeError
258 gpgme_op_trustlist_end (GpgmeCtx ctx)
259 {
260   if (!ctx)
261     return GPGME_Invalid_Value;
262   if (!ctx->pending)
263     return GPGME_No_Request;
264
265   ctx->pending = 0;
266   return 0;
267 }
268
269
270 void
271 gpgme_trust_item_release (GpgmeTrustItem item)
272 {
273   if (!item)
274     return;
275   if (item->name)
276     free (item->name);
277   free (item);
278 }
279
280
281 const char *
282 gpgme_trust_item_get_string_attr (GpgmeTrustItem item, GpgmeAttr what,
283                                   const void *reserved, int idx)
284 {
285   const char *val = NULL;
286
287   if (!item)
288     return NULL;
289   if (reserved)
290     return NULL;
291   if (idx)
292     return NULL;
293
294   switch (what)
295     {
296     case GPGME_ATTR_KEYID:
297       val = item->keyid;
298       break;
299     case GPGME_ATTR_OTRUST:  
300       val = item->ot;
301       break;
302     case GPGME_ATTR_VALIDITY:
303       val = item->val;
304       break;
305     case GPGME_ATTR_USERID:  
306       val = item->name;
307       break;
308     default:
309       break;
310     }
311   return val;
312 }
313
314
315 int
316 gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what,
317                                const void *reserved, int idx)
318 {
319   int val = 0;
320   
321   if (!item)
322     return 0;
323   if (reserved)
324     return 0;
325   if (idx)
326     return 0;
327
328   switch (what)
329     {
330     case GPGME_ATTR_LEVEL:    
331       val = item->level;
332       break;
333     case GPGME_ATTR_TYPE:    
334       val = item->type;
335       break;
336     default:
337       break;
338     }
339   return val;
340 }