2009-06-22 Marcus Brinkmann <marcus@g10code.de>
[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 "context.h"
28 #include "ops.h"
29
30 \f
31 typedef struct
32 {
33   /* The user callback function and its hook value.  */
34   gpgme_edit_cb_t fnc;
35   void *fnc_value;
36 } *op_data_t;
37
38 \f
39 static gpgme_error_t
40 edit_status_handler (void *priv, gpgme_status_code_t status, char *args)
41 {
42   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
43   gpgme_error_t err;
44   void *hook;
45   op_data_t opd;
46
47   err = _gpgme_passphrase_status_handler (priv, status, args);
48   if (err)
49     return err;
50
51   err = _gpgme_progress_status_handler (priv, status, args);
52   if (err)
53     return err;
54
55   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
56   opd = hook;
57   if (err)
58     return err;
59
60   return (*opd->fnc) (opd->fnc_value, status, args, -1);
61 }
62
63
64 static gpgme_error_t
65 command_handler (void *priv, gpgme_status_code_t status, const char *args,
66                  int fd, int *processed_r)
67 {
68   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
69   gpgme_error_t err;
70   int processed = 0;
71
72   if (ctx->passphrase_cb)
73     {
74       err = _gpgme_passphrase_command_handler (ctx, status, args,
75                                                fd, &processed);
76       if (err)
77         return err;
78     }
79
80   if (!processed)
81     {
82       void *hook;
83       op_data_t opd;
84
85       err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
86       opd = hook;
87       if (err)
88         return err;
89
90       /* FIXME: We expect the user to handle _all_ status codes.
91          Later, we may fix the callback interface to allow the user
92          indicate if it processed the status code or not.  */
93       *processed_r = 1;
94
95       return (*opd->fnc) (opd->fnc_value, status, args, fd);
96     }
97
98   *processed_r = processed;
99   return 0;
100 }
101
102
103 static gpgme_error_t
104 edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
105             gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
106 {
107   gpgme_error_t err;
108   void *hook;
109   op_data_t opd;
110
111   err = _gpgme_op_reset (ctx, synchronous);
112   if (err)
113     return err;
114
115   if (!fnc || !out)
116     return gpg_error (GPG_ERR_INV_VALUE);
117
118   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
119   opd = hook;
120   if (err)
121     return err;
122
123   opd->fnc = fnc;
124   opd->fnc_value = fnc_value;
125
126   err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
127                                            ctx, out);
128   if (err)
129     return err;
130
131   _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
132
133   return _gpgme_engine_op_edit (ctx->engine, type, key, out, ctx);
134 }
135
136
137 gpgme_error_t
138 gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
139                      gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
140 {
141   return edit_start (ctx, 0, 0, key, fnc, fnc_value, out);
142 }
143
144
145 /* Edit the key KEY.  Send status and command requests to FNC and
146    output of edit commands to OUT.  */
147 gpgme_error_t
148 gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
149                gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
150 {
151   gpgme_error_t err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out);
152   if (!err)
153     err = _gpgme_wait_one (ctx);
154   return err;
155 }
156
157 \f
158 gpgme_error_t
159 gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
160                           gpgme_edit_cb_t fnc, void *fnc_value,
161                           gpgme_data_t out)
162 {
163   return edit_start (ctx, 0, 1, key, fnc, fnc_value, out);
164 }
165
166
167 /* Edit the card for the key KEY.  Send status and command requests to
168    FNC and output of edit commands to OUT.  */
169 gpgme_error_t
170 gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
171                     gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
172 {
173   gpgme_error_t err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out);
174   if (!err)
175     err = _gpgme_wait_one (ctx);
176   return err;
177 }