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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 77 - (show annotations)
Mon Nov 14 15:01:01 2005 UTC (19 years, 3 months ago) by twoaday
File size: 47103 byte(s)
2005-11-12  Timo Schulz  <ts@g10code.com>
 
        Fix more GCC warnings.
 
2005-11-10  Timo Schulz  <ts@g10code.com>
 
        * wptClipSignDlg.cpp (one_key_proc): Use
        release_gpg_passphrase_cb() to free the context.
        * wptListView.cpp (listview_deselect_all): New.
        * wptMAPI.cpp (mapi_send_pubkey): Works again.
        * wptFileManagerDlg.cpp (file_manager_dlg_proc): Support encrypt &
        zip.
        * wptPassphraseCB.cpp (passphrase_callback_proc): Fix passphrase
        caching for signing operations.
        * wptKeyManager.cpp (km_send_to_mail_recipient): Works again.
        * wptFileManager.cpp (fm_send_file): Likewise.
        (fm_encrypt_into_zip): New.
         

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26