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