Spelling fixes for comments and doc
[gpgme.git] / src / 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 "debug.h"
32 #include "util.h"
33 #include "context.h"
34 #include "ops.h"
35
36 \f
37 struct trust_queue_item_s
38 {
39   struct trust_queue_item_s *next;
40   gpgme_trust_item_t item;
41 };
42
43 typedef struct
44 {
45   /* Something new is available.  */
46   int trust_cond;
47   struct trust_queue_item_s *trust_queue;
48 } *op_data_t;
49
50
51 \f
52 static gpgme_error_t
53 trustlist_status_handler (void *priv, gpgme_status_code_t code, char *args)
54 {
55   (void)priv;
56   (void)code;
57   (void)args;
58   return 0;
59 }
60
61
62 /* This handler is used to parse the output of --list-trust-path:
63    Format:
64    level:keyid:type:recno:ot:val:mc:cc:name:
65    With TYPE = U for a user ID
66                K for a key
67    The RECNO is either the one of the dir record or the one of the uid
68    record.  OT is the the usual trust letter and only availabel on K
69    lines.  VAL is the calculated validity MC is the marginal trust
70    counter and only available on U lines CC is the same for the
71    complete count NAME ist the username and only printed on U
72    lines.  */
73 static gpgme_error_t
74 trustlist_colon_handler (void *priv, char *line)
75 {
76   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
77   gpgme_error_t err;
78   char *p, *pend;
79   int field = 0;
80   gpgme_trust_item_t item = NULL;
81
82   if (!line)
83     return 0; /* EOF */
84
85   for (p = line; p; p = pend)
86     {
87       field++;
88       pend = strchr (p, ':');
89       if (pend)
90         *pend++ = 0;
91
92       switch (field)
93         {
94         case 1: /* level */
95           err = _gpgme_trust_item_new (&item);
96           if (err)
97             return err;
98           item->level = atoi (p);
99           break;
100         case 2: /* long keyid */
101           if (strlen (p) == DIM(item->keyid) - 1)
102             strcpy (item->keyid, p);
103           break;
104         case 3: /* type */
105           item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0;
106           break;
107         case 5: /* owner trust */
108           item->_owner_trust[0] = *p;
109           break;
110         case 6: /* validity */
111           item->_validity[0] = *p;
112           break;
113         case 9: /* user ID */
114           item->name = strdup (p);
115           if (!item->name)
116             {
117               int saved_err = gpg_error_from_syserror ();
118               gpgme_trust_item_unref (item);
119               return saved_err;
120             }
121           break;
122         }
123     }
124
125   if (item)
126     _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_TRUSTITEM, item);
127   return 0;
128 }
129
130
131 void
132 _gpgme_op_trustlist_event_cb (void *data, gpgme_event_io_t type,
133                               void *type_data)
134 {
135   gpgme_ctx_t ctx = (gpgme_ctx_t) data;
136   gpgme_error_t err;
137   void *hook;
138   op_data_t opd;
139   gpgme_trust_item_t item = (gpgme_trust_item_t) type_data;
140   struct trust_queue_item_s *q, *q2;
141
142   assert (type == GPGME_EVENT_NEXT_TRUSTITEM);
143
144   err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
145   opd = hook;
146   if (err)
147     return;
148
149   q = malloc (sizeof *q);
150   if (!q)
151     {
152       gpgme_trust_item_unref (item);
153       /* FIXME: GPGME_Out_Of_Core; */
154       return;
155     }
156   q->item = item;
157   q->next = NULL;
158   /* FIXME: Use a tail pointer */
159   q2 = opd->trust_queue;
160   if (!q2)
161     opd->trust_queue = q;
162   else
163     {
164       while (q2->next)
165         q2 = q2->next;
166       q2->next = q;
167     }
168   /* FIXME: unlock queue */
169   opd->trust_cond = 1;
170 }
171
172
173 gpgme_error_t
174 gpgme_op_trustlist_start (gpgme_ctx_t ctx, const char *pattern, int max_level)
175 {
176   gpgme_error_t err = 0;
177   void *hook;
178   op_data_t opd;
179
180   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_trustlist_start", ctx,
181               "pattern=%s, max_level=%i", pattern, max_level);
182
183   if (!ctx || !pattern || !*pattern)
184     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
185
186   err = _gpgme_op_reset (ctx, 2);
187   if (err)
188     return TRACE_ERR (err);
189
190   err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook,
191                                sizeof (*opd), NULL);
192   opd = hook;
193   if (err)
194     return TRACE_ERR (err);
195
196   _gpgme_engine_set_status_handler (ctx->engine,
197                                     trustlist_status_handler, ctx);
198   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
199                                               trustlist_colon_handler, ctx);
200   if (err)
201     return TRACE_ERR (err);
202
203   err = _gpgme_engine_op_trustlist (ctx->engine, pattern);
204   return TRACE_ERR (err);
205 }
206
207
208 gpgme_error_t
209 gpgme_op_trustlist_next (gpgme_ctx_t ctx, gpgme_trust_item_t *r_item)
210 {
211   gpgme_error_t err;
212   void *hook;
213   op_data_t opd;
214   struct trust_queue_item_s *q;
215
216   TRACE_BEG (DEBUG_CTX, "gpgme_op_trustlist_next", ctx);
217
218   if (!ctx || !r_item)
219     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
220   *r_item = NULL;
221   if (!ctx)
222     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
223
224   err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
225   opd = hook;
226   if (err)
227     return TRACE_ERR (err);
228   if (opd == NULL)
229     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
230
231   if (!opd->trust_queue)
232     {
233       err = _gpgme_wait_on_condition (ctx, &opd->trust_cond, NULL);
234       if (err)
235         return TRACE_ERR (err);
236       if (!opd->trust_cond)
237         return TRACE_ERR (gpg_error (GPG_ERR_EOF));
238       opd->trust_cond = 0;
239       assert (opd->trust_queue);
240     }
241   q = opd->trust_queue;
242   opd->trust_queue = q->next;
243
244   *r_item = q->item;
245   free (q);
246   if ((*r_item)->type == 1)
247     {
248       TRACE_SUC5 ("trust_item=%p: %s: owner trust %s with level %i "
249                   "and validity 0x%x", *r_item, (*r_item)->keyid,
250                   (*r_item)->owner_trust, (*r_item)->level,
251                   (*r_item)->validity);
252     }
253   else if ((*r_item)->type == 2)
254     {
255       TRACE_SUC5 ("trust_item=%p: %s: UID %s with level %i "
256                   "and validity 0x%x", *r_item, (*r_item)->keyid,
257                   (*r_item)->name, (*r_item)->level, (*r_item)->validity);
258     }
259   else
260     {
261       TRACE_SUC5 ("trust_item=%p: %s: unknown type %i with level %i "
262                   "and validity 0x%x", *r_item, (*r_item)->keyid,
263                   (*r_item)->type, (*r_item)->level, (*r_item)->validity);
264     }
265   return 0;
266 }
267
268
269 /* Terminate a pending trustlist operation within CTX.  */
270 gpgme_error_t
271 gpgme_op_trustlist_end (gpgme_ctx_t ctx)
272 {
273   TRACE (DEBUG_CTX, "gpgme_op_trustlist_end", ctx);
274
275   if (!ctx)
276     return gpg_error (GPG_ERR_INV_VALUE);
277
278   return 0;
279 }