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

Legend:
Removed from v.2  
changed lines
  Added in v.217

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26