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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 463 - (hide annotations)
Tue Oct 9 09:07:28 2012 UTC (12 years, 4 months ago) by twoaday
File size: 44224 byte(s)
2012-10-09  Timo Schulz  <twoaday@gmx.net>

        * wptFileManager.cpp (fm_check_armor_type): Check more than
	        one line to determine the message type.
		

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26