Fix timestamp parsing for y2038 hack.
[gpgme.git] / src / export.c
1 /* export.c - Export a key.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2010 g10 Code GmbH
4
5    This file is part of GPGME.
6  
7    GPGME is free software; you can redistribute it and/or modify it
8    under the terms of the GNU Lesser General Public License as
9    published by the Free Software Foundation; either version 2.1 of
10    the License, or (at your option) any later version.
11    
12    GPGME is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16    
17    You should have received a copy of the GNU Lesser General Public
18    License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "gpgme.h"
28 #include "util.h"
29 #include "debug.h"
30 #include "context.h"
31 #include "ops.h"
32
33 \f
34 static gpgme_error_t
35 export_status_handler (void *priv, gpgme_status_code_t code, char *args)
36 {
37   return 0;
38 }
39
40
41 static gpgme_error_t
42 export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
43               gpgme_export_mode_t mode, gpgme_data_t keydata)
44 {
45   gpgme_error_t err;
46
47   if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
48                 |GPGME_EXPORT_MODE_MINIMAL)))
49     return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE.  */
50
51   
52   if ((mode & GPGME_EXPORT_MODE_EXTERN))
53     {
54       if (keydata)
55         return gpg_error (GPG_ERR_INV_VALUE);
56     }
57   else
58     {
59       if (!keydata)
60         return gpg_error (GPG_ERR_INV_VALUE);
61     }
62
63   err = _gpgme_op_reset (ctx, synchronous);
64   if (err)
65     return err;
66
67   _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
68
69   return _gpgme_engine_op_export (ctx->engine, pattern, mode, keydata,
70                                   ctx->use_armor);
71 }
72
73
74 /* Export the keys listed in PATTERN into KEYDATA.  */
75 gpgme_error_t
76 gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern,
77                        gpgme_export_mode_t mode, gpgme_data_t keydata)
78 {
79   gpgme_error_t err;
80
81   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_export_start", ctx,
82               "pattern=%s, mode=0x%x, keydata=%p", pattern, mode, keydata);
83
84   if (!ctx)
85     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
86
87   err = export_start (ctx, 0, pattern, mode, keydata);
88   return TRACE_ERR (err);
89 }
90
91
92 /* Export the keys listed in PATTERN into KEYDATA.  */
93 gpgme_error_t
94 gpgme_op_export (gpgme_ctx_t ctx, const char *pattern,
95                  gpgme_export_mode_t mode, gpgme_data_t keydata)
96 {
97   gpgme_error_t err;
98
99   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_export", ctx,
100               "pattern=%s, mode=0x%x, keydata=%p", pattern, mode, keydata);
101
102   if (!ctx)
103     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
104
105   err = export_start (ctx, 1, pattern, mode, keydata);
106   if (!err)
107     err = _gpgme_wait_one (ctx);
108   return err;
109 }
110
111 \f
112 static gpgme_error_t
113 export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
114                   gpgme_export_mode_t mode, gpgme_data_t keydata)
115 {
116   gpgme_error_t err;
117
118   if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
119                 |GPGME_EXPORT_MODE_MINIMAL)))
120     return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE.  */
121
122   if ((mode & GPGME_EXPORT_MODE_EXTERN))
123     {
124       if (keydata)
125         return gpg_error (GPG_ERR_INV_VALUE);
126     }
127   else
128     {
129       if (!keydata)
130         return gpg_error (GPG_ERR_INV_VALUE);
131     }
132
133   err = _gpgme_op_reset (ctx, synchronous);
134   if (err)
135     return err;
136
137   _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
138
139   return _gpgme_engine_op_export_ext (ctx->engine, pattern, mode, keydata,
140                                       ctx->use_armor);
141 }
142
143
144 /* Export the keys listed in PATTERN into KEYDATA.  */
145 gpgme_error_t
146 gpgme_op_export_ext_start (gpgme_ctx_t ctx, const char *pattern[],
147                            gpgme_export_mode_t mode, gpgme_data_t keydata)
148 {
149   gpgme_error_t err;
150
151   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
152               "mode=0x%x, keydata=%p", mode, keydata);
153
154   if (!ctx)
155     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
156
157   if (_gpgme_debug_trace () && pattern)
158     {
159       int i = 0;
160
161       while (pattern[i])
162         {
163           TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
164           i++;
165         }
166     }
167
168   err = export_ext_start (ctx, 0, pattern, mode, keydata);
169   return TRACE_ERR (err);
170 }
171
172
173 /* Export the keys listed in PATTERN into KEYDATA.  */
174 gpgme_error_t
175 gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[],
176                      gpgme_export_mode_t mode, gpgme_data_t keydata)
177 {
178   gpgme_error_t err;
179
180   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
181               "mode=0x%x, keydata=%p", mode, keydata);
182
183   if (!ctx)
184     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
185
186   if (_gpgme_debug_trace () && pattern)
187     {
188       int i = 0;
189
190       while (pattern[i])
191         {
192           TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
193           i++;
194         }
195     }
196
197   err = export_ext_start (ctx, 1, pattern, mode, keydata);
198   if (!err)
199     err = _gpgme_wait_one (ctx);
200   return TRACE_ERR (err);
201 }
202
203
204
205 \f
206
207 static gpgme_error_t
208 export_keys_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t keys[],
209                    gpgme_export_mode_t mode, gpgme_data_t keydata)
210 {
211   gpgme_error_t err;
212   int nkeys, idx;
213   char **pattern;
214
215   if (!keys)
216     return gpg_error (GPG_ERR_INV_VALUE);
217
218   /* Create a list of pattern from the keys.  */
219   for (idx=nkeys=0; keys[idx]; idx++)
220     if (keys[idx]->protocol == ctx->protocol)
221       nkeys++;
222   if (!nkeys)
223     return gpg_error (GPG_ERR_NO_DATA);
224   
225   pattern = calloc (nkeys+1, sizeof *pattern);
226   if (!pattern)
227     return gpg_error_from_syserror ();
228
229   for (idx=nkeys=0; keys[idx]; idx++)
230     if (keys[idx]->protocol == ctx->protocol
231         && keys[idx]->subkeys
232         && keys[idx]->subkeys->fpr
233         && *keys[idx]->subkeys->fpr)
234       {
235         pattern[nkeys] = strdup (keys[idx]->subkeys->fpr);
236         if (!pattern[nkeys])
237           {
238             err = gpg_error_from_syserror ();
239             goto leave;
240           }
241         nkeys++;
242       }
243
244
245   /* Pass on to the regular function.  */
246   err = export_ext_start (ctx, synchronous, (const char**)pattern,
247                           mode, keydata);
248
249  leave:
250   for (idx=0; pattern[idx]; idx++)
251     free (pattern[idx]);
252   free (pattern);
253
254   return err;
255 }
256
257
258 /* Export the keys from the array KEYS into KEYDATA.  Only keys of the
259    current protocol are exported and only those which have a
260    fingerprint set; that is keys received with some external search
261    methods are silently skipped.  */
262 gpgme_error_t
263 gpgme_op_export_keys_start (gpgme_ctx_t ctx,
264                             gpgme_key_t keys[],
265                             gpgme_export_mode_t mode,
266                             gpgme_data_t keydata)
267 {
268   gpg_error_t err;
269
270   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys_start", ctx,
271               "mode=0x%x, keydata=%p", mode, keydata);
272
273   if (!ctx)
274     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
275   
276   if (_gpgme_debug_trace () && keys)
277     {
278       int i = 0;
279
280       while (keys[i])
281         {
282           TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
283                       (keys[i]->subkeys && keys[i]->subkeys->fpr) ? 
284                       keys[i]->subkeys->fpr : "invalid");
285           i++;
286         }
287     }
288
289   err = export_keys_start (ctx, 0, keys, mode, keydata);
290   return TRACE_ERR (err);
291 }
292
293 gpgme_error_t
294 gpgme_op_export_keys (gpgme_ctx_t ctx,
295                       gpgme_key_t keys[],
296                       gpgme_export_mode_t mode,
297                       gpgme_data_t keydata)
298 {
299   gpgme_error_t err;
300
301   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys", ctx,
302               "mode=0x%x, keydata=%p", mode, keydata);
303
304   if (!ctx)
305     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
306   
307   if (_gpgme_debug_trace () && keys)
308     {
309       int i = 0;
310
311       while (keys[i])
312         {
313           TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
314                       (keys[i]->subkeys && keys[i]->subkeys->fpr) ? 
315                       keys[i]->subkeys->fpr : "invalid");
316           i++;
317         }
318     }
319
320   err = export_keys_start (ctx, 1, keys, mode, keydata);
321   if (!err)
322     err = _gpgme_wait_one (ctx);
323   return TRACE_ERR (err);
324 }
325