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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 271 - (hide annotations)
Sun Nov 5 08:57:45 2006 UTC (18 years, 3 months ago) by twoaday
File size: 51873 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 werner 36 int
925     fm_parse_files (listview_ctrl_t lv, HWND dlg, int cmd)
926     {
927     struct secdel_confirm_s confirm = {0};
928     struct progress_filter_s pfx, pfx2;
929     fm_state_s * ctx;
930     int fm_cmd, sig_detached = 0;
931     int rc = 0, i, n, ndel = 0;
932 twoaday 270 char fname[2*MAX_PATH+1], status[128];
933 werner 36
934     switch (cmd) {
935     case ID_FILEMISC_ENCRYPT: fm_cmd = FM_ENCRYPT; break;
936 twoaday 77 case ID_FILEMISC_ENCRYPT_ZIP:fm_cmd = FM_ENCRYPT_ZIP; break;
937 werner 36 case ID_FILEMISC_DECRYPT: fm_cmd = FM_DECRYPT; break;
938     case ID_FILEMISC_SYMENC: fm_cmd = FM_SYMENC; break;
939     case ID_FILEMISC_SIGN: fm_cmd = FM_SIGN; break;
940     case ID_FILEMISC_VERIFY: fm_cmd = FM_VERIFY; break;
941     case ID_FILEMISC_IMPORT: fm_cmd = FM_IMPORT; break;
942     case ID_FILEMISC_WIPE: fm_cmd = FM_WIPE; break;
943     case ID_FILEMISC_LIST: fm_cmd = FM_LIST; break;
944     case ID_FILEMISC_SIGNENC: fm_cmd = FM_SIGNENCRYPT; break;
945     default: return 1; /* unknown command */
946     }
947    
948     if (fm_get_current_pos (lv) == -1)
949 twoaday 77 return WPTERR_GENERAL;
950 werner 36 rc = fm_state_new (&ctx);
951     if (rc)
952     BUG (0);
953     ctx->dlg = dlg;
954    
955     // XXX: for file operations the progress dialog will be
956     // reloaded somewhere and thus a 'dummy' dialog remains
957    
958     /* we use it here to make sure that pfx_cleanup will not use
959     any weird values. */
960     memset (&pfx, 0, sizeof (pfx));
961     ctx->prog_cb = NULL;
962     if (cmd != FM_VERIFY && cmd != FM_SIGN /*&& reg_prefs.fm.progress > 0*/) {
963     pfx.hwnd = dlg;
964     /*gpgme_set_progress_cb (ctx->ctx, progress_callback, &pfx);*/
965     /*ctx->prog_cb = &pfx;*/
966     }
967    
968     /* Commands we need before we can perform the main command */
969     switch (fm_cmd) {
970 twoaday 77 case FM_ENCRYPT_ZIP:
971 werner 36 case FM_ENCRYPT:
972     case FM_SIGNENCRYPT:
973     if (fm_cmd == FM_SIGNENCRYPT)
974     ctx->req_signer = 1;
975 twoaday 105 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILE_ENCRYPT,
976     ctx->dlg, file_encrypt_dlg_proc, (LPARAM)ctx);
977 werner 36 if (ctx->cancel == 1) {
978 twoaday 105 rc = WPTERR_GENERAL;
979 werner 36 goto leave;
980     }
981     break;
982    
983     case FM_SIGN:
984     DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_FILE_SIGN, dlg,
985     file_sign_dlg_proc, (LPARAM) ctx);
986     if (ctx->cancel == 1 || fm_clearsign_8bit (lv, ctx)) {
987     rc = WPTERR_GENERAL;
988     goto leave;
989     }
990     break;
991    
992     case FM_WIPE:
993     memset (&pfx2, 0, sizeof (pfx2));
994     secure_unlink_set_cb (progress_callback, &pfx2);
995     break;
996     }
997    
998 twoaday 270 for( i = 0, n = 0; i < listview_count_items (lv, 0); i++ ) {
999     if (!listview_get_item_state (lv, i))
1000 werner 36 continue;
1001 twoaday 270 listview_get_item_text (lv, i, FM_COL_STAT, status, DIM (status) -1);
1002 twoaday 271 if (!strcmp (status, "ENCRYPTED") && fm_cmd == FM_DECRYPT)
1003 werner 36 n++;
1004 twoaday 271 if (!strcmp (status, "UNKNOWN") && fm_cmd == FM_SIGN)
1005 werner 36 n++;
1006     if (fm_cmd == FM_WIPE)
1007     ndel++;
1008     }
1009    
1010     if (n > 1 && fm_cmd != FM_SYMENC)
1011     ctx->cache_cb = 1;
1012    
1013     if (fm_cmd == FM_WIPE && ndel > 0) {
1014     memset (&confirm, 0, sizeof confirm);
1015     confirm.lv_files = lv;
1016     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILES_SECDEL, ctx->dlg,
1017 twoaday 77 file_secdel_confirm_dlg_proc, (LPARAM)&confirm);
1018 werner 36 if (!confirm.yes)
1019     goto leave;
1020     }
1021 twoaday 119
1022 twoaday 77 if (fm_cmd == FM_ENCRYPT_ZIP)
1023     fm_encrypt_into_zip (ctx, lv);
1024    
1025     for (i = 0; i < listview_count_items (lv, 0); i++) {
1026 twoaday 177 if (!listview_get_item_state (lv, i))
1027 werner 36 continue;
1028 twoaday 270 listview_get_item_text (lv, i, FM_COL_NAME, fname, DIM (fname) - 1);
1029 twoaday 271 if (file_exist_check (fname) && !is_directory (fname)) {
1030 twoaday 119 log_box (_("File Manager"), MB_ERR,
1031     _("\"%s\" does not exist"), fname);
1032 werner 36 continue;
1033     }
1034 twoaday 119 if (is_directory (fname))
1035 werner 36 fm_cmd = FM_ENCRYPT_DIR;
1036 twoaday 119 if (!fm_check_file_type (lv, i, fm_cmd))
1037 werner 36 continue;
1038 twoaday 119 sig_detached = fm_check_detached_sig (lv, i);
1039 twoaday 77 switch (fm_cmd) {
1040 werner 36 case FM_LIST: rc = fm_list( fname, dlg ); break;
1041     case FM_WIPE: rc = fm_wipe( fname ); break;
1042     case FM_ENCRYPT: rc = fm_encrypt( ctx, fname, 0 ); break;
1043     case FM_ENCRYPT_DIR: rc = fm_encrypt_directory( ctx, fname ); break;
1044     case FM_SIGNENCRYPT: rc = fm_encrypt( ctx, fname, 1 ); break;
1045     case FM_DECRYPT: rc = fm_decrypt( ctx, fname ); break;
1046     case FM_SIGN: rc = fm_sign( ctx, fname ); break;
1047 twoaday 177 case FM_SYMENC: rc = fm_sym_encrypt (ctx, fname); break;
1048 werner 36 case FM_VERIFY: rc = fm_verify (ctx, sig_detached, fname);break;
1049     case FM_IMPORT:
1050     free_if_alloc (ctx->opaque);
1051     ctx->opaque = m_strdup (fname);
1052 twoaday 177 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
1053     file_import_dlg_proc, (LPARAM)ctx);
1054 werner 36 if (ctx->cancel == 1)
1055     continue;
1056     rc = fm_import (ctx, fname);
1057     break;
1058     }
1059 twoaday 177 if (ctx->cancel == 1) {
1060     ctx->cancel = 0;
1061     continue;
1062     }
1063 twoaday 88 fm_set_status (lv, i, fm_cmd, ctx->sigmode, !rc, ctx->output);
1064 werner 36 free_if_alloc (ctx->output);
1065     progress_cleanup (&pfx);
1066     }
1067 twoaday 77
1068 werner 36 if (fm_cmd == FM_WIPE) {
1069     secure_unlink_set_cb (NULL, NULL);
1070     progress_cleanup (&pfx2);
1071     }
1072     if (ctx->cache_cb) {
1073     release_gpg_passphrase_cb (&ctx->pass_cb);
1074     ctx->cache_cb = 0; /* make sure it's only used for this session! */
1075     }
1076    
1077     /* remove wipe files from the list */
1078     n = listview_count_items (lv, 0);
1079     while (n--) {
1080 twoaday 270 listview_get_item_text (lv, n, FM_COL_STAT, status, DIM (status) - 1);
1081 twoaday 77 if (!strcmp (status, "WIPED"))
1082 werner 36 listview_del_item (lv, n);
1083     }
1084    
1085     leave:
1086     if (!rc)
1087     fm_state_release (ctx);
1088     progress_cleanup (&pfx);
1089     return rc;
1090 twoaday 270 }
1091 werner 36
1092    
1093     /* Wipe the given file @name with the delete mode
1094     from the configuration.
1095     Return value: 0 on success. */
1096     int
1097     fm_wipe (const char *name)
1098     {
1099     int rc;
1100    
1101     SetCursor (LoadCursor (NULL, IDC_WAIT));
1102     remove_crit_file_attrs (name, 1);
1103     rc = secure_unlink (name, reg_prefs.wipe_mode);
1104     SetCursor (LoadCursor (NULL, IDC_ARROW));
1105     return rc;
1106     }
1107    
1108    
1109     /* Dump out the given PGP packets from file @name in a dialog. */
1110     int
1111     fm_list (const char *name, HWND dlg)
1112     {
1113     dialog_box_param( glob_hinst, (LPCTSTR)IDD_WINPT_FILE_STAT, dlg,
1114     file_stat_dlg_proc, (LPARAM)name, _("File Status"),
1115     IDS_WINPT_FILE_STAT );
1116     return 0;
1117     }
1118    
1119    
1120     static int
1121     ask_filename (fm_state_t c, const char *msg, char **dst)
1122     {
1123 twoaday 226 const char *s;
1124 werner 36
1125 twoaday 77 s = get_filesave_dlg (c->dlg, msg, NULL, NULL);
1126 werner 36 if (!s)
1127     return WPTERR_GENERAL;
1128    
1129     if (dst != NULL)
1130     free_if_alloc (*dst);
1131     free_if_alloc (c->output);
1132     c->output = m_strdup (s);
1133     if (dst)
1134     *dst = fm_quote_file (s);
1135     return 0;
1136     }
1137    
1138    
1139     int
1140     fm_encrypt (fm_state_t c, const char *name, int sign)
1141     {
1142     gpgme_error_t err;
1143     gpgme_key_t key = NULL;
1144     gpgme_ctx_t ctx = c->ctx;
1145     file_data_t in=NULL, out=NULL;
1146     char *keyid = NULL, ext[5];
1147     int rc = 0;
1148    
1149     c->output = new char[strlen (name) + 5 + 1];
1150     if (!c->output)
1151     BUG (0);
1152     strcpy (ext, file_get_extension (ctx, c->sigmode));
1153     strcpy (c->output, name);
1154 twoaday 105 strcat (c->output, ext);
1155 werner 36
1156     if (!overwrite_file (c->output)) {
1157 twoaday 226 rc = ask_filename (c, _("Enter Filename for Encrypted File"), NULL);
1158 werner 36 if (rc)
1159     goto leave;
1160     }
1161    
1162 twoaday 105 err = gpg_file_data_new (name, F_DATA_READ, &in);
1163 werner 36 if (err)
1164     goto leave;
1165 twoaday 105 remove_crit_file_attrs (c->output, 0);
1166     err = gpg_file_data_new (c->output, F_DATA_WRITE, &out);
1167 werner 36 if (err)
1168     goto leave;
1169    
1170     /*
1171 twoaday 270 int no_compr = 0;
1172 werner 36 if (c->prog_cb) {
1173     c->prog_cb->what = name;
1174     gpg_file_data_set_cb (in, c->prog_cb);
1175     }
1176     */
1177    
1178 twoaday 105 /* XXX: disable compression for multi-media files.
1179 werner 36 no_compr = is_multi_media (name);
1180     gpgme_control (ctx, GPGME_CTRL_NO_COMPR, no_compr);
1181     */
1182    
1183     if (sign) {
1184     if (gpgme_signers_enum (ctx, 0) == NULL) {
1185     keyid = get_gnupg_default_key ();
1186     if (!keyid) {
1187     msg_box (c->dlg, _("Could not get default secret key."),
1188     _("Signing"), MB_ERR);
1189     rc = WPTERR_GENERAL;
1190     goto leave;
1191     }
1192     if (get_seckey (keyid, &key))
1193     BUG (0);
1194     gpgme_signers_add (ctx, key);
1195     }
1196     else {
1197 twoaday 77 gpgme_key_t sigkey = gpgme_signers_enum (ctx, 0);
1198     if (sigkey && sigkey->subkeys) {
1199     keyid = m_strdup (sigkey->subkeys->keyid);
1200 werner 36 }
1201     }
1202     if (!c->init_cb || !c->cache_cb) {
1203     set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_SIGN,
1204     c->dlg, _("Signing"));
1205     c->init_cb = 1;
1206     }
1207     op_begin ();
1208     err = gpgme_op_encrypt_sign (ctx, c->recp, GPGME_ENCRYPT_ALWAYS_TRUST,
1209     in->dat, out->dat);
1210     op_end ();
1211     if (!c->cache_cb)
1212     release_gpg_passphrase_cb (&c->pass_cb);
1213     if (c->pass_cb.cancel) {
1214     rc = WPTERR_GENERAL;
1215     goto leave;
1216     }
1217     if (err) {
1218     msg_box (c->dlg, gpgme_strerror (err), _("Sign"), MB_ERR);
1219     if (gpgme_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
1220     agent_del_cache (keyid);
1221     rc = WPTERR_GENERAL;
1222     goto leave;
1223     }
1224     }
1225     else {
1226     op_begin ();
1227     err = gpgme_op_encrypt (ctx, c->recp, GPGME_ENCRYPT_ALWAYS_TRUST,
1228     in->dat, out->dat);
1229     op_end ();
1230     if (err) {
1231     msg_box (c->dlg, gpgme_strerror (err), _("Encrypt"), MB_ERR);
1232     rc = WPTERR_GENERAL;
1233     goto leave;
1234     }
1235     }
1236    
1237     leave:
1238     if (in)
1239     gpg_file_data_release (in);
1240     if (out)
1241     gpg_file_data_release (out);
1242 twoaday 77 free_if_alloc (keyid);
1243 twoaday 76 if (!rc && c->wipe)
1244     secure_unlink (name, WIPE_MODE_SIMPLE);
1245 werner 36 return rc;
1246     }
1247    
1248    
1249     int
1250     fm_sym_encrypt (fm_state_t c, const char * name)
1251     {
1252     gpgme_ctx_t ctx = c->ctx;
1253     gpgme_error_t err;
1254     file_data_t in=NULL, out=NULL;
1255     int rc = 0, cancel = 0;
1256 twoaday 226 char ext[5], *pass;
1257 werner 36
1258 twoaday 226 pass = request_passphrase2 (_("Symmetric Encryption"), 0, &cancel);
1259 twoaday 177 if (cancel) {
1260     c->cancel = 1;
1261 werner 36 return 0;
1262 twoaday 177 }
1263 werner 36
1264 twoaday 226 /* XXX: a convenient feature could be to select the preferred
1265     symmetric algorithm. */
1266 werner 36 c->output = new char[strlen (name) + 5 + 1];
1267     if (!c->output)
1268     BUG (0);
1269     strcpy (ext, file_get_extension (ctx, c->sigmode));
1270     strcpy (c->output, name);
1271     strcat (c->output, ext);
1272    
1273     if (overwrite_file (c->output) == 0) {
1274     rc = WPTERR_GENERAL;
1275     goto leave;
1276     }
1277    
1278 twoaday 226 gpgme_set_passphrase_cb (ctx, sym_passphrase_cb, pass);
1279 werner 36 err = gpg_file_data_new (name, 1, &in);
1280     if (err)
1281     goto leave;
1282     err = gpg_file_data_new (c->output, 0, &out);
1283     if (err)
1284     goto leave;
1285    
1286     op_begin ();
1287     err = gpgme_op_encrypt (ctx, NULL, GPGME_ENCRYPT_ALWAYS_TRUST,
1288     in->dat, out->dat);
1289     op_end ();
1290     if (err) {
1291     msg_box (c->dlg, gpgme_strerror (err), _("Symmetric"), MB_ERR);
1292     rc = WPTERR_GENERAL;
1293     goto leave;
1294     }
1295     if (file_exist_check (c->output)) {
1296     msg_box (c->dlg, _("Encryption failed."), _("Symmetric"), MB_ERR);
1297     rc = WPTERR_GENERAL;
1298     }
1299    
1300     leave:
1301     if (in)
1302     gpg_file_data_release (in);
1303     if (out)
1304     gpg_file_data_release (out);
1305     sfree_if_alloc (pass);
1306     return rc;
1307 twoaday 105 }
1308 werner 36
1309    
1310     /* Check the recipients if we have at least one secret key. */
1311     bool
1312 twoaday 217 is_seckey_available (gpgme_recipient_t rset)
1313 werner 36 {
1314     gpgme_recipient_t r;
1315 twoaday 217 winpt_key_s key;
1316 werner 36
1317 twoaday 105 for (r=rset; r; r = r->next) {
1318 werner 36 if (gpgme_err_code (r->status) == GPG_ERR_NO_SECKEY)
1319     continue;
1320     else {
1321 twoaday 217 memset (&key, 0, sizeof (key));
1322 werner 36 /* extra check to make sure the key is available right now. */
1323 twoaday 217 if (!winpt_get_seckey (r->keyid, &key)) {
1324     winpt_release_pubkey (&key);
1325 werner 36 return true;
1326 twoaday 217 }
1327     winpt_release_pubkey (&key);
1328 werner 36 }
1329     }
1330     return false;
1331     }
1332    
1333    
1334 twoaday 195 /* If the decrypt result contains the original file name,
1335     we use it instead of the artificial "output - .gpg" string. */
1336     static int
1337 twoaday 197 restore_original_name (const char *output, const char *file_name)
1338 twoaday 195 {
1339     char *dir;
1340     char *orig;
1341     int rc = 0;
1342    
1343     dir = strrchr (output, '\\');
1344     if (!dir)
1345 twoaday 197 orig = strdup (file_name);
1346 twoaday 195 else {
1347 twoaday 197 orig = (char*)calloc (1, strlen (file_name)+ 1 +
1348 twoaday 195 strlen (output)+1);
1349     if (!orig)
1350     BUG (0);
1351     memcpy (orig, output, (dir-output)+1);
1352 twoaday 197 strcat (orig, file_name);
1353 twoaday 195 }
1354 twoaday 214 /* XXX: we need to find out if the string needs to be utf8 decoded. */
1355 twoaday 195 if (overwrite_file (orig)) {
1356     DeleteFile (orig);
1357     if (!MoveFile (output, orig))
1358     rc = -1;
1359     }
1360     safe_free (orig);
1361     return rc;
1362     }
1363    
1364    
1365 werner 36 /* Decrypt the file @name. */
1366     int
1367     fm_decrypt (fm_state_t c, const char *name)
1368     {
1369     gpgme_error_t err;
1370     gpgme_ctx_t ctx = c->ctx;
1371     gpgme_decrypt_result_t res;
1372     gpgme_verify_result_t sigres;
1373 twoaday 195 file_data_t in = NULL, out = NULL;
1374 werner 36 int rc = 0;
1375    
1376     if (!c->init_cb || !c->cache_cb) {
1377 twoaday 119 set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_DECRYPT,
1378 werner 36 c->dlg, _("Decryption"));
1379 twoaday 119 c->init_cb = 1;
1380     }
1381 werner 36
1382     c->output = m_strdup (name);
1383     if (is_openpgp_ext (c->output))
1384     c->output[strlen (c->output)-4] = '\0';
1385     else {
1386 twoaday 41 const char *s;
1387     s = get_filesave_dlg (c->dlg, _("Choose Filename for Output"),
1388     NULL, NULL);
1389 werner 36 if (s) {
1390     free_if_alloc (c->output);
1391     c->output = m_strdup (s);
1392     }
1393     }
1394    
1395     if (overwrite_file (c->output) == 0) {
1396 twoaday 226 rc = ask_filename (c, _("Enter Filename for Plaintext File"), NULL);
1397 werner 36 if (rc)
1398     goto leave;
1399 twoaday 105 }
1400 werner 36
1401 twoaday 214 /* we fetch all recipients here to make sure they list is complete. */
1402     release_gpg_recipients (&c->pass_cb.recipients);
1403     gpg_get_recipients (name, &c->pass_cb.recipients);
1404    
1405 twoaday 105 err = gpg_file_data_new (name, F_DATA_READ, &in);
1406 werner 36 if (err)
1407     goto leave;
1408 twoaday 105 remove_crit_file_attrs (c->output, 0);
1409     err = gpg_file_data_new (c->output, F_DATA_WRITE, &out);
1410 werner 36 if (err)
1411     goto leave;
1412 twoaday 214
1413 werner 36 op_begin ();
1414     err = gpgme_op_decrypt_verify (ctx, in->dat, out->dat);
1415     op_end ();
1416     if (!c->cache_cb)
1417     release_gpg_passphrase_cb (&c->pass_cb);
1418     if (c->pass_cb.cancel) {
1419     rc = WPTERR_GENERAL;
1420     goto leave;
1421     }
1422    
1423     res = gpgme_op_decrypt_result (ctx);
1424 twoaday 217 if (res && res->recipients && !is_seckey_available (res->recipients)) {
1425 twoaday 256 const char *keyid = get_keyid_from_fpr (res->recipients->keyid);
1426     char *p = get_key_userid (keyid);
1427 werner 36 gpgme_pubkey_algo_t pkalgo = res->recipients->pubkey_algo;
1428    
1429 twoaday 195 log_box (_("Decryption"), MB_ERR,
1430 twoaday 256 _("Encrypted with %s key, ID 0x%s.%s\n"
1431 werner 36 "Decryption failed: secret key not available."),
1432 twoaday 256 get_key_pubalgo (pkalgo), keyid, p);
1433 werner 36 rc = WPTERR_GENERAL;
1434     free_if_alloc (p);
1435     goto leave;
1436     }
1437     else if (err) {
1438     msg_box (c->dlg, gpgme_strerror (err), _("Decrypt"), MB_ERR);
1439     rc = WPTERR_GENERAL;
1440     goto leave;
1441     }
1442     if (file_exist_check (c->output)) {
1443 twoaday 105 log_box ("Decrypt", MB_ERR,
1444     _("Decryption failed.\n%s: does not exist."), c->output);
1445 werner 36 rc = WPTERR_GENERAL;
1446 twoaday 195 goto leave;
1447 werner 36 }
1448 twoaday 195 else if (res && res->file_name) {
1449 twoaday 214 char *file;
1450 twoaday 217 int id = IDNO;
1451 twoaday 214
1452     file = strrchr (c->output, '\\');
1453     if (!file)
1454     file = c->output;
1455     else
1456     file++;
1457 twoaday 217 if (strcmp (res->file_name, file))
1458     id = log_box (_("Decrypt"), MB_QUEST_ASK,
1459     _("The original file name is '%s'.\n\n"
1460     "Do you want to use this instead of '%s'?"),
1461 twoaday 214 res->file_name, file);
1462 twoaday 195 if (id == IDYES) {
1463     /* before we can move the file, it needs to be closed first. */
1464     gpg_file_data_release (out);
1465     out = NULL;
1466     restore_original_name (c->output, res->file_name);
1467     }
1468     }
1469 werner 36 sigres = gpgme_op_verify_result (ctx);
1470     if (sigres && sigres->signatures)
1471 twoaday 220 verify_show_signature_state (sigres->signatures);
1472 werner 36
1473     leave:
1474     if (in)
1475     gpg_file_data_release (in);
1476     if (out)
1477     gpg_file_data_release (out);
1478 twoaday 119
1479 werner 36 return rc;
1480     }
1481    
1482    
1483     int
1484     fm_sign (fm_state_t c, const char * name)
1485 twoaday 105 {
1486 werner 36 gpgme_ctx_t ctx = c->ctx;
1487     gpgme_error_t err;
1488     file_data_t in=NULL, out=NULL;
1489     char ext[5];
1490 twoaday 105 int rc = 0;
1491 werner 36
1492     if (!c->init_cb || !c->cache_cb) {
1493 twoaday 119 set_gpg_passphrase_cb (&c->pass_cb, c->ctx,
1494     GPG_CMD_SIGN, c->dlg, _("Signing"));
1495 werner 36 c->init_cb = 1;
1496     }
1497    
1498     free_if_alloc (c->output);
1499     c->output = new char[strlen (name) + 5 + 1];
1500 twoaday 105 if (!c->output)
1501     BUG (NULL);
1502 werner 36 strcpy (ext, file_get_extension (ctx, c->sigmode));
1503     strcpy (c->output, name);
1504     strcat (c->output, ext);
1505    
1506     if (!overwrite_file (c->output)) {
1507 twoaday 226 rc = ask_filename (c, _("Enter Filename for Signed File"), NULL);
1508 werner 36 if (rc)
1509     goto leave;
1510     }
1511 twoaday 105
1512     err = gpg_file_data_new (name, F_DATA_READ, &in);
1513 werner 36 if (err)
1514     goto leave;
1515 twoaday 105 remove_crit_file_attrs (c->output, 0);
1516     err = gpg_file_data_new (c->output, F_DATA_WRITE, &out);
1517 werner 36 if (err)
1518     goto leave;
1519    
1520     op_begin ();
1521     err = gpgme_op_sign (ctx, in->dat, out->dat, c->sigmode);
1522     op_end ();
1523 twoaday 105 if (!c->cache_cb)
1524 werner 36 release_gpg_passphrase_cb (&c->pass_cb);
1525 twoaday 105 if (c->pass_cb.cancel) {
1526 werner 36 rc = WPTERR_GENERAL;
1527     goto leave;
1528     }
1529 twoaday 105 if (err) {
1530     msg_box (c->dlg, gpgme_strerror (err), _("Sign"), MB_ERR);
1531 werner 36 rc = WPTERR_GENERAL;
1532     goto leave;
1533     }
1534    
1535     leave:
1536     if (in)
1537     gpg_file_data_release (in);
1538     if (out)
1539     gpg_file_data_release (out);
1540     return rc;
1541     }
1542    
1543    
1544 twoaday 105 static void
1545 werner 36 fm_add_sig_stat (file_sig_ctx_t log)
1546     {
1547 twoaday 208 struct winpt_key_s key;
1548 werner 36 const char *kid;
1549    
1550 twoaday 208 memset (&key, 0, sizeof (key));
1551     kid = get_keyid_from_fpr (log->sig->fpr);
1552     log->use_uid = 0;
1553     if (!winpt_get_pubkey (kid, &key)) {
1554     log->user_id = key.ext->uids->uid;
1555 werner 36 log->use_uid = 1;
1556     }
1557     file_verify_add_state (log);
1558 twoaday 270 winpt_release_pubkey (&key);
1559 werner 36 }
1560    
1561    
1562 twoaday 105 /* Verify a detached signature from the clipboard. */
1563 werner 36 static int
1564 twoaday 105 verify_pasted (listview_ctrl_t lv, fm_state_t ctx,
1565     const char *dat, int pos, HWND dlg)
1566 werner 36 {
1567 twoaday 105 FILE *fp;
1568 werner 36 char stat[32];
1569 twoaday 105 char file[256], *fname = NULL;
1570     int del_end = 0;
1571 werner 36
1572 twoaday 262 listview_get_item_text (lv, pos, FM_COL_STAT, stat, DIM (stat)-1);
1573     listview_get_item_text (lv, pos, FM_COL_NAME, file, DIM (file)-1);
1574 werner 36 if (strcmp (stat, "UNKNOWN"))
1575     return 0;
1576     fname = make_filename (NULL, file, "asc");
1577     if (file_exist_check (fname) != 0) {
1578     fp = fopen (fname, "wb");
1579     if (fp == NULL) {
1580 twoaday 226 log_box (_("File Manager"), MB_ERR, "Could not create '%s'", fname);
1581 werner 36 free_if_alloc (fname);
1582 twoaday 105 return WPTERR_GENERAL;
1583     }
1584 werner 36 fwrite (dat, 1, strlen (dat), fp);
1585     fclose (fp);
1586     del_end = 1;
1587     }
1588     fm_verify (ctx, 1, fname);
1589     if (del_end)
1590 twoaday 226 DeleteFile (fname);
1591 werner 36 free_if_alloc (fname);
1592     return 0;
1593     }
1594    
1595    
1596 twoaday 105 /* Figure out if the clipboard contains a detached signature. */
1597 werner 36 int
1598     fm_verify_pasted_detsig (listview_ctrl_t lv, HWND dlg)
1599     {
1600     fm_state_t ctx = NULL;
1601     char * dat=NULL;
1602     int i, fnd = 0;
1603    
1604     dat = get_clip_text (NULL);
1605     if (!dat || !strstr (dat, "BEGIN PGP SIGNATURE")) {
1606     msg_box (dlg, _("Could not find detached signature in the clipboard."),
1607     _("File Manager"), MB_ERR);
1608     free_if_alloc (dat);
1609     return WPTERR_GENERAL;
1610     }
1611     /* XXX find a way to filter out bad signatures or just ignore all in
1612     this case */
1613     fm_state_new (&ctx);
1614 twoaday 105 i = listview_get_curr_pos (lv);
1615 twoaday 260 if (i == -1) {
1616 werner 36 verify_pasted (lv, ctx, dat, i, dlg);
1617     fnd = 1;
1618     }
1619     else {
1620     for (i=0; i < listview_count_items (lv, 0); i++) {
1621     verify_pasted (lv, ctx, dat, i, dlg);
1622     fnd = 1;
1623     }
1624     }
1625     if (!fnd)
1626     msg_box (dlg, _("No files to check."), _("File Manager"), MB_INFO);
1627     free_if_alloc (dat);
1628     fm_state_release (ctx);
1629     return 0;
1630     }
1631    
1632    
1633     /* Extract automatically the output file name from @name.
1634     If @detached is 1, a detached sig is assumed. */
1635     static int
1636     get_output_file (fm_state_t c, const char *name, int detached)
1637     {
1638     const char *file = NULL;
1639     const char *title;
1640     char fname[384];
1641    
1642     if (detached)
1643     title = _("Select Data File");
1644     else
1645     title = _("Selected Output File");
1646    
1647 twoaday 226 if (is_openpgp_ext (name)) {
1648 twoaday 262 _snprintf (fname, DIM (fname) - 1, "%s", name);
1649 werner 36 fname[strlen (fname) - 4] = '\0';
1650     if (file_exist_check (fname) == 0 && detached)
1651     file = fname;
1652     else if (!detached) {
1653     /* If the signature is clear or normal, make sure we do not
1654     overwrite the original file if it exists. */
1655     if (file_exist_check (fname) == 0 && !overwrite_file (fname)) {
1656     file = get_filesave_dlg (c->dlg, title, NULL, NULL);
1657     if (!file)
1658     return WPTERR_GENERAL;
1659     }
1660     else
1661     file = fname;
1662     }
1663     }
1664     if (!file)
1665     file = get_fileopen_dlg (c->dlg, title, NULL, NULL);
1666     if (file) {
1667     free_if_alloc (c->output);
1668     c->output = m_strdup (file);
1669     }
1670     else {
1671     msg_box (c->dlg, _("Invalid file name. Exit"), _("Verify"), MB_ERR);
1672     return WPTERR_GENERAL;
1673     }
1674     if (detached)
1675     c->sigmode = GPGME_SIG_MODE_DETACH;
1676     else {
1677 twoaday 197 if (stristr (name, ".asc"))
1678 werner 36 c->sigmode = GPGME_SIG_MODE_CLEAR;
1679     else
1680     c->sigmode = GPGME_SIG_MODE_NORMAL;
1681     }
1682     return 0;
1683     }
1684    
1685    
1686 twoaday 271 /* Handy function to kick of the gpg verify process. */
1687     static gpgme_error_t
1688     fm_gpg_verify (gpgme_sig_mode_t sigmode, gpgme_ctx_t ctx,
1689     file_data_t in, file_data_t out)
1690     {
1691     gpgme_error_t err;
1692    
1693     op_begin ();
1694     if (sigmode == GPGME_SIG_MODE_DETACH)
1695     err = gpgme_op_verify (ctx, in->dat, out->dat, NULL);
1696     else
1697     err = gpgme_op_verify (ctx, in->dat, in->dat, out->dat);
1698     op_end ();
1699     return err;
1700     }
1701    
1702    
1703 werner 36 /* Verify the signature from the file @name. If @detached 1,
1704     it is assumed that a detached signature should be checked. */
1705     int
1706     fm_verify (fm_state_t c, int detached, const char *name)
1707     {
1708     gpgme_error_t err;
1709     gpgme_signature_t s;
1710     gpgme_verify_result_t res;
1711     struct file_sig_ctx_s log;
1712     file_data_t in=NULL, out=NULL;
1713     int rc = 0;
1714    
1715 twoaday 197 if (stristr (name, ".sig"))
1716 werner 36 detached = 1;
1717    
1718     if (get_output_file (c, name, detached))
1719     return WPTERR_GENERAL;
1720    
1721     file_verify_create_dlg ();
1722    
1723 twoaday 271 memset (&log, 0, sizeof (log));
1724     log.file = m_strdup (name);
1725    
1726 twoaday 105 err = gpg_file_data_new (name, F_DATA_READ, &in);
1727 werner 36 if (err)
1728     goto leave;
1729 twoaday 105 err = gpg_file_data_new (c->output,
1730     detached? F_DATA_READ : F_DATA_WRITE, &out);
1731 werner 36 if (err)
1732     goto leave;
1733    
1734 twoaday 271 err = fm_gpg_verify (c->sigmode, c->ctx, in, out);
1735 werner 36 if (err) {
1736     msg_box (c->dlg, gpgme_strerror (err), _("Verify"), MB_ERR);
1737     rc = WPTERR_GENERAL;
1738     goto leave;
1739     }
1740    
1741 twoaday 271 res = gpgme_op_verify_result (c->ctx);
1742 twoaday 270 if (!res)
1743     goto leave;
1744 twoaday 271 if (res->signatures != NULL &&
1745     gpgme_err_code (res->signatures->status) == GPG_ERR_NO_PUBKEY) {
1746     /* We need to call gpg again to get the actual sig state
1747     and the data files must be rewinded also. */
1748     if (fetch_key_from_keyserver (c->dlg, res->signatures)) {
1749     rc = WPTERR_GENERAL;
1750     goto leave;
1751     }
1752     gpg_file_data_rewind (in);
1753     gpg_file_data_rewind (out);
1754     err = fm_gpg_verify (c->sigmode, c->ctx, in, out);
1755     if (err) {
1756     msg_box (c->dlg, gpgme_strerror (err), _("Verify"), MB_ERR);
1757     rc = WPTERR_GENERAL;
1758     goto leave;
1759     }
1760     /* Refresh the pointer because a new GPG instance has been
1761     created for the new verify operation. */
1762     res = gpgme_op_verify_result (c->ctx);
1763     }
1764    
1765 werner 36 for (s=res->signatures; s; s=s->next) {
1766     log.sig = s;
1767     fm_add_sig_stat (&log);
1768     }
1769     if (!c->output)
1770     c->output = m_strdup (name); /* for later use */
1771    
1772     leave:
1773     if (in)
1774     gpg_file_data_release (in);
1775     if (out)
1776     gpg_file_data_release (out);
1777 twoaday 105 free_if_alloc (log.file);
1778 werner 36 return rc;
1779     }
1780    
1781    
1782 twoaday 105 /* Import the keys from the file @name.
1783     Return value: 0 on success. */
1784 werner 36 int
1785     fm_import (fm_state_t c, const char *name)
1786     {
1787     gpgme_ctx_t ctx = c->ctx;
1788     gpgme_error_t err;
1789     gpgme_import_result_t res;
1790     file_data_t keydata = NULL;
1791     int rc = 0;
1792    
1793     free_if_alloc (c->output);
1794     c->output = m_strdup (name);
1795    
1796 twoaday 105 err = gpg_file_data_new (name, F_DATA_READ, &keydata);
1797 werner 36 if (err)
1798     goto leave;
1799    
1800     op_begin ();
1801     err = gpgme_op_import (ctx, keydata->dat);
1802     op_end ();
1803     if (err) {
1804     msg_box (c->dlg, gpgme_strerror (err), _("Import"), MB_ERR);
1805     rc = WPTERR_GENERAL;
1806     goto leave;
1807     }
1808    
1809     res = gpgme_op_import_result (ctx);
1810     print_import_status (res);
1811     if (res->no_user_id > 0) {
1812 twoaday 105 msg_box (c->dlg, _("Key without a self signature was dectected!\n"
1813 werner 36 "(This key is NOT usable for encryption, etc)\n"
1814     "\n"
1815     "Cannot import these key(s)!"), _("Import"), MB_INFO);
1816     }
1817    
1818     leave:
1819     if (keydata)
1820     gpg_file_data_release (keydata);
1821     return rc;
1822 twoaday 105 }
1823 werner 36
1824    
1825     /* Export the selected keys from the File Manager to a file. */
1826     int
1827     fm_export (fm_state_t c)
1828 twoaday 197 {
1829 werner 36 gpgme_ctx_t ctx = c->ctx;
1830     gpgme_error_t err;
1831     gpgme_key_t *rset = c->recp;
1832     file_data_t keydata = NULL;
1833 twoaday 94 const char *name;
1834 werner 36 char *p = NULL, *patt = NULL;
1835 twoaday 197 int rc = 0;
1836 werner 36
1837     if (!rset || !rset[0]) {
1838 twoaday 226 msg_box (c->dlg, _("No key was selected for export."),
1839     _("Export"), MB_ERR);
1840 werner 36 rc = WPTERR_GENERAL;
1841     goto leave;
1842     }
1843    
1844 twoaday 105 if (rset[1] == NULL) /* count == 1*/
1845 twoaday 129 p = km_gen_export_filename (rset[0]->subkeys->keyid+8, 0);
1846 werner 36
1847 twoaday 77 name = get_filesave_dlg (c->dlg, _("Choose Name for Key File"),
1848 werner 36 NULL, p? p : NULL);
1849     if (!name)
1850 twoaday 218 name = reg_prefs.default_ext? "keys.pgp" : "keys.gpg";
1851 werner 36
1852     patt = gpg_keylist_to_pattern (rset, c->n_recp);
1853    
1854 twoaday 105 err = gpg_file_data_new (name, F_DATA_WRITE, &keydata);
1855 werner 36 if (err)
1856     goto leave;
1857    
1858     op_begin ();
1859     err = gpgme_op_export (ctx, patt, 0, keydata->dat);
1860     op_end ();
1861     if (err) {
1862     msg_box (c->dlg, gpgme_strerror (err), _("Export"), MB_ERR);
1863     rc = WPTERR_GENERAL;
1864     goto leave;
1865     }
1866     log_box (_("GnuPG status"), MB_OK, _("Finished (Output: %s)"), name);
1867    
1868     leave:
1869     if (keydata)
1870     gpg_file_data_release (keydata);
1871 twoaday 197 safe_free (patt);
1872 werner 36 free_if_alloc (p);
1873     return rc;
1874     }
1875    
1876    
1877     /* Parse the command line and process the given file. */
1878     int
1879     fm_parse_command_line (char *cmdl)
1880     {
1881     fm_state_t ctx;
1882     const char *s;
1883     char *p, *fn = NULL;
1884     int count = 0, detached = 0;
1885     int type;
1886    
1887     if (!cmdl || !*cmdl)
1888     return 0;
1889    
1890     fm_state_new (&ctx);
1891     ctx->dlg = GetActiveWindow ();
1892     ctx->cache_cb = 1;
1893    
1894     p = cmdl;
1895     if (p && *p > 32 && !stristr (p, "winpt.exe")
1896     && !strstr (p, "--" )) {
1897     count++;
1898     if (*p == '"') { /* need to remove quotes */
1899     fn = new char[strlen (p)];
1900     if (!fn)
1901     BUG (NULL);
1902     memcpy (fn, p+1, strlen (p) - 2);
1903     fn[strlen (p) -2] = '\0';
1904     }
1905     else
1906     fn = m_strdup (p);
1907     s = fm_get_file_type (fn, &type);
1908     if (!s || !strcmp (s, "UNKNOWN"))
1909     s = gnupg_check_file_ext (fn, &type);
1910     if (type == PGP_NONE) {
1911     log_box (_("File Manager"), MB_ERR,
1912     _("%s: no valid OpenPGP data found."), p);
1913     free_if_alloc (fn);
1914     return count;
1915     }
1916     switch (type) {
1917     case PGP_MESSAGE:
1918     fm_decrypt (ctx, fn);
1919     break;
1920    
1921     case PGP_PUBKEY:
1922     case PGP_SECKEY:
1923     fm_import (ctx, fn);
1924     break;
1925    
1926     case PGP_SIG:
1927     case PGP_CLEARSIG:
1928     if (type == PGP_SIG)
1929     detached = 1;
1930     fm_verify (ctx, detached, fn);
1931     file_verify_wait ();
1932 twoaday 77 break;
1933 twoaday 88
1934 twoaday 77 default:
1935     break;
1936 werner 36 }
1937     }
1938    
1939     wipememory (&ctx->pass_cb, sizeof (ctx->pass_cb));
1940     free_if_alloc (fn);
1941     fm_state_release (ctx);
1942     return count;
1943     }
1944    
1945    
1946 twoaday 105 /* Extract the last folder name from @name. */
1947 werner 36 const char*
1948     default_dirname (const char *name)
1949     {
1950 twoaday 105 char *p = strrchr (name, '\\');
1951     if (!p)
1952 werner 36 return NULL;
1953     return p+1;
1954 twoaday 105 }
1955 werner 36
1956    
1957 twoaday 77 /* Store all selected files from @lv in a zip archive
1958     and encrypt the zip archive then.
1959     Return value: 0 on success. */
1960 werner 36 int
1961 twoaday 77 fm_encrypt_into_zip (fm_state_t ctx, listview_ctrl_t lv)
1962     {
1963     PK_FILE_LIST list=NULL;
1964 twoaday 197 const char *outfile, *ext;
1965 twoaday 77 char *out_enc;
1966 twoaday 197 int nitems;
1967 twoaday 77 int i, idx = -1;
1968     int rc;
1969    
1970 twoaday 197 nitems = listview_count_items (lv, 0);
1971 twoaday 77 if (!nitems) {
1972     msg_box (NULL, _("Encrypting into a ZIP archive makes sense with multiple files"),
1973     _("File Manager"), MB_ERR);
1974 twoaday 105 return WPTERR_GENERAL;
1975 twoaday 77 }
1976    
1977 twoaday 105 outfile = get_filesave_dlg (ctx->dlg, _("Choose File Name for Output"),
1978     NULL, "Encrypted_Files.zip");
1979 twoaday 77 if (!outfile)
1980 twoaday 105 return WPTERR_GENERAL;
1981 twoaday 77
1982     for (i=0; i < nitems; i++) {
1983 twoaday 256 char name[MAX_PATH+32];
1984    
1985 twoaday 77 if (!listview_get_item_state (lv, i))
1986     continue;
1987     if (idx == -1)
1988     idx = i;
1989 twoaday 262 listview_get_item_text (lv, i, 1, name, DIM (name)-1);
1990 twoaday 77 pk_list_add (&list, name);
1991     }
1992    
1993     pk_archiv_create (list, outfile);
1994     pk_list_free (list);
1995    
1996     rc = fm_encrypt (ctx, outfile, 0);
1997     DeleteFile (outfile);
1998     if (rc)
1999     return rc;
2000    
2001 twoaday 197 ext = file_get_extension (ctx->ctx, ctx->sigmode)+1;
2002     out_enc = make_filename (NULL, outfile, ext);
2003 twoaday 88 fm_set_status (lv, idx, FM_ENCRYPT, (gpgme_sig_mode_t)0, 1, out_enc);
2004 twoaday 77 free_if_alloc (out_enc);
2005    
2006 twoaday 256 for (i=nitems; i > -1; i--) {
2007 twoaday 77 if (i != idx && listview_get_item_state (lv, i))
2008     listview_del_item (lv, i);
2009     }
2010     return 0;
2011     }
2012    
2013    
2014     int
2015 twoaday 105 fm_encrypt_directory (fm_state_t c, const char *name)
2016 twoaday 256 {
2017 werner 36 WIN32_FIND_DATA findbuf;
2018     HANDLE hd;
2019 twoaday 256 PK_FILE_LIST list = NULL;
2020 twoaday 226 const char *s;
2021     char *patt = NULL, *p;
2022 werner 36 int rc = 0;
2023    
2024 twoaday 105 if (!is_directory (name))
2025 werner 36 return -1;
2026 twoaday 105 patt = new char[strlen (name) + 4];
2027     if (!patt)
2028     BUG (NULL);
2029     strcpy (patt, name);
2030     strcat (patt, "\\*");
2031     hd = FindFirstFile (patt, &findbuf);
2032     if (!hd) {
2033     free_if_alloc (patt);
2034     return WPTERR_GENERAL;
2035 werner 36 }
2036 twoaday 226 if (strcmp (findbuf.cFileName, ".") && strcmp (findbuf.cFileName, "..")) {
2037     p = make_filename (name, findbuf.cFileName, NULL);
2038     pk_list_add (&list, p);
2039     free_if_alloc (p);
2040 werner 36 }
2041 twoaday 262 /* XXX: support to scan sub directories also. */
2042 twoaday 256 while (FindNextFile (hd, &findbuf)) {
2043     if (strcmp (findbuf.cFileName, ".") && strcmp (findbuf.cFileName, "..")) {
2044     p = make_filename (name, findbuf.cFileName, NULL);
2045     pk_list_add (&list, p);
2046     free_if_alloc (p);
2047 werner 36 }
2048     }
2049 twoaday 105 s = get_filesave_dlg (c->dlg, _("Choose a Name for the Archive"),
2050     NULL, default_dirname (name));
2051 twoaday 256 if (!s) {
2052 twoaday 226 msg_box (c->dlg, _("Invalid archive name. Exit."),
2053     _("Encrypt Directory"), MB_ERR);
2054 werner 36 rc = -1;
2055     goto leave;
2056     }
2057    
2058 twoaday 226 rc = pk_archiv_create (list, s);
2059 twoaday 256 if (rc)
2060 twoaday 226 msg_box (c->dlg, _("Could not create zip archive."),
2061     _("Encrypt Directory"), MB_ERR);
2062 werner 36 else {
2063 twoaday 226 fm_encrypt (c, s, 0);
2064     DeleteFile (s);
2065 werner 36 }
2066     leave:
2067     FindClose (hd);
2068 twoaday 226 pk_list_free (list);
2069     free_if_alloc (patt);
2070 werner 36 return rc;
2071 twoaday 105 }
2072 werner 36
2073    
2074     static int CALLBACK
2075 twoaday 105 fm_cmp_cb (LPARAM first, LPARAM second, LPARAM sortby)
2076 werner 36 {
2077 twoaday 244 fm_model_t a, b;
2078     int cmpres = 0;
2079 werner 36
2080 twoaday 244 a = (fm_model_t)first;
2081     b = (fm_model_t)second;
2082     if (!a || !b)
2083     return 0;
2084    
2085 twoaday 197 switch ((int)sortby) {
2086 twoaday 244 case FM_COL_STAT:
2087     cmpres = stricmp (a->status, b->status);
2088 werner 36 break;
2089 twoaday 244
2090     case FM_COL_NAME:
2091     cmpres = stricmp (a->name, b->name);
2092 werner 36 break;
2093 twoaday 244
2094     case FM_COL_OP:
2095     if (a->op && b->op)
2096     cmpres = stricmp (a->op, b->op);
2097 werner 36 break;
2098     }
2099 twoaday 244 return cmpres;
2100 twoaday 105 }
2101 werner 36
2102 twoaday 244
2103 twoaday 105 /* Sort the list items from @lv with the mode given by @sortby. */
2104 werner 36 int
2105 twoaday 105 fm_sort (listview_ctrl_t lv, int sortby)
2106 werner 36 {
2107 twoaday 244 return ListView_SortItems (lv->ctrl, fm_cmp_cb, (LPARAM)sortby);
2108 twoaday 105 }
2109 werner 36
2110    
2111 twoaday 105 /* Start the 'print md' dialog. Pass over the listview control
2112     @lv and the digest algo @mdalgo. */
2113 werner 36 void
2114 twoaday 105 fm_print_md (listview_ctrl_t lv, HWND dlg, int mdalgo)
2115 werner 36 {
2116     struct md_file_s mdctx;
2117    
2118 twoaday 105 if (listview_count_items (lv, 0) == 0)
2119 werner 36 return;
2120     memset (&mdctx, 0, sizeof (mdctx));
2121     mdctx.lv = lv;
2122     mdctx.mdalgo = mdalgo;
2123 twoaday 105 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILE_MDSUM, dlg,
2124     mdsum_dlg_proc, (LPARAM)&mdctx);
2125     }
2126 werner 36
2127    
2128 twoaday 77 /* Send the selected file in @lv via MAPI to a mail recipient. */
2129 werner 36 int
2130     fm_send_file (listview_ctrl_t lv)
2131     {
2132 twoaday 262 char name[MAX_PATH+1];
2133 werner 36 int rc;
2134    
2135 twoaday 262 rc = listview_get_item_text (lv, -1, FM_COL_NAME, name, DIM (name)-1);
2136 twoaday 77 if (rc != -1)
2137 twoaday 256 mapi_send_ascfile (name);
2138 werner 36 return 0;
2139     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26