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