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