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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (show annotations)
Fri Oct 28 07:15:26 2005 UTC (19 years, 4 months ago) by twoaday
File size: 45620 byte(s)
A lot of bug fixes. See ChangeLog.

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26