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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 295 - (hide annotations)
Tue Mar 13 18:53:40 2007 UTC (17 years, 11 months ago) by twoaday
File size: 51683 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26