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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 76 - (hide annotations)
Thu Nov 10 14:07:06 2005 UTC (19 years, 3 months ago) by twoaday
File size: 45650 byte(s)
2005-11-09  Timo Schulz  <ts@g10code.com>
 
        * wptNLS.c (get_gettext_langid): Map user language id to
        printable gettext language strings.
        * wptRegistry.cpp (get_reg_entry_mo): Support for the
        gettext environment.
        * wptFileManager.cpp (fm_encrypt): Close all files before
        the wipe procedure is called.
        * wptVerlist.cpp (verlist_add_sig): Handle the case the
        issuer is not valid but the signature is.
        (verlist_add_sig_log): Likewise. Thanks to the folks on
        winpt-users.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26