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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 48 - (hide annotations)
Mon Oct 31 21:14:11 2005 UTC (19 years, 4 months ago) by werner
File size: 45712 byte(s)
More changes.  Compiles again but there are at least gettext issues with
w32-gettext.c.  I can't get a gpg-error build with ENABLE_NLS.

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26