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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 273 - (hide annotations)
Fri Dec 8 10:22:17 2006 UTC (18 years, 2 months ago) by twoaday
File size: 51914 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26