2fd4b9c7119a76a14c0739d905ceb75859052380
[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->error)
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
91   if (ctx->error)
92     return;
93   if (!line)
94     return; /* EOF */
95
96   for (p = line; p; p = pend)
97     {
98       field++;
99       pend = strchr (p, ':');
100       if (pend) 
101         *pend++ = 0;
102
103       switch (field)
104         {
105         case 1: /* level */
106           item = trust_item_new ();
107           if (!item)
108             {
109               ctx->error = mk_error (Out_Of_Core);
110               return;
111             }
112           item->level = atoi (p);
113           break;
114         case 2: /* long keyid */
115           if (strlen (p) == DIM(item->keyid) - 1)
116             strcpy (item->keyid, p);
117           break;
118         case 3: /* type */
119           item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0;
120           break;
121         case 5: /* owner trust */
122           item->ot[0] = *p;
123           item->ot[1] = 0;
124           break;
125         case 6: /* validity */
126           item->val[0] = *p;
127           item->val[1] = 0;
128           break;
129         case 9: /* user ID */
130           item->name = xtrystrdup (p);
131           if (!item->name)
132             ctx->error = mk_error (Out_Of_Core);
133           break;
134         }
135     }
136
137   if (item)
138     _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_TRUSTITEM, item);
139 }
140
141
142 void
143 _gpgme_op_trustlist_event_cb (void *data, GpgmeEventIO type, void *type_data)
144 {
145   GpgmeCtx ctx = (GpgmeCtx) data;
146   GpgmeTrustItem item = (GpgmeTrustItem) type_data;
147   struct trust_queue_item_s *q, *q2;
148
149   assert (type == GPGME_EVENT_NEXT_KEY);
150
151   q = xtrymalloc (sizeof *q);
152   if (!q)
153     {
154       gpgme_trust_item_release (item);
155       ctx->error = mk_error (Out_Of_Core);
156       return;
157     }
158   q->item = item;
159   q->next = NULL;
160   /* FIXME: lock queue, keep a tail pointer */
161   q2 = ctx->trust_queue;
162   if (!q2)
163     ctx->trust_queue = q;
164   else
165     {
166       while (q2->next)
167         q2 = q2->next;
168       q2->next = q;
169     }
170   /* FIXME: unlock queue */
171   ctx->key_cond = 1;
172 }
173
174
175 GpgmeError
176 gpgme_op_trustlist_start (GpgmeCtx ctx, const char *pattern, int max_level)
177 {
178   GpgmeError err = 0;
179
180   if (!pattern || !*pattern)
181     return mk_error (Invalid_Value);
182
183   err = _gpgme_op_reset (ctx, 2);
184   if (err)
185     goto leave;
186
187   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
188                                               trustlist_colon_handler, ctx);
189   if (err)
190     goto leave;
191
192   err =_gpgme_engine_op_trustlist (ctx->engine, pattern);
193
194   if (!err)     /* And kick off the process.  */
195     err = _gpgme_engine_start (ctx->engine, ctx);
196
197  leave:
198   if (err)
199     {
200       ctx->pending = 0; 
201       _gpgme_engine_release (ctx->engine);
202       ctx->engine = NULL;
203     }
204   return err;
205 }
206
207
208 GpgmeError
209 gpgme_op_trustlist_next (GpgmeCtx ctx, GpgmeTrustItem *r_item)
210 {
211   struct trust_queue_item_s *q;
212
213   if (!r_item)
214     return mk_error (Invalid_Value);
215   *r_item = NULL;
216   if (!ctx)
217     return mk_error (Invalid_Value);
218   if (!ctx->pending)
219     return mk_error (No_Request);
220   if (ctx->error)
221     return ctx->error;
222
223   if (!ctx->trust_queue)
224     {
225       GpgmeError err = _gpgme_wait_on_condition (ctx, &ctx->key_cond);
226       if (err)
227         {
228           ctx->pending = 0;
229           return err;
230         }
231       if (!ctx->pending)
232         {
233           /* The operation finished.  Because not all keys might have
234              been returned to the caller yet, we just reset the
235              pending flag to 1.  This will cause us to call
236              _gpgme_wait_on_condition without any active file
237              descriptors, but that is a no-op, so it is safe.  */
238           ctx->pending = 1;
239         }
240       if (!ctx->key_cond)
241         {
242           ctx->pending = 0;
243           return mk_error (EOF);
244         }
245       ctx->key_cond = 0; 
246       assert (ctx->trust_queue);
247     }
248   q = ctx->trust_queue;
249   ctx->trust_queue = q->next;
250
251   *r_item = q->item;
252   xfree (q);
253   return 0;
254 }
255
256
257 /**
258  * gpgme_op_trustlist_end:
259  * @c: Context
260  *
261  * Ends the trustlist operation and allows to use the context for some
262  * other operation next.
263  **/
264 GpgmeError
265 gpgme_op_trustlist_end (GpgmeCtx ctx)
266 {
267   if (!ctx)
268     return mk_error (Invalid_Value);
269   if (!ctx->pending)
270     return mk_error (No_Request);
271   if (ctx->error)
272     return ctx->error;
273
274   ctx->pending = 0;
275   return 0;
276 }
277
278
279 void
280 gpgme_trust_item_release (GpgmeTrustItem item)
281 {
282   if (!item)
283     return;
284   xfree (item->name);
285   xfree (item);
286 }
287
288
289 const char *
290 gpgme_trust_item_get_string_attr (GpgmeTrustItem item, GpgmeAttr what,
291                                   const void *reserved, int idx)
292 {
293   const char *val = NULL;
294
295   if (!item)
296     return NULL;
297   if (reserved)
298     return NULL;
299   if (idx)
300     return NULL;
301
302   switch (what)
303     {
304     case GPGME_ATTR_KEYID:
305       val = item->keyid;
306       break;
307     case GPGME_ATTR_OTRUST:  
308       val = item->ot;
309       break;
310     case GPGME_ATTR_VALIDITY:
311       val = item->val;
312       break;
313     case GPGME_ATTR_USERID:  
314       val = item->name;
315       break;
316     default:
317       break;
318     }
319   return val;
320 }
321
322
323 int
324 gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what,
325                                const void *reserved, int idx)
326 {
327   int val = 0;
328   
329   if (!item)
330     return 0;
331   if (reserved)
332     return 0;
333   if (idx)
334     return 0;
335
336   switch (what)
337     {
338     case GPGME_ATTR_LEVEL:    
339       val = item->level;
340       break;
341     case GPGME_ATTR_TYPE:    
342       val = item->type;
343       break;
344     default:
345       break;
346     }
347   return val;
348 }