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

Diff of /trunk/Src/wptFileManager.cpp

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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26