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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide annotations)
Fri Oct 28 08:25:30 2005 UTC (19 years, 4 months ago) by werner
File size: 45692 byte(s)
Readded lost changes from revision 40

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26