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

Legend:
Removed from v.34  
changed lines
  Added in v.167

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26