a5a291582c888e4f5e1f1e50e9b282e1b3153dfb
[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,
125                               void *type_data)
126 {
127   gpgme_ctx_t ctx = (gpgme_ctx_t) data;
128   gpgme_error_t err;
129   void *hook;
130   op_data_t opd;
131   gpgme_trust_item_t item = (gpgme_trust_item_t) type_data;
132   struct trust_queue_item_s *q, *q2;
133
134   assert (type == GPGME_EVENT_NEXT_TRUSTITEM);
135
136   err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
137   opd = hook;
138   if (err)
139     return;
140
141   q = malloc (sizeof *q);
142   if (!q)
143     {
144       gpgme_trust_item_unref (item);
145       /* FIXME: GPGME_Out_Of_Core; */
146       return;
147     }
148   q->item = item;
149   q->next = NULL;
150   /* FIXME: Use a tail pointer */
151   q2 = opd->trust_queue;
152   if (!q2)
153     opd->trust_queue = q;
154   else
155     {
156       while (q2->next)
157         q2 = q2->next;
158       q2->next = q;
159     }
160   /* FIXME: unlock queue */
161   opd->trust_cond = 1;
162 }
163
164
165 gpgme_error_t
166 gpgme_op_trustlist_start (gpgme_ctx_t ctx, const char *pattern, int max_level)
167 {
168   gpgme_error_t err = 0;
169   void *hook;
170   op_data_t opd;
171
172   if (!pattern || !*pattern)
173     return GPGME_Invalid_Value;
174
175   err = _gpgme_op_reset (ctx, 2);
176   if (err)
177     return err;
178
179   err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook,
180                                sizeof (*opd), NULL);
181   opd = hook;
182   if (err)
183     return err;
184
185   _gpgme_engine_set_status_handler (ctx->engine,
186                                     trustlist_status_handler, ctx);
187   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
188                                               trustlist_colon_handler, ctx);
189   if (err)
190     return err;
191
192   return _gpgme_engine_op_trustlist (ctx->engine, pattern);
193 }
194
195
196 gpgme_error_t
197 gpgme_op_trustlist_next (gpgme_ctx_t ctx, gpgme_trust_item_t *r_item)
198 {
199   gpgme_error_t err;
200   void *hook;
201   op_data_t opd;
202   struct trust_queue_item_s *q;
203
204   if (!r_item)
205     return GPGME_Invalid_Value;
206   *r_item = NULL;
207   if (!ctx)
208     return GPGME_Invalid_Value;
209
210   err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
211   opd = hook;
212   if (err)
213     return err;
214
215   if (!opd->trust_queue)
216     {
217       err = _gpgme_wait_on_condition (ctx, &opd->trust_cond);
218       if (err)
219         return err;
220       if (!opd->trust_cond)
221         return GPGME_EOF;
222       opd->trust_cond = 0; 
223       assert (opd->trust_queue);
224     }
225   q = opd->trust_queue;
226   opd->trust_queue = q->next;
227
228   *r_item = q->item;
229   free (q);
230   return 0;
231 }
232
233
234 /* Terminate a pending trustlist operation within CTX.  */
235 gpgme_error_t
236 gpgme_op_trustlist_end (gpgme_ctx_t ctx)
237 {
238   if (!ctx)
239     return GPGME_Invalid_Value;
240
241   return 0;
242 }