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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 234 - (hide annotations)
Tue Jun 27 10:16:41 2006 UTC (18 years, 8 months ago) by twoaday
File size: 48564 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26