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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 88 - (show annotations)
Mon Nov 21 12:06:59 2005 UTC (19 years, 3 months ago) by twoaday
File size: 47463 byte(s)
2005-11-21  Timo Schulz  <ts@g10code.com>
 
        * WinPT.cpp (WinMain): Implement --stop switch.
        * wptClipEditDlg.cpp (clip_edit_dlg_proc): Localize
        missing string.
        * wptPreferencesDlg.cpp (prefs_dlg_proc): Likewise.
        * wptKeygenDlg.cpp (keygen_dlg_proc): Verify valid context
        first. Thanks to Ralf.
        * wptFileManagerDlg.cpp (update_ui_items): New.
        * wptFileManager.cpp (fm_set_status): New sigmode param.
        Changed all callers.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26