/[winpt]/trunk/Src/wptFileManager.cpp
ViewVC logotype

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 36 - (hide annotations)
Thu Oct 27 15:25:13 2005 UTC (19 years, 4 months ago) by werner
File size: 44331 byte(s)
First set of changes to use autotools for building.
1 werner 36 /* wptFileManager.cpp - File Manager routines
2     * Copyright (C) 2001-2005 Timo Schulz
3     * Copyright (C) 2005 g10 Code GmbH
4     *
5     * This file is part of WinPT.
6     *
7     * WinPT is free software; you can redistribute it and/or
8     * modify it under the terms of the GNU General Public License
9     * as published by the Free Software Foundation; either version 2
10     * of the License, or (at your option) any later version.
11     *
12     * WinPT 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 GNU
15     * General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with WinPT; if not, write to the Free Software Foundation,
19     * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21     /* TODO:
22     * check_armor_type: we should check the whole file and not only the first line!
23     */
24    
25     #ifdef HAVE_CONFIG_H
26     #include <config.h>
27     #endif
28    
29     #include <sys/types.h>
30     #include <sys/types.h>
31     #include <windows.h>
32     #include <commdlg.h>
33     #include <io.h>
34    
35     #include "../resource.h"
36     #include "wptTypes.h"
37     #include "wptGPG.h"
38     #include "wptAgent.h"
39     #include "wptCommonCtl.h"
40     #include "wptContext.h"
41     #include "wptErrors.h"
42     #include "wptKeylist.h"
43     #include "wptFileManager.h"
44     #include "wptNLS.h"
45     #include "wptW32API.h"
46     #include "wptVersion.h"
47     #include "wptDlgs.h"
48     #include "wptZIP.h"
49     #include "wptUTF8.h"
50     #include "wptRegistry.h"
51     #include "wptImport.h"
52    
53     #include "openpgp.h"
54    
55     #define op_begin() SetCursor (LoadCursor (NULL, IDC_WAIT))
56     #define op_end() SetCursor (LoadCursor (NULL, IDC_ARROW))
57    
58     void progress_cleanup (progress_filter_s *pfx);
59     BOOL CALLBACK file_secdel_confirm_dlg_proc (HWND dlg, UINT msg,
60     WPARAM wparam, LPARAM lparam);
61     char* gpg_keylist_to_pattern (gpgme_key_t *rset, int n);
62     gpgme_error_t sym_passphrase_cb (void *hook, const char *hint, const char *pass_inf,
63     int prev_was_bad, int fd);
64    
65     /*-- wptFileVerifyDlg.cpp --*/
66     void file_verify_add_state (file_sig_ctx_t c);
67     void file_verify_use_event (void);
68     void file_verify_wait (void);
69    
70     static const char * mm_files[] = {".mov", ".avi", ".mpg", ".mpeg",
71     ".mp3", ".wav", ".mid", ".wma",
72     ".gif", ".jpg", ".png", ".jpeg", ".dib", 0};
73    
74    
75     /* Check if the drive given by @fname is a floppy disc.
76     Return value: 1 for success. */
77     static int
78     is_floppy_disc (const char * fname)
79     {
80     char drv[32] = {0};
81     int i=0;
82    
83     if (!strstr (fname, ":\\"))
84     return 0;
85    
86     while (fname && *fname && *fname != '\\')
87     drv[i++] = *fname++;
88     drv[i++] = '\\';
89     drv[i++] = '\0';
90     i = GetDriveType (drv);
91     if (i == DRIVE_REMOVABLE)
92     return -1;
93     return 0;
94     }
95    
96    
97     /* Ask the user to overwrite file @fname.
98     Return value: 0 for cancel. */
99     int
100     overwrite_file (const char *fname)
101     {
102     int id;
103    
104     if (file_exist_check (fname))
105     return -1;
106     id = log_box (_("File Manager"), MB_YESNO,
107     _("\"%s\" already exists.\n"
108     "Replace existing file?"), fname);
109     return id == IDNO ? 0 : -1;
110     }
111    
112    
113     /* Removes 'critical' attributes from the file @fname.
114     If @force is 1, the user is not asked for permission. */
115     static void
116     remove_crit_file_attrs (const char *fname, int force)
117     {
118     u32 f_attr;
119     int id;
120    
121     if (file_exist_check (fname))
122     return; /* Does not exist */
123    
124     f_attr = GetFileAttributes (fname);
125     if ((f_attr & FILE_ATTRIBUTE_READONLY) && force)
126     SetFileAttributes (fname, FILE_ATTRIBUTE_NORMAL);
127     else if (f_attr & FILE_ATTRIBUTE_READONLY) {
128     id = log_box (_("File Manager"), MB_YESNO,
129     _("\"%s\" has read-only attribute.\n"
130     "Set attribute to normal?"), fname);
131     if (id == IDYES)
132     SetFileAttributes (fname, FILE_ATTRIBUTE_NORMAL);
133     }
134     }
135    
136    
137     static int inline
138     is_directory (const char *fname)
139     {
140     return GetFileAttributes (fname) & FILE_ATTRIBUTE_DIRECTORY? 1 : 0;
141     }
142    
143    
144     static int inline
145     is_openpgp_ext (const char *name)
146     {
147     if (strstr (name, ".gpg") || strstr (name, ".asc")
148     || strstr (name, ".sig") || strstr (name, ".pgp"))
149     return -1;
150     return 0;
151     }
152    
153    
154     static int
155     is_multi_media (const char * name)
156     {
157     const char * val;
158     char * p;
159     int i;
160     int ans=0;
161    
162     i = get_reg_winpt_single (CFG_NOZIP_MMEDIA);
163     if (i == -1)
164     {
165     ans = msg_box (NULL, _("Multi-Media files are already compressed, GPG would compress\n"
166     "them anyway and this costs a lot of time.\n"
167     "It is possible to disable compression for these files.\n"
168     "Do you want to disable it?"),
169     _("File Manager"), MB_YESNO|MB_INFO);
170     set_reg_winpt_single (CFG_NOZIP_MMEDIA, ans == IDYES? 1 : 0);
171     if (ans == IDNO)
172     return 0;
173     }
174     else if (i == 0)
175     return 0;
176    
177     p = strrchr (name, '.');
178     if (!p)
179     return 0;
180     for (i=0; (val = mm_files[i]); i++)
181     {
182     if (!stricmp (p, val))
183     return -1;
184     }
185     return 0;
186     }
187    
188    
189     const char*
190     file_get_extension (gpgme_ctx_t ctx, gpgme_sig_mode_t sigmode)
191     {
192     int use_armor = gpgme_get_armor (ctx);
193    
194     if (use_armor || sigmode == GPGME_SIG_MODE_CLEAR)
195     return ".asc";
196     if (!use_armor && sigmode == GPGME_SIG_MODE_DETACH)
197     return ".sig";
198     return ".gpg";
199     }
200    
201    
202     char*
203     fm_quote_file (const char * name)
204     {
205     char * p;
206     size_t len = strlen (name) + 8;
207    
208     if (*name == '"')
209     return m_strdup (name); /* avoid double quotes */
210     p = new char[len + 1];
211     if (!p)
212     BUG (0);
213     _snprintf (p, len, "\"%s\"", name);
214    
215     return p;
216     } /* fm_quote_file */
217    
218    
219    
220     /* Check the armor type of the file @fname and return
221     a string representation of it. */
222     static const char *
223     fm_check_armor_type (const char *fname, int *r_type)
224     {
225     FILE * fp;
226     char header[768], * p;
227    
228     if (r_type)
229     *r_type = PGP_NONE;
230     fp = fopen (fname, "rb");
231     if (!fp)
232     return "UNKNOWN";
233     p = fgets (header, sizeof (header) - 1, fp);
234     fclose (fp);
235     if (!p)
236     return "UNKNOWN";
237    
238     if (strncmp (header, "-----", 5))
239     goto leave;
240     if (strstr( header, "BEGIN PGP PUBLIC KEY" )) {
241     if (r_type) *r_type = PGP_PUBKEY;
242     return "PUBKEY";
243     }
244     else if (strstr (header, "BEGIN PGP PRIVATE KEY") ||
245     strstr (header, "BEGIN PGP SECRET KEY")) {
246     if (r_type) *r_type = PGP_SECKEY;
247     return "SECKEY";
248     }
249     else if (strstr (header, "BEGIN PGP MESSAGE")) {
250     if (r_type) *r_type = PGP_MESSAGE;
251     return "ENCRYPTED";
252     }
253     else if (strstr( header, "BEGIN PGP SIGNED MESSAGE")) {
254     if (r_type) *r_type = PGP_CLEARSIG;
255     return "SIGNED-CLEAR";
256     }
257     else if (strstr(header, "BEGIN PGP SIGNATURE")) {
258     if (r_type) *r_type = PGP_SIG;
259     return "SIGNED-DETACH";
260     }
261    
262     leave:
263     return "UNKNOWN";
264     }
265    
266    
267     /* Extract file type from @fname. If @r_type is valid,
268     it contains the PGP type on success. */
269     static const char *
270     fm_get_file_type (const char *fname, int *r_type)
271     {
272     gpg_iobuf_t inp;
273     armor_filter_context_t afx;
274     PACKET * pkt = (PACKET *)calloc (1, sizeof *pkt);
275     int i = 0, rc = 0;
276     const char *s = NULL;
277    
278     if (r_type)
279     *r_type = PGP_NONE;
280     if (!fname) {
281     safe_free (pkt);
282     return NULL;
283     }
284    
285     if (is_floppy_disc (fname))
286     return fm_check_armor_type (fname, r_type);
287    
288     inp = gpg_iobuf_open (fname);
289     if (!inp) {
290     const char *s = winpt_strerror (WPTERR_FILE_OPEN);
291     log_box( _("File Manager"), MB_ERR, "\"%s\": %s", fname, s );
292     safe_free( pkt );
293     return NULL;
294     }
295     gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
296     if (gpg_iobuf_get_filelength (inp) > 32000000 /* 32MB */
297     && !is_openpgp_ext (fname)) {
298     gpg_iobuf_close (inp);
299     return "UNKNOWN";
300     }
301    
302     if (gpg_use_armor_filter(inp)) {
303     memset (&afx, 0, sizeof (afx));
304     gpg_iobuf_push_filter (inp, gpg_armor_filter, &afx);
305     }
306    
307     gpg_init_packet (pkt);
308     while (!(rc = gpg_parse_packet (inp, pkt))) {
309     switch (pkt->pkttype) {
310     case PKT_PUBKEY_ENC:
311     s = "ENCRYPTED";rc = -2;
312     if (r_type) *r_type = PGP_MESSAGE;
313     break;
314     case PKT_SYMKEY_ENC:
315     case PKT_ENCRYPTED:
316     s = "SYMKEYENC";rc = -2;
317     if (r_type) *r_type = PGP_MESSAGE;
318     break;
319     case PKT_SIGNATURE:
320     case PKT_ONEPASS_SIG:
321     s = "SIGNED"; rc = -2;
322     if (r_type) *r_type = PGP_SIG;
323     break;
324     case PKT_PUBLIC_KEY:
325     s = "PUBKEY"; rc = -2;
326     if (r_type) *r_type = PGP_PUBKEY;
327     break;
328     case PKT_SECRET_KEY:
329     s = "SECKEY"; rc = -2;
330     if (r_type) *r_type = PGP_SECKEY;
331     break;
332     }
333     gpg_free_packet (pkt);
334     gpg_init_packet (pkt);
335     if (rc == -2)
336     break; /* found */
337     }
338     safe_free (pkt);
339     gpg_iobuf_close (inp);
340     if (!s)
341     s = fm_check_armor_type (fname, r_type);
342     if (!s)
343     s = "UNKNOWN";
344     if (!strcmp (s, "SIGNED")
345     && strcmp (fm_check_armor_type (fname, r_type), "SIGNED-CLEAR ")) {
346     if (r_type) *r_type = PGP_SIG;
347     s = "SIGNED-DETACH";
348     }
349     return s;
350     }
351    
352    
353     int
354     fm_build (listview_ctrl_t *lv, HWND ctrl)
355     {
356     int i, rc = 0;
357     listview_ctrl_t c;
358     struct listview_column_s col[] =
359     {
360     {0, 80, (char *)_("Status") },
361     {1, 256, (char *)_("Name") },
362     {2, 128, (char *)_("Operation") },
363     {0, 0, NULL }
364     };
365    
366     rc = listview_new( &c );
367     if( rc )
368     BUG( NULL );
369     c->ctrl = ctrl;
370     for ( i = 0; col[i].width; i++ )
371     listview_add_column( c, &col[i] );
372     listview_set_ext_style( c );
373     if( lv )
374     *lv = c;
375     return 0;
376     } /* fm_build */
377    
378    
379     void
380     fm_delete( listview_ctrl_t lv )
381     {
382     if( lv ) {
383     listview_release( lv );
384     }
385     } /* fm_delete */
386    
387    
388     int
389     fm_state_new (fm_state_t * ctx)
390     {
391     gpgme_error_t rc;
392     fm_state_s * c;
393    
394     c = new fm_state_s;
395     if (!c)
396     BUG (0);
397     memset (c, 0, sizeof * c);
398     rc = gpgme_new (&c->ctx);
399     if (rc)
400     BUG (0);
401     /* XXX rc = gpgme_recipients_new (&c->recp);*/
402     /* XXX gpgme_set_comment (c->ctx, "Generated by WinPT "PGM_VERSION); */
403     *ctx = c;
404     return 0;
405     } /* fm_state_new */
406    
407    
408     /* Release the FM state handle @c. */
409     void
410     fm_state_release (fm_state_t c)
411     {
412     if (!c)
413     return;
414     if (c->recp)
415     free (c->recp);
416     if (c->ctx) {
417     gpgme_release (c->ctx);
418     c->ctx = NULL;
419     }
420     free_if_alloc (c->opaque);
421     free_if_alloc (c->output);
422     delete c; c = NULL;
423     }
424    
425     static int
426     fm_check_for_entry( listview_ctrl_t lv, const char *file )
427     {
428     char name[512];
429     int i;
430    
431     memset (name, 0, sizeof (name));
432     for( i = 0; i < listview_count_items( lv, 0 ); i++ )
433     {
434     listview_get_item_text( lv, i, 1, name, sizeof (name) - 1 );
435     if( !strcmp( name, file ) )
436     return 1; /* found */
437     }
438    
439     return 0;
440     } /* fm_check_for_entry */
441    
442    
443     static int
444     fm_set_ftype (listview_ctrl_t lv, const char *name)
445     {
446     const char *type;
447     int rc;
448    
449     rc = fm_check_for_entry (lv, name);
450     if (rc)
451     return 0;
452     type = fm_get_file_type (name, NULL);
453     if (!type || !strcmp (type, "UNKNOWN"))
454     type = gnupg_check_file_ext (name, NULL);
455     rc = listview_add_item (lv, " ");
456     if (rc)
457     return -1;
458     listview_add_sub_item (lv, 0, 0, type);
459     listview_add_sub_item (lv, 0, 1, name);
460     return 0;
461     }
462    
463    
464     static int
465     fm_add_dir_files (listview_ctrl_t lv, char *path)
466     {
467     struct _finddata_t fd;
468     char * p;
469     long hd;
470    
471     strcat (path, "\\*");
472     hd = _findfirst (path, &fd);
473     do {
474     p = new char [(strlen (path) + strlen (fd.name))+1];
475     if (!p)
476     BUG (0);
477     memcpy (p, path, strlen (path)-1);
478     p[strlen (path)-1] = 0;
479     strcat (p, fd.name);
480     if (!is_directory (p))
481     fm_set_ftype (lv, p);
482     free_if_alloc (p);
483    
484     } while (_findnext (hd, &fd) == 0);
485     _findclose (hd);
486     return 0;
487     }
488    
489    
490     /* Add the drag & drop files from @dd_files to the
491     list view control @lv. */
492     int
493     fm_add_dropped_files (listview_ctrl_t lv, HDROP dd_files)
494     {
495     char name[384+4];
496     int nfiles, rc, i;
497    
498     memset (name, 0, sizeof (name));
499     nfiles = DragQueryFile (dd_files, 0xFFFFFFFF, NULL, 0);
500     for (i = 0; i < nfiles; i++) {
501     DragQueryFile (dd_files, i, name, sizeof (name) -1);
502     if (is_directory (name))
503     rc = fm_add_dir_files (lv, name);
504     else
505     rc = fm_set_ftype (lv, name);
506     if (rc == -1)
507     break;
508     }
509     return rc;
510     }
511    
512    
513     int
514     fm_add_opened_files (listview_ctrl_t lv, HWND dlg)
515     {
516     OPENFILENAME open;
517     const char *type;
518     char file[512] = "";
519     int rc;
520    
521     /* XXX: support to add multiple files. */
522     memset (&open, 0, sizeof (open));
523     open.lStructSize = sizeof (OPENFILENAME);
524     open.hInstance = glob_hinst;
525     open.lpstrTitle = _("File Open");
526     open.lpstrFilter = _("All Files (*.*)\0*.*\0\0");
527     open.hwndOwner = dlg;
528     open.lpstrFile = file;
529     open.nMaxFile = sizeof (file) - 1;
530     open.Flags = 0;
531    
532     if (GetOpenFileName (&open)) {
533     type = fm_get_file_type (open.lpstrFile, NULL);
534     if (!type)
535     return WPTERR_FILE_OPEN;
536     if (!strcmp (type, "UNKNOWN"))
537     type = gnupg_check_file_ext (open.lpstrFile, NULL);
538     rc = listview_add_item (lv, "");
539     if (!rc) {
540     listview_add_sub_item (lv, 0, 0, type);
541     listview_add_sub_item (lv, 0, 1, open.lpstrFile);
542     }
543     }
544    
545     return rc;
546     }
547    
548    
549     int
550     fm_assume_onepass_sig (const char * fname)
551     {
552     gpgme_data_t dat;
553     armor_filter_context_t afx;
554     gpg_iobuf_t fp;
555     PACKET * pkt = (PACKET *)calloc (1, sizeof *pkt);
556     int check = 0;
557    
558     if (!fname) {
559     gpg_data_new_from_clipboard (&dat, 0);
560     gpg_data_release_and_set_file (dat, "gpgme.tmp");
561    
562     fp = gpg_iobuf_open ("gpgme.tmp");
563     if (!fp)
564     return 0;
565     gpg_iobuf_ioctl (fp, 3, 1, NULL);
566     if (gpg_use_armor_filter(fp)) {
567     memset (&afx, 0, sizeof (afx));
568     gpg_iobuf_push_filter (fp, gpg_armor_filter, &afx);
569     }
570     gpg_init_packet (pkt);
571     if (!gpg_parse_packet (fp, pkt)
572     && pkt->pkttype == PKT_COMPRESSED)
573     check = 1;
574     gpg_free_packet (pkt);
575     safe_free (pkt);
576     gpg_iobuf_close (fp);
577     unlink ("gpgme.tmp");
578     }
579     /* XXX: implement it for real files */
580     return check;
581     }
582    
583    
584     int
585     fm_get_current_pos (listview_ctrl_t lv)
586     {
587     int i = 0, items;
588    
589     items = listview_count_items (lv, 0);
590     if (!items)
591     return -1;
592     else if (items == 1)
593     {
594     listview_select_one (lv, 0);
595     return 0;
596     }
597     else if (items > 1)
598     {
599     i = listview_get_curr_pos (lv);
600     if (i == -1)
601     {
602     msg_box (lv->ctrl, _("Please select a file."), _("File Manager"), MB_ERR);
603     return -1;
604     }
605     return i;
606     }
607    
608     return -1;
609     } /* fm_get_current_pos */
610    
611    
612     static int
613     fm_check_detached_sig( listview_ctrl_t lv, int pos )
614     {
615     char type[128];
616    
617     listview_get_item_text( lv, pos, 0, type, 127 );
618     return !strcmp( type, "SIGNED-DETACH" )? 1 : 0;
619     } /* fm_check_detached_sig */
620    
621    
622     int
623     fm_check_file_type (listview_ctrl_t lv, int pos, int fm_cmd)
624     {
625     char status[128];
626     int rc = 0;
627    
628     listview_get_item_text (lv, pos, 0, status, sizeof (status) - 1);
629    
630     switch (fm_cmd) {
631     case FM_ENCRYPT:
632     case FM_ENCRYPT_DIR:
633     case FM_SIGNENCRYPT:
634     if (strcmp (status, "ENCRYPTED")
635     && strcmp (status, "SYMKEYENC"))
636     rc = 1;
637     break;
638    
639     case FM_DECRYPT:
640     if (!strcmp (status, "DATA")
641     || !strcmp (status, "ENCRYPTED")
642     || !strcmp (status, "SYMKEYENC")
643     || !strcmp (status, "ARMORED"))
644     rc = 1;
645     break;
646    
647     case FM_SIGN:
648     if( strncmp( status, "SIGNED", 6 ) )
649     rc = 1;
650     break;
651    
652     case FM_VERIFY:
653     if( !strncmp( status, "SIGNED", 6 )
654     || !strcmp( status, "COMPRESSED" ) )
655     rc = 1;
656     break;
657    
658     case FM_SYMENC:
659     if( strcmp( status, "SYMKEYENC" ) )
660     rc = 1;
661     break;
662    
663     case FM_IMPORT:
664     if( !strcmp( status, "PUBKEY" )
665     || !strcmp( status, "SECKEY" ) )
666     rc = 1;
667     break;
668    
669     case FM_WIPE:
670     case FM_LIST:
671     rc = 1;
672     break;
673     }
674    
675     return rc;
676     } /* fm_check_file_type */
677    
678    
679     static void
680     fm_set_status (listview_ctrl_t lv, int pos, int fm_cmd, int success,
681     const char * output)
682     {
683     char status[128], operat[128];
684     int update = 1;
685     const char *s;
686    
687     if ( fm_cmd == FM_LIST )
688     return;
689     success ? s = "SUCCESS" : s = "FAILED";
690     strcpy( operat, s );
691    
692     switch (fm_cmd) {
693     case FM_ENCRYPT:
694     case FM_ENCRYPT_DIR:
695     case FM_SIGNENCRYPT: strcpy( status, "ENCRYPTED" ); break;
696     case FM_DECRYPT: strcpy( status, "UNKNOWN" ); break;
697     case FM_SIGN: strcpy( status, "SIGNED" ); break;
698     case FM_VERIFY: update = 0; break;
699     case FM_SYMENC: strcpy( status, "SYMKEYENC" ); break;
700     case FM_IMPORT: update = 0; break;
701     case FM_WIPE: strcpy( status, "WIPED" ); break;
702     default: strcpy( status, "UNKNOWN"); break;
703     }
704    
705     if (success) {
706     if (update) {
707     listview_add_sub_item (lv, pos, 0, status);
708     listview_add_sub_item (lv, pos, 1, output);
709     }
710     }
711     listview_add_sub_item( lv, pos, 2, operat );
712     } /* fm_set_status */
713    
714    
715     int
716     fm_clearsign_8bit (listview_ctrl_t lv, fm_state_s *ctx)
717     {
718     FILE *f;
719     byte buf[32];
720     char name[256];
721     int i, n, cnt=0;
722    
723     if (ctx->sigmode != GPGME_SIG_MODE_CLEAR)
724     return 0;
725     listview_get_item_text (lv, -1, 1, name, sizeof (name)-1);
726     if (stristr (name, ".TXT"))
727     return 0;
728     f = fopen (name, "rb");
729     if (!f)
730     return -1; /* should never happen */
731     n = fread (buf, 1, 32, f);
732     for (i = 0; i < n; i++) {
733     if (buf[i] == 0x00 || buf[i] > 170)
734     cnt++;
735     }
736     fclose (f);
737     if (!cnt)
738     return 0;
739     n = -1;
740     i = log_box (_("File Manager"), MB_WARN|MB_YESNO,
741     _("\"%s\" does not seems to be a text file.\n"
742     "Do you really want to clearsign it?"), name);
743     if (i == IDYES)
744     n = 0;
745     return n;
746     }
747    
748     int
749     fm_parse_files (listview_ctrl_t lv, HWND dlg, int cmd)
750     {
751     struct secdel_confirm_s confirm = {0};
752     struct progress_filter_s pfx, pfx2;
753     fm_state_s * ctx;
754     int fm_cmd, sig_detached = 0;
755     int rc = 0, i, n, ndel = 0;
756     char fname[512], status[128];
757    
758     switch (cmd) {
759     case ID_FILEMISC_ENCRYPT: fm_cmd = FM_ENCRYPT; break;
760     case ID_FILEMISC_DECRYPT: fm_cmd = FM_DECRYPT; break;
761     case ID_FILEMISC_SYMENC: fm_cmd = FM_SYMENC; break;
762     case ID_FILEMISC_SIGN: fm_cmd = FM_SIGN; break;
763     case ID_FILEMISC_VERIFY: fm_cmd = FM_VERIFY; break;
764     case ID_FILEMISC_IMPORT: fm_cmd = FM_IMPORT; break;
765     case ID_FILEMISC_WIPE: fm_cmd = FM_WIPE; break;
766     case ID_FILEMISC_LIST: fm_cmd = FM_LIST; break;
767     case ID_FILEMISC_SIGNENC: fm_cmd = FM_SIGNENCRYPT; break;
768     default: return 1; /* unknown command */
769     }
770    
771     if (fm_get_current_pos (lv) == -1)
772     return WPTERR_GENERAL;
773     rc = fm_state_new (&ctx);
774     if (rc)
775     BUG (0);
776     ctx->dlg = dlg;
777    
778     // XXX: for file operations the progress dialog will be
779     // reloaded somewhere and thus a 'dummy' dialog remains
780    
781     /* we use it here to make sure that pfx_cleanup will not use
782     any weird values. */
783     memset (&pfx, 0, sizeof (pfx));
784     ctx->prog_cb = NULL;
785     if (cmd != FM_VERIFY && cmd != FM_SIGN /*&& reg_prefs.fm.progress > 0*/) {
786     pfx.hwnd = dlg;
787     /*gpgme_set_progress_cb (ctx->ctx, progress_callback, &pfx);*/
788     /*ctx->prog_cb = &pfx;*/
789     }
790    
791     /* Commands we need before we can perform the main command */
792     switch (fm_cmd) {
793     case FM_ENCRYPT:
794     case FM_SIGNENCRYPT:
795     if (fm_cmd == FM_SIGNENCRYPT)
796     ctx->req_signer = 1;
797     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILE_ENCRYPT, ctx->dlg,
798     file_encrypt_dlg_proc, (LPARAM)ctx);
799     if (ctx->cancel == 1) {
800     rc = WPTERR_GENERAL;
801     goto leave;
802     }
803     break;
804    
805     case FM_SIGN:
806     DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_FILE_SIGN, dlg,
807     file_sign_dlg_proc, (LPARAM) ctx);
808     if (ctx->cancel == 1 || fm_clearsign_8bit (lv, ctx)) {
809     rc = WPTERR_GENERAL;
810     goto leave;
811     }
812     break;
813    
814     case FM_WIPE:
815     memset (&pfx2, 0, sizeof (pfx2));
816     secure_unlink_set_cb (progress_callback, &pfx2);
817     break;
818     }
819    
820     for( i = 0, n = 0; i < listview_count_items( lv, 0 ); i++ ) {
821     if( !listview_get_item_state( lv, i ) )
822     continue;
823     listview_get_item_text( lv, i, 0, status, sizeof (status) -1 );
824     if (!strcmp( status, "ENCRYPTED" ) && fm_cmd == FM_DECRYPT)
825     n++;
826     if (!strcmp( status, "UNKNOWN" ) && fm_cmd == FM_SIGN)
827     n++;
828     if (fm_cmd == FM_WIPE)
829     ndel++;
830     }
831    
832     if (n > 1 && fm_cmd != FM_SYMENC)
833     ctx->cache_cb = 1;
834    
835     if (fm_cmd == FM_WIPE && ndel > 0) {
836     memset (&confirm, 0, sizeof confirm);
837     confirm.lv_files = lv;
838     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILES_SECDEL, ctx->dlg,
839     file_secdel_confirm_dlg_proc, (LPARAM)&confirm);
840     if (!confirm.yes)
841     goto leave;
842     }
843    
844     for( i = 0; i < listview_count_items( lv, 0 ); i++ ) {
845     if( !listview_get_item_state( lv, i ) )
846     continue;
847     listview_get_item_text( lv, i, 1, fname, sizeof (fname) - 1 );
848     if( file_exist_check( fname ) && !is_directory( fname ) ) {
849     log_box( _("File Manager"), MB_ERR, _("\"%s\" does not exist"), fname );
850     continue;
851     }
852     if( is_directory( fname ) )
853     fm_cmd = FM_ENCRYPT_DIR;
854     if( !fm_check_file_type( lv, i, fm_cmd ) )
855     continue;
856     sig_detached = fm_check_detached_sig( lv, i );
857     switch( fm_cmd ) {
858     case FM_LIST: rc = fm_list( fname, dlg ); break;
859     case FM_WIPE: rc = fm_wipe( fname ); break;
860     case FM_ENCRYPT: rc = fm_encrypt( ctx, fname, 0 ); break;
861     case FM_ENCRYPT_DIR: rc = fm_encrypt_directory( ctx, fname ); break;
862     case FM_SIGNENCRYPT: rc = fm_encrypt( ctx, fname, 1 ); break;
863     case FM_DECRYPT: rc = fm_decrypt( ctx, fname ); break;
864     case FM_SIGN: rc = fm_sign( ctx, fname ); break;
865     case FM_SYMENC: rc = fm_sym_encrypt( ctx, fname );break;
866     case FM_VERIFY: rc = fm_verify (ctx, sig_detached, fname);break;
867     case FM_IMPORT:
868     free_if_alloc (ctx->opaque);
869     ctx->opaque = m_strdup (fname);
870     if (!ctx->opaque)
871     BUG (0);
872     DialogBoxParam( glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
873     file_import_dlg_proc, (LPARAM)ctx );
874     if (ctx->cancel == 1)
875     continue;
876     rc = fm_import (ctx, fname);
877     break;
878     }
879     fm_set_status (lv, i, fm_cmd, !rc, ctx->output);
880     free_if_alloc (ctx->output);
881     progress_cleanup (&pfx);
882     }
883     if (fm_cmd == FM_WIPE) {
884     secure_unlink_set_cb (NULL, NULL);
885     progress_cleanup (&pfx2);
886     }
887     if (ctx->cache_cb) {
888     release_gpg_passphrase_cb (&ctx->pass_cb);
889     ctx->cache_cb = 0; /* make sure it's only used for this session! */
890     }
891    
892     /* remove wipe files from the list */
893     n = listview_count_items (lv, 0);
894     while (n--) {
895     char status[128];
896     listview_get_item_text (lv, n, 0, status, sizeof (status) - 1);
897     if( !strcmp (status, "WIPED"))
898     listview_del_item (lv, n);
899     }
900    
901     leave:
902     if (!rc)
903     fm_state_release (ctx);
904     progress_cleanup (&pfx);
905     return rc;
906     } /* fm_parse_files */
907    
908    
909     /* Wipe the given file @name with the delete mode
910     from the configuration.
911     Return value: 0 on success. */
912     int
913     fm_wipe (const char *name)
914     {
915     int rc;
916    
917     SetCursor (LoadCursor (NULL, IDC_WAIT));
918     remove_crit_file_attrs (name, 1);
919     rc = secure_unlink (name, reg_prefs.wipe_mode);
920     SetCursor (LoadCursor (NULL, IDC_ARROW));
921     return rc;
922     }
923    
924    
925     /* Dump out the given PGP packets from file @name in a dialog. */
926     int
927     fm_list (const char *name, HWND dlg)
928     {
929     dialog_box_param( glob_hinst, (LPCTSTR)IDD_WINPT_FILE_STAT, dlg,
930     file_stat_dlg_proc, (LPARAM)name, _("File Status"),
931     IDS_WINPT_FILE_STAT );
932     return 0;
933     }
934    
935    
936     static int
937     ask_filename (fm_state_t c, const char *msg, char **dst)
938     {
939     const char * s;
940    
941     s = get_filename_dlg (c->dlg, FILE_SAVE, msg, NULL, NULL);
942     if (!s)
943     return WPTERR_GENERAL;
944    
945     if (dst != NULL)
946     free_if_alloc (*dst);
947     free_if_alloc (c->output);
948     c->output = m_strdup (s);
949     if (!c->output)
950     BUG (0);
951     if (dst)
952     *dst = fm_quote_file (s);
953     return 0;
954     }
955    
956    
957     int
958     fm_encrypt (fm_state_t c, const char *name, int sign)
959     {
960     gpgme_error_t err;
961     gpgme_key_t key = NULL;
962     gpgme_ctx_t ctx = c->ctx;
963     file_data_t in=NULL, out=NULL;
964     char *keyid = NULL, ext[5];
965     int no_compr = 0;
966     int rc = 0;
967    
968     c->output = new char[strlen (name) + 5 + 1];
969     if (!c->output)
970     BUG (0);
971     strcpy (ext, file_get_extension (ctx, c->sigmode));
972     strcpy (c->output, name);
973     strcat (c->output, ext);
974    
975     if (!overwrite_file (c->output)) {
976     rc = ask_filename (c, _("Enter filename for encrypted file"), NULL);
977     if (rc)
978     goto leave;
979     }
980    
981     err = gpg_file_data_new (name, 1, &in);
982     if (err)
983     goto leave;
984     err = gpg_file_data_new (c->output, 0, &out);
985     if (err)
986     goto leave;
987    
988     /*
989     if (c->prog_cb) {
990     c->prog_cb->what = name;
991     gpg_file_data_set_cb (in, c->prog_cb);
992     }
993     */
994    
995     /* XXX
996     no_compr = is_multi_media (name);
997     gpgme_control (ctx, GPGME_CTRL_NO_COMPR, no_compr);
998     */
999    
1000     if (sign) {
1001     if (gpgme_signers_enum (ctx, 0) == NULL) {
1002     keyid = get_gnupg_default_key ();
1003     if (!keyid) {
1004     msg_box (c->dlg, _("Could not get default secret key."),
1005     _("Signing"), MB_ERR);
1006     rc = WPTERR_GENERAL;
1007     goto leave;
1008     }
1009     if (get_seckey (keyid, &key))
1010     BUG (0);
1011     gpgme_signers_add (ctx, key);
1012     }
1013     else {
1014     gpgme_key_t key = gpgme_signers_enum (ctx, 0);
1015     if (key && key->subkeys) {
1016     keyid = m_strdup (key->subkeys->keyid);
1017     if (!keyid)
1018     BUG (NULL);
1019     }
1020     }
1021     if (!c->init_cb || !c->cache_cb) {
1022     set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_SIGN,
1023     c->dlg, _("Signing"));
1024     c->init_cb = 1;
1025     }
1026     op_begin ();
1027     err = gpgme_op_encrypt_sign (ctx, c->recp, GPGME_ENCRYPT_ALWAYS_TRUST,
1028     in->dat, out->dat);
1029     op_end ();
1030     if (!c->cache_cb)
1031     release_gpg_passphrase_cb (&c->pass_cb);
1032     if (c->pass_cb.cancel) {
1033     rc = WPTERR_GENERAL;
1034     goto leave;
1035     }
1036     if (err) {
1037     msg_box (c->dlg, gpgme_strerror (err), _("Sign"), MB_ERR);
1038     if (gpgme_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
1039     agent_del_cache (keyid);
1040     rc = WPTERR_GENERAL;
1041     goto leave;
1042     }
1043     }
1044     else {
1045     op_begin ();
1046     err = gpgme_op_encrypt (ctx, c->recp, GPGME_ENCRYPT_ALWAYS_TRUST,
1047     in->dat, out->dat);
1048     op_end ();
1049     if (err) {
1050     msg_box (c->dlg, gpgme_strerror (err), _("Encrypt"), MB_ERR);
1051     rc = WPTERR_GENERAL;
1052     goto leave;
1053     }
1054     }
1055     if (c->wipe)
1056     secure_unlink (name, WIPE_MODE_SIMPLE);
1057    
1058     leave:
1059     if (in)
1060     gpg_file_data_release (in);
1061     if (out)
1062     gpg_file_data_release (out);
1063     free_if_alloc (keyid);
1064     return rc;
1065     }
1066    
1067    
1068     int
1069     fm_sym_encrypt (fm_state_t c, const char * name)
1070     {
1071     gpgme_ctx_t ctx = c->ctx;
1072     gpgme_error_t err;
1073     file_data_t in=NULL, out=NULL;
1074     int rc = 0, cancel = 0;
1075     char * src = NULL, * dst = NULL;
1076     char ext[5], * pass;
1077    
1078     pass = request_passphrase2 (_("Symmetric"), 0, &cancel);
1079     if (cancel)
1080     return 0;
1081    
1082     /* XXX gpgme_control (ctx, GPGME_CTRL_CIPHER, -1);*/
1083     c->output = new char[strlen (name) + 5 + 1];
1084     if (!c->output)
1085     BUG (0);
1086     strcpy (ext, file_get_extension (ctx, c->sigmode));
1087     strcpy (c->output, name);
1088     strcat (c->output, ext);
1089    
1090     if (overwrite_file (c->output) == 0) {
1091     rc = WPTERR_GENERAL;
1092     goto leave;
1093     }
1094    
1095     gpgme_set_passphrase_cb (ctx, sym_passphrase_cb, pass);
1096    
1097     err = gpg_file_data_new (name, 1, &in);
1098     if (err)
1099     goto leave;
1100     err = gpg_file_data_new (c->output, 0, &out);
1101     if (err)
1102     goto leave;
1103    
1104     op_begin ();
1105     err = gpgme_op_encrypt (ctx, NULL, GPGME_ENCRYPT_ALWAYS_TRUST,
1106     in->dat, out->dat);
1107     op_end ();
1108     if (err) {
1109     msg_box (c->dlg, gpgme_strerror (err), _("Symmetric"), MB_ERR);
1110     rc = WPTERR_GENERAL;
1111     goto leave;
1112     }
1113     if (file_exist_check (c->output)) {
1114     msg_box (c->dlg, _("Encryption failed."), _("Symmetric"), MB_ERR);
1115     rc = WPTERR_GENERAL;
1116     }
1117    
1118     leave:
1119     if (in)
1120     gpg_file_data_release (in);
1121     if (out)
1122     gpg_file_data_release (out);
1123     sfree_if_alloc (pass);
1124     return rc;
1125     } /* fm_sym_encrypt */
1126    
1127    
1128     /* Show the human readable verify result from @sigres. */
1129     static void
1130     show_verify_result (gpgme_verify_result_t sigres)
1131     {
1132     gpgme_key_t key=NULL;
1133     gpgme_signature_t sig=sigres->signatures;
1134     const char *s, *keyid;
1135     int sigok = 0;
1136     int type;
1137     char buf[384];
1138    
1139     sig = sigres->signatures;
1140     sigok = sig->summary & GPGME_SIGSUM_GREEN;
1141     s = sigok? _("Good signature") : _("BAD signature");
1142     type = sigok? MB_OK: MB_ICONWARNING|MB_OK;
1143     keyid = sig->fpr;
1144     if (!keyid)
1145     return;
1146    
1147     keyid = strlen (sig->fpr) == 40? sig->fpr+32 : sig->fpr + 24;
1148     get_pubkey (sig->fpr, &key);
1149     _snprintf (buf, sizeof (buf)-1, "Signature made %s using %s key ID %s\n"
1150     "%s from \"%s\"",
1151     strtimestamp (sig->timestamp), get_key_pubalgo (sig->pubkey_algo),
1152     keyid, s, key? key->uids->uid : _("user ID not found"));
1153     msg_box (NULL, buf, _("Decrypt Verify"), type);
1154     }
1155    
1156    
1157     /* Check the recipients if we have at least one secret key. */
1158     bool
1159     secret_key_available (gpgme_recipient_t rset)
1160     {
1161     gpgme_recipient_t r;
1162     gpgme_key_t key;
1163    
1164     for (r=rset; r; r = r->next) {
1165     if (gpgme_err_code (r->status) == GPG_ERR_NO_SECKEY)
1166     continue;
1167     else {
1168     /* extra check to make sure the key is available right now. */
1169     if (!get_seckey (r->keyid, &key))
1170     return true;
1171     }
1172     }
1173     return false;
1174     }
1175    
1176    
1177     /* Decrypt the file @name. */
1178     int
1179     fm_decrypt (fm_state_t c, const char *name)
1180     {
1181     gpgme_error_t err;
1182     gpgme_ctx_t ctx = c->ctx;
1183     gpgme_decrypt_result_t res;
1184     gpgme_verify_result_t sigres;
1185     file_data_t in =NULL, out=NULL;
1186     int is_signed = 0;
1187     int rc = 0;
1188    
1189     if (!c->init_cb || !c->cache_cb) {
1190     set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_DECRYPT,
1191     c->dlg, _("Decryption"));
1192     c->init_cb = 1;
1193     }
1194    
1195     c->output = m_strdup (name);
1196     if (!c->output)
1197     BUG (0);
1198     if (is_openpgp_ext (c->output))
1199     c->output[strlen (c->output)-4] = '\0';
1200     else {
1201     const char *s = get_filesave_dlg (c->dlg, _("Choose Filename for Output"),
1202     NULL, NULL);
1203     if (s) {
1204     free_if_alloc (c->output);
1205     c->output = m_strdup (s);
1206     if (!c->output)
1207     BUG (NULL);
1208     }
1209     }
1210    
1211     if (overwrite_file (c->output) == 0) {
1212     rc = ask_filename (c, _("Please enter filename for plaintext file"), NULL);
1213     if (rc)
1214     goto leave;
1215     }
1216    
1217     remove_crit_file_attrs (c->output, 0);
1218    
1219     err = gpg_file_data_new (name, 1, &in);
1220     if (err)
1221     goto leave;
1222     err = gpg_file_data_new (c->output, 0, &out);
1223     if (err)
1224     goto leave;
1225    
1226     op_begin ();
1227     err = gpgme_op_decrypt_verify (ctx, in->dat, out->dat);
1228     op_end ();
1229     if (!c->cache_cb)
1230     release_gpg_passphrase_cb (&c->pass_cb);
1231     if (c->pass_cb.cancel) {
1232     rc = WPTERR_GENERAL;
1233     goto leave;
1234     }
1235    
1236     res = gpgme_op_decrypt_result (ctx);
1237     if (res && res->recipients && !secret_key_available (res->recipients)) {
1238     const char *keyid = res->recipients->keyid;
1239     char *p = get_key_userid (keyid+8);
1240     gpgme_pubkey_algo_t pkalgo = res->recipients->pubkey_algo;
1241    
1242     log_box( _("Decryption"), MB_ERR,
1243     _("Encrypted with %s key, ID %s.%s\n"
1244     "Decryption failed: secret key not available."),
1245     get_key_pubalgo (pkalgo), keyid+8, p);
1246     rc = WPTERR_GENERAL;
1247     free_if_alloc (p);
1248     goto leave;
1249     }
1250     else if (err) {
1251     msg_box (c->dlg, gpgme_strerror (err), _("Decrypt"), MB_ERR);
1252     rc = WPTERR_GENERAL;
1253     goto leave;
1254     }
1255     if (file_exist_check (c->output)) {
1256     log_box ("Decrypt", MB_ERR, _("Decryption failed.\n%s: does not exist."), c->output);
1257     rc = WPTERR_GENERAL;
1258     }
1259    
1260     sigres = gpgme_op_verify_result (ctx);
1261     if (sigres && sigres->signatures)
1262     show_verify_result (sigres);
1263    
1264    
1265     leave:
1266     if (in)
1267     gpg_file_data_release (in);
1268     if (out)
1269     gpg_file_data_release (out);
1270     return rc;
1271     }
1272    
1273    
1274     int
1275     fm_sign (fm_state_t c, const char * name)
1276     {
1277     int rc = 0;
1278     gpgme_ctx_t ctx = c->ctx;
1279     gpgme_error_t err;
1280     file_data_t in=NULL, out=NULL;
1281     char ext[5];
1282    
1283     if (!c->init_cb || !c->cache_cb) {
1284     set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_SIGN, c->dlg, _("Signing") );
1285     c->init_cb = 1;
1286     }
1287    
1288     free_if_alloc (c->output);
1289     c->output = new char[strlen (name) + 5 + 1];
1290     if( !c->output)
1291     BUG( NULL );
1292     strcpy (ext, file_get_extension (ctx, c->sigmode));
1293     strcpy (c->output, name);
1294     strcat (c->output, ext);
1295    
1296     if (!overwrite_file (c->output)) {
1297     rc = ask_filename (c, _("Enter filename for signed file"), NULL);
1298     if (rc)
1299     goto leave;
1300     }
1301     remove_crit_file_attrs (c->output, 0);
1302    
1303     err = gpg_file_data_new (name, 1, &in);
1304     if (err)
1305     goto leave;
1306     err = gpg_file_data_new (c->output, 0, &out);
1307     if (err)
1308     goto leave;
1309    
1310     op_begin ();
1311     err = gpgme_op_sign (ctx, in->dat, out->dat, c->sigmode);
1312     op_end ();
1313     if( !c->cache_cb )
1314     release_gpg_passphrase_cb (&c->pass_cb);
1315     if( c->pass_cb.cancel ) {
1316     rc = WPTERR_GENERAL;
1317     goto leave;
1318     }
1319     if( err ) {
1320     msg_box( c->dlg, gpgme_strerror( err ), _("Sign"), MB_ERR );
1321     rc = WPTERR_GENERAL;
1322     goto leave;
1323     }
1324    
1325     leave:
1326     if (in)
1327     gpg_file_data_release (in);
1328     if (out)
1329     gpg_file_data_release (out);
1330     return rc;
1331     }
1332    
1333    
1334     static int
1335     fm_add_sig_stat (file_sig_ctx_t log)
1336     {
1337     gpgme_key_t key;
1338     const char *kid;
1339     int not_found = 0;
1340    
1341     kid = log->sig->fpr;
1342     if (!kid)
1343     BUG (NULL);
1344     if (strlen (kid) == 40)
1345     kid += 32;
1346     else if (strlen (kid) == 32)
1347     kid += 24;
1348     if (get_pubkey (kid, &key))
1349     log->use_uid = 0;
1350     else {
1351     log->user_id = key->uids->uid;
1352     log->use_uid = 1;
1353     }
1354     file_verify_add_state (log);
1355     return 0;
1356     }
1357    
1358    
1359     static int
1360     verify_pasted (listview_ctrl_t lv, fm_state_t ctx, const char * dat,
1361     int i, HWND dlg)
1362     {
1363     FILE * fp;
1364     char stat[32];
1365     char file[256], * fname = NULL;
1366     int del_end=0;
1367    
1368     listview_get_item_text (lv, i, 0, stat, sizeof (stat)-1);
1369     listview_get_item_text (lv, i, 1, file, sizeof (file)-1);
1370     if (strcmp (stat, "UNKNOWN"))
1371     return 0;
1372     fname = make_filename (NULL, file, "asc");
1373     if (file_exist_check (fname) != 0) {
1374     fp = fopen (fname, "wb");
1375     if (fp == NULL) {
1376     log_box (_("File Manager"), MB_ERR, "could not create '%s'", fname);
1377     free_if_alloc (fname);
1378     return WPTERR_GENERAL;
1379     }
1380     fwrite (dat, 1, strlen (dat), fp);
1381     fclose (fp);
1382     del_end = 1;
1383     }
1384     fm_verify (ctx, 1, fname);
1385     if (del_end)
1386     unlink (fname);
1387     free_if_alloc (fname);
1388     return 0;
1389     }
1390    
1391    
1392     int
1393     fm_verify_pasted_detsig (listview_ctrl_t lv, HWND dlg)
1394     {
1395     fm_state_t ctx = NULL;
1396     char * dat=NULL;
1397     int i, fnd = 0;
1398    
1399     dat = get_clip_text (NULL);
1400     if (!dat || !strstr (dat, "BEGIN PGP SIGNATURE")) {
1401     msg_box (dlg, _("Could not find detached signature in the clipboard."),
1402     _("File Manager"), MB_ERR);
1403     free_if_alloc (dat);
1404     return WPTERR_GENERAL;
1405     }
1406     /* XXX find a way to filter out bad signatures or just ignore all in
1407     this case */
1408     fm_state_new (&ctx);
1409     if ((i=listview_get_curr_pos (lv)) != -1) {
1410     verify_pasted (lv, ctx, dat, i, dlg);
1411     fnd = 1;
1412     }
1413     else {
1414     for (i=0; i < listview_count_items (lv, 0); i++) {
1415     verify_pasted (lv, ctx, dat, i, dlg);
1416     fnd = 1;
1417     }
1418     }
1419     if (!fnd)
1420     msg_box (dlg, _("No files to check."), _("File Manager"), MB_INFO);
1421     free_if_alloc (dat);
1422     fm_state_release (ctx);
1423     return 0;
1424     }
1425    
1426    
1427     /* Extract automatically the output file name from @name.
1428     If @detached is 1, a detached sig is assumed. */
1429     static int
1430     get_output_file (fm_state_t c, const char *name, int detached)
1431     {
1432     const char *file = NULL;
1433     const char *title;
1434     char fname[384];
1435    
1436     if (detached)
1437     title = _("Select Data File");
1438     else
1439     title = _("Selected Output File");
1440    
1441     if (strstr (name, ".sig") || strstr (name, ".asc") || strstr (name, ".gpg")) {
1442     _snprintf (fname, sizeof (fname) - 1, "%s", name);
1443     fname[strlen (fname) - 4] = '\0';
1444     if (file_exist_check (fname) == 0 && detached)
1445     file = fname;
1446     else if (!detached) {
1447     /* If the signature is clear or normal, make sure we do not
1448     overwrite the original file if it exists. */
1449     if (file_exist_check (fname) == 0 && !overwrite_file (fname)) {
1450     file = get_filesave_dlg (c->dlg, title, NULL, NULL);
1451     if (!file)
1452     return WPTERR_GENERAL;
1453     }
1454     else
1455     file = fname;
1456     }
1457     }
1458     if (!file)
1459     file = get_fileopen_dlg (c->dlg, title, NULL, NULL);
1460     if (file) {
1461     free_if_alloc (c->output);
1462     c->output = m_strdup (file);
1463     if (!c->output)
1464     BUG (NULL);
1465     }
1466     else {
1467     msg_box (c->dlg, _("Invalid file name. Exit"), _("Verify"), MB_ERR);
1468     return WPTERR_GENERAL;
1469     }
1470     if (detached)
1471     c->sigmode = GPGME_SIG_MODE_DETACH;
1472     else {
1473     if (strstr (name, ".asc"))
1474     c->sigmode = GPGME_SIG_MODE_CLEAR;
1475     else
1476     c->sigmode = GPGME_SIG_MODE_NORMAL;
1477     }
1478     return 0;
1479     }
1480    
1481    
1482     /* Verify the signature from the file @name. If @detached 1,
1483     it is assumed that a detached signature should be checked. */
1484     int
1485     fm_verify (fm_state_t c, int detached, const char *name)
1486     {
1487     gpgme_ctx_t ctx = c->ctx;
1488     gpgme_error_t err;
1489     gpgme_signature_t s;
1490     gpgme_verify_result_t res;
1491     struct file_sig_ctx_s log;
1492     file_data_t in=NULL, out=NULL;
1493     int rc = 0;
1494    
1495     if (strstr (name, ".sig"))
1496     detached = 1;
1497    
1498     if (get_output_file (c, name, detached))
1499     return WPTERR_GENERAL;
1500    
1501     memset (&log, 0, sizeof (log));
1502     log.file = m_strdup (name);
1503     if (!log.file)
1504     BUG (NULL);
1505     file_verify_create_dlg ();
1506    
1507     err = gpg_file_data_new (name, 1, &in);
1508     if (err)
1509     goto leave;
1510     err = gpg_file_data_new (c->output, detached? 1 : 0, &out);
1511     if (err)
1512     goto leave;
1513    
1514     op_begin ();
1515     if (c->sigmode == GPGME_SIG_MODE_DETACH)
1516     err = gpgme_op_verify (ctx, in->dat, out->dat, NULL);
1517     else
1518     err = gpgme_op_verify (ctx, in->dat, in->dat, out->dat);
1519     op_end ();
1520     if (err) {
1521     msg_box (c->dlg, gpgme_strerror (err), _("Verify"), MB_ERR);
1522     rc = WPTERR_GENERAL;
1523     goto leave;
1524     }
1525    
1526     res = gpgme_op_verify_result (ctx);
1527     for (s=res->signatures; s; s=s->next) {
1528     log.sig = s;
1529     fm_add_sig_stat (&log);
1530     }
1531     if (!c->output)
1532     c->output = m_strdup (name); /* for later use */
1533    
1534     leave:
1535     if (in)
1536     gpg_file_data_release (in);
1537     if (out)
1538     gpg_file_data_release (out);
1539     if (log.file)
1540     delete []log.file;
1541     return rc;
1542     }
1543    
1544    
1545     int
1546     fm_import (fm_state_t c, const char *name)
1547     {
1548     gpgme_ctx_t ctx = c->ctx;
1549     gpgme_error_t err;
1550     gpgme_import_result_t res;
1551     file_data_t keydata = NULL;
1552     int rc = 0;
1553    
1554     free_if_alloc (c->output);
1555     c->output = m_strdup (name);
1556     if (!c->output)
1557     BUG (NULL);
1558    
1559     err = gpg_file_data_new (name, 1, &keydata);
1560     if (err)
1561     goto leave;
1562    
1563     op_begin ();
1564     err = gpgme_op_import (ctx, keydata->dat);
1565     op_end ();
1566     if (err) {
1567     msg_box (c->dlg, gpgme_strerror (err), _("Import"), MB_ERR);
1568     rc = WPTERR_GENERAL;
1569     goto leave;
1570     }
1571    
1572     res = gpgme_op_import_result (ctx);
1573     print_import_status (res);
1574     if (res->no_user_id > 0) {
1575     msg_box (c->dlg, _("Key without a self signature was dectected!\n"
1576     "(This key is NOT usable for encryption, etc)\n"
1577     "\n"
1578     "Cannot import these key(s)!"), _("Import"), MB_INFO);
1579     }
1580    
1581     leave:
1582     if (keydata)
1583     gpg_file_data_release (keydata);
1584     return rc;
1585     } /* fm_import */
1586    
1587    
1588     /* Export the selected keys from the File Manager to a file. */
1589     int
1590     fm_export (fm_state_t c)
1591     {
1592     int rc = 0, id = 0;
1593     gpgme_ctx_t ctx = c->ctx;
1594     gpgme_error_t err;
1595     gpgme_key_t *rset = c->recp;
1596     file_data_t keydata = NULL;
1597     const char *name, *s = NULL;
1598     char *p = NULL, *patt = NULL;
1599    
1600     if (!rset || !rset[0]) {
1601     msg_box (c->dlg, _("No key was selected for export."), _("Export"), MB_ERR);
1602     rc = WPTERR_GENERAL;
1603     goto leave;
1604     }
1605    
1606     if (rset[1] == NULL) { /* count == 1*/
1607     gpgme_key_t k = rset[0];
1608     const char *s = k->uids->name;
1609     p = new char[strlen (s)+1+8];
1610     if (!p)
1611     BUG (NULL);
1612     strcpy (p, s );
1613     strcat (p, ".asc");
1614     }
1615    
1616     name = get_filename_dlg (c->dlg, FILE_SAVE, _("Choose Name for Key File"),
1617     NULL, p? p : NULL);
1618    
1619     if (!name)
1620     name = "keys.gpg";
1621    
1622     patt = gpg_keylist_to_pattern (rset, c->n_recp);
1623    
1624     err = gpg_file_data_new (name, 0, &keydata);
1625     if (err)
1626     goto leave;
1627    
1628     op_begin ();
1629     err = gpgme_op_export (ctx, patt, 0, keydata->dat);
1630     op_end ();
1631     if (err) {
1632     msg_box (c->dlg, gpgme_strerror (err), _("Export"), MB_ERR);
1633     rc = WPTERR_GENERAL;
1634     goto leave;
1635     }
1636     log_box (_("GnuPG status"), MB_OK, _("Finished (Output: %s)"), name);
1637    
1638     leave:
1639     if (keydata)
1640     gpg_file_data_release (keydata);
1641     if (patt)
1642     free (patt);
1643     free_if_alloc (p);
1644    
1645     return rc;
1646     }
1647    
1648    
1649     /* Parse the command line and process the given file. */
1650     int
1651     fm_parse_command_line (char *cmdl)
1652     {
1653     fm_state_t ctx;
1654     const char *s;
1655     char *p, *fn = NULL;
1656     int count = 0, detached = 0;
1657     int type;
1658    
1659     if (!cmdl || !*cmdl)
1660     return 0;
1661    
1662     fm_state_new (&ctx);
1663     ctx->dlg = GetActiveWindow ();
1664     ctx->cache_cb = 1;
1665    
1666     p = cmdl;
1667     if (p && *p > 32 && !stristr (p, "winpt.exe")
1668     && !strstr (p, "--" )) {
1669     count++;
1670     if (*p == '"') { /* need to remove quotes */
1671     fn = new char[strlen (p)];
1672     if (!fn)
1673     BUG (NULL);
1674     memcpy (fn, p+1, strlen (p) - 2);
1675     fn[strlen (p) -2] = '\0';
1676     }
1677     else
1678     fn = m_strdup (p);
1679     s = fm_get_file_type (fn, &type);
1680     if (!s || !strcmp (s, "UNKNOWN"))
1681     s = gnupg_check_file_ext (fn, &type);
1682     if (type == PGP_NONE) {
1683     log_box (_("File Manager"), MB_ERR,
1684     _("%s: no valid OpenPGP data found."), p);
1685     free_if_alloc (fn);
1686     return count;
1687     }
1688     switch (type) {
1689     case PGP_MESSAGE:
1690     fm_decrypt (ctx, fn);
1691     break;
1692    
1693     case PGP_PUBKEY:
1694     case PGP_SECKEY:
1695     fm_import (ctx, fn);
1696     break;
1697    
1698     case PGP_SIG:
1699     case PGP_CLEARSIG:
1700     file_verify_use_event ();
1701     if (type == PGP_SIG)
1702     detached = 1;
1703     fm_verify (ctx, detached, fn);
1704     file_verify_wait ();
1705     break;
1706     }
1707     }
1708    
1709     wipememory (&ctx->pass_cb, sizeof (ctx->pass_cb));
1710     free_if_alloc (fn);
1711     fm_state_release (ctx);
1712     return count;
1713     }
1714    
1715    
1716     const char*
1717     default_dirname (const char *name)
1718     {
1719     char * p = strrchr( name, '\\' );
1720     if( !p )
1721     return NULL;
1722     return p+1;
1723     } /* default_dirname */
1724    
1725    
1726     int
1727     fm_encrypt_directory( fm_state_t c, const char * name )
1728     {
1729     PK_FILE_LIST list = NULL;
1730     WIN32_FIND_DATA findbuf;
1731     HANDLE hd;
1732     const char * s;
1733     char * patt = NULL, * p;
1734     int rc = 0;
1735    
1736     if( !is_directory( name ) )
1737     return -1;
1738     patt = new char[strlen( name ) + 4];
1739     if( !patt )
1740     BUG( NULL );
1741     strcpy( patt, name );
1742     strcat( patt, "\\*" );
1743     hd = FindFirstFile( patt, &findbuf );
1744     if( !hd ) {
1745     free_if_alloc( patt );
1746     return -1;
1747     }
1748     if( strcmp( findbuf.cFileName, "." ) && strcmp( findbuf.cFileName, ".." ) ) {
1749     p = make_filename( name, findbuf.cFileName, NULL );
1750     pk_list_add( &list, p );
1751     free_if_alloc( p );
1752     }
1753     while( FindNextFile( hd, &findbuf ) ) {
1754     if( strcmp( findbuf.cFileName, "." ) && strcmp( findbuf.cFileName, ".." ) ) {
1755     p = make_filename( name, findbuf.cFileName, NULL );
1756     pk_list_add( &list, p );
1757     free_if_alloc( p );
1758     }
1759     }
1760     s = get_filename_dlg( c->dlg, FILE_SAVE, _("Choose a Name for the Archive"),
1761     NULL, default_dirname( name ) );
1762     if( !s ) {
1763     msg_box( c->dlg, _("Invalid archive name. Exit."), _("Encrypt Directory"), MB_ERR );
1764     rc = -1;
1765     goto leave;
1766     }
1767    
1768     rc = pk_archiv_create( list, s );
1769     if( rc )
1770     msg_box( c->dlg, _("Could not create zip archive."), _("Encrypt Directory"), MB_ERR );
1771     else {
1772     fm_encrypt( c, s, 0 );
1773     unlink( s );
1774     }
1775     leave:
1776     FindClose (hd);
1777     pk_list_free( list );
1778     free_if_alloc( patt );
1779     return rc;
1780     } /* fm_encrypt_directory */
1781    
1782    
1783     static int CALLBACK
1784     fm_cmp_cb( LPARAM first, LPARAM second, LPARAM sortby )
1785     {
1786     const char * a = 0, * b = 0;
1787    
1788     switch( (int)sortby ) {
1789     case FM_SORT_STAT:
1790     break;
1791     case FM_SORT_NAME:
1792     break;
1793     case FM_SORT_OP:
1794     break;
1795     }
1796     return stricmp( a, b );
1797     } /* fm_cmp_cb */
1798    
1799    
1800     int
1801     fm_sort( listview_ctrl_t lv, int sortby )
1802     {
1803     return listview_sort_items( lv, sortby, fm_cmp_cb );
1804     } /* fm_sort */
1805    
1806    
1807     void
1808     fm_print_md( listview_ctrl_t lv, HWND dlg, int mdalgo )
1809     {
1810     struct md_file_s mdctx;
1811    
1812     if( listview_count_items( lv, 0 ) == 0 )
1813     return;
1814     memset (&mdctx, 0, sizeof (mdctx));
1815     mdctx.lv = lv;
1816     mdctx.mdalgo = mdalgo;
1817     DialogBoxParam( glob_hinst, (LPCTSTR)IDD_WINPT_FILE_MDSUM, dlg,
1818     mdsum_dlg_proc, (LPARAM)&mdctx );
1819     } /* fm_print_md */
1820    
1821    
1822     int
1823     fm_send_file (listview_ctrl_t lv)
1824     {
1825     char buf[128];
1826     int rc;
1827    
1828     rc = listview_get_item_text (lv, -1, 1, buf, sizeof (buf)-1);
1829     if (rc == -1)
1830     return 0;
1831     /*mapi_send_ascfile (buf); XXX */
1832     return 0;
1833     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26