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

Annotation of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 197 - (hide annotations)
Mon Apr 10 07:38:06 2006 UTC (18 years, 10 months ago) by twoaday
File size: 48779 byte(s)
2006-04-09  Timo Schulz  <ts@g10code.de>
 
        * wptGPGPrefsDlg.cpp (gpgprefs_dlg_proc): Only return true
        if the homedir value was changed.
        * wptGPG.cpp (default_key_from_cache): Only return secret key
        if public part is available.
        (set_gnupg_default_key): Fix NULL problem.
        * wptKeyEditDlgs.cpp (do_editkey_clean): Set update flag.
        * wptFileCBS.cpp (write_cb, read_cb): Better error handling.
        * wptFileManagerDlg.cpp (file_manager_dlg_proc): Handle
        'always-on-top' correctly.
        * wptKeylist.cpp (keylist_get_recipients): Allocate enough
        mem to hold all possible keys.
        (keylist_enum_keys): Likewise.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26