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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 94 - (hide annotations)
Wed Nov 23 12:16:55 2005 UTC (19 years, 3 months ago) by twoaday
File size: 47452 byte(s)
Change version to CVS.

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26