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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 105 - (show annotations)
Wed Nov 30 10:22:00 2005 UTC (19 years, 3 months ago) by twoaday
File size: 48279 byte(s)
Several cleanups and improved translation.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26