2002-02-02 Marcus Brinkmann <marcus@g10code.de>
[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   struct trust_queue_item_s *q, *q2;
91
92   if (ctx->error)
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->error = mk_error (Out_Of_Core);
111               return;
112             }
113           q->next = NULL;
114           q->item = item = trust_item_new ();
115           if (!q->item)
116             {
117               xfree (q);
118               ctx->error = mk_error (Out_Of_Core);
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->error = mk_error (Out_Of_Core);
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   if (ctx->engine)
174     {
175       _gpgme_engine_release (ctx->engine); 
176       ctx->engine = NULL;
177     }
178
179   _gpgme_release_result (ctx);
180
181   err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
182                            : GPGME_PROTOCOL_OpenPGP, &ctx->engine);
183   if (err)
184     goto leave;
185
186   _gpgme_engine_set_status_handler (ctx->engine, trustlist_status_handler, ctx);
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       _gpgme_wait_on_condition (ctx, 1, &ctx->key_cond);
226       if (ctx->error)
227         return ctx->error;
228       if (!ctx->key_cond)
229         return mk_error (EOF);
230       ctx->key_cond = 0; 
231       assert (ctx->trust_queue);
232     }
233   q = ctx->trust_queue;
234   ctx->trust_queue = q->next;
235
236   *r_item = q->item;
237   xfree (q);
238   return 0;
239 }
240
241
242 /**
243  * gpgme_op_trustlist_end:
244  * @c: Context
245  *
246  * Ends the trustlist operation and allows to use the context for some
247  * other operation next.
248  **/
249 GpgmeError
250 gpgme_op_trustlist_end (GpgmeCtx ctx)
251 {
252   if (!ctx)
253     return mk_error (Invalid_Value);
254   if (!ctx->pending)
255     return mk_error (No_Request);
256   if (ctx->error)
257     return ctx->error;
258
259   ctx->pending = 0;
260   return 0;
261 }
262
263
264 void
265 gpgme_trust_item_release (GpgmeTrustItem item)
266 {
267   if (!item)
268     return;
269   xfree (item->name);
270   xfree (item);
271 }
272
273
274 const char *
275 gpgme_trust_item_get_string_attr (GpgmeTrustItem item, GpgmeAttr what,
276                                   const void *reserved, int idx)
277 {
278   const char *val = NULL;
279
280   if (!item)
281     return NULL;
282   if (reserved)
283     return NULL;
284   if (idx)
285     return NULL;
286
287   switch (what)
288     {
289     case GPGME_ATTR_KEYID:
290       val = item->keyid;
291       break;
292     case GPGME_ATTR_OTRUST:  
293       val = item->ot;
294       break;
295     case GPGME_ATTR_VALIDITY:
296       val = item->val;
297       break;
298     case GPGME_ATTR_USERID:  
299       val = item->name;
300       break;
301     default:
302       break;
303     }
304   return val;
305 }
306
307
308 int
309 gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what,
310                                const void *reserved, int idx)
311 {
312   int val = 0;
313   
314   if (!item)
315     return 0;
316   if (reserved)
317     return 0;
318   if (idx)
319     return 0;
320
321   switch (what)
322     {
323     case GPGME_ATTR_LEVEL:    
324       val = item->level;
325       break;
326     case GPGME_ATTR_TYPE:    
327       val = item->type;
328       break;
329     default:
330       break;
331     }
332   return val;
333 }