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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 409 - (hide annotations)
Mon Feb 6 19:39:00 2012 UTC (13 years ago) by twoaday
File size: 44197 byte(s)
2012-02-06  Timo Schulz  <twoaday@gmx.net>

       * wptGPG.cpp (check_keyring): Improved error checking.
       * wptFileManager.cpp: Removed obsolete code.
		

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26