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

Legend:
Removed from v.32  
changed lines
  Added in v.177

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26