doc/
[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       _gpgme_engine_release (ctx->engine);
196       ctx->engine = NULL;
197     }
198   return err;
199 }
200
201
202 GpgmeError
203 gpgme_op_trustlist_next (GpgmeCtx ctx, GpgmeTrustItem *r_item)
204 {
205   struct trust_queue_item_s *q;
206
207   if (!r_item)
208     return GPGME_Invalid_Value;
209   *r_item = NULL;
210   if (!ctx)
211     return GPGME_Invalid_Value;
212
213   if (!ctx->trust_queue)
214     {
215       GpgmeError err = _gpgme_wait_on_condition (ctx, &ctx->key_cond);
216       if (err)
217         return err;
218       if (!ctx->key_cond)
219         return GPGME_EOF;
220       ctx->key_cond = 0; 
221       assert (ctx->trust_queue);
222     }
223   q = ctx->trust_queue;
224   ctx->trust_queue = q->next;
225
226   *r_item = q->item;
227   free (q);
228   return 0;
229 }
230
231
232 /**
233  * gpgme_op_trustlist_end:
234  * @c: Context
235  *
236  * Ends the trustlist operation and allows to use the context for some
237  * other operation next.
238  **/
239 GpgmeError
240 gpgme_op_trustlist_end (GpgmeCtx ctx)
241 {
242   if (!ctx)
243     return GPGME_Invalid_Value;
244
245   return 0;
246 }
247
248
249 void
250 gpgme_trust_item_release (GpgmeTrustItem item)
251 {
252   if (!item)
253     return;
254   if (item->name)
255     free (item->name);
256   free (item);
257 }
258
259
260 const char *
261 gpgme_trust_item_get_string_attr (GpgmeTrustItem item, GpgmeAttr what,
262                                   const void *reserved, int idx)
263 {
264   const char *val = NULL;
265
266   if (!item)
267     return NULL;
268   if (reserved)
269     return NULL;
270   if (idx)
271     return NULL;
272
273   switch (what)
274     {
275     case GPGME_ATTR_KEYID:
276       val = item->keyid;
277       break;
278     case GPGME_ATTR_OTRUST:  
279       val = item->ot;
280       break;
281     case GPGME_ATTR_VALIDITY:
282       val = item->val;
283       break;
284     case GPGME_ATTR_USERID:  
285       val = item->name;
286       break;
287     default:
288       break;
289     }
290   return val;
291 }
292
293
294 int
295 gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what,
296                                const void *reserved, int idx)
297 {
298   int val = 0;
299   
300   if (!item)
301     return 0;
302   if (reserved)
303     return 0;
304   if (idx)
305     return 0;
306
307   switch (what)
308     {
309     case GPGME_ATTR_LEVEL:    
310       val = item->level;
311       break;
312     case GPGME_ATTR_TYPE:    
313       val = item->type;
314       break;
315     default:
316       break;
317     }
318   return val;
319 }