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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 77 - (hide annotations)
Mon Nov 14 15:01:01 2005 UTC (19 years, 3 months ago) by twoaday
File size: 47103 byte(s)
2005-11-12  Timo Schulz  <ts@g10code.com>
 
        Fix more GCC warnings.
 
2005-11-10  Timo Schulz  <ts@g10code.com>
 
        * wptClipSignDlg.cpp (one_key_proc): Use
        release_gpg_passphrase_cb() to free the context.
        * wptListView.cpp (listview_deselect_all): New.
        * wptMAPI.cpp (mapi_send_pubkey): Works again.
        * wptFileManagerDlg.cpp (file_manager_dlg_proc): Support encrypt &
        zip.
        * wptPassphraseCB.cpp (passphrase_callback_proc): Fix passphrase
        caching for signing operations.
        * wptKeyManager.cpp (km_send_to_mail_recipient): Works again.
        * wptFileManager.cpp (fm_send_file): Likewise.
        (fm_encrypt_into_zip): New.
         

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26