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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 270 - (hide annotations)
Sat Oct 21 18:08:57 2006 UTC (18 years, 4 months ago) by twoaday
File size: 50893 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 werner 36 #include "openpgp.h"
52    
53    
54     void progress_cleanup (progress_filter_s *pfx);
55     BOOL CALLBACK file_secdel_confirm_dlg_proc (HWND dlg, UINT msg,
56     WPARAM wparam, LPARAM lparam);
57 twoaday 260 char* gpg_keylist_to_pattern (gpgme_key_t *rset, size_t n);
58 werner 36 gpgme_error_t sym_passphrase_cb (void *hook, const char *hint, const char *pass_inf,
59     int prev_was_bad, int fd);
60 twoaday 220 void verify_show_signature_state (gpgme_signature_t sig);
61 werner 36
62    
63 twoaday 195 static const char *mm_files[] = {".mov", ".avi", ".mpg", ".mpeg",
64 werner 36 ".mp3", ".wav", ".mid", ".wma",
65     ".gif", ".jpg", ".png", ".jpeg", ".dib", 0};
66    
67    
68 twoaday 244 /* Add a new file to the model @fm. */
69     static void
70     fm_model_add_file (fm_model_t *fm, fm_model_t file)
71     {
72     fm_model_t m;
73    
74     if (!*fm) {
75     *fm = file;
76     return;
77     }
78     for (m = *fm; m->next; m = m->next)
79     ;
80     m->next = file;
81     }
82    
83    
84     /* Search for a file model based on the name @name. */
85     static fm_model_t
86     fm_model_find_file (fm_model_t fm, const char *name)
87     {
88     fm_model_t m;
89    
90     for (m=fm; m; m=m->next) {
91     if (!stricmp (m->name, name))
92     return m;
93     }
94     return NULL;
95     }
96    
97    
98 werner 36 /* Check if the drive given by @fname is a floppy disc.
99 twoaday 41 Return value: -1 for success. */
100 werner 36 static int
101 twoaday 41 is_floppy_disc (const char *fname)
102 werner 36 {
103 twoaday 41 char drv[32] = {0};
104 twoaday 262 int max = DIM (drv)-1;
105 werner 36 int i=0;
106    
107     if (!strstr (fname, ":\\"))
108     return 0;
109    
110 twoaday 41 while (fname && *fname && *fname != '\\' && i < max)
111 werner 36 drv[i++] = *fname++;
112     drv[i++] = '\\';
113     drv[i++] = '\0';
114     i = GetDriveType (drv);
115     if (i == DRIVE_REMOVABLE)
116     return -1;
117     return 0;
118     }
119    
120    
121     /* Ask the user to overwrite file @fname.
122     Return value: 0 for cancel. */
123 twoaday 41 static int
124 werner 36 overwrite_file (const char *fname)
125     {
126     int id;
127    
128     if (file_exist_check (fname))
129     return -1;
130     id = log_box (_("File Manager"), MB_YESNO,
131     _("\"%s\" already exists.\n"
132     "Replace existing file?"), fname);
133     return id == IDNO ? 0 : -1;
134     }
135    
136    
137     /* Removes 'critical' attributes from the file @fname.
138     If @force is 1, the user is not asked for permission. */
139 twoaday 172 void
140 werner 36 remove_crit_file_attrs (const char *fname, int force)
141     {
142 twoaday 193 DWORD fattr;
143 twoaday 41 int id = 0;
144 werner 36
145     if (file_exist_check (fname))
146     return; /* Does not exist */
147    
148 twoaday 41 fattr = GetFileAttributes (fname);
149     if ((fattr & FILE_ATTRIBUTE_READONLY) && force)
150     id = IDYES;
151     else if (fattr & FILE_ATTRIBUTE_READONLY)
152 werner 36 id = log_box (_("File Manager"), MB_YESNO,
153     _("\"%s\" has read-only attribute.\n"
154     "Set attribute to normal?"), fname);
155 twoaday 41 if (id == IDYES) {
156     if (!SetFileAttributes (fname, FILE_ATTRIBUTE_NORMAL))
157     msg_box (NULL, _("Could not reset file attribute to normal."),
158     _("File Manager"), MB_ERR);
159 werner 36 }
160     }
161    
162    
163 twoaday 41 /* Return 1 if the given path @fname is a directory, 0 otherwise. */
164     static int
165 werner 36 is_directory (const char *fname)
166 twoaday 41 {
167 werner 36 return GetFileAttributes (fname) & FILE_ATTRIBUTE_DIRECTORY? 1 : 0;
168     }
169    
170    
171 twoaday 219 /* Return -1 if the given name @name is a valid GPG extension. */
172     int
173 werner 36 is_openpgp_ext (const char *name)
174     {
175 twoaday 226 if (stristr (name, ".gpg") ||
176     stristr (name, ".asc") ||
177     stristr (name, ".sig") ||
178     stristr (name, ".pgp"))
179 werner 36 return -1;
180     return 0;
181     }
182    
183    
184     static int
185     is_multi_media (const char * name)
186     {
187     const char * val;
188     char * p;
189     int i;
190     int ans=0;
191    
192     i = get_reg_winpt_single (CFG_NOZIP_MMEDIA);
193 twoaday 270 if (i == -1) {
194 werner 36 ans = msg_box (NULL, _("Multi-Media files are already compressed, GPG would compress\n"
195 twoaday 248 "them anyway and this takes a lot of time.\n"
196 werner 36 "It is possible to disable compression for these files.\n"
197     "Do you want to disable it?"),
198     _("File Manager"), MB_YESNO|MB_INFO);
199     set_reg_winpt_single (CFG_NOZIP_MMEDIA, ans == IDYES? 1 : 0);
200     if (ans == IDNO)
201     return 0;
202     }
203     else if (i == 0)
204     return 0;
205    
206     p = strrchr (name, '.');
207     if (!p)
208     return 0;
209 twoaday 41 for (i=0; (val = mm_files[i]); i++) {
210 werner 36 if (!stricmp (p, val))
211     return -1;
212     }
213     return 0;
214     }
215    
216    
217 twoaday 41 /* Return a GPG file extension which depends on the operation
218     mode in @ctx and the sig mode @sigmode. */
219 werner 36 const char*
220     file_get_extension (gpgme_ctx_t ctx, gpgme_sig_mode_t sigmode)
221     {
222     int use_armor = gpgme_get_armor (ctx);
223    
224     if (use_armor || sigmode == GPGME_SIG_MODE_CLEAR)
225     return ".asc";
226     if (!use_armor && sigmode == GPGME_SIG_MODE_DETACH)
227     return ".sig";
228 twoaday 218 return reg_prefs.default_ext == 1? ".pgp" : ".gpg";
229 werner 36 }
230    
231    
232 twoaday 41 /* Quote a file to avoid shell problems with spaces in the files. */
233 werner 36 char*
234     fm_quote_file (const char * name)
235     {
236     char * p;
237     size_t len = strlen (name) + 8;
238    
239     if (*name == '"')
240     return m_strdup (name); /* avoid double quotes */
241     p = new char[len + 1];
242     if (!p)
243     BUG (0);
244     _snprintf (p, len, "\"%s\"", name);
245    
246     return p;
247 twoaday 41 }
248 werner 36
249    
250    
251     /* Check the armor type of the file @fname and return
252     a string representation of it. */
253 twoaday 195 static const char*
254 werner 36 fm_check_armor_type (const char *fname, int *r_type)
255     {
256 twoaday 195 FILE *fp;
257 twoaday 270 char header[512], *p;
258 werner 36
259     if (r_type)
260     *r_type = PGP_NONE;
261     fp = fopen (fname, "rb");
262     if (!fp)
263     return "UNKNOWN";
264 twoaday 262 p = fgets (header, DIM (header) - 1, fp);
265 werner 36 fclose (fp);
266     if (!p)
267     return "UNKNOWN";
268    
269     if (strncmp (header, "-----", 5))
270     goto leave;
271 twoaday 270 if (strstr (header, "BEGIN PGP PUBLIC KEY" )) {
272 werner 36 if (r_type) *r_type = PGP_PUBKEY;
273     return "PUBKEY";
274     }
275     else if (strstr (header, "BEGIN PGP PRIVATE KEY") ||
276     strstr (header, "BEGIN PGP SECRET KEY")) {
277     if (r_type) *r_type = PGP_SECKEY;
278     return "SECKEY";
279     }
280     else if (strstr (header, "BEGIN PGP MESSAGE")) {
281     if (r_type) *r_type = PGP_MESSAGE;
282     return "ENCRYPTED";
283     }
284     else if (strstr( header, "BEGIN PGP SIGNED MESSAGE")) {
285     if (r_type) *r_type = PGP_CLEARSIG;
286     return "SIGNED-CLEAR";
287     }
288     else if (strstr(header, "BEGIN PGP SIGNATURE")) {
289     if (r_type) *r_type = PGP_SIG;
290     return "SIGNED-DETACH";
291     }
292    
293     leave:
294     return "UNKNOWN";
295     }
296    
297    
298     /* Extract file type from @fname. If @r_type is valid,
299     it contains the PGP type on success. */
300 twoaday 105 static const char*
301 werner 36 fm_get_file_type (const char *fname, int *r_type)
302     {
303     gpg_iobuf_t inp;
304     armor_filter_context_t afx;
305 twoaday 41 PACKET *pkt;
306     const char *s = NULL;
307 twoaday 105 size_t count = 0, compr = 0;
308 twoaday 77 int rc = 0;
309 werner 36
310     if (r_type)
311     *r_type = PGP_NONE;
312     if (!fname) {
313 twoaday 41 log_debug ("fm_get_file_type: !fname\r\n");
314 werner 36 return NULL;
315     }
316    
317 twoaday 270 /* to avoid lengthy operations on floppy disks, we use a quick check. */
318 werner 36 if (is_floppy_disc (fname))
319     return fm_check_armor_type (fname, r_type);
320    
321     inp = gpg_iobuf_open (fname);
322     if (!inp) {
323 twoaday 77 const char *err = winpt_strerror (WPTERR_FILE_OPEN);
324     log_box (_("File Manager"), MB_ERR, "\"%s\": %s", fname, err);
325 werner 36 return NULL;
326     }
327     gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
328     if (gpg_iobuf_get_filelength (inp) > 32000000 /* 32MB */
329     && !is_openpgp_ext (fname)) {
330     gpg_iobuf_close (inp);
331     return "UNKNOWN";
332     }
333    
334     if (gpg_use_armor_filter(inp)) {
335     memset (&afx, 0, sizeof (afx));
336     gpg_iobuf_push_filter (inp, gpg_armor_filter, &afx);
337     }
338 twoaday 41 pkt = (PACKET *)calloc (1, sizeof *pkt);
339     if (!pkt)
340     BUG (NULL);
341 werner 36 gpg_init_packet (pkt);
342 twoaday 270 /* XXX: for larger files, we could just look for the first ~3 packets
343     and stop if we found a packet which were sufficient to idenitfy
344     the file contents. */
345 werner 36 while (!(rc = gpg_parse_packet (inp, pkt))) {
346     switch (pkt->pkttype) {
347     case PKT_PUBKEY_ENC:
348     s = "ENCRYPTED";rc = -2;
349     if (r_type) *r_type = PGP_MESSAGE;
350     break;
351 twoaday 270
352 werner 36 case PKT_SYMKEY_ENC:
353     case PKT_ENCRYPTED:
354     s = "SYMKEYENC";rc = -2;
355     if (r_type) *r_type = PGP_MESSAGE;
356     break;
357 twoaday 270
358 werner 36 case PKT_SIGNATURE:
359     case PKT_ONEPASS_SIG:
360     s = "SIGNED"; rc = -2;
361     if (r_type) *r_type = PGP_SIG;
362     break;
363 twoaday 270
364 werner 36 case PKT_PUBLIC_KEY:
365     s = "PUBKEY"; rc = -2;
366     if (r_type) *r_type = PGP_PUBKEY;
367     break;
368 twoaday 270
369 werner 36 case PKT_SECRET_KEY:
370     s = "SECKEY"; rc = -2;
371     if (r_type) *r_type = PGP_SECKEY;
372     break;
373 twoaday 88
374 twoaday 105 case PKT_COMPRESSED:
375     /* If we only find 1 packet and it is compressed,
376 twoaday 270 we assume a compressed one-pass signature. */
377 twoaday 105 if (count != 0)
378     break;
379 twoaday 270 s = "SIGNED"; rc = -2;
380 twoaday 105 compr = 1;
381     break;
382    
383 twoaday 69 default:
384     break;
385 werner 36 }
386 twoaday 105 count++;
387 werner 36 gpg_free_packet (pkt);
388     gpg_init_packet (pkt);
389     if (rc == -2)
390     break; /* found */
391     }
392     safe_free (pkt);
393     gpg_iobuf_close (inp);
394     if (!s)
395     s = fm_check_armor_type (fname, r_type);
396     if (!s)
397     s = "UNKNOWN";
398 twoaday 105 if (!strcmp (s, "SIGNED") && !compr
399 twoaday 270 && strcmp (fm_check_armor_type (fname, r_type), "SIGNED-CLEAR")) {
400 werner 36 if (r_type) *r_type = PGP_SIG;
401     s = "SIGNED-DETACH";
402     }
403     return s;
404     }
405    
406    
407 twoaday 244 /* Build the File Manager dialog context. */
408     void
409     fm_build (fm_info_t *r_fm, HWND ctrl)
410 werner 36 {
411 twoaday 270
412 twoaday 244 fm_info_t fm;
413 twoaday 105 struct listview_column_s col[] = {
414 werner 36 {0, 80, (char *)_("Status") },
415     {1, 256, (char *)_("Name") },
416     {2, 128, (char *)_("Operation") },
417 twoaday 195 {0, 0, NULL}
418 werner 36 };
419 twoaday 270 int i;
420 twoaday 244
421     fm = new fm_info_s;
422     memset (fm, 0, sizeof *fm);
423     listview_new (&fm->lv, ctrl);
424 twoaday 105 for (i = 0; col[i].width; i++)
425 twoaday 244 listview_add_column (fm->lv, &col[i]);
426     listview_set_ext_style (fm->lv);
427     fm->model = NULL; /*init*/
428     *r_fm = fm;
429 twoaday 105 }
430 werner 36
431    
432 twoaday 270 /* Release the file model in @mod. */
433 twoaday 244 static void
434     fm_model_release (fm_model_t mod)
435 werner 36 {
436 twoaday 244 fm_model_t m;
437    
438     while (mod) {
439     m = mod->next;
440     free_if_alloc (mod->name);
441     free_if_alloc (mod->op);
442     free_if_alloc (mod->status);
443     free_if_alloc (mod);
444     mod = m;
445 werner 36 }
446 twoaday 105 }
447 werner 36
448    
449 twoaday 270 /* Reset the File Manager info context @fm. */
450 twoaday 244 void
451     fm_reset (fm_info_t fm)
452     {
453     listview_del_all_items (fm->lv);
454     fm_model_release (fm->model);
455     fm->model = NULL;
456     }
457    
458    
459 twoaday 270 /* Release the File Manager dialog context @fm. */
460 twoaday 244 void
461     fm_delete (fm_info_t fm)
462     {
463     if (!fm)
464     return;
465     if (fm->menu)
466     DestroyMenu (fm->menu);
467     listview_release (fm->lv);
468     fm_model_release (fm->model);
469     free_if_alloc (fm);
470     }
471    
472    
473 werner 36 int
474     fm_state_new (fm_state_t * ctx)
475     {
476 twoaday 195 fm_state_s *c;
477 werner 36
478     c = new fm_state_s;
479     if (!c)
480     BUG (0);
481 twoaday 41 memset (c, 0, sizeof *c);
482 twoaday 211 if (gpgme_new (&c->ctx))
483 werner 36 BUG (0);
484     *ctx = c;
485     return 0;
486 twoaday 195 }
487 werner 36
488    
489     /* Release the FM state handle @c. */
490     void
491     fm_state_release (fm_state_t c)
492     {
493     if (!c)
494     return;
495     if (c->ctx) {
496     gpgme_release (c->ctx);
497     c->ctx = NULL;
498     }
499 twoaday 105 safe_free (c->recp);
500 werner 36 free_if_alloc (c->opaque);
501     free_if_alloc (c->output);
502 twoaday 195 delete c;
503 werner 36 }
504    
505 twoaday 195
506 twoaday 270 /* Check if file @file is already in the list view. */
507 werner 36 static int
508 twoaday 226 fm_check_for_entry (listview_ctrl_t lv, const char *file)
509 werner 36 {
510 twoaday 244 char name[MAX_PATH+128];
511 werner 36 int i;
512    
513     memset (name, 0, sizeof (name));
514 twoaday 226 for (i = 0; i < listview_count_items (lv, 0); i++) {
515 twoaday 262 listview_get_item_text (lv, i, FM_COL_NAME, name, DIM (name) - 1);
516 twoaday 270 if (!stricmp (name, file))
517 werner 36 return 1; /* found */
518     }
519    
520     return 0;
521 twoaday 195 }
522 werner 36
523    
524     static int
525 twoaday 244 fm_set_ftype (listview_ctrl_t lv, fm_model_t *fm, const char *name)
526 werner 36 {
527 twoaday 244 fm_model_t m;
528 werner 36 const char *type;
529     int rc;
530    
531     rc = fm_check_for_entry (lv, name);
532     if (rc)
533 twoaday 270 return 0; /* already present. */
534 twoaday 244 m = new fm_model_s;
535     memset (m, 0, sizeof *m);
536 werner 36 type = fm_get_file_type (name, NULL);
537     if (!type || !strcmp (type, "UNKNOWN"))
538     type = gnupg_check_file_ext (name, NULL);
539 twoaday 244 listview_add_item2 (lv, " ", (void*)m);
540 twoaday 226 listview_add_sub_item (lv, 0, FM_COL_STAT, type);
541     listview_add_sub_item (lv, 0, FM_COL_NAME, name);
542 twoaday 244 m->name = m_strdup (name);
543     m->status = m_strdup (type);
544     m->op = NULL;
545     fm_model_add_file (fm, m);
546 werner 36 return 0;
547     }
548    
549    
550 twoaday 195 /* Add all files from the directory @path to the list view @lv. */
551 werner 36 static int
552 twoaday 244 fm_add_dir_files (listview_ctrl_t lv, fm_model_t *fm, char *path)
553 werner 36 {
554 twoaday 270 WIN32_FIND_DATA fd;
555     HANDLE hd;
556 twoaday 226 char *p;
557 werner 36
558     strcat (path, "\\*");
559 twoaday 270 hd = FindFirstFile (path, &fd);
560     if (hd == INVALID_HANDLE_VALUE)
561     return -1;
562 werner 36 do {
563 twoaday 270 if (fd.cFileName[0] == '.' && strlen (fd.cFileName) < 3)
564     continue;
565     p = new char [strlen (path) + strlen (fd.cFileName)+1];
566 werner 36 if (!p)
567     BUG (0);
568     memcpy (p, path, strlen (path)-1);
569     p[strlen (path)-1] = 0;
570 twoaday 270 strcat (p, fd.cFileName);
571 werner 36 if (!is_directory (p))
572 twoaday 244 fm_set_ftype (lv, fm, p);
573 werner 36 free_if_alloc (p);
574 twoaday 270 } while (FindNextFile (hd, &fd));
575     FindClose (hd);
576 werner 36 return 0;
577     }
578    
579    
580     /* Add the drag & drop files from @dd_files to the
581     list view control @lv. */
582     int
583 twoaday 244 fm_add_dropped_files (fm_info_t fm, HDROP dd_files)
584 werner 36 {
585 twoaday 270 char name[MAX_PATH+32+4];
586 twoaday 77 int rc = 0;
587 twoaday 270 UINT i;
588    
589     for (i = 0; i < DragQueryFile (dd_files, 0xFFFFFFFF, NULL, 0); i++) {
590     memset (name, 0, sizeof (name));
591 twoaday 262 DragQueryFile (dd_files, i, name, DIM (name) -1);
592 werner 36 if (is_directory (name))
593 twoaday 244 rc = fm_add_dir_files (fm->lv, &fm->model, name);
594 werner 36 else
595 twoaday 244 rc = fm_set_ftype (fm->lv, &fm->model, name);
596 werner 36 if (rc == -1)
597 twoaday 41 break; /* XXX: fixme? */
598 werner 36 }
599 twoaday 167 DragFinish (dd_files);
600 werner 36 return rc;
601     }
602    
603    
604 twoaday 41 /* Add a single file @name to the list view and before
605     figure out the type of it.
606     Return value: 0 on success. */
607     static int
608 twoaday 244 add_single_file (listview_ctrl_t lv, fm_model_t *fm, const char *name)
609 twoaday 41 {
610 twoaday 244 fm_model_t m;
611 twoaday 41 const char *type;
612 twoaday 270 int rc;
613 twoaday 244
614 twoaday 41 type = fm_get_file_type (name, NULL);
615     if (!type)
616     return WPTERR_FILE_OPEN;
617 twoaday 244 m = new fm_model_s;
618     memset (m, 0, sizeof *m);
619 twoaday 41 if (!strcmp (type, "UNKNOWN"))
620 twoaday 195 type = gnupg_check_file_ext (name, NULL);
621 twoaday 244 rc = listview_add_item2 (lv, "", (void*)m);
622 twoaday 195 if (!rc) {
623 twoaday 226 listview_add_sub_item (lv, 0, FM_COL_STAT, type);
624     listview_add_sub_item (lv, 0, FM_COL_NAME, name);
625 twoaday 41 }
626 twoaday 244 m->status = m_strdup (type);
627     m->name = m_strdup (name);
628     m->op = NULL;
629     fm_model_add_file (fm, m);
630 twoaday 41 return rc;
631     }
632    
633    
634     /* Use the common Open-File-Dialog to allow the user to
635     add one ore more selected files to the listview @lv. */
636 werner 36 int
637 twoaday 244 fm_add_opened_files (fm_info_t fm, HWND dlg)
638 werner 36 {
639     OPENFILENAME open;
640 twoaday 41 char file[512], name[MAX_PATH+1];
641     char *path = NULL;
642     const char *s;
643     int i, len=0, n=0;
644     int rc=0;
645    
646 werner 36 memset (&open, 0, sizeof (open));
647     open.lStructSize = sizeof (OPENFILENAME);
648     open.hInstance = glob_hinst;
649     open.lpstrTitle = _("File Open");
650 twoaday 167 open.lpstrFilter = "All Files (*.*)\0*.*\0\0";
651 werner 36 open.hwndOwner = dlg;
652     open.lpstrFile = file;
653 twoaday 262 open.nMaxFile = DIM (file) - 1;
654 twoaday 41 open.Flags = OFN_ALLOWMULTISELECT|OFN_EXPLORER ;
655 werner 36
656 twoaday 41 memset (file, 0, sizeof file);
657     if (!GetOpenFileName (&open))
658     return 0;
659    
660 twoaday 226 /* It is possible that multiple files are returned
661     and then they are separated by \0 chars. */
662 twoaday 41 s = file;
663 twoaday 262 len = DIM (file)-1;
664 twoaday 41 for (;;) {
665     if (len < 2 || (*s == '\0' && *(s+1) == '\0'))
666     break;
667     memset (name, 0, sizeof (name));
668     for (i=0; len > 0; len--, i++) {
669     if (*s == '\0') {
670     name[i] = *s++;
671     break;
672     }
673     name[i] = *s++;
674     }
675     if (n == 0)
676 twoaday 226 path = m_strdup (name);
677 twoaday 41 else {
678     char *p = make_filename (path, name, NULL);
679 twoaday 244 rc = add_single_file (fm->lv, &fm->model, p);
680 twoaday 226 free_if_alloc (p);
681 twoaday 41 }
682     n++;
683 werner 36 }
684 twoaday 41 if (n == 1) /* single file selected. */
685 twoaday 244 rc = add_single_file (fm->lv, &fm->model, path);
686 twoaday 226 free_if_alloc (path);
687 werner 36 return rc;
688     }
689    
690    
691     int
692 twoaday 214 fm_assume_onepass_sig (const char *fname)
693 twoaday 197 {
694 werner 36 armor_filter_context_t afx;
695     gpg_iobuf_t fp;
696 twoaday 197 gpgme_data_t dat;
697     PACKET *pkt;
698     char tmpfile[MAX_PATH+1];
699 werner 36 int check = 0;
700    
701 twoaday 197 pkt = (PACKET *)calloc (1, sizeof *pkt);
702 werner 36 if (!fname) {
703 twoaday 262 get_temp_name (tmpfile, DIM (tmpfile)-1, "gpgme.tmp");
704 werner 36 gpg_data_new_from_clipboard (&dat, 0);
705 twoaday 197 gpg_data_release_and_set_file (dat, tmpfile);
706 werner 36
707 twoaday 197 fp = gpg_iobuf_open (tmpfile);
708 werner 36 if (!fp)
709     return 0;
710 twoaday 270 gpg_iobuf_ioctl (fp, 3, 1, NULL); /* disable cache. */
711 werner 36 if (gpg_use_armor_filter(fp)) {
712     memset (&afx, 0, sizeof (afx));
713     gpg_iobuf_push_filter (fp, gpg_armor_filter, &afx);
714     }
715     gpg_init_packet (pkt);
716     if (!gpg_parse_packet (fp, pkt)
717     && pkt->pkttype == PKT_COMPRESSED)
718     check = 1;
719     gpg_free_packet (pkt);
720     gpg_iobuf_close (fp);
721 twoaday 226 DeleteFile (tmpfile);
722 werner 36 }
723     /* XXX: implement it for real files */
724 twoaday 197 safe_free (pkt);
725 werner 36 return check;
726     }
727    
728    
729     int
730     fm_get_current_pos (listview_ctrl_t lv)
731     {
732 twoaday 270 int i = 0;
733     int items;
734 werner 36
735     items = listview_count_items (lv, 0);
736     if (!items)
737     return -1;
738 twoaday 197 else if (items == 1) {
739 werner 36 listview_select_one (lv, 0);
740     return 0;
741     }
742 twoaday 197 else if (items > 1) {
743 werner 36 i = listview_get_curr_pos (lv);
744 twoaday 197 if (i == -1) {
745     msg_box (lv->ctrl, _("Please select a file."),
746     _("File Manager"), MB_ERR);
747 werner 36 return -1;
748     }
749     return i;
750     }
751    
752     return -1;
753 twoaday 197 }
754 werner 36
755    
756     static int
757 twoaday 197 fm_check_detached_sig (listview_ctrl_t lv, int pos)
758 werner 36 {
759 twoaday 270 char type[64];
760 werner 36
761 twoaday 262 listview_get_item_text (lv, pos, 0, type, DIM (type)-1);
762 twoaday 197 return !strcmp (type, "SIGNED-DETACH")? 1 : 0;
763     }
764 werner 36
765    
766 twoaday 270 /* Check if the given file on position @pos is useful for
767     command @fmd_cmd. For example sign can be used for all files
768     which are not already signed. */
769 werner 36 int
770     fm_check_file_type (listview_ctrl_t lv, int pos, int fm_cmd)
771     {
772 twoaday 270 char status[64];
773 werner 36 int rc = 0;
774    
775 twoaday 262 listview_get_item_text (lv, pos, 0, status, DIM (status) - 1);
776 werner 36
777     switch (fm_cmd) {
778     case FM_ENCRYPT:
779     case FM_ENCRYPT_DIR:
780     case FM_SIGNENCRYPT:
781     if (strcmp (status, "ENCRYPTED")
782     && strcmp (status, "SYMKEYENC"))
783     rc = 1;
784     break;
785    
786     case FM_DECRYPT:
787 twoaday 226 if (!strcmp (status, "DATA") ||
788     !strcmp (status, "ENCRYPTED") ||
789     !strcmp (status, "SYMKEYENC") ||
790     !strcmp (status, "ARMORED"))
791 werner 36 rc = 1;
792     break;
793    
794     case FM_SIGN:
795 twoaday 270 if (strncmp( status, "SIGNED", 6))
796 werner 36 rc = 1;
797     break;
798    
799     case FM_VERIFY:
800 twoaday 270 if(!strncmp (status, "SIGNED", 6) ||
801     !strcmp (status, "COMPRESSED"))
802 werner 36 rc = 1;
803     break;
804    
805     case FM_SYMENC:
806 twoaday 270 if (strcmp (status, "SYMKEYENC"))
807 werner 36 rc = 1;
808     break;
809    
810     case FM_IMPORT:
811 twoaday 270 if (!strcmp (status, "PUBKEY") ||
812     !strcmp (status, "SECKEY"))
813 werner 36 rc = 1;
814     break;
815    
816     case FM_WIPE:
817     case FM_LIST:
818     rc = 1;
819     break;
820     }
821    
822     return rc;
823 twoaday 197 }
824 werner 36
825    
826 twoaday 88 /* Set the file status of the given command @fm_cmd.
827     @success is 0 on success. */
828 werner 36 static void
829 twoaday 88 fm_set_status (listview_ctrl_t lv, int pos, int fm_cmd,
830     gpgme_sig_mode_t sigmode, int success, const char *output)
831 werner 36 {
832     char status[128], operat[128];
833     int update = 1;
834     const char *s;
835    
836 twoaday 88 if (fm_cmd == FM_LIST)
837 werner 36 return;
838     success ? s = "SUCCESS" : s = "FAILED";
839 twoaday 88 strcpy (operat, s);
840 werner 36
841     switch (fm_cmd) {
842     case FM_ENCRYPT:
843     case FM_ENCRYPT_DIR:
844 twoaday 270 case FM_SIGNENCRYPT:
845     strcpy (status, "ENCRYPTED");
846     break;
847    
848     case FM_DECRYPT:
849     strcpy (status, "UNKNOWN");
850     break;
851    
852 twoaday 88 case FM_SIGN:
853     if (sigmode == GPGME_SIG_MODE_DETACH)
854     strcpy (status, "SIGNED-DETACH");
855 twoaday 119 else if (sigmode == GPGME_SIG_MODE_CLEAR)
856     strcpy (status, "SIGNED-CLEAR");
857 twoaday 88 else
858     strcpy (status, "SIGNED");
859     break;
860 twoaday 270 case FM_VERIFY:
861     update = 0;
862     break;
863    
864     case FM_SYMENC:
865     strcpy (status, "SYMKEYENC");
866     break;
867    
868     case FM_IMPORT:
869     update = 0;
870     break;
871    
872     case FM_WIPE:
873     strcpy (status, "WIPED");
874     break;
875    
876     default:
877     strcpy (status, "UNKNOWN");
878     break;
879 werner 36 }
880    
881 twoaday 119 if (success && update) {
882 twoaday 270 listview_add_sub_item (lv, pos, FM_COL_STAT, status);
883     listview_add_sub_item (lv, pos, FM_COL_NAME, output);
884 werner 36 }
885 twoaday 270 listview_add_sub_item (lv, pos, FM_COL_OP, operat);
886 twoaday 88 }
887 werner 36
888    
889     int
890     fm_clearsign_8bit (listview_ctrl_t lv, fm_state_s *ctx)
891     {
892     FILE *f;
893 twoaday 234 BYTE buf[32];
894 twoaday 270 char name[MAX_PATH+1];
895 werner 36 int i, n, cnt=0;
896    
897     if (ctx->sigmode != GPGME_SIG_MODE_CLEAR)
898     return 0;
899 twoaday 262 listview_get_item_text (lv, -1, FM_COL_NAME, name, DIM (name)-1);
900 twoaday 270 if (stristr (name, ".txt"))
901 werner 36 return 0;
902     f = fopen (name, "rb");
903     if (!f)
904     return -1; /* should never happen */
905     n = fread (buf, 1, 32, f);
906 twoaday 226 fclose (f);
907 werner 36 for (i = 0; i < n; i++) {
908     if (buf[i] == 0x00 || buf[i] > 170)
909     cnt++;
910     }
911     if (!cnt)
912     return 0;
913     n = -1;
914 twoaday 197 i = log_box (_("File Manager"), MB_WARN|MB_YESNO,
915 werner 36 _("\"%s\" does not seems to be a text file.\n"
916     "Do you really want to clearsign it?"), name);
917     if (i == IDYES)
918     n = 0;
919     return n;
920     }
921    
922 twoaday 197
923 werner 36 int
924     fm_parse_files (listview_ctrl_t lv, HWND dlg, int cmd)
925     {
926     struct secdel_confirm_s confirm = {0};
927     struct progress_filter_s pfx, pfx2;
928     fm_state_s * ctx;
929     int fm_cmd, sig_detached = 0;
930     int rc = 0, i, n, ndel = 0;
931 twoaday 270 char fname[2*MAX_PATH+1], status[128];
932 werner 36
933     switch (cmd) {
934     case ID_FILEMISC_ENCRYPT: fm_cmd = FM_ENCRYPT; break;
935 twoaday 77 case ID_FILEMISC_ENCRYPT_ZIP:fm_cmd = FM_ENCRYPT_ZIP; break;
936 werner 36 case ID_FILEMISC_DECRYPT: fm_cmd = FM_DECRYPT; break;
937     case ID_FILEMISC_SYMENC: fm_cmd = FM_SYMENC; break;
938     case ID_FILEMISC_SIGN: fm_cmd = FM_SIGN; break;
939     case ID_FILEMISC_VERIFY: fm_cmd = FM_VERIFY; break;
940     case ID_FILEMISC_IMPORT: fm_cmd = FM_IMPORT; break;
941     case ID_FILEMISC_WIPE: fm_cmd = FM_WIPE; break;
942     case ID_FILEMISC_LIST: fm_cmd = FM_LIST; break;
943     case ID_FILEMISC_SIGNENC: fm_cmd = FM_SIGNENCRYPT; break;
944     default: return 1; /* unknown command */
945     }
946    
947     if (fm_get_current_pos (lv) == -1)
948 twoaday 77 return WPTERR_GENERAL;
949 werner 36 rc = fm_state_new (&ctx);
950     if (rc)
951     BUG (0);
952     ctx->dlg = dlg;
953    
954     // XXX: for file operations the progress dialog will be
955     // reloaded somewhere and thus a 'dummy' dialog remains
956    
957     /* we use it here to make sure that pfx_cleanup will not use
958     any weird values. */
959     memset (&pfx, 0, sizeof (pfx));
960     ctx->prog_cb = NULL;
961     if (cmd != FM_VERIFY && cmd != FM_SIGN /*&& reg_prefs.fm.progress > 0*/) {
962     pfx.hwnd = dlg;
963     /*gpgme_set_progress_cb (ctx->ctx, progress_callback, &pfx);*/
964     /*ctx->prog_cb = &pfx;*/
965     }
966    
967     /* Commands we need before we can perform the main command */
968     switch (fm_cmd) {
969 twoaday 77 case FM_ENCRYPT_ZIP:
970 werner 36 case FM_ENCRYPT:
971     case FM_SIGNENCRYPT:
972     if (fm_cmd == FM_SIGNENCRYPT)
973     ctx->req_signer = 1;
974 twoaday 105 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILE_ENCRYPT,
975     ctx->dlg, file_encrypt_dlg_proc, (LPARAM)ctx);
976 werner 36 if (ctx->cancel == 1) {
977 twoaday 105 rc = WPTERR_GENERAL;
978 werner 36 goto leave;
979     }
980     break;
981    
982     case FM_SIGN:
983     DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_FILE_SIGN, dlg,
984     file_sign_dlg_proc, (LPARAM) ctx);
985     if (ctx->cancel == 1 || fm_clearsign_8bit (lv, ctx)) {
986     rc = WPTERR_GENERAL;
987     goto leave;
988     }
989     break;
990    
991     case FM_WIPE:
992     memset (&pfx2, 0, sizeof (pfx2));
993     secure_unlink_set_cb (progress_callback, &pfx2);
994     break;
995     }
996    
997 twoaday 270 for( i = 0, n = 0; i < listview_count_items (lv, 0); i++ ) {
998     if (!listview_get_item_state (lv, i))
999 werner 36 continue;
1000 twoaday 270 listview_get_item_text (lv, i, FM_COL_STAT, status, DIM (status) -1);
1001     if (!strcmp( status, "ENCRYPTED") && fm_cmd == FM_DECRYPT)
1002 werner 36 n++;
1003 twoaday 270 if (!strcmp( status, "UNKNOWN") && fm_cmd == FM_SIGN)
1004 werner 36 n++;
1005     if (fm_cmd == FM_WIPE)
1006     ndel++;
1007     }
1008    
1009     if (n > 1 && fm_cmd != FM_SYMENC)
1010     ctx->cache_cb = 1;
1011    
1012     if (fm_cmd == FM_WIPE && ndel > 0) {
1013     memset (&confirm, 0, sizeof confirm);
1014     confirm.lv_files = lv;
1015     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILES_SECDEL, ctx->dlg,
1016 twoaday 77 file_secdel_confirm_dlg_proc, (LPARAM)&confirm);
1017 werner 36 if (!confirm.yes)
1018     goto leave;
1019     }
1020 twoaday 119
1021 twoaday 77 if (fm_cmd == FM_ENCRYPT_ZIP)
1022     fm_encrypt_into_zip (ctx, lv);
1023    
1024     for (i = 0; i < listview_count_items (lv, 0); i++) {
1025 twoaday 177 if (!listview_get_item_state (lv, i))
1026 werner 36 continue;
1027 twoaday 270 listview_get_item_text (lv, i, FM_COL_NAME, fname, DIM (fname) - 1);
1028 twoaday 119 if( file_exist_check (fname) && !is_directory (fname)) {
1029     log_box (_("File Manager"), MB_ERR,
1030     _("\"%s\" does not exist"), fname);
1031 werner 36 continue;
1032     }
1033 twoaday 119 if (is_directory (fname))
1034 werner 36 fm_cmd = FM_ENCRYPT_DIR;
1035 twoaday 119 if (!fm_check_file_type (lv, i, fm_cmd))
1036 werner 36 continue;
1037 twoaday 119 sig_detached = fm_check_detached_sig (lv, i);
1038 twoaday 77 switch (fm_cmd) {
1039 werner 36 case FM_LIST: rc = fm_list( fname, dlg ); break;
1040     case FM_WIPE: rc = fm_wipe( fname ); break;
1041     case FM_ENCRYPT: rc = fm_encrypt( ctx, fname, 0 ); break;
1042     case FM_ENCRYPT_DIR: rc = fm_encrypt_directory( ctx, fname ); break;
1043     case FM_SIGNENCRYPT: rc = fm_encrypt( ctx, fname, 1 ); break;
1044     case FM_DECRYPT: rc = fm_decrypt( ctx, fname ); break;
1045     case FM_SIGN: rc = fm_sign( ctx, fname ); break;
1046 twoaday 177 case FM_SYMENC: rc = fm_sym_encrypt (ctx, fname); break;
1047 werner 36 case FM_VERIFY: rc = fm_verify (ctx, sig_detached, fname);break;
1048     case FM_IMPORT:
1049     free_if_alloc (ctx->opaque);
1050     ctx->opaque = m_strdup (fname);
1051 twoaday 177 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
1052     file_import_dlg_proc, (LPARAM)ctx);
1053 werner 36 if (ctx->cancel == 1)
1054     continue;
1055     rc = fm_import (ctx, fname);
1056     break;
1057     }
1058 twoaday 177 if (ctx->cancel == 1) {
1059     ctx->cancel = 0;
1060     continue;
1061     }
1062 twoaday 88 fm_set_status (lv, i, fm_cmd, ctx->sigmode, !rc, ctx->output);
1063 werner 36 free_if_alloc (ctx->output);
1064     progress_cleanup (&pfx);
1065     }
1066 twoaday 77
1067 werner 36 if (fm_cmd == FM_WIPE) {
1068     secure_unlink_set_cb (NULL, NULL);
1069     progress_cleanup (&pfx2);
1070     }
1071     if (ctx->cache_cb) {
1072     release_gpg_passphrase_cb (&ctx->pass_cb);
1073     ctx->cache_cb = 0; /* make sure it's only used for this session! */
1074     }
1075    
1076     /* remove wipe files from the list */
1077     n = listview_count_items (lv, 0);
1078     while (n--) {
1079 twoaday 270 listview_get_item_text (lv, n, FM_COL_STAT, status, DIM (status) - 1);
1080 twoaday 77 if (!strcmp (status, "WIPED"))
1081 werner 36 listview_del_item (lv, n);
1082     }
1083    
1084     leave:
1085     if (!rc)
1086     fm_state_release (ctx);
1087     progress_cleanup (&pfx);
1088     return rc;
1089 twoaday 270 }
1090 werner 36
1091    
1092     /* Wipe the given file @name with the delete mode
1093     from the configuration.
1094     Return value: 0 on success. */
1095     int
1096     fm_wipe (const char *name)
1097     {
1098     int rc;
1099    
1100     SetCursor (LoadCursor (NULL, IDC_WAIT));
1101     remove_crit_file_attrs (name, 1);
1102     rc = secure_unlink (name, reg_prefs.wipe_mode);
1103     SetCursor (LoadCursor (NULL, IDC_ARROW));
1104     return rc;
1105     }
1106    
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     secure_unlink (name, WIPE_MODE_SIMPLE);
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     /* Verify the signature from the file @name. If @detached 1,
1686     it is assumed that a detached signature should be checked. */
1687     int
1688     fm_verify (fm_state_t c, int detached, const char *name)
1689     {
1690     gpgme_ctx_t ctx = c->ctx;
1691     gpgme_error_t err;
1692     gpgme_signature_t s;
1693     gpgme_verify_result_t res;
1694     struct file_sig_ctx_s log;
1695     file_data_t in=NULL, out=NULL;
1696     int rc = 0;
1697    
1698 twoaday 197 if (stristr (name, ".sig"))
1699 werner 36 detached = 1;
1700    
1701     if (get_output_file (c, name, detached))
1702     return WPTERR_GENERAL;
1703    
1704     memset (&log, 0, sizeof (log));
1705     log.file = m_strdup (name);
1706     file_verify_create_dlg ();
1707    
1708 twoaday 105 err = gpg_file_data_new (name, F_DATA_READ, &in);
1709 werner 36 if (err)
1710     goto leave;
1711 twoaday 105 err = gpg_file_data_new (c->output,
1712     detached? F_DATA_READ : F_DATA_WRITE, &out);
1713 werner 36 if (err)
1714     goto leave;
1715    
1716     op_begin ();
1717     if (c->sigmode == GPGME_SIG_MODE_DETACH)
1718     err = gpgme_op_verify (ctx, in->dat, out->dat, NULL);
1719     else
1720     err = gpgme_op_verify (ctx, in->dat, in->dat, out->dat);
1721     op_end ();
1722     if (err) {
1723     msg_box (c->dlg, gpgme_strerror (err), _("Verify"), MB_ERR);
1724     rc = WPTERR_GENERAL;
1725     goto leave;
1726     }
1727    
1728     res = gpgme_op_verify_result (ctx);
1729 twoaday 270 if (!res)
1730     goto leave;
1731 werner 36 for (s=res->signatures; s; s=s->next) {
1732     log.sig = s;
1733     fm_add_sig_stat (&log);
1734     }
1735     if (!c->output)
1736     c->output = m_strdup (name); /* for later use */
1737    
1738     leave:
1739     if (in)
1740     gpg_file_data_release (in);
1741     if (out)
1742     gpg_file_data_release (out);
1743 twoaday 105 free_if_alloc (log.file);
1744 werner 36 return rc;
1745     }
1746    
1747    
1748 twoaday 105 /* Import the keys from the file @name.
1749     Return value: 0 on success. */
1750 werner 36 int
1751     fm_import (fm_state_t c, const char *name)
1752     {
1753     gpgme_ctx_t ctx = c->ctx;
1754     gpgme_error_t err;
1755     gpgme_import_result_t res;
1756     file_data_t keydata = NULL;
1757     int rc = 0;
1758    
1759     free_if_alloc (c->output);
1760     c->output = m_strdup (name);
1761    
1762 twoaday 105 err = gpg_file_data_new (name, F_DATA_READ, &keydata);
1763 werner 36 if (err)
1764     goto leave;
1765    
1766     op_begin ();
1767     err = gpgme_op_import (ctx, keydata->dat);
1768     op_end ();
1769     if (err) {
1770     msg_box (c->dlg, gpgme_strerror (err), _("Import"), MB_ERR);
1771     rc = WPTERR_GENERAL;
1772     goto leave;
1773     }
1774    
1775     res = gpgme_op_import_result (ctx);
1776     print_import_status (res);
1777     if (res->no_user_id > 0) {
1778 twoaday 105 msg_box (c->dlg, _("Key without a self signature was dectected!\n"
1779 werner 36 "(This key is NOT usable for encryption, etc)\n"
1780     "\n"
1781     "Cannot import these key(s)!"), _("Import"), MB_INFO);
1782     }
1783    
1784     leave:
1785     if (keydata)
1786     gpg_file_data_release (keydata);
1787     return rc;
1788 twoaday 105 }
1789 werner 36
1790    
1791     /* Export the selected keys from the File Manager to a file. */
1792     int
1793     fm_export (fm_state_t c)
1794 twoaday 197 {
1795 werner 36 gpgme_ctx_t ctx = c->ctx;
1796     gpgme_error_t err;
1797     gpgme_key_t *rset = c->recp;
1798     file_data_t keydata = NULL;
1799 twoaday 94 const char *name;
1800 werner 36 char *p = NULL, *patt = NULL;
1801 twoaday 197 int rc = 0;
1802 werner 36
1803     if (!rset || !rset[0]) {
1804 twoaday 226 msg_box (c->dlg, _("No key was selected for export."),
1805     _("Export"), MB_ERR);
1806 werner 36 rc = WPTERR_GENERAL;
1807     goto leave;
1808     }
1809    
1810 twoaday 105 if (rset[1] == NULL) /* count == 1*/
1811 twoaday 129 p = km_gen_export_filename (rset[0]->subkeys->keyid+8, 0);
1812 werner 36
1813 twoaday 77 name = get_filesave_dlg (c->dlg, _("Choose Name for Key File"),
1814 werner 36 NULL, p? p : NULL);
1815     if (!name)
1816 twoaday 218 name = reg_prefs.default_ext? "keys.pgp" : "keys.gpg";
1817 werner 36
1818     patt = gpg_keylist_to_pattern (rset, c->n_recp);
1819    
1820 twoaday 105 err = gpg_file_data_new (name, F_DATA_WRITE, &keydata);
1821 werner 36 if (err)
1822     goto leave;
1823    
1824     op_begin ();
1825     err = gpgme_op_export (ctx, patt, 0, keydata->dat);
1826     op_end ();
1827     if (err) {
1828     msg_box (c->dlg, gpgme_strerror (err), _("Export"), MB_ERR);
1829     rc = WPTERR_GENERAL;
1830     goto leave;
1831     }
1832     log_box (_("GnuPG status"), MB_OK, _("Finished (Output: %s)"), name);
1833    
1834     leave:
1835     if (keydata)
1836     gpg_file_data_release (keydata);
1837 twoaday 197 safe_free (patt);
1838 werner 36 free_if_alloc (p);
1839     return rc;
1840     }
1841    
1842    
1843     /* Parse the command line and process the given file. */
1844     int
1845     fm_parse_command_line (char *cmdl)
1846     {
1847     fm_state_t ctx;
1848     const char *s;
1849     char *p, *fn = NULL;
1850     int count = 0, detached = 0;
1851     int type;
1852    
1853     if (!cmdl || !*cmdl)
1854     return 0;
1855    
1856     fm_state_new (&ctx);
1857     ctx->dlg = GetActiveWindow ();
1858     ctx->cache_cb = 1;
1859    
1860     p = cmdl;
1861     if (p && *p > 32 && !stristr (p, "winpt.exe")
1862     && !strstr (p, "--" )) {
1863     count++;
1864     if (*p == '"') { /* need to remove quotes */
1865     fn = new char[strlen (p)];
1866     if (!fn)
1867     BUG (NULL);
1868     memcpy (fn, p+1, strlen (p) - 2);
1869     fn[strlen (p) -2] = '\0';
1870     }
1871     else
1872     fn = m_strdup (p);
1873     s = fm_get_file_type (fn, &type);
1874     if (!s || !strcmp (s, "UNKNOWN"))
1875     s = gnupg_check_file_ext (fn, &type);
1876     if (type == PGP_NONE) {
1877     log_box (_("File Manager"), MB_ERR,
1878     _("%s: no valid OpenPGP data found."), p);
1879     free_if_alloc (fn);
1880     return count;
1881     }
1882     switch (type) {
1883     case PGP_MESSAGE:
1884     fm_decrypt (ctx, fn);
1885     break;
1886    
1887     case PGP_PUBKEY:
1888     case PGP_SECKEY:
1889     fm_import (ctx, fn);
1890     break;
1891    
1892     case PGP_SIG:
1893     case PGP_CLEARSIG:
1894     if (type == PGP_SIG)
1895     detached = 1;
1896     fm_verify (ctx, detached, fn);
1897     file_verify_wait ();
1898 twoaday 77 break;
1899 twoaday 88
1900 twoaday 77 default:
1901     break;
1902 werner 36 }
1903     }
1904    
1905     wipememory (&ctx->pass_cb, sizeof (ctx->pass_cb));
1906     free_if_alloc (fn);
1907     fm_state_release (ctx);
1908     return count;
1909     }
1910    
1911    
1912 twoaday 105 /* Extract the last folder name from @name. */
1913 werner 36 const char*
1914     default_dirname (const char *name)
1915     {
1916 twoaday 105 char *p = strrchr (name, '\\');
1917     if (!p)
1918 werner 36 return NULL;
1919     return p+1;
1920 twoaday 105 }
1921 werner 36
1922    
1923 twoaday 77 /* Store all selected files from @lv in a zip archive
1924     and encrypt the zip archive then.
1925     Return value: 0 on success. */
1926 werner 36 int
1927 twoaday 77 fm_encrypt_into_zip (fm_state_t ctx, listview_ctrl_t lv)
1928     {
1929     PK_FILE_LIST list=NULL;
1930 twoaday 197 const char *outfile, *ext;
1931 twoaday 77 char *out_enc;
1932 twoaday 197 int nitems;
1933 twoaday 77 int i, idx = -1;
1934     int rc;
1935    
1936 twoaday 197 nitems = listview_count_items (lv, 0);
1937 twoaday 77 if (!nitems) {
1938     msg_box (NULL, _("Encrypting into a ZIP archive makes sense with multiple files"),
1939     _("File Manager"), MB_ERR);
1940 twoaday 105 return WPTERR_GENERAL;
1941 twoaday 77 }
1942    
1943 twoaday 105 outfile = get_filesave_dlg (ctx->dlg, _("Choose File Name for Output"),
1944     NULL, "Encrypted_Files.zip");
1945 twoaday 77 if (!outfile)
1946 twoaday 105 return WPTERR_GENERAL;
1947 twoaday 77
1948     for (i=0; i < nitems; i++) {
1949 twoaday 256 char name[MAX_PATH+32];
1950    
1951 twoaday 77 if (!listview_get_item_state (lv, i))
1952     continue;
1953     if (idx == -1)
1954     idx = i;
1955 twoaday 262 listview_get_item_text (lv, i, 1, name, DIM (name)-1);
1956 twoaday 77 pk_list_add (&list, name);
1957     }
1958    
1959     pk_archiv_create (list, outfile);
1960     pk_list_free (list);
1961    
1962     rc = fm_encrypt (ctx, outfile, 0);
1963     DeleteFile (outfile);
1964     if (rc)
1965     return rc;
1966    
1967 twoaday 197 ext = file_get_extension (ctx->ctx, ctx->sigmode)+1;
1968     out_enc = make_filename (NULL, outfile, ext);
1969 twoaday 88 fm_set_status (lv, idx, FM_ENCRYPT, (gpgme_sig_mode_t)0, 1, out_enc);
1970 twoaday 77 free_if_alloc (out_enc);
1971    
1972 twoaday 256 for (i=nitems; i > -1; i--) {
1973 twoaday 77 if (i != idx && listview_get_item_state (lv, i))
1974     listview_del_item (lv, i);
1975     }
1976     return 0;
1977     }
1978    
1979    
1980     int
1981 twoaday 105 fm_encrypt_directory (fm_state_t c, const char *name)
1982 twoaday 256 {
1983 werner 36 WIN32_FIND_DATA findbuf;
1984     HANDLE hd;
1985 twoaday 256 PK_FILE_LIST list = NULL;
1986 twoaday 226 const char *s;
1987     char *patt = NULL, *p;
1988 werner 36 int rc = 0;
1989    
1990 twoaday 105 if (!is_directory (name))
1991 werner 36 return -1;
1992 twoaday 105 patt = new char[strlen (name) + 4];
1993     if (!patt)
1994     BUG (NULL);
1995     strcpy (patt, name);
1996     strcat (patt, "\\*");
1997     hd = FindFirstFile (patt, &findbuf);
1998     if (!hd) {
1999     free_if_alloc (patt);
2000     return WPTERR_GENERAL;
2001 werner 36 }
2002 twoaday 226 if (strcmp (findbuf.cFileName, ".") && strcmp (findbuf.cFileName, "..")) {
2003     p = make_filename (name, findbuf.cFileName, NULL);
2004     pk_list_add (&list, p);
2005     free_if_alloc (p);
2006 werner 36 }
2007 twoaday 262 /* XXX: support to scan sub directories also. */
2008 twoaday 256 while (FindNextFile (hd, &findbuf)) {
2009     if (strcmp (findbuf.cFileName, ".") && strcmp (findbuf.cFileName, "..")) {
2010     p = make_filename (name, findbuf.cFileName, NULL);
2011     pk_list_add (&list, p);
2012     free_if_alloc (p);
2013 werner 36 }
2014     }
2015 twoaday 105 s = get_filesave_dlg (c->dlg, _("Choose a Name for the Archive"),
2016     NULL, default_dirname (name));
2017 twoaday 256 if (!s) {
2018 twoaday 226 msg_box (c->dlg, _("Invalid archive name. Exit."),
2019     _("Encrypt Directory"), MB_ERR);
2020 werner 36 rc = -1;
2021     goto leave;
2022     }
2023    
2024 twoaday 226 rc = pk_archiv_create (list, s);
2025 twoaday 256 if (rc)
2026 twoaday 226 msg_box (c->dlg, _("Could not create zip archive."),
2027     _("Encrypt Directory"), MB_ERR);
2028 werner 36 else {
2029 twoaday 226 fm_encrypt (c, s, 0);
2030     DeleteFile (s);
2031 werner 36 }
2032     leave:
2033     FindClose (hd);
2034 twoaday 226 pk_list_free (list);
2035     free_if_alloc (patt);
2036 werner 36 return rc;
2037 twoaday 105 }
2038 werner 36
2039    
2040     static int CALLBACK
2041 twoaday 105 fm_cmp_cb (LPARAM first, LPARAM second, LPARAM sortby)
2042 werner 36 {
2043 twoaday 244 fm_model_t a, b;
2044     int cmpres = 0;
2045 werner 36
2046 twoaday 244 a = (fm_model_t)first;
2047     b = (fm_model_t)second;
2048     if (!a || !b)
2049     return 0;
2050    
2051 twoaday 197 switch ((int)sortby) {
2052 twoaday 244 case FM_COL_STAT:
2053     cmpres = stricmp (a->status, b->status);
2054 werner 36 break;
2055 twoaday 244
2056     case FM_COL_NAME:
2057     cmpres = stricmp (a->name, b->name);
2058 werner 36 break;
2059 twoaday 244
2060     case FM_COL_OP:
2061     if (a->op && b->op)
2062     cmpres = stricmp (a->op, b->op);
2063 werner 36 break;
2064     }
2065 twoaday 244 return cmpres;
2066 twoaday 105 }
2067 werner 36
2068 twoaday 244
2069 twoaday 105 /* Sort the list items from @lv with the mode given by @sortby. */
2070 werner 36 int
2071 twoaday 105 fm_sort (listview_ctrl_t lv, int sortby)
2072 werner 36 {
2073 twoaday 244 return ListView_SortItems (lv->ctrl, fm_cmp_cb, (LPARAM)sortby);
2074 twoaday 105 }
2075 werner 36
2076    
2077 twoaday 105 /* Start the 'print md' dialog. Pass over the listview control
2078     @lv and the digest algo @mdalgo. */
2079 werner 36 void
2080 twoaday 105 fm_print_md (listview_ctrl_t lv, HWND dlg, int mdalgo)
2081 werner 36 {
2082     struct md_file_s mdctx;
2083    
2084 twoaday 105 if (listview_count_items (lv, 0) == 0)
2085 werner 36 return;
2086     memset (&mdctx, 0, sizeof (mdctx));
2087     mdctx.lv = lv;
2088     mdctx.mdalgo = mdalgo;
2089 twoaday 105 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILE_MDSUM, dlg,
2090     mdsum_dlg_proc, (LPARAM)&mdctx);
2091     }
2092 werner 36
2093    
2094 twoaday 77 /* Send the selected file in @lv via MAPI to a mail recipient. */
2095 werner 36 int
2096     fm_send_file (listview_ctrl_t lv)
2097     {
2098 twoaday 262 char name[MAX_PATH+1];
2099 werner 36 int rc;
2100    
2101 twoaday 262 rc = listview_get_item_text (lv, -1, FM_COL_NAME, name, DIM (name)-1);
2102 twoaday 77 if (rc != -1)
2103 twoaday 256 mapi_send_ascfile (name);
2104 werner 36 return 0;
2105     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26