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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide annotations)
Wed Oct 12 10:04:26 2005 UTC (19 years, 4 months ago) by twoaday
File size: 44410 byte(s)
First testing phase finished.
Provide bug fixes for a lot of (minor) problems.

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26