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

Diff of /trunk/Src/wptKeyEditDlgs.cpp

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

revision 16 by twoaday, Mon May 9 08:54:21 2005 UTC revision 25 by twoaday, Wed Oct 12 10:04:26 2005 UTC
# Line 35  Line 35 
35  #include "wptKeylist.h"  #include "wptKeylist.h"
36  #include "wptKeyManager.h"  #include "wptKeyManager.h"
37  #include "wptRegistry.h"  #include "wptRegistry.h"
38    #include "wptKeyEdit.h"
39    
40    /* All edit key commands. */
41  enum keyedit_commands {      enum keyedit_commands {    
42      CMD_ADDKEY = 0,      CMD_ADDKEY = 0,
43      CMD_ADDUID,      CMD_ADDUID,
# Line 50  enum keyedit_commands { Line 52  enum keyedit_commands {
52      /*CMD_PREF,*/      /*CMD_PREF,*/
53      CMD_SHOWPREF,      CMD_SHOWPREF,
54      /*CMD_SETPREF,*/      /*CMD_SETPREF,*/
55      CMD_UPDPREF,      /*CMD_UPDPREF,*/
56      CMD_PASSWD,      CMD_PASSWD,
57      CMD_PRIMARY,      CMD_PRIMARY,
58      CMD_TRUST,      CMD_TRUST,
# Line 63  enum keyedit_commands { Line 65  enum keyedit_commands {
65  };  };
66    
67    
68    /* Symbolic ids for the subkey columns. */
69    enum {
70        SUBK_COL_DESC       = 0,
71        SUBK_COL_KEYID      = 1,    
72        SUBK_COL_CREATION   = 2,    
73        SUBK_COL_EXPIRES    = 3,
74        SUBK_COL_STATUS     = 4,
75        SUBK_COL_C_FLAG     = 5,
76        SUBK_COL_S_FLAG     = 6,
77        SUBK_COL_E_FLAG     = 7,
78        SUBK_COL_A_FLAG     = 8
79    };
80    
81    /* Symbolic ids for the userid columns. */
82    enum {
83        UID_COL_VALID       = 0,
84        UID_COL_NAME        = 1,
85        UID_COL_EMAIL       = 2,
86        UID_COL_CREATION    = 3
87    };
88    
89  struct keyedit_callback_s {  struct keyedit_callback_s {
90      gpgme_editkey_t ek;      const char     *keyid;
91      const char * pass;      const char     *pass;
92      listview_ctrl_t lv;      listview_ctrl_t lv;
93      void * opaque;      void           *opaque;
94        unsigned int    finished:1;
95  };  };
96  typedef struct keyedit_callback_s KEYEDIT_CB;  typedef struct keyedit_callback_s KEYEDIT_CB;
97    
98  struct keygen_callback_s {  struct keygen_callback_s {
99      int bits;      int   bits;
100      int algo;      int   algo;
101      u32 expire;      u32   expire;
102      char * fpr;      char *fpr;
103  };  };
104  typedef struct keygen_callback_s KEYGEN_CB;  typedef struct keygen_callback_s KEYGEN_CB;
105    
# Line 83  typedef struct keygen_callback_s KEYGEN_ Line 107  typedef struct keygen_callback_s KEYGEN_
107  static subclass_s keyedit_subkey_proc;  static subclass_s keyedit_subkey_proc;
108  static subclass_s keyedit_uid_proc;  static subclass_s keyedit_uid_proc;
109    
110  int keygen_check_date( SYSTEMTIME * st );  int keygen_check_date (SYSTEMTIME *st);
111  void get_userid_preflist (char ** r_prefs, int * r_flags);  void get_userid_preflist (char **r_prefs, int * r_flags);
112    char* get_subkey_fingerprint (const char *keyid);
113    
114    
115    /* Associate each key with a combo box entry.
116       Skip the key in @k. */
117  static void  static void
118  do_init_keylist (HWND dlg, winpt_key_t k)  do_init_keylist (HWND dlg, winpt_key_t k)
119  {  {
120      gpgme_keycache_t pub;      gpg_keycache_t pub;
121      gpgme_key_t key;      gpgme_key_t key;
122      const char * s, * kid;      const char * s, * kid;
123      char * u;      char * u;
# Line 99  do_init_keylist (HWND dlg, winpt_key_t k Line 127  do_init_keylist (HWND dlg, winpt_key_t k
127      if (!pub)      if (!pub)
128          BUG (0);          BUG (0);
129    
130      while( !gpgme_keycache_next_key( pub, 0, &key ) ) {      gpg_keycache_rewind (pub);
131          s = gpgme_key_get_string_attr( key, GPGME_ATTR_USERID, NULL, 0 );      while( !gpg_keycache_next_key( pub, 0, &key ) ) {
132          kid = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, NULL, 0);          s = key->uids->uid;
133            kid = key->subkeys->keyid;
134          if (!s || !strcmp (kid+8, k->keyid+2))          if (!s || !strcmp (kid+8, k->keyid+2))
135              continue;              continue;
136          u = utf8_to_wincp (s, strlen (s));          u = utf8_to_wincp (s, strlen (s));
137          SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_ADDSTRING,          SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_ADDSTRING,
138                              0, (WPARAM)(char *)u);                              0, (WPARAM)(char *)u);
139          free( u );          free (u);
140      }      }
141      gpgme_keycache_rewind( pub );      gpg_keycache_rewind (pub);
142      n = SendDlgItemMessage( dlg, IDC_ADDREV_KEYLIST, CB_GETCOUNT, 0, 0 );      n = SendDlgItemMessage( dlg, IDC_ADDREV_KEYLIST, CB_GETCOUNT, 0, 0 );
143      for( i = 0; i < n; i++ ) {      for (i = 0; i < n; i++) {
144          gpgme_keycache_next_key( pub, 0, &key );          gpg_keycache_next_key (pub, 0, &key);
145          SendDlgItemMessage( dlg, IDC_ADDREV_KEYLIST, CB_SETITEMDATA,          SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETITEMDATA,
146                              (WPARAM)(int)i, (LPARAM)key );                              (WPARAM)(int)i, (LPARAM)key);
147      }      }
148      SendDlgItemMessage( dlg, IDC_ADDREV_KEYLIST, CB_SETCURSEL, 0, 0 );      SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETCURSEL, 0, 0);
149  } /* do_init_keylist */  }
150    
151    
152    /* Add a new user-id to the list view @lv. */
153  static void  static void
154  do_add_new_userid (listview_ctrl_t lv, const char * name, const char *email,  do_add_new_userid (listview_ctrl_t lv,
155                     const char * comment )                     const char * name, const char *email, const char * comment)
156  {  {
157      char * p;      char * p;
158      size_t n;      size_t n;
# Line 148  do_add_new_userid (listview_ctrl_t lv, c Line 178  do_add_new_userid (listview_ctrl_t lv, c
178    
179    
180  static void  static void
181  do_add_new_subkey (listview_ctrl_t lv, KEYGEN_CB * keygen, unsigned int flags)  do_add_new_subkey (listview_ctrl_t lv, KEYGEN_CB *keygen, unsigned int flags)
182  {  {
183      char info[128], keyid[32];      char info[128], keyid[32];
184      const char * expdate, * s;      const char * expdate, * s;
# Line 157  do_add_new_subkey (listview_ctrl_t lv, K Line 187  do_add_new_subkey (listview_ctrl_t lv, K
187      expdate = keygen->expire? get_key_expire_date (keygen->expire) : _("Never");      expdate = keygen->expire? get_key_expire_date (keygen->expire) : _("Never");
188      _snprintf (info, sizeof info-1, "%d-bit %s",      _snprintf (info, sizeof info-1, "%d-bit %s",
189                 keygen->bits,                 keygen->bits,
190                 gpgme_key_expand_attr (GPGME_ATTR_ALGO, keygen->algo));                 get_key_pubalgo ((gpgme_pubkey_algo_t)keygen->algo));
191      _snprintf (keyid, sizeof keyid-1, "0x%s", keygen->fpr+32);      _snprintf (keyid, sizeof keyid-1, "0x%s", keygen->fpr+32);
192      n = listview_count_items (lv, 0);      n = listview_count_items (lv, 0);
193      listview_add_item_pos (lv, n);      listview_add_item_pos (lv, n);
# Line 172  do_add_new_subkey (listview_ctrl_t lv, K Line 202  do_add_new_subkey (listview_ctrl_t lv, K
202  } /* do_add_new_subkey */  } /* do_add_new_subkey */
203    
204    
205    /* Try to find the GPG edit key index which belongs to the user ID
206       given by @name. If @r_inf != NULL, the info context will be returned.
207       Return value: index of the user ID or -1 on error. */
208  static int  static int
209  do_find_userid (const char * keyid, const char * name, gpgme_uidinfo_t *r_inf)  do_find_userid (const char *keyid, const char *name, gpg_uid_info_t *r_inf)
210  {  {
211      gpgme_uidinfo_t inf;      GpgKeyEdit *ke;
     gpgme_ctx_t ctx;  
212      gpgme_error_t err;      gpgme_error_t err;
213      int nitems = 0, pos = -1;      gpg_uid_info_t inf, ui;
214      const char * s;      int pos = -1;
215    
216      err = gpgme_new (&ctx);      ke = new GpgKeyEdit (keyid);
217      if (err)      if (!ke)
218          BUG (0);          BUG (NULL);
219      err = gpgme_op_editkey_get_info (ctx, keyid, &inf);      err = ke->getUseridInfo (&inf);
220        delete ke;
221      if (err) {      if (err) {
222          log_box (_("user ID"), MB_ERR, _("Could not get key information for: \"%s\""), name);          log_box (_("user ID"), MB_ERR,
223          gpgme_release (ctx);                  _("Could not get key information for: \"%s\":\n%s"),
224                    name, gpgme_strerror (err));
225          return -1;          return -1;
226      }      }
227      gpgme_release (ctx);  
228      nitems = gpgme_editkey_count_items (inf);          for (ui = inf; ui; ui = ui->next) {
229      while (nitems--) {          if (!strcmp (ui->email, name)) {
230          s = gpgme_editkey_get_string_attr (inf, GPGME_ATTR_EMAIL, nitems);              pos = ui->index;
         if (!s)  
             continue;  
           
         if (!strcmp (s, name)) {  
             pos = gpgme_editkey_get_ulong_attr (inf, GPGME_ATTR_LEVEL, nitems);  
231              break;              break;
232          }          }
233      }      }
   
234      if (r_inf)      if (r_inf)
235          *r_inf = inf;          *r_inf = inf;
236      else      else
237          gpgme_uid_info_release (inf);          gpg_uid_info_release (inf);
238      return pos;      return pos;
239  } /* do_find_userid */  }
240    
241    
242    /* Dialog box procedure to add a photo. */
243  BOOL CALLBACK  BOOL CALLBACK
244  keyedit_addphoto_dlg_proc( HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam )  keyedit_addphoto_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
245  {  {
246      static winpt_key_t k;          static winpt_key_t k;        
247      gpgme_editkey_t ek;      GpgKeyEdit *ke;
248      gpgme_error_t ec;      gpgme_error_t ec;    
     gpgme_ctx_t ctx;  
249      const char * s;          const char * s;    
250      char pwd[128], file[128];      char pwd[128], file[128];
251      int id;      int id;
# Line 225  keyedit_addphoto_dlg_proc( HWND dlg, UIN Line 253  keyedit_addphoto_dlg_proc( HWND dlg, UIN
253      switch( msg ) {      switch( msg ) {
254      case WM_INITDIALOG:      case WM_INITDIALOG:
255          k = (winpt_key_t)lparam;          k = (winpt_key_t)lparam;
256          if( !k )          if (!k)
257              BUG( NULL );              BUG (NULL);
258          SetDlgItemText (dlg, IDC_ADDPHOTO_INF, _("Remember that the image is stored within your public key.  If you use a very large picture, your key will become very large as well! Keeping the image close to 240x288 is a good size to use."));          SetDlgItemText (dlg, IDC_ADDPHOTO_INF, _("Remember that the image is stored within your public key.  If you use a very large picture, your key will become very large as well! Keeping the image close to 240x288 is a good size to use."));
259          SetDlgItemText (dlg, IDC_ADDPHOTO_FILEINF, _("Pick an image to use for your photo ID.\nThe image must be a JPEG file."));          SetDlgItemText (dlg, IDC_ADDPHOTO_FILEINF, _("Pick an image to use for your photo ID.\nThe image must be a JPEG file."));
260          SetDlgItemText (dlg, IDC_ADDPHOTO_PWDINF, _("Passphrase"));          SetDlgItemText (dlg, IDC_ADDPHOTO_PWDINF, _("Passphrase"));
# Line 268  keyedit_addphoto_dlg_proc( HWND dlg, UIN Line 296  keyedit_addphoto_dlg_proc( HWND dlg, UIN
296                      return FALSE;                      return FALSE;
297                  }                  }
298              }              }
299              ec = gpgme_editkey_new( &ek );              ke = new GpgKeyEdit (k->keyid);
300              if( !ec )              if (!ke)
301                  ec = gpgme_new( &ctx );                  BUG (NULL);
302              if( ec )  
303                  BUG( NULL );              if (k->is_protected)
304              gpgme_enable_logging( ctx );                  ke->setPassphrase (pwd);
305              gpgme_editkey_addphoto_set( ek, file, k->is_protected? pwd : NULL );              ec = ke->addPhotoid (file);
306              gpgme_set_edit_ctx( ctx, ek, GPGME_EDITKEY_ADDPHOTO );              delete ke;
307              ec = gpgme_op_editkey( ctx, k->keyid );              memset (pwd, 0, sizeof pwd);
308              gpgme_editkey_release( ek );              if (ec) {
309              if( ec ) {                  msg_box (dlg, gpgme_strerror (ec), _("Add Photo"), MB_ERR );
                 gpgme_show_error( dlg, ec, ctx, _("Add Photo"), MB_ERR );  
                 gpgme_release( ctx );  
310                  return FALSE;                  return FALSE;
311              }              }
312              else {              else {
313                  keycache_set_reload( 1 );                  k->update = 1;
314                  msg_box( dlg, _("Photo successfully added."), _("GnuPG Status"), MB_OK );                  msg_box (dlg, _("Photo successfully added."), _("GnuPG Status"), MB_OK);
315              }              }
316              gpgme_release( ctx );              EndDialog (dlg, TRUE);
             EndDialog( dlg, TRUE );  
317              break;              break;
318    
319          case IDCANCEL:          case IDCANCEL:
320              EndDialog( dlg, FALSE );              EndDialog (dlg, FALSE);
321              break;              break;
322          }          }
323          break;          break;
324      }      }
325      return FALSE;      return FALSE;
326  } /* keyedit_addphoto_dlg_proc */  }
327    
328    
329    /* Dialog box procedure to add a designated revoker. */
330  BOOL CALLBACK  BOOL CALLBACK
331  keyedit_addrevoker_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  keyedit_addrevoker_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
332  {  {
333      static winpt_key_t k;      static winpt_key_t k;
334      static gpgme_key_t seckey;          static gpgme_key_t seckey;    
335      gpgme_editkey_t ek;      GpgKeyEdit *ke;
336      gpgme_ctx_t ctx;      gpgme_error_t err;
     gpgme_error_t ec;      
337      char uid[128], pwd[128];      char uid[128], pwd[128];
338            
339    
# Line 319  keyedit_addrevoker_dlg_proc (HWND dlg, U Line 344  keyedit_addrevoker_dlg_proc (HWND dlg, U
344              BUG( NULL );              BUG( NULL );
345          if( get_seckey( k->keyid, &seckey ) )            if( get_seckey( k->keyid, &seckey ) )  
346              BUG( NULL );              BUG( NULL );
347          if( !k->is_protected )          if (!k->is_protected)
348              EnableWindow( GetDlgItem( dlg, IDC_ADDREV_PASS ), FALSE );              EnableWindow (GetDlgItem (dlg, IDC_ADDREV_PASS), FALSE);
349          do_init_keylist( dlg, k );          do_init_keylist (dlg, k);
350          SetDlgItemText (dlg, IDC_ADDREV_INF, _("Appointing a key as designated revoker cannot be undone."));          SetDlgItemText (dlg, IDC_ADDREV_INF, _("Appointing a key as designated revoker cannot be undone."));
351          SetDlgItemText (dlg, IDC_ADDREV_KEYINF, _("Public key"));          SetDlgItemText (dlg, IDC_ADDREV_KEYINF, _("Public key"));
352          SetDlgItemText (dlg, IDC_ADDREV_PWDINF, _("Passphrase"));          SetDlgItemText (dlg, IDC_ADDREV_PWDINF, _("Passphrase"));
# Line 350  keyedit_addrevoker_dlg_proc (HWND dlg, U Line 375  keyedit_addrevoker_dlg_proc (HWND dlg, U
375                      return FALSE;                      return FALSE;
376                  }                  }
377              }              }
378              ec = gpgme_editkey_new( &ek );              ke = new GpgKeyEdit (k->keyid);
379              if( !ec )              if (k->is_protected)
380                  ec = gpgme_new( &ctx );                  ke->setPassphrase (pwd);
381              if( ec )              err = ke->addDesignatedRevoker (uid);
382                  BUG( NULL );              delete ke;
383              gpgme_enable_logging( ctx );              memset (pwd, 0, sizeof pwd);
384              gpgme_editkey_addrev_set( ek, uid, k->is_protected? pwd : NULL );              if (err) {
385              gpgme_set_edit_ctx( ctx, ek, GPGME_EDITKEY_ADDREV );                  msg_box (dlg, gpgme_strerror (err), _("Add Revoker"), MB_ERR);
386              ec = gpgme_op_editkey( ctx, k->keyid );                  return TRUE;
             gpgme_editkey_release( ek );  
             memset( pwd, 0, sizeof pwd );  
             if( ec ) {  
                 gpgme_show_error( dlg, ec, ctx, _("Add Revoker"), MB_ERR );  
                 gpgme_release( ctx );  
                 return FALSE;  
387              }              }
388              else {              else {
389                  msg_box( dlg, _("Revoker successfully addded."), _("GnuPG Status"), MB_OK );                  k->update = 1;
390                  keycache_set_reload( 1 );                  msg_box (dlg, _("Revoker successfully addded."), _("GnuPG Status"), MB_OK);
391              }              }
             gpgme_release( ctx );  
392              EndDialog( dlg, TRUE );              EndDialog( dlg, TRUE );
393              break;              break;
394    
# Line 381  keyedit_addrevoker_dlg_proc (HWND dlg, U Line 399  keyedit_addrevoker_dlg_proc (HWND dlg, U
399          break;          break;
400      }      }
401      return FALSE;      return FALSE;
402  } /* keyedit_addrevoker_dlg_proc */  }
403    
404    
405    /* Dialog box procedure to add a new user-ID. */
406  BOOL CALLBACK  BOOL CALLBACK
407  keyedit_adduid_dlg_proc( HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam )  keyedit_adduid_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
408  {  {
409      static KEYEDIT_CB *ctx;      static KEYEDIT_CB *ctx;
410        gpgme_error_t err;
411        GpgKeyEdit *ke;
412      char *utf8_name = NULL;      char *utf8_name = NULL;
413      char name[128], email[128], comment[128];      char name[128], email[128], comment[128];
414      int rc;      int rc;
# Line 407  keyedit_adduid_dlg_proc( HWND dlg, UINT Line 428  keyedit_adduid_dlg_proc( HWND dlg, UINT
428          return FALSE;          return FALSE;
429                    
430      case WM_SYSCOMMAND:      case WM_SYSCOMMAND:
431          if( LOWORD (wparam) == SC_CLOSE ) {          if (LOWORD (wparam) == SC_CLOSE) {
             gpgme_editkey_make_invalid( ctx->ek );  
432              EndDialog(dlg, TRUE);              EndDialog(dlg, TRUE);
433          }          }
434          return FALSE;          return FALSE;
# Line 417  keyedit_adduid_dlg_proc( HWND dlg, UINT Line 437  keyedit_adduid_dlg_proc( HWND dlg, UINT
437          switch ( LOWORD( wparam ) )  {          switch ( LOWORD( wparam ) )  {
438          case IDOK:          case IDOK:
439              rc = GetDlgItemText( dlg, IDC_ADDUID_NAME, name, sizeof name-1 );              rc = GetDlgItemText( dlg, IDC_ADDUID_NAME, name, sizeof name-1 );
440              if( !rc || rc < 5 ) {              if (!rc || rc < 5) {
441                  msg_box( dlg, _("Please enter a name (min. 5 chars.)"), _("UserID"), MB_ERR );                  msg_box( dlg, _("Please enter a name (min. 5 chars.)"), _("UserID"), MB_ERR );
442                  return FALSE;                  return FALSE;
443              }              }
444              if( strchr( name, '@' ) ) {              if (strchr (name, '@')) {
445                  msg_box( dlg, _("Please enter the email address in the email field and not in the name field"), _("UserID"), MB_INFO );                  msg_box( dlg, _("Please enter the email address in the email field and not in the name field"), _("UserID"), MB_INFO );
446                  return FALSE;                  return FALSE;
447              }              }
# Line 430  keyedit_adduid_dlg_proc( HWND dlg, UINT Line 450  keyedit_adduid_dlg_proc( HWND dlg, UINT
450                  msg_box( dlg, _("Please enter an email address."), _("UserID"), MB_ERR );                  msg_box( dlg, _("Please enter an email address."), _("UserID"), MB_ERR );
451                  return FALSE;                  return FALSE;
452              }              }
453              if( !strchr( email, '@' ) ) {              if( !strchr( email, '@' ) || strchr (email, ' ')) {
454                  msg_box( dlg, _("Invalid email address."), _("UserID"), MB_ERR );                  msg_box( dlg, _("Invalid email address."), _("UserID"), MB_ERR );
455                  return FALSE;                  return FALSE;
456              }              }
457                            
458              rc = GetDlgItemText( dlg, IDC_ADDUID_COMMENT, comment, sizeof comment -1 );              rc = GetDlgItemText( dlg, IDC_ADDUID_COMMENT, comment, sizeof comment -1 );
459    
460              /* xxx: something is wrong with the encoding :-( */              /* XXX: something is wrong with the encoding :-( */
461              utf8_name = wincp_to_utf8 (name, strlen (name));              utf8_name = wincp_to_utf8 (name, strlen (name));
462    
463              gpgme_editkey_adduid_set( ctx->ek, utf8_name? utf8_name : name, email,              ke = new GpgKeyEdit (ctx->keyid);
464                                        rc? comment: NULL, ctx->pass );              if (!ke)
465                    BUG (NULL);
466                if (ctx->pass)
467                    ke->setPassphrase (ctx->pass);
468                err = ke->addUserid (utf8_name? utf8_name : name,
469                                     rc > 0? comment : NULL, email);
470                if (err)
471                    msg_box (dlg, gpgme_strerror (err), _("UserID"), MB_ERR);
472                else {
473                    msg_box (dlg, _("user ID successfully added."), _("GnuPG Status"), MB_OK);
474                    ctx->finished = 1;
475                }
476                delete ke;
477              free (utf8_name);              free (utf8_name);
478              if (ctx->lv)              if (!err && ctx->lv)
479                  do_add_new_userid (ctx->lv, name, email, rc?comment : NULL);                  do_add_new_userid (ctx->lv, name, email, rc?comment : NULL);
480              EndDialog( dlg, TRUE );              EndDialog (dlg, TRUE);
481              return TRUE;              return TRUE;
482                            
483          case IDCANCEL:          case IDCANCEL:
484              gpgme_editkey_make_invalid( ctx->ek );              EndDialog (dlg, FALSE);
             EndDialog( dlg, FALSE );  
485              return FALSE;              return FALSE;
486          }          }
487          break;          break;
488      }      }
489            
490      return FALSE;      return FALSE;
491  } /* keyedit_adduid_dlg_proc */  }
492    
493    
494    static int
495    diff_time (HWND dt, SYSTEMTIME *in_exp)
496    {
497        SYSTEMTIME exp, now;
498        double e=0, n=0;
499    
500        if (in_exp)
501            memcpy (&exp, in_exp, sizeof (SYSTEMTIME));
502        else
503            DateTime_GetSystemtime (dt, &exp);
504        GetSystemTime (&now);
505        SystemTimeToVariantTime (&exp, &e);
506        SystemTimeToVariantTime (&now, &n);
507        if (n > e)
508            return 0;
509        return (int)(e-n);
510    }
511    
512    
513    static void
514    init_keysize_box (HWND dlg, int ctlid)
515    {
516        const char *sizelist[] = {
517            "1024", "1536", "2048", "2560", "3072", "3854", "4096", NULL
518        };
519        int i;
520        for (i=0; sizelist[i] != NULL; i++)
521            SendDlgItemMessage (dlg, ctlid, CB_ADDSTRING, 0, (LPARAM)(char*)sizelist[i]);
522        SendDlgItemMessage (dlg, ctlid, CB_SETCURSEL, (WPARAM)2, 0);
523    }
524    
525    static int
526    get_keysize_from_box (HWND dlg, int ctlid)
527    {
528        int pos;
529        char buf[32];
530    
531        pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0);
532        if (pos == CB_ERR)
533            return -1;
534        SendDlgItemMessage (dlg, ctlid, CB_GETLBTEXT, pos, (LPARAM)(char*)buf);
535        return atol (buf);
536    }
537    
538    
539  BOOL CALLBACK  BOOL CALLBACK
540  keyedit_addsubkey_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  keyedit_addsubkey_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
541  {  {
542      static KEYEDIT_CB * ctx;      static KEYEDIT_CB *ctx;
543      static KEYGEN_CB * keygen;      static KEYGEN_CB *keygen;
544      gpgme_error_t rc;      GpgKeyEdit *ke;
545      int index, size, valid;      gpgme_error_t err;
546      HWND lb;      HWND lb;
547        int index, size, valid;
548            
549      switch ( msg ) {      switch (msg) {
550      case WM_INITDIALOG:      case WM_INITDIALOG:
551          ctx = (KEYEDIT_CB *)lparam;          ctx = (KEYEDIT_CB *)lparam;
552          if( !ctx )          if (!ctx)
553              dlg_fatal_error( dlg, "Could not get dialog param!" );              dlg_fatal_error (dlg, "Could not get dialog param!");
554          keygen = (KEYGEN_CB *)ctx->opaque;          keygen = (KEYGEN_CB *)ctx->opaque;
555  #ifndef LANG_DE  #ifndef LANG_DE
556          SetWindowText( dlg, _("Add new Subkey") );          SetWindowText (dlg, _("Add new Subkey"));
557          SetDlgItemText( dlg, IDC_ADDSUBKEY_INFALGO, _("Key type") );          SetDlgItemText (dlg, IDC_ADDSUBKEY_INFALGO, _("Key type"));
558          SetDlgItemText( dlg, IDC_ADDSUBKEY_INFSIZE, _("Size") );          SetDlgItemText (dlg, IDC_ADDSUBKEY_INFSIZE, _("Size in bits"));
559          SetDlgItemText( dlg, IDC_ADDSUBKEY_INFVALID,          SetDlgItemText (dlg, IDC_ADDSUBKEY_INFVALID, _("Key expiration"));
                         _("Valid for 'n' days. 0 means forever") );  
560  #endif  #endif
561          lb = GetDlgItem( dlg, IDC_ADDSUBKEY_ALGO );          lb = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
562          listbox_add_string( lb, "DSA (sign only)");          listbox_add_string (lb, "DSA (sign only)");
563          listbox_add_string( lb, "ElGamal (encrypt only)" );          listbox_add_string (lb, "ElGamal (encrypt only)");
564          listbox_add_string( lb, "RSA (sign only)");          listbox_add_string (lb, "RSA (sign only)");
565          listbox_add_string( lb, "RSA (encrypt only)" );          listbox_add_string (lb, "RSA (encrypt only)");
566          SetDlgItemInt( dlg, IDC_ADDSUBKEY_VALID, 0, FALSE );          CheckDlgButton (dlg, IDC_ADDSUBKEY_EXPIRE, BST_CHECKED);
567          SetDlgItemInt( dlg, IDC_ADDSUBKEY_SIZE, DFAULT_KEYSIZE, FALSE );          EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
568            init_keysize_box (dlg, IDC_ADDSUBKEY_SIZE);
569          SetForegroundWindow( dlg );          SetForegroundWindow( dlg );
570          return FALSE;          return FALSE;
571                    
572      case WM_SYSCOMMAND:      case WM_SYSCOMMAND:
573          if( LOWORD (wparam) == SC_CLOSE ) {          if( LOWORD (wparam) == SC_CLOSE ) {
             gpgme_editkey_make_invalid( ctx->ek );  
574              EndDialog( dlg, TRUE );              EndDialog( dlg, TRUE );
575          }          }
576          return FALSE;          return FALSE;
577                    
578      case WM_COMMAND:      case WM_COMMAND:
579            if (HIWORD (wparam) == BN_CLICKED && LOWORD (wparam) == IDC_ADDSUBKEY_EXPIRE) {
580                if (IsDlgButtonChecked (dlg, IDC_ADDSUBKEY_EXPIRE))
581                    EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
582                else
583                    EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), TRUE);
584            }
585            if (HIWORD (wparam) == LBN_SELCHANGE && LOWORD (wparam) == IDC_ADDSUBKEY_ALGO) {
586                index = SendMessage ((HWND)lparam, LB_GETCURSEL, 0, 0);
587                if (index == 0)
588                    SendDlgItemMessage (dlg, IDC_ADDSUBKEY_SIZE, CB_SETCURSEL, 0, 0);
589            }
590    
591          switch ( LOWORD(wparam) ) {                  switch ( LOWORD(wparam) ) {        
592          case IDOK:          case IDOK:
593              lb = GetDlgItem( dlg, IDC_ADDSUBKEY_ALGO );              lb = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
594              switch (listbox_get_cursel (lb)) {              switch (listbox_get_cursel (lb)) {
595              case 0: index = 2; break;              case 0: index = 2; break;
596              case 1: index = 4; break;              case 1: index = 4; break;
# Line 512  keyedit_addsubkey_dlg_proc (HWND dlg, UI Line 600  keyedit_addsubkey_dlg_proc (HWND dlg, UI
600                  msg_box( dlg, _("Please select one entry."), _("Add Subkey"), MB_ERR );                  msg_box( dlg, _("Please select one entry."), _("Add Subkey"), MB_ERR );
601                  return FALSE;                  return FALSE;
602              }              }
603              if (gpgver[0] == 1 && gpgver[1] == 2) { /* GPG 1.2.x kludge */              size = get_keysize_from_box (dlg, IDC_ADDSUBKEY_SIZE);
604                  if (listbox_get_cursel (lb) > 1)              if (index == 2 && size != 1024) {
                     index++;  
             }  
             size = GetDlgItemInt( dlg, IDC_ADDSUBKEY_SIZE, NULL, TRUE );  
             if( !size ) {  
                 msg_box( dlg, _("Please enter the keysize."), _("Add Subkey"), MB_ERR );  
                 return FALSE;  
             }  
             else if (index == 2 && size != 1024) {  
605                  msg_box( dlg,_("DSS uses a fixed keysize of 1024. Size changed."), _("Add Subkey"), MB_INFO );                  msg_box( dlg,_("DSS uses a fixed keysize of 1024. Size changed."), _("Add Subkey"), MB_INFO );
606                  size = 1024;                  size = 1024;
607              }              }
608              else if (size > 4096) {              valid = diff_time (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), NULL);
609                  int id;  
                 msg_box (dlg, _("Chosen size must be between 1024 and 4096."), _("Add Subkey"), MB_ERR);  
                 id = msg_box (dlg, _("Do you really need such a large key?"), _("Add Subkey"), MB_QUEST_ASK);  
                 if (id == IDNO)  
                     size = DFAULT_KEYSIZE;  
                 else  
                     size = 4096;  
                 SetDlgItemInt (dlg, IDC_ADDSUBKEY_SIZE, size, TRUE);  
             }  
             else if (size < 1024) {  
                 msg_box( dlg, _("Keys with a size of less then 1024 are considered insecure.\n"  
                                 "Size changed to 1024!"), _("Add Subkey"), MB_INFO );  
                 size = 1024;  
             }  
             valid = GetDlgItemInt (dlg, IDC_ADDSUBKEY_VALID, NULL, TRUE);  
             if (valid < 0) {  
                 msg_box( dlg, _("Please enter the days the key is valid."), _("Add Subkey"), MB_ERR );  
                 return FALSE;  
             }  
             rc = gpgme_editkey_addkey_set (ctx->ek, ctx->pass, index, size, valid);  
             if (rc) {  
                 msg_box (dlg, gpgme_strerror (rc), _("Add Subkey"), MB_ERR);  
                 return FALSE;  
             }  
610              keygen->bits = size;              keygen->bits = size;
611              switch (index) {              switch (index) {
612              case 2: keygen->algo = GPGME_PK_DSA; break;              case 2: keygen->algo = GPGME_PK_DSA; break;
# Line 557  keyedit_addsubkey_dlg_proc (HWND dlg, UI Line 614  keyedit_addsubkey_dlg_proc (HWND dlg, UI
614              case 5: keygen->algo = GPGME_PK_RSA_S; break;              case 5: keygen->algo = GPGME_PK_RSA_S; break;
615              case 6: keygen->algo = GPGME_PK_RSA_E; break;              case 6: keygen->algo = GPGME_PK_RSA_E; break;
616              }              }
617              if (valid)              if (valid > 0)
618                  keygen->expire = time (NULL) + valid*24*60*60;                  keygen->expire = time (NULL) + valid*24*60*60;
619              EndDialog( dlg, TRUE );  
620                ke = new GpgKeyEdit (ctx->keyid);
621                if (!ke)
622                    BUG (NULL);
623                ke->setCallback (keygen_cb, NULL);
624                if (ctx->pass)
625                    ke->setPassphrase (ctx->pass);      
626                keygen_cb_dlg_create ();
627    
628                err = ke->addSubkey ((gpgme_pubkey_algo_t)index, size, valid);
629                keygen->fpr = get_subkey_fingerprint (ctx->keyid);
630                keygen_cb_dlg_destroy ();
631                keygen_cb (NULL, NULL, 0, 0, 0); /* flush */
632                if (err)
633                    msg_box (dlg, gpgme_strerror (err), _("Add Subkey"), MB_ERR);
634                else {
635                    msg_box (dlg, _("Subkey successfully added."), _("GnuPG Status"), MB_OK);
636                    if (ctx->lv)
637                        do_add_new_subkey (ctx->lv, keygen, /*XXXk->flags*/0);
638                    ctx->finished = 1;
639                }
640                delete ke;
641                EndDialog (dlg, TRUE);
642              return TRUE;              return TRUE;
643                            
644          case IDCANCEL:          case IDCANCEL:
             gpgme_editkey_make_invalid( ctx ->ek );  
645              EndDialog( dlg, FALSE );              EndDialog( dlg, FALSE );
646              return FALSE;              return FALSE;
647          }          }
# Line 577  keyedit_addsubkey_dlg_proc (HWND dlg, UI Line 655  keyedit_addsubkey_dlg_proc (HWND dlg, UI
655  BOOL  BOOL
656  keyedit_add_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)  keyedit_add_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
657  {  {
     gpgme_error_t ec;  
     gpgme_ctx_t ctx;  
     gpgme_editkey_t ek;  
658      KEYEDIT_CB cb;      KEYEDIT_CB cb;
659      char * pass = NULL;      char *pass = NULL;
660      int cancel = 0;      int cancel = 0;
661    
662      if (!k->key_pair) {      if (!k->key_pair) {
# Line 591  keyedit_add_userid (winpt_key_t k, HWND Line 666  keyedit_add_userid (winpt_key_t k, HWND
666    
667      if (k->is_protected) {      if (k->is_protected) {
668          pass = request_passphrase( _("Key Edit"), 1, &cancel );          pass = request_passphrase( _("Key Edit"), 1, &cancel );
669          if( cancel )              if (cancel)
670              return FALSE;              return FALSE;
671      }      }
   
     ec = gpgme_editkey_new( &ek );  
     if( ec )  
         BUG( dlg );  
672                        
673      memset( &cb, 0, sizeof cb );      memset (&cb, 0, sizeof cb);
     cb.ek = ek;  
674      cb.pass = k->is_protected? pass : NULL;      cb.pass = k->is_protected? pass : NULL;
675      cb.lv = lv;      cb.lv = lv;
676      dialog_box_param( glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDUID,      cb.keyid = k->keyid;
677        dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDUID,
678                        dlg, keyedit_adduid_dlg_proc,                                dlg, keyedit_adduid_dlg_proc,        
679                       (LPARAM)&cb, _("Add user ID"),                        (LPARAM)&cb, _("Add user ID"),
680                      IDS_WINPT_KEYEDIT_ADDUID );                        IDS_WINPT_KEYEDIT_ADDUID);
681      if( !gpgme_editkey_is_valid( ek ) ) {  
682          free_if_alloc( pass );      if (cb.finished)
683          return FALSE;          k->update = 1;
684      }  
685                    sfree_if_alloc (pass);
     ec = gpgme_new( &ctx );  
     if( ec )  
         BUG( dlg );  
     gpgme_enable_logging( ctx );  
     gpgme_set_edit_ctx( ctx, ek, GPGME_EDITKEY_ADDUID );  
     ec = gpgme_op_editkey( ctx, k->keyid );  
     if( ec )  
         gpgme_show_error( dlg, ec, ctx, _("Add user ID"), MB_ERR );  
     else {  
         msg_box(dlg, _("User ID successfully added"), _("GnuPG Status"), MB_OK );  
         keycache_set_reload( 1 );  
     }  
     gpgme_editkey_release( ek );  
     gpgme_release( ctx );  
     free_if_alloc( pass );  
686      return TRUE;      return TRUE;
687  } /* keyedit_add_userid */  }
688    
689    
690  char*  char*
691  get_subkey_fingerprint (gpgme_ctx_t ctx, const char *keyid)  get_subkey_fingerprint (const char *keyid)
692  {  {
693      static char fpr[40];      static char fpr[40];
     const char *s;  
694      gpgme_error_t err;      gpgme_error_t err;
695      gpgme_key_t key, main;      gpgme_key_t key, main;
696        gpgme_ctx_t ctx;
697        gpgme_subkey_t last_sk, k, new_sk;
698      int n;      int n;
699    
700      /* XXX: this is very slow and complicated */      err = gpgme_new (&ctx);
     err = gpgme_op_keylist_start (ctx, keyid, 0);  
701      if (err)      if (err)
702          return NULL;          return NULL;
703      err = gpgme_op_keylist_next (ctx, &key);      err = gpgme_get_key (ctx, keyid, &key, 0);
704      if (err)      if (err)
705          return NULL;          return NULL;
706        /* XXX: this is very slow and complicated */
707            
708      n = gpgme_key_count_items (key, GPGME_ATTR_KEYID);      n = count_subkeys (key);
709      s = gpgme_key_get_string_attr (key, GPGME_ATTR_FPR, NULL, n-1);      last_sk = get_nth_key (key, n-1);
710      strcpy (fpr, s);      new_sk = (gpgme_subkey_t)calloc (1, sizeof *new_sk);
711        if (!new_sk)
712            BUG (NULL);
713        memcpy (new_sk, last_sk, sizeof *last_sk);
714        new_sk->fpr = strdup (last_sk->fpr);
715        new_sk->keyid = strdup (last_sk->keyid);
716    
717      get_pubkey (keyid, &main);      get_pubkey (keyid, &main);
718      gpgme_key_append (main, key, n-1);      for (k=main->subkeys; k->next; k=k->next)
719            ;
720        k->next = new_sk;
721    
722      gpgme_key_release (key);      gpgme_key_release (key);
723      return fpr;      return new_sk->fpr;
724  }  }
725    
726    
727  BOOL  BOOL
728  keyedit_add_subkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)  keyedit_add_subkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
729  {  {
     gpgme_error_t ec;  
     gpgme_ctx_t ctx;  
     gpgme_editkey_t ek;  
730      KEYEDIT_CB cb;      KEYEDIT_CB cb;
731      KEYGEN_CB keygen;      KEYGEN_CB keygen;
732      char * pass = NULL;      char *pass = NULL;
733      int cancel = 0;      int cancel = 0;
734    
735      if( !k->key_pair ) {      if (!k->key_pair) {
736          msg_box( dlg, _("There is no secret key available!"), _("Add Subkey"), MB_ERR );          msg_box (dlg, _("There is no secret key available!"), _("Add Subkey"), MB_ERR);
737          return FALSE;          return FALSE;
738      }      }
739      if( k->is_protected ) {      if (k->is_protected) {
740          pass = request_passphrase (_("Key Edit"), 1, &cancel);          pass = request_passphrase (_("Key Edit"), 1, &cancel);
741          if( cancel )              if (cancel)
742              return FALSE;              return FALSE;
743      }      }
744      ec = gpgme_editkey_new( &ek );  
     if( ec )  
         BUG( dlg );  
       
745      memset (&keygen, 0, sizeof (keygen));      memset (&keygen, 0, sizeof (keygen));
746      memset (&cb, 0, sizeof (cb));      memset (&cb, 0, sizeof (cb));
747      cb.ek = ek;      cb.keyid = k->keyid;
748      cb.pass = k->is_protected? pass : NULL;      cb.pass = k->is_protected? pass : NULL;
749      cb.opaque = &keygen;      cb.opaque = &keygen;
750      dialog_box_param( glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDSUBKEY,          dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDSUBKEY,    
751                        dlg, keyedit_addsubkey_dlg_proc,                        dlg, keyedit_addsubkey_dlg_proc,
752                        (LPARAM)&cb, _("Add new Subkey" ),                                (LPARAM)&cb, _("Add new Subkey"),
753                        IDS_WINPT_KEYEDIT_ADDSUBKEY );                                IDS_WINPT_KEYEDIT_ADDSUBKEY);
754      if( !gpgme_editkey_is_valid( ek ) ) {      if (cb.finished)
755          free_if_alloc( pass );          k->update = 1;
756    
757        sfree_if_alloc (pass);    
758        return cb.finished? TRUE: FALSE;
759    }
760    
761    
762    BOOL
763    keyedit_set_pref_keyserver (winpt_key_t k, HWND dlg)
764    {
765        GpgKeyEdit *ke;
766        gpgme_error_t err;
767        struct URL_ctx_s *url;
768        char *pass;
769    
770        url = (struct URL_ctx_s *)get_keyserver_URL_dlg (dlg);
771        if (url->cancel == 1) {
772            delete url;
773          return FALSE;          return FALSE;
774      }      }
775    
776      ec = gpgme_new (&ctx);      pass = request_passphrase (_("Key Edit"), 1, &url->cancel);
777      if (ec)      if (url->cancel) {
778          BUG (dlg);          delete url;
779      gpgme_enable_logging (ctx);          return FALSE;
780      gpgme_set_edit_ctx (ctx, ek, GPGME_EDITKEY_ADDKEY);      }
     gpgme_set_progress_cb (ctx, keygen_cb, NULL);  
     keygen_cb_dlg_create ();  
       
     ec = gpgme_op_editkey (ctx, k->keyid);  
     keygen.fpr = get_subkey_fingerprint (ctx, k->keyid);  
     keygen_cb_dlg_destroy ();  
     keygen_cb (NULL, NULL, 0, 0, 0); /* flush */  
     if (ec)  
         gpgme_show_error (dlg, ec, ctx, _("Add Subkey"), MB_ERR);  
     else {        
         msg_box (dlg, _("Subkey successfully added."), _("GnuPG Status"), MB_OK);  
         if (lv)  
             do_add_new_subkey (lv, &keygen, k->flags);  
         keycache_set_reload (1);  
     }  
     free_if_alloc (pass);  
     gpgme_editkey_release (ek);  
     gpgme_release (ctx);  
       
     return ec? FALSE : TRUE;  
 } /* keyedit_add_subkey */  
781    
782        ke = new GpgKeyEdit (k->keyid);
783        if (!ke)
784            BUG (NULL);
785        ke->setPassphrase (pass);
786        err = ke->setPreferredKeyserver (0 /* XXX */, url->url);
787        if (!err)
788            msg_box (dlg, _("Preferred keyserver successfully set."), _("Key Edit"), MB_OK);
789    
790        sfree_if_alloc (pass);
791        delete ke;
792        delete url;    
793        return err == 0? 0 : WPTERR_GENERAL;
794    }
795    
796    
797    /* Add a photo-ID to the key specified in @k. @dlg is the handle of
798       the calling dialog. */
799  BOOL  BOOL
800  keyedit_add_photo( winpt_key_t k, HWND dlg  )  keyedit_add_photo (winpt_key_t k, HWND dlg)
801  {  {
802      if( !k->key_pair ) {      if (!k->key_pair) {
803          msg_box( dlg, _("There is no secret key available!"), _("Add Photo"), MB_ERR );          msg_box (dlg, _("There is no secret key available!"), _("Add Photo"), MB_ERR);
804          return FALSE;          return FALSE;
805      }      }
806      DialogBoxParam( glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDPHOTO, dlg,      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDPHOTO, dlg,
807                      keyedit_addphoto_dlg_proc, (LPARAM)k );                      keyedit_addphoto_dlg_proc, (LPARAM)k);
808      return TRUE;      return TRUE;
809  } /* keyedit_add_photo */  }
810    
811    
812  BOOL  BOOL
# Line 746  keyedit_add_revoker (winpt_key_t k, HWND Line 816  keyedit_add_revoker (winpt_key_t k, HWND
816          msg_box( dlg, _("There is no secret key available!"), _("Add Revoker"), MB_ERR );          msg_box( dlg, _("There is no secret key available!"), _("Add Revoker"), MB_ERR );
817          return FALSE;          return FALSE;
818      }      }
819      DialogBoxParam( glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDREV, dlg,      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDREV, dlg,
820                      keyedit_addrevoker_dlg_proc, (LPARAM)k );                      keyedit_addrevoker_dlg_proc, (LPARAM)k);
821      return TRUE;      return TRUE;
822  } /* keyedit_add_revoker */  } /* keyedit_add_revoker */
823    
824    
825  static int  static int
826  is_idea_protect_algo( const char * keyid )  is_idea_protect_algo (const char * keyid)
827  {  {
828      gpgme_key_t key;      winpt_key_s k;
829      const char * sym_prefs;      const unsigned char *sym_prefs;
830      size_t n;      size_t n;
831    
832      if( get_pubkey( keyid, &key ) )      memset (&k, 0, sizeof (k));
833          BUG( NULL );      if (winpt_get_pubkey (keyid, &k))
834      sym_prefs = gpgme_key_get_string_attr( key, GPGME_ATTR_KEY_SYMPREFS, NULL, 0 );              BUG (NULL);
835      if( !sym_prefs )      sym_prefs = k.ext->sym_prefs;
836        if (!sym_prefs)
837          return 1; /* assume that only v3 keys have no symmetric cipher preferences          return 1; /* assume that only v3 keys have no symmetric cipher preferences
838                       and thus IDEA is explicit. */                       and thus IDEA is explicit. */
839      for( n = 0; sym_prefs[n]; n++ )      for (n = 0; sym_prefs[n]; n++)
840          ;          ;
841      if( (n == 0 || n == 1) && *sym_prefs == 0x01 )      if ((n == 0 || n == 1) && *sym_prefs == 0x01)
842          return 1;          return 1;
843      return 0;      return 0;
844  } /* is_idea_protect_algo */  } /* is_idea_protect_algo */
# Line 776  is_idea_protect_algo( const char * keyid Line 847  is_idea_protect_algo( const char * keyid
847  BOOL  BOOL
848  keyedit_change_passwd( winpt_key_t k, HWND dlg )  keyedit_change_passwd( winpt_key_t k, HWND dlg )
849  {  {
850      gpgme_error_t ec;      GpgKeyEdit *ke;
851      gpgme_ctx_t ctx;      gpgme_error_t ec;    
852      gpgme_editkey_t ek;      char *old_pass = NULL, *new_pass = NULL;
     char * old_pass = NULL, * new_pass = NULL;  
853      int cancel = 0;      int cancel = 0;
854    
855      if( !k->key_pair ) {      if( !k->key_pair ) {
# Line 814  keyedit_change_passwd( winpt_key_t k, HW Line 884  keyedit_change_passwd( winpt_key_t k, HW
884          return FALSE;          return FALSE;
885      }      }
886    
887      ec = gpgme_new( &ctx );      ke = new GpgKeyEdit (k->keyid);
888      if( !ec )        if (!ke)
889          ec = gpgme_editkey_new( &ek );          BUG (NULL);
890      if( ec )  
891          BUG( NULL );      ke->setPassphrase (k->is_protected? old_pass : NULL);
892      gpgme_enable_logging( ctx );      ec = ke->changePassphrase (new_pass, 0);
     gpgme_editkey_passwd_set( ek, k->is_protected? old_pass : NULL, new_pass, 0 );  
     gpgme_set_edit_ctx( ctx, ek, GPGME_EDITKEY_PASSWD );  
     ec = gpgme_op_editkey( ctx, k->keyid );  
893      if( ec )      if( ec )
894          gpgme_show_error( dlg, ec, ctx, _("Change Passwd"), MB_ERR );          msg_box (dlg, gpgme_strerror (ec), _("Change Passwd"), MB_ERR);
895      else      else
896          msg_box( dlg, _("Passphrase successfully changed."),  _("GnuPG status"), MB_OK );          msg_box (dlg, _("Passphrase successfully changed."),  _("GnuPG status"), MB_OK);
897      free_if_alloc( old_pass );      sfree_if_alloc (old_pass);
898      free_if_alloc( new_pass );      sfree_if_alloc (new_pass);
899      gpgme_editkey_release( ek );      delete ke;
     gpgme_release( ctx );  
900      return TRUE;      return TRUE;
901  } /* keyedit_change_passwd */  }
902    
903    
904  listview_ctrl_t  listview_ctrl_t
# Line 840  subkey_list_init( HWND dlg, winpt_key_t Line 906  subkey_list_init( HWND dlg, winpt_key_t
906  {  {
907      LV_ITEM lvi;      LV_ITEM lvi;
908      gpgme_key_t key;      gpgme_key_t key;
909        gpgme_subkey_t sub;
910      struct listview_column_s cols[] = {      struct listview_column_s cols[] = {
911          {0, 80, (char *)_("Description")},          {0, 80, (char *)_("Description")},
912          {1, 78, (char *)_("Key ID")},          {1, 78, (char *)_("Key ID")},
# Line 855  subkey_list_init( HWND dlg, winpt_key_t Line 922  subkey_list_init( HWND dlg, winpt_key_t
922      listview_ctrl_t lv;      listview_ctrl_t lv;
923      char buf[256], tmp[128];      char buf[256], tmp[128];
924      const char *t;      const char *t;
925      int nkeys = 0, rc = 0, i, bits, j;      int nkeys = 0, rc = 0, i, bits;    
926    
927      if( get_pubkey( k->keyid, &key ) ) {      if( get_pubkey( k->keyid, &key ) ) {
928          msg_box( dlg, _("Could not find key."), _("Key Edit"), MB_ERR );          msg_box( dlg, _("Could not find key."), _("Key Edit"), MB_ERR );
929          return NULL;          return NULL;
930      }      }
931                nkeys = count_subkeys (key);
     nkeys = gpgme_key_count_items( key, GPGME_ATTR_KEYID );  
932      if( !nkeys ) {      if( !nkeys ) {
933          msg_box( dlg, _("No subkey(s) found."), _("Key Edit"), MB_ERR );          msg_box( dlg, _("No subkey(s) found."), _("Key Edit"), MB_ERR );
934          return NULL;          return NULL;
# Line 887  subkey_list_init( HWND dlg, winpt_key_t Line 953  subkey_list_init( HWND dlg, winpt_key_t
953      }      }
954                    
955      listview_set_ext_style( lv );      listview_set_ext_style( lv );
956      for( i = 0; i < nkeys; i++ ) {      for( i = 0, sub = key->subkeys; i < nkeys; i++, sub = sub->next ) {
957          memset( buf, 0, sizeof buf );          memset( buf, 0, sizeof buf );
958    
959          bits = gpgme_key_get_ulong_attr( key, GPGME_ATTR_LEN, NULL, i );          bits = sub->length;
960          _snprintf( tmp, sizeof tmp-1, "%d-bit ", bits );          _snprintf( tmp, sizeof tmp-1, "%d-bit ", bits );
961          strcat( buf, tmp );          strcat( buf, tmp );
962    
963          j = gpgme_key_get_ulong_attr( key, GPGME_ATTR_ALGO, NULL, i );          _snprintf( tmp, sizeof tmp-1, "%s", get_key_pubalgo (sub->pubkey_algo));
         t = gpgme_key_expand_attr( GPGME_ATTR_ALGO, j );  
         _snprintf( tmp, sizeof tmp-1, "%s", t );  
964          strcat( buf, tmp );          strcat( buf, tmp );
965                    
966          listview_add_sub_item( lv, i, 0, buf );          listview_add_sub_item( lv, i, 0, buf );
967          t = gpgme_key_get_string_attr( key, GPGME_ATTR_KEYID, NULL, i );          t = sub->keyid;
968          if( !t )          if( !t )
969              t = "DEADBEEFDEADBEEF";              t = "DEADBEEFDEADBEEF";
970          _snprintf( tmp, sizeof tmp-1, "0x%s", t+8 );          _snprintf( tmp, sizeof tmp-1, "0x%s", t+8 );
971          listview_add_sub_item( lv, i, 1, tmp );          listview_add_sub_item( lv, i, 1, tmp );
972    
973          j = gpgme_key_get_ulong_attr( key, GPGME_ATTR_CREATED, NULL, i );          t = get_key_created (sub->timestamp);
         t = gpgme_key_expand_attr( GPGME_ATTR_CREATED, j );  
974          if( !t )          if( !t )
975              t = "????-??-??";              t = "????-??-??";
976          listview_add_sub_item( lv, i, 2, t );          listview_add_sub_item( lv, i, 2, t );
977    
978          j = gpgme_key_get_ulong_attr( key, GPGME_ATTR_EXPIRES, NULL, i );          if( sub->expires ) {
979          if( j ) {              t = get_key_created (sub->expires);
             t = gpgme_key_expand_attr( GPGME_ATTR_CREATED, j );  
980              listview_add_sub_item( lv, i, 3, t );              listview_add_sub_item( lv, i, 3, t );
981          }          }
982          else          else
983              listview_add_sub_item( lv, i, 3, _("Never") );              listview_add_sub_item( lv, i, 3, _("Never") );
984    
985          if( gpgme_key_get_ulong_attr(key, GPGME_ATTR_KEY_EXPIRED, NULL, i ) )          if( sub->expired )
986              t = _("Expired");              t = _("Expired");
987          else if( gpgme_key_get_ulong_attr( key, GPGME_ATTR_KEY_REVOKED, NULL, i ) )          else if( sub->revoked )
988              t = _("Revoked");              t = _("Revoked");
989          else          else
990              t = _("OK");              t = _("OK");
991          listview_add_sub_item( lv, i, 4, t );          listview_add_sub_item( lv, i, 4, t );
992    
993          gpgme_key_get_cability( key, GPGME_ATTR_CAN_CERTIFY, i )?          if (sub->can_certify) t = "*"; else t = "";
994              t = "*" : t = "";          listview_add_sub_item (lv, i, 5, t);
995          listview_add_sub_item( lv, i, 5, t );          if (sub->can_sign) t = "*"; else t = "";
         gpgme_key_get_cability( key, GPGME_ATTR_CAN_SIGN, i )?  
             t = "*" : t = "";  
996          listview_add_sub_item( lv, i, 6, t );          listview_add_sub_item( lv, i, 6, t );
997          gpgme_key_get_cability( key, GPGME_ATTR_CAN_ENCRYPT, i )?          if (sub->can_encrypt) t = "*"; else t = "";
             t = "*" : t = "";  
998          listview_add_sub_item( lv, i, 7, t );          listview_add_sub_item( lv, i, 7, t );
999            if (sub->can_authenticate) t = "*"; else t = "";
         gpgme_key_get_cability (key, GPGME_ATTR_CAN_AUTH, i)?  
             t = "*" : t = "";  
1000          listview_add_sub_item (lv, i, 8, t);          listview_add_sub_item (lv, i, 8, t);
1001      }      }
1002      return lv;      return lv;
# Line 951  userid_list_init (HWND dlg, winpt_key_t Line 1008  userid_list_init (HWND dlg, winpt_key_t
1008  {  {
1009      listview_ctrl_t lv = NULL;      listview_ctrl_t lv = NULL;
1010      gpgme_key_t key;      gpgme_key_t key;
1011        gpgme_key_sig_t ks;
1012        gpgme_user_id_t u;
1013      int nuids = 0, rc, j, u_attr;      int nuids = 0, rc, j, u_attr;
1014      struct listview_column_s cols[] = {      struct listview_column_s cols[] = {
1015          {0,  72, (char *)_("Validity")},          {0,  72, (char *)_("Validity")},
1016          {1, 180, (char *)_("Name")},          {1, 150, (char *)_("Name")},
1017          {2,  90, (char *)_("Email")},          {2, 110, (char *)_("Email")},
1018          {3,  76, (char *)_("Creation")},          {3,  76, (char *)_("Creation")},
1019          {0, 0, 0}          {0, 0, 0}
1020      };          };    
# Line 965  userid_list_init (HWND dlg, winpt_key_t Line 1024  userid_list_init (HWND dlg, winpt_key_t
1024          msg_box( dlg, _("Could not find key."), _("Key Edit"), MB_ERR );          msg_box( dlg, _("Could not find key."), _("Key Edit"), MB_ERR );
1025          return NULL;          return NULL;
1026      }      }
1027                
1028      nuids = gpgme_key_count_items (key, GPGME_ATTR_USERID);      nuids = count_userids (key);
1029      if (!nuids) {      if (!nuids) {
1030          msg_box (dlg, _("No user ID(s) found."), _("Key Edit"), MB_ERR);          msg_box (dlg, _("No user ID(s) found."), _("Key Edit"), MB_ERR);
1031          return NULL;          return NULL;
# Line 985  userid_list_init (HWND dlg, winpt_key_t Line 1044  userid_list_init (HWND dlg, winpt_key_t
1044      }      }
1045    
1046      listview_set_ext_style (lv);      listview_set_ext_style (lv);
1047      for (j = 0; j < nuids; j++) {      for (j = 0, u=key->uids; j < nuids; u=u->next, j++) {
1048          if (gpgme_key_get_ulong_attr (key, GPGME_ATTR_UID_REVOKED, NULL, j))          if (u->revoked)
1049              attr = _("Revoked");              attr = _("Revoked");
1050          else {          else {
1051              u_attr = gpgme_key_get_ulong_attr (key, GPGME_ATTR_VALIDITY, NULL, j);              u_attr = (int)u->validity;
1052              attr = gpgme_key_expand_attr (GPGME_ATTR_VALIDITY, u_attr);              attr = get_key_trust2 (NULL, u_attr, 0, 0);
1053          }          }
1054          listview_add_sub_item( lv, j, 0, (char *)attr );                  listview_add_sub_item( lv, j, 0, (char *)attr );        
1055    
1056          /* XXX: add comment if available */          /* XXX: add comment if available */
1057          attr = gpgme_key_get_string_attr( key, GPGME_ATTR_NAME, NULL, j );          attr = u->name;
1058          if (attr) {          if (attr) {
1059              char * uid = utf8_to_wincp (attr, strlen (attr));              char * uid = utf8_to_wincp (attr, strlen (attr));
1060              if (uid) {              if (uid) {
# Line 1005  userid_list_init (HWND dlg, winpt_key_t Line 1064  userid_list_init (HWND dlg, winpt_key_t
1064          }          }
1065          else          else
1066              listview_add_sub_item( lv, j, 1, _("Invalid user ID") );              listview_add_sub_item( lv, j, 1, _("Invalid user ID") );
1067          attr = gpgme_key_get_string_attr (key, GPGME_ATTR_EMAIL, NULL, j);          attr = u->email;
1068          if (attr)          if (attr)
1069              listview_add_sub_item (lv, j, 2, attr);              listview_add_sub_item (lv, j, 2, attr);
1070          u_attr = gpgme_key_get_ulong_attr (key, GPGME_ATTR_UID_CREATED, NULL, j);  
1071          if (u_attr)          ks = get_selfsig (u, k->keyid+2, 1);
1072              listview_add_sub_item (lv, j, 3, get_key_created (u_attr));          if (ks)
1073                listview_add_sub_item (lv, j, 3, get_key_created (ks->timestamp));
1074      }      }
1075      if( !k->key_pair ) {      if( !k->key_pair ) {
1076          CheckDlgButton( dlg, IDC_KEYUID_ADD, BST_INDETERMINATE );          CheckDlgButton( dlg, IDC_KEYUID_ADD, BST_INDETERMINATE );
# Line 1068  is_cmd_openpgp( int cmdid ) Line 1128  is_cmd_openpgp( int cmdid )
1128      case CMD_ADDREVOKER:      case CMD_ADDREVOKER:
1129      case CMD_DELPHOTO:      case CMD_DELPHOTO:
1130      /*case CMD_SHOWPHOTO:*/      /*case CMD_SHOWPHOTO:*/
1131      case CMD_UPDPREF:      /*case CMD_SETPREF:*/
1132          return 1;          return 1;
1133      }      }
1134      return 0;      return 0;
# Line 1108  do_show_help( HWND dlg ) Line 1168  do_show_help( HWND dlg )
1168    
1169    
1170  static int  static int
1171  do_editkey_delkey( winpt_key_t k, HWND dlg, listview_ctrl_t lv  )  do_editkey_delkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1172  {  {
1173        gpgme_error_t err;
1174        GpgKeyEdit *ke;
1175      int j, id;      int j, id;
1176      char tmp[64];      char tmp[64];
1177      gpgme_error_t ec;  
1178      gpgme_editkey_t ek;      if (!k->key_pair)
1179      gpgme_ctx_t ctx;          return FALSE; /* XXX: shall we allow to modify non-secret keys?? */
1180    
1181      if( listview_count_items( lv, 0 ) == 1 ) {      if( listview_count_items( lv, 0 ) == 1 ) {
1182          msg_box( dlg, _("Primary key can not be deleted!"), _("Key Edit"), MB_ERR);          msg_box( dlg, _("Primary key can not be deleted!"), _("Key Edit"), MB_ERR);
# Line 1138  do_editkey_delkey( winpt_key_t k, HWND d Line 1200  do_editkey_delkey( winpt_key_t k, HWND d
1200      if( id == IDNO )      if( id == IDNO )
1201          return FALSE;          return FALSE;
1202    
1203      ec = gpgme_new( &ctx );      ke = new GpgKeyEdit (k->keyid);
1204      if( !ec )      if (!ke)
1205          ec = gpgme_editkey_new( &ek );          BUG (NULL);
1206      if( ec )      err = ke->delKey (j);
1207          BUG( dlg );      if (err)
1208      gpgme_enable_logging( ctx );          msg_box (dlg, gpgme_strerror (err), _("Delete Subkey"), MB_ERR);
     gpgme_editkey_delkey_set_id( ek, j );  
     gpgme_set_edit_ctx( ctx, ek, GPGME_EDITKEY_DELKEY );  
     ec = gpgme_op_editkey( ctx, k->keyid );  
     if( ec )  
         gpgme_show_error( dlg, ec, ctx, _("Delete Subkey"), MB_ERR );  
1209      else {      else {
1210          listview_del_item( lv, j );          listview_del_item (lv, j);
1211          keycache_set_reload( 1 );              k->update = 1;
1212          status_box( dlg, _("Subkey successfully deleted."), _("GnuPG status") );          status_box (dlg, _("Subkey successfully deleted."), _("GnuPG status"));
1213      }      }
1214      gpgme_editkey_release( ek );      delete ke;
1215      gpgme_release( ctx );          return err? FALSE : TRUE;
     return ec? FALSE : TRUE;  
1216  } /* do_editkey_delkey */  } /* do_editkey_delkey */
1217    
1218    
1219    /* Set the expiration date for the selected key in list view @lv.
1220       Return value: TRUE on success. */
1221  static int  static int
1222  do_editkey_expire( winpt_key_t k, HWND dlg, listview_ctrl_t lv )  do_editkey_expire (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1223  {  {
1224      gpgme_error_t ec;      gpgme_error_t err;
1225      gpgme_editkey_t ek;      GpgKeyEdit *ke;
     gpgme_ctx_t ctx;  
1226      date_s udd = {0};      date_s udd = {0};
1227      char buf[256], * pass = NULL;      char buf[256], * pass = NULL;
1228      int j, cancel = 0;      int j, cancel = 0;
1229    
1230      if( !k->key_pair ) {      if (!k->key_pair) {
1231          msg_box( dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR );          msg_box( dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR );
1232          return FALSE;          return FALSE;
1233      }      }
# Line 1179  do_editkey_expire( winpt_key_t k, HWND d Line 1236  do_editkey_expire( winpt_key_t k, HWND d
1236          return FALSE;          return FALSE;
1237      }      }
1238                            
1239      listview_get_item_text( lv, j, 3, buf, sizeof buf -1 );          listview_get_item_text( lv, j, SUBK_COL_STATUS, buf, sizeof buf -1 );    
1240      if( !strcmp( buf, _("Expired") ) ) {          if( !strcmp( buf, _("Expired") ) ) {    
1241          msg_box( dlg, _("Key already expired!"), _("Key Edit"), MB_ERR );          msg_box( dlg, _("Key already expired!"), _("Key Edit"), MB_ERR );
1242          return FALSE;          return FALSE;
1243      }      }
1244      memset( &udd, 0, sizeof udd );      memset (&udd, 0, sizeof udd);
1245      udd.text = _("Key Expiration Date");      udd.text = _("Key Expiration Date");
1246      dialog_box_param( glob_hinst, (LPCSTR)IDD_WINPT_DATE, dlg,          dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_DATE, dlg,    
1247                          date_dlg_proc, (LPARAM)&udd,                        date_dlg_proc, (LPARAM)&udd,
1248                      _("Key Expiration Date"), IDS_WINPT_DATE );                        _("Key Expiration Date"), IDS_WINPT_DATE);
1249      if( udd.cancel == 1 )      if (udd.cancel == 1)
1250          return FALSE;          return FALSE;
1251      if( !keygen_check_date( &udd.st ) ) {      if (!keygen_check_date (&udd.st)) {
1252          msg_box( dlg, _("The date you have chosen lies in the past."), _("Key Edit"), MB_ERR );          msg_box (dlg, _("The date you have chosen lies in the past."),
1253                     _("Key Edit"), MB_ERR);
1254          return FALSE;          return FALSE;
1255      }      }
1256      if( k->is_protected ) {      if( k->is_protected ) {
# Line 1200  do_editkey_expire( winpt_key_t k, HWND d Line 1258  do_editkey_expire( winpt_key_t k, HWND d
1258          if( cancel )          if( cancel )
1259              return FALSE;              return FALSE;
1260      }      }
1261      _snprintf( buf, sizeof buf - 1, "%04d-%02d-%02d",      
1262                  udd.st.wYear, udd.st.wMonth, udd.st.wDay );      ke = new GpgKeyEdit (k->keyid);
1263      ec = gpgme_editkey_new( &ek );      if (!ke)
1264      if( !ec )          BUG (NULL);
1265          ec = gpgme_new( &ctx );      if (k->is_protected)
1266      if( ec )          ke->setPassphrase (pass);
1267          BUG( dlg );      err = ke->setKeyExpireDate (j, diff_time (NULL, &udd.st), true);
1268      gpgme_editkey_expire_set( ek, j, 0, buf, k->is_protected? pass : NULL );      if (err)
1269      gpgme_enable_logging( ctx );          msg_box (dlg, gpgme_strerror (err), _("Expire Subkey"), MB_ERR);
     gpgme_set_edit_ctx( ctx, ek, GPGME_EDITKEY_EXPIRE );  
     ec = gpgme_op_editkey( ctx, k->keyid );  
     if( ec )  
         gpgme_show_error( dlg, ec, ctx, _("Expire Subkey"), MB_ERR );  
1270      else {      else {
1271          listview_add_sub_item( lv, j, 3, buf );          _snprintf (buf, sizeof buf - 1, "%04d-%02d-%02d",      
1272          keycache_set_reload( 1 );                     udd.st.wYear, udd.st.wMonth, udd.st.wDay);
1273          msg_box( dlg, _("Subkey expire date successfully set."), _("GnuPG status"), MB_OK );          listview_add_sub_item (lv, j, SUBK_COL_EXPIRES, buf);
1274      }          k->update = 1;
1275      free_if_alloc( pass );          msg_box (dlg, _("Subkey expire date successfully set."),
1276      gpgme_release( ctx );                   _("GnuPG status"), MB_OK);
1277      gpgme_editkey_release( ek );      }
1278        sfree_if_alloc (pass);
1279        delete ke;
1280      return TRUE;      return TRUE;
1281  } /* do_editkey_expire */  }
1282    
1283    
1284    /* Revoke the selected key in the list view @lv. @k contains
1285       control information about the global key.
1286       Return value: TRUE on success. */
1287  static int  static int
1288  do_editkey_revoke( winpt_key_t k, HWND dlg, listview_ctrl_t lv )  do_editkey_revoke (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1289  {  {
1290      gpgme_ctx_t ctx;      gpgme_error_t err;
1291      gpgme_error_t ec;      GpgKeyEdit *ke;
1292      gpgme_editkey_t ek;      char buf[256];
1293      char buf[256], * pass = NULL;      char *pass = NULL;
1294      int j, cancel = 0;      int j, cancel = 0;
1295    
1296      if( !k->key_pair ) {      if (!k->key_pair) {
1297          msg_box( dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR );          msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
1298          return FALSE;          return FALSE;
1299                }
1300      }                    
1301                if ((j = listview_get_curr_pos (lv)) == -1) {
     if( (j = listview_get_curr_pos( lv )) == -1 ) {  
1302          msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );          msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
1303          return FALSE;          return FALSE;
1304      }      }
1305      else if( listview_count_items( lv, 0 ) == 1 ) {      else if (listview_count_items (lv, 0) == 1) {
1306          msg_box( dlg, _("No subkeys were found, if you want to revoke the\n"          msg_box( dlg, _("No subkeys were found, if you want to revoke the\n"
1307                          "whole key, please use the Key Manager command directly.\n\n"                          "whole key, please use the Key Manager command directly.\n\n"
1308                          "This command is only available to revoke single subkeys"),                          "This command is only available to revoke single subkeys"),
# Line 1252  do_editkey_revoke( winpt_key_t k, HWND d Line 1310  do_editkey_revoke( winpt_key_t k, HWND d
1310          return FALSE;          return FALSE;
1311      }      }
1312                            
1313      listview_get_item_text( lv, j, 3, buf, sizeof buf-1 );      listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, sizeof (buf)-1);
1314      if( !strcmp( buf, _("Revoked") ) ) {      if (!strcmp (buf, _("Revoked"))) {
1315          msg_box( dlg, _("Key already revoked."), _("Key Edit"), MB_ERR );          msg_box (dlg, _("Key already revoked."), _("Key Edit"), MB_ERR);
1316          return FALSE;          return FALSE;
1317      }      }
1318            
1319      if( k->is_protected ) {      if (k->is_protected) {
1320          pass = request_passphrase (_("Key Edit"), 1, &cancel);          pass = request_passphrase (_("Key Edit"), 1, &cancel);
1321          if( cancel )          if (cancel)
1322              return FALSE;                        return FALSE;          
1323      }      }
1324                
1325      ec = gpgme_editkey_new( &ek );      ke = new GpgKeyEdit (k->keyid);
1326      if( !ec )      if (!ke)
1327          ec = gpgme_new( &ctx );          BUG (NULL);
1328      if( ec )      if (k->is_protected)
1329          BUG( NULL );          ke->setPassphrase (pass);
1330      gpgme_enable_logging( ctx );      err = ke->revokeSubkey (j, 0, NULL);
1331      gpgme_editkey_revkey_set( ek, j, 0, k->is_protected? pass : NULL );      if (err)
1332      gpgme_set_edit_ctx( ctx, ek, GPGME_EDITKEY_REVKEY );          msg_box( dlg, gpgme_strerror (err), _("Revoke Subkey"), MB_ERR);
     ec = gpgme_op_editkey( ctx, k->keyid );  
     if( ec )  
         gpgme_show_error( dlg, ec, ctx, _("Revoke Subkey"), MB_ERR );  
1333      else {      else {
1334          listview_add_sub_item( lv, j, 5, _("Revoked") );          listview_add_sub_item (lv, j, SUBK_COL_STATUS, _("Revoked"));
1335          keycache_set_reload( 1 );          k->update = 1;
1336          msg_box( dlg, _("Subkey successfully revoked."), _("GnuPG Status"), MB_OK );          msg_box( dlg, _("Subkey successfully revoked."), _("GnuPG Status"), MB_OK );
1337      }      }
1338      free_if_alloc( pass );      sfree_if_alloc (pass);
1339      gpgme_release( ctx );      delete ke;
     gpgme_editkey_release( ek );  
1340      return TRUE;      return TRUE;
1341  } /* do_editkey_revoke */  }
1342    
1343    
1344    /* Revoked the selected userid in list view @lv.
1345       Return value: TRUE on success. */
1346  int  int
1347  do_editkey_revuid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)  do_editkey_revuid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1348  {  {
1349      gpgme_ctx_t ctx;      gpgme_error_t err;
1350      gpgme_error_t ec;      GpgKeyEdit *ke;
     gpgme_editkey_t ek;  
1351      char buf[256], t[512], * pass;      char buf[256], t[512], * pass;
1352      int cancel = 0, id = 0, j;      int cancel = 0, id = 0, j;
1353    
1354      if( !k->key_pair ) {      if (!k->key_pair) {
1355          msg_box( dlg, _("There is no secret key available!"), _("Revoke user ID"), MB_ERR );          msg_box( dlg, _("There is no secret key available!"), _("Revoke user ID"), MB_ERR );
1356          return FALSE;          return FALSE;
1357      }      }
# Line 1317  do_editkey_revuid (winpt_key_t k, HWND d Line 1372  do_editkey_revuid (winpt_key_t k, HWND d
1372          return FALSE;          return FALSE;
1373      }      }
1374                            
1375      listview_get_item_text( lv, j, 1, buf, sizeof buf -1 );      listview_get_item_text (lv, j, 1, buf, sizeof buf -1);
1376      _snprintf( t, sizeof t -1, _("user ID \"%s\".\n\n"      _snprintf( t, sizeof t -1, _("user ID \"%s\".\n\n"
1377                  "Do you really want to revoke this user ID?"), buf );                  "Do you really want to revoke this user ID?"), buf );
1378      if( msg_box( dlg, t, _("Key Edit"), MB_WARN_ASK) == IDNO )      if( msg_box( dlg, t, _("Key Edit"), MB_WARN_ASK) == IDNO )
# Line 1327  do_editkey_revuid (winpt_key_t k, HWND d Line 1382  do_editkey_revuid (winpt_key_t k, HWND d
1382          if( cancel )              if( cancel )    
1383              return FALSE;                        return FALSE;          
1384      }      }
1385        listview_get_item_text (lv, j, 2, buf, sizeof (buf)-1);
1386      id = do_find_userid (k->keyid, buf, NULL);      id = do_find_userid (k->keyid, buf, NULL);
1387      if (id == -1)      if (id == -1)
1388          BUG (dlg);          BUG (NULL);
1389      ec = gpgme_new (&ctx);  
1390      if (!ec)          ke = new GpgKeyEdit (k->keyid);
1391          ec = gpgme_editkey_new (&ek);      if (!ke)
1392      if( ec )          BUG (NULL);
1393          BUG( dlg );      if (k->is_protected)
1394      gpgme_enable_logging( ctx );          ke->setPassphrase (pass);
1395      gpgme_editkey_revsig_set( ek, id, k->is_protected? pass : NULL );      err = ke->revokeUserid (id);
1396      gpgme_set_edit_ctx( ctx, ek, GPGME_EDITKEY_REVSIG );      if (err)
1397      ec = gpgme_op_editkey( ctx, k->keyid );          msg_box (dlg, gpgme_strerror (err), _("Revoke Signature"), MB_ERR);
     if (ec)  
         gpgme_show_error (dlg, ec, ctx, _("Revoke Signature"), MB_ERR);  
1398      else {      else {
1399          listview_add_sub_item (lv, j, 0, _("Revoked"));          listview_add_sub_item (lv, j, 0, _("Revoked"));
1400          keycache_set_reload (1);          k->update = 1;
1401          status_box (dlg, _("User ID successfully revoked"), _("GnuPG Status"));          status_box (dlg, _("User ID successfully revoked"), _("GnuPG Status"));
1402      }      }
1403      free_if_alloc (pass);      sfree_if_alloc (pass);
1404      gpgme_editkey_release (ek);      delete ke;
1405      gpgme_release (ctx);      return err? FALSE : TRUE;
1406      return ec? FALSE : TRUE;  }
 } /* do_editkey_revuid */  
1407    
1408    
1409  static int  static int
1410  do_editkey_setpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)  do_editkey_setpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1411  {  {
     gpgme_ctx_t ctx;  
     gpgme_editkey_t ek;  
1412      gpgme_error_t rc;      gpgme_error_t rc;
1413        GpgKeyEdit *ke;
1414      char buf[256], * pass = NULL, * prefs;      char buf[256], * pass = NULL, * prefs;
1415      int j, id, cancel=0, flags=0;      int j, id, cancel=0, flags=0;
1416    
# Line 1366  do_editkey_setpref (winpt_key_t k, HWND Line 1418  do_editkey_setpref (winpt_key_t k, HWND
1418          msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);          msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1419          return FALSE;          return FALSE;
1420      }      }
1421      listview_get_item_text (lv, j, 1, buf, sizeof buf-1);      listview_get_item_text (lv, j, 2, buf, sizeof buf-1);
1422      id = do_find_userid (k->keyid, buf, NULL);      id = do_find_userid (k->keyid, buf, NULL);
1423      if (id == -1)      if (id == -1)
1424          BUG (dlg);          BUG (dlg);
# Line 1375  do_editkey_setpref (winpt_key_t k, HWND Line 1427  do_editkey_setpref (winpt_key_t k, HWND
1427          if (cancel)          if (cancel)
1428              return FALSE;              return FALSE;
1429      }      }
1430      rc = gpgme_new (&ctx);  
1431      if (!rc)      ke = new GpgKeyEdit (k->keyid);
1432          rc = gpgme_editkey_new (&ek);      if (!ke)
     if (rc)  
1433          BUG (NULL);          BUG (NULL);
1434        if (k->is_protected)
1435            ke->setPassphrase (pass);
1436    
1437      get_userid_preflist (&prefs, &flags);      get_userid_preflist (&prefs, &flags);
     gpgme_editkey_setpref_set (ek, prefs, id, pass);  
     gpgme_set_edit_ctx (ctx, ek, GPGME_EDITKEY_SETPREF);  
     rc = gpgme_op_editkey (ctx, k->keyid);  
     free_if_alloc (pass);  
1438    
1439        rc = ke->setUseridPreferences (id, prefs);
1440        /* XXX */
1441    
1442        sfree_if_alloc (pass);
1443      free_if_alloc (prefs);      free_if_alloc (prefs);
1444      gpgme_release (ctx);      delete ke;
     gpgme_editkey_release (ek);  
1445      return 0;      return 0;
1446  }  }
1447    
1448    
1449  static int  static int
1450  do_editkey_primary( winpt_key_t k, HWND dlg, listview_ctrl_t lv )  do_editkey_primary (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1451  {  {
1452      gpgme_ctx_t ctx;      gpgme_error_t err;
1453      gpgme_editkey_t ek;      GpgKeyEdit *ke;
     gpgme_error_t ec;  
1454      int j, id, cancel=0;      int j, id, cancel=0;
1455      char buf[256], * pass = NULL;      char buf[256], * pass = NULL;
1456    
1457      if( (j = listview_get_curr_pos( lv )) == -1 ) {      if (listview_count_items (lv, 0) == 1)
1458            return TRUE;
1459        if ((j = listview_get_curr_pos (lv)) == -1) {
1460          msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );          msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1461          return FALSE;          return FALSE;
1462      }      }
1463      listview_get_item_text( lv, j, 1, buf, sizeof buf-1 );      listview_get_item_text (lv, j, 2, buf, sizeof buf-1);
1464      id = do_find_userid (k->keyid, buf, NULL);      id = do_find_userid (k->keyid, buf, NULL);
1465      if( id == -1 )      if (id == -1)
1466          BUG( dlg );          BUG (dlg);
1467      if( k->is_protected ) {      if (k->is_protected) {
1468          pass = request_passphrase( _("Key Edit"), 1, &cancel );          pass = request_passphrase (_("Key Edit"), 1, &cancel);
1469          if( cancel )          if( cancel )
1470              return FALSE;              return FALSE;
1471      }      }
1472    
1473      ec = gpgme_new( &ctx );      ke = new GpgKeyEdit (k->keyid);
1474      if( !ec )      if (k->is_protected)
1475          ec = gpgme_editkey_new( &ek );          ke->setPassphrase (pass);
1476      if( ec )      err = ke->setPrimaryUserid (id);
1477          BUG( dlg );      if (err)
1478      gpgme_enable_logging( ctx );          msg_box (dlg, gpgme_strerror (err), _("Primary"), MB_ERR);
     gpgme_editkey_primary_set( ek, id, k->is_protected? pass : NULL );  
     gpgme_set_edit_ctx( ctx, ek, GPGME_EDITKEY_PRIMARY );  
     ec = gpgme_op_editkey( ctx, k->keyid );  
     if( ec )  
         gpgme_show_error( dlg, ec, ctx, _("Primary"), MB_ERR );  
1479      else {      else {
1480          keycache_set_reload( 1 );          k->update = 1;
1481          status_box( dlg, _("User ID successfully flagged"), _("GnuPG Status") );          status_box (dlg, _("User ID successfully flagged"), _("GnuPG Status"));
1482      }      }
1483    
1484      free_if_alloc( pass );      sfree_if_alloc (pass);
1485      gpgme_editkey_release( ek );      delete ke;
1486      gpgme_release( ctx );      return err? FALSE : TRUE;
1487      return ec? FALSE : TRUE;  }
 } /* do_editkey_primary */  
1488    
1489    
1490  static int  static int
1491  parse_preflist (HWND dlg, const char *list)  parse_preflist (HWND dlg, const char *list)
1492  {  {
1493      char *p;      char *p, buf[128] = {0}, *pbuf = buf;
1494      const char *ciphers[11] = {0, "IDEA", "3DES", "CAST5", "BLOWFISH", 0, 0, "AES", "AES192", "AES256", "TWOFISH"};      const char *ciphers[11] = {0, "IDEA", "3DES", "CAST5", "BLOWFISH", 0, 0, "AES", "AES192", "AES256", "TWOFISH"};
1495      const char *hash[4] = {0, "MD5", "SHA1", "RMD160"};      const char *hash[11] = {0, "MD5", "SHA1", "RMD160", 0, 0, 0, 0, "SHA256", "SHA384", "SHA512"};
1496      const char *compress[4] = {0, "ZIP", "ZLIB", "BZIP2"};      const char *compress[4] = {0, "ZIP", "ZLIB", "BZIP2"};
1497      int n=0;      int n=0;
1498    
1499      p = strtok ((char*)list, " ");      strncpy (buf, list, 127);
1500        p = strtok (pbuf, " ");
1501      while (p != NULL) {      while (p != NULL) {
1502          int algid = atol (p+1);          int algid = atol (p+1);
1503          n++;          n++;
# Line 1459  parse_preflist (HWND dlg, const char *li Line 1507  parse_preflist (HWND dlg, const char *li
1507              break;              break;
1508    
1509          case 'H':          case 'H':
1510              SendDlgItemMessage (dlg, IDC_SHOWPREF_HASH, LB_ADDSTRING, 0, (LPARAM)(const char*)hash[algid % 4]);              SendDlgItemMessage (dlg, IDC_SHOWPREF_HASH, LB_ADDSTRING, 0, (LPARAM)(const char*)hash[algid % 10]);
1511              break;              break;
1512    
1513          case 'Z':          case 'Z':
# Line 1474  parse_preflist (HWND dlg, const char *li Line 1522  parse_preflist (HWND dlg, const char *li
1522      return n;      return n;
1523  }  }
1524    
1525    
1526    /* Dialog box procedure to show the key preferences. */
1527  BOOL CALLBACK  BOOL CALLBACK
1528  showpref_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  showpref_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1529  {  {
1530      static keyedit_callback_s *cb = NULL;      static keyedit_callback_s *cb = NULL;
1531      gpgme_uidinfo_t inf=NULL;      gpg_uid_info_t inf=NULL;
1532      char buf[128];      char buf[128];
1533      int pos;      int pos;
1534    
# Line 1491  showpref_dlg_proc (HWND dlg, UINT msg, W Line 1541  showpref_dlg_proc (HWND dlg, UINT msg, W
1541          SetDlgItemText (dlg, IDC_SHOWPREF_INFO, buf);          SetDlgItemText (dlg, IDC_SHOWPREF_INFO, buf);
1542          pos = do_find_userid (((winpt_key_t)cb->opaque)->keyid, buf, &inf);          pos = do_find_userid (((winpt_key_t)cb->opaque)->keyid, buf, &inf);
1543          if (inf) {          if (inf) {
1544              const char *prefs;              const char *prefs = inf->prefs;
             prefs = gpgme_editkey_get_string_attr (inf, GPGME_ATTR_UID_PREFS, pos-1);  
1545              if (prefs && *prefs) {              if (prefs && *prefs) {
1546                  if (parse_preflist (dlg, prefs) <= 0)                  if (parse_preflist (dlg, prefs) <= 0)
1547                      pos = -1;                      pos = -1;
1548              }              }
1549              else              else
1550                  pos = -1;                  pos = -1;
1551              gpgme_uid_info_release (inf);              gpg_uid_info_release (inf);
1552              if (pos == -1) {              if (pos == -1) {
1553                  msg_box (dlg, _("No preferences available."), _("Key Edit"), MB_ERR);                  msg_box (dlg, _("No preferences available."), _("Key Edit"), MB_ERR);
1554                  EndDialog (dlg, TRUE);                  EndDialog (dlg, TRUE);
1555              }              }
1556                if (inf->flags.mdc)
1557                    CheckDlgButton (dlg, IDC_SHOWPREF_MDC, BST_CHECKED);
1558          }          }
1559          SetForegroundWindow (dlg);          SetForegroundWindow (dlg);
1560          break;          break;
# Line 1519  showpref_dlg_proc (HWND dlg, UINT msg, W Line 1570  showpref_dlg_proc (HWND dlg, UINT msg, W
1570      return FALSE;      return FALSE;
1571  }  }
1572    
1573    
1574  static int  static int
1575  do_editkey_showpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)  do_editkey_showpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1576  {  {
1577      struct keyedit_callback_s cb;      struct keyedit_callback_s cb;
1578    
1579        if (k->is_v3)
1580            return TRUE;
1581    
1582      if (listview_get_curr_pos (lv) == -1) {      if (listview_get_curr_pos (lv) == -1) {
1583          msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);          msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1584          return FALSE;          return FALSE;
# Line 1533  do_editkey_showpref (winpt_key_t k, HWND Line 1589  do_editkey_showpref (winpt_key_t k, HWND
1589      cb.opaque = k;      cb.opaque = k;
1590      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_SHOWPREF, dlg,      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_SHOWPREF, dlg,
1591                      showpref_dlg_proc, (LPARAM)&cb);                      showpref_dlg_proc, (LPARAM)&cb);
1592      return 0;      return TRUE;
1593  }  }
1594    
1595    
1596  static int  static int
1597  do_editkey_deluid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)  do_editkey_deluid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1598  {  {
1599      gpgme_ctx_t ctx;      gpgme_error_t err;
1600      gpgme_editkey_t ek;      GpgKeyEdit *ke;
     gpgme_error_t ec;  
1601      char buf[256], t[512];      char buf[256], t[512];
1602      int j, id = 0;      int j, id = 0;
1603    
1604        if (!k->key_pair)
1605            return FALSE; /* XXX: see do_editkey_delsubkey */
1606    
1607      if( listview_count_items( lv, 0 ) == 1 ) {      if( listview_count_items( lv, 0 ) == 1 ) {
1608          msg_box( dlg, _("Primary user ID can not be deleted!"), _("Key Edit"), MB_ERR );          msg_box( dlg, _("Primary user ID can not be deleted!"), _("Key Edit"), MB_ERR );
1609          return FALSE;          return FALSE;
# Line 1555  do_editkey_deluid (winpt_key_t k, HWND d Line 1613  do_editkey_deluid (winpt_key_t k, HWND d
1613          return FALSE;          return FALSE;
1614      }      }
1615            
1616        /* XXX: add a hint that also all signatures will be deleted? */
1617      listview_get_item_text( lv, j, 1, buf, DIM(buf) -1 );      listview_get_item_text( lv, j, 1, buf, DIM(buf) -1 );
1618      _snprintf( t, sizeof t -1, _("user ID \"%s\".\n\n"      _snprintf( t, DIM (t)-1, _("user ID \"%s\".\n\n"
1619          "Do you really want to delete this user ID?"), buf );                                 "Do you really want to delete this user ID?"),
1620                                   buf);
1621      if( msg_box( dlg, t, _("Key Edit"), MB_YESNO|MB_ICONWARNING ) == IDNO )      if( msg_box( dlg, t, _("Key Edit"), MB_YESNO|MB_ICONWARNING ) == IDNO )
1622          return FALSE;          return FALSE;
1623            
# Line 1565  do_editkey_deluid (winpt_key_t k, HWND d Line 1625  do_editkey_deluid (winpt_key_t k, HWND d
1625      id = do_find_userid (k->keyid, buf, NULL);      id = do_find_userid (k->keyid, buf, NULL);
1626      if (id == -1)      if (id == -1)
1627          BUG (dlg);          BUG (dlg);
1628      ec = gpgme_new( &ctx );  
1629      if( !ec )      ke = new GpgKeyEdit (k->keyid);
1630          ec = gpgme_editkey_new( &ek );      if (!ke)
1631      if( ec )          BUG (NULL);
1632          BUG( dlg );  
1633      gpgme_enable_logging( ctx );      err = ke->delUserid (id);
1634      gpgme_editkey_deluid_set_id( ek,  id );          if( err )
1635      gpgme_set_edit_ctx( ctx, ek, GPGME_EDITKEY_DELUID );              msg_box( dlg, gpgme_strerror (err), _("Delete user ID"), MB_ERR );
     ec = gpgme_op_editkey( ctx, k->keyid );  
     if( ec )  
         gpgme_show_error( dlg, ec, ctx, _("Delete user ID"), MB_ERR );  
1636      else {      else {
1637          listview_del_item( lv, j );          listview_del_item( lv, j );
1638          keycache_set_reload( 1 );          k->update = 1;
1639          status_box( dlg, _("User ID successfully deleted"), _("GnuPG Status") );          status_box( dlg, _("User ID successfully deleted"), _("GnuPG Status") );
1640      }      }
1641      gpgme_editkey_release( ek );          delete ke;
1642      gpgme_release( ctx );      return err? FALSE : TRUE;
     return ec? FALSE : TRUE;  
1643  } /* do_editkey_deluid */  } /* do_editkey_deluid */
1644    
1645    
# Line 1681  keyedit_main_dlg_proc (HWND dlg, UINT ms Line 1737  keyedit_main_dlg_proc (HWND dlg, UINT ms
1737              EnableWindow (GetDlgItem (dlg, IDOK), FALSE);              EnableWindow (GetDlgItem (dlg, IDOK), FALSE);
1738          }          }
1739          SetForegroundWindow( dlg );          SetForegroundWindow( dlg );
1740          center_window( dlg );          center_window( dlg, NULL );
1741          return TRUE;          return TRUE;
1742    
1743      case WM_DESTROY:      case WM_DESTROY:
# Line 1706  keyedit_main_dlg_proc (HWND dlg, UINT ms Line 1762  keyedit_main_dlg_proc (HWND dlg, UINT ms
1762      case WM_COMMAND:      case WM_COMMAND:
1763          switch( LOWORD( wparam ) ) {          switch( LOWORD( wparam ) ) {
1764          case IDOK:          case IDOK:
1765              cmd = SendDlgItemMessage( dlg, IDC_KEYEDIT_CMD, CB_GETCURSEL, 0, 0 );              cmd = SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_GETCURSEL, 0, 0);
1766              if( cmd == LB_ERR ) {              if (cmd == LB_ERR) {
1767                  msg_box( dlg, _("Please select a command."), _("Key Edit"), MB_INFO );                  msg_box( dlg, _("Please select a command."), _("Key Edit"), MB_INFO );
1768                  return FALSE;                  return FALSE;
1769              }              }
1770              idxsub = listview_get_curr_pos( lvsub );              idxsub = listview_get_curr_pos (lvsub);
1771              if( km_key_is_v3( lvsub, idxsub==-1? 0 : idxsub ) && is_cmd_openpgp( cmd ) ) {              if (k->is_v3 && is_cmd_openpgp (cmd)) {
1772                  msg_box( dlg, _("This command cannot be used with PGP 2 (v3) keys\n"                  msg_box (dlg, _("This command cannot be used with PGP 2 (v3) keys.\n"),
1773                                  " because it is not OpenPGP compliant."),                                  _("Key Edit"), MB_ERR);
                                 _("Key Edit"), MB_ERR );  
1774                  return FALSE;                  return FALSE;
1775              }              }
1776              switch( cmd ) {              switch (cmd) {
1777              case CMD_SHOWPREF: do_editkey_showpref (k, dlg, lvuid); break;              case CMD_SHOWPREF: do_editkey_showpref (k, dlg, lvuid); break;
1778              case CMD_DELKEY: do_editkey_delkey (k, dlg, lvsub); break;              case CMD_DELKEY: do_editkey_delkey (k, dlg, lvsub); break;
1779              case CMD_ADDKEY: keyedit_add_subkey (k, dlg, lvsub); break;              case CMD_ADDKEY: keyedit_add_subkey (k, dlg, lvsub); break;
# Line 1738  keyedit_main_dlg_proc (HWND dlg, UINT ms Line 1793  keyedit_main_dlg_proc (HWND dlg, UINT ms
1793              break;              break;
1794    
1795          case IDCANCEL:          case IDCANCEL:
1796              EndDialog( dlg, FALSE );              EndDialog (dlg, FALSE);
1797              break;              break;
1798    
1799          case IDC_KEYEDIT_HELP:          case IDC_KEYEDIT_HELP:

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26