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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 48 - (show 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 /* 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 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <sys/types.h>
30 #include <sys/types.h>
31 #include <windows.h>
32 #include <commdlg.h>
33 #include <io.h>
34 #include <stdio.h>
35
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 #include "wptCrypto.h"
54
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 Return value: -1 for success. */
79 static int
80 is_floppy_disc (const char *fname)
81 {
82 char drv[32] = {0};
83 int max = sizeof (drv)-1;
84 int i=0;
85
86 if (!strstr (fname, ":\\"))
87 return 0;
88
89 while (fname && *fname && *fname != '\\' && i < max)
90 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 static int
103 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 u32 fattr;
122 int id = 0;
123
124 if (file_exist_check (fname))
125 return; /* Does not exist */
126
127 fattr = GetFileAttributes (fname);
128 if ((fattr & FILE_ATTRIBUTE_READONLY) && force)
129 id = IDYES;
130 else if (fattr & FILE_ATTRIBUTE_READONLY)
131 id = log_box (_("File Manager"), MB_YESNO,
132 _("\"%s\" has read-only attribute.\n"
133 "Set attribute to normal?"), fname);
134 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 }
139 }
140
141
142 /* Return 1 if the given path @fname is a directory, 0 otherwise. */
143 static int
144 is_directory (const char *fname)
145 {
146 return GetFileAttributes (fname) & FILE_ATTRIBUTE_DIRECTORY? 1 : 0;
147 }
148
149
150 /* Return -1 if the given name @name is a valid PGP extension. */
151 static int
152 is_openpgp_ext (const char *name)
153 {
154 if (stristr (name, ".gpg") || stristr (name, ".asc")
155 || stristr (name, ".sig") || stristr (name, ".pgp"))
156 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 for (i=0; (val = mm_files[i]); i++) {
188 if (!stricmp (p, val))
189 return -1;
190 }
191 return 0;
192 }
193
194
195 /* Return a GPG file extension which depends on the operation
196 mode in @ctx and the sig mode @sigmode. */
197 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 /* Quote a file to avoid shell problems with spaces in the files. */
211 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 }
226
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 PACKET *pkt;
284 const char *s = NULL;
285 int i = 0, rc = 0;
286
287 if (r_type)
288 *r_type = PGP_NONE;
289 if (!fname) {
290 log_debug ("fm_get_file_type: !fname\r\n");
291 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 log_box (_("File Manager"), MB_ERR, "\"%s\": %s", fname, s);
301 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 pkt = (PACKET *)calloc (1, sizeof *pkt);
315 if (!pkt)
316 BUG (NULL);
317 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 memset (c, 0, sizeof *c);
408 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 for (i = 0; i < listview_count_items( lv, 0 ); i++) {
443 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 break; /* XXX: fixme? */
516 }
517 return rc;
518 }
519
520
521 /* 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 int
547 fm_add_opened_files (listview_ctrl_t lv, HWND dlg)
548 {
549 OPENFILENAME open;
550 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 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 open.Flags = OFN_ALLOWMULTISELECT|OFN_EXPLORER ;
565
566 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 }
592 if (n == 1) /* single file selected. */
593 rc = add_single_file (lv, path);
594 if (path)
595 free (path);
596 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 const char *s;
1253 s = get_filesave_dlg (c->dlg, _("Choose Filename for Output"),
1254 NULL, NULL);
1255 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