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, ctx);
143 11 : if (err)
144 0 : return err;
145 :
146 11 : _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
147 :
148 11 : return _gpgme_engine_op_edit (ctx->engine,
149 11 : (flags & GPGME_INTERACT_CARD)? 1: 0,
150 : key, out, ctx);
151 : }
152 :
153 :
154 : gpgme_error_t
155 0 : gpgme_op_interact_start (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags,
156 : gpgme_interact_cb_t fnc, void *fnc_value,
157 : gpgme_data_t out)
158 : {
159 : gpgme_error_t err;
160 :
161 0 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_interact_start", ctx,
162 : "key=%p flags=0x%x fnc=%p fnc_value=%p, out=%p",
163 : key, flags,fnc, fnc_value, out);
164 :
165 0 : if (!ctx)
166 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
167 :
168 0 : err = interact_start (ctx, 0, key, flags, fnc, fnc_value, out);
169 0 : return err;
170 : }
171 :
172 :
173 : gpgme_error_t
174 11 : gpgme_op_interact (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags,
175 : gpgme_interact_cb_t fnc, void *fnc_value,
176 : gpgme_data_t out)
177 : {
178 : gpgme_error_t err;
179 :
180 11 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_interact", ctx,
181 : "key=%p flags=0x%x fnc=%p fnc_value=%p, out=%p",
182 : key, flags,fnc, fnc_value, out);
183 :
184 11 : if (!ctx)
185 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
186 :
187 11 : err = interact_start (ctx, 1, key, flags, fnc, fnc_value, out);
188 11 : if (!err)
189 11 : err = _gpgme_wait_one (ctx);
190 11 : return err;
191 : }
192 :
193 :
194 :
195 :
196 : /* The deprecated interface. */
197 : static gpgme_error_t
198 2 : edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
199 : gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
200 : {
201 : gpgme_error_t err;
202 : void *hook;
203 : op_data_t opd;
204 :
205 2 : err = _gpgme_op_reset (ctx, synchronous);
206 2 : if (err)
207 0 : return err;
208 :
209 2 : if (!fnc || !out)
210 0 : return gpg_error (GPG_ERR_INV_VALUE);
211 :
212 2 : err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
213 2 : opd = hook;
214 2 : if (err)
215 0 : return err;
216 :
217 2 : opd->fnc = NULL;
218 2 : opd->fnc_old = fnc;
219 2 : opd->fnc_value = fnc_value;
220 :
221 2 : err = _gpgme_engine_set_command_handler (ctx->engine, command_handler, ctx);
222 2 : if (err)
223 0 : return err;
224 :
225 2 : _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
226 :
227 2 : return _gpgme_engine_op_edit (ctx->engine, type, key, out, ctx);
228 : }
229 :
230 :
231 : gpgme_error_t
232 0 : gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
233 : gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
234 : {
235 : gpgme_error_t err;
236 :
237 0 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit_start", ctx,
238 : "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
239 : (key && key->subkeys && key->subkeys->fpr) ?
240 : key->subkeys->fpr : "invalid", fnc, fnc_value, out);
241 :
242 0 : if (!ctx)
243 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
244 :
245 0 : err = edit_start (ctx, 0, 0, key, fnc, fnc_value, out);
246 0 : return err;
247 : }
248 :
249 :
250 : /* Edit the key KEY. Send status and command requests to FNC and
251 : output of edit commands to OUT. */
252 : gpgme_error_t
253 2 : gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
254 : gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
255 : {
256 : gpgme_error_t err;
257 :
258 2 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit", ctx,
259 : "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
260 : (key && key->subkeys && key->subkeys->fpr) ?
261 : key->subkeys->fpr : "invalid", fnc, fnc_value, out);
262 :
263 2 : if (!ctx)
264 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
265 :
266 2 : err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out);
267 :
268 2 : if (!err)
269 2 : err = _gpgme_wait_one (ctx);
270 2 : return TRACE_ERR (err);
271 : }
272 :
273 :
274 : gpgme_error_t
275 0 : gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
276 : gpgme_edit_cb_t fnc, void *fnc_value,
277 : gpgme_data_t out)
278 : {
279 : gpgme_error_t err;
280 :
281 0 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit_start", ctx,
282 : "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
283 : (key && key->subkeys && key->subkeys->fpr) ?
284 : key->subkeys->fpr : "invalid", fnc, fnc_value, out);
285 :
286 0 : if (!ctx)
287 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
288 :
289 0 : err = edit_start (ctx, 0, 1, key, fnc, fnc_value, out);
290 0 : return err;
291 : }
292 :
293 :
294 : /* Edit the card for the key KEY. Send status and command requests to
295 : FNC and output of edit commands to OUT. */
296 : gpgme_error_t
297 0 : gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
298 : gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
299 : {
300 : gpgme_error_t err;
301 :
302 0 : TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit", ctx,
303 : "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
304 : (key && key->subkeys && key->subkeys->fpr) ?
305 : key->subkeys->fpr : "invalid", fnc, fnc_value, out);
306 :
307 0 : if (!ctx)
308 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
309 :
310 0 : err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out);
311 0 : if (!err)
312 0 : err = _gpgme_wait_one (ctx);
313 0 : return TRACE_ERR (err);
314 : }
|