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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26