/[winpt]/trunk/Src/wptFileManager.cpp
ViewVC logotype

Diff of /trunk/Src/wptFileManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26