2002-06-10 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   if (!pattern || !*pattern)
168     return mk_error (Invalid_Value);
169
170   err = _gpgme_op_reset (ctx, 0);
171   if (err)
172     goto leave;
173
174   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
175                                               trustlist_colon_handler, ctx);
176   if (err)
177     goto leave;
178
179   err =_gpgme_engine_op_trustlist (ctx->engine, pattern);
180
181   if (!err)     /* And kick off the process.  */
182     err = _gpgme_engine_start (ctx->engine, ctx);
183
184  leave:
185   if (err)
186     {
187       ctx->pending = 0; 
188       _gpgme_engine_release (ctx->engine);
189       ctx->engine = NULL;
190     }
191   return err;
192 }
193
194
195 GpgmeError
196 gpgme_op_trustlist_next (GpgmeCtx ctx, GpgmeTrustItem *r_item)
197 {
198   struct trust_queue_item_s *q;
199
200   if (!r_item)
201     return mk_error (Invalid_Value);
202   *r_item = NULL;
203   if (!ctx)
204     return mk_error (Invalid_Value);
205   if (!ctx->pending)
206     return mk_error (No_Request);
207   if (ctx->error)
208     return ctx->error;
209
210   if (!ctx->trust_queue)
211     {
212       _gpgme_wait_on_condition (ctx, 1, &ctx->key_cond);
213       if (ctx->error)
214         return ctx->error;
215       if (!ctx->key_cond)
216         return mk_error (EOF);
217       ctx->key_cond = 0; 
218       assert (ctx->trust_queue);
219     }
220   q = ctx->trust_queue;
221   ctx->trust_queue = q->next;
222
223   *r_item = q->item;
224   xfree (q);
225   return 0;
226 }
227
228
229 /**
230  * gpgme_op_trustlist_end:
231  * @c: Context
232  *
233  * Ends the trustlist operation and allows to use the context for some
234  * other operation next.
235  **/
236 GpgmeError
237 gpgme_op_trustlist_end (GpgmeCtx ctx)
238 {
239   if (!ctx)
240     return mk_error (Invalid_Value);
241   if (!ctx->pending)
242     return mk_error (No_Request);
243   if (ctx->error)
244     return ctx->error;
245
246   ctx->pending = 0;
247   return 0;
248 }
249
250
251 void
252 gpgme_trust_item_release (GpgmeTrustItem item)
253 {
254   if (!item)
255     return;
256   xfree (item->name);
257   xfree (item);
258 }
259
260
261 const char *
262 gpgme_trust_item_get_string_attr (GpgmeTrustItem item, GpgmeAttr what,
263                                   const void *reserved, int idx)
264 {
265   const char *val = NULL;
266
267   if (!item)
268     return NULL;
269   if (reserved)
270     return NULL;
271   if (idx)
272     return NULL;
273
274   switch (what)
275     {
276     case GPGME_ATTR_KEYID:
277       val = item->keyid;
278       break;
279     case GPGME_ATTR_OTRUST:  
280       val = item->ot;
281       break;
282     case GPGME_ATTR_VALIDITY:
283       val = item->val;
284       break;
285     case GPGME_ATTR_USERID:  
286       val = item->name;
287       break;
288     default:
289       break;
290     }
291   return val;
292 }
293
294
295 int
296 gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what,
297                                const void *reserved, int idx)
298 {
299   int val = 0;
300   
301   if (!item)
302     return 0;
303   if (reserved)
304     return 0;
305   if (idx)
306     return 0;
307
308   switch (what)
309     {
310     case GPGME_ATTR_LEVEL:    
311       val = item->level;
312       break;
313     case GPGME_ATTR_TYPE:    
314       val = item->type;
315       break;
316     default:
317       break;
318     }
319   return val;
320 }