/[winpt]/trunk/MyGPGME/decrypt.c
ViewVC logotype

Contents of /trunk/MyGPGME/decrypt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 21 - (show annotations)
Wed Jul 27 11:17:44 2005 UTC (19 years, 7 months ago) by twoaday
File MIME type: text/plain
File size: 19777 byte(s)
2005-07-22  Timo Schulz  <twoaday@freakmail.de>
 
        * gpgme.c (_gpgme_add_comment): Forgot to alloc an extra
        byte for the '0'. This fixes a lot of crashes related to
        file operations.
        * keylist.c (gpgme_op_keylist_getkey): Use the param for
        'pub' or 'sec' mode.
        * keycache.c (gpgme_keycache_update_key): If the key is
        not in the cache, add it and if the cache contain secret
        key, sync it with the pub cache.
        * editkey.c (edit_key_colon_handler): Allocate 1 byte for
        the NUL-char.  This also fixes a lot of reported crashes
        related to the showpref feature.
 


1 /* decrypt.c - decrypt functions
2 * Copyright (C) 2000 Werner Koch (dd9jn)
3 * Copyright (C) 2001-2005 Timo Schulz
4 *
5 * This file is part of MyGPGME.
6 *
7 * MyGPGME 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 * MyGPGME 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 <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <windows.h>
27
28 #include "util.h"
29 #include "context.h"
30 #include "ops.h"
31
32 struct decrypt_result_s {
33 gpgme_sig_t sig;
34 int no_data;
35 int no_seckey;
36 int no_passphrase;
37 int idea_cipher;
38 int okay;
39 int sig_okay;
40 int failed;
41 int bad_mdc;
42 int bad_armor;
43 int bad_passphrase;
44 int key_algo;
45 int file_start;
46 int file_done;
47 char keyid[16+1];
48 char cardno[32+1];
49 void *last_pw_handle;
50 char *userid_hint;
51 char *passphrase_info;
52 char *file_name;
53 struct {
54 int mode;
55 long times;
56 char *name;
57 } plain;
58 };
59
60
61 void
62 gpgme_decrypt_get_sig_ctx (gpgme_ctx_t ctx, gpgme_sig_t * r_sig)
63 {
64 if (!ctx)
65 return;
66 if (r_sig)
67 *r_sig = NULL;
68 if (ctx && ctx->result.decrypt->sig) {
69 _gpgme_sig_ref (ctx->result.decrypt->sig);
70 if (r_sig)
71 *r_sig = ctx->result.decrypt->sig;
72 }
73 } /* gpgme_decrypt_get_sig_ctx */
74
75
76 void
77 gpgme_decrypt_get_status (gpgme_ctx_t ctx, char * keyid,
78 gpgme_op_flags_t * r_flags)
79 {
80 gpgme_op_flags_t flags = 0;
81 _decrypt_result_t res;
82
83 if (!keyid)
84 return;
85 if (ctx->result_type != RESULT_TYPE_DECRYPT)
86 return;
87 if (!ctx->result.decrypt->okay
88 && ctx->result.decrypt->no_seckey) {
89 strcpy (keyid, ctx->result.decrypt->keyid);
90 flags |= GPGME_OPFLAG_NOSECKEY;
91 }
92 res = ctx->result.decrypt;
93 if (res->bad_armor)
94 flags |= GPGME_OPFLAG_BADARMOR;
95 if (res->bad_mdc)
96 flags |= GPGME_OPFLAG_BADMDC;
97 if (r_flags)
98 *r_flags = flags;
99 } /* gpgme_decrypt_get_status */
100
101
102 void
103 _gpgme_release_decrypt_result( _decrypt_result_t res )
104 {
105 if( res ) {
106 safe_free (res->passphrase_info);
107 safe_free (res->userid_hint);
108 safe_free (res->file_name);
109 safe_free (res->plain.name);
110 gpgme_sig_release(res->sig);
111 safe_free (res);
112 }
113 } /* _gpgme_release_decrypt_result */
114
115
116 static gpgme_error_t
117 create_result_struct (gpgme_ctx_t ctx)
118 {
119 assert( !ctx->result.decrypt );
120 ctx->result.decrypt = calloc( 1, sizeof * ctx->result.decrypt );
121 if( !ctx->result.decrypt )
122 return mk_error( Out_Of_Core );
123 ctx->result_type = RESULT_TYPE_DECRYPT;
124 return 0;
125 } /* create_result_struct */
126
127
128 static void
129 list_status_handler( gpgme_ctx_t ctx, gpg_status_code_t code, char * args )
130 {
131 char keyid[32] = {0};
132
133 if (ctx->out_of_core)
134 return;
135 if (code == STATUS_ENC_TO) {
136 keyid[0] = (char)atol (args+17);
137 strncpy (keyid+1, args, 16);
138 gpgme_recipients_add_name (ctx->enc_to, keyid);
139 }
140 } /* list_status_handler */
141
142
143 static gpgme_sig_t
144 add_signature( gpgme_ctx_t ctx )
145 {
146 gpgme_sig_t sig, s;
147 gpgme_error_t err;
148
149 err = gpgme_sig_new( &sig );
150 if( err ) {
151 ctx->out_of_core = 1;
152 return NULL;
153 }
154 if( ctx->result.decrypt->file_name ) {
155 sig->file_name = strdup( ctx->result.decrypt->file_name );
156 if( !sig->file_name ) {
157 ctx->out_of_core = 1;
158 safe_free( sig );
159 return NULL;
160 }
161 }
162 if( !ctx->result.decrypt->sig )
163 ctx->result.decrypt->sig = sig;
164 else {
165 for( s = ctx->result.decrypt->sig; s->next; s=s->next )
166 ;
167 s->next = sig;
168 }
169 return sig;
170 } /* add_signature */
171
172
173 static void
174 decrypt_status_handler (gpgme_ctx_t ctx, gpg_status_code_t code, char *args)
175 {
176 static gpgme_sig_t sig = NULL;
177 static char keyid[16+1];
178 char *p = NULL, fpr[40+1];
179 int i = 0, j=0;
180 char ch = 0;
181
182 if (ctx->out_of_core)
183 return;
184
185 if (ctx->result_type == RESULT_TYPE_NONE) {
186 if (create_result_struct (ctx)) {
187 ctx->out_of_core = 1;
188 return;
189 }
190 }
191
192 assert (ctx->result_type == RESULT_TYPE_DECRYPT);
193
194 if (code == STATUS_GOODSIG || code == STATUS_REVKEYSIG
195 || code == STATUS_EXPKEYSIG || code == STATUS_BADSIG
196 || code == STATUS_ERRSIG) {
197 sig = add_signature (ctx);
198 if (!sig || ctx->out_of_core)
199 return;
200 }
201
202 _gpgme_nodata_status_handler (code, args, &ctx->result.decrypt->no_data);
203 _gpgme_pass_status_handler (code, args, &ctx->result.decrypt->bad_passphrase,
204 &ctx->result.decrypt->no_data,
205 &ctx->result.decrypt->passphrase_info);
206 if (sig && (code >= STATUS_TRUST_UNDEFINED && code <= STATUS_TRUST_ULTIMATE)) {
207 _gpgme_sigtrust_status_handler (code, args, &sig->trust);
208 DEBUG1("sig_trust: %d", sig->trust);
209 }
210
211 switch (code) {
212 case STATUS_EOF:
213 break;
214
215 case STATUS_USERID_HINT:
216 safe_free (ctx->result.decrypt->userid_hint);
217 p = ctx->result.decrypt->userid_hint = strdup (args);
218 if (!p) {
219 ctx->out_of_core = 1;
220 return;
221 }
222 break;
223
224 case STATUS_DECRYPTION_OKAY:
225 ctx->result.decrypt->okay = 1;
226 break;
227
228 case STATUS_DECRYPTION_FAILED:
229 ctx->result.decrypt->failed = 1;
230 break;
231
232 case STATUS_RSA_OR_IDEA:
233 ctx->result.decrypt->idea_cipher = 1;
234 break;
235
236 case STATUS_SIG_ID:
237 DEBUG0 ("Plaintext was signed!\n");
238 break;
239
240 case STATUS_NO_SECKEY:
241 ctx->result.decrypt->no_seckey++;
242 strncpy (ctx->result.decrypt->keyid, args, 16);
243 break;
244
245 case STATUS_NO_PUBKEY:
246 sig->sigstat = GPGME_SIG_STAT_NOKEY;
247 break;
248
249 case STATUS_PLAINTEXT:
250 i=0;
251 while (args[i] && args[i] == ' ')
252 i++;
253 ctx->result.decrypt->plain.mode = strtoul (args+i, NULL, 10);
254 while (args[i] && args[i] != ' ')
255 i++;
256 i++;
257 ctx->result.decrypt->plain.times = strtoul (args+i, NULL, 10);
258 while (args[i] && args[i] != ' ')
259 i++;
260 i++;
261 safe_free (ctx->result.decrypt->plain.name);
262 if (args[i]) {
263 p = ctx->result.decrypt->plain.name = strdup (args+i);
264 if (!p)
265 ctx->out_of_core = 1;
266 }
267 break;
268
269 case STATUS_VALIDSIG:
270 p = fpr;
271 for( i = 0; i < DIM(fpr) && args[i] && args[i] != ' ' ; i++ )
272 *p++ = args[i];
273 *p = 0;
274 /* skip the formatted date */
275 while ( args[i] && args[i] == ' ')
276 i++;
277 while ( args[i] && args[i] != ' ')
278 i++;
279 /* and get the timestamp */
280 sig->created = strtoul( args + i, NULL, 10 );
281 ctx->result.decrypt->sig_okay = 1;
282 break;
283
284 case STATUS_GOODSIG:
285 case STATUS_BADSIG:
286 if (code == STATUS_GOODSIG)
287 sig->sigstat = GPGME_SIG_STAT_GOOD;
288 else
289 sig->sigstat = GPGME_SIG_STAT_BAD;
290 strncpy( sig->id, args, 16 );
291 sig->user_id = p = calloc (1, strlen (args + 16) + 2);
292 if (!p)
293 {
294 ctx->out_of_core = 1;
295 return;
296 }
297 strcpy (p, args + 16);
298 break;
299
300 case STATUS_EXPKEYSIG:
301 case STATUS_REVKEYSIG:
302 if( code == STATUS_EXPKEYSIG )
303 sig->sigstat = GPGME_SIG_STAT_E_GOOD;
304 else if( code == STATUS_REVKEYSIG )
305 sig->sigstat = GPGME_SIG_STAT_R_GOOD;
306 for( i=0, p=sig->id; args[i] && args[i] != ' '; i++ )
307 *p++ = args[i];
308 *p = '\0';
309 p = sig->user_id = calloc( 1, strlen( args+i ) + 2 );
310 if( !p ) {
311 ctx->out_of_core = 1;
312 return;
313 }
314 j=0;
315 while (args[i])
316 p[j++] = args[i++];
317 p[j++] = '\0';
318 break;
319
320 case STATUS_ERRSIG:
321 sig->sigstat = GPGME_SIG_STAT_ERROR;
322 break;
323
324 case STATUS_BADMDC:
325 ctx->result.decrypt->bad_mdc = 1;
326 break;
327
328 case STATUS_BADARMOR:
329 ctx->result.decrypt->bad_armor = 1;
330 break;
331
332 case STATUS_FILE_START:
333 if (*args == '3') {
334 safe_free (ctx->result.decrypt->file_name);
335 p = ctx->result.decrypt->file_name = strdup (args+2);
336 if (!p) {
337 ctx->out_of_core = 1;
338 return;
339 }
340 }
341 ctx->result.decrypt->file_start++;
342 if (ctx->cb.interactiv)
343 ctx->cb.interactiv (ctx->cb.interactiv_value, code, NULL, args+2);
344 break;
345
346 case STATUS_FILE_DONE:
347 ctx->result.decrypt->file_done++;
348 if (ctx->cb.interactiv)
349 ctx->cb.interactiv (ctx->cb.interactiv_value, code, NULL, NULL);
350 break;
351
352 case STATUS_CARDCTRL:
353 ch = args[i++];
354 if (ch == '4') {
355 ctx->result.decrypt->no_seckey = -1;
356 break;
357 }
358 if (ch != '3')
359 break;
360 i++;
361 p = ctx->result.decrypt->cardno;
362 for (; i-1 < DIM (ctx->result.decrypt->cardno) && args[i]; i++)
363 *p++ = args[i];
364 *p = 0;
365 break;
366
367 default:
368 break; /* ignore all other codes */
369 }
370 } /* decrypt_status_handler */
371
372
373 static const char *
374 decrypt_command_handler (void * opaque, gpg_status_code_t code, const char * key)
375 {
376 gpgme_ctx_t c = opaque;
377
378 if (!code) {
379 /* We have been called for cleanup */
380 if (c->cb.passphrase) {
381 c->cb.passphrase (c->cb.passphrase_value, NULL,
382 &c->result.decrypt->last_pw_handle);
383 }
384 return NULL;
385 }
386
387 if (!key || !c->cb.passphrase)
388 return NULL;
389
390 if (c->result_type == RESULT_TYPE_NONE) {
391 if (create_result_struct (c)) {
392 c->out_of_core = 1;
393 return NULL;
394 }
395 }
396
397 if( code == STATUS_GET_HIDDEN
398 && (!strcmp( key, "passphrase.enter" )
399 || !strcmp( key, "passphrase.pin.ask" )) ) {
400 const char * userid_hint = c->result.decrypt->userid_hint;
401 const char * passphrase_info = c->result.decrypt->passphrase_info;
402 const char * cardno = c->result.decrypt->cardno;
403 int bad_passphrase = c->result.decrypt->bad_passphrase;
404 int is_card=0;
405 char * buf;
406 const char *s;
407
408 c->result.decrypt->bad_passphrase = 0;
409 is_card = !strcmp (key, "passphrase.pin.ask");
410 if (!userid_hint)
411 userid_hint = "[User ID hint missing]";
412 if (!passphrase_info)
413 passphrase_info = "[passphrase info missing]";
414 buf = malloc (20 + strlen (userid_hint)
415 + strlen (passphrase_info) + 3);
416 if( !buf ) {
417 c->out_of_core = 1;
418 return NULL;
419 }
420 sprintf (buf, "%s\n%s\n%s", bad_passphrase? "TRY_AGAIN":"ENTER_PASSPHRASE",
421 userid_hint, passphrase_info);
422 s = c->cb.passphrase (c->cb.passphrase_value, is_card? cardno : buf,
423 &c->result.decrypt->last_pw_handle);
424 safe_free (buf);
425 return s;
426 }
427 else if( (code == STATUS_GET_BOOL
428 && !strcmp( key, "openfile.overwrite.okay" ))
429 || (code == STATUS_GET_LINE && !strcmp( key, "openfile.askoutname" )) )
430 if (c->cb.interactiv)
431 return c->cb.interactiv( c->cb.interactiv_value, code, key, NULL );
432
433 return NULL;
434 } /* decrypt_command_handler */
435
436
437 static gpgme_error_t
438 list_keys_start( gpgme_ctx_t ctx, gpgme_data_t ciph, const char * file,
439 gpgme_recipients_t * r_keys )
440 {
441 gpgme_error_t rc;
442 gpgme_recipients_t keys;
443 FILE * fp;
444 const char * s;
445 char * p;
446
447 if (!r_keys)
448 return mk_error (Invalid_Value);
449 if (ciph && file || !ciph && !file)
450 return mk_error (Invalid_Mode);
451
452 *r_keys = NULL;
453 fail_on_pending_request( ctx );
454 ctx->pending = 1;
455
456 _gpgme_gpg_release( &ctx->gpg );
457 rc = _gpgme_gpg_new( &ctx->gpg );
458 if( rc )
459 return rc;
460
461 if( ciph ) {
462 p = _gpgme_data_get_as_string( ciph );
463 if( !p )
464 return mk_error( Out_Of_Core );
465
466 s = _gpgme_get_tmpfile( 0 );
467 fp = fopen( s, "wb" );
468 if( !fp ) {
469 safe_free( p );
470 return mk_error( File_Error );
471 }
472 fwrite (p, 1, strlen (p), fp);
473 fclose (fp);
474 safe_free (p);
475 }
476 else
477 s = file;
478
479 rc = gpgme_recipients_new( &keys );
480 if( rc )
481 return rc;
482 ctx->enc_to = keys;
483
484 _gpgme_gpg_set_status_handler( ctx->gpg, list_status_handler, ctx );
485 _gpgme_gpg_add_arg( ctx->gpg, "--list-only" );
486 _gpgme_gpg_add_arg( ctx->gpg, s );
487
488 rc = _gpgme_gpg_spawn( ctx->gpg, ctx );
489 if( rc ) {
490 ctx->pending = 0;
491 _gpgme_gpg_release( &ctx->gpg );
492 gpgme_recipients_release( keys ); keys = NULL;
493 }
494 *r_keys = keys;
495 return rc;
496 } /* list_keys_start */
497
498
499 /* It either works with a file or a data object but not with both! */
500 gpgme_error_t
501 gpgme_op_list_keys( gpgme_data_t ciph, const char * file,
502 gpgme_recipients_t * r_rset )
503 {
504 gpgme_ctx_t ctx = NULL;
505 gpgme_error_t err;
506
507 if( !r_rset )
508 return mk_error (Invalid_Value);
509 *r_rset = NULL;
510 err = gpgme_new( &ctx );
511 if( !err )
512 err = list_keys_start( ctx, ciph, file, r_rset );
513 if( !err ) {
514 gpgme_wait( ctx, 1 );
515 ctx->pending = 0;
516 }
517 gpgme_release( ctx );
518 return err;
519 } /* gpgme_op_list_keys */
520
521
522 static gpgme_error_t
523 file_decrypt_start( gpgme_ctx_t ctx, const char ** input, size_t nfiles,
524 const char * output )
525 {
526 gpgme_error_t rc;
527
528 if( !input )
529 return mk_error( Invalid_Value );
530
531 fail_on_pending_request( ctx );
532 ctx->pending = 1;
533
534 _gpgme_gpg_release( &ctx->gpg );
535 rc = _gpgme_gpg_new( &ctx->gpg );
536 if( rc )
537 return rc;
538
539 _gpgme_gpg_set_status_handler( ctx->gpg, decrypt_status_handler, ctx );
540 if( !ctx->use_pass_fd )
541 _gpgme_gpg_set_command_handler( ctx->gpg, decrypt_command_handler, ctx );
542 else {
543 rc = _gpgme_add_passphrase( ctx );
544 if( rc ) {
545 _gpgme_gpg_release( &ctx->gpg );
546 return rc;
547 }
548 }
549
550 if( !ctx->cb.interactiv )
551 _gpgme_gpg_add_arg( ctx->gpg, "--yes" );
552 if( nfiles > 1 || !output )
553 _gpgme_gpg_add_arg( ctx->gpg, "--no-mangle-dos-filenames" );
554 if( ctx->pipemode || nfiles > 1 )
555 _gpgme_gpg_add_arg( ctx->gpg, "--decrypt-files" );
556 else
557 _gpgme_gpg_add_arg( ctx->gpg, "--decrypt" );
558
559 /* cannot use --output with --decrypt-files */
560 if( nfiles == 1 && !ctx->pipemode && output ) {
561 _gpgme_gpg_add_arg( ctx->gpg, "--output" );
562 _gpgme_gpg_add_arg( ctx->gpg, output );
563 }
564
565 while( nfiles-- )
566 _gpgme_gpg_add_arg( ctx->gpg, *input++ );
567
568 rc = _gpgme_gpg_spawn( ctx->gpg, ctx );
569 if( rc ) {
570 ctx->pending = 0;
571 _gpgme_gpg_release( &ctx->gpg );
572 }
573
574 return rc;
575 } /* file_decrypt_start */
576
577
578 static gpgme_error_t
579 decrypt_start( gpgme_ctx_t ctx, gpgme_data_t ciph, gpgme_data_t plain )
580 {
581 int rc = 0;
582
583 fail_on_pending_request (ctx);
584 ctx->pending = 1;
585
586 _gpgme_release_result (ctx);
587 ctx->out_of_core = 0;
588
589 /* create a process object */
590 _gpgme_gpg_release( &ctx->gpg );
591 rc = _gpgme_gpg_new( &ctx->gpg );
592 if( rc )
593 goto leave;
594
595 _gpgme_gpg_set_status_handler( ctx->gpg, decrypt_status_handler, ctx );
596 if( ctx->use_logging )
597 _gpgme_gpg_set_logging_handler( ctx->gpg, ctx );
598 if( ctx->cb.passphrase ) {
599 rc = _gpgme_gpg_set_command_handler( ctx->gpg, decrypt_command_handler, ctx );
600 if ( rc )
601 goto leave;
602 }
603 else if( ctx->passphrase_value ) {
604 rc = _gpgme_add_passphrase( ctx );
605 if( rc )
606 goto leave;
607 }
608
609 /* build the commandline */
610 _gpgme_gpg_add_arg( ctx->gpg, "--decrypt" );
611 /* Check the supplied data */
612 if( !ciph || gpgme_data_get_type( ciph ) == GPGME_DATA_TYPE_NONE ) {
613 rc = mk_error( No_Data );
614 goto leave;
615 }
616 _gpgme_data_set_mode( ciph, GPGME_DATA_MODE_OUT );
617 if( gpgme_data_get_type( plain ) != GPGME_DATA_TYPE_NONE ) {
618 rc = mk_error( Invalid_Value );
619 goto leave;
620 }
621 _gpgme_data_set_mode( plain, GPGME_DATA_MODE_IN );
622
623 /* Tell the gpg object about the data */
624 _gpgme_gpg_add_arg ( ctx->gpg, "--output" );
625 _gpgme_gpg_add_arg ( ctx->gpg, "-" );
626 _gpgme_gpg_add_data( ctx->gpg, plain, 1 );
627 _gpgme_gpg_add_data( ctx->gpg, ciph, 0 );
628
629 /* and kick off the process */
630 rc = _gpgme_gpg_spawn( ctx->gpg, ctx );
631
632 leave:
633 if( rc ) {
634 ctx->pending = 0;
635 _gpgme_gpg_release( &ctx->gpg );
636 }
637 return rc;
638 } /* decrypt_start */
639
640
641 static gpgme_error_t
642 get_decrypt_result( gpgme_ctx_t ctx )
643 {
644 gpgme_error_t err;
645 struct decrypt_result_s * res;
646
647 assert( ctx->result.decrypt );
648 res = ctx->result.decrypt;
649 if( ctx->result_type != RESULT_TYPE_DECRYPT )
650 err = mk_error( General_Error );
651 else if (res->okay || res->sig_okay)
652 err = 0;
653 else if( ctx->out_of_core )
654 err = mk_error( Out_Of_Core );
655 else if( res->no_passphrase )
656 err = mk_error( No_Passphrase );
657 else if( res->bad_passphrase )
658 err = mk_error( Bad_Passphrase );
659 else if( res->no_seckey)
660 err = mk_error( No_Seckey );
661 else if( res->idea_cipher )
662 err = mk_error( Cipher_IDEA );
663 else if( res->failed || (res->file_start != res->file_done) )
664 err = mk_error( Decryption_Failed );
665 else if( !res->okay || !res->no_data )
666 err = mk_error( No_Data );
667 else if( gpgme_get_process_rc( ctx ) )
668 err = mk_error( Internal_GPG_Problem );
669 return err;
670 } /* get_decrypt_result */
671
672
673 /**
674 * gpgme_op_decrypt:
675 * @c: The context
676 * @ciph: ciphertext input
677 * @plain: plaintext output
678 *
679 * This function decrypts @in to @out.
680 * Other parameters are take from the context @c.
681 * The function does wait for the result.
682 *
683 * Return value: 0 on success or an errorcode.
684 **/
685 gpgme_error_t
686 gpgme_op_decrypt( gpgme_ctx_t ctx, gpgme_data_t ciph, gpgme_data_t plain )
687
688 {
689 gpgme_error_t err;
690
691 err = decrypt_start( ctx, ciph, plain );
692 if( !err ) {
693 gpgme_wait( ctx, 1 );
694 ctx->pending = 0;
695 err = get_decrypt_result( ctx );
696 }
697 return err;
698 } /* gpgme_op_decrypt */
699
700
701 gpgme_error_t
702 gpgme_op_file_decrypt( gpgme_ctx_t ctx, const char * ciph, const char * plain )
703 {
704 gpgme_error_t err;
705 const char * files[1];
706
707 files[0] = ciph;
708
709 err = file_decrypt_start( ctx, files, 1, plain );
710 if( !err ) {
711 gpgme_wait( ctx, 1 );
712 err = get_decrypt_result( ctx );
713 ctx->pending = 0;
714 }
715 return err;
716 } /* gpgme_op_file_decrypt */
717
718
719 gpgme_error_t
720 gpgme_op_files_decrypt( gpgme_ctx_t ctx, const char ** files, size_t nfiles )
721 {
722 gpgme_error_t err;
723
724 err = file_decrypt_start( ctx, files, nfiles, NULL );
725 if( !err ) {
726 gpgme_wait( ctx, 1 );
727 err = get_decrypt_result( ctx );
728 ctx->pending = 0;
729 }
730 return err;
731 }
732
733
734 gpgme_error_t
735 gpgme_op_clip_decrypt( gpgme_ctx_t ctx )
736 {
737 gpgme_error_t err;
738 gpgme_data_t ciph = NULL;
739 gpgme_data_t plain = NULL;
740
741 err = gpgme_data_new_from_clipboard (&ciph);
742 if( !err )
743 err = gpgme_data_new( &plain );
744 if( !err )
745 err = gpgme_op_decrypt( ctx, ciph, plain );
746
747 gpgme_data_release_and_set_clipboard( plain );
748 gpgme_data_release( ciph );
749
750 return err;
751 } /* gpgme_op_clip_decrypt */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26