2009-11-05 Marcus Brinkmann <marcus@g10code.de>
[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 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, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "gpgme.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     return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE.  */
49
50   
51   if ((mode & GPGME_EXPORT_MODE_EXTERN))
52     {
53       if (keydata)
54         return gpg_error (GPG_ERR_INV_VALUE);
55     }
56   else
57     {
58       if (!keydata)
59         return gpg_error (GPG_ERR_INV_VALUE);
60     }
61
62   err = _gpgme_op_reset (ctx, synchronous);
63   if (err)
64     return err;
65
66   _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
67
68   return _gpgme_engine_op_export (ctx->engine, pattern, mode, keydata,
69                                   ctx->use_armor);
70 }
71
72
73 /* Export the keys listed in PATTERN into KEYDATA.  */
74 gpgme_error_t
75 gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern,
76                        gpgme_export_mode_t mode, gpgme_data_t keydata)
77 {
78   gpgme_error_t err;
79
80   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_export_start", ctx,
81               "pattern=%s, mode=0x%x, keydata=%p", pattern, mode, keydata);
82   err = export_start (ctx, 0, pattern, mode, keydata);
83   return TRACE_ERR (err);
84 }
85
86
87 /* Export the keys listed in PATTERN into KEYDATA.  */
88 gpgme_error_t
89 gpgme_op_export (gpgme_ctx_t ctx, const char *pattern,
90                  gpgme_export_mode_t mode, gpgme_data_t keydata)
91 {
92   gpgme_error_t err;
93
94   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_export", ctx,
95               "pattern=%s, mode=0x%x, keydata=%p", pattern, mode, keydata);
96
97   err = export_start (ctx, 1, pattern, mode, keydata);
98   if (!err)
99     err = _gpgme_wait_one (ctx);
100   return err;
101 }
102
103 \f
104 static gpgme_error_t
105 export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
106                   gpgme_export_mode_t mode, gpgme_data_t keydata)
107 {
108   gpgme_error_t err;
109
110   if ((mode & ~(GPGME_EXPORT_MODE_EXTERN)))
111     return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE.  */
112
113   if ((mode & GPGME_EXPORT_MODE_EXTERN))
114     {
115       if (keydata)
116         return gpg_error (GPG_ERR_INV_VALUE);
117     }
118   else
119     {
120       if (!keydata)
121         return gpg_error (GPG_ERR_INV_VALUE);
122     }
123
124   err = _gpgme_op_reset (ctx, synchronous);
125   if (err)
126     return err;
127
128   _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
129
130   return _gpgme_engine_op_export_ext (ctx->engine, pattern, mode, keydata,
131                                       ctx->use_armor);
132 }
133
134
135 /* Export the keys listed in PATTERN into KEYDATA.  */
136 gpgme_error_t
137 gpgme_op_export_ext_start (gpgme_ctx_t ctx, const char *pattern[],
138                            gpgme_export_mode_t mode, gpgme_data_t keydata)
139 {
140   gpgme_error_t err;
141
142   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
143               "mode=0x%x, keydata=%p", mode, keydata);
144
145   if (_gpgme_debug_trace () && pattern)
146     {
147       int i = 0;
148
149       while (pattern[i])
150         {
151           TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
152           i++;
153         }
154     }
155
156   err = export_ext_start (ctx, 0, pattern, mode, keydata);
157   return TRACE_ERR (err);
158 }
159
160
161 /* Export the keys listed in PATTERN into KEYDATA.  */
162 gpgme_error_t
163 gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[],
164                      gpgme_export_mode_t mode, gpgme_data_t keydata)
165 {
166   gpgme_error_t err;
167
168   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
169               "mode=0x%x, keydata=%p", mode, keydata);
170
171   if (_gpgme_debug_trace () && pattern)
172     {
173       int i = 0;
174
175       while (pattern[i])
176         {
177           TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
178           i++;
179         }
180     }
181
182   err = export_ext_start (ctx, 1, pattern, mode, keydata);
183   if (!err)
184     err = _gpgme_wait_one (ctx);
185   return TRACE_ERR (err);
186 }
187
188
189
190 \f
191
192 static gpgme_error_t
193 export_keys_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t keys[],
194                    gpgme_export_mode_t mode, gpgme_data_t keydata)
195 {
196   gpgme_error_t err;
197   int nkeys, idx;
198   char **pattern;
199
200   if (!keys)
201     return gpg_error (GPG_ERR_INV_VALUE);
202
203   /* Create a list of pattern from the keys.  */
204   for (idx=nkeys=0; keys[idx]; idx++)
205     if (keys[idx]->protocol == ctx->protocol)
206       nkeys++;
207   if (!nkeys)
208     return gpg_error (GPG_ERR_NO_DATA);
209   
210   pattern = calloc (nkeys+1, sizeof *pattern);
211   if (!pattern)
212     return gpg_error_from_syserror ();
213
214   for (idx=nkeys=0; keys[idx]; idx++)
215     if (keys[idx]->protocol == ctx->protocol
216         && keys[idx]->subkeys
217         && keys[idx]->subkeys->fpr
218         && *keys[idx]->subkeys->fpr)
219       {
220         pattern[nkeys] = strdup (keys[idx]->subkeys->fpr);
221         if (!pattern[nkeys])
222           {
223             err = gpg_error_from_syserror ();
224             goto leave;
225           }
226         nkeys++;
227       }
228
229
230   /* Pass on to the regular function.  */
231   err = export_ext_start (ctx, synchronous, (const char**)pattern,
232                           mode, keydata);
233
234  leave:
235   for (idx=0; pattern[idx]; idx++)
236     free (pattern[idx]);
237   free (pattern);
238
239   return err;
240 }
241
242
243 /* Export the keys from the array KEYS into KEYDATA.  Only keys of the
244    current protocol are exported and only those which have a
245    fingerprint set; that is keys received with some external search
246    methods are silently skipped.  */
247 gpgme_error_t
248 gpgme_op_export_keys_start (gpgme_ctx_t ctx,
249                             gpgme_key_t keys[],
250                             gpgme_export_mode_t mode,
251                             gpgme_data_t keydata)
252 {
253   gpg_error_t err;
254
255   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys_start", ctx,
256               "mode=0x%x, keydata=%p", mode, keydata);
257   
258   if (_gpgme_debug_trace () && keys)
259     {
260       int i = 0;
261
262       while (keys[i])
263         {
264           TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
265                       (keys[i]->subkeys && keys[i]->subkeys->fpr) ? 
266                       keys[i]->subkeys->fpr : "invalid");
267           i++;
268         }
269     }
270
271   err = export_keys_start (ctx, 0, keys, mode, keydata);
272   return TRACE_ERR (err);
273 }
274
275 gpgme_error_t
276 gpgme_op_export_keys (gpgme_ctx_t ctx,
277                       gpgme_key_t keys[],
278                       gpgme_export_mode_t mode,
279                       gpgme_data_t keydata)
280 {
281   gpgme_error_t err;
282
283   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys", ctx,
284               "mode=0x%x, keydata=%p", mode, keydata);
285   
286   if (_gpgme_debug_trace () && keys)
287     {
288       int i = 0;
289
290       while (keys[i])
291         {
292           TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
293                       (keys[i]->subkeys && keys[i]->subkeys->fpr) ? 
294                       keys[i]->subkeys->fpr : "invalid");
295           i++;
296         }
297     }
298
299   err = export_keys_start (ctx, 1, keys, mode, keydata);
300   if (!err)
301     err = _gpgme_wait_one (ctx);
302   return TRACE_ERR (err);
303 }
304