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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (hide annotations)
Tue Oct 25 07:46:20 2005 UTC (19 years, 4 months ago) by twoaday
File size: 45802 byte(s)
More bug fixes and cleanups.
See ChangeLog for details.

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26