/[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 47 by werner, Mon Oct 31 14:04:59 2005 UTC revision 211 by twoaday, Sun May 7 12:36:48 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-2006 Timo Schulz
3   *      Copyright (C) 2005 g10 Code GmbH   *      Copyright (C) 2005 g10 Code GmbH
4   *   *
5   * This file is part of WinPT.   * This file is part of WinPT.
# Line 18  Line 18 
18   * along with WinPT; if not, write to the Free Software Foundation,   * along with WinPT; if not, write to the Free Software Foundation,
19   * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA   * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20   */   */
 /* TODO:  
  *    check_armor_type: we should check the whole file and not only the first line!  
  */  
21    
22  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
23  #include <config.h>  #include <config.h>
24  #endif  #endif
25    
26  #include <sys/types.h>  #include <sys/types.h>
 #include <sys/types.h>  
27  #include <windows.h>  #include <windows.h>
28  #include <commdlg.h>  #include <commdlg.h>
29  #include <io.h>  #include <io.h>
# Line 50  Line 46 
46  #include "wptUTF8.h"  #include "wptUTF8.h"
47  #include "wptRegistry.h"  #include "wptRegistry.h"
48  #include "wptImport.h"  #include "wptImport.h"
49    #include "wptCrypto.h"
50    #include "wptKeyManager.h"
51  #include "openpgp.h"  #include "openpgp.h"
52    
 #define op_begin()  SetCursor (LoadCursor (NULL, IDC_WAIT))  
 #define op_end()    SetCursor (LoadCursor (NULL, IDC_ARROW))  
53    
54  void progress_cleanup (progress_filter_s *pfx);  void progress_cleanup (progress_filter_s *pfx);
55  BOOL CALLBACK file_secdel_confirm_dlg_proc (HWND dlg, UINT msg,  BOOL CALLBACK file_secdel_confirm_dlg_proc (HWND dlg, UINT msg,
# Line 63  char* gpg_keylist_to_pattern (gpgme_key_ Line 58  char* gpg_keylist_to_pattern (gpgme_key_
58  gpgme_error_t sym_passphrase_cb (void *hook, const char *hint, const char *pass_inf,  gpgme_error_t sym_passphrase_cb (void *hook, const char *hint, const char *pass_inf,
59                                   int prev_was_bad, int fd);                                   int prev_was_bad, int fd);
60    
 /*-- wptFileVerifyDlg.cpp --*/  
 void file_verify_add_state (file_sig_ctx_t c);  
 void file_verify_use_event (void);  
 void file_verify_wait (void);  
61    
62  static const char * mm_files[] = {".mov", ".avi", ".mpg", ".mpeg",  /* Symbolic column IDs. */
63    enum {
64        FM_COL_STAT = 0,
65        FM_COL_NAME = 1,
66        FM_COL_OP   = 2
67    };
68    
69    static const char *mm_files[] = {".mov", ".avi", ".mpg", ".mpeg",
70                                    ".mp3", ".wav", ".mid", ".wma",                                    ".mp3", ".wav", ".mid", ".wma",
71                                    ".gif", ".jpg", ".png", ".jpeg", ".dib", 0};                                    ".gif", ".jpg", ".png", ".jpeg", ".dib", 0};
72    
# Line 114  overwrite_file (const char *fname) Line 112  overwrite_file (const char *fname)
112    
113  /* Removes 'critical' attributes from the file @fname.  /* Removes 'critical' attributes from the file @fname.
114     If @force is 1, the user is not asked for permission. */     If @force is 1, the user is not asked for permission. */
115  static void  void
116  remove_crit_file_attrs (const char *fname, int force)  remove_crit_file_attrs (const char *fname, int force)
117  {  {
118      u32 fattr;      DWORD fattr;
119      int id = 0;      int id = 0;
120    
121      if (file_exist_check (fname))      if (file_exist_check (fname))
# Line 227  fm_quote_file (const char * name) Line 225  fm_quote_file (const char * name)
225    
226  /* Check the armor type of the file @fname and return  /* Check the armor type of the file @fname and return
227     a string representation of it. */     a string representation of it. */
228  static const char *  static const char*
229  fm_check_armor_type (const char *fname, int *r_type)  fm_check_armor_type (const char *fname, int *r_type)
230  {  {
231      FILE * fp;      FILE *fp;
232      char header[768], * p;      char header[768], *p;
233            
234      if (r_type)      if (r_type)
235          *r_type = PGP_NONE;          *r_type = PGP_NONE;
# Line 274  leave: Line 272  leave:
272    
273  /* Extract file type from @fname. If @r_type is valid,  /* Extract file type from @fname. If @r_type is valid,
274     it contains the PGP type on success. */     it contains the PGP type on success. */
275  static const char *  static const char*
276  fm_get_file_type (const char *fname, int *r_type)  fm_get_file_type (const char *fname, int *r_type)
277  {          {        
278      gpg_iobuf_t inp;      gpg_iobuf_t inp;
279      armor_filter_context_t afx;      armor_filter_context_t afx;
280      PACKET *pkt;      PACKET *pkt;
281      const char *s = NULL;      const char *s = NULL;
282      int i = 0, rc = 0;      size_t count = 0, compr = 0;
283        int rc = 0;
284    
285      if (r_type)      if (r_type)
286          *r_type = PGP_NONE;          *r_type = PGP_NONE;
# Line 295  fm_get_file_type (const char *fname, int Line 294  fm_get_file_type (const char *fname, int
294    
295      inp = gpg_iobuf_open (fname);      inp = gpg_iobuf_open (fname);
296      if (!inp) {      if (!inp) {
297          const char *s = winpt_strerror (WPTERR_FILE_OPEN);          const char *err = winpt_strerror (WPTERR_FILE_OPEN);
298          log_box (_("File Manager"), MB_ERR, "\"%s\": %s", fname, s);          log_box (_("File Manager"), MB_ERR, "\"%s\": %s", fname, err);
299          return NULL;          return NULL;
300      }      }
301      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
# Line 338  fm_get_file_type (const char *fname, int Line 337  fm_get_file_type (const char *fname, int
337              s = "SECKEY";   rc = -2;              s = "SECKEY";   rc = -2;
338              if (r_type) *r_type = PGP_SECKEY;              if (r_type) *r_type = PGP_SECKEY;
339              break;              break;
340    
341            case PKT_COMPRESSED:
342                /* If we only find 1 packet and it is compressed,
343                   we assume a compress one-pass signature. */
344                if (count != 0)
345                    break;
346                s = "SIGNED";   rc = -2;
347                compr = 1;
348                break;
349    
350            default:
351                break;
352          }          }
353            count++;
354          gpg_free_packet (pkt);          gpg_free_packet (pkt);
355          gpg_init_packet (pkt);          gpg_init_packet (pkt);
356          if (rc == -2)          if (rc == -2)
# Line 350  fm_get_file_type (const char *fname, int Line 362  fm_get_file_type (const char *fname, int
362          s = fm_check_armor_type (fname, r_type);          s = fm_check_armor_type (fname, r_type);
363      if (!s)      if (!s)
364          s = "UNKNOWN";          s = "UNKNOWN";
365      if (!strcmp (s, "SIGNED")      if (!strcmp (s, "SIGNED") && !compr
366          && strcmp (fm_check_armor_type (fname, r_type), "SIGNED-CLEAR ")) {          && strcmp (fm_check_armor_type (fname, r_type), "SIGNED-CLEAR ")) {
367          if (r_type) *r_type = PGP_SIG;          if (r_type) *r_type = PGP_SIG;
368          s = "SIGNED-DETACH";          s = "SIGNED-DETACH";
# Line 359  fm_get_file_type (const char *fname, int Line 371  fm_get_file_type (const char *fname, int
371  }  }
372    
373    
374    /* Build the File Manager list view control. */
375  int  int
376  fm_build (listview_ctrl_t *lv, HWND ctrl)  fm_build (listview_ctrl_t *lv, HWND ctrl)
377  {  {
378      int i, rc = 0;      int i;
379      listview_ctrl_t c;      listview_ctrl_t c;
380      struct listview_column_s col[] =      struct listview_column_s col[] = {
     {  
381          {0,  80, (char *)_("Status") },          {0,  80, (char *)_("Status") },
382          {1, 256, (char *)_("Name") },          {1, 256, (char *)_("Name") },
383          {2, 128, (char *)_("Operation") },          {2, 128, (char *)_("Operation") },
384          {0,   0, NULL }          {0,   0, NULL}  
385      };      };
386                    
387      rc = listview_new( &c );      listview_new (&c, ctrl);
388      if( rc )      for (i = 0; col[i].width; i++)
389          BUG( NULL );          listview_add_column (c, &col[i]);
390      c->ctrl = ctrl;      listview_set_ext_style (c);
391      for ( i = 0; col[i].width; i++ )      if (lv)
         listview_add_column( c, &col[i] );  
     listview_set_ext_style( c );  
     if( lv )  
392          *lv = c;          *lv = c;
393      return 0;      return 0;
394  } /* fm_build */  }
395    
396    
397    /* Release the File Manager listview control. */
398  void  void
399  fm_delete( listview_ctrl_t lv )  fm_delete (listview_ctrl_t lv)
400  {  {
401      if( lv ) {      if (lv) {
402          listview_release( lv );          listview_release(lv);  
403      }      }
404  } /* fm_delete */  }
405    
406    
407  int  int
408  fm_state_new (fm_state_t * ctx)  fm_state_new (fm_state_t * ctx)
409  {  {
410      gpgme_error_t rc;      fm_state_s *c;
     fm_state_s * c;  
411    
412      c = new fm_state_s;      c = new fm_state_s;
413      if (!c)      if (!c)
414          BUG (0);          BUG (0);
415      memset (c, 0, sizeof *c);      memset (c, 0, sizeof *c);
416      rc = gpgme_new (&c->ctx);      if (gpgme_new (&c->ctx))
     if (rc)  
417          BUG (0);          BUG (0);
     /* XXX rc = gpgme_recipients_new (&c->recp);*/  
     /* XXX gpgme_set_comment (c->ctx, "Generated by WinPT "PGM_VERSION); */  
418      *ctx = c;      *ctx = c;
419      return 0;      return 0;
420  } /* fm_state_new */  }
421    
422    
423  /* Release the FM state handle @c. */  /* Release the FM state handle @c. */
# Line 420  fm_state_release (fm_state_t c) Line 426  fm_state_release (fm_state_t c)
426  {  {
427      if (!c)      if (!c)
428          return;          return;
     if (c->recp)  
         free (c->recp);  
429      if (c->ctx) {      if (c->ctx) {
430          gpgme_release (c->ctx);          gpgme_release (c->ctx);
431          c->ctx = NULL;            c->ctx = NULL;  
432      }      }
433        safe_free (c->recp);
434      free_if_alloc (c->opaque);      free_if_alloc (c->opaque);
435      free_if_alloc (c->output);      free_if_alloc (c->output);
436      delete c; c = NULL;          delete c;
437  }  }
438    
439    
440  static int  static int
441  fm_check_for_entry( listview_ctrl_t lv, const char *file )  fm_check_for_entry( listview_ctrl_t lv, const char *file )
442  {  {
# Line 445  fm_check_for_entry( listview_ctrl_t lv, Line 451  fm_check_for_entry( listview_ctrl_t lv,
451      }      }
452    
453      return 0;      return 0;
454  } /* fm_check_for_entry */  }
455    
456    
457  static int  static int
# Line 469  fm_set_ftype (listview_ctrl_t lv, const Line 475  fm_set_ftype (listview_ctrl_t lv, const
475  }  }
476    
477    
478    /* Add all files from the directory @path to the list view @lv. */
479  static int  static int
480  fm_add_dir_files (listview_ctrl_t lv, char *path)  fm_add_dir_files (listview_ctrl_t lv, char *path)
481  {  {
# Line 500  int Line 507  int
507  fm_add_dropped_files (listview_ctrl_t lv, HDROP dd_files)  fm_add_dropped_files (listview_ctrl_t lv, HDROP dd_files)
508  {  {
509      char name[384+4];      char name[384+4];
510      int nfiles, rc, i;      int nfiles;
511        int rc = 0;
512        int i;
513            
514      memset (name, 0, sizeof (name));      memset (name, 0, sizeof (name));
515      nfiles = DragQueryFile (dd_files, 0xFFFFFFFF, NULL, 0);      nfiles = DragQueryFile (dd_files, 0xFFFFFFFF, NULL, 0);
# Line 513  fm_add_dropped_files (listview_ctrl_t lv Line 522  fm_add_dropped_files (listview_ctrl_t lv
522          if (rc == -1)          if (rc == -1)
523              break; /* XXX: fixme? */              break; /* XXX: fixme? */
524      }      }
525        DragFinish (dd_files);
526      return rc;      return rc;
527  }  }
528    
# Line 530  add_single_file (listview_ctrl_t lv, con Line 540  add_single_file (listview_ctrl_t lv, con
540      if (!type)      if (!type)
541          return WPTERR_FILE_OPEN;          return WPTERR_FILE_OPEN;
542      if (!strcmp (type, "UNKNOWN"))            if (!strcmp (type, "UNKNOWN"))      
543          type = gnupg_check_file_ext (name, NULL);                    type = gnupg_check_file_ext (name, NULL);
544      rc = listview_add_item (lv, "");              rc = listview_add_item (lv, "");
545      if (!rc) {        if (!rc) {
546          listview_add_sub_item (lv, 0, 0, type);          listview_add_sub_item (lv, 0, 0, type);
547          listview_add_sub_item (lv, 0, 1, name);          listview_add_sub_item (lv, 0, 1, name);
548      }      }
# Line 556  fm_add_opened_files (listview_ctrl_t lv, Line 566  fm_add_opened_files (listview_ctrl_t lv,
566      open.lStructSize = sizeof (OPENFILENAME);      open.lStructSize = sizeof (OPENFILENAME);
567      open.hInstance = glob_hinst;      open.hInstance = glob_hinst;
568      open.lpstrTitle = _("File Open");      open.lpstrTitle = _("File Open");
569      open.lpstrFilter = _("All Files (*.*)\0*.*\0\0");      open.lpstrFilter = "All Files (*.*)\0*.*\0\0";
570      open.hwndOwner = dlg;      open.hwndOwner = dlg;
571      open.lpstrFile = file;      open.lpstrFile = file;
572      open.nMaxFile = sizeof (file) - 1;      open.nMaxFile = sizeof (file) - 1;
# Line 584  fm_add_opened_files (listview_ctrl_t lv, Line 594  fm_add_opened_files (listview_ctrl_t lv,
594          else {          else {
595              char *p = make_filename (path, name, NULL);              char *p = make_filename (path, name, NULL);
596              rc = add_single_file (lv, p);              rc = add_single_file (lv, p);
597              free (p);              safe_free (p);
598          }          }
599          n++;          n++;
600      }      }
601      if (n == 1) /* single file selected. */      if (n == 1) /* single file selected. */
602          rc = add_single_file (lv, path);          rc = add_single_file (lv, path);
603      if (path)      safe_free (path);
         free (path);  
604      return rc;      return rc;
605  }  }
606    
607    
608  int  int
609  fm_assume_onepass_sig (const char * fname)  fm_assume_onepass_sig (const char * fname)
610  {  {    
     gpgme_data_t dat;  
611      armor_filter_context_t afx;      armor_filter_context_t afx;
612      gpg_iobuf_t fp;      gpg_iobuf_t fp;
613      PACKET * pkt = (PACKET *)calloc (1, sizeof *pkt);      gpgme_data_t dat;
614        PACKET *pkt;
615        char tmpfile[MAX_PATH+1];
616      int check = 0;      int check = 0;
617    
618        pkt = (PACKET *)calloc (1, sizeof *pkt);
619      if (!fname) {      if (!fname) {
620            get_temp_name (tmpfile, sizeof (tmpfile)-1, "gpgme.tmp");
621          gpg_data_new_from_clipboard (&dat, 0);          gpg_data_new_from_clipboard (&dat, 0);
622          gpg_data_release_and_set_file (dat, "gpgme.tmp");          gpg_data_release_and_set_file (dat, tmpfile);
623    
624          fp = gpg_iobuf_open ("gpgme.tmp");          fp = gpg_iobuf_open (tmpfile);
625          if (!fp)          if (!fp)
626              return 0;              return 0;
627          gpg_iobuf_ioctl (fp, 3, 1, NULL);          gpg_iobuf_ioctl (fp, 3, 1, NULL);
# Line 622  fm_assume_onepass_sig (const char * fnam Line 634  fm_assume_onepass_sig (const char * fnam
634              && pkt->pkttype == PKT_COMPRESSED)              && pkt->pkttype == PKT_COMPRESSED)
635              check = 1;                check = 1;  
636          gpg_free_packet (pkt);          gpg_free_packet (pkt);
         safe_free (pkt);  
637          gpg_iobuf_close (fp);          gpg_iobuf_close (fp);
638          unlink ("gpgme.tmp");          remove (tmpfile);
639      }      }
640      /* XXX: implement it for real files */      /* XXX: implement it for real files */
641        safe_free (pkt);
642      return check;      return check;
643  }  }
644    
# Line 639  fm_get_current_pos (listview_ctrl_t lv) Line 651  fm_get_current_pos (listview_ctrl_t lv)
651      items = listview_count_items (lv, 0);      items = listview_count_items (lv, 0);
652      if (!items)      if (!items)
653          return -1;          return -1;
654      else if (items == 1)      else if (items == 1) {
     {  
655          listview_select_one (lv, 0);          listview_select_one (lv, 0);
656          return 0;          return 0;
657      }      }
658      else if (items > 1)      else if (items > 1) {
     {  
659          i = listview_get_curr_pos (lv);          i = listview_get_curr_pos (lv);
660          if (i == -1)          if (i == -1) {
661          {              msg_box (lv->ctrl, _("Please select a file."),
662              msg_box (lv->ctrl, _("Please select a file."), _("File Manager"), MB_ERR);                       _("File Manager"), MB_ERR);
663              return -1;              return -1;
664          }          }
665          return i;          return i;
666      }      }
667    
668      return -1;      return -1;
669  } /* fm_get_current_pos */  }
670    
671    
672  static int  static int
673  fm_check_detached_sig( listview_ctrl_t lv, int pos )  fm_check_detached_sig (listview_ctrl_t lv, int pos)
674  {  {
675      char type[128];      char type[128];
676    
677      listview_get_item_text( lv, pos, 0, type, 127 );      listview_get_item_text (lv, pos, 0, type, sizeof (type)-1);
678      return !strcmp( type, "SIGNED-DETACH" )? 1 : 0;      return !strcmp (type, "SIGNED-DETACH")? 1 : 0;
679  } /* fm_check_detached_sig */  }
680    
681    
682  int  int
# Line 723  fm_check_file_type (listview_ctrl_t lv, Line 733  fm_check_file_type (listview_ctrl_t lv,
733      }      }
734            
735      return rc;      return rc;
736  } /* fm_check_file_type */  }
737    
738    
739    /* Set the file status of the given command @fm_cmd.
740       @success is 0 on success. */
741  static void  static void
742  fm_set_status (listview_ctrl_t lv, int pos, int fm_cmd, int success,  fm_set_status (listview_ctrl_t lv, int pos, int fm_cmd,
743                 const char * output)                 gpgme_sig_mode_t sigmode, int success, const char *output)
744  {  {
745      char status[128], operat[128];      char status[128], operat[128];
746      int update = 1;      int update = 1;
747      const char *s;      const char *s;
748    
749      if ( fm_cmd == FM_LIST )      if (fm_cmd == FM_LIST)
750          return;          return;
751      success ? s = "SUCCESS" : s = "FAILED";      success ? s = "SUCCESS" : s = "FAILED";
752      strcpy( operat, s );      strcpy (operat, s);
753    
754      switch (fm_cmd) {      switch (fm_cmd) {
755      case FM_ENCRYPT:      case FM_ENCRYPT:
756      case FM_ENCRYPT_DIR:      case FM_ENCRYPT_DIR:
757      case FM_SIGNENCRYPT: strcpy( status, "ENCRYPTED" ); break;      case FM_SIGNENCRYPT: strcpy (status, "ENCRYPTED"); break;
758      case FM_DECRYPT:     strcpy( status, "UNKNOWN" );   break;      case FM_DECRYPT:     strcpy (status, "UNKNOWN");   break;
759      case FM_SIGN:        strcpy( status, "SIGNED" );    break;      case FM_SIGN:
760            if (sigmode == GPGME_SIG_MODE_DETACH)
761                strcpy (status, "SIGNED-DETACH");
762            else if (sigmode == GPGME_SIG_MODE_CLEAR)
763                strcpy (status, "SIGNED-CLEAR");
764            else
765                strcpy (status, "SIGNED");
766            break;
767      case FM_VERIFY:      update = 0;                    break;      case FM_VERIFY:      update = 0;                    break;
768      case FM_SYMENC:      strcpy( status, "SYMKEYENC" ); break;      case FM_SYMENC:      strcpy (status, "SYMKEYENC"); break;
769      case FM_IMPORT:      update = 0;                    break;      case FM_IMPORT:      update = 0;                    break;
770      case FM_WIPE:        strcpy( status, "WIPED" );     break;      case FM_WIPE:        strcpy (status, "WIPED");     break;
771      default:             strcpy( status, "UNKNOWN");    break;      default:             strcpy (status, "UNKNOWN");    break;
772      }      }
773    
774      if (success) {      if (success && update) {
775          if (update) {          listview_add_sub_item (lv, pos, 0, status);
776              listview_add_sub_item (lv, pos, 0, status);          listview_add_sub_item (lv, pos, 1, output);
             listview_add_sub_item (lv, pos, 1, output);  
         }  
777      }      }
778      listview_add_sub_item( lv, pos, 2, operat );      listview_add_sub_item( lv, pos, 2, operat );
779  } /* fm_set_status */  }
780    
781    
782  int  int
# Line 787  fm_clearsign_8bit (listview_ctrl_t lv, f Line 804  fm_clearsign_8bit (listview_ctrl_t lv, f
804      if (!cnt)      if (!cnt)
805          return 0;          return 0;
806      n = -1;      n = -1;
807      i = log_box (_("File Manager"), MB_WARN|MB_YESNO,      i = log_box (_("File Manager"), MB_WARN|MB_YESNO,
808                   _("\"%s\" does not seems to be a text file.\n"                   _("\"%s\" does not seems to be a text file.\n"
809                     "Do you really want to clearsign it?"), name);                     "Do you really want to clearsign it?"), name);
810      if (i == IDYES)      if (i == IDYES)
# Line 795  fm_clearsign_8bit (listview_ctrl_t lv, f Line 812  fm_clearsign_8bit (listview_ctrl_t lv, f
812      return n;      return n;
813  }  }
814    
815    
816  int  int
817  fm_parse_files (listview_ctrl_t lv, HWND dlg, int cmd)  fm_parse_files (listview_ctrl_t lv, HWND dlg, int cmd)
818  {  {
# Line 807  fm_parse_files (listview_ctrl_t lv, HWND Line 825  fm_parse_files (listview_ctrl_t lv, HWND
825            
826      switch (cmd) {      switch (cmd) {
827      case ID_FILEMISC_ENCRYPT: fm_cmd = FM_ENCRYPT; break;      case ID_FILEMISC_ENCRYPT: fm_cmd = FM_ENCRYPT; break;
828        case ID_FILEMISC_ENCRYPT_ZIP:fm_cmd = FM_ENCRYPT_ZIP; break;
829      case ID_FILEMISC_DECRYPT: fm_cmd = FM_DECRYPT; break;      case ID_FILEMISC_DECRYPT: fm_cmd = FM_DECRYPT; break;
830      case ID_FILEMISC_SYMENC:  fm_cmd = FM_SYMENC;  break;      case ID_FILEMISC_SYMENC:  fm_cmd = FM_SYMENC;  break;
831      case ID_FILEMISC_SIGN:    fm_cmd = FM_SIGN;    break;          case ID_FILEMISC_SIGN:    fm_cmd = FM_SIGN;    break;    
# Line 819  fm_parse_files (listview_ctrl_t lv, HWND Line 838  fm_parse_files (listview_ctrl_t lv, HWND
838      }      }
839            
840      if (fm_get_current_pos (lv) == -1)      if (fm_get_current_pos (lv) == -1)
841          return WPTERR_GENERAL;              return WPTERR_GENERAL;
842      rc = fm_state_new (&ctx);      rc = fm_state_new (&ctx);
843      if (rc)      if (rc)
844          BUG (0);          BUG (0);
# Line 840  fm_parse_files (listview_ctrl_t lv, HWND Line 859  fm_parse_files (listview_ctrl_t lv, HWND
859            
860      /* Commands we need before we can perform the main command */      /* Commands we need before we can perform the main command */
861      switch (fm_cmd) {      switch (fm_cmd) {
862        case FM_ENCRYPT_ZIP:
863      case FM_ENCRYPT:      case FM_ENCRYPT:
864      case FM_SIGNENCRYPT:      case FM_SIGNENCRYPT:
865          if (fm_cmd == FM_SIGNENCRYPT)          if (fm_cmd == FM_SIGNENCRYPT)
866              ctx->req_signer = 1;              ctx->req_signer = 1;
867          DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILE_ENCRYPT, ctx->dlg,          DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILE_ENCRYPT,
868                          file_encrypt_dlg_proc, (LPARAM)ctx);                          ctx->dlg, file_encrypt_dlg_proc, (LPARAM)ctx);
869          if (ctx->cancel == 1) {          if (ctx->cancel == 1) {
870              rc = WPTERR_GENERAL;              rc = WPTERR_GENERAL;
871              goto leave;              goto leave;
872          }          }
873          break;          break;
# Line 886  fm_parse_files (listview_ctrl_t lv, HWND Line 906  fm_parse_files (listview_ctrl_t lv, HWND
906          memset (&confirm, 0, sizeof confirm);          memset (&confirm, 0, sizeof confirm);
907          confirm.lv_files = lv;          confirm.lv_files = lv;
908          DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILES_SECDEL, ctx->dlg,          DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILES_SECDEL, ctx->dlg,
909                              file_secdel_confirm_dlg_proc, (LPARAM)&confirm);                          file_secdel_confirm_dlg_proc, (LPARAM)&confirm);
910          if (!confirm.yes)          if (!confirm.yes)
911              goto leave;              goto leave;
912      }      }
913        
914      for( i = 0; i < listview_count_items( lv, 0 ); i++ ) {      if (fm_cmd == FM_ENCRYPT_ZIP)
915          if( !listview_get_item_state( lv, i ) )          fm_encrypt_into_zip (ctx, lv);
916    
917        for (i = 0; i < listview_count_items (lv, 0); i++) {
918            if (!listview_get_item_state (lv, i))
919              continue;              continue;
920          listview_get_item_text( lv, i, 1, fname, sizeof (fname) - 1 );          listview_get_item_text (lv, i, 1, fname, sizeof (fname) - 1);
921          if( file_exist_check( fname ) && !is_directory( fname ) ) {          if( file_exist_check (fname) && !is_directory (fname)) {
922              log_box( _("File Manager"), MB_ERR, _("\"%s\" does not exist"), fname );              log_box (_("File Manager"), MB_ERR,
923                         _("\"%s\" does not exist"), fname);
924              continue;              continue;
925          }          }
926          if( is_directory( fname ) )          if (is_directory (fname))
927              fm_cmd = FM_ENCRYPT_DIR;                      fm_cmd = FM_ENCRYPT_DIR;        
928          if( !fm_check_file_type( lv, i, fm_cmd ) )          if (!fm_check_file_type (lv, i, fm_cmd))
929              continue;              continue;
930          sig_detached = fm_check_detached_sig( lv, i );          sig_detached = fm_check_detached_sig (lv, i);
931          switch( fm_cmd ) {          switch (fm_cmd) {
932          case FM_LIST:        rc = fm_list( fname, dlg );       break;          case FM_LIST:        rc = fm_list( fname, dlg );       break;
933          case FM_WIPE:        rc = fm_wipe( fname );            break;          case FM_WIPE:        rc = fm_wipe( fname );            break;
934          case FM_ENCRYPT:     rc = fm_encrypt( ctx, fname, 0 ); break;          case FM_ENCRYPT:     rc = fm_encrypt( ctx, fname, 0 ); break;
# Line 912  fm_parse_files (listview_ctrl_t lv, HWND Line 936  fm_parse_files (listview_ctrl_t lv, HWND
936          case FM_SIGNENCRYPT: rc = fm_encrypt( ctx, fname, 1 ); break;          case FM_SIGNENCRYPT: rc = fm_encrypt( ctx, fname, 1 ); break;
937          case FM_DECRYPT:     rc = fm_decrypt( ctx, fname );    break;          case FM_DECRYPT:     rc = fm_decrypt( ctx, fname );    break;
938          case FM_SIGN:        rc = fm_sign( ctx, fname );       break;          case FM_SIGN:        rc = fm_sign( ctx, fname );       break;
939          case FM_SYMENC:      rc = fm_sym_encrypt( ctx, fname );break;          case FM_SYMENC:      rc = fm_sym_encrypt (ctx, fname); break;
940          case FM_VERIFY:      rc = fm_verify (ctx, sig_detached, fname);break;          case FM_VERIFY:      rc = fm_verify (ctx, sig_detached, fname);break;
941          case FM_IMPORT:          case FM_IMPORT:
942              free_if_alloc (ctx->opaque);              free_if_alloc (ctx->opaque);
943              ctx->opaque = m_strdup (fname);              ctx->opaque = m_strdup (fname);
944              if (!ctx->opaque)              DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
945                  BUG (0);                              file_import_dlg_proc, (LPARAM)ctx);
             DialogBoxParam( glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,  
                            file_import_dlg_proc, (LPARAM)ctx );  
946              if (ctx->cancel == 1)              if (ctx->cancel == 1)
947                  continue;                  continue;
948              rc = fm_import (ctx, fname);              rc = fm_import (ctx, fname);
949              break;              break;
950          }          }
951          fm_set_status (lv, i, fm_cmd, !rc, ctx->output);          if (ctx->cancel == 1) {
952                ctx->cancel = 0;
953                continue;
954            }
955            fm_set_status (lv, i, fm_cmd, ctx->sigmode, !rc, ctx->output);
956          free_if_alloc (ctx->output);          free_if_alloc (ctx->output);
957          progress_cleanup (&pfx);          progress_cleanup (&pfx);
958      }      }
959    
960      if (fm_cmd == FM_WIPE) {      if (fm_cmd == FM_WIPE) {
961          secure_unlink_set_cb (NULL, NULL);          secure_unlink_set_cb (NULL, NULL);
962          progress_cleanup (&pfx2);          progress_cleanup (&pfx2);
# Line 942  fm_parse_files (listview_ctrl_t lv, HWND Line 969  fm_parse_files (listview_ctrl_t lv, HWND
969      /* remove wipe files from the list */      /* remove wipe files from the list */
970      n = listview_count_items (lv, 0);      n = listview_count_items (lv, 0);
971      while (n--) {      while (n--) {
         char status[128];  
972          listview_get_item_text (lv, n, 0, status, sizeof (status) - 1);          listview_get_item_text (lv, n, 0, status, sizeof (status) - 1);
973          if( !strcmp (status, "WIPED"))          if (!strcmp (status, "WIPED"))
974              listview_del_item (lv, n);              listview_del_item (lv, n);
975      }      }
976            
# Line 988  ask_filename (fm_state_t c, const char * Line 1014  ask_filename (fm_state_t c, const char *
1014  {  {
1015      const char * s;      const char * s;
1016    
1017      s = get_filename_dlg (c->dlg, FILE_SAVE, msg, NULL, NULL);      s = get_filesave_dlg (c->dlg, msg, NULL, NULL);
1018      if (!s)      if (!s)
1019          return WPTERR_GENERAL;          return WPTERR_GENERAL;
1020    
# Line 996  ask_filename (fm_state_t c, const char * Line 1022  ask_filename (fm_state_t c, const char *
1022          free_if_alloc (*dst);          free_if_alloc (*dst);
1023      free_if_alloc (c->output);      free_if_alloc (c->output);
1024      c->output = m_strdup (s);      c->output = m_strdup (s);
     if (!c->output)  
         BUG (0);  
1025      if (dst)      if (dst)
1026          *dst = fm_quote_file (s);          *dst = fm_quote_file (s);
1027      return 0;      return 0;
# Line 1012  fm_encrypt (fm_state_t c, const char *na Line 1036  fm_encrypt (fm_state_t c, const char *na
1036      gpgme_ctx_t ctx = c->ctx;      gpgme_ctx_t ctx = c->ctx;
1037      file_data_t in=NULL, out=NULL;      file_data_t in=NULL, out=NULL;
1038      char *keyid = NULL, ext[5];      char *keyid = NULL, ext[5];
1039      int no_compr = 0;      /*int no_compr = 0;*/
1040      int rc = 0;      int rc = 0;
1041    
1042      c->output = new char[strlen (name) + 5 + 1];      c->output = new char[strlen (name) + 5 + 1];
# Line 1020  fm_encrypt (fm_state_t c, const char *na Line 1044  fm_encrypt (fm_state_t c, const char *na
1044          BUG (0);          BUG (0);
1045      strcpy (ext, file_get_extension (ctx, c->sigmode));      strcpy (ext, file_get_extension (ctx, c->sigmode));
1046      strcpy (c->output, name);      strcpy (c->output, name);
1047      strcat (c->output, ext);              strcat (c->output, ext);
1048            
1049      if (!overwrite_file (c->output)) {      if (!overwrite_file (c->output)) {
1050          rc = ask_filename (c, _("Enter filename for encrypted file"), NULL);          rc = ask_filename (c, _("Enter filename for encrypted file"), NULL);
# Line 1028  fm_encrypt (fm_state_t c, const char *na Line 1052  fm_encrypt (fm_state_t c, const char *na
1052              goto leave;              goto leave;
1053      }      }
1054    
1055      err = gpg_file_data_new (name, 1, &in);      err = gpg_file_data_new (name, F_DATA_READ, &in);
1056      if (err)      if (err)
1057          goto leave;          goto leave;
1058      err = gpg_file_data_new (c->output, 0, &out);      remove_crit_file_attrs (c->output, 0);
1059        err = gpg_file_data_new (c->output, F_DATA_WRITE, &out);
1060      if (err)      if (err)
1061          goto leave;          goto leave;
1062    
# Line 1042  fm_encrypt (fm_state_t c, const char *na Line 1067  fm_encrypt (fm_state_t c, const char *na
1067      }      }
1068      */      */
1069            
1070      /* XXX      /* XXX: disable compression for multi-media files.
1071      no_compr = is_multi_media (name);      no_compr = is_multi_media (name);
1072      gpgme_control (ctx, GPGME_CTRL_NO_COMPR, no_compr);      gpgme_control (ctx, GPGME_CTRL_NO_COMPR, no_compr);
1073      */      */
# Line 1061  fm_encrypt (fm_state_t c, const char *na Line 1086  fm_encrypt (fm_state_t c, const char *na
1086              gpgme_signers_add (ctx, key);              gpgme_signers_add (ctx, key);
1087          }          }
1088          else {          else {
1089              gpgme_key_t key = gpgme_signers_enum (ctx, 0);              gpgme_key_t sigkey = gpgme_signers_enum (ctx, 0);
1090              if (key && key->subkeys) {              if (sigkey && sigkey->subkeys) {
1091                  keyid = m_strdup (key->subkeys->keyid);                  keyid = m_strdup (sigkey->subkeys->keyid);
                 if (!keyid)  
                     BUG (NULL);  
1092              }              }
1093          }          }
1094          if (!c->init_cb || !c->cache_cb) {          if (!c->init_cb || !c->cache_cb) {
# Line 1102  fm_encrypt (fm_state_t c, const char *na Line 1125  fm_encrypt (fm_state_t c, const char *na
1125              goto leave;              goto leave;
1126          }          }
1127      }      }
     if (c->wipe)  
         secure_unlink (name, WIPE_MODE_SIMPLE);  
1128            
1129  leave:  leave:
1130      if (in)      if (in)
# Line 1111  leave: Line 1132  leave:
1132      if (out)      if (out)
1133          gpg_file_data_release (out);          gpg_file_data_release (out);
1134      free_if_alloc (keyid);      free_if_alloc (keyid);
1135        if (!rc && c->wipe)
1136            secure_unlink (name, WIPE_MODE_SIMPLE);
1137      return rc;      return rc;
1138  }  }
1139    
# Line 1122  fm_sym_encrypt (fm_state_t c, const char Line 1145  fm_sym_encrypt (fm_state_t c, const char
1145      gpgme_error_t err;          gpgme_error_t err;    
1146      file_data_t in=NULL, out=NULL;      file_data_t in=NULL, out=NULL;
1147      int rc = 0, cancel = 0;      int rc = 0, cancel = 0;
     char * src = NULL, * dst = NULL;  
1148      char ext[5], * pass;          char ext[5], * pass;    
1149            
1150      pass = request_passphrase2 (_("Symmetric"), 0, &cancel);      pass = request_passphrase2 (_("Symmetric"), 0, &cancel);
1151      if (cancel)      if (cancel) {
1152            c->cancel = 1;
1153          return 0;          return 0;
1154        }
1155            
1156      /* XXX gpgme_control (ctx, GPGME_CTRL_CIPHER, -1);*/      /* XXX gpgme_control (ctx, GPGME_CTRL_CIPHER, -1);*/
1157      c->output = new char[strlen (name) + 5 + 1];      c->output = new char[strlen (name) + 5 + 1];
# Line 1172  leave: Line 1196  leave:
1196          gpg_file_data_release (out);          gpg_file_data_release (out);
1197      sfree_if_alloc (pass);      sfree_if_alloc (pass);
1198      return rc;      return rc;
1199  } /* fm_sym_encrypt */  }
1200    
1201    
1202    char* get_pka_status (gpgme_signature_t sig);
1203    
1204    
1205  /* Show the human readable verify result from @sigres. */  /* Show the human readable verify result from @sigres. */
1206  static void  static void
1207  show_verify_result (gpgme_verify_result_t sigres)  show_verify_result (gpgme_verify_result_t sigres)
1208  {  {    
     gpgme_key_t key=NULL;  
1209      gpgme_signature_t sig=sigres->signatures;      gpgme_signature_t sig=sigres->signatures;
1210      const char *s, *keyid;      winpt_key_s key;
1211      int sigok = 0;      const char *s, *keyid, *uid;
1212      int type;      char *pka_info;
1213      char buf[384];      char buf[384];
1214        int sigok = 0;
1215    
1216      sig = sigres->signatures;      sig = sigres->signatures;
1217      sigok = sig->summary & GPGME_SIGSUM_GREEN;      sigok = sig->summary & GPGME_SIGSUM_GREEN;
1218      s = sigok? _("Good signature") : _("BAD signature");      s = sigok? _("Good signature") : _("BAD signature");
1219      type = sigok? MB_OK: MB_ICONWARNING|MB_OK;      keyid = sig->fpr;
     keyid = sig->fpr;    
1220      if (!keyid)      if (!keyid)
1221          return;          return;
1222        pka_info = get_pka_status (sig);
1223      keyid = strlen (sig->fpr) == 40? sig->fpr+32 : sig->fpr + 24;      keyid = get_keyid_from_fpr (sig->fpr);
1224      get_pubkey (sig->fpr, &key);      memset (&key, 0, sizeof (key));
1225      _snprintf (buf, sizeof (buf)-1, "Signature made %s using %s key ID %s\n"      if (!winpt_get_pubkey (sig->fpr, &key))
1226                                      "%s from \"%s\"",          uid = key.ext->uids->uid;
1227                  strtimestamp (sig->timestamp), get_key_pubalgo (sig->pubkey_algo),      else
1228                  keyid, s, key? key->uids->uid : _("user ID not found"));          uid = _("user ID not found");
1229      msg_box (NULL, buf, _("Decrypt Verify"), type);      _snprintf (buf, sizeof (buf)-1, _("Signature made %s using %s key ID %s\n"
1230                                          "%s from \"%s\"\n%s"),
1231                    strtimestamp (sig->timestamp),
1232                    get_key_pubalgo (sig->pubkey_algo),
1233                    keyid, s, uid, pka_info? pka_info : "");
1234        msg_box (NULL, buf, _("Decrypt Verify"), sigok? MB_OK: MB_ICONWARNING|MB_OK);
1235        free_if_alloc (pka_info);
1236  }  }
1237    
1238    
# Line 1211  secret_key_available (gpgme_recipient_t Line 1243  secret_key_available (gpgme_recipient_t
1243      gpgme_recipient_t r;      gpgme_recipient_t r;
1244      gpgme_key_t key;      gpgme_key_t key;
1245    
1246      for (r=rset; r; r = r->next) {            for (r=rset; r; r = r->next) {
1247          if (gpgme_err_code (r->status) == GPG_ERR_NO_SECKEY)          if (gpgme_err_code (r->status) == GPG_ERR_NO_SECKEY)
1248              continue;              continue;
1249          else {          else {
# Line 1224  secret_key_available (gpgme_recipient_t Line 1256  secret_key_available (gpgme_recipient_t
1256  }  }
1257    
1258    
1259    /* If the decrypt result contains the original file name,
1260       we use it instead of the artificial "output - .gpg" string. */
1261    static int
1262    restore_original_name (const char *output, const char *file_name)
1263    {
1264        char *dir;
1265        char *orig;
1266        int rc = 0;
1267    
1268        dir = strrchr (output, '\\');
1269        if (!dir)
1270            orig = strdup (file_name);
1271        else {
1272            orig = (char*)calloc (1, strlen (file_name)+ 1 +
1273                                     strlen (output)+1);
1274            if (!orig)
1275                BUG (0);
1276            memcpy (orig, output, (dir-output)+1);
1277            strcat (orig, file_name);
1278        }
1279        if (overwrite_file (orig)) {
1280            DeleteFile (orig);
1281            if (!MoveFile (output, orig))
1282                rc = -1;
1283        }
1284        safe_free (orig);
1285        return rc;
1286    }
1287    
1288    
1289  /* Decrypt the file @name. */  /* Decrypt the file @name. */
1290  int  int
1291  fm_decrypt (fm_state_t c, const char *name)  fm_decrypt (fm_state_t c, const char *name)
# Line 1232  fm_decrypt (fm_state_t c, const char *na Line 1294  fm_decrypt (fm_state_t c, const char *na
1294      gpgme_ctx_t ctx = c->ctx;          gpgme_ctx_t ctx = c->ctx;    
1295      gpgme_decrypt_result_t res;      gpgme_decrypt_result_t res;
1296      gpgme_verify_result_t sigres;      gpgme_verify_result_t sigres;
1297      file_data_t in =NULL, out=NULL;      file_data_t in = NULL, out = NULL;
     int is_signed = 0;  
1298      int rc = 0;      int rc = 0;
1299            
1300      if (!c->init_cb || !c->cache_cb) {      if (!c->init_cb || !c->cache_cb) {
1301          set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_DECRYPT,          set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_DECRYPT,
1302                                 c->dlg, _("Decryption"));                                 c->dlg, _("Decryption"));
1303          c->init_cb = 1;          c->init_cb = 1;
1304      }          }
1305            
1306      c->output = m_strdup (name);      c->output = m_strdup (name);
     if (!c->output)  
         BUG (0);  
1307      if (is_openpgp_ext (c->output))      if (is_openpgp_ext (c->output))
1308          c->output[strlen (c->output)-4] = '\0';          c->output[strlen (c->output)-4] = '\0';
1309      else {      else {
# Line 1254  fm_decrypt (fm_state_t c, const char *na Line 1313  fm_decrypt (fm_state_t c, const char *na
1313          if (s) {          if (s) {
1314              free_if_alloc (c->output);              free_if_alloc (c->output);
1315              c->output = m_strdup (s);              c->output = m_strdup (s);
             if (!c->output)  
                 BUG (NULL);  
1316          }          }
1317      }      }
1318    
# Line 1263  fm_decrypt (fm_state_t c, const char *na Line 1320  fm_decrypt (fm_state_t c, const char *na
1320          rc = ask_filename (c, _("Please enter filename for plaintext file"), NULL);          rc = ask_filename (c, _("Please enter filename for plaintext file"), NULL);
1321          if (rc)          if (rc)
1322              goto leave;              goto leave;
1323      }          }
   
     remove_crit_file_attrs (c->output, 0);  
1324    
1325      err = gpg_file_data_new (name, 1, &in);      err = gpg_file_data_new (name, F_DATA_READ, &in);
1326      if (err)      if (err)
1327          goto leave;          goto leave;
1328      err = gpg_file_data_new (c->output, 0, &out);      remove_crit_file_attrs (c->output, 0);
1329        err = gpg_file_data_new (c->output, F_DATA_WRITE, &out);
1330      if (err)      if (err)
1331          goto leave;          goto leave;
1332    
# Line 1290  fm_decrypt (fm_state_t c, const char *na Line 1346  fm_decrypt (fm_state_t c, const char *na
1346          char *p = get_key_userid (keyid+8);          char *p = get_key_userid (keyid+8);
1347          gpgme_pubkey_algo_t pkalgo = res->recipients->pubkey_algo;          gpgme_pubkey_algo_t pkalgo = res->recipients->pubkey_algo;
1348                    
1349          log_box( _("Decryption"), MB_ERR,          log_box (_("Decryption"), MB_ERR,
1350                   _("Encrypted with %s key, ID %s.%s\n"                   _("Encrypted with %s key, ID %s.%s\n"
1351                     "Decryption failed: secret key not available."),                     "Decryption failed: secret key not available."),
1352                     get_key_pubalgo (pkalgo), keyid+8, p);                     get_key_pubalgo (pkalgo), keyid+8, p);
# Line 1304  fm_decrypt (fm_state_t c, const char *na Line 1360  fm_decrypt (fm_state_t c, const char *na
1360          goto leave;          goto leave;
1361      }      }
1362      if (file_exist_check (c->output)) {      if (file_exist_check (c->output)) {
1363          log_box ("Decrypt", MB_ERR, _("Decryption failed.\n%s: does not exist."), c->output);          log_box ("Decrypt", MB_ERR,
1364                     _("Decryption failed.\n%s: does not exist."), c->output);
1365          rc = WPTERR_GENERAL;          rc = WPTERR_GENERAL;
1366            goto leave;
1367        }
1368        else if (res && res->file_name) {
1369            char *file = strrchr (c->output, '\\');
1370            int id = log_box (_("Decrypt"), MB_QUEST_ASK,
1371                              _("The original file name is '%s'.\n\n"
1372                                "Do you want to use this instead of '%s'?"),
1373                                res->file_name, file? file+1 : c->output);
1374            if (id == IDYES) {
1375                /* before we can move the file, it needs to be closed first. */
1376                gpg_file_data_release (out);
1377                out = NULL;
1378                restore_original_name (c->output, res->file_name);
1379            }
1380      }      }
       
1381      sigres = gpgme_op_verify_result (ctx);      sigres = gpgme_op_verify_result (ctx);
1382      if (sigres && sigres->signatures)      if (sigres && sigres->signatures)
1383          show_verify_result (sigres);          show_verify_result (sigres);    
1384            
1385  leave:  leave:
1386      if (in)      if (in)
1387          gpg_file_data_release (in);          gpg_file_data_release (in);
1388      if (out)      if (out)
1389          gpg_file_data_release (out);          gpg_file_data_release (out);
1390    
1391      return rc;      return rc;
1392  }  }
1393    
1394    
1395  int  int
1396  fm_sign (fm_state_t c, const char * name)  fm_sign (fm_state_t c, const char * name)
1397  {        {
     int rc = 0;  
1398      gpgme_ctx_t ctx = c->ctx;      gpgme_ctx_t ctx = c->ctx;
1399      gpgme_error_t err;      gpgme_error_t err;
1400      file_data_t in=NULL, out=NULL;      file_data_t in=NULL, out=NULL;
1401      char ext[5];      char ext[5];
1402        int rc = 0;
1403    
1404      if (!c->init_cb || !c->cache_cb) {      if (!c->init_cb || !c->cache_cb) {
1405          set_gpg_passphrase_cb (&c->pass_cb, c->ctx, GPG_CMD_SIGN, c->dlg, _("Signing") );          set_gpg_passphrase_cb (&c->pass_cb, c->ctx,
1406                                   GPG_CMD_SIGN, c->dlg, _("Signing"));
1407          c->init_cb = 1;          c->init_cb = 1;
1408      }      }
1409            
1410      free_if_alloc (c->output);      free_if_alloc (c->output);
1411      c->output = new char[strlen (name) + 5 + 1];      c->output = new char[strlen (name) + 5 + 1];
1412      if( !c->output)      if (!c->output)
1413          BUG( NULL );          BUG (NULL);
1414      strcpy (ext, file_get_extension (ctx, c->sigmode));      strcpy (ext, file_get_extension (ctx, c->sigmode));
1415      strcpy (c->output, name);      strcpy (c->output, name);
1416      strcat (c->output, ext);      strcat (c->output, ext);
# Line 1348  fm_sign (fm_state_t c, const char * name Line 1420  fm_sign (fm_state_t c, const char * name
1420          if (rc)          if (rc)
1421              goto leave;              goto leave;
1422      }      }
1423      remove_crit_file_attrs (c->output, 0);      
1424        err = gpg_file_data_new (name, F_DATA_READ, &in);
     err = gpg_file_data_new (name, 1, &in);  
1425      if (err)      if (err)
1426          goto leave;          goto leave;
1427      err = gpg_file_data_new (c->output, 0, &out);      remove_crit_file_attrs (c->output, 0);
1428        err = gpg_file_data_new (c->output, F_DATA_WRITE, &out);
1429      if (err)      if (err)
1430          goto leave;          goto leave;
1431    
1432      op_begin ();      op_begin ();
1433      err = gpgme_op_sign (ctx, in->dat, out->dat, c->sigmode);      err = gpgme_op_sign (ctx, in->dat, out->dat, c->sigmode);
1434      op_end ();      op_end ();
1435      if( !c->cache_cb )      if (!c->cache_cb)
1436          release_gpg_passphrase_cb (&c->pass_cb);          release_gpg_passphrase_cb (&c->pass_cb);
1437      if( c->pass_cb.cancel ) {      if (c->pass_cb.cancel) {
1438          rc = WPTERR_GENERAL;          rc = WPTERR_GENERAL;
1439          goto leave;          goto leave;
1440      }      }
1441      if( err ) {      if (err) {
1442          msg_box( c->dlg, gpgme_strerror( err ), _("Sign"), MB_ERR );          msg_box (c->dlg, gpgme_strerror (err), _("Sign"), MB_ERR);
1443          rc = WPTERR_GENERAL;          rc = WPTERR_GENERAL;
1444          goto leave;              goto leave;    
1445      }      }
# Line 1381  leave: Line 1453  leave:
1453  }  }
1454    
1455    
1456  static int  static void
1457  fm_add_sig_stat (file_sig_ctx_t log)  fm_add_sig_stat (file_sig_ctx_t log)
1458  {  {
1459      gpgme_key_t key;          struct winpt_key_s key;
1460      const char *kid;      const char *kid;
     int not_found = 0;  
1461    
1462      kid = log->sig->fpr;      memset (&key, 0, sizeof (key));
1463      if (!kid)      kid = get_keyid_from_fpr (log->sig->fpr);
1464          BUG (NULL);      log->use_uid = 0;
1465      if (strlen (kid) == 40)      if (!winpt_get_pubkey (kid, &key)) {
1466          kid += 32;                log->user_id = key.ext->uids->uid;
     else if (strlen (kid) == 32)  
         kid += 24;  
     if (get_pubkey (kid, &key))  
         log->use_uid = 0;  
     else {  
         log->user_id = key->uids->uid;  
1467          log->use_uid = 1;          log->use_uid = 1;
1468      }      }
1469      file_verify_add_state (log);      file_verify_add_state (log);
     return 0;  
1470  }  }
1471    
1472    
1473    /* Verify a detached signature from the clipboard. */  
1474  static int  static int
1475  verify_pasted (listview_ctrl_t lv, fm_state_t ctx, const char * dat,  verify_pasted (listview_ctrl_t lv, fm_state_t ctx,
1476                 int i, HWND dlg)                 const char *dat, int pos, HWND dlg)
1477  {  {
1478      FILE * fp;      FILE *fp;
1479      char stat[32];      char stat[32];
1480      char file[256], * fname = NULL;      char file[256], *fname = NULL;
1481      int del_end=0;      int del_end = 0;
1482    
1483      listview_get_item_text (lv, i, 0, stat, sizeof (stat)-1);      listview_get_item_text (lv, pos, 0, stat, sizeof (stat)-1);
1484      listview_get_item_text (lv, i, 1, file, sizeof (file)-1);      listview_get_item_text (lv, pos, 1, file, sizeof (file)-1);
1485      if (strcmp (stat, "UNKNOWN"))      if (strcmp (stat, "UNKNOWN"))
1486          return 0;          return 0;
1487      fname = make_filename (NULL, file, "asc");      fname = make_filename (NULL, file, "asc");
# Line 1425  verify_pasted (listview_ctrl_t lv, fm_st Line 1490  verify_pasted (listview_ctrl_t lv, fm_st
1490          if (fp == NULL) {          if (fp == NULL) {
1491              log_box (_("File Manager"), MB_ERR, "could not create '%s'", fname);              log_box (_("File Manager"), MB_ERR, "could not create '%s'", fname);
1492              free_if_alloc (fname);              free_if_alloc (fname);
1493              return WPTERR_GENERAL;                    return WPTERR_GENERAL;
1494          }                }
1495          fwrite (dat, 1, strlen (dat), fp);          fwrite (dat, 1, strlen (dat), fp);
1496          fclose (fp);          fclose (fp);
1497          del_end = 1;          del_end = 1;
1498      }      }
1499      fm_verify (ctx, 1, fname);      fm_verify (ctx, 1, fname);
1500      if (del_end)      if (del_end)
1501          unlink (fname);          remove (fname);
1502      free_if_alloc (fname);      free_if_alloc (fname);
1503      return 0;      return 0;
1504  }  }
1505    
1506    
1507    /* Figure out if the clipboard contains a detached signature. */
1508  int  int
1509  fm_verify_pasted_detsig (listview_ctrl_t lv, HWND dlg)  fm_verify_pasted_detsig (listview_ctrl_t lv, HWND dlg)
1510  {  {
# Line 1456  fm_verify_pasted_detsig (listview_ctrl_t Line 1522  fm_verify_pasted_detsig (listview_ctrl_t
1522      /* XXX find a way to filter out bad signatures or just ignore all in      /* XXX find a way to filter out bad signatures or just ignore all in
1523             this case */             this case */
1524      fm_state_new (&ctx);      fm_state_new (&ctx);
1525      if ((i=listview_get_curr_pos (lv)) != -1) {      i = listview_get_curr_pos (lv);
1526        if (i= -1) {
1527          verify_pasted (lv, ctx, dat, i, dlg);          verify_pasted (lv, ctx, dat, i, dlg);
1528          fnd = 1;          fnd = 1;
1529      }      }
# Line 1488  get_output_file (fm_state_t c, const cha Line 1555  get_output_file (fm_state_t c, const cha
1555      else      else
1556          title = _("Selected Output File");          title = _("Selected Output File");
1557    
1558      if (strstr (name, ".sig") || strstr (name, ".asc") || strstr (name, ".gpg")) {      if (stristr (name, ".sig") ||
1559            stristr (name, ".asc") ||
1560            stristr (name, ".gpg")) {
1561          _snprintf (fname, sizeof (fname) - 1, "%s", name);          _snprintf (fname, sizeof (fname) - 1, "%s", name);
1562          fname[strlen (fname) - 4] = '\0';          fname[strlen (fname) - 4] = '\0';
1563          if (file_exist_check (fname) == 0 && detached)            if (file_exist_check (fname) == 0 && detached)  
# Line 1510  get_output_file (fm_state_t c, const cha Line 1579  get_output_file (fm_state_t c, const cha
1579      if (file) {          if (file) {    
1580          free_if_alloc (c->output);              free_if_alloc (c->output);    
1581          c->output = m_strdup (file);          c->output = m_strdup (file);
         if (!c->output)  
             BUG (NULL);  
1582      }      }
1583      else {      else {
1584          msg_box (c->dlg, _("Invalid file name. Exit"), _("Verify"), MB_ERR);          msg_box (c->dlg, _("Invalid file name. Exit"), _("Verify"), MB_ERR);
# Line 1520  get_output_file (fm_state_t c, const cha Line 1587  get_output_file (fm_state_t c, const cha
1587      if (detached)      if (detached)
1588          c->sigmode = GPGME_SIG_MODE_DETACH;          c->sigmode = GPGME_SIG_MODE_DETACH;
1589      else {      else {
1590          if (strstr (name, ".asc"))          if (stristr (name, ".asc"))
1591              c->sigmode = GPGME_SIG_MODE_CLEAR;              c->sigmode = GPGME_SIG_MODE_CLEAR;
1592          else          else
1593              c->sigmode = GPGME_SIG_MODE_NORMAL;              c->sigmode = GPGME_SIG_MODE_NORMAL;
# Line 1542  fm_verify (fm_state_t c, int detached, c Line 1609  fm_verify (fm_state_t c, int detached, c
1609      file_data_t in=NULL, out=NULL;      file_data_t in=NULL, out=NULL;
1610      int rc = 0;      int rc = 0;
1611    
1612      if (strstr (name, ".sig"))      if (stristr (name, ".sig"))
1613          detached = 1;          detached = 1;
1614    
1615      if (get_output_file (c, name, detached))      if (get_output_file (c, name, detached))
# Line 1550  fm_verify (fm_state_t c, int detached, c Line 1617  fm_verify (fm_state_t c, int detached, c
1617    
1618      memset (&log, 0, sizeof (log));      memset (&log, 0, sizeof (log));
1619      log.file = m_strdup (name);      log.file = m_strdup (name);
     if (!log.file)  
         BUG (NULL);  
1620      file_verify_create_dlg ();      file_verify_create_dlg ();
1621    
1622      err = gpg_file_data_new (name, 1, &in);      err = gpg_file_data_new (name, F_DATA_READ, &in);
1623      if (err)      if (err)
1624          goto leave;          goto leave;
1625      err = gpg_file_data_new (c->output, detached? 1 : 0, &out);      err = gpg_file_data_new (c->output,
1626                                 detached? F_DATA_READ : F_DATA_WRITE, &out);
1627      if (err)      if (err)
1628          goto leave;          goto leave;
1629    
# Line 1586  leave: Line 1652  leave:
1652          gpg_file_data_release (in);          gpg_file_data_release (in);
1653      if (out)      if (out)
1654          gpg_file_data_release (out);          gpg_file_data_release (out);
1655      if (log.file)      free_if_alloc (log.file);
         delete []log.file;  
1656      return rc;      return rc;
1657  }  }
1658    
1659    
1660    /* Import the keys from the file @name.
1661       Return value: 0 on success. */
1662  int  int
1663  fm_import (fm_state_t c, const char *name)  fm_import (fm_state_t c, const char *name)
1664  {  {
# Line 1603  fm_import (fm_state_t c, const char *nam Line 1670  fm_import (fm_state_t c, const char *nam
1670    
1671      free_if_alloc (c->output);      free_if_alloc (c->output);
1672      c->output = m_strdup (name);      c->output = m_strdup (name);
     if (!c->output)  
         BUG (NULL);  
1673    
1674      err = gpg_file_data_new (name, 1, &keydata);      err = gpg_file_data_new (name, F_DATA_READ, &keydata);
1675      if (err)      if (err)
1676          goto leave;          goto leave;
1677    
# Line 1622  fm_import (fm_state_t c, const char *nam Line 1687  fm_import (fm_state_t c, const char *nam
1687      res = gpgme_op_import_result (ctx);      res = gpgme_op_import_result (ctx);
1688      print_import_status (res);      print_import_status (res);
1689      if (res->no_user_id > 0) {      if (res->no_user_id > 0) {
1690          msg_box (c->dlg, _("Key without a self signature was dectected!\n"                msg_box (c->dlg, _("Key without a self signature was dectected!\n"
1691                             "(This key is NOT usable for encryption, etc)\n"                             "(This key is NOT usable for encryption, etc)\n"
1692                             "\n"                             "\n"
1693                             "Cannot import these key(s)!"), _("Import"), MB_INFO);                             "Cannot import these key(s)!"), _("Import"), MB_INFO);
# Line 1632  leave: Line 1697  leave:
1697      if (keydata)      if (keydata)
1698          gpg_file_data_release (keydata);          gpg_file_data_release (keydata);
1699      return rc;      return rc;
1700  } /* fm_import */  }
1701    
1702    
1703  /* Export the selected keys from the File Manager to a file. */  /* Export the selected keys from the File Manager to a file. */
1704  int  int
1705  fm_export (fm_state_t c)  fm_export (fm_state_t c)
1706  {  {    
     int rc = 0, id = 0;  
1707      gpgme_ctx_t ctx = c->ctx;      gpgme_ctx_t ctx = c->ctx;
1708      gpgme_error_t err;      gpgme_error_t err;
1709      gpgme_key_t *rset = c->recp;      gpgme_key_t *rset = c->recp;
1710      file_data_t keydata = NULL;      file_data_t keydata = NULL;
1711      const char *name, *s = NULL;      const char *name;
1712      char *p = NULL, *patt = NULL;      char *p = NULL, *patt = NULL;
1713        int rc = 0;
1714    
1715      if (!rset || !rset[0]) {      if (!rset || !rset[0]) {
1716          msg_box (c->dlg, _("No key was selected for export."), _("Export"), MB_ERR);          msg_box (c->dlg, _("No key was selected for export."), _("Export"), MB_ERR);
# Line 1653  fm_export (fm_state_t c) Line 1718  fm_export (fm_state_t c)
1718          goto leave;          goto leave;
1719      }      }
1720    
1721      if (rset[1] == NULL) { /* count == 1*/      if (rset[1] == NULL) /* count == 1*/
1722          gpgme_key_t k = rset[0];          p = km_gen_export_filename (rset[0]->subkeys->keyid+8, 0);
         const char *s = k->uids->name;  
         p = new char[strlen (s)+1+8];  
         if (!p)  
             BUG (NULL);  
         strcpy (p, s );  
         strcat (p, ".asc");  
     }  
1723    
1724      name = get_filename_dlg (c->dlg, FILE_SAVE, _("Choose Name for Key File"),      name = get_filesave_dlg (c->dlg, _("Choose Name for Key File"),
1725                               NULL, p? p : NULL);                               NULL, p? p : NULL);
                               
1726      if (!name)      if (!name)
1727          name = "keys.gpg";          name = "keys.gpg";
1728    
1729      patt = gpg_keylist_to_pattern (rset, c->n_recp);      patt = gpg_keylist_to_pattern (rset, c->n_recp);
1730    
1731      err = gpg_file_data_new (name, 0, &keydata);      err = gpg_file_data_new (name, F_DATA_WRITE, &keydata);
1732      if (err)      if (err)
1733          goto leave;          goto leave;
1734    
# Line 1688  fm_export (fm_state_t c) Line 1745  fm_export (fm_state_t c)
1745  leave:  leave:
1746      if (keydata)      if (keydata)
1747          gpg_file_data_release (keydata);          gpg_file_data_release (keydata);
1748      if (patt)      safe_free (patt);
         free (patt);  
1749      free_if_alloc (p);      free_if_alloc (p);
           
1750      return rc;      return rc;
1751  }  }
1752    
# Line 1747  fm_parse_command_line (char *cmdl) Line 1802  fm_parse_command_line (char *cmdl)
1802    
1803          case PGP_SIG:          case PGP_SIG:
1804          case PGP_CLEARSIG:          case PGP_CLEARSIG:
             file_verify_use_event ();  
1805              if (type == PGP_SIG)                  if (type == PGP_SIG)    
1806                  detached = 1;                  detached = 1;
1807              fm_verify (ctx, detached, fn);              fm_verify (ctx, detached, fn);
1808              file_verify_wait ();              file_verify_wait ();
1809              break;              break;
1810    
1811            default:
1812                break;
1813          }          }
1814      }      }
1815    
# Line 1763  fm_parse_command_line (char *cmdl) Line 1820  fm_parse_command_line (char *cmdl)
1820  }  }
1821    
1822    
1823    /* Extract the last folder name from @name. */
1824  const char*  const char*
1825  default_dirname (const char *name)  default_dirname (const char *name)
1826  {  {
1827      char * p = strrchr( name, '\\' );      char *p = strrchr (name, '\\');
1828      if( !p )      if (!p)
1829          return NULL;          return NULL;
1830      return p+1;      return p+1;
1831  } /* default_dirname */  }
1832    
1833    
1834    /* Store all selected files from @lv in a zip archive
1835       and encrypt the zip archive then.
1836       Return value: 0 on success. */
1837    int
1838    fm_encrypt_into_zip (fm_state_t ctx, listview_ctrl_t lv)
1839    {
1840        PK_FILE_LIST list=NULL;
1841        const char *outfile, *ext;
1842        char *out_enc;
1843        int nitems;
1844        int i, idx = -1;
1845        int rc;
1846    
1847        nitems = listview_count_items (lv, 0);
1848        if (!nitems) {
1849            msg_box (NULL, _("Encrypting into a ZIP archive makes sense with multiple files"),
1850                     _("File Manager"), MB_ERR);
1851            return WPTERR_GENERAL;
1852        }
1853    
1854        outfile = get_filesave_dlg (ctx->dlg, _("Choose File Name for Output"),
1855                                    NULL, "Encrypted_Files.zip");
1856        if (!outfile)
1857            return WPTERR_GENERAL;
1858    
1859        for (i=0; i < nitems; i++) {
1860            char name[300];
1861            if (!listview_get_item_state (lv, i))
1862                continue;
1863            if (idx == -1)
1864                idx = i;
1865            listview_get_item_text (lv, i, 1, name, sizeof (name)-1);
1866            pk_list_add (&list, name);
1867        }    
1868    
1869        pk_archiv_create (list, outfile);
1870        pk_list_free (list);
1871    
1872        rc = fm_encrypt (ctx, outfile, 0);
1873        DeleteFile (outfile);
1874        if (rc)
1875            return rc;
1876    
1877        ext = file_get_extension (ctx->ctx, ctx->sigmode)+1;
1878        out_enc = make_filename (NULL, outfile, ext);
1879        fm_set_status (lv, idx, FM_ENCRYPT, (gpgme_sig_mode_t)0, 1, out_enc);
1880        free_if_alloc (out_enc);
1881    
1882        for (i=0; i < nitems; i++) {
1883            if (i != idx && listview_get_item_state (lv, i))
1884                listview_del_item (lv, i);
1885        }
1886        return 0;
1887    }
1888    
1889    
1890  int  int
1891  fm_encrypt_directory( fm_state_t c, const char * name )  fm_encrypt_directory (fm_state_t c, const char *name)
1892  {  {
1893      PK_FILE_LIST list = NULL;      PK_FILE_LIST list = NULL;
1894      WIN32_FIND_DATA findbuf;      WIN32_FIND_DATA findbuf;
# Line 1783  fm_encrypt_directory( fm_state_t c, cons Line 1897  fm_encrypt_directory( fm_state_t c, cons
1897      char * patt = NULL, * p;      char * patt = NULL, * p;
1898      int rc = 0;      int rc = 0;
1899            
1900      if( !is_directory( name ) )          if (!is_directory (name))
1901          return -1;          return -1;
1902      patt = new char[strlen( name ) + 4];      patt = new char[strlen (name) + 4];
1903      if( !patt )      if (!patt)
1904          BUG( NULL );          BUG (NULL);
1905      strcpy( patt, name );      strcpy (patt, name);
1906      strcat( patt, "\\*" );      strcat (patt, "\\*");
1907      hd = FindFirstFile( patt, &findbuf );          hd = FindFirstFile (patt, &findbuf);
1908      if( !hd ) {      if (!hd) {
1909          free_if_alloc( patt );            free_if_alloc (patt);
1910          return -1;                return WPTERR_GENERAL;
1911      }      }
1912      if( strcmp( findbuf.cFileName, "." ) && strcmp( findbuf.cFileName, ".." ) ) {      if( strcmp( findbuf.cFileName, "." ) && strcmp( findbuf.cFileName, ".." ) ) {
1913          p = make_filename( name, findbuf.cFileName, NULL );          p = make_filename( name, findbuf.cFileName, NULL );
# Line 1807  fm_encrypt_directory( fm_state_t c, cons Line 1921  fm_encrypt_directory( fm_state_t c, cons
1921              free_if_alloc( p );              free_if_alloc( p );
1922          }          }
1923      }      }
1924      s = get_filename_dlg( c->dlg, FILE_SAVE, _("Choose a Name for the Archive"),      s = get_filesave_dlg (c->dlg, _("Choose a Name for the Archive"),
1925                            NULL, default_dirname( name ) );                            NULL, default_dirname (name));
1926      if( !s ) {      if( !s ) {
1927          msg_box( c->dlg, _("Invalid archive name. Exit."), _("Encrypt Directory"), MB_ERR );          msg_box( c->dlg, _("Invalid archive name. Exit."), _("Encrypt Directory"), MB_ERR );
1928          rc = -1;          rc = -1;
# Line 1820  fm_encrypt_directory( fm_state_t c, cons Line 1934  fm_encrypt_directory( fm_state_t c, cons
1934          msg_box( c->dlg, _("Could not create zip archive."), _("Encrypt Directory"), MB_ERR );          msg_box( c->dlg, _("Could not create zip archive."), _("Encrypt Directory"), MB_ERR );
1935      else {      else {
1936          fm_encrypt( c, s, 0 );          fm_encrypt( c, s, 0 );
1937          unlink( s );          remove( s );
1938      }      }
1939  leave:  leave:
1940      FindClose (hd);      FindClose (hd);
1941      pk_list_free( list );      pk_list_free( list );
1942      free_if_alloc( patt );      free_if_alloc( patt );
1943      return rc;      return rc;
1944  } /* fm_encrypt_directory */  }
1945    
1946    
1947  static int CALLBACK  static int CALLBACK
1948  fm_cmp_cb( LPARAM first, LPARAM second, LPARAM sortby )  fm_cmp_cb (LPARAM first, LPARAM second, LPARAM sortby)
1949  {  {
1950      const char * a = 0, * b = 0;      const char *a = 0;
1951        const char *b = 0;
1952    
1953      switch( (int)sortby ) {      switch ((int)sortby) {
1954      case FM_SORT_STAT:      case FM_SORT_STAT:
1955          break;          break;
1956      case FM_SORT_NAME:      case FM_SORT_NAME:
# Line 1843  fm_cmp_cb( LPARAM first, LPARAM second, Line 1958  fm_cmp_cb( LPARAM first, LPARAM second,
1958      case FM_SORT_OP:      case FM_SORT_OP:
1959          break;          break;
1960      }      }
1961      return stricmp( a, b );      return stricmp (a, b);
1962  } /* fm_cmp_cb */  }
1963                    
1964    
1965    /* Sort the list items from @lv with the mode given by @sortby. */
1966  int  int
1967  fm_sort( listview_ctrl_t lv, int sortby )  fm_sort (listview_ctrl_t lv, int sortby)
1968  {  {
1969      return listview_sort_items( lv, sortby, fm_cmp_cb );      return listview_sort_items (lv, sortby, fm_cmp_cb);
1970  } /* fm_sort */  }
1971    
1972    
1973    /* Start the 'print md' dialog. Pass over the listview control
1974       @lv and the digest algo @mdalgo. */
1975  void  void
1976  fm_print_md( listview_ctrl_t lv, HWND dlg, int mdalgo )  fm_print_md (listview_ctrl_t lv, HWND dlg, int mdalgo)
1977  {  {
1978      struct md_file_s mdctx;      struct md_file_s mdctx;
1979    
1980      if( listview_count_items( lv, 0 ) == 0 )      if (listview_count_items (lv, 0) == 0)
1981          return;          return;
1982      memset (&mdctx, 0, sizeof (mdctx));      memset (&mdctx, 0, sizeof (mdctx));
1983      mdctx.lv = lv;      mdctx.lv = lv;
1984      mdctx.mdalgo = mdalgo;      mdctx.mdalgo = mdalgo;
1985      DialogBoxParam( glob_hinst, (LPCTSTR)IDD_WINPT_FILE_MDSUM, dlg,      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_FILE_MDSUM, dlg,
1986                      mdsum_dlg_proc, (LPARAM)&mdctx );                      mdsum_dlg_proc, (LPARAM)&mdctx);
1987  } /* fm_print_md */  }
1988    
1989    
1990    /* Send the selected file in @lv via MAPI to a mail recipient. */
1991  int  int
1992  fm_send_file (listview_ctrl_t lv)  fm_send_file (listview_ctrl_t lv)
1993  {  {
# Line 1876  fm_send_file (listview_ctrl_t lv) Line 1995  fm_send_file (listview_ctrl_t lv)
1995      int rc;      int rc;
1996    
1997      rc = listview_get_item_text (lv, -1, 1, buf, sizeof (buf)-1);      rc = listview_get_item_text (lv, -1, 1, buf, sizeof (buf)-1);
1998      if (rc == -1)      if (rc != -1)
1999          return 0;          mapi_send_ascfile (buf);
     /*mapi_send_ascfile (buf); XXX */  
2000      return 0;      return 0;
2001  }  }

Legend:
Removed from v.47  
changed lines
  Added in v.211

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26