Fix comment indentation.
[gpgme.git] / gpgme / encrypt.c
1 /* encrypt.c - Encrypt functions.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003 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 General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (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    General Public License for more details.
16  
17    You should have received a copy of the GNU General Public License
18    along with GPGME; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #include "util.h"
30 #include "context.h"
31 #include "ops.h"
32 #include "wait.h"
33
34 #define SKIP_TOKEN_OR_RETURN(a) do { \
35     while (*(a) && *(a) != ' ') (a)++; \
36     while (*(a) == ' ') (a)++; \
37     if (!*(a)) \
38         return; /* oops */ \
39 } while (0)
40
41 struct encrypt_result_s
42 {
43   int no_valid_recipients;
44   int invalid_recipients;
45   GpgmeData xmlinfo;
46 };
47
48 void
49 _gpgme_release_encrypt_result (EncryptResult result)
50 {
51   if (!result)
52     return;
53   gpgme_data_release (result->xmlinfo);
54   free (result);
55 }
56
57 /* Parse the args and save the information in an XML structure.  With
58    args of NULL the xml structure is closed.  */
59 static void
60 append_xml_encinfo (GpgmeData *rdh, char *args)
61 {
62   GpgmeData dh;
63   char helpbuf[100];
64
65   if (!*rdh)
66     {
67       if (gpgme_data_new (rdh))
68         return; /* FIXME: We are ignoring out-of-core.  */
69       dh = *rdh;
70       _gpgme_data_append_string (dh, "<GnupgOperationInfo>\n");
71     }
72   else
73     {
74       dh = *rdh;
75       _gpgme_data_append_string (dh, "  </encryption>\n");
76     }
77
78   if (!args)
79     {
80       /* Just close the XML containter.  */
81       _gpgme_data_append_string (dh, "</GnupgOperationInfo>\n");
82       return;
83     }
84
85   _gpgme_data_append_string (dh, "  <encryption>\n"
86                              "    <error>\n"
87                              "      <invalidRecipient/>\n");
88     
89   sprintf (helpbuf, "      <reason>%d</reason>\n", atoi (args));
90   _gpgme_data_append_string (dh, helpbuf);
91   SKIP_TOKEN_OR_RETURN (args);
92
93   _gpgme_data_append_string (dh, "      <name>");
94   _gpgme_data_append_percentstring_for_xml (dh, args);
95   _gpgme_data_append_string (dh, "</name>\n"
96                              "    </error>\n");
97 }
98
99
100 GpgmeError
101 _gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
102 {
103   test_and_allocate_result (ctx, encrypt);
104
105   switch (code)
106     {
107     case GPGME_STATUS_EOF:
108       if (ctx->result.encrypt->xmlinfo)
109         {
110           append_xml_encinfo (&ctx->result.encrypt->xmlinfo, NULL);
111           _gpgme_set_op_info (ctx, ctx->result.encrypt->xmlinfo);
112           ctx->result.encrypt->xmlinfo = NULL;
113         }
114       if (ctx->result.encrypt->no_valid_recipients) 
115         return GPGME_No_Recipients;
116       else if (ctx->result.encrypt->invalid_recipients) 
117         return GPGME_Invalid_Recipients;
118       break;
119
120     case GPGME_STATUS_INV_RECP:
121       ctx->result.encrypt->invalid_recipients++;
122       append_xml_encinfo (&ctx->result.encrypt->xmlinfo, args);
123       break;
124
125     case GPGME_STATUS_NO_RECP:
126       ctx->result.encrypt->no_valid_recipients = 1;
127       break;
128
129     default:
130       break;
131     }
132   return 0;
133 }
134
135
136 GpgmeError
137 _gpgme_encrypt_sym_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
138                                    char *args)
139 {
140   return _gpgme_passphrase_status_handler (ctx, code, args);
141 }
142
143
144 static GpgmeError
145 _gpgme_op_encrypt_start (GpgmeCtx ctx, int synchronous,
146                          GpgmeRecipients recp, GpgmeData plain, GpgmeData ciph)
147 {
148   GpgmeError err = 0;
149   int symmetric = 0;
150
151   /* Do some checks.  */
152   if (!recp)
153     symmetric = 1;
154   else if (!gpgme_recipients_count (recp))
155     {
156       err = GPGME_No_Recipients;
157       goto leave;
158     }
159
160   err = _gpgme_op_reset (ctx, synchronous);
161   if (err)
162     goto leave;
163
164   if (symmetric)
165     {
166       err = _gpgme_passphrase_start (ctx);
167       if (err)
168         goto leave;
169     }
170
171   _gpgme_engine_set_status_handler (ctx->engine,
172                                     symmetric
173                                     ? _gpgme_encrypt_sym_status_handler
174                                     : _gpgme_encrypt_status_handler,
175                                     ctx);
176   _gpgme_engine_set_verbosity (ctx->engine, ctx->verbosity);
177
178   /* Check the supplied data */
179   if (!plain)
180     {
181       err = GPGME_No_Data;
182       goto leave;
183     }
184   if (!ciph)
185     {
186       err = GPGME_Invalid_Value;
187       goto leave;
188     }
189
190   err = _gpgme_engine_op_encrypt (ctx->engine, recp, plain, ciph,
191                                   ctx->use_armor);
192
193  leave:
194   if (err)
195     {
196       ctx->pending = 0; 
197       _gpgme_engine_release (ctx->engine);
198       ctx->engine = NULL;
199     }
200   return err;
201 }
202
203
204 GpgmeError
205 gpgme_op_encrypt_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData plain,
206                         GpgmeData ciph)
207 {
208   return _gpgme_op_encrypt_start (ctx, 0, recp, plain, ciph);
209 }
210
211
212 /**
213  * gpgme_op_encrypt:
214  * @c: The context
215  * @recp: A set of recipients 
216  * @in: plaintext input
217  * @out: ciphertext output
218  * 
219  * This function encrypts @in to @out for all recipients from
220  * @recp.  Other parameters are take from the context @c.
221  * The function does wait for the result.
222  * 
223  * Return value:  0 on success or an errorcode. 
224  **/
225 GpgmeError
226 gpgme_op_encrypt (GpgmeCtx ctx, GpgmeRecipients recp,
227                   GpgmeData plain, GpgmeData cipher)
228 {
229   int err = _gpgme_op_encrypt_start (ctx, 1, recp, plain, cipher);
230   if (!err)
231     err = _gpgme_wait_one (ctx);
232   return err;
233 }