fbdcfdfb6cdcc430d7d66a8012bd920d2c882c84
[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   gpgme_error_t err;
143
144   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit_start", ctx,
145               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
146               (key->subkeys && key->subkeys->fpr) ? 
147               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
148   err = edit_start (ctx, 0, 0, key, fnc, fnc_value, out);
149   return err;
150 }
151
152
153 /* Edit the key KEY.  Send status and command requests to FNC and
154    output of edit commands to OUT.  */
155 gpgme_error_t
156 gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
157                gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
158 {
159   gpgme_error_t err;
160
161   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit", ctx,
162               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
163               (key->subkeys && key->subkeys->fpr) ? 
164               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
165
166   err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out);
167
168   if (!err)
169     err = _gpgme_wait_one (ctx);
170   return TRACE_ERR (err);
171 }
172
173 \f
174 gpgme_error_t
175 gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
176                           gpgme_edit_cb_t fnc, void *fnc_value,
177                           gpgme_data_t out)
178 {
179   gpgme_error_t err;
180
181   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit_start", ctx,
182               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
183               (key->subkeys && key->subkeys->fpr) ? 
184               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
185   err = edit_start (ctx, 0, 1, key, fnc, fnc_value, out);
186   return err;
187 }
188
189
190 /* Edit the card for the key KEY.  Send status and command requests to
191    FNC and output of edit commands to OUT.  */
192 gpgme_error_t
193 gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
194                     gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
195 {
196   gpgme_error_t err;
197
198   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit", ctx,
199               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
200               (key->subkeys && key->subkeys->fpr) ? 
201               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
202   err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out);
203   if (!err)
204     err = _gpgme_wait_one (ctx);
205   return TRACE_ERR (err);
206 }