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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (show annotations)
Sat Nov 5 12:28:12 2005 UTC (19 years, 3 months ago) by twoaday
File size: 45643 byte(s)
More minor fixes...

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26