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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (hide 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 twoaday 2 /* wptFileManager.cpp - File Manager routines
2     * Copyright (C) 2001-2005 Timo Schulz
3 twoaday 24 * Copyright (C) 2005 g10 Code GmbH
4 twoaday 2 *
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 twoaday 33 #include "wptZIP.h"
44 twoaday 2 #include "wptUTF8.h"
45     #include "wptRegistry.h"
46 twoaday 23 #include "wptImport.h"
47 twoaday 2
48     #include "openpgp.h"
49    
50 twoaday 34 #define op_begin() SetCursor (LoadCursor (NULL, IDC_WAIT))
51     #define op_end() SetCursor (LoadCursor (NULL, IDC_ARROW))
52    
53 twoaday 25 void progress_cleanup (progress_filter_s *pfx);
54 twoaday 32 BOOL CALLBACK file_secdel_confirm_dlg_proc (HWND dlg, UINT msg,
55     WPARAM wparam, LPARAM lparam);
56 twoaday 25 char* gpg_keylist_to_pattern (gpgme_key_t *rset, int n);
57 twoaday 23 gpgme_error_t sym_passphrase_cb (void *hook, const char *hint, const char *pass_inf,
58     int prev_was_bad, int fd);
59    
60 twoaday 2 /*-- wptFileVerifyDlg.cpp --*/
61 twoaday 32 void file_verify_add_state (file_sig_ctx_t c);
62 twoaday 2 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 twoaday 23
70 twoaday 32 /* 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 twoaday 2 {
75 twoaday 32 char drv[32] = {0};
76     int i=0;
77 twoaday 2
78 twoaday 32 if (!strstr (fname, ":\\"))
79     return 0;
80 twoaday 2
81 twoaday 32 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 twoaday 2
91    
92 twoaday 32 /* Ask the user to overwrite file @fname.
93     Return value: 0 for cancel. */
94 twoaday 2 int
95 twoaday 32 overwrite_file (const char *fname)
96 twoaday 2 {
97     int id;
98    
99     if (file_exist_check (fname))
100 twoaday 23 return -1;
101 twoaday 2 id = log_box (_("File Manager"), MB_YESNO,
102     _("\"%s\" already exists.\n"
103     "Replace existing file?"), fname);
104 twoaday 23 return id == IDNO ? 0 : -1;
105 twoaday 32 }
106 twoaday 2
107    
108 twoaday 32 /* Removes 'critical' attributes from the file @fname.
109     If @force is 1, the user is not asked for permission. */
110 twoaday 2 static void
111 twoaday 32 remove_crit_file_attrs (const char *fname, int force)
112 twoaday 2 {
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 twoaday 32 }
130 twoaday 2
131    
132     static int inline
133 twoaday 32 is_directory (const char *fname)
134 twoaday 2 {
135     return GetFileAttributes (fname) & FILE_ATTRIBUTE_DIRECTORY? 1 : 0;
136 twoaday 32 }
137 twoaday 2
138    
139     static int inline
140 twoaday 32 is_openpgp_ext (const char *name)
141 twoaday 2 {
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 twoaday 23 file_get_extension (gpgme_ctx_t ctx, gpgme_sig_mode_t sigmode)
186 twoaday 2 {
187 twoaday 23 int use_armor = gpgme_get_armor (ctx);
188 twoaday 2
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 twoaday 32 }
195 twoaday 2
196    
197 twoaday 32 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 twoaday 2 int
349 twoaday 32 fm_build (listview_ctrl_t *lv, HWND ctrl)
350 twoaday 2 {
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 twoaday 23 /* XXX rc = gpgme_recipients_new (&c->recp);*/
397     /* XXX gpgme_set_comment (c->ctx, "Generated by WinPT "PGM_VERSION); */
398 twoaday 2 *ctx = c;
399     return 0;
400     } /* fm_state_new */
401    
402    
403 twoaday 23 /* Release the FM state handle @c. */
404 twoaday 2 void
405     fm_state_release (fm_state_t c)
406     {
407 twoaday 23 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 twoaday 2 }
415 twoaday 23 free_if_alloc (c->opaque);
416     free_if_alloc (c->output);
417     delete c; c = NULL;
418     }
419 twoaday 2
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 twoaday 32 fm_set_ftype (listview_ctrl_t lv, const char *name)
440 twoaday 2 {
441     const char *type;
442     int rc;
443    
444     rc = fm_check_for_entry (lv, name);
445     if (rc)
446     return 0;
447 twoaday 32 type = fm_get_file_type (name, NULL);
448 twoaday 2 if (!type || !strcmp (type, "UNKNOWN"))
449 twoaday 32 type = gnupg_check_file_ext (name, NULL);
450 twoaday 2 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 twoaday 23 /* Add the drag & drop files from @dd_files to the
486     list view control @lv. */
487 twoaday 2 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 twoaday 23 memset (name, 0, sizeof (name));
494     nfiles = DragQueryFile (dd_files, 0xFFFFFFFF, NULL, 0);
495 twoaday 2 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 twoaday 23 }
506 twoaday 2
507    
508     int
509     fm_add_opened_files (listview_ctrl_t lv, HWND dlg)
510     {
511     OPENFILENAME open;
512     const char *type;
513 twoaday 32 char file[512] = "";
514 twoaday 2 int rc;
515    
516 twoaday 32 /* XXX: support to add multiple files. */
517     memset (&open, 0, sizeof (open));
518 twoaday 2 open.lStructSize = sizeof (OPENFILENAME);
519     open.hInstance = glob_hinst;
520     open.lpstrTitle = _("File Open");
521 twoaday 23 open.lpstrFilter = _("All Files (*.*)\0*.*\0\0");
522 twoaday 2 open.hwndOwner = dlg;
523     open.lpstrFile = file;
524     open.nMaxFile = sizeof (file) - 1;
525     open.Flags = 0;
526    
527     if (GetOpenFileName (&open)) {
528 twoaday 32 type = fm_get_file_type (open.lpstrFile, NULL);
529 twoaday 2 if (!type)
530     return WPTERR_FILE_OPEN;
531     if (!strcmp (type, "UNKNOWN"))
532 twoaday 32 type = gnupg_check_file_ext (open.lpstrFile, NULL);
533 twoaday 2 rc = listview_add_item (lv, "");
534 twoaday 32 if (!rc) {
535 twoaday 2 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 twoaday 23 }
542 twoaday 2
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 twoaday 32 if (!fname) {
554 twoaday 23 gpg_data_new_from_clipboard (&dat, 0);
555     gpg_data_release_and_set_file (dat, "gpgme.tmp");
556 twoaday 2
557     fp = gpg_iobuf_open ("gpgme.tmp");
558     if (!fp)
559     return 0;
560     gpg_iobuf_ioctl (fp, 3, 1, NULL);
561 twoaday 32 if (gpg_use_armor_filter(fp)) {
562 twoaday 2 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 twoaday 4 if (strcmp (status, "ENCRYPTED")
630     && strcmp (status, "SYMKEYENC"))
631 twoaday 2 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 twoaday 5
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 twoaday 2 memset (&pfx, 0, sizeof (pfx));
779 twoaday 25 ctx->prog_cb = NULL;
780     if (cmd != FM_VERIFY && cmd != FM_SIGN /*&& reg_prefs.fm.progress > 0*/) {
781 twoaday 5 pfx.hwnd = dlg;
782 twoaday 25 /*gpgme_set_progress_cb (ctx->ctx, progress_callback, &pfx);*/
783     /*ctx->prog_cb = &pfx;*/
784 twoaday 5 }
785 twoaday 2
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 twoaday 4 if (!strcmp( status, "ENCRYPTED" ) && fm_cmd == FM_DECRYPT)
820 twoaday 2 n++;
821 twoaday 4 if (!strcmp( status, "UNKNOWN" ) && fm_cmd == FM_SIGN)
822 twoaday 2 n++;
823 twoaday 23 if (fm_cmd == FM_WIPE)
824 twoaday 2 ndel++;
825     }
826    
827 twoaday 4 if (n > 1 && fm_cmd != FM_SYMENC)
828 twoaday 2 ctx->cache_cb = 1;
829    
830 twoaday 4 if (fm_cmd == FM_WIPE && ndel > 0) {
831 twoaday 23 memset (&confirm, 0, sizeof confirm);
832     confirm.lv_files = lv;
833 twoaday 2 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 twoaday 25 case FM_VERIFY: rc = fm_verify (ctx, sig_detached, fname);break;
862 twoaday 2 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 twoaday 24 release_gpg_passphrase_cb (&ctx->pass_cb);
884 twoaday 2 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 twoaday 23 /* Wipe the given file @name with the delete mode
905     from the configuration.
906     Return value: 0 on success. */
907 twoaday 2 int
908 twoaday 23 fm_wipe (const char *name)
909 twoaday 2 {
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 twoaday 23 }
918 twoaday 2
919    
920 twoaday 23 /* Dump out the given PGP packets from file @name in a dialog. */
921 twoaday 2 int
922 twoaday 23 fm_list (const char *name, HWND dlg)
923 twoaday 2 {
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 twoaday 23 }
929 twoaday 2
930    
931     static int
932 twoaday 23 ask_filename (fm_state_t c, const char *msg, char **dst)
933 twoaday 2 {
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 twoaday 24 if (dst != NULL)
941     free_if_alloc (*dst);
942 twoaday 2 free_if_alloc (c->output);
943     c->output = m_strdup (s);
944     if (!c->output)
945     BUG (0);
946 twoaday 23 if (dst)
947     *dst = fm_quote_file (s);
948 twoaday 2 return 0;
949     }
950    
951    
952     int
953 twoaday 25 fm_encrypt (fm_state_t c, const char *name, int sign)
954 twoaday 2 {
955     gpgme_error_t err;
956     gpgme_key_t key = NULL;
957     gpgme_ctx_t ctx = c->ctx;
958 twoaday 23 file_data_t in=NULL, out=NULL;
959 twoaday 25 char *keyid = NULL, ext[5];
960 twoaday 2 int no_compr = 0;
961     int rc = 0;
962 twoaday 24
963 twoaday 2 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 twoaday 23 strcpy (c->output, name);
968     strcat (c->output, ext);
969 twoaday 2
970 twoaday 23 if (!overwrite_file (c->output)) {
971     rc = ask_filename (c, _("Enter filename for encrypted file"), NULL);
972 twoaday 2 if (rc)
973     goto leave;
974     }
975 twoaday 23
976 twoaday 24 err = gpg_file_data_new (name, 1, &in);
977 twoaday 23 if (err)
978     goto leave;
979 twoaday 24 err = gpg_file_data_new (c->output, 0, &out);
980 twoaday 23 if (err)
981     goto leave;
982 twoaday 25
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 twoaday 2
990 twoaday 23 /* XXX
991 twoaday 2 no_compr = is_multi_media (name);
992     gpgme_control (ctx, GPGME_CTRL_NO_COMPR, no_compr);
993 twoaday 23 */
994 twoaday 2
995     if (sign) {
996     if (gpgme_signers_enum (ctx, 0) == NULL) {
997     keyid = get_gnupg_default_key ();
998     if (!keyid) {
999 twoaday 23 msg_box (c->dlg, _("Could not get default secret key."),
1000 twoaday 2 _("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 twoaday 23 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 twoaday 2 }
1016     if (!c->init_cb || !c->cache_cb) {
1017 twoaday 23 set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_SIGN,
1018 twoaday 2 c->dlg, _("Signing"));
1019     c->init_cb = 1;
1020     }
1021 twoaday 34 op_begin ();
1022 twoaday 23 err = gpgme_op_encrypt_sign (ctx, c->recp, GPGME_ENCRYPT_ALWAYS_TRUST,
1023     in->dat, out->dat);
1024 twoaday 34 op_end ();
1025 twoaday 2 if (!c->cache_cb)
1026 twoaday 24 release_gpg_passphrase_cb (&c->pass_cb);
1027 twoaday 2 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 twoaday 25 if (gpgme_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
1034 twoaday 2 agent_del_cache (keyid);
1035     rc = WPTERR_GENERAL;
1036     goto leave;
1037     }
1038     }
1039     else {
1040 twoaday 34 op_begin ();
1041 twoaday 25 err = gpgme_op_encrypt (ctx, c->recp, GPGME_ENCRYPT_ALWAYS_TRUST,
1042 twoaday 23 in->dat, out->dat);
1043 twoaday 34 op_end ();
1044 twoaday 2 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 twoaday 23 if (in)
1055     gpg_file_data_release (in);
1056     if (out)
1057     gpg_file_data_release (out);
1058 twoaday 2 free_if_alloc (keyid);
1059     return rc;
1060 twoaday 23 }
1061 twoaday 2
1062    
1063     int
1064     fm_sym_encrypt (fm_state_t c, const char * name)
1065     {
1066 twoaday 23 gpgme_ctx_t ctx = c->ctx;
1067     gpgme_error_t err;
1068     file_data_t in=NULL, out=NULL;
1069 twoaday 2 int rc = 0, cancel = 0;
1070     char * src = NULL, * dst = NULL;
1071 twoaday 23 char ext[5], * pass;
1072 twoaday 2
1073 twoaday 22 pass = request_passphrase2 (_("Symmetric"), 0, &cancel);
1074 twoaday 2 if (cancel)
1075     return 0;
1076    
1077 twoaday 23 /* XXX gpgme_control (ctx, GPGME_CTRL_CIPHER, -1);*/
1078 twoaday 2 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 twoaday 23 strcat (c->output, ext);
1084 twoaday 2
1085     if (overwrite_file (c->output) == 0) {
1086     rc = WPTERR_GENERAL;
1087     goto leave;
1088     }
1089 twoaday 23
1090     gpgme_set_passphrase_cb (ctx, sym_passphrase_cb, pass);
1091    
1092 twoaday 24 err = gpg_file_data_new (name, 1, &in);
1093 twoaday 23 if (err)
1094     goto leave;
1095 twoaday 24 err = gpg_file_data_new (c->output, 0, &out);
1096 twoaday 23 if (err)
1097     goto leave;
1098    
1099 twoaday 34 op_begin ();
1100     err = gpgme_op_encrypt (ctx, NULL, GPGME_ENCRYPT_ALWAYS_TRUST,
1101     in->dat, out->dat);
1102     op_end ();
1103 twoaday 2 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 twoaday 23 if (in)
1115     gpg_file_data_release (in);
1116     if (out)
1117     gpg_file_data_release (out);
1118 twoaday 2 sfree_if_alloc (pass);
1119     return rc;
1120     } /* fm_sym_encrypt */
1121    
1122    
1123 twoaday 25 /* 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 twoaday 27 for (r=rset; r; r = r->next) {
1160 twoaday 28 if (gpgme_err_code (r->status) == GPG_ERR_NO_SECKEY)
1161 twoaday 27 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 twoaday 25 }
1168     return false;
1169     }
1170    
1171    
1172 twoaday 23 /* Decrypt the file @name. */
1173 twoaday 2 int
1174 twoaday 23 fm_decrypt (fm_state_t c, const char *name)
1175 twoaday 2 {
1176     gpgme_error_t err;
1177 twoaday 25 gpgme_ctx_t ctx = c->ctx;
1178 twoaday 23 gpgme_decrypt_result_t res;
1179     gpgme_verify_result_t sigres;
1180     file_data_t in =NULL, out=NULL;
1181 twoaday 25 int is_signed = 0;
1182 twoaday 2 int rc = 0;
1183    
1184     if (!c->init_cb || !c->cache_cb) {
1185 twoaday 23 set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_DECRYPT,
1186 twoaday 2 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 twoaday 25 const char *s = get_filesave_dlg (c->dlg, _("Choose Filename for Output"),
1197 twoaday 2 NULL, NULL);
1198 twoaday 25 if (s) {
1199 twoaday 23 free_if_alloc (c->output);
1200     c->output = m_strdup (s);
1201     if (!c->output)
1202     BUG (NULL);
1203 twoaday 2 }
1204     }
1205    
1206     if (overwrite_file (c->output) == 0) {
1207 twoaday 23 rc = ask_filename (c, _("Please enter filename for plaintext file"), NULL);
1208 twoaday 2 if (rc)
1209     goto leave;
1210     }
1211 twoaday 23
1212     remove_crit_file_attrs (c->output, 0);
1213    
1214 twoaday 24 err = gpg_file_data_new (name, 1, &in);
1215 twoaday 23 if (err)
1216     goto leave;
1217 twoaday 24 err = gpg_file_data_new (c->output, 0, &out);
1218 twoaday 23 if (err)
1219     goto leave;
1220    
1221 twoaday 34 op_begin ();
1222 twoaday 23 err = gpgme_op_decrypt_verify (ctx, in->dat, out->dat);
1223 twoaday 34 op_end ();
1224 twoaday 23 if (!c->cache_cb)
1225 twoaday 24 release_gpg_passphrase_cb (&c->pass_cb);
1226 twoaday 23 if (c->pass_cb.cancel) {
1227 twoaday 2 rc = WPTERR_GENERAL;
1228     goto leave;
1229     }
1230 twoaday 23
1231     res = gpgme_op_decrypt_result (ctx);
1232 twoaday 25 if (res && res->recipients && !secret_key_available (res->recipients)) {
1233     const char *keyid = res->recipients->keyid;
1234 twoaday 23 char *p = get_key_userid (keyid+8);
1235 twoaday 25 gpgme_pubkey_algo_t pkalgo = res->recipients->pubkey_algo;
1236    
1237 twoaday 2 log_box( _("Decryption"), MB_ERR,
1238     _("Encrypted with %s key, ID %s.%s\n"
1239     "Decryption failed: secret key not available."),
1240 twoaday 23 get_key_pubalgo (pkalgo), keyid+8, p);
1241 twoaday 2 rc = WPTERR_GENERAL;
1242 twoaday 23 free_if_alloc (p);
1243 twoaday 2 goto leave;
1244     }
1245 twoaday 23 else if (err) {
1246 twoaday 24 msg_box (c->dlg, gpgme_strerror (err), _("Decrypt"), MB_ERR);
1247 twoaday 2 rc = WPTERR_GENERAL;
1248     goto leave;
1249     }
1250 twoaday 24 if (file_exist_check (c->output)) {
1251     log_box ("Decrypt", MB_ERR, _("Decryption failed.\n%s: does not exist."), c->output);
1252 twoaday 2 rc = WPTERR_GENERAL;
1253     }
1254    
1255 twoaday 23 sigres = gpgme_op_verify_result (ctx);
1256 twoaday 25 if (sigres && sigres->signatures)
1257     show_verify_result (sigres);
1258 twoaday 23
1259 twoaday 2
1260     leave:
1261 twoaday 23 if (in)
1262     gpg_file_data_release (in);
1263     if (out)
1264     gpg_file_data_release (out);
1265 twoaday 2 return rc;
1266 twoaday 23 }
1267 twoaday 2
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 twoaday 23 file_data_t in=NULL, out=NULL;
1276 twoaday 2 char ext[5];
1277    
1278 twoaday 25 if (!c->init_cb || !c->cache_cb) {
1279 twoaday 23 set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_SIGN, c->dlg, _("Signing") );
1280 twoaday 2 c->init_cb = 1;
1281     }
1282    
1283 twoaday 23 free_if_alloc (c->output);
1284 twoaday 25 c->output = new char[strlen (name) + 5 + 1];
1285 twoaday 23 if( !c->output)
1286 twoaday 2 BUG( NULL );
1287 twoaday 25 strcpy (ext, file_get_extension (ctx, c->sigmode));
1288     strcpy (c->output, name);
1289     strcat (c->output, ext);
1290 twoaday 2
1291     if (!overwrite_file (c->output)) {
1292 twoaday 23 rc = ask_filename (c, _("Enter filename for signed file"), NULL);
1293 twoaday 2 if (rc)
1294     goto leave;
1295     }
1296 twoaday 25 remove_crit_file_attrs (c->output, 0);
1297 twoaday 23
1298 twoaday 24 err = gpg_file_data_new (name, 1, &in);
1299 twoaday 23 if (err)
1300     goto leave;
1301 twoaday 24 err = gpg_file_data_new (c->output, 0, &out);
1302 twoaday 23 if (err)
1303     goto leave;
1304    
1305 twoaday 34 op_begin ();
1306 twoaday 23 err = gpgme_op_sign (ctx, in->dat, out->dat, c->sigmode);
1307 twoaday 34 op_end ();
1308 twoaday 2 if( !c->cache_cb )
1309 twoaday 24 release_gpg_passphrase_cb (&c->pass_cb);
1310 twoaday 2 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 twoaday 23 if (in)
1322     gpg_file_data_release (in);
1323     if (out)
1324     gpg_file_data_release (out);
1325 twoaday 2 return rc;
1326 twoaday 25 }
1327 twoaday 2
1328    
1329     static int
1330 twoaday 25 fm_add_sig_stat (file_sig_ctx_t log)
1331 twoaday 2 {
1332     gpgme_key_t key;
1333 twoaday 23 const char *kid;
1334 twoaday 2 int not_found = 0;
1335    
1336 twoaday 23 kid = log->sig->fpr;
1337     if (!kid)
1338 twoaday 25 BUG (NULL);
1339 twoaday 23 if (strlen (kid) == 40)
1340 twoaday 25 kid += 32;
1341     else if (strlen (kid) == 32)
1342 twoaday 23 kid += 24;
1343     if (get_pubkey (kid, &key))
1344 twoaday 25 log->use_uid = 0;
1345     else {
1346 twoaday 23 log->user_id = key->uids->uid;
1347 twoaday 25 log->use_uid = 1;
1348 twoaday 2 }
1349 twoaday 23 file_verify_add_state (log);
1350 twoaday 2 return 0;
1351 twoaday 25 }
1352 twoaday 2
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 twoaday 25 /* 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 twoaday 2 {
1427 twoaday 25 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 twoaday 2 file = fname;
1451     }
1452     }
1453 twoaday 25 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 twoaday 2 else {
1462 twoaday 25 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 twoaday 23 if (strstr (name, ".asc"))
1469 twoaday 2 c->sigmode = GPGME_SIG_MODE_CLEAR;
1470     else
1471     c->sigmode = GPGME_SIG_MODE_NORMAL;
1472     }
1473 twoaday 25 return 0;
1474     }
1475 twoaday 2
1476 twoaday 25
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 twoaday 23 memset (&log, 0, sizeof (log));
1497 twoaday 25 log.file = m_strdup (name);
1498     if (!log.file)
1499     BUG (NULL);
1500 twoaday 23 file_verify_create_dlg ();
1501    
1502 twoaday 24 err = gpg_file_data_new (name, 1, &in);
1503 twoaday 23 if (err)
1504     goto leave;
1505 twoaday 25 err = gpg_file_data_new (c->output, detached? 1 : 0, &out);
1506 twoaday 23 if (err)
1507     goto leave;
1508    
1509 twoaday 34 op_begin ();
1510 twoaday 23 if (c->sigmode == GPGME_SIG_MODE_DETACH)
1511 twoaday 25 err = gpgme_op_verify (ctx, in->dat, out->dat, NULL);
1512 twoaday 23 else
1513 twoaday 25 err = gpgme_op_verify (ctx, in->dat, in->dat, out->dat);
1514 twoaday 34 op_end ();
1515 twoaday 23 if (err) {
1516 twoaday 25 msg_box (c->dlg, gpgme_strerror (err), _("Verify"), MB_ERR);
1517 twoaday 2 rc = WPTERR_GENERAL;
1518     goto leave;
1519 twoaday 23 }
1520    
1521 twoaday 25 res = gpgme_op_verify_result (ctx);
1522 twoaday 23 for (s=res->signatures; s; s=s->next) {
1523     log.sig = s;
1524     fm_add_sig_stat (&log);
1525 twoaday 2 }
1526 twoaday 23 if (!c->output)
1527 twoaday 25 c->output = m_strdup (name); /* for later use */
1528 twoaday 2
1529     leave:
1530 twoaday 23 if (in)
1531     gpg_file_data_release (in);
1532     if (out)
1533     gpg_file_data_release (out);
1534 twoaday 25 if (log.file)
1535     delete []log.file;
1536 twoaday 2 return rc;
1537 twoaday 25 }
1538 twoaday 2
1539    
1540     int
1541 twoaday 23 fm_import (fm_state_t c, const char *name)
1542 twoaday 2 {
1543     gpgme_ctx_t ctx = c->ctx;
1544     gpgme_error_t err;
1545 twoaday 23 gpgme_import_result_t res;
1546     file_data_t keydata = NULL;
1547 twoaday 2 int rc = 0;
1548    
1549 twoaday 23 free_if_alloc (c->output);
1550     c->output = m_strdup (name);
1551     if (!c->output)
1552     BUG (NULL);
1553    
1554 twoaday 24 err = gpg_file_data_new (name, 1, &keydata);
1555 twoaday 23 if (err)
1556 twoaday 2 goto leave;
1557 twoaday 23
1558 twoaday 34 op_begin ();
1559 twoaday 23 err = gpgme_op_import (ctx, keydata->dat);
1560 twoaday 34 op_end ();
1561 twoaday 23 if (err) {
1562     msg_box (c->dlg, gpgme_strerror (err), _("Import"), MB_ERR);
1563     rc = WPTERR_GENERAL;
1564     goto leave;
1565 twoaday 2 }
1566 twoaday 23
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 twoaday 2 "(This key is NOT usable for encryption, etc)\n"
1572     "\n"
1573 twoaday 23 "Cannot import these key(s)!"), _("Import"), MB_INFO);
1574 twoaday 2 }
1575    
1576     leave:
1577 twoaday 23 if (keydata)
1578     gpg_file_data_release (keydata);
1579 twoaday 2 return rc;
1580     } /* fm_import */
1581    
1582    
1583 twoaday 23 /* Export the selected keys from the File Manager to a file. */
1584 twoaday 2 int
1585 twoaday 23 fm_export (fm_state_t c)
1586 twoaday 2 {
1587     int rc = 0, id = 0;
1588     gpgme_ctx_t ctx = c->ctx;
1589     gpgme_error_t err;
1590 twoaday 23 gpgme_key_t *rset = c->recp;
1591     file_data_t keydata = NULL;
1592 twoaday 2 const char *name, *s = NULL;
1593 twoaday 23 char *p = NULL, *patt = NULL;
1594 twoaday 2
1595 twoaday 23 if (!rset || !rset[0]) {
1596     msg_box (c->dlg, _("No key was selected for export."), _("Export"), MB_ERR);
1597 twoaday 2 rc = WPTERR_GENERAL;
1598     goto leave;
1599     }
1600    
1601 twoaday 23 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 twoaday 2 }
1610    
1611 twoaday 23 name = get_filename_dlg (c->dlg, FILE_SAVE, _("Choose Name for Key File"),
1612     NULL, p? p : NULL);
1613 twoaday 2
1614 twoaday 23 if (!name)
1615 twoaday 2 name = "keys.gpg";
1616    
1617 twoaday 25 patt = gpg_keylist_to_pattern (rset, c->n_recp);
1618 twoaday 23
1619 twoaday 24 err = gpg_file_data_new (name, 0, &keydata);
1620 twoaday 23 if (err)
1621     goto leave;
1622    
1623 twoaday 34 op_begin ();
1624 twoaday 23 err = gpgme_op_export (ctx, patt, 0, keydata->dat);
1625 twoaday 34 op_end ();
1626 twoaday 23 if (err) {
1627     msg_box (c->dlg, gpgme_strerror (err), _("Export"), MB_ERR);
1628     rc = WPTERR_GENERAL;
1629 twoaday 2 goto leave;
1630     }
1631 twoaday 23 log_box (_("GnuPG status"), MB_OK, _("Finished (Output: %s)"), name);
1632 twoaday 2
1633     leave:
1634 twoaday 23 if (keydata)
1635     gpg_file_data_release (keydata);
1636     if (patt)
1637     free (patt);
1638     free_if_alloc (p);
1639 twoaday 2
1640     return rc;
1641 twoaday 23 }
1642 twoaday 2
1643    
1644 twoaday 32 /* Parse the command line and process the given file. */
1645 twoaday 2 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 twoaday 32 int type;
1653 twoaday 2
1654 twoaday 32 if (!cmdl || !*cmdl)
1655 twoaday 2 return 0;
1656    
1657 twoaday 32 fm_state_new (&ctx);
1658     ctx->dlg = GetActiveWindow ();
1659     ctx->cache_cb = 1;
1660 twoaday 2
1661     p = cmdl;
1662 twoaday 32 if (p && *p > 32 && !stristr (p, "winpt.exe")
1663     && !strstr (p, "--" )) {
1664 twoaday 2 count++;
1665 twoaday 14 if (*p == '"') { /* need to remove quotes */
1666 twoaday 32 fn = new char[strlen (p)];
1667 twoaday 14 if (!fn)
1668 twoaday 32 BUG (NULL);
1669     memcpy (fn, p+1, strlen (p) - 2);
1670     fn[strlen (p) -2] = '\0';
1671 twoaday 2 }
1672     else
1673     fn = m_strdup (p);
1674 twoaday 32 s = fm_get_file_type (fn, &type);
1675 twoaday 2 if (!s || !strcmp (s, "UNKNOWN"))
1676 twoaday 32 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 twoaday 2 return count;
1682     }
1683 twoaday 32 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 twoaday 14 file_verify_use_event ();
1696 twoaday 32 if (type == PGP_SIG)
1697     detached = 1;
1698     fm_verify (ctx, detached, fn);
1699     file_verify_wait ();
1700 twoaday 2 break;
1701     }
1702     }
1703    
1704 twoaday 32 wipememory (&ctx->pass_cb, sizeof (ctx->pass_cb));
1705     free_if_alloc (fn);
1706     fm_state_release (ctx);
1707 twoaday 2 return count;
1708 twoaday 32 }
1709 twoaday 2
1710    
1711 twoaday 32 const char*
1712     default_dirname (const char *name)
1713 twoaday 2 {
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 twoaday 32 FindClose (hd);
1772 twoaday 2 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 twoaday 32 memset (&mdctx, 0, sizeof (mdctx));
1810 twoaday 2 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 twoaday 24 /*mapi_send_ascfile (buf); XXX */
1827 twoaday 2 return 0;
1828     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26