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

Legend:
Removed from v.28  
changed lines
  Added in v.220

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26