3d10e5112a8148490dc93602983f6a62467accf4
[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   /* Trustlist operations are always "synchronous" in the sense that
171      we don't add ourself to the global FD table.  */
172   err = _gpgme_op_reset (ctx, 1);
173   if (err)
174     goto leave;
175
176   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
177                                               trustlist_colon_handler, ctx);
178   if (err)
179     goto leave;
180
181   err =_gpgme_engine_op_trustlist (ctx->engine, pattern);
182
183   if (!err)     /* And kick off the process.  */
184     err = _gpgme_engine_start (ctx->engine, ctx);
185
186  leave:
187   if (err)
188     {
189       ctx->pending = 0; 
190       _gpgme_engine_release (ctx->engine);
191       ctx->engine = NULL;
192     }
193   return err;
194 }
195
196
197 GpgmeError
198 gpgme_op_trustlist_next (GpgmeCtx ctx, GpgmeTrustItem *r_item)
199 {
200   struct trust_queue_item_s *q;
201
202   if (!r_item)
203     return mk_error (Invalid_Value);
204   *r_item = NULL;
205   if (!ctx)
206     return mk_error (Invalid_Value);
207   if (!ctx->pending)
208     return mk_error (No_Request);
209   if (ctx->error)
210     return ctx->error;
211
212   if (!ctx->trust_queue)
213     {
214       GpgmeError err = _gpgme_wait_on_condition (ctx, &ctx->key_cond);
215       if (err)
216         {
217           ctx->pending = 0;
218           return err;
219         }
220       if (!ctx->pending)
221         {
222           /* The operation finished.  Because not all keys might have
223              been returned to the caller yet, we just reset the
224              pending flag to 1.  This will cause us to call
225              _gpgme_wait_on_condition without any active file
226              descriptors, but that is a no-op, so it is safe.  */
227           ctx->pending = 1;
228         }
229       if (!ctx->key_cond)
230         {
231           ctx->pending = 0;
232           return mk_error (EOF);
233         }
234       ctx->key_cond = 0; 
235       assert (ctx->trust_queue);
236     }
237   q = ctx->trust_queue;
238   ctx->trust_queue = q->next;
239
240   *r_item = q->item;
241   xfree (q);
242   return 0;
243 }
244
245
246 /**
247  * gpgme_op_trustlist_end:
248  * @c: Context
249  *
250  * Ends the trustlist operation and allows to use the context for some
251  * other operation next.
252  **/
253 GpgmeError
254 gpgme_op_trustlist_end (GpgmeCtx ctx)
255 {
256   if (!ctx)
257     return mk_error (Invalid_Value);
258   if (!ctx->pending)
259     return mk_error (No_Request);
260   if (ctx->error)
261     return ctx->error;
262
263   ctx->pending = 0;
264   return 0;
265 }
266
267
268 void
269 gpgme_trust_item_release (GpgmeTrustItem item)
270 {
271   if (!item)
272     return;
273   xfree (item->name);
274   xfree (item);
275 }
276
277
278 const char *
279 gpgme_trust_item_get_string_attr (GpgmeTrustItem item, GpgmeAttr what,
280                                   const void *reserved, int idx)
281 {
282   const char *val = NULL;
283
284   if (!item)
285     return NULL;
286   if (reserved)
287     return NULL;
288   if (idx)
289     return NULL;
290
291   switch (what)
292     {
293     case GPGME_ATTR_KEYID:
294       val = item->keyid;
295       break;
296     case GPGME_ATTR_OTRUST:  
297       val = item->ot;
298       break;
299     case GPGME_ATTR_VALIDITY:
300       val = item->val;
301       break;
302     case GPGME_ATTR_USERID:  
303       val = item->name;
304       break;
305     default:
306       break;
307     }
308   return val;
309 }
310
311
312 int
313 gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what,
314                                const void *reserved, int idx)
315 {
316   int val = 0;
317   
318   if (!item)
319     return 0;
320   if (reserved)
321     return 0;
322   if (idx)
323     return 0;
324
325   switch (what)
326     {
327     case GPGME_ATTR_LEVEL:    
328       val = item->level;
329       break;
330     case GPGME_ATTR_TYPE:    
331       val = item->type;
332       break;
333     default:
334       break;
335     }
336   return val;
337 }