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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26