1 |
/* trustlist.c |
2 |
* Copyright (C) 2000 Werner Koch (dd9jn) |
3 |
* |
4 |
* This file is part of MyGPGME. |
5 |
* |
6 |
* MyGPGME is free software; you can redistribute it and/or modify |
7 |
* it under the terms of the GNU General Public License as published by |
8 |
* the Free Software Foundation; either version 2 of the License, or |
9 |
* (at your option) any later version. |
10 |
* |
11 |
* MyGPGME is distributed in the hope that it will be useful, |
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
* GNU General Public License for more details. |
15 |
* |
16 |
* You should have received a copy of the GNU General Public License |
17 |
* along with this program; if not, write to the Free Software |
18 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
19 |
*/ |
20 |
#if 0 /* >= GPG 1.2.x does not support it yet */ |
21 |
|
22 |
#if 0 |
23 |
void gpgme_trust_item_release ( GpgmeTrustItem item ); |
24 |
const char *gpgme_trust_item_get_string_attr ( GpgmeTrustItem item, |
25 |
GpgmeAttr what, |
26 |
const void *reserved, int idx ); |
27 |
int gpgme_trust_item_get_int_attr ( GpgmeTrustItem item, GpgmeAttr what, |
28 |
const void *reserved, int idx ); |
29 |
|
30 |
gpgme_error_t gpgme_op_trustlist_start ( gpgme_ctx_t c, |
31 |
const char *pattern, int max_level ); |
32 |
gpgme_error_t gpgme_op_trustlist_next ( gpgme_ctx_t c, GpgmeTrustItem *r_item ); |
33 |
#endif |
34 |
|
35 |
#include <stdio.h> |
36 |
#include <stdlib.h> |
37 |
#include <string.h> |
38 |
#include <time.h> |
39 |
#include <assert.h> |
40 |
|
41 |
#include "util.h" |
42 |
#include "context.h" |
43 |
#include "ops.h" |
44 |
|
45 |
#define my_isdigit(a) ( (a) >='0' && (a) <= '9' ) |
46 |
|
47 |
struct gpgme_trust_item_s { |
48 |
int level; |
49 |
char keyid[16+1]; |
50 |
int type; |
51 |
char ot[2]; |
52 |
char val[2]; |
53 |
char *name; |
54 |
}; |
55 |
|
56 |
|
57 |
static GpgmeTrustItem |
58 |
trust_item_new (void) |
59 |
{ |
60 |
GpgmeTrustItem item; |
61 |
|
62 |
item = calloc (1, sizeof *item); |
63 |
return item; |
64 |
} |
65 |
|
66 |
|
67 |
|
68 |
static void |
69 |
trustlist_status_handler ( gpgme_ctx_t ctx, GpgStatusCode code, char *args ) |
70 |
{ |
71 |
if ( ctx->out_of_core ) |
72 |
return; |
73 |
|
74 |
switch (code) { |
75 |
case STATUS_EOF: |
76 |
break; |
77 |
|
78 |
default: |
79 |
break; |
80 |
} |
81 |
} |
82 |
|
83 |
|
84 |
|
85 |
/* |
86 |
* This handler is used to parse the output of --list-trust-path: |
87 |
* Format: |
88 |
* level:keyid:type:recno:ot:val:mc:cc:name: |
89 |
* With TYPE = U for a user ID |
90 |
* K for a key |
91 |
* The RECNO is either the one of the dir record or the one of the uid record. |
92 |
* OT is the the usual trust letter and only availabel on K lines. |
93 |
* VAL is the calcualted validity |
94 |
* MC is the marginal trust counter and only available on U lines |
95 |
* CC is the same for the complete count |
96 |
* NAME ist the username and only printed on U lines |
97 |
*/ |
98 |
static void |
99 |
trustlist_colon_handler ( gpgme_ctx_t ctx, char *line ) |
100 |
{ |
101 |
char *p, *pend; |
102 |
int field = 0; |
103 |
GpgmeTrustItem item = NULL; |
104 |
struct trust_queue_item_s *q, *q2; |
105 |
|
106 |
if ( ctx->out_of_core ) |
107 |
return; |
108 |
if (!line) |
109 |
return; /* EOF */ |
110 |
|
111 |
for (p = line; p; p = pend) { |
112 |
field++; |
113 |
pend = strchr (p, ':'); |
114 |
if (pend) |
115 |
*pend++ = 0; |
116 |
|
117 |
switch (field) { |
118 |
case 1: /* level */ |
119 |
q = malloc ( sizeof *q ); |
120 |
if ( !q ) { |
121 |
ctx->out_of_core = 1; |
122 |
return; |
123 |
} |
124 |
q->next = NULL; |
125 |
q->item = item = trust_item_new (); |
126 |
if (!q->item) { |
127 |
safe_free (q); |
128 |
ctx->out_of_core = 1; |
129 |
return; |
130 |
} |
131 |
/* fixme: lock queue, keep a tail pointer */ |
132 |
if ( !(q2 = ctx->trust_queue) ) |
133 |
ctx->trust_queue = q; |
134 |
else { |
135 |
for ( ; q2->next; q2 = q2->next ) |
136 |
; |
137 |
q2->next = q; |
138 |
} |
139 |
/* fixme: unlock queue */ |
140 |
item->level = atoi (p); |
141 |
break; |
142 |
case 2: /* long keyid */ |
143 |
if ( strlen (p) == DIM(item->keyid)-1 ) |
144 |
strcpy (item->keyid, p); |
145 |
break; |
146 |
case 3: /* type */ |
147 |
item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0; |
148 |
break; |
149 |
case 5: /* owner trust */ |
150 |
item->ot[0] = *p; |
151 |
item->ot[1] = 0; |
152 |
break; |
153 |
case 6: /* validity */ |
154 |
item->val[0] = *p; |
155 |
item->val[1] = 0; |
156 |
break; |
157 |
case 9: /* user ID */ |
158 |
item->name = xtrystrdup (p); |
159 |
if (!item->name) |
160 |
ctx->out_of_core = 1; |
161 |
break; |
162 |
} |
163 |
} |
164 |
|
165 |
if (field) |
166 |
ctx->key_cond = 1; |
167 |
} |
168 |
|
169 |
|
170 |
|
171 |
gpgme_error_t |
172 |
gpgme_op_trustlist_start ( gpgme_ctx_t c, const char *pattern, int max_level ) |
173 |
{ |
174 |
gpgme_error_t rc = 0; |
175 |
|
176 |
fail_on_pending_request( c ); |
177 |
if ( !pattern || !*pattern ) { |
178 |
return mk_error (Invalid_Value); |
179 |
} |
180 |
|
181 |
c->pending = 1; |
182 |
|
183 |
_gpgme_release_result (c); |
184 |
c->out_of_core = 0; |
185 |
|
186 |
if ( c->gpg ) { |
187 |
_gpgme_gpg_release ( c->gpg ); |
188 |
c->gpg = NULL; |
189 |
} |
190 |
|
191 |
rc = _gpgme_gpg_new ( &c->gpg ); |
192 |
if (rc) |
193 |
goto leave; |
194 |
|
195 |
_gpgme_gpg_set_status_handler ( c->gpg, trustlist_status_handler, c ); |
196 |
rc = _gpgme_gpg_set_colon_line_handler ( c->gpg, |
197 |
trustlist_colon_handler, c ); |
198 |
if (rc) |
199 |
goto leave; |
200 |
|
201 |
/* build the commandline */ |
202 |
_gpgme_gpg_add_arg ( c->gpg, "--with-colons" ); |
203 |
_gpgme_gpg_add_arg ( c->gpg, "--list-trust-path" ); |
204 |
|
205 |
/* Tell the gpg object about the data */ |
206 |
_gpgme_gpg_add_arg ( c->gpg, "--" ); |
207 |
_gpgme_gpg_add_arg ( c->gpg, pattern ); |
208 |
|
209 |
/* and kick off the process */ |
210 |
rc = _gpgme_gpg_spawn ( c->gpg, c ); |
211 |
|
212 |
leave: |
213 |
if (rc) { |
214 |
c->pending = 0; |
215 |
_gpgme_gpg_release ( c->gpg ); c->gpg = NULL; |
216 |
} |
217 |
return rc; |
218 |
} |
219 |
|
220 |
|
221 |
gpgme_error_t |
222 |
gpgme_op_trustlist_next ( gpgme_ctx_t c, GpgmeTrustItem *r_item ) |
223 |
{ |
224 |
struct trust_queue_item_s *q; |
225 |
|
226 |
if (!r_item) |
227 |
return mk_error (Invalid_Value); |
228 |
*r_item = NULL; |
229 |
if (!c) |
230 |
return mk_error (Invalid_Value); |
231 |
if ( !c->pending ) |
232 |
return mk_error (No_Request); |
233 |
if ( c->out_of_core ) |
234 |
return mk_error (Out_Of_Core); |
235 |
|
236 |
if ( !c->trust_queue ) { |
237 |
_gpgme_wait_on_condition (c, 1, &c->key_cond ); |
238 |
if ( c->out_of_core ) |
239 |
return mk_error (Out_Of_Core); |
240 |
if ( !c->key_cond ) |
241 |
return mk_error (EOF); |
242 |
c->key_cond = 0; |
243 |
assert ( c->trust_queue ); |
244 |
} |
245 |
q = c->trust_queue; |
246 |
c->trust_queue = q->next; |
247 |
|
248 |
*r_item = q->item; |
249 |
safe_free (q); |
250 |
return 0; |
251 |
} |
252 |
|
253 |
|
254 |
void |
255 |
gpgme_trust_item_release ( GpgmeTrustItem item ) |
256 |
{ |
257 |
if (!item) |
258 |
return; |
259 |
safe_free (item->name); |
260 |
safe_free (item); |
261 |
} |
262 |
|
263 |
|
264 |
const char * |
265 |
gpgme_trust_item_get_string_attr ( GpgmeTrustItem item, GpgmeAttr what, |
266 |
const void *reserved, int idx ) |
267 |
{ |
268 |
const char *val = NULL; |
269 |
|
270 |
if (!item) |
271 |
return NULL; |
272 |
if (reserved) |
273 |
return NULL; |
274 |
if (idx) |
275 |
return NULL; |
276 |
|
277 |
switch (what) { |
278 |
case GPGME_ATTR_KEYID: |
279 |
val = item->keyid; |
280 |
break; |
281 |
case GPGME_ATTR_OTRUST: |
282 |
val = item->ot; |
283 |
break; |
284 |
case GPGME_ATTR_VALIDITY: |
285 |
val = item->val; |
286 |
break; |
287 |
case GPGME_ATTR_USERID: |
288 |
val = item->name; |
289 |
break; |
290 |
default: |
291 |
break; |
292 |
} |
293 |
return val; |
294 |
} |
295 |
|
296 |
|
297 |
int |
298 |
gpgme_trust_item_get_int_attr ( GpgmeTrustItem item, GpgmeAttr what, |
299 |
const void *reserved, int idx ) |
300 |
{ |
301 |
int val = 0; |
302 |
|
303 |
if (!item) |
304 |
return 0; |
305 |
if (reserved) |
306 |
return 0; |
307 |
if (idx) |
308 |
return 0; |
309 |
|
310 |
switch (what) { |
311 |
case GPGME_ATTR_LEVEL: |
312 |
val = item->level; |
313 |
break; |
314 |
case GPGME_ATTR_TYPE: |
315 |
val = item->type; |
316 |
break; |
317 |
default: |
318 |
break; |
319 |
} |
320 |
return val; |
321 |
} |
322 |
#endif |