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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (hide annotations)
Fri Oct 28 07:15:26 2005 UTC (19 years, 4 months ago) by twoaday
File size: 45620 byte(s)
A lot of bug fixes. See ChangeLog.

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26