Added sign functionality
[gpgme.git] / gpgme / decrypt.c
1 /* decrypt.c -  decrypt functions
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *
4  * This file is part of GPGME.
5  *
6  * GPGME is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GPGME is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26
27 #include "util.h"
28 #include "context.h"
29 #include "ops.h"
30
31
32 struct decrypt_result_s {
33     int no_passphrase;
34     int okay;
35     int failed;
36 };
37
38
39 void
40 _gpgme_release_decrypt_result ( DecryptResult res )
41 {
42     xfree (res);
43 }
44
45
46
47 static void
48 decrypt_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
49 {
50     if ( ctx->out_of_core )
51         return;
52     if ( ctx->result_type == RESULT_TYPE_NONE ) {
53         assert ( !ctx->result.decrypt );
54         ctx->result.decrypt = xtrycalloc ( 1, sizeof *ctx->result.decrypt );
55         if ( !ctx->result.decrypt ) {
56             ctx->out_of_core = 1;
57             return;
58         }
59         ctx->result_type = RESULT_TYPE_DECRYPT;
60     }
61     assert ( ctx->result_type == RESULT_TYPE_DECRYPT );
62
63     switch (code) {
64       case STATUS_EOF:
65         break;
66
67       case STATUS_NEED_PASSPHRASE:
68       case STATUS_NEED_PASSPHRASE_SYM:
69         fprintf (stderr, "Ooops: Need a passphrase -  use the agent\n");
70         break;
71
72       case STATUS_MISSING_PASSPHRASE:
73         fprintf (stderr, "Missing passphrase - stop\n");;
74         ctx->result.decrypt->no_passphrase = 1;
75         break;
76
77       case STATUS_DECRYPTION_OKAY:
78         ctx->result.decrypt->okay = 1;
79         break;
80
81       case STATUS_DECRYPTION_FAILED:
82         ctx->result.decrypt->failed = 1;
83         break;
84         
85
86       default:
87         /* ignore all other codes */
88         fprintf (stderr, "decrypt_status: code=%d not handled\n", code );
89         break;
90     }
91 }
92
93
94
95 GpgmeError
96 gpgme_op_decrypt_start ( GpgmeCtx c, GpgmeData ciph, GpgmeData plain )
97 {
98     int rc = 0;
99     int i;
100
101     fail_on_pending_request( c );
102     c->pending = 1;
103
104     _gpgme_release_result (c);
105     c->out_of_core = 0;
106
107     /* do some checks */
108     assert ( !c->gpg );
109         
110     /* create a process object */
111     rc = _gpgme_gpg_new ( &c->gpg );
112     if (rc)
113         goto leave;
114
115     _gpgme_gpg_set_status_handler ( c->gpg, decrypt_status_handler, c );
116
117     /* build the commandline */
118     _gpgme_gpg_add_arg ( c->gpg, "--decrypt" );
119     for ( i=0; i < c->verbosity; i++ )
120         _gpgme_gpg_add_arg ( c->gpg, "--verbose" );
121     
122     /* Check the supplied data */
123     if ( !ciph || gpgme_data_get_type (ciph) == GPGME_DATA_TYPE_NONE ) {
124         rc = mk_error (No_Data);
125         goto leave;
126     }
127
128     _gpgme_data_set_mode (ciph, GPGME_DATA_MODE_OUT );
129     if ( gpgme_data_get_type (plain) != GPGME_DATA_TYPE_NONE ) {
130         rc = mk_error (Invalid_Value);
131         goto leave;
132     }
133     _gpgme_data_set_mode (plain, GPGME_DATA_MODE_IN );
134
135     /* Tell the gpg object about the data */
136     _gpgme_gpg_add_arg ( c->gpg, "--output" );
137     _gpgme_gpg_add_arg ( c->gpg, "-" );
138     _gpgme_gpg_add_data ( c->gpg, plain, 1 );
139     _gpgme_gpg_add_data ( c->gpg, ciph, 0 );
140
141     /* and kick off the process */
142     rc = _gpgme_gpg_spawn ( c->gpg, c );
143
144  leave:
145     if (rc) {
146         c->pending = 0; 
147         _gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
148     }
149     return rc;
150 }
151
152
153 /**
154  * gpgme_op_decrypt:
155  * @c: The context
156  * @in: ciphertext input
157  * @out: plaintext output
158  * 
159  * This function decrypts @in to @out.
160  * Other parameters are take from the context @c.
161  * The function does wait for the result.
162  * 
163  * Return value:  0 on success or an errorcode. 
164  **/
165 GpgmeError
166 gpgme_op_decrypt ( GpgmeCtx c, GpgmeData in, GpgmeData out )
167 {
168     GpgmeError err = gpgme_op_decrypt_start ( c, in, out );
169     if ( !err ) {
170         gpgme_wait (c, 1);
171         if ( c->result_type != RESULT_TYPE_DECRYPT )
172             err = mk_error (General_Error);
173         else if ( c->out_of_core )
174             err = mk_error (Out_Of_Core);
175         else {
176             assert ( c->result.decrypt );
177             if ( c->result.decrypt->no_passphrase ) 
178                 err = mk_error (No_Passphrase);
179             else if ( c->result.decrypt->failed ) 
180                 err = mk_error (Decryption_Failed);
181             else if (!c->result.decrypt->okay)
182                 err = mk_error (No_Data);
183         }
184         c->pending = 0;
185     }
186     return err;
187 }
188
189
190
191
192
193
194
195
196