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

Diff of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.32  
changed lines
  Added in v.195

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26