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