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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 172 - (show annotations)
Mon Jan 30 13:47:35 2006 UTC (19 years, 1 month ago) by twoaday
File size: 48066 byte(s)
2006-01-30  Timo Schulz  <ts@g10code.de>
 
        * WinPT.cpp (check_readonly_attr): New.
        (load_gpg_env): Use it here.
        * wptRegistry.cpp (regist_int_winpt): Make sure
        the register extension is only offered once to the user.
         

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26