2002-02-02 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / decrypt.c
1 /* decrypt.c -  decrypt functions
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *      Copyright (C) 2001 g10 Code GmbH
4  *
5  * This file is part of GPGME.
6  *
7  * GPGME is free software; you can redistribute it and/or modify
8  * it 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,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #include "util.h"
29 #include "context.h"
30 #include "ops.h"
31
32
33 struct decrypt_result_s
34 {
35   int okay;
36   int failed;
37 };
38
39
40 void
41 _gpgme_release_decrypt_result (DecryptResult result)
42 {
43   if (!result)
44     return;
45   xfree (result);
46 }
47
48
49 void
50 _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
51 {
52   _gpgme_passphrase_status_handler (ctx, code, args);
53
54   if (ctx->error)
55     return;
56   test_and_allocate_result (ctx, decrypt);
57
58   switch (code)
59     {
60     case STATUS_EOF:
61       if (ctx->result.decrypt->failed)
62         ctx->error = mk_error (Decryption_Failed);
63       else if (!ctx->result.decrypt->okay)
64         ctx->error = mk_error (No_Data);
65       break;
66
67     case STATUS_DECRYPTION_OKAY:
68       ctx->result.decrypt->okay = 1;
69       break;
70
71     case STATUS_DECRYPTION_FAILED:
72       ctx->result.decrypt->failed = 1;
73       break;
74         
75     default:
76       /* Ignore all other codes.  */
77       break;
78     }
79 }
80
81
82 GpgmeError
83 _gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain,
84                       void *status_handler)
85 {
86   GpgmeError err = 0;
87
88   fail_on_pending_request (ctx);
89   ctx->pending = 1;
90
91   _gpgme_release_result (ctx);
92
93   /* Create a process object.  */
94   _gpgme_engine_release (ctx->engine);
95   err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
96                            : GPGME_PROTOCOL_OpenPGP, &ctx->engine);
97   if (err)
98     goto leave;
99
100   /* Check the supplied data.  */
101   if (!ciph || gpgme_data_get_type (ciph) == GPGME_DATA_TYPE_NONE)
102     {
103       err = mk_error (No_Data);
104       goto leave;
105     }
106   _gpgme_data_set_mode (ciph, GPGME_DATA_MODE_OUT);
107
108   if (gpgme_data_get_type (plain) != GPGME_DATA_TYPE_NONE)
109     {
110       err = mk_error (Invalid_Value);
111       goto leave;
112     }
113   _gpgme_data_set_mode (plain, GPGME_DATA_MODE_IN);
114
115   err = _gpgme_passphrase_start (ctx);
116   if (err)
117     goto leave;
118
119   _gpgme_engine_set_status_handler (ctx->engine, status_handler, ctx);
120   _gpgme_engine_set_verbosity (ctx->engine, ctx->verbosity);
121
122   err = _gpgme_engine_op_decrypt (ctx->engine, ciph, plain);
123
124   if (!err)     /* And kick off the process.  */
125     err = _gpgme_engine_start (ctx->engine, ctx);
126
127  leave:
128   if (err)
129     {
130       ctx->pending = 0; 
131       _gpgme_engine_release (ctx->engine);
132       ctx->engine = NULL;
133     }
134   return err;
135 }
136
137
138 GpgmeError
139 gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain)
140 {
141   return _gpgme_decrypt_start (ctx, ciph, plain,
142                                _gpgme_decrypt_status_handler);
143 }
144
145
146 /**
147  * gpgme_op_decrypt:
148  * @ctx: The context
149  * @in: ciphertext input
150  * @out: plaintext output
151  * 
152  * This function decrypts @in to @out.
153  * Other parameters are take from the context @ctx.
154  * The function does wait for the result.
155  * 
156  * Return value:  0 on success or an errorcode. 
157  **/
158 GpgmeError
159 gpgme_op_decrypt (GpgmeCtx ctx, GpgmeData in, GpgmeData out)
160 {
161   GpgmeError err = gpgme_op_decrypt_start (ctx, in, out);
162   if (!err)
163     {
164       gpgme_wait (ctx, 1);
165       err = ctx->error;
166     }
167   return err;
168 }