Fix comment.
[gpgme.git] / gpgme / decrypt.c
1 /* decrypt.c - Decrypt function.
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 <stdlib.h>
25 #include <string.h>
26
27 #include "gpgme.h"
28 #include "util.h"
29 #include "context.h"
30 #include "ops.h"
31
32 \f
33 typedef struct
34 {
35   struct _gpgme_op_decrypt_result result;
36
37   int okay;
38   int failed;
39 } *op_data_t;
40
41
42 static void
43 release_op_data (void *hook)
44 {
45   op_data_t opd = (op_data_t) hook;
46
47   if (opd->result.unsupported_algorithm)
48     free (opd->result.unsupported_algorithm);
49 }
50
51
52 gpgme_decrypt_result_t
53 gpgme_op_decrypt_result (gpgme_ctx_t ctx)
54 {
55   void *hook;
56   op_data_t opd;
57   gpgme_error_t err;
58
59   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
60   opd = hook;
61   if (err || !opd)
62     return NULL;
63
64   return &opd->result;
65 }
66
67 \f
68 gpgme_error_t
69 _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
70                                char *args)
71 {
72   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
73   gpgme_error_t err;
74   void *hook;
75   op_data_t opd;
76
77   err = _gpgme_passphrase_status_handler (priv, code, args);
78   if (err)
79     return err;
80
81   err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
82   opd = hook;
83   if (err)
84     return err;
85
86   switch (code)
87     {
88     case GPGME_STATUS_EOF:
89       if (opd->failed)
90         return GPGME_Decryption_Failed;
91       else if (!opd->okay)
92         return GPGME_No_Data;
93       break;
94
95     case GPGME_STATUS_DECRYPTION_OKAY:
96       opd->okay = 1;
97       break;
98
99     case GPGME_STATUS_DECRYPTION_FAILED:
100       opd->failed = 1;
101       break;
102
103     case GPGME_STATUS_ERROR:
104       {
105         const char d_alg[] = "decrypt.algorithm";
106         const char u_alg[] = "Unsupported_Algorithm";
107         if (!strncmp (args, d_alg, sizeof (d_alg) - 1))
108           {
109             args += sizeof (d_alg);
110             while (*args == ' ')
111               args++;
112
113             if (!strncmp (args, u_alg, sizeof (u_alg) - 1))
114               {
115                 char *end;
116
117                 args += sizeof (u_alg);
118                 while (*args == ' ')
119                   args++;
120
121                 end = strchr (args, ' ');
122                 if (end)
123                   *end = '\0';
124
125                 if (!(*args == '?' && *(args + 1) == '\0'))
126                   {
127                     opd->result.unsupported_algorithm = strdup (args);
128                     if (!opd->result.unsupported_algorithm)
129                       return GPGME_Out_Of_Core;
130                   }
131               }
132           }
133       }
134       break;
135         
136     default:
137       break;
138     }
139
140   return 0;
141 }
142
143
144 static gpgme_error_t
145 decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
146 {
147   return _gpgme_progress_status_handler (priv, code, args)
148     || _gpgme_decrypt_status_handler (priv, code, args);
149 }
150
151
152 gpgme_error_t
153 _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx)
154 {
155   void *hook;
156   op_data_t opd;
157
158   return _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook,
159                                 sizeof (*opd), release_op_data);
160 }
161
162
163 static gpgme_error_t
164 decrypt_start (gpgme_ctx_t ctx, int synchronous,
165                       gpgme_data_t cipher, gpgme_data_t plain)
166 {
167   gpgme_error_t err;
168
169   err = _gpgme_op_reset (ctx, synchronous);
170   if (err)
171     return err;
172
173   err = _gpgme_op_decrypt_init_result (ctx);
174   if (err)
175     return err;
176
177   if (!cipher)
178     return GPGME_No_Data;
179   if (!plain)
180     return GPGME_Invalid_Value;
181
182   if (err)
183     return err;
184
185   if (ctx->passphrase_cb)
186     {
187       err = _gpgme_engine_set_command_handler
188         (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
189       if (err)
190         return err;
191     }
192
193   _gpgme_engine_set_status_handler (ctx->engine, decrypt_status_handler, ctx);
194
195   return _gpgme_engine_op_decrypt (ctx->engine, cipher, plain);
196 }
197
198
199 gpgme_error_t
200 gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
201                         gpgme_data_t plain)
202 {
203   return decrypt_start (ctx, 0, cipher, plain);
204 }
205
206
207 /* Decrypt ciphertext CIPHER within CTX and store the resulting
208    plaintext in PLAIN.  */
209 gpgme_error_t
210 gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
211 {
212   gpgme_error_t err = decrypt_start (ctx, 1, cipher, plain);
213   if (!err)
214     err = _gpgme_wait_one (ctx);
215   return err;
216 }