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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26