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