1be60c46939b42ad44dd742b3a49e4092e5c98cb
[gpgme.git] / src / edit.c
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
31 \f
32 typedef struct
33 {
34   /* The user callback function and its hook value.  */
35   gpgme_edit_cb_t fnc;
36   void *fnc_value;
37 } *op_data_t;
38
39 \f
40 static gpgme_error_t
41 edit_status_handler (void *priv, gpgme_status_code_t status, char *args)
42 {
43   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
44   gpgme_error_t err;
45   void *hook;
46   op_data_t opd;
47
48   err = _gpgme_passphrase_status_handler (priv, status, args);
49   if (err)
50     return err;
51
52   err = _gpgme_progress_status_handler (priv, status, args);
53   if (err)
54     return err;
55
56   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
57   opd = hook;
58   if (err)
59     return err;
60
61   return (*opd->fnc) (opd->fnc_value, status, args, -1);
62 }
63
64
65 static gpgme_error_t
66 command_handler (void *priv, gpgme_status_code_t status, const char *args,
67                  int fd, int *processed_r)
68 {
69   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
70   gpgme_error_t err;
71   int processed = 0;
72
73   if (ctx->passphrase_cb)
74     {
75       err = _gpgme_passphrase_command_handler (ctx, status, args,
76                                                fd, &processed);
77       if (err)
78         return err;
79     }
80   else
81     err = 0;
82
83   if (!processed)
84     {
85       void *hook;
86       op_data_t opd;
87
88       err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
89       opd = hook;
90       if (err)
91         return err;
92
93       err = (*opd->fnc) (opd->fnc_value, status, args, fd);
94       if (gpg_err_code (err) == GPG_ERR_FALSE)
95         err = 0;
96       else
97         processed = 1;
98     }
99
100   *processed_r = processed;
101   return err;
102 }
103
104
105 static gpgme_error_t
106 edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
107             gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
108 {
109   gpgme_error_t err;
110   void *hook;
111   op_data_t opd;
112
113   err = _gpgme_op_reset (ctx, synchronous);
114   if (err)
115     return err;
116
117   if (!fnc || !out)
118     return gpg_error (GPG_ERR_INV_VALUE);
119
120   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
121   opd = hook;
122   if (err)
123     return err;
124
125   opd->fnc = fnc;
126   opd->fnc_value = fnc_value;
127
128   err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
129                                            ctx, out);
130   if (err)
131     return err;
132
133   _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
134
135   return _gpgme_engine_op_edit (ctx->engine, type, key, out, ctx);
136 }
137
138
139 gpgme_error_t
140 gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
141                      gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
142 {
143   gpgme_error_t err;
144
145   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit_start", ctx,
146               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
147               (key && key->subkeys && key->subkeys->fpr) ?
148               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
149
150   if (!ctx)
151     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
152
153   err = edit_start (ctx, 0, 0, key, fnc, fnc_value, out);
154   return err;
155 }
156
157
158 /* Edit the key KEY.  Send status and command requests to FNC and
159    output of edit commands to OUT.  */
160 gpgme_error_t
161 gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
162                gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
163 {
164   gpgme_error_t err;
165
166   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit", ctx,
167               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
168               (key && key->subkeys && key->subkeys->fpr) ?
169               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
170
171   if (!ctx)
172     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
173
174   err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out);
175
176   if (!err)
177     err = _gpgme_wait_one (ctx);
178   return TRACE_ERR (err);
179 }
180
181 \f
182 gpgme_error_t
183 gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
184                           gpgme_edit_cb_t fnc, void *fnc_value,
185                           gpgme_data_t out)
186 {
187   gpgme_error_t err;
188
189   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit_start", ctx,
190               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
191               (key && key->subkeys && key->subkeys->fpr) ?
192               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
193
194   if (!ctx)
195     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
196
197   err = edit_start (ctx, 0, 1, key, fnc, fnc_value, out);
198   return err;
199 }
200
201
202 /* Edit the card for the key KEY.  Send status and command requests to
203    FNC and output of edit commands to OUT.  */
204 gpgme_error_t
205 gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
206                     gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
207 {
208   gpgme_error_t err;
209
210   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit", ctx,
211               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
212               (key && key->subkeys && key->subkeys->fpr) ?
213               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
214
215   if (!ctx)
216     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
217
218   err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out);
219   if (!err)
220     err = _gpgme_wait_one (ctx);
221   return TRACE_ERR (err);
222 }