2005-04-14 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / 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)
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_internal (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       return (*opd->fnc) (opd->fnc_value, status, args, fd);
91     }
92   return 0;
93 }
94
95
96 static gpgme_error_t
97 edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
98             gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
99 {
100   gpgme_error_t err;
101   void *hook;
102   op_data_t opd;
103
104   err = _gpgme_op_reset (ctx, synchronous);
105   if (err)
106     return err;
107
108   if (!fnc || !out)
109     return gpg_error (GPG_ERR_INV_VALUE);
110
111   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
112   opd = hook;
113   if (err)
114     return err;
115
116   opd->fnc = fnc;
117   opd->fnc_value = fnc_value;
118
119   err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
120                                            ctx, out);
121   if (err)
122     return err;
123
124   _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
125
126   return _gpgme_engine_op_edit (ctx->engine, type, key, out, ctx);
127 }
128
129
130 gpgme_error_t
131 gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
132                      gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
133 {
134   return edit_start (ctx, 0, 0, key, fnc, fnc_value, out);
135 }
136
137
138 /* Edit the key KEY.  Send status and command requests to FNC and
139    output of edit commands to OUT.  */
140 gpgme_error_t
141 gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
142                gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
143 {
144   gpgme_error_t err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out);
145   if (!err)
146     err = _gpgme_wait_one (ctx);
147   return err;
148 }
149
150 \f
151 gpgme_error_t
152 gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
153                           gpgme_edit_cb_t fnc, void *fnc_value,
154                           gpgme_data_t out)
155 {
156   return edit_start (ctx, 0, 1, key, fnc, fnc_value, out);
157 }
158
159
160 /* Edit the card for the key KEY.  Send status and command requests to
161    FNC and output of edit commands to OUT.  */
162 gpgme_error_t
163 gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
164                     gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
165 {
166   gpgme_error_t err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out);
167   if (!err)
168     err = _gpgme_wait_one (ctx);
169   return err;
170 }