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

Legend:
Removed from v.33  
changed lines
  Added in v.94

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26