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

Annotation of /trunk/MyGPGME/decrypt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 17 - (hide annotations)
Fri May 20 08:38:32 2005 UTC (19 years, 9 months ago) by twoaday
File MIME type: text/plain
File size: 19172 byte(s)
2005-05-20      Timo Schulz  <twoaday@freakmail.de>
 
        * gpgme.h: s/cliptype/pgptype. Suggested by Kurt Fitzner.
        s/CLIP/PGP. Likewise.
        * w32-io.c (_gpgme_io_select): Increment the right loop variable.
        Kudos to Kurt.
        * keylist.c (gpgme_op_keylist_getkey): New. Handy function to
        retrieve a single key.
        * verify.c (gpgme_get_sig_key): Use it here.
        * keycache.c (gpgme_keycache_update_key): Update a single key.
 


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26