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