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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 328 - (hide annotations)
Fri Sep 25 16:07:38 2009 UTC (15 years, 5 months ago) by twoaday
File size: 47241 byte(s)


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     return; /* Does not exist */
134    
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_ENCRYPT_DIR:
733     case FM_SIGNENCRYPT:
734     if (strcmp (status, "ENCRYPTED")
735     && strcmp (status, "SYMKEYENC"))
736     rc = 1;
737     break;
738    
739     case FM_DECRYPT:
740 twoaday 226 if (!strcmp (status, "DATA") ||
741     !strcmp (status, "ENCRYPTED") ||
742     !strcmp (status, "SYMKEYENC") ||
743     !strcmp (status, "ARMORED"))
744 werner 36 rc = 1;
745     break;
746    
747     case FM_SIGN:
748 twoaday 270 if (strncmp( status, "SIGNED", 6))
749 werner 36 rc = 1;
750     break;
751    
752     case FM_VERIFY:
753 twoaday 270 if(!strncmp (status, "SIGNED", 6) ||
754     !strcmp (status, "COMPRESSED"))
755 werner 36 rc = 1;
756     break;
757    
758     case FM_SYMENC:
759 twoaday 270 if (strcmp (status, "SYMKEYENC"))
760 werner 36 rc = 1;
761     break;
762    
763     case FM_IMPORT:
764 twoaday 270 if (!strcmp (status, "PUBKEY") ||
765     !strcmp (status, "SECKEY"))
766 werner 36 rc = 1;
767     break;
768    
769     case FM_LIST:
770     rc = 1;
771     break;
772     }
773    
774     return rc;
775 twoaday 197 }
776 werner 36
777    
778 twoaday 88 /* Set the file status of the given command @fm_cmd.
779     @success is 0 on success. */
780 werner 36 static void
781 twoaday 88 fm_set_status (listview_ctrl_t lv, int pos, int fm_cmd,
782     gpgme_sig_mode_t sigmode, int success, const char *output)
783 werner 36 {
784     char status[128], operat[128];
785     int update = 1;
786     const char *s;
787    
788 twoaday 88 if (fm_cmd == FM_LIST)
789 werner 36 return;
790     success ? s = "SUCCESS" : s = "FAILED";
791 twoaday 88 strcpy (operat, s);
792 werner 36
793     switch (fm_cmd) {
794     case FM_ENCRYPT:
795     case FM_ENCRYPT_DIR:
796 twoaday 270 case FM_SIGNENCRYPT:
797     strcpy (status, "ENCRYPTED");
798     break;
799    
800     case FM_DECRYPT:
801     strcpy (status, "UNKNOWN");
802     break;
803    
804 twoaday 88 case FM_SIGN:
805     if (sigmode == GPGME_SIG_MODE_DETACH)
806     strcpy (status, "SIGNED-DETACH");
807 twoaday 119 else if (sigmode == GPGME_SIG_MODE_CLEAR)
808     strcpy (status, "SIGNED-CLEAR");
809 twoaday 88 else
810     strcpy (status, "SIGNED");
811     break;
812 twoaday 270 case FM_VERIFY:
813     update = 0;
814     break;
815    
816     case FM_SYMENC:
817     strcpy (status, "SYMKEYENC");
818     break;
819    
820     case FM_IMPORT:
821     update = 0;
822     break;
823    
824     default:
825     strcpy (status, "UNKNOWN");
826     break;
827 werner 36 }
828    
829 twoaday 119 if (success && update) {
830 twoaday 270 listview_add_sub_item (lv, pos, FM_COL_STAT, status);
831     listview_add_sub_item (lv, pos, FM_COL_NAME, output);
832 werner 36 }
833 twoaday 270 listview_add_sub_item (lv, pos, FM_COL_OP, operat);
834 twoaday 88 }
835 werner 36
836    
837     int
838     fm_clearsign_8bit (listview_ctrl_t lv, fm_state_s *ctx)
839     {
840     FILE *f;
841 twoaday 234 BYTE buf[32];
842 twoaday 270 char name[MAX_PATH+1];
843 werner 36 int i, n, cnt=0;
844    
845     if (ctx->sigmode != GPGME_SIG_MODE_CLEAR)
846     return 0;
847 twoaday 262 listview_get_item_text (lv, -1, FM_COL_NAME, name, DIM (name)-1);
848 twoaday 270 if (stristr (name, ".txt"))
849 werner 36 return 0;
850     f = fopen (name, "rb");
851     if (!f)
852     return -1; /* should never happen */
853     n = fread (buf, 1, 32, f);
854 twoaday 226 fclose (f);
855 werner 36 for (i = 0; i < n; i++) {
856     if (buf[i] == 0x00 || buf[i] > 170)
857     cnt++;
858     }
859     if (!cnt)
860     return 0;
861     n = -1;
862 twoaday 197 i = log_box (_("File Manager"), MB_WARN|MB_YESNO,
863 werner 36 _("\"%s\" does not seems to be a text file.\n"
864     "Do you really want to clearsign it?"), name);
865     if (i == IDYES)
866     n = 0;
867     return n;
868     }
869    
870     int
871     fm_parse_files (listview_ctrl_t lv, HWND dlg, int cmd)
872     {
873 twoaday 328 struct progress_filter_s pfx/*, pfx2*/;
874 werner 36 fm_state_s * ctx;
875     int fm_cmd, sig_detached = 0;
876 twoaday 328 int rc = 0, i, n;
877 twoaday 270 char fname[2*MAX_PATH+1], status[128];
878 werner 36
879     switch (cmd) {
880     case ID_FILEMISC_ENCRYPT: fm_cmd = FM_ENCRYPT; break;
881     case ID_FILEMISC_DECRYPT: fm_cmd = FM_DECRYPT; break;
882     case ID_FILEMISC_SYMENC: fm_cmd = FM_SYMENC; break;
883     case ID_FILEMISC_SIGN: fm_cmd = FM_SIGN; break;
884     case ID_FILEMISC_VERIFY: fm_cmd = FM_VERIFY; break;
885     case ID_FILEMISC_IMPORT: fm_cmd = FM_IMPORT; break;
886     case ID_FILEMISC_LIST: fm_cmd = FM_LIST; break;
887     case ID_FILEMISC_SIGNENC: fm_cmd = FM_SIGNENCRYPT; break;
888     default: return 1; /* unknown command */
889     }
890    
891     if (fm_get_current_pos (lv) == -1)
892 twoaday 77 return WPTERR_GENERAL;
893 werner 36 rc = fm_state_new (&ctx);
894     if (rc)
895     BUG (0);
896     ctx->dlg = dlg;
897    
898 twoaday 328 // TODO: for file operations the progress dialog will be
899 werner 36 // reloaded somewhere and thus a 'dummy' dialog remains
900    
901     /* we use it here to make sure that pfx_cleanup will not use
902     any weird values. */
903     memset (&pfx, 0, sizeof (pfx));
904     ctx->prog_cb = NULL;
905     if (cmd != FM_VERIFY && cmd != FM_SIGN /*&& reg_prefs.fm.progress > 0*/) {
906     pfx.hwnd = dlg;
907     /*gpgme_set_progress_cb (ctx->ctx, progress_callback, &pfx);*/
908     /*ctx->prog_cb = &pfx;*/
909     }
910    
911     /* Commands we need before we can perform the main command */
912     switch (fm_cmd) {
913 twoaday 77 case FM_ENCRYPT_ZIP:
914 werner 36 case FM_ENCRYPT:
915     case FM_SIGNENCRYPT:
916     if (fm_cmd == FM_SIGNENCRYPT)
917     ctx->req_signer = 1;
918 twoaday 105 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILE_ENCRYPT,
919     ctx->dlg, file_encrypt_dlg_proc, (LPARAM)ctx);
920 werner 36 if (ctx->cancel == 1) {
921 twoaday 105 rc = WPTERR_GENERAL;
922 werner 36 goto leave;
923     }
924     break;
925    
926     case FM_SIGN:
927     DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_FILE_SIGN, dlg,
928     file_sign_dlg_proc, (LPARAM) ctx);
929     if (ctx->cancel == 1 || fm_clearsign_8bit (lv, ctx)) {
930     rc = WPTERR_GENERAL;
931     goto leave;
932     }
933     break;
934     }
935    
936 twoaday 328 for (i = 0, n = 0; i < listview_count_items (lv, 0); i++) {
937 twoaday 270 if (!listview_get_item_state (lv, i))
938 werner 36 continue;
939 twoaday 270 listview_get_item_text (lv, i, FM_COL_STAT, status, DIM (status) -1);
940 twoaday 271 if (!strcmp (status, "ENCRYPTED") && fm_cmd == FM_DECRYPT)
941 werner 36 n++;
942 twoaday 271 if (!strcmp (status, "UNKNOWN") && fm_cmd == FM_SIGN)
943 werner 36 n++;
944     }
945    
946     if (n > 1 && fm_cmd != FM_SYMENC)
947     ctx->cache_cb = 1;
948    
949 twoaday 77 for (i = 0; i < listview_count_items (lv, 0); i++) {
950 twoaday 177 if (!listview_get_item_state (lv, i))
951 werner 36 continue;
952 twoaday 270 listview_get_item_text (lv, i, FM_COL_NAME, fname, DIM (fname) - 1);
953 twoaday 271 if (file_exist_check (fname) && !is_directory (fname)) {
954 twoaday 119 log_box (_("File Manager"), MB_ERR,
955     _("\"%s\" does not exist"), fname);
956 werner 36 continue;
957     }
958 twoaday 119 if (is_directory (fname))
959 werner 36 fm_cmd = FM_ENCRYPT_DIR;
960 twoaday 119 if (!fm_check_file_type (lv, i, fm_cmd))
961 werner 36 continue;
962 twoaday 119 sig_detached = fm_check_detached_sig (lv, i);
963 twoaday 77 switch (fm_cmd) {
964 twoaday 328 case FM_LIST: fm_list( fname, dlg ); break;
965 werner 36 case FM_ENCRYPT: rc = fm_encrypt( ctx, fname, 0 ); break;
966     case FM_SIGNENCRYPT: rc = fm_encrypt( ctx, fname, 1 ); break;
967     case FM_DECRYPT: rc = fm_decrypt( ctx, fname ); break;
968     case FM_SIGN: rc = fm_sign( ctx, fname ); break;
969 twoaday 177 case FM_SYMENC: rc = fm_sym_encrypt (ctx, fname); break;
970 werner 36 case FM_VERIFY: rc = fm_verify (ctx, sig_detached, fname);break;
971     case FM_IMPORT:
972     free_if_alloc (ctx->opaque);
973     ctx->opaque = m_strdup (fname);
974 twoaday 177 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
975     file_import_dlg_proc, (LPARAM)ctx);
976 werner 36 if (ctx->cancel == 1)
977     continue;
978     rc = fm_import (ctx, fname);
979     break;
980     }
981 twoaday 177 if (ctx->cancel == 1) {
982     ctx->cancel = 0;
983     continue;
984     }
985 twoaday 88 fm_set_status (lv, i, fm_cmd, ctx->sigmode, !rc, ctx->output);
986 werner 36 free_if_alloc (ctx->output);
987     progress_cleanup (&pfx);
988     }
989 twoaday 77
990 werner 36 if (ctx->cache_cb) {
991     release_gpg_passphrase_cb (&ctx->pass_cb);
992     ctx->cache_cb = 0; /* make sure it's only used for this session! */
993     }
994    
995     leave:
996     if (!rc)
997     fm_state_release (ctx);
998     progress_cleanup (&pfx);
999     return rc;
1000 twoaday 270 }
1001 werner 36
1002    
1003     /* Dump out the given PGP packets from file @name in a dialog. */
1004 twoaday 328 void
1005 werner 36 fm_list (const char *name, HWND dlg)
1006     {
1007 twoaday 328 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_FILE_STAT, dlg,
1008 werner 36 file_stat_dlg_proc, (LPARAM)name, _("File Status"),
1009 twoaday 328 IDS_WINPT_FILE_STAT);
1010 werner 36 }
1011    
1012    
1013     static int
1014 twoaday 328 ask_filename (fm_state_t c, const char *msg, const char *oldfile, char **dst)
1015 werner 36 {
1016 twoaday 226 const char *s;
1017 werner 36
1018 twoaday 328 s = get_filesave_dlg (c->dlg, msg, NULL, oldfile);
1019 werner 36 if (!s)
1020     return WPTERR_GENERAL;
1021    
1022     if (dst != NULL)
1023     free_if_alloc (*dst);
1024     free_if_alloc (c->output);
1025     c->output = m_strdup (s);
1026 twoaday 328 if (dst != NULL)
1027 werner 36 *dst = fm_quote_file (s);
1028     return 0;
1029     }
1030    
1031    
1032     int
1033     fm_encrypt (fm_state_t c, const char *name, int sign)
1034     {
1035     gpgme_error_t err;
1036     gpgme_key_t key = NULL;
1037     gpgme_ctx_t ctx = c->ctx;
1038     file_data_t in=NULL, out=NULL;
1039     char *keyid = NULL, ext[5];
1040     int rc = 0;
1041    
1042     c->output = new char[strlen (name) + 5 + 1];
1043     if (!c->output)
1044     BUG (0);
1045     strcpy (ext, file_get_extension (ctx, c->sigmode));
1046     strcpy (c->output, name);
1047 twoaday 105 strcat (c->output, ext);
1048 werner 36
1049     if (!overwrite_file (c->output)) {
1050 twoaday 328 rc = ask_filename (c, _("Enter Filename for Encrypted File"), c->output, NULL);
1051 werner 36 if (rc)
1052     goto leave;
1053     }
1054    
1055 twoaday 105 err = gpg_file_data_new (name, F_DATA_READ, &in);
1056 werner 36 if (err)
1057     goto leave;
1058 twoaday 105 remove_crit_file_attrs (c->output, 0);
1059     err = gpg_file_data_new (c->output, F_DATA_WRITE, &out);
1060 werner 36 if (err)
1061     goto leave;
1062    
1063     /*
1064 twoaday 270 int no_compr = 0;
1065 werner 36 if (c->prog_cb) {
1066     c->prog_cb->what = name;
1067     gpg_file_data_set_cb (in, c->prog_cb);
1068     }
1069     */
1070    
1071 twoaday 328 // TODO: disable compression for multi-media files.
1072    
1073 werner 36 if (sign) {
1074     if (gpgme_signers_enum (ctx, 0) == NULL) {
1075     keyid = get_gnupg_default_key ();
1076     if (!keyid) {
1077     msg_box (c->dlg, _("Could not get default secret key."),
1078     _("Signing"), MB_ERR);
1079     rc = WPTERR_GENERAL;
1080     goto leave;
1081     }
1082     if (get_seckey (keyid, &key))
1083     BUG (0);
1084     gpgme_signers_add (ctx, key);
1085     }
1086     else {
1087 twoaday 77 gpgme_key_t sigkey = gpgme_signers_enum (ctx, 0);
1088     if (sigkey && sigkey->subkeys) {
1089     keyid = m_strdup (sigkey->subkeys->keyid);
1090 werner 36 }
1091     }
1092     if (!c->init_cb || !c->cache_cb) {
1093     set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_SIGN,
1094     c->dlg, _("Signing"));
1095     c->init_cb = 1;
1096     }
1097     op_begin ();
1098     err = gpgme_op_encrypt_sign (ctx, c->recp, GPGME_ENCRYPT_ALWAYS_TRUST,
1099     in->dat, out->dat);
1100     op_end ();
1101     if (!c->cache_cb)
1102     release_gpg_passphrase_cb (&c->pass_cb);
1103     if (c->pass_cb.cancel) {
1104     rc = WPTERR_GENERAL;
1105     goto leave;
1106     }
1107     if (err) {
1108     msg_box (c->dlg, gpgme_strerror (err), _("Sign"), MB_ERR);
1109     if (gpgme_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
1110     agent_del_cache (keyid);
1111     rc = WPTERR_GENERAL;
1112     goto leave;
1113     }
1114     }
1115     else {
1116     op_begin ();
1117     err = gpgme_op_encrypt (ctx, c->recp, GPGME_ENCRYPT_ALWAYS_TRUST,
1118     in->dat, out->dat);
1119     op_end ();
1120     if (err) {
1121     msg_box (c->dlg, gpgme_strerror (err), _("Encrypt"), MB_ERR);
1122     rc = WPTERR_GENERAL;
1123     goto leave;
1124     }
1125     }
1126    
1127     leave:
1128     if (in)
1129     gpg_file_data_release (in);
1130     if (out)
1131     gpg_file_data_release (out);
1132 twoaday 77 free_if_alloc (keyid);
1133 werner 36 return rc;
1134     }
1135    
1136    
1137     int
1138     fm_sym_encrypt (fm_state_t c, const char * name)
1139     {
1140     gpgme_ctx_t ctx = c->ctx;
1141     gpgme_error_t err;
1142     file_data_t in=NULL, out=NULL;
1143     int rc = 0, cancel = 0;
1144 twoaday 226 char ext[5], *pass;
1145 werner 36
1146 twoaday 226 pass = request_passphrase2 (_("Symmetric Encryption"), 0, &cancel);
1147 twoaday 177 if (cancel) {
1148     c->cancel = 1;
1149 werner 36 return 0;
1150 twoaday 177 }
1151 werner 36
1152 twoaday 226 /* XXX: a convenient feature could be to select the preferred
1153     symmetric algorithm. */
1154 werner 36 c->output = new char[strlen (name) + 5 + 1];
1155     if (!c->output)
1156     BUG (0);
1157     strcpy (ext, file_get_extension (ctx, c->sigmode));
1158     strcpy (c->output, name);
1159     strcat (c->output, ext);
1160    
1161     if (overwrite_file (c->output) == 0) {
1162     rc = WPTERR_GENERAL;
1163     goto leave;
1164     }
1165    
1166 twoaday 226 gpgme_set_passphrase_cb (ctx, sym_passphrase_cb, pass);
1167 werner 36 err = gpg_file_data_new (name, 1, &in);
1168     if (err)
1169     goto leave;
1170     err = gpg_file_data_new (c->output, 0, &out);
1171     if (err)
1172     goto leave;
1173    
1174     op_begin ();
1175     err = gpgme_op_encrypt (ctx, NULL, GPGME_ENCRYPT_ALWAYS_TRUST,
1176     in->dat, out->dat);
1177     op_end ();
1178     if (err) {
1179     msg_box (c->dlg, gpgme_strerror (err), _("Symmetric"), MB_ERR);
1180     rc = WPTERR_GENERAL;
1181     goto leave;
1182     }
1183     if (file_exist_check (c->output)) {
1184     msg_box (c->dlg, _("Encryption failed."), _("Symmetric"), MB_ERR);
1185     rc = WPTERR_GENERAL;
1186     }
1187    
1188     leave:
1189     if (in)
1190     gpg_file_data_release (in);
1191     if (out)
1192     gpg_file_data_release (out);
1193     sfree_if_alloc (pass);
1194     return rc;
1195 twoaday 105 }
1196 werner 36
1197    
1198     /* Check the recipients if we have at least one secret key. */
1199     bool
1200 twoaday 217 is_seckey_available (gpgme_recipient_t rset)
1201 werner 36 {
1202     gpgme_recipient_t r;
1203 twoaday 217 winpt_key_s key;
1204 werner 36
1205 twoaday 105 for (r=rset; r; r = r->next) {
1206 werner 36 if (gpgme_err_code (r->status) == GPG_ERR_NO_SECKEY)
1207     continue;
1208     else {
1209 twoaday 217 memset (&key, 0, sizeof (key));
1210 werner 36 /* extra check to make sure the key is available right now. */
1211 twoaday 217 if (!winpt_get_seckey (r->keyid, &key)) {
1212     winpt_release_pubkey (&key);
1213 werner 36 return true;
1214 twoaday 217 }
1215     winpt_release_pubkey (&key);
1216 werner 36 }
1217     }
1218     return false;
1219     }
1220    
1221    
1222 twoaday 195 /* If the decrypt result contains the original file name,
1223     we use it instead of the artificial "output - .gpg" string. */
1224     static int
1225 twoaday 197 restore_original_name (const char *output, const char *file_name)
1226 twoaday 195 {
1227     char *dir;
1228     char *orig;
1229     int rc = 0;
1230    
1231     dir = strrchr (output, '\\');
1232     if (!dir)
1233 twoaday 197 orig = strdup (file_name);
1234 twoaday 195 else {
1235 twoaday 197 orig = (char*)calloc (1, strlen (file_name)+ 1 +
1236 twoaday 195 strlen (output)+1);
1237     if (!orig)
1238     BUG (0);
1239     memcpy (orig, output, (dir-output)+1);
1240 twoaday 197 strcat (orig, file_name);
1241 twoaday 195 }
1242 twoaday 214 /* XXX: we need to find out if the string needs to be utf8 decoded. */
1243 twoaday 195 if (overwrite_file (orig)) {
1244     DeleteFile (orig);
1245     if (!MoveFile (output, orig))
1246     rc = -1;
1247     }
1248     safe_free (orig);
1249     return rc;
1250     }
1251    
1252    
1253 werner 36 /* Decrypt the file @name. */
1254     int
1255     fm_decrypt (fm_state_t c, const char *name)
1256     {
1257     gpgme_error_t err;
1258     gpgme_ctx_t ctx = c->ctx;
1259     gpgme_decrypt_result_t res;
1260     gpgme_verify_result_t sigres;
1261 twoaday 195 file_data_t in = NULL, out = NULL;
1262 werner 36 int rc = 0;
1263    
1264     if (!c->init_cb || !c->cache_cb) {
1265 twoaday 119 set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_DECRYPT,
1266 werner 36 c->dlg, _("Decryption"));
1267 twoaday 119 c->init_cb = 1;
1268     }
1269 werner 36
1270     c->output = m_strdup (name);
1271     if (is_openpgp_ext (c->output))
1272     c->output[strlen (c->output)-4] = '\0';
1273     else {
1274 twoaday 41 const char *s;
1275     s = get_filesave_dlg (c->dlg, _("Choose Filename for Output"),
1276     NULL, NULL);
1277 werner 36 if (s) {
1278     free_if_alloc (c->output);
1279     c->output = m_strdup (s);
1280     }
1281     }
1282    
1283     if (overwrite_file (c->output) == 0) {
1284 twoaday 328 rc = ask_filename (c, _("Enter Filename for Plaintext File"), c->output, NULL);
1285 werner 36 if (rc)
1286     goto leave;
1287 twoaday 105 }
1288 werner 36
1289 twoaday 214 /* we fetch all recipients here to make sure they list is complete. */
1290     release_gpg_recipients (&c->pass_cb.recipients);
1291     gpg_get_recipients (name, &c->pass_cb.recipients);
1292    
1293 twoaday 105 err = gpg_file_data_new (name, F_DATA_READ, &in);
1294 werner 36 if (err)
1295     goto leave;
1296 twoaday 105 remove_crit_file_attrs (c->output, 0);
1297     err = gpg_file_data_new (c->output, F_DATA_WRITE, &out);
1298 werner 36 if (err)
1299     goto leave;
1300 twoaday 214
1301 werner 36 op_begin ();
1302     err = gpgme_op_decrypt_verify (ctx, in->dat, out->dat);
1303     op_end ();
1304     if (!c->cache_cb)
1305     release_gpg_passphrase_cb (&c->pass_cb);
1306     if (c->pass_cb.cancel) {
1307     rc = WPTERR_GENERAL;
1308     goto leave;
1309     }
1310    
1311     res = gpgme_op_decrypt_result (ctx);
1312 twoaday 217 if (res && res->recipients && !is_seckey_available (res->recipients)) {
1313 twoaday 256 const char *keyid = get_keyid_from_fpr (res->recipients->keyid);
1314     char *p = get_key_userid (keyid);
1315 werner 36 gpgme_pubkey_algo_t pkalgo = res->recipients->pubkey_algo;
1316    
1317 twoaday 195 log_box (_("Decryption"), MB_ERR,
1318 twoaday 256 _("Encrypted with %s key, ID 0x%s.%s\n"
1319 werner 36 "Decryption failed: secret key not available."),
1320 twoaday 256 get_key_pubalgo (pkalgo), keyid, p);
1321 werner 36 rc = WPTERR_GENERAL;
1322     free_if_alloc (p);
1323     goto leave;
1324     }
1325     else if (err) {
1326     msg_box (c->dlg, gpgme_strerror (err), _("Decrypt"), MB_ERR);
1327     rc = WPTERR_GENERAL;
1328     goto leave;
1329     }
1330     if (file_exist_check (c->output)) {
1331 twoaday 105 log_box ("Decrypt", MB_ERR,
1332     _("Decryption failed.\n%s: does not exist."), c->output);
1333 werner 36 rc = WPTERR_GENERAL;
1334 twoaday 195 goto leave;
1335 werner 36 }
1336 twoaday 195 else if (res && res->file_name) {
1337 twoaday 214 char *file;
1338 twoaday 217 int id = IDNO;
1339 twoaday 214
1340     file = strrchr (c->output, '\\');
1341     if (!file)
1342     file = c->output;
1343     else
1344     file++;
1345 twoaday 217 if (strcmp (res->file_name, file))
1346     id = log_box (_("Decrypt"), MB_QUEST_ASK,
1347     _("The original file name is '%s'.\n\n"
1348     "Do you want to use this instead of '%s'?"),
1349 twoaday 214 res->file_name, file);
1350 twoaday 195 if (id == IDYES) {
1351     /* before we can move the file, it needs to be closed first. */
1352     gpg_file_data_release (out);
1353     out = NULL;
1354     restore_original_name (c->output, res->file_name);
1355     }
1356     }
1357 werner 36 sigres = gpgme_op_verify_result (ctx);
1358     if (sigres && sigres->signatures)
1359 twoaday 220 verify_show_signature_state (sigres->signatures);
1360 werner 36
1361     leave:
1362     if (in)
1363     gpg_file_data_release (in);
1364     if (out)
1365     gpg_file_data_release (out);
1366 twoaday 119
1367 werner 36 return rc;
1368     }
1369    
1370    
1371     int
1372     fm_sign (fm_state_t c, const char * name)
1373 twoaday 105 {
1374 werner 36 gpgme_ctx_t ctx = c->ctx;
1375     gpgme_error_t err;
1376     file_data_t in=NULL, out=NULL;
1377     char ext[5];
1378 twoaday 105 int rc = 0;
1379 werner 36
1380     if (!c->init_cb || !c->cache_cb) {
1381 twoaday 119 set_gpg_passphrase_cb (&c->pass_cb, c->ctx,
1382     GPG_CMD_SIGN, c->dlg, _("Signing"));
1383 werner 36 c->init_cb = 1;
1384     }
1385    
1386     free_if_alloc (c->output);
1387     c->output = new char[strlen (name) + 5 + 1];
1388 twoaday 105 if (!c->output)
1389     BUG (NULL);
1390 werner 36 strcpy (ext, file_get_extension (ctx, c->sigmode));
1391     strcpy (c->output, name);
1392     strcat (c->output, ext);
1393    
1394     if (!overwrite_file (c->output)) {
1395 twoaday 328 rc = ask_filename (c, _("Enter Filename for Signed File"), c->output, NULL);
1396 werner 36 if (rc)
1397     goto leave;
1398     }
1399 twoaday 105
1400     err = gpg_file_data_new (name, F_DATA_READ, &in);
1401 werner 36 if (err)
1402     goto leave;
1403 twoaday 105 remove_crit_file_attrs (c->output, 0);
1404     err = gpg_file_data_new (c->output, F_DATA_WRITE, &out);
1405 werner 36 if (err)
1406     goto leave;
1407    
1408     op_begin ();
1409     err = gpgme_op_sign (ctx, in->dat, out->dat, c->sigmode);
1410     op_end ();
1411 twoaday 105 if (!c->cache_cb)
1412 werner 36 release_gpg_passphrase_cb (&c->pass_cb);
1413 twoaday 105 if (c->pass_cb.cancel) {
1414 werner 36 rc = WPTERR_GENERAL;
1415     goto leave;
1416     }
1417 twoaday 105 if (err) {
1418     msg_box (c->dlg, gpgme_strerror (err), _("Sign"), MB_ERR);
1419 werner 36 rc = WPTERR_GENERAL;
1420     goto leave;
1421     }
1422    
1423     leave:
1424     if (in)
1425     gpg_file_data_release (in);
1426     if (out)
1427     gpg_file_data_release (out);
1428     return rc;
1429     }
1430    
1431    
1432 twoaday 105 static void
1433 werner 36 fm_add_sig_stat (file_sig_ctx_t log)
1434     {
1435 twoaday 208 struct winpt_key_s key;
1436 werner 36 const char *kid;
1437    
1438 twoaday 208 memset (&key, 0, sizeof (key));
1439     kid = get_keyid_from_fpr (log->sig->fpr);
1440     log->use_uid = 0;
1441     if (!winpt_get_pubkey (kid, &key)) {
1442     log->user_id = key.ext->uids->uid;
1443 werner 36 log->use_uid = 1;
1444     }
1445     file_verify_add_state (log);
1446 twoaday 270 winpt_release_pubkey (&key);
1447 werner 36 }
1448    
1449    
1450 twoaday 105 /* Verify a detached signature from the clipboard. */
1451 werner 36 static int
1452 twoaday 105 verify_pasted (listview_ctrl_t lv, fm_state_t ctx,
1453     const char *dat, int pos, HWND dlg)
1454 werner 36 {
1455 twoaday 105 FILE *fp;
1456 werner 36 char stat[32];
1457 twoaday 328 char file[MAX_PATH+1], *fname = NULL;
1458 twoaday 105 int del_end = 0;
1459 werner 36
1460 twoaday 262 listview_get_item_text (lv, pos, FM_COL_STAT, stat, DIM (stat)-1);
1461     listview_get_item_text (lv, pos, FM_COL_NAME, file, DIM (file)-1);
1462 werner 36 if (strcmp (stat, "UNKNOWN"))
1463     return 0;
1464     fname = make_filename (NULL, file, "asc");
1465     if (file_exist_check (fname) != 0) {
1466     fp = fopen (fname, "wb");
1467     if (fp == NULL) {
1468 twoaday 226 log_box (_("File Manager"), MB_ERR, "Could not create '%s'", fname);
1469 werner 36 free_if_alloc (fname);
1470 twoaday 105 return WPTERR_GENERAL;
1471     }
1472 werner 36 fwrite (dat, 1, strlen (dat), fp);
1473     fclose (fp);
1474     del_end = 1;
1475     }
1476     fm_verify (ctx, 1, fname);
1477     if (del_end)
1478 twoaday 226 DeleteFile (fname);
1479 werner 36 free_if_alloc (fname);
1480     return 0;
1481     }
1482    
1483    
1484 twoaday 105 /* Figure out if the clipboard contains a detached signature. */
1485 werner 36 int
1486     fm_verify_pasted_detsig (listview_ctrl_t lv, HWND dlg)
1487     {
1488     fm_state_t ctx = NULL;
1489     char * dat=NULL;
1490     int i, fnd = 0;
1491    
1492     dat = get_clip_text (NULL);
1493     if (!dat || !strstr (dat, "BEGIN PGP SIGNATURE")) {
1494     msg_box (dlg, _("Could not find detached signature in the clipboard."),
1495     _("File Manager"), MB_ERR);
1496     free_if_alloc (dat);
1497     return WPTERR_GENERAL;
1498     }
1499     /* XXX find a way to filter out bad signatures or just ignore all in
1500     this case */
1501     fm_state_new (&ctx);
1502 twoaday 105 i = listview_get_curr_pos (lv);
1503 twoaday 260 if (i == -1) {
1504 werner 36 verify_pasted (lv, ctx, dat, i, dlg);
1505     fnd = 1;
1506     }
1507     else {
1508     for (i=0; i < listview_count_items (lv, 0); i++) {
1509     verify_pasted (lv, ctx, dat, i, dlg);
1510     fnd = 1;
1511     }
1512     }
1513     if (!fnd)
1514     msg_box (dlg, _("No files to check."), _("File Manager"), MB_INFO);
1515     free_if_alloc (dat);
1516     fm_state_release (ctx);
1517     return 0;
1518     }
1519    
1520    
1521     /* Extract automatically the output file name from @name.
1522     If @detached is 1, a detached sig is assumed. */
1523     static int
1524     get_output_file (fm_state_t c, const char *name, int detached)
1525     {
1526     const char *file = NULL;
1527     const char *title;
1528     char fname[384];
1529    
1530     if (detached)
1531     title = _("Select Data File");
1532     else
1533     title = _("Selected Output File");
1534    
1535 twoaday 226 if (is_openpgp_ext (name)) {
1536 twoaday 262 _snprintf (fname, DIM (fname) - 1, "%s", name);
1537 werner 36 fname[strlen (fname) - 4] = '\0';
1538     if (file_exist_check (fname) == 0 && detached)
1539     file = fname;
1540     else if (!detached) {
1541     /* If the signature is clear or normal, make sure we do not
1542     overwrite the original file if it exists. */
1543     if (file_exist_check (fname) == 0 && !overwrite_file (fname)) {
1544     file = get_filesave_dlg (c->dlg, title, NULL, NULL);
1545     if (!file)
1546     return WPTERR_GENERAL;
1547     }
1548     else
1549     file = fname;
1550     }
1551     }
1552     if (!file)
1553     file = get_fileopen_dlg (c->dlg, title, NULL, NULL);
1554     if (file) {
1555     free_if_alloc (c->output);
1556     c->output = m_strdup (file);
1557     }
1558     else {
1559     msg_box (c->dlg, _("Invalid file name. Exit"), _("Verify"), MB_ERR);
1560     return WPTERR_GENERAL;
1561     }
1562     if (detached)
1563     c->sigmode = GPGME_SIG_MODE_DETACH;
1564     else {
1565 twoaday 197 if (stristr (name, ".asc"))
1566 werner 36 c->sigmode = GPGME_SIG_MODE_CLEAR;
1567     else
1568     c->sigmode = GPGME_SIG_MODE_NORMAL;
1569     }
1570     return 0;
1571     }
1572    
1573    
1574 twoaday 271 /* Handy function to kick of the gpg verify process. */
1575     static gpgme_error_t
1576     fm_gpg_verify (gpgme_sig_mode_t sigmode, gpgme_ctx_t ctx,
1577     file_data_t in, file_data_t out)
1578     {
1579     gpgme_error_t err;
1580    
1581     op_begin ();
1582     if (sigmode == GPGME_SIG_MODE_DETACH)
1583     err = gpgme_op_verify (ctx, in->dat, out->dat, NULL);
1584     else
1585     err = gpgme_op_verify (ctx, in->dat, in->dat, out->dat);
1586     op_end ();
1587     return err;
1588     }
1589    
1590    
1591 werner 36 /* Verify the signature from the file @name. If @detached 1,
1592     it is assumed that a detached signature should be checked. */
1593     int
1594     fm_verify (fm_state_t c, int detached, const char *name)
1595     {
1596     gpgme_error_t err;
1597     gpgme_signature_t s;
1598     gpgme_verify_result_t res;
1599     struct file_sig_ctx_s log;
1600     file_data_t in=NULL, out=NULL;
1601     int rc = 0;
1602    
1603 twoaday 197 if (stristr (name, ".sig"))
1604 werner 36 detached = 1;
1605    
1606     if (get_output_file (c, name, detached))
1607     return WPTERR_GENERAL;
1608    
1609     file_verify_create_dlg ();
1610    
1611 twoaday 271 memset (&log, 0, sizeof (log));
1612     log.file = m_strdup (name);
1613    
1614 twoaday 105 err = gpg_file_data_new (name, F_DATA_READ, &in);
1615 werner 36 if (err)
1616     goto leave;
1617 twoaday 105 err = gpg_file_data_new (c->output,
1618     detached? F_DATA_READ : F_DATA_WRITE, &out);
1619 werner 36 if (err)
1620     goto leave;
1621    
1622 twoaday 271 err = fm_gpg_verify (c->sigmode, c->ctx, in, out);
1623 werner 36 if (err) {
1624     msg_box (c->dlg, gpgme_strerror (err), _("Verify"), MB_ERR);
1625     rc = WPTERR_GENERAL;
1626     goto leave;
1627     }
1628    
1629 twoaday 271 res = gpgme_op_verify_result (c->ctx);
1630 twoaday 270 if (!res)
1631     goto leave;
1632 twoaday 271 if (res->signatures != NULL &&
1633     gpgme_err_code (res->signatures->status) == GPG_ERR_NO_PUBKEY) {
1634     /* We need to call gpg again to get the actual sig state
1635     and the data files must be rewinded also. */
1636     if (fetch_key_from_keyserver (c->dlg, res->signatures)) {
1637     rc = WPTERR_GENERAL;
1638     goto leave;
1639     }
1640     gpg_file_data_rewind (in);
1641     gpg_file_data_rewind (out);
1642     err = fm_gpg_verify (c->sigmode, c->ctx, in, out);
1643     if (err) {
1644     msg_box (c->dlg, gpgme_strerror (err), _("Verify"), MB_ERR);
1645     rc = WPTERR_GENERAL;
1646     goto leave;
1647     }
1648     /* Refresh the pointer because a new GPG instance has been
1649     created for the new verify operation. */
1650     res = gpgme_op_verify_result (c->ctx);
1651     }
1652    
1653 werner 36 for (s=res->signatures; s; s=s->next) {
1654     log.sig = s;
1655     fm_add_sig_stat (&log);
1656     }
1657     if (!c->output)
1658     c->output = m_strdup (name); /* for later use */
1659    
1660     leave:
1661     if (in)
1662     gpg_file_data_release (in);
1663     if (out)
1664     gpg_file_data_release (out);
1665 twoaday 105 free_if_alloc (log.file);
1666 werner 36 return rc;
1667     }
1668    
1669    
1670 twoaday 105 /* Import the keys from the file @name.
1671     Return value: 0 on success. */
1672 werner 36 int
1673     fm_import (fm_state_t c, const char *name)
1674     {
1675     gpgme_ctx_t ctx = c->ctx;
1676     gpgme_error_t err;
1677     gpgme_import_result_t res;
1678     file_data_t keydata = NULL;
1679     int rc = 0;
1680    
1681     free_if_alloc (c->output);
1682     c->output = m_strdup (name);
1683    
1684 twoaday 105 err = gpg_file_data_new (name, F_DATA_READ, &keydata);
1685 werner 36 if (err)
1686     goto leave;
1687    
1688     op_begin ();
1689     err = gpgme_op_import (ctx, keydata->dat);
1690     op_end ();
1691     if (err) {
1692     msg_box (c->dlg, gpgme_strerror (err), _("Import"), MB_ERR);
1693     rc = WPTERR_GENERAL;
1694     goto leave;
1695     }
1696    
1697     res = gpgme_op_import_result (ctx);
1698     print_import_status (res);
1699     if (res->no_user_id > 0) {
1700 twoaday 105 msg_box (c->dlg, _("Key without a self signature was dectected!\n"
1701 werner 36 "(This key is NOT usable for encryption, etc)\n"
1702     "\n"
1703     "Cannot import these key(s)!"), _("Import"), MB_INFO);
1704     }
1705    
1706     leave:
1707     if (keydata)
1708     gpg_file_data_release (keydata);
1709     return rc;
1710 twoaday 105 }
1711 werner 36
1712    
1713     /* Parse the command line and process the given file. */
1714     int
1715     fm_parse_command_line (char *cmdl)
1716     {
1717     fm_state_t ctx;
1718     const char *s;
1719     char *p, *fn = NULL;
1720     int count = 0, detached = 0;
1721     int type;
1722    
1723     if (!cmdl || !*cmdl)
1724     return 0;
1725    
1726     fm_state_new (&ctx);
1727     ctx->dlg = GetActiveWindow ();
1728     ctx->cache_cb = 1;
1729    
1730     p = cmdl;
1731     if (p && *p > 32 && !stristr (p, "winpt.exe")
1732     && !strstr (p, "--" )) {
1733     count++;
1734     if (*p == '"') { /* need to remove quotes */
1735     fn = new char[strlen (p)];
1736     if (!fn)
1737     BUG (NULL);
1738     memcpy (fn, p+1, strlen (p) - 2);
1739     fn[strlen (p) -2] = '\0';
1740     }
1741     else
1742     fn = m_strdup (p);
1743     s = fm_get_file_type (fn, &type);
1744     if (!s || !strcmp (s, "UNKNOWN"))
1745     s = gnupg_check_file_ext (fn, &type);
1746     if (type == PGP_NONE) {
1747     log_box (_("File Manager"), MB_ERR,
1748     _("%s: no valid OpenPGP data found."), p);
1749     free_if_alloc (fn);
1750     return count;
1751     }
1752     switch (type) {
1753     case PGP_MESSAGE:
1754     fm_decrypt (ctx, fn);
1755     break;
1756    
1757     case PGP_PUBKEY:
1758     case PGP_SECKEY:
1759     fm_import (ctx, fn);
1760     break;
1761    
1762     case PGP_SIG:
1763     case PGP_CLEARSIG:
1764     if (type == PGP_SIG)
1765     detached = 1;
1766     fm_verify (ctx, detached, fn);
1767     file_verify_wait ();
1768 twoaday 77 break;
1769 twoaday 88
1770 twoaday 77 default:
1771     break;
1772 werner 36 }
1773     }
1774    
1775     wipememory (&ctx->pass_cb, sizeof (ctx->pass_cb));
1776     free_if_alloc (fn);
1777     fm_state_release (ctx);
1778     return count;
1779     }
1780    
1781    
1782 twoaday 105 /* Extract the last folder name from @name. */
1783 werner 36 const char*
1784     default_dirname (const char *name)
1785     {
1786 twoaday 105 char *p = strrchr (name, '\\');
1787     if (!p)
1788 werner 36 return NULL;
1789     return p+1;
1790 twoaday 105 }
1791 werner 36
1792 twoaday 328 #if 0
1793 twoaday 77 /* Store all selected files from @lv in a zip archive
1794     and encrypt the zip archive then.
1795     Return value: 0 on success. */
1796 werner 36 int
1797 twoaday 77 fm_encrypt_into_zip (fm_state_t ctx, listview_ctrl_t lv)
1798     {
1799     PK_FILE_LIST list=NULL;
1800 twoaday 197 const char *outfile, *ext;
1801 twoaday 77 char *out_enc;
1802 twoaday 197 int nitems;
1803 twoaday 77 int i, idx = -1;
1804     int rc;
1805    
1806 twoaday 197 nitems = listview_count_items (lv, 0);
1807 twoaday 77 if (!nitems) {
1808     msg_box (NULL, _("Encrypting into a ZIP archive makes sense with multiple files"),
1809     _("File Manager"), MB_ERR);
1810 twoaday 105 return WPTERR_GENERAL;
1811 twoaday 77 }
1812    
1813 twoaday 105 outfile = get_filesave_dlg (ctx->dlg, _("Choose File Name for Output"),
1814     NULL, "Encrypted_Files.zip");
1815 twoaday 77 if (!outfile)
1816 twoaday 105 return WPTERR_GENERAL;
1817 twoaday 77
1818     for (i=0; i < nitems; i++) {
1819 twoaday 256 char name[MAX_PATH+32];
1820    
1821 twoaday 77 if (!listview_get_item_state (lv, i))
1822     continue;
1823     if (idx == -1)
1824     idx = i;
1825 twoaday 262 listview_get_item_text (lv, i, 1, name, DIM (name)-1);
1826 twoaday 77 pk_list_add (&list, name);
1827     }
1828    
1829     pk_archiv_create (list, outfile);
1830     pk_list_free (list);
1831    
1832     rc = fm_encrypt (ctx, outfile, 0);
1833     DeleteFile (outfile);
1834     if (rc)
1835     return rc;
1836    
1837 twoaday 197 ext = file_get_extension (ctx->ctx, ctx->sigmode)+1;
1838     out_enc = make_filename (NULL, outfile, ext);
1839 twoaday 88 fm_set_status (lv, idx, FM_ENCRYPT, (gpgme_sig_mode_t)0, 1, out_enc);
1840 twoaday 77 free_if_alloc (out_enc);
1841    
1842 twoaday 256 for (i=nitems; i > -1; i--) {
1843 twoaday 77 if (i != idx && listview_get_item_state (lv, i))
1844     listview_del_item (lv, i);
1845     }
1846     return 0;
1847     }
1848    
1849     int
1850 twoaday 105 fm_encrypt_directory (fm_state_t c, const char *name)
1851 twoaday 256 {
1852 werner 36 WIN32_FIND_DATA findbuf;
1853     HANDLE hd;
1854 twoaday 256 PK_FILE_LIST list = NULL;
1855 twoaday 226 const char *s;
1856     char *patt = NULL, *p;
1857 werner 36 int rc = 0;
1858    
1859 twoaday 105 if (!is_directory (name))
1860 werner 36 return -1;
1861 twoaday 105 patt = new char[strlen (name) + 4];
1862     if (!patt)
1863     BUG (NULL);
1864     strcpy (patt, name);
1865     strcat (patt, "\\*");
1866     hd = FindFirstFile (patt, &findbuf);
1867     if (!hd) {
1868     free_if_alloc (patt);
1869     return WPTERR_GENERAL;
1870 werner 36 }
1871 twoaday 226 if (strcmp (findbuf.cFileName, ".") && strcmp (findbuf.cFileName, "..")) {
1872     p = make_filename (name, findbuf.cFileName, NULL);
1873     pk_list_add (&list, p);
1874     free_if_alloc (p);
1875 werner 36 }
1876 twoaday 262 /* XXX: support to scan sub directories also. */
1877 twoaday 256 while (FindNextFile (hd, &findbuf)) {
1878     if (strcmp (findbuf.cFileName, ".") && strcmp (findbuf.cFileName, "..")) {
1879     p = make_filename (name, findbuf.cFileName, NULL);
1880     pk_list_add (&list, p);
1881     free_if_alloc (p);
1882 werner 36 }
1883     }
1884 twoaday 105 s = get_filesave_dlg (c->dlg, _("Choose a Name for the Archive"),
1885     NULL, default_dirname (name));
1886 twoaday 256 if (!s) {
1887 twoaday 226 msg_box (c->dlg, _("Invalid archive name. Exit."),
1888     _("Encrypt Directory"), MB_ERR);
1889 werner 36 rc = -1;
1890     goto leave;
1891     }
1892    
1893 twoaday 226 rc = pk_archiv_create (list, s);
1894 twoaday 256 if (rc)
1895 twoaday 226 msg_box (c->dlg, _("Could not create zip archive."),
1896     _("Encrypt Directory"), MB_ERR);
1897 werner 36 else {
1898 twoaday 226 fm_encrypt (c, s, 0);
1899     DeleteFile (s);
1900 werner 36 }
1901     leave:
1902     FindClose (hd);
1903 twoaday 226 pk_list_free (list);
1904     free_if_alloc (patt);
1905 werner 36 return rc;
1906 twoaday 105 }
1907 twoaday 328 #endif
1908 werner 36
1909     static int CALLBACK
1910 twoaday 105 fm_cmp_cb (LPARAM first, LPARAM second, LPARAM sortby)
1911 werner 36 {
1912 twoaday 244 fm_model_t a, b;
1913     int cmpres = 0;
1914 werner 36
1915 twoaday 244 a = (fm_model_t)first;
1916     b = (fm_model_t)second;
1917     if (!a || !b)
1918     return 0;
1919    
1920 twoaday 197 switch ((int)sortby) {
1921 twoaday 244 case FM_COL_STAT:
1922     cmpres = stricmp (a->status, b->status);
1923 werner 36 break;
1924 twoaday 244
1925     case FM_COL_NAME:
1926     cmpres = stricmp (a->name, b->name);
1927 werner 36 break;
1928 twoaday 244
1929     case FM_COL_OP:
1930     if (a->op && b->op)
1931     cmpres = stricmp (a->op, b->op);
1932 werner 36 break;
1933     }
1934 twoaday 244 return cmpres;
1935 twoaday 105 }
1936 werner 36
1937 twoaday 244
1938 twoaday 105 /* Sort the list items from @lv with the mode given by @sortby. */
1939 werner 36 int
1940 twoaday 105 fm_sort (listview_ctrl_t lv, int sortby)
1941 werner 36 {
1942 twoaday 244 return ListView_SortItems (lv->ctrl, fm_cmp_cb, (LPARAM)sortby);
1943 twoaday 105 }
1944 werner 36
1945    
1946    
1947 twoaday 77 /* Send the selected file in @lv via MAPI to a mail recipient. */
1948 werner 36 int
1949     fm_send_file (listview_ctrl_t lv)
1950     {
1951 twoaday 262 char name[MAX_PATH+1];
1952 werner 36 int rc;
1953    
1954 twoaday 262 rc = listview_get_item_text (lv, -1, FM_COL_NAME, name, DIM (name)-1);
1955 twoaday 77 if (rc != -1)
1956 twoaday 256 mapi_send_ascfile (name);
1957 werner 36 return 0;
1958     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26