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

Annotation of /trunk/MyGPGME/decrypt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (hide annotations)
Mon Apr 4 07:01:43 2005 UTC (19 years, 11 months ago) by twoaday
File MIME type: text/plain
File size: 19065 byte(s)
2005-03-22  Timo Schulz  <twoaday@freakmail.de>
                                                                                
        * editcard.c: Support new status-fd entries SC_OP_SUCCESS
        and SC_OP_FAILURE.
        * editkey.c (cmd_addrev_handler): Check if context != NULL.
        * import.c (import_command_handler): Wrong function signature.
        Noted by Kurt Fitzner.
        * types.h: Fixed encrypt_result_s. Noted by Kurt.
        * gpgme.h (gpgme_editkey_addrev_set): Changed return type.
        Kudos to Kurt.
        * key.c: Removed some unreachable code. By Kurt.
                                                                                


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26