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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26