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

Legend:
Removed from v.25  
changed lines
  Added in v.172

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26