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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26