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

Contents of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (show annotations)
Wed Oct 26 11:20:09 2005 UTC (19 years, 4 months ago) by twoaday
File size: 46087 byte(s)
2005-10-25  Timo Schulz  <twoaday@g10code.com>
                                                                                
        * wptGPGUtil.cpp (create_process): Hide window.
        * wptKeyPropsDlg.cpp (get_photo_tmpname): New.
        * wptClipSignEncDlg.cpp (clip_signenc_dlg_proc): Remove
        static var 'enable'.
        * wptKeygenDlg.cpp (keygen_dlg_proc): Likewise.
        (gpg_genkey_params): Make sure all primary keys are capable
        for signing and certification.
        * wptKeySigDlg.cpp (is_sig): If no item is selected, return 0.
        * wptGPG.cpp (gnupg_access_keyring): Check return value for
        NULL. Noted by Ralf.
        (get_gnupg_prog): Simplified.
        (check_homedir): Fixed. Return 0 when the dir is successfully created.
        * wptKeyManagerDlg.cpp (km_file_import): Use the hourglass to
        indicate a pending GPG process.
        * wptFileManager.cpp (op_begin, op_end): New. Indicate an start
        and and of an operation. For now just the cursor changes.
        (fm_parse_command_line): Remove debug output. Thanks to Ralf again.
        * WinPT.cpp (WinMain): Check if there is already an instance and
        set a variable early as possible.
        (load_gettext): If a previous instance was found, do not output
        any errors. Kudos to Ralf.


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26