Line data Source code
1 : /* edit.c - Key edit function.
2 : Copyright (C) 2002, 2003, 2004 g10 Code GmbH
3 :
4 : This file is part of GPGME.
5 :
6 : GPGME is free software; you can redistribute it and/or modify it
7 : under the terms of the GNU Lesser General Public License as
8 : published by the Free Software Foundation; either version 2.1 of
9 : the License, or (at your option) any later version.
10 :
11 : GPGME is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should have received a copy of the GNU Lesser General Public
17 : License along with this program; if not, write to the Free Software
18 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 : 02111-1307, USA. */
20 :
21 : #if HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif
24 : #include <stdlib.h>
25 :
26 : #include "gpgme.h"
27 : #include "debug.h"
28 : #include "context.h"
29 : #include "ops.h"
30 : #include "util.h"
31 :
32 :
33 :
34 : typedef struct
35 : {
36 : /* The user callback function and its hook value. */
37 : gpgme_interact_cb_t fnc;
38 : gpgme_edit_cb_t fnc_old;
39 : void *fnc_value;
40 : } *op_data_t;
41 :
42 :
43 : static gpgme_error_t
44 76 : edit_status_handler (void *priv, gpgme_status_code_t status, char *args)
45 : {
46 76 : gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
47 : gpgme_error_t err;
48 : void *hook;
49 : op_data_t opd;
50 :
51 76 : err = _gpgme_passphrase_status_handler (priv, status, args);
52 76 : if (err)
53 0 : return err;
54 :
55 76 : err = _gpgme_progress_status_handler (priv, status, args);
56 76 : if (err)
57 0 : return err;
58 :
59 76 : err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
60 76 : opd = hook;
61 76 : if (err)
62 0 : return err;
63 :
64 76 : if (opd->fnc_old)
65 11 : return (*opd->fnc_old) (opd->fnc_value, status, args, -1);
66 :
67 65 : return (*opd->fnc) (opd->fnc_value, _gpgme_status_to_string (status),
68 : args, -1);
69 : }
70 :
71 :
72 : static gpgme_error_t
73 52 : command_handler (void *priv, gpgme_status_code_t status, const char *args,
74 : int fd, int *processed_r)
75 : {
76 52 : gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
77 : gpgme_error_t err;
78 52 : int processed = 0;
79 :
80 52 : if (ctx->passphrase_cb)
81 : {
82 37 : err = _gpgme_passphrase_command_handler (ctx, status, args,
83 : fd, &processed);
84 37 : if (err)
85 0 : return err;
86 : }
87 : else
88 15 : err = 0;
89 :
90 52 : if (!processed)
91 : {
92 : void *hook;
93 : op_data_t opd;
94 :
95 52 : err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
96 52 : opd = hook;
97 52 : if (err)
98 0 : return err;
99 :
100 52 : if (opd->fnc_old)
101 7 : err = (*opd->fnc_old) (opd->fnc_value, status, args, fd);
102 : else
103 45 : err = (*opd->fnc) (opd->fnc_value, _gpgme_status_to_string (status),
104 : args, fd);
105 :
106 52 : if (gpg_err_code (err) == GPG_ERR_FALSE)
107 0 : err = 0;
108 : else
109 52 : processed = 1;
110 : }
111 :
112 52 : *processed_r = processed;
113 52 : return err;
114 : }
115 :
116 :
117 : static gpgme_error_t
118 11 : interact_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key,
119 : unsigned int flags,
120 : gpgme_interact_cb_t fnc, void *fnc_value, gpgme_data_t out)
121 : {
122 : gpgme_error_t err;
123 : void *hook;
124 : op_data_t opd;
125 :
126 11 : err = _gpgme_op_reset (ctx, synchronous);
127 11 : if (err)
128 0 : return err;
129 :
130 11 : if (!fnc || !out)
131 0 : return gpg_error (GPG_ERR_INV_VALUE);
132 :
133 11 : err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
134 11 : opd = hook;
135 11 : if (err)
136 0 : return err;
137 :
138 11 : opd->fnc = fnc;
139 11 : opd->fnc_old = NULL;
140 11 : opd->fnc_value = fnc_value;
141 :
142 11 : err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
143 : ctx, out);
144 11 : if (err)
145 0 : return err;
146 :
147 11 : _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
148 :
149 11 : return _gpgme_engine_op_edit (ctx->engine,
150 11 : (flags & GPGME_INTERACT_CARD)? 1: 0,
151 : key, out, ctx);
152 : }
153 :
154 :
155 : gpgme_error_t
156 0 : gpgme_op_interact_start (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags,
157 : gpgme_interact_cb_t fnc, void *fnc_value,
158 : gpgme_data_t out)
159 : {
160 : gpgme_error_t err;
161 :
162 0 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_interact_start", ctx,
163 : "key=%p flags=0x%x fnc=%p fnc_value=%p, out=%p",
164 : key, flags,fnc, fnc_value, out);
165 :
166 0 : if (!ctx)
167 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
168 :
169 0 : err = interact_start (ctx, 0, key, flags, fnc, fnc_value, out);
170 0 : return err;
171 : }
172 :
173 :
174 : gpgme_error_t
175 11 : gpgme_op_interact (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags,
176 : gpgme_interact_cb_t fnc, void *fnc_value,
177 : gpgme_data_t out)
178 : {
179 : gpgme_error_t err;
180 :
181 11 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_interact", ctx,
182 : "key=%p flags=0x%x fnc=%p fnc_value=%p, out=%p",
183 : key, flags,fnc, fnc_value, out);
184 :
185 11 : if (!ctx)
186 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
187 :
188 11 : err = interact_start (ctx, 1, key, flags, fnc, fnc_value, out);
189 11 : if (!err)
190 11 : err = _gpgme_wait_one (ctx);
191 11 : return err;
192 : }
193 :
194 :
195 :
196 :
197 : /* The deprectated interface. */
198 : static gpgme_error_t
199 2 : edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
200 : gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
201 : {
202 : gpgme_error_t err;
203 : void *hook;
204 : op_data_t opd;
205 :
206 2 : err = _gpgme_op_reset (ctx, synchronous);
207 2 : if (err)
208 0 : return err;
209 :
210 2 : if (!fnc || !out)
211 0 : return gpg_error (GPG_ERR_INV_VALUE);
212 :
213 2 : err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
214 2 : opd = hook;
215 2 : if (err)
216 0 : return err;
217 :
218 2 : opd->fnc = NULL;
219 2 : opd->fnc_old = fnc;
220 2 : opd->fnc_value = fnc_value;
221 :
222 2 : err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
223 : ctx, out);
224 2 : if (err)
225 0 : return err;
226 :
227 2 : _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
228 :
229 2 : return _gpgme_engine_op_edit (ctx->engine, type, key, out, ctx);
230 : }
231 :
232 :
233 : gpgme_error_t
234 0 : gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
235 : gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
236 : {
237 : gpgme_error_t err;
238 :
239 0 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit_start", ctx,
240 : "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
241 : (key && key->subkeys && key->subkeys->fpr) ?
242 : key->subkeys->fpr : "invalid", fnc, fnc_value, out);
243 :
244 0 : if (!ctx)
245 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
246 :
247 0 : err = edit_start (ctx, 0, 0, key, fnc, fnc_value, out);
248 0 : return err;
249 : }
250 :
251 :
252 : /* Edit the key KEY. Send status and command requests to FNC and
253 : output of edit commands to OUT. */
254 : gpgme_error_t
255 2 : gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
256 : gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
257 : {
258 : gpgme_error_t err;
259 :
260 2 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit", ctx,
261 : "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
262 : (key && key->subkeys && key->subkeys->fpr) ?
263 : key->subkeys->fpr : "invalid", fnc, fnc_value, out);
264 :
265 2 : if (!ctx)
266 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
267 :
268 2 : err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out);
269 :
270 2 : if (!err)
271 2 : err = _gpgme_wait_one (ctx);
272 2 : return TRACE_ERR (err);
273 : }
274 :
275 :
276 : gpgme_error_t
277 0 : gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
278 : gpgme_edit_cb_t fnc, void *fnc_value,
279 : gpgme_data_t out)
280 : {
281 : gpgme_error_t err;
282 :
283 0 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit_start", ctx,
284 : "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
285 : (key && key->subkeys && key->subkeys->fpr) ?
286 : key->subkeys->fpr : "invalid", fnc, fnc_value, out);
287 :
288 0 : if (!ctx)
289 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
290 :
291 0 : err = edit_start (ctx, 0, 1, key, fnc, fnc_value, out);
292 0 : return err;
293 : }
294 :
295 :
296 : /* Edit the card for the key KEY. Send status and command requests to
297 : FNC and output of edit commands to OUT. */
298 : gpgme_error_t
299 0 : gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
300 : gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
301 : {
302 : gpgme_error_t err;
303 :
304 0 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit", ctx,
305 : "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
306 : (key && key->subkeys && key->subkeys->fpr) ?
307 : key->subkeys->fpr : "invalid", fnc, fnc_value, out);
308 :
309 0 : if (!ctx)
310 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
311 :
312 0 : err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out);
313 0 : if (!err)
314 0 : err = _gpgme_wait_one (ctx);
315 0 : return TRACE_ERR (err);
316 : }
|