edf20894ed9fe1d4021c5af714e41e8c46f6f987
[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
81   if (!processed)
82     {
83       void *hook;
84       op_data_t opd;
85
86       err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
87       opd = hook;
88       if (err)
89         return err;
90
91       /* FIXME: We expect the user to handle _all_ status codes.
92          Later, we may fix the callback interface to allow the user
93          indicate if it processed the status code or not.  */
94       *processed_r = 1;
95
96       return (*opd->fnc) (opd->fnc_value, status, args, fd);
97     }
98
99   *processed_r = processed;
100   return 0;
101 }
102
103
104 static gpgme_error_t
105 edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
106             gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
107 {
108   gpgme_error_t err;
109   void *hook;
110   op_data_t opd;
111
112   err = _gpgme_op_reset (ctx, synchronous);
113   if (err)
114     return err;
115
116   if (!fnc || !out)
117     return gpg_error (GPG_ERR_INV_VALUE);
118
119   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
120   opd = hook;
121   if (err)
122     return err;
123
124   opd->fnc = fnc;
125   opd->fnc_value = fnc_value;
126
127   err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
128                                            ctx, out);
129   if (err)
130     return err;
131
132   _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
133
134   return _gpgme_engine_op_edit (ctx->engine, type, key, out, ctx);
135 }
136
137
138 gpgme_error_t
139 gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
140                      gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
141 {
142   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit_start", ctx,
143               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
144               (key->subkeys && !key->subkeys->fpr) ? 
145               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
146   return TRACE_ERR (edit_start (ctx, 0, 0, key, fnc, fnc_value, out));
147 }
148
149
150 /* Edit the key KEY.  Send status and command requests to FNC and
151    output of edit commands to OUT.  */
152 gpgme_error_t
153 gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
154                gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
155 {
156   gpgme_error_t err;
157
158   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit", ctx,
159               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
160               (key->subkeys && !key->subkeys->fpr) ? 
161               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
162
163   err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out);
164
165   if (!err)
166     err = _gpgme_wait_one (ctx);
167   return TRACE_ERR (err);
168 }
169
170 \f
171 gpgme_error_t
172 gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
173                           gpgme_edit_cb_t fnc, void *fnc_value,
174                           gpgme_data_t out)
175 {
176   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit_start", ctx,
177               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
178               (key->subkeys && !key->subkeys->fpr) ? 
179               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
180   return TRACE_ERR (edit_start (ctx, 0, 1, key, fnc, fnc_value, out));
181 }
182
183
184 /* Edit the card for the key KEY.  Send status and command requests to
185    FNC and output of edit commands to OUT.  */
186 gpgme_error_t
187 gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
188                     gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
189 {
190   gpgme_error_t err;
191
192   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit", ctx,
193               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
194               (key->subkeys && !key->subkeys->fpr) ? 
195               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
196   err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out);
197   if (!err)
198     err = _gpgme_wait_one (ctx);
199   return TRACE_ERR (err);
200 }