f33860a426b1c13b151d8b4ab629975539fe912d
[gpgme.git] / gpgme / trustlist.c
1 /* trustlist.c - Trust item listing.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004 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 Lesser General Public License as
9    published by the Free Software Foundation; either version 2.1 of
10    the License, or (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    Lesser General Public License for more details.
16    
17    You should have received a copy of the GNU Lesser General Public
18    License along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <errno.h>
29
30 #include "gpgme.h"
31 #include "util.h"
32 #include "context.h"
33 #include "ops.h"
34
35 \f
36 struct trust_queue_item_s
37 {
38   struct trust_queue_item_s *next;
39   gpgme_trust_item_t item;
40 };
41
42 typedef struct
43 {
44   /* Something new is available.  */
45   int trust_cond;
46   struct trust_queue_item_s *trust_queue;
47 } *op_data_t;
48
49
50 \f
51 static gpgme_error_t
52 trustlist_status_handler (void *priv, gpgme_status_code_t code, char *args)
53 {
54   return 0;
55 }
56
57
58 /* This handler is used to parse the output of --list-trust-path:
59    Format:
60    level:keyid:type:recno:ot:val:mc:cc:name:
61    With TYPE = U for a user ID
62                K for a key
63    The RECNO is either the one of the dir record or the one of the uid
64    record.  OT is the the usual trust letter and only availabel on K
65    lines.  VAL is the calcualted validity MC is the marginal trust
66    counter and only available on U lines CC is the same for the
67    complete count NAME ist the username and only printed on U
68    lines.  */
69 static gpgme_error_t
70 trustlist_colon_handler (void *priv, char *line)
71 {
72   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
73   gpgme_error_t err;
74   char *p, *pend;
75   int field = 0;
76   gpgme_trust_item_t item = NULL;
77
78   if (!line)
79     return 0; /* EOF */
80
81   for (p = line; p; p = pend)
82     {
83       field++;
84       pend = strchr (p, ':');
85       if (pend) 
86         *pend++ = 0;
87
88       switch (field)
89         {
90         case 1: /* level */
91           err = _gpgme_trust_item_new (&item);
92           if (err)
93             return err;
94           item->level = atoi (p);
95           break;
96         case 2: /* long keyid */
97           if (strlen (p) == DIM(item->keyid) - 1)
98             strcpy (item->keyid, p);
99           break;
100         case 3: /* type */
101           item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0;
102           break;
103         case 5: /* owner trust */
104           item->_owner_trust[0] = *p;
105           break;
106         case 6: /* validity */
107           item->_validity[0] = *p;
108           break;
109         case 9: /* user ID */
110           item->name = strdup (p);
111           if (!item->name)
112             {
113               int saved_errno = errno;
114               gpgme_trust_item_unref (item);
115               return gpg_error_from_errno (saved_errno);
116             }
117           break;
118         }
119     }
120
121   if (item)
122     _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_TRUSTITEM, item);
123   return 0;
124 }
125
126
127 void
128 _gpgme_op_trustlist_event_cb (void *data, gpgme_event_io_t type,
129                               void *type_data)
130 {
131   gpgme_ctx_t ctx = (gpgme_ctx_t) data;
132   gpgme_error_t err;
133   void *hook;
134   op_data_t opd;
135   gpgme_trust_item_t item = (gpgme_trust_item_t) type_data;
136   struct trust_queue_item_s *q, *q2;
137
138   assert (type == GPGME_EVENT_NEXT_TRUSTITEM);
139
140   err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
141   opd = hook;
142   if (err)
143     return;
144
145   q = malloc (sizeof *q);
146   if (!q)
147     {
148       gpgme_trust_item_unref (item);
149       /* FIXME: GPGME_Out_Of_Core; */
150       return;
151     }
152   q->item = item;
153   q->next = NULL;
154   /* FIXME: Use a tail pointer */
155   q2 = opd->trust_queue;
156   if (!q2)
157     opd->trust_queue = q;
158   else
159     {
160       while (q2->next)
161         q2 = q2->next;
162       q2->next = q;
163     }
164   /* FIXME: unlock queue */
165   opd->trust_cond = 1;
166 }
167
168
169 gpgme_error_t
170 gpgme_op_trustlist_start (gpgme_ctx_t ctx, const char *pattern, int max_level)
171 {
172   gpgme_error_t err = 0;
173   void *hook;
174   op_data_t opd;
175
176   if (!pattern || !*pattern)
177     return gpg_error (GPG_ERR_INV_VALUE);
178
179   err = _gpgme_op_reset (ctx, 2);
180   if (err)
181     return err;
182
183   err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook,
184                                sizeof (*opd), NULL);
185   opd = hook;
186   if (err)
187     return err;
188
189   _gpgme_engine_set_status_handler (ctx->engine,
190                                     trustlist_status_handler, ctx);
191   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
192                                               trustlist_colon_handler, ctx);
193   if (err)
194     return err;
195
196   return _gpgme_engine_op_trustlist (ctx->engine, pattern);
197 }
198
199
200 gpgme_error_t
201 gpgme_op_trustlist_next (gpgme_ctx_t ctx, gpgme_trust_item_t *r_item)
202 {
203   gpgme_error_t err;
204   void *hook;
205   op_data_t opd;
206   struct trust_queue_item_s *q;
207
208   if (!r_item)
209     return gpg_error (GPG_ERR_INV_VALUE);
210   *r_item = NULL;
211   if (!ctx)
212     return gpg_error (GPG_ERR_INV_VALUE);
213
214   err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
215   opd = hook;
216   if (err)
217     return err;
218
219   if (!opd->trust_queue)
220     {
221       err = _gpgme_wait_on_condition (ctx, &opd->trust_cond);
222       if (err)
223         return err;
224       if (!opd->trust_cond)
225         return gpg_error (GPG_ERR_EOF);
226       opd->trust_cond = 0; 
227       assert (opd->trust_queue);
228     }
229   q = opd->trust_queue;
230   opd->trust_queue = q->next;
231
232   *r_item = q->item;
233   free (q);
234   return 0;
235 }
236
237
238 /* Terminate a pending trustlist operation within CTX.  */
239 gpgme_error_t
240 gpgme_op_trustlist_end (gpgme_ctx_t ctx)
241 {
242   if (!ctx)
243     return gpg_error (GPG_ERR_INV_VALUE);
244
245   return 0;
246 }