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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (show annotations)
Mon Oct 24 08:03:48 2005 UTC (19 years, 4 months ago) by twoaday
File size: 45805 byte(s)
2005-10-23  Timo Schulz  <twoaday@g10code.com>
 
        * wptFileManager.cpp (fm_get_file_type): Detect detached sigs.
        * wptKeyList.cpp (keylist_cmp_cb): Take care of expired/revoked keys.
        (get_ext_validity): New.
        * wptFileVerifyDlg.cpp (file_verify_dlg_proc): Several cleanups.
        * wptClipEditDlg.cpp (load_clipboard): Factored out some code into
        this function.
        (load_clipboard_from_file): Likewise.
        (save_clipboard_to_file): New.
        * wptKeyManagerDlg.cpp (keyprops_dlg_proc): Fix stack overflow.

For complete details, see the ChangeLog files.

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26