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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 47 - (show annotations)
Mon Oct 31 14:04:59 2005 UTC (19 years, 4 months ago) by werner
File size: 45689 byte(s)
Minor changes; compiles now but gettext is still missing.

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26