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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 193 - (show annotations)
Sat Apr 1 12:36:35 2006 UTC (18 years, 11 months ago) by twoaday
File size: 48156 byte(s)
2006-03-31  Timo Schulz  <ts@g10code.de>
 
        * wptCommonDlg.cpp (nls_load_langlist): New.
        (nsl_set_language): New.
        (nls_dlg_proc): New.
        (select_language): New. Allow user to select the language.
        * wptNLS.c (get_gettext_langid): Updated available languages.
        * WinPT.cpp (WinMain): Allow to select the languag on first
        start in non-installer environments.
        * wptVerifyList.cpp (verlist_build): Simplified.
        (verlist_add_sig_log): Likewise.
        * wptListview.cpp (listview_set_column_width,
        listview_get_selected_item): New.
        * wptKeyManager.cpp (gpg_clip_export): Merged into..
        (km_clip_export): ..this function.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26