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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26