2010-05-06 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, 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 "debug.h"
29 #include "context.h"
30 #include "ops.h"
31
32 \f
33 static gpgme_error_t
34 export_status_handler (void *priv, gpgme_status_code_t code, char *args)
35 {
36   return 0;
37 }
38
39
40 static gpgme_error_t
41 export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
42               gpgme_export_mode_t mode, gpgme_data_t keydata)
43 {
44   gpgme_error_t err;
45
46   if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
47                 |GPGME_EXPORT_MODE_MINIMAL)))
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                 |GPGME_EXPORT_MODE_MINIMAL)))
112     return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE.  */
113
114   if ((mode & GPGME_EXPORT_MODE_EXTERN))
115     {
116       if (keydata)
117         return gpg_error (GPG_ERR_INV_VALUE);
118     }
119   else
120     {
121       if (!keydata)
122         return gpg_error (GPG_ERR_INV_VALUE);
123     }
124
125   err = _gpgme_op_reset (ctx, synchronous);
126   if (err)
127     return err;
128
129   _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
130
131   return _gpgme_engine_op_export_ext (ctx->engine, pattern, mode, keydata,
132                                       ctx->use_armor);
133 }
134
135
136 /* Export the keys listed in PATTERN into KEYDATA.  */
137 gpgme_error_t
138 gpgme_op_export_ext_start (gpgme_ctx_t ctx, const char *pattern[],
139                            gpgme_export_mode_t mode, gpgme_data_t keydata)
140 {
141   gpgme_error_t err;
142
143   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
144               "mode=0x%x, keydata=%p", mode, keydata);
145
146   if (_gpgme_debug_trace () && pattern)
147     {
148       int i = 0;
149
150       while (pattern[i])
151         {
152           TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
153           i++;
154         }
155     }
156
157   err = export_ext_start (ctx, 0, pattern, mode, keydata);
158   return TRACE_ERR (err);
159 }
160
161
162 /* Export the keys listed in PATTERN into KEYDATA.  */
163 gpgme_error_t
164 gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[],
165                      gpgme_export_mode_t mode, gpgme_data_t keydata)
166 {
167   gpgme_error_t err;
168
169   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
170               "mode=0x%x, keydata=%p", mode, keydata);
171
172   if (_gpgme_debug_trace () && pattern)
173     {
174       int i = 0;
175
176       while (pattern[i])
177         {
178           TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
179           i++;
180         }
181     }
182
183   err = export_ext_start (ctx, 1, pattern, mode, keydata);
184   if (!err)
185     err = _gpgme_wait_one (ctx);
186   return TRACE_ERR (err);
187 }
188
189
190
191 \f
192
193 static gpgme_error_t
194 export_keys_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t keys[],
195                    gpgme_export_mode_t mode, gpgme_data_t keydata)
196 {
197   gpgme_error_t err;
198   int nkeys, idx;
199   char **pattern;
200
201   if (!keys)
202     return gpg_error (GPG_ERR_INV_VALUE);
203
204   /* Create a list of pattern from the keys.  */
205   for (idx=nkeys=0; keys[idx]; idx++)
206     if (keys[idx]->protocol == ctx->protocol)
207       nkeys++;
208   if (!nkeys)
209     return gpg_error (GPG_ERR_NO_DATA);
210   
211   pattern = calloc (nkeys+1, sizeof *pattern);
212   if (!pattern)
213     return gpg_error_from_syserror ();
214
215   for (idx=nkeys=0; keys[idx]; idx++)
216     if (keys[idx]->protocol == ctx->protocol
217         && keys[idx]->subkeys
218         && keys[idx]->subkeys->fpr
219         && *keys[idx]->subkeys->fpr)
220       {
221         pattern[nkeys] = strdup (keys[idx]->subkeys->fpr);
222         if (!pattern[nkeys])
223           {
224             err = gpg_error_from_syserror ();
225             goto leave;
226           }
227         nkeys++;
228       }
229
230
231   /* Pass on to the regular function.  */
232   err = export_ext_start (ctx, synchronous, (const char**)pattern,
233                           mode, keydata);
234
235  leave:
236   for (idx=0; pattern[idx]; idx++)
237     free (pattern[idx]);
238   free (pattern);
239
240   return err;
241 }
242
243
244 /* Export the keys from the array KEYS into KEYDATA.  Only keys of the
245    current protocol are exported and only those which have a
246    fingerprint set; that is keys received with some external search
247    methods are silently skipped.  */
248 gpgme_error_t
249 gpgme_op_export_keys_start (gpgme_ctx_t ctx,
250                             gpgme_key_t keys[],
251                             gpgme_export_mode_t mode,
252                             gpgme_data_t keydata)
253 {
254   gpg_error_t err;
255
256   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys_start", ctx,
257               "mode=0x%x, keydata=%p", mode, keydata);
258   
259   if (_gpgme_debug_trace () && keys)
260     {
261       int i = 0;
262
263       while (keys[i])
264         {
265           TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
266                       (keys[i]->subkeys && keys[i]->subkeys->fpr) ? 
267                       keys[i]->subkeys->fpr : "invalid");
268           i++;
269         }
270     }
271
272   err = export_keys_start (ctx, 0, keys, mode, keydata);
273   return TRACE_ERR (err);
274 }
275
276 gpgme_error_t
277 gpgme_op_export_keys (gpgme_ctx_t ctx,
278                       gpgme_key_t keys[],
279                       gpgme_export_mode_t mode,
280                       gpgme_data_t keydata)
281 {
282   gpgme_error_t err;
283
284   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys", ctx,
285               "mode=0x%x, keydata=%p", mode, keydata);
286   
287   if (_gpgme_debug_trace () && keys)
288     {
289       int i = 0;
290
291       while (keys[i])
292         {
293           TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
294                       (keys[i]->subkeys && keys[i]->subkeys->fpr) ? 
295                       keys[i]->subkeys->fpr : "invalid");
296           i++;
297         }
298     }
299
300   err = export_keys_start (ctx, 1, keys, mode, keydata);
301   if (!err)
302     err = _gpgme_wait_one (ctx);
303   return TRACE_ERR (err);
304 }
305