/[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 117 by twoaday, Thu Dec 8 09:26:32 2005 UTC revision 314 by twoaday, Sun May 13 09:44:03 2007 UTC
# Line 1  Line 1 
1  /* wptKeyEditDlgs.cpp - GPG key edit dialogs  /* wptKeyEditDlgs.cpp - GPG key edit dialogs
2   *      Copyright (C) 2002-2005 Timo Schulz   *      Copyright (C) 2002-2007 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
# Line 12  Line 12 
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.   * GNU General Public License for more details.
  *  
  * You should have received a copy of the GNU General Public License  
  * along with WinPT; if not, write to the Free Software Foundation,  
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA  
15   */   */
   
16  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
17  #include <config.h>  #include <config.h>
18  #endif  #endif
19    
20  #include <windows.h>  #include <windows.h>
 #include <oleauto.h>  
21  #include <commctrl.h>  #include <commctrl.h>
22  #include <time.h>  #include <time.h>
23    #include <assert.h>
24    
25  #include "resource.h"  #include "resource.h"
   
26  #include "wptTypes.h"  #include "wptTypes.h"
27  #include "wptW32API.h"  #include "wptW32API.h"
28  #include "wptVersion.h"  #include "wptVersion.h"
# Line 43  Line 37 
37  #include "wptKeyManager.h"  #include "wptKeyManager.h"
38  #include "wptRegistry.h"  #include "wptRegistry.h"
39  #include "wptKeyEdit.h"  #include "wptKeyEdit.h"
40    #include "StringBuffer.h"
41    
42    
43  /* All edit key commands. */  /* All edit key commands. */
44  enum keyedit_commands {      enum keyedit_commands {    
# Line 50  enum keyedit_commands { Line 46  enum keyedit_commands {
46      CMD_ADDUID,      CMD_ADDUID,
47      CMD_ADDPHOTO,      CMD_ADDPHOTO,
48      CMD_ADDREVOKER,      CMD_ADDREVOKER,
     /*CMD_FPR,*/  
49      CMD_DELUID,      CMD_DELUID,
50      CMD_DELKEY,      CMD_DELKEY,
     CMD_DELPHOTO,  
     /*CMD_DELSIG,*/  
51      CMD_EXPIRE,      CMD_EXPIRE,
     /*CMD_PREF,*/  
52      CMD_SHOWPREF,      CMD_SHOWPREF,
53      /*CMD_SETPREF,*/      CMD_SETPREF,
     /*CMD_UPDPREF,*/  
54      CMD_PASSWD,      CMD_PASSWD,
55      CMD_PRIMARY,      CMD_PRIMARY,
56      CMD_TRUST,      CMD_TRUST,
     /*CMD_REVSIG,*/  
57      CMD_REVUID,      CMD_REVUID,
58      CMD_REVKEY,      CMD_REVKEY,
59      CMD_DISABLE,      CMD_DISABLE,
60      CMD_ENABLE,      CMD_ENABLE,    
61      /*CMD_SHOWPHOTO,*/      CMD_SIGN,
62        CMD_LSIGN,
63        CMD_CHECK,
64        CMD_CLEAN,
65        CMD_MINIMIZE
66    };
67    
68    struct cmdlist_s {
69        const char   *name;
70        unsigned int  need_pair:1;
71        int       id;
72    } cmdlist[] = {
73        {"ADDKEY", 1, CMD_ADDKEY},
74        {"ADDUID", 1, CMD_ADDUID},
75        {"ADDPHOTO", 1, CMD_ADDPHOTO},
76        {"ADDREVOKER", 1, CMD_ADDREVOKER},
77        {"DELUID", 1, CMD_DELUID},
78        {"DELKEY", 1, CMD_DELKEY},
79        {"EXPIRE", 1, CMD_EXPIRE},
80        {"SHOWPREF", 0, CMD_SHOWPREF},
81        /*{"SETPREF", 1, CMD_SETPREF},*/
82        {"PASSWD", 1, CMD_PASSWD},
83        {"PRIMARY", 1, CMD_PRIMARY},
84        {"TRUST", 0, CMD_TRUST},
85        {"REVUID", 1, CMD_REVUID},
86        {"REVKEY", 1, CMD_REVKEY},
87        {"DISABLE", 0, CMD_DISABLE},
88        {"ENABLE", 0, CMD_ENABLE},
89        {"SIGN", 0, CMD_SIGN},
90        {"LSIGN", 0, CMD_LSIGN},
91        {"CHECK", 0, CMD_CHECK},
92        {"CLEAN", 0, CMD_CLEAN},
93        {"MINIMIZE", 0, CMD_MINIMIZE},
94        {NULL, 0}  
95  };  };
96    
97    
# Line 93  enum uid_col_t { Line 116  enum uid_col_t {
116      UID_COL_CREATION    = 3      UID_COL_CREATION    = 3
117  };  };
118    
119  struct keyedit_callback_s {  /* Key edit callback context. */
120      const char     *keyid;  struct keyedit_cb_s {
121      const char     *pass;      HWND            parent; /* parent window handle. */
122        const char     *keyid;  /* key ID of the key. */
123        const char     *pass;   /* pointer to the passphrase. */
124      listview_ctrl_t lv;      listview_ctrl_t lv;
125        int             lv_pos;
126      void           *opaque;      void           *opaque;
127      unsigned int    finished:1;      unsigned int    finished:1;
128        unsigned int    is_protected:1;
129  };  };
130  typedef struct keyedit_callback_s KEYEDIT_CB;  typedef struct keyedit_cb_s *keyedit_cb_t;
131    
 struct keygen_callback_s {  
     int   bits;  
     int   algo;  
     u32   expire;  
     char *fpr;  
 };  
 typedef struct keygen_callback_s KEYGEN_CB;  
132    
133    /* Key generation callback context. */
134    struct keygen_cb_s {
135        int    bits;
136        int    algo;
137        DWORD  expire; /* date of expiration or '0' for infinite valid. */
138        char  *fpr;
139        char  *name;
140        char  *comment;
141        char  *email;
142    };
143    typedef struct keygen_cb_s *keygen_cb_t;
144    
145    /* Subclass context for the subkey list. */
146  static subclass_s keyedit_subkey_proc;  static subclass_s keyedit_subkey_proc;
147    
148    /* Subclass context for the user-id list. */
149  static subclass_s keyedit_uid_proc;  static subclass_s keyedit_uid_proc;
150    
151  int keygen_check_date (SYSTEMTIME *st);  int keygen_check_date (SYSTEMTIME *st);
152  void get_userid_preflist (char **r_prefs, int * r_flags);  void get_userid_preflist (const char *old_prefs, char **r_prefs, int *r_flags);
153  char* get_subkey_fingerprint (const char *keyid);  char* get_subkey_keyid (const char *keyid);
154    void ComboBox_AddString_utf8 (HWND cb, const char *txt);
155    
156    
157  /* Associate each key with a combo box entry.  /* Associate each key with a combo box entry.
158     Skip the key in @k. */     Skip the key in @k. */
159  static void  static void
160  do_init_keylist (HWND dlg, winpt_key_t k)  do_init_keylist (HWND dlg, const char *keyid)
161  {  {
162      gpg_keycache_t pub;      gpg_keycache_t pub;
163      gpgme_key_t key;      gpgme_key_t key;
164      const char * s, * kid;      const char *s, *kid;
     char * u;  
165      int i, n;      int i, n;
166    
167      pub = keycache_get_ctx (1);      pub = keycache_get_ctx (1);
     if (!pub)  
         BUG (0);  
   
168      gpg_keycache_rewind (pub);      gpg_keycache_rewind (pub);
169      while( !gpg_keycache_next_key( pub, 0, &key ) ) {      while (!gpg_keycache_next_key (pub, 0, &key)) {
170          if (key->expired || key->revoked ||          if (!key_is_useable (key) || key->invalid)
             key->disabled || key->invalid)  
171              continue;              continue;
           
172          s = key->uids->uid;          s = key->uids->uid;
173          kid = key->subkeys->keyid;          kid = key->subkeys->keyid;
174          if (!s || !strcmp (kid+8, k->keyid+2))          if (!s || !strcmp (kid+8, keyid))
175              continue;              continue;
176          u = utf8_to_wincp (s, strlen (s));          ComboBox_AddString_utf8 (GetDlgItem (dlg, IDC_ADDREV_KEYLIST), s);
         SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_ADDSTRING,  
                             0, (WPARAM)(char *)u);  
         free (u);  
177      }      }
178        
179      gpg_keycache_rewind (pub);      gpg_keycache_rewind (pub);
180      n = SendDlgItemMessage( dlg, IDC_ADDREV_KEYLIST, CB_GETCOUNT, 0, 0 );      /* In the second loop, we set a key pointer for each element. */
181        n = SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_GETCOUNT, 0, 0);
182      for (i = 0; i < n; i++) {      for (i = 0; i < n; i++) {
183          gpg_keycache_next_key (pub, 0, &key);          gpg_keycache_next_key (pub, 0, &key);
184          SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETITEMDATA,          SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETITEMDATA,
# Line 163  do_init_keylist (HWND dlg, winpt_key_t k Line 191  do_init_keylist (HWND dlg, winpt_key_t k
191  /* Add a new user-id to the list view @lv. */  /* Add a new user-id to the list view @lv. */
192  static void  static void
193  do_add_new_userid (listview_ctrl_t lv,  do_add_new_userid (listview_ctrl_t lv,
194                     const char * name, const char *email, const char * comment)                     const char *utf8_name, const char *email,
195                       const char *utf8_comment)
196  {  {
197      char * p;      StringBuffer p;
198      size_t n;      char *native;
199            
200      n = strlen (name) + strlen (email) + 16;      if (utf8_comment != NULL)
201      if (comment)          p = p + utf8_name + " (" + utf8_comment + ")";
         n += strlen (comment);  
     p = new char[n+1];  
     if (!p)  
         BUG( NULL );  
     if (comment)  
         sprintf (p, "%s (%s)", name, comment);  
202      else      else
203          sprintf (p, "%s", name);          p = p + utf8_name;
204        native = utf8_to_native (p.getBuffer ());
205    
206      listview_add_item (lv, "");      listview_add_item (lv, "");
207      listview_add_sub_item (lv, 0, 0, _("Ultimate" ));      listview_add_sub_item (lv, 0, UID_COL_VALID, _("Ultimate" ));
208      listview_add_sub_item (lv, 0, 1, p);      listview_add_sub_item (lv, 0, UID_COL_NAME, native);
209      listview_add_sub_item (lv, 0, 2, email && *email? email : "");      listview_add_sub_item (lv, 0, UID_COL_EMAIL, email && *email? email : "");
210      listview_add_sub_item (lv, 0, 3, get_key_created (time (NULL)));      listview_add_sub_item (lv, 0, UID_COL_CREATION,
211      free_if_alloc (p);                             get_key_created (time (NULL)));
212  } /* do_add_new_userid */      free_if_alloc (native);
213    }
214    
215    
216  static void  static void
217  do_add_new_subkey (listview_ctrl_t lv, KEYGEN_CB *keygen, unsigned int flags)  do_add_new_subkey (listview_ctrl_t lv, keygen_cb_t keygen, unsigned int flags)
218  {  {
219      char info[128], keyid[32];      char info[128], keyid[32];
220      const char * expdate, * s;      const char *expdate, *s, *kid;
221      int n;      int n;
222            
223      expdate = keygen->expire? get_key_expire_date (keygen->expire) : _("Never");      expdate = keygen->expire? get_key_expire_date (keygen->expire) : _("Never");
224      _snprintf (info, sizeof info-1, "%d-bit %s",      _snprintf (info, DIM (info)-1, "%d-bit %s", keygen->bits,
                keygen->bits,  
225                 get_key_pubalgo ((gpgme_pubkey_algo_t)keygen->algo));                 get_key_pubalgo ((gpgme_pubkey_algo_t)keygen->algo));
226      _snprintf (keyid, sizeof keyid-1, "0x%s", keygen->fpr+32);      kid = get_keyid_from_fpr (keygen->fpr);
227        _snprintf (keyid, DIM (keyid)-1, "0x%s", kid);
228        s = get_key_created (time (NULL));
229      n = listview_count_items (lv, 0);      n = listview_count_items (lv, 0);
230      listview_add_item_pos (lv, n);      listview_add_item_pos (lv, n);
231      listview_add_sub_item (lv, n, 0, info);      listview_add_sub_item (lv, n, SUBK_COL_DESC, info);
232      listview_add_sub_item (lv, n, 1, keyid);      listview_add_sub_item (lv, n, SUBK_COL_KEYID, keyid);
233      listview_add_sub_item (lv, n, 2, get_key_created (time (NULL)));      listview_add_sub_item (lv, n, SUBK_COL_CREATION, s);
234      listview_add_sub_item (lv, n, 3, expdate);      listview_add_sub_item (lv, n, SUBK_COL_EXPIRES, expdate);
235      if (flags & KM_FLAG_REVOKED) s = _("Revoked");            if (flags & KM_FLAG_REVOKED)
236      else if (flags & KM_FLAG_EXPIRED) s = _("Expired");          s = _("Revoked");      
237      else s = _("OK");      else if (flags & KM_FLAG_EXPIRED)
238      listview_add_sub_item (lv, n, 4, s);          s = _("Expired");
239  } /* do_add_new_subkey */      else
240            s = _("OK");
241        listview_add_sub_item (lv, n, SUBK_COL_STATUS, s);
242    }
243    
244    
245  /* Try to find the GPG edit key index which belongs to the user ID  /* Try to find the GPG edit key index which belongs to the user ID
246     given by @name. If @r_inf != NULL, the info context will be returned.     given by the email address @email, @name is used as a fallback.
247       If @r_inf != NULL, the info context will be returned.
248     Return value: index of the user ID or -1 on error. */     Return value: index of the user ID or -1 on error. */
249  static int  static int
250  do_find_userid (const char *keyid, const char *name, gpg_uid_info_t *r_inf)  do_find_userid (const char *keyid, const char *email,
251                    const char *name, gpg_uid_info_t *r_inf)
252  {  {
253      GpgKeyEdit *ke;      GpgKeyEdit ke;
254      gpgme_error_t err;      gpgme_error_t err;
255      gpg_uid_info_t inf, ui;      gpg_uid_info_t inf, ui;
256      int pos = -1;      int pos = -1;
257    
258      ke = new GpgKeyEdit (keyid);      ke.setKeyID (keyid);
259      if (!ke)      err = ke.getUseridInfo (&inf);
         BUG (NULL);  
     err = ke->getUseridInfo (&inf);  
     delete ke;  
260      if (err) {      if (err) {
261          log_box (_("user ID"), MB_ERR,          log_box (_("user ID"), MB_ERR,
262                  _("Could not get key information for: \"%s\":\n%s"),                   _("Could not get key information for: \"%s\":\n%s"),
263                  name, gpgme_strerror (err));                   name, gpgme_strerror (err));
264          return -1;          return -1;
265      }      }
266    
267      for (ui = inf; ui; ui = ui->next) {      for (ui = inf; ui; ui = ui->next) {
268          if (!strcmp (ui->email, name)) {          if (name && email && ui->email && ui->name) {
269                if (!strcmp (ui->email, email) &&
270                    !strncmp (ui->name, name, strlen (name))) {
271                    pos = ui->index;
272                    break;
273                }
274                continue;
275            }
276            if (email && ui->email) {
277                if (!strcmp (ui->email, email)) {
278                    pos = ui->index;
279                    break;
280                }
281                /* The email address is more unique, use the name just
282                   as the fallbck when no email address is available. */
283                continue;
284            }
285            if (ui->name && name && !strcmp (ui->name, name)) {
286              pos = ui->index;              pos = ui->index;
287              break;              break;
288          }          }
# Line 250  do_find_userid (const char *keyid, const Line 295  do_find_userid (const char *keyid, const
295  }  }
296    
297    
298    /* Return true if @fname is a JPEG file. */
299    bool
300    is_jpg_file (const char *fname)
301    {
302        FILE *fp;
303        BYTE buf[10];
304        int n;
305    
306        fp = fopen (fname, "rb");
307        if (!fp)
308            return false;
309        n = fread (buf, 1, DIM (buf), fp);
310        fclose (fp);
311        if (n < DIM (buf))
312            return false;
313        return buf[6] == 'J' && buf[7] == 'F' &&
314               buf[8] == 'I' && buf[9] == 'F';
315    }
316    
317    
318  /* Dialog box procedure to add a photo. */  /* Dialog box procedure to add a photo. */
319  BOOL CALLBACK  BOOL CALLBACK
320  keyedit_addphoto_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  keyedit_addphoto_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
321  {  {
322      static winpt_key_t k;              static keyedit_cb_t cb;
323      GpgKeyEdit *ke;      gpgme_error_t err;
324      gpgme_error_t ec;          const char *s;    
325      const char * s;          char file[128];
     char pwd[128], file[128];  
326      int id;      int id;
327    
328      switch( msg ) {      switch (msg) {
329      case WM_INITDIALOG:      case WM_INITDIALOG:
330          k = (winpt_key_t)lparam;          cb = (keyedit_cb_t)lparam;
331          if (!k)          if (!cb)
332              BUG (NULL);              BUG (NULL);
333          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 advised."));
334          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."));
335          SetDlgItemText (dlg, IDC_ADDPHOTO_PWDINF, _("Passphrase"));          SetDlgItemText (dlg, IDC_ADDPHOTO_PWDINF, _("Passphrase"));
336          SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));          SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
337          SetWindowText (dlg, _("Add Photo ID"));          SetWindowText (dlg, _("Add Photo ID"));
338          SetForegroundWindow (dlg);          SetForegroundWindow (dlg);
339          break;          break;
340    
     case WM_DESTROY:  
         break;  
   
     case WM_SYSCOMMAND:  
         if( LOWORD (wparam) == SC_CLOSE )  
             EndDialog( dlg, TRUE );  
         break;  
   
341      case WM_COMMAND:      case WM_COMMAND:
342          switch( LOWORD( wparam ) ) {          switch( LOWORD (wparam)) {
   
343          case IDC_ADDPHOTO_SELFILE:          case IDC_ADDPHOTO_SELFILE:
344              s = get_fileopen_dlg( dlg, _("Select Image File"), _("JPEG Files (*.jpg, *.jpeg)\0*.jpg;*.jpeg\0\0"), NULL );              s = get_fileopen_dlg (dlg, _("Select Image File"),
345              if( s && *s )                                    "JPEG Files (*.jpg, *.jpeg)\0*.jpg;*.jpeg\0\0",
346                  SetDlgItemText( dlg, IDC_ADDPHOTO_FILE, s );                                    NULL);
347                if (s && !is_jpg_file (s)) {
348                    log_box (_("Add Photo"), MB_ERR,
349                             _("'%s' is not a valid JPEG file."), s);
350                    return FALSE;
351                }
352                if (s && *s)
353                    SetDlgItemText (dlg, IDC_ADDPHOTO_FILE, s);
354              break;              break;
355    
356          case IDOK:          case IDOK:
357              if( !GetDlgItemText( dlg, IDC_ADDPHOTO_FILE, file, sizeof file-1 ) ){              if (!GetDlgItemText (dlg, IDC_ADDPHOTO_FILE, file, sizeof (file)-1)){
358                  msg_box( dlg, _("Please enter a file name."), _("Add Photo"), MB_ERR );                  msg_box (dlg, _("Please enter a file name."),
359                             _("Add Photo"), MB_ERR);
360                  return FALSE;                  return FALSE;
361              }              }
362              if( get_file_size( file ) == 0 || get_file_size( file ) > 6144 ) {              if (get_file_size (file) == 0 || get_file_size (file) > 6144) {
363                  id = msg_box( dlg, _("The JPEG is really large.\n"                  id = msg_box (dlg, _("The JPEG is really large.\n"
364                                       "Are you sure you want to use it?"),                                       "Are you sure you want to use it?"),
365                                       _("Add Photo"), MB_YESNO|MB_INFO );                                       _("Add Photo"), MB_YESNO|MB_INFO);
366                  if( id == IDNO )                  if (id == IDNO)
367                      return TRUE;                      return TRUE;
368              }              }
369              if( k->is_protected ) {              
370                  if( !GetDlgItemText( dlg, IDC_ADDPHOTO_PASS, pwd, sizeof pwd-1 ) ) {              {
371                      msg_box( dlg, _("Please enter a passphrase."), _("Add Photo"), MB_ERR );                  GpgKeyEdit ke;
372                      return FALSE;                  
373                  }                  ke.setKeyID (cb->keyid);
374                    if (cb->pass)
375                        ke.setPassphrase (cb->pass);
376                    else
377                        ke.setNoPassphrase (true);
378                    err = ke.addPhotoid (file);
379              }              }
380              ke = new GpgKeyEdit (k->keyid);              if (err) {
381              if (!ke)                  msg_box (dlg, gpgme_strerror (err), _("Add Photo"), MB_ERR);
                 BUG (NULL);  
   
             if (k->is_protected)  
                 ke->setPassphrase (pwd);  
             ec = ke->addPhotoid (file);  
             delete ke;  
             memset (pwd, 0, sizeof pwd);  
             if (ec) {  
                 msg_box (dlg, gpgme_strerror (ec), _("Add Photo"), MB_ERR );  
382                  return FALSE;                  return FALSE;
383              }              }
384              else {              else {
385                  k->update = 1;                  cb->finished = 1;
386                  msg_box (dlg, _("Photo successfully added."), _("GnuPG Status"), MB_OK);                  msg_box (dlg, _("Photo successfully added."),
387                             _("GnuPG Status"), MB_OK);
388              }              }
389              EndDialog (dlg, TRUE);              EndDialog (dlg, TRUE);
390              break;              break;
# Line 343  keyedit_addphoto_dlg_proc (HWND dlg, UIN Line 403  keyedit_addphoto_dlg_proc (HWND dlg, UIN
403  BOOL CALLBACK  BOOL CALLBACK
404  keyedit_addrevoker_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  keyedit_addrevoker_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
405  {  {
406      static winpt_key_t k;      static keyedit_cb_t cb;
     static gpgme_key_t seckey;      
     GpgKeyEdit *ke;  
407      gpgme_error_t err;      gpgme_error_t err;
408      char uid[128], pwd[128];      char *uid=NULL;
       
409    
410      switch( msg ) {      switch (msg) {
411      case WM_INITDIALOG:      case WM_INITDIALOG:
412          k = (winpt_key_t)lparam;          cb = (keyedit_cb_t)lparam;
413          if( !k )          if (!cb)
414              BUG( NULL );              BUG (NULL);
415          if( get_seckey( k->keyid, &seckey ) )            do_init_keylist (dlg, cb->keyid);
416              BUG( NULL );          SetDlgItemText (dlg, IDC_ADDREV_INF,
417          if (!k->is_protected)                          _("Appointing a key as designated revoker cannot be undone."));
             EnableWindow (GetDlgItem (dlg, IDC_ADDREV_PASS), FALSE);  
         do_init_keylist (dlg, k);  
         SetDlgItemText (dlg, IDC_ADDREV_INF, _("Appointing a key as designated revoker cannot be undone."));  
418          SetDlgItemText (dlg, IDC_ADDREV_KEYINF, _("Public key"));          SetDlgItemText (dlg, IDC_ADDREV_KEYINF, _("Public key"));
419          SetDlgItemText (dlg, IDC_ADDREV_PWDINF, _("Passphrase"));          SetDlgItemText (dlg, IDC_ADDREV_PWDINF, _("Passphrase"));
420          SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));          SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
421          SetWindowText (dlg, _("Add Revoker"));            SetWindowText (dlg, _("Add Revoker"));
422          SetForegroundWindow (dlg);          SetForegroundWindow (dlg);
423          break;          center_window (dlg, cb->parent);
   
     case WM_DESTROY:      
         break;  
   
     case WM_SYSCOMMAND:  
         if( LOWORD (wparam) == SC_CLOSE )  
             EndDialog( dlg, TRUE );  
424          break;          break;
425    
426      case WM_COMMAND:      case WM_COMMAND:
427          switch( LOWORD( wparam ) ) {          switch (LOWORD (wparam)) {
428          case IDOK:                    case IDOK:
429              if( !GetDlgItemText( dlg, IDC_ADDREV_KEYLIST, uid, sizeof uid-1 ) ) {              if (!GetDlgItemText_utf8 (dlg, IDC_ADDREV_KEYLIST, &uid)) {
430                  msg_box( dlg, _("Please select a user ID."), _("Add Revoker"), MB_ERR );                  msg_box (dlg, _("Please select a user ID."), _("Add Revoker"), MB_ERR);
431                  return FALSE;                  return FALSE;
432              }              }
433                    
434              if( k->is_protected ) {              {
435                  if( !GetDlgItemText( dlg, IDC_ADDREV_PASS, pwd, sizeof pwd-1 ) ) {                  GpgKeyEdit ke;
436                      msg_box( dlg, _("Please enter the passphrase."), _("Add Revoker"), MB_ERR );                  
437                      return FALSE;                  ke.setKeyID (cb->keyid);
438                  }                  if (cb->pass)
439              }                      ke.setPassphrase (cb->pass);
440              ke = new GpgKeyEdit (k->keyid);                  else
441              if (k->is_protected)                      ke.setNoPassphrase (true);
442                  ke->setPassphrase (pwd);                  err = ke.addDesignatedRevoker (uid);
443              err = ke->addDesignatedRevoker (uid);              }
444              delete ke;  
445              memset (pwd, 0, sizeof pwd);              safe_free (uid);
446              if (err) {              if (err) {
447                  msg_box (dlg, gpgme_strerror (err), _("Add Revoker"), MB_ERR);                  msg_box (dlg, gpgme_strerror (err), _("Add Revoker"), MB_ERR);
448                  return TRUE;                  return TRUE;
449              }              }
450              else {              else {
451                  k->update = 1;                  cb->finished = 1;
452                  msg_box (dlg, _("Revoker successfully addded."), _("GnuPG Status"), MB_OK);                  msg_box (dlg, _("Revoker successfully addded."),
453                             _("GnuPG Status"), MB_OK);
454              }              }
455              EndDialog( dlg, TRUE );              EndDialog (dlg, TRUE);
456              break;              break;
457    
458          case IDCANCEL:          case IDCANCEL:
459              EndDialog( dlg, FALSE );              EndDialog (dlg, FALSE);
460              break;              break;
461          }          }
462          break;          break;
# Line 421  keyedit_addrevoker_dlg_proc (HWND dlg, U Line 469  keyedit_addrevoker_dlg_proc (HWND dlg, U
469  BOOL CALLBACK  BOOL CALLBACK
470  keyedit_adduid_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  keyedit_adduid_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
471  {  {
472      static KEYEDIT_CB *ctx;      static keyedit_cb_t ctx;
473        keygen_cb_t keygen;
474      gpgme_error_t err;      gpgme_error_t err;
     GpgKeyEdit *ke;  
475      char *utf8_name = NULL;      char *utf8_name = NULL;
476      char name[128], email[128], comment[128];      char *utf8_comment = NULL;
477        char email[128];
478      int rc;      int rc;
479            
480      switch ( msg ) {      switch (msg) {
481      case WM_INITDIALOG:      case WM_INITDIALOG:
482          ctx = (KEYEDIT_CB *)lparam;          ctx = (keyedit_cb_t)lparam;
483          if( !ctx )          if (!ctx)
484              dlg_fatal_error(dlg, "Could not get dialog param!");              dlg_fatal_error(dlg, "Could not get dialog param!");
   
485          SetWindowText (dlg, _("Add new User ID"));          SetWindowText (dlg, _("Add new User ID"));
486          SetDlgItemText (dlg, IDC_ADDUID_INFNAME, _("&Name"));          SetDlgItemText (dlg, IDC_ADDUID_INFNAME, _("&Name"));
487          SetDlgItemText (dlg, IDC_ADDUID_INFEMAIL, _("&Email"));          SetDlgItemText (dlg, IDC_ADDUID_INFEMAIL, _("&Email"));
488          SetDlgItemText (dlg, IDC_ADDUID_INFCOMMENT, _("&Comment"));          SetDlgItemText (dlg, IDC_ADDUID_INFCOMMENT, _("&Comment"));
489          SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));          SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
490          SetForegroundWindow (dlg);          SetForegroundWindow (dlg);
491          return FALSE;          center_window (dlg, ctx->parent);
           
     case WM_SYSCOMMAND:  
         if (LOWORD (wparam) == SC_CLOSE) {  
             EndDialog(dlg, TRUE);  
         }  
492          return FALSE;          return FALSE;
493                    
494      case WM_COMMAND:      case WM_COMMAND:
495          switch ( LOWORD( wparam ) )  {          switch ( LOWORD( wparam ) )  {
496          case IDOK:          case IDOK:
497              rc = GetDlgItemText( dlg, IDC_ADDUID_NAME, name, sizeof name-1 );              keygen = (keygen_cb_t)ctx->opaque;
498                rc = GetDlgItemText_utf8 (dlg, IDC_ADDUID_NAME, &utf8_name);
499              if (!rc || rc < 5) {              if (!rc || rc < 5) {
500                  msg_box( dlg, _("Please enter a name (min. 5 chars.)"), _("UserID"), MB_ERR );                  msg_box (dlg, _("Please enter a name (min. 5 chars.)"),
501                             _("UserID"), MB_ERR);
502                    free_if_alloc (utf8_name);
503                  return FALSE;                  return FALSE;
504              }              }
505              if (strchr (name, '@')) {              if (strchr (utf8_name, '@')) {
506                  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"),
507                             _("UserID"), MB_INFO);
508                    free_if_alloc (utf8_name);
509                  return FALSE;                  return FALSE;
510              }              }
511                                      
512              if( !GetDlgItemText( dlg, IDC_ADDUID_EMAIL, email, sizeof email -1 ) ) {              if( !GetDlgItemText (dlg, IDC_ADDUID_EMAIL, email, sizeof (email) -1)) {
513                  msg_box( dlg, _("Please enter an email address."), _("UserID"), MB_ERR );                  msg_box (dlg, _("Please enter an email address."), _("UserID"), MB_ERR);
514                    free_if_alloc (utf8_name);
515                  return FALSE;                  return FALSE;
516              }              }
517              if( !strchr( email, '@' ) || strchr (email, ' ')) {              if (check_email_address (email)) {
518                  msg_box( dlg, _("Invalid email address."), _("UserID"), MB_ERR );                  msg_box (dlg, _("Invalid email address."), _("UserID"), MB_ERR);
519                    free_if_alloc (utf8_name);
520                  return FALSE;                  return FALSE;
521              }              }
522                            
523              rc = GetDlgItemText( dlg, IDC_ADDUID_COMMENT, comment, sizeof comment -1 );              rc = GetDlgItemText_utf8 (dlg, IDC_ADDUID_COMMENT, &utf8_comment);
524    
525              /* XXX: something is wrong with the encoding :-( */              {
526              utf8_name = wincp_to_utf8 (name, strlen (name));                  GpgKeyEdit ke;
527                    
528              ke = new GpgKeyEdit (ctx->keyid);                  ke.setKeyID (ctx->keyid);
529              if (!ke)                  if (ctx->is_protected)
530                  BUG (NULL);                      ke.setPassphrase (ctx->pass);
531              if (ctx->pass)                  else
532                  ke->setPassphrase (ctx->pass);                      ke.setNoPassphrase (true);
533              err = ke->addUserid (utf8_name? utf8_name : name,                  err = ke.addUserid (utf8_name, utf8_comment, email);
534                                   rc > 0? comment : NULL, email);              }
535              if (err)              if (err)
536                  msg_box (dlg, gpgme_strerror (err), _("UserID"), MB_ERR);                  msg_box (dlg, gpgme_strerror (err), _("UserID"), MB_ERR);
537              else {              else {
538                  msg_box (dlg, _("user ID successfully added."), _("GnuPG Status"), MB_OK);                  msg_box (dlg, _("user ID successfully added."), _("GnuPG Status"), MB_OK);
539                  ctx->finished = 1;                  ctx->finished = 1;
540                    /* The caller releases this items later. */
541                    keygen->name = utf8_name;
542                    keygen->comment = utf8_comment;
543                    keygen->email = m_strdup (email);
544              }              }
             delete ke;  
             free (utf8_name);  
             if (!err && ctx->lv)  
                 do_add_new_userid (ctx->lv, name, email, rc?comment : NULL);  
545              EndDialog (dlg, TRUE);              EndDialog (dlg, TRUE);
546              return TRUE;              return TRUE;
547                            
# Line 506  keyedit_adduid_dlg_proc (HWND dlg, UINT Line 556  keyedit_adduid_dlg_proc (HWND dlg, UINT
556  }  }
557    
558    
559  static int  /* Initalize a combo box with default key sizes (1024-4096). */
 diff_time (HWND dt, SYSTEMTIME *in_exp)  
 {  
     SYSTEMTIME exp, now;  
     double e=0, n=0;  
   
     if (in_exp)  
         memcpy (&exp, in_exp, sizeof (SYSTEMTIME));  
     else  
         DateTime_GetSystemtime (dt, &exp);  
     GetSystemTime (&now);  
     SystemTimeToVariantTime (&exp, &e);  
     SystemTimeToVariantTime (&now, &n);  
     if (n > e)  
         return 0;  
     return (int)(e-n);  
 }  
   
   
560  static void  static void
561  init_keysize_box (HWND dlg, int ctlid)  init_keysize_box (HWND dlg, int ctlid)
562  {  {
563        /* Array with standard key-length in bits. */
564      const char *sizelist[] = {      const char *sizelist[] = {
565          "1024", "1536", "2048", "2560", "3072", "3854", "4096", NULL          "1024", "1536",
566            "2048", "3072",
567            "4096", NULL
568      };      };
569      int i;      int i;
570    
571      for (i=0; sizelist[i] != NULL; i++)      for (i=0; sizelist[i] != NULL; i++)
572          SendDlgItemMessage (dlg, ctlid, CB_ADDSTRING, 0, (LPARAM)(char*)sizelist[i]);          SendDlgItemMessage (dlg, ctlid, CB_ADDSTRING, 0,
573                                (LPARAM)(char*)sizelist[i]);
574      SendDlgItemMessage (dlg, ctlid, CB_SETCURSEL, (WPARAM)2, 0);      SendDlgItemMessage (dlg, ctlid, CB_SETCURSEL, (WPARAM)2, 0);
575  }  }
576    
577    
578  static int  static int
579  get_keysize_from_box (HWND dlg, int ctlid)  get_keysize_from_box (HWND dlg, int ctlid)
580  {  {
# Line 547  get_keysize_from_box (HWND dlg, int ctli Line 585  get_keysize_from_box (HWND dlg, int ctli
585      if (pos == CB_ERR)      if (pos == CB_ERR)
586          return -1;          return -1;
587      SendDlgItemMessage (dlg, ctlid, CB_GETLBTEXT, pos, (LPARAM)(char*)buf);      SendDlgItemMessage (dlg, ctlid, CB_GETLBTEXT, pos, (LPARAM)(char*)buf);
588      return atol (buf);      return atoi (buf);
589  }  }
590    
591    
592    /* Create a time_t from a system time @st. */
593    time_t
594    w32_mktime (SYSTEMTIME *st)
595    {
596        struct tm tm;
597    
598        memset (&tm, 0, sizeof (tm));
599        tm.tm_year = st->wYear-1900;
600        tm.tm_mday = st->wDay+1;
601        tm.tm_mon = st->wMonth-1;
602        return mktime (&tm);
603    }
604    
605    
606    /* Dialog procedure for adding a new secondary key. */
607  BOOL CALLBACK  BOOL CALLBACK
608  keyedit_addsubkey_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  keyedit_addsubkey_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
609  {  {
610      static KEYEDIT_CB *ctx;      static keyedit_cb_t ctx;
611      static KEYGEN_CB *keygen;      keygen_cb_t keygen;
     GpgKeyEdit *ke;  
612      gpgme_error_t err;      gpgme_error_t err;
613      HWND lb;      SYSTEMTIME st;
614        HWND hwnd;
615      int index, size, valid;      int index, size, valid;
616            
617      switch (msg) {      switch (msg) {
618      case WM_INITDIALOG:      case WM_INITDIALOG:
619          ctx = (KEYEDIT_CB *)lparam;          ctx = (keyedit_cb_t)lparam;
620          if (!ctx)          if (!ctx)
621              dlg_fatal_error (dlg, "Could not get dialog param!");              BUG (NULL);
         keygen = (KEYGEN_CB *)ctx->opaque;  
   
622          SetWindowText (dlg, _("Add new Subkey"));          SetWindowText (dlg, _("Add new Subkey"));
623          SetDlgItemText (dlg, IDC_ADDSUBKEY_INFALGO, _("Key type"));          SetDlgItemText (dlg, IDC_ADDSUBKEY_INFALGO, _("Key type"));
624          SetDlgItemText (dlg, IDC_ADDSUBKEY_INFSIZE, _("Size in bits"));          SetDlgItemText (dlg, IDC_ADDSUBKEY_INFSIZE, _("Size in bits"));
# Line 575  keyedit_addsubkey_dlg_proc (HWND dlg, UI Line 626  keyedit_addsubkey_dlg_proc (HWND dlg, UI
626          SetDlgItemText (dlg, IDC_ADDSUBKEY_EXPIRE, _("&Never"));          SetDlgItemText (dlg, IDC_ADDSUBKEY_EXPIRE, _("&Never"));
627          SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));          SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
628    
629          lb = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);          hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
630          listbox_add_string (lb, "DSA (sign only)");          listbox_add_string (hwnd, "DSA (sign only)");
631          listbox_add_string (lb, "ElGamal (encrypt only)");          listbox_add_string (hwnd, "ElGamal (encrypt only)");
632          listbox_add_string (lb, "RSA (sign only)");          listbox_add_string (hwnd, "RSA (sign only)");
633          listbox_add_string (lb, "RSA (encrypt only)");          listbox_add_string (hwnd, "RSA (encrypt only)");
634          CheckDlgButton (dlg, IDC_ADDSUBKEY_EXPIRE, BST_CHECKED);          CheckDlgButton (dlg, IDC_ADDSUBKEY_EXPIRE, BST_CHECKED);
635          EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);          EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
636          init_keysize_box (dlg, IDC_ADDSUBKEY_SIZE);          init_keysize_box (dlg, IDC_ADDSUBKEY_SIZE);
637          SetForegroundWindow (dlg);          SetForegroundWindow (dlg);
638          return FALSE;          center_window (dlg, ctx->parent);
           
     case WM_SYSCOMMAND:  
         if( LOWORD (wparam) == SC_CLOSE ) {  
             EndDialog( dlg, TRUE );  
         }  
639          return FALSE;          return FALSE;
640                    
641      case WM_COMMAND:      case WM_COMMAND:
642          if (HIWORD (wparam) == BN_CLICKED && LOWORD (wparam) == IDC_ADDSUBKEY_EXPIRE) {          if (HIWORD (wparam) == BN_CLICKED &&
643                LOWORD (wparam) == IDC_ADDSUBKEY_EXPIRE) {
644              if (IsDlgButtonChecked (dlg, IDC_ADDSUBKEY_EXPIRE))              if (IsDlgButtonChecked (dlg, IDC_ADDSUBKEY_EXPIRE))
645                  EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);                  EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
646              else              else
647                  EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), TRUE);                  EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), TRUE);
648          }          }
649          if (HIWORD (wparam) == LBN_SELCHANGE && LOWORD (wparam) == IDC_ADDSUBKEY_ALGO) {          if (HIWORD (wparam) == LBN_SELCHANGE &&
650                LOWORD (wparam) == IDC_ADDSUBKEY_ALGO) {
651                /* If the selected algorithm is DSA, automatically set the
652                   size to 1024, otherwise use the default keysize. */
653              index = SendMessage ((HWND)lparam, LB_GETCURSEL, 0, 0);              index = SendMessage ((HWND)lparam, LB_GETCURSEL, 0, 0);
654              if (index == 0)              SendDlgItemMessage (dlg, IDC_ADDSUBKEY_SIZE, CB_SETCURSEL,
655                  SendDlgItemMessage (dlg, IDC_ADDSUBKEY_SIZE, CB_SETCURSEL, 0, 0);                                  index==0? 0 : 2, 0);
656          }          }
657    
658          switch ( LOWORD(wparam) ) {                  switch (LOWORD (wparam)) {
659          case IDOK:          case IDOK:
660              lb = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);              keygen = (keygen_cb_t)ctx->opaque;
661              switch (listbox_get_cursel (lb)) {              assert (keygen);
662                hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
663                /* Map combo box numbers to GPG answers. */
664                switch (listbox_get_cursel (hwnd)) {
665              case 0: index = 2; break;              case 0: index = 2; break;
666              case 1: index = 4; break;              case 1: index = 4; break;
667              case 2: index = 5; break;              case 2: index = 5; break;
668              case 3: index = 6; break;              case 3: index = 6; break;
669              default:              default:
670                  msg_box( dlg, _("Please select one entry."), _("Add Subkey"), MB_ERR );                  msg_box (dlg, _("Please select one entry."),
671                             _("Add Subkey"), MB_ERR);
672                  return FALSE;                  return FALSE;
673              }              }
674              size = get_keysize_from_box (dlg, IDC_ADDSUBKEY_SIZE);              size = get_keysize_from_box (dlg, IDC_ADDSUBKEY_SIZE);
675              if (index == 2 && size != 1024) {              if (index == 2 && size != 1024) {
676                  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."),
677                             _("Add Subkey"), MB_INFO);
678                  size = 1024;                  size = 1024;
679              }              }
680              valid = diff_time (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), NULL);  
681                hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE);
682                DateTime_GetSystemtime (hwnd, &st);
683                valid = w32_mktime (&st) - time (NULL);
684                valid /= 86400;
685    
686              keygen->bits = size;              keygen->bits = size;
687              switch (index) {              switch (index) {
# Line 634  keyedit_addsubkey_dlg_proc (HWND dlg, UI Line 693  keyedit_addsubkey_dlg_proc (HWND dlg, UI
693              if (valid > 0)              if (valid > 0)
694                  keygen->expire = time (NULL) + valid*24*60*60;                  keygen->expire = time (NULL) + valid*24*60*60;
695    
696              ke = new GpgKeyEdit (ctx->keyid);              {
697              if (!ke)                  GpgKeyEdit ke;
698                  BUG (NULL);                  
699              ke->setCallback (keygen_cb, NULL);                  ke.setKeyID (ctx->keyid);
700              if (ctx->pass)                  ke.setCallback (keygen_cb, NULL);
701                  ke->setPassphrase (ctx->pass);                        if (ctx->is_protected)
702              keygen_cb_dlg_create ();                      ke.setPassphrase (ctx->pass);
703                    else
704              err = ke->addSubkey ((gpgme_pubkey_algo_t)index, size, valid);                      ke.setNoPassphrase (true);
705              keygen->fpr = get_subkey_fingerprint (ctx->keyid);                  keygen_cb_dlg_create ();
706              keygen_cb_dlg_destroy ();                  err = ke.addSubkey ((gpgme_pubkey_algo_t)index, size, valid);
707              keygen_cb (NULL, NULL, 0, 0, 0); /* flush */              }
708                keygen->fpr = get_subkey_keyid (ctx->keyid);
709                keygen_cb_dlg_destroy (1);
710              if (err)              if (err)
711                  msg_box (dlg, gpgme_strerror (err), _("Add Subkey"), MB_ERR);                  msg_box (dlg, gpgme_strerror (err), _("Add Subkey"), MB_ERR);
712              else {              else {
713                  msg_box (dlg, _("Subkey successfully added."), _("GnuPG Status"), MB_OK);                  msg_box (dlg, _("Subkey successfully added."),
714                  if (ctx->lv)                           _("GnuPG Status"), MB_OK);
                     do_add_new_subkey (ctx->lv, keygen, /*XXXk->flags*/0);  
715                  ctx->finished = 1;                  ctx->finished = 1;
716              }              }
717              delete ke;              EndDialog (dlg, TRUE);
             EndDialog (dlg, TRUE);  
718              return TRUE;              return TRUE;
719                            
720          case IDCANCEL:          case IDCANCEL:
721              EndDialog( dlg, FALSE );              EndDialog (dlg, FALSE);
722              return FALSE;              return FALSE;
723          }          }
724          break;          break;
725      }      }
726            
727      return FALSE;      return FALSE;
728  } /* keyedit_addsubkey_dlg_proc */  }
729    
730    
731  BOOL  BOOL
732  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)
733  {  {
734      KEYEDIT_CB cb;      keyedit_cb_s cb;
735        keygen_cb_s keygen;
736      char *pass = NULL;      char *pass = NULL;
737      int cancel = 0;      int cancel = 0;
738    
739      if (!k->key_pair) {      if (!k->key_pair) {
740          msg_box( dlg, _("There is no secret key available!"), _("Add user ID"), MB_ERR );          msg_box (dlg, _("There is no secret key available!"),
741                     _("Add user ID"), MB_ERR);
742          return FALSE;          return FALSE;
743      }      }
744    
745      if (k->is_protected) {      if (k->is_protected) {
746          pass = request_passphrase( _("Key Edit"), 1, &cancel );          pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
747          if (cancel)          if (cancel)
748              return FALSE;              return FALSE;
749      }      }
750              
751      memset (&cb, 0, sizeof cb);      memset (&keygen, 0, sizeof (keygen));
752      cb.pass = k->is_protected? pass : NULL;      memset (&cb, 0, sizeof (cb));
753      cb.lv = lv;      cb.parent = dlg;
754        cb.opaque = &keygen;
755        cb.is_protected = k->is_protected;
756        cb.pass = pass;
757      cb.keyid = k->keyid;      cb.keyid = k->keyid;
758      dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDUID,      dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDUID,
759                        dlg, keyedit_adduid_dlg_proc,                                dlg, keyedit_adduid_dlg_proc,        
760                        (LPARAM)&cb, _("Add user ID"),                        (LPARAM)&cb, _("Add user ID"),
761                        IDS_WINPT_KEYEDIT_ADDUID);                        IDS_WINPT_KEYEDIT_ADDUID);
762        if (lv != NULL && cb.finished)
763            do_add_new_userid (lv, keygen.name, keygen.email, keygen.comment);
764      if (cb.finished)      if (cb.finished)
765          k->update = 1;          k->update = 1;
766    
767        free_if_alloc (keygen.name);
768        free_if_alloc (keygen.email);
769        free_if_alloc (keygen.comment);
770      sfree_if_alloc (pass);      sfree_if_alloc (pass);
771      return TRUE;      return TRUE;
772  }  }
773    
774    
775    /* Return the keyID of the last subkey. */
776  char*  char*
777  get_subkey_fingerprint (const char *keyid)  get_subkey_keyid (const char *keyid)
778  {  {
779      gpgme_error_t err;      gpgme_error_t err;
780      gpgme_key_t key, main;      gpgme_key_t key;
781      gpgme_ctx_t ctx;      gpgme_ctx_t ctx;
782      gpgme_subkey_t last_sk, k, new_sk;      gpgme_subkey_t subk;
783      int n;      char *kid = NULL;
784    
785      err = gpgme_new (&ctx);      err = gpgme_new (&ctx);
786      if (err)      if (err)
787          return NULL;          return NULL;
788      err = gpgme_get_key (ctx, keyid, &key, 0);      err = gpgme_get_key (ctx, keyid, &key, 0);
789        gpgme_release (ctx);
790      if (err)      if (err)
791          return NULL;          return NULL;
792      /* XXX: this is very slow and complicated */      subk = get_nth_key (key, count_subkeys (key));
793            if (subk != NULL)
794      n = count_subkeys (key);          kid = strdup (subk->keyid);
     last_sk = get_nth_key (key, n-1);  
     new_sk = (gpgme_subkey_t)calloc (1, sizeof *new_sk);  
     if (!new_sk)  
         BUG (NULL);  
     memcpy (new_sk, last_sk, sizeof *last_sk);  
     new_sk->fpr = strdup (last_sk->fpr);  
     new_sk->keyid = strdup (last_sk->keyid);  
   
     get_pubkey (keyid, &main);  
     for (k=main->subkeys; k->next; k=k->next)  
         ;  
     k->next = new_sk;  
   
795      gpgme_key_release (key);      gpgme_key_release (key);
796      return new_sk->fpr;      return kid;
797  }  }
798    
799    
800  BOOL  BOOL
801  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)
802  {  {
803      KEYEDIT_CB cb;      keyedit_cb_s cb;
804      KEYGEN_CB keygen;      keygen_cb_s keygen;
805      char *pass = NULL;      char *pass = NULL;
806      int cancel = 0;      int cancel = 0;
807    
808      if (!k->key_pair) {      if (!k->key_pair) {
809          msg_box (dlg, _("There is no secret key available!"), _("Add Subkey"), MB_ERR);          msg_box (dlg, _("There is no secret key available!"),
810                     _("Add Subkey"), MB_ERR);
811          return FALSE;          return FALSE;
812      }      }
813      if (k->is_protected) {      if (k->is_protected) {
814          pass = request_passphrase (_("Key Edit"), 1, &cancel);          pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
815          if (cancel)          if (cancel)
816              return FALSE;              return FALSE;
817      }      }
# Line 761  keyedit_add_subkey (winpt_key_t k, HWND Line 819  keyedit_add_subkey (winpt_key_t k, HWND
819      memset (&keygen, 0, sizeof (keygen));      memset (&keygen, 0, sizeof (keygen));
820      memset (&cb, 0, sizeof (cb));      memset (&cb, 0, sizeof (cb));
821      cb.keyid = k->keyid;      cb.keyid = k->keyid;
822      cb.pass = k->is_protected? pass : NULL;      cb.is_protected = k->is_protected;
823        cb.pass = pass;
824      cb.opaque = &keygen;      cb.opaque = &keygen;
825      dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDSUBKEY,          dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDSUBKEY,    
826                        dlg, keyedit_addsubkey_dlg_proc,                        dlg, keyedit_addsubkey_dlg_proc,
827                        (LPARAM)&cb, _("Add new Subkey"),                        (LPARAM)&cb, _("Add new Subkey"),
828                        IDS_WINPT_KEYEDIT_ADDSUBKEY);                        IDS_WINPT_KEYEDIT_ADDSUBKEY);
829        if (lv != NULL && cb.finished)
830            do_add_new_subkey (lv, &keygen, 0);
831      if (cb.finished)      if (cb.finished)
832          k->update = 1;          k->update = 1;
833    
834      sfree_if_alloc (pass);          safe_free (keygen.fpr);
835        sfree_if_alloc (pass);
836      return cb.finished? TRUE: FALSE;      return cb.finished? TRUE: FALSE;
837  }  }
838    
839    
840    /* Set the preferred keyserver of the given key @k. */
841  BOOL  BOOL
842  keyedit_set_pref_keyserver (winpt_key_t k, HWND dlg)  keyedit_set_pref_keyserver (winpt_key_t k, HWND dlg)
843  {  {
844      GpgKeyEdit *ke;      GpgKeyEdit ke;
845      gpgme_error_t err;      gpgme_error_t err;
846      struct URL_ctx_s *url;      struct URL_ctx_s *url;
847      char *pass;      char *pass = NULL;
848    
849      url = (struct URL_ctx_s *)get_keyserver_URL_dlg (dlg);      url = (struct URL_ctx_s *)get_keyserver_URL_dlg (dlg);
850      if (url->cancel == 1) {      if (url->cancel == 1) {
# Line 789  keyedit_set_pref_keyserver (winpt_key_t Line 852  keyedit_set_pref_keyserver (winpt_key_t
852          return FALSE;          return FALSE;
853      }      }
854    
855      pass = request_passphrase (_("Key Edit"), 1, &url->cancel);      pass = request_key_passphrase (k->ctx, _("Key Edit"), &url->cancel);
856      if (url->cancel) {      if (url->cancel) {
857          delete url;          delete url;
858          return FALSE;          return FALSE;
859      }      }
860    
861      ke = new GpgKeyEdit (k->keyid);      ke.setKeyID (k->keyid);
862      if (!ke)      if (k->is_protected)
863          BUG (NULL);          ke.setPassphrase (pass);
864      ke->setPassphrase (pass);      else
865      err = ke->setPreferredKeyserver (0 /* XXX */, url->url);          ke.setNoPassphrase (true);
866        err = ke.setPreferredKeyserver (-1, url->url);
867      if (!err)      if (!err)
868          msg_box (dlg, _("Preferred keyserver successfully set."), _("Key Edit"), MB_OK);          msg_box (dlg, _("Preferred keyserver successfully set."),
869                     _("Key Edit"), MB_OK);
870        else
871            msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
872    
873      sfree_if_alloc (pass);      sfree_if_alloc (pass);
874      delete ke;      delete url;
     delete url;      
875      return err == 0? 0 : WPTERR_GENERAL;      return err == 0? 0 : WPTERR_GENERAL;
876  }  }
877    
# Line 815  keyedit_set_pref_keyserver (winpt_key_t Line 881  keyedit_set_pref_keyserver (winpt_key_t
881  BOOL  BOOL
882  keyedit_add_photo (winpt_key_t k, HWND dlg)  keyedit_add_photo (winpt_key_t k, HWND dlg)
883  {  {
884        keyedit_cb_s cb;
885        char *pass = NULL;
886        int cancel;
887        
888      if (!k->key_pair) {      if (!k->key_pair) {
889          msg_box (dlg, _("There is no secret key available!"), _("Add Photo"), MB_ERR);          msg_box (dlg, _("There is no secret key available!"),
890                     _("Add Photo"), MB_ERR);
891          return FALSE;          return FALSE;
892      }      }
893    
894        memset (&cb, 0, sizeof (cb));
895        if (k->is_protected) {
896            pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
897            if (cancel)
898                return FALSE;
899        }
900        cb.parent = dlg;
901        cb.pass = pass;
902        cb.keyid = k->keyid;
903      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDPHOTO, dlg,      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDPHOTO, dlg,
904                      keyedit_addphoto_dlg_proc, (LPARAM)k);                      keyedit_addphoto_dlg_proc, (LPARAM)&cb);
905    
906        if (cb.finished)
907            k->update = 1;
908        sfree_if_alloc (pass);    
909      return TRUE;      return TRUE;
910  }  }
911    
# Line 828  keyedit_add_photo (winpt_key_t k, HWND d Line 913  keyedit_add_photo (winpt_key_t k, HWND d
913  BOOL  BOOL
914  keyedit_add_revoker (winpt_key_t k, HWND dlg)  keyedit_add_revoker (winpt_key_t k, HWND dlg)
915  {  {
916      if( !k->key_pair ) {      keyedit_cb_s cb;
917          msg_box( dlg, _("There is no secret key available!"), _("Add Revoker"), MB_ERR );      char *pass = NULL;
918        int cancel;
919    
920        if (!k->key_pair) {
921            msg_box (dlg, _("There is no secret key available!"), _("Add Revoker"), MB_ERR);
922          return FALSE;          return FALSE;
923      }      }
924    
925        if (k->is_protected) {
926            pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
927            if (cancel)
928                return FALSE;
929        }
930    
931        memset (&cb, 0, sizeof (cb));
932        cb.parent = dlg;
933        cb.is_protected = k->is_protected;
934        cb.keyid = k->keyid;
935        cb.pass = pass;
936      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDREV, dlg,      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDREV, dlg,
937                      keyedit_addrevoker_dlg_proc, (LPARAM)k);                      keyedit_addrevoker_dlg_proc, (LPARAM)&cb);
938    
939        if (cb.finished)
940            k->update = 1;
941        sfree_if_alloc (pass);
942      return TRUE;      return TRUE;
943  } /* keyedit_add_revoker */  }
944    
945    
946    /* Change ownertrust of the given key @key.
947       Return TRUE if the ownertrust was changed. */
948    BOOL
949    keyedit_change_ownertrust (winpt_key_t key, HWND dlg)
950    {
951        int rc;
952    
953        rc = dialog_box_param (glob_hinst,
954                                 (LPCSTR)IDD_WINPT_KEYEDIT_OWNERTRUST,
955                                 dlg, keyedit_ownertrust_dlg_proc,
956                                 (LPARAM)key, _("Change Ownertrust"),
957                                 IDS_WINPT_KEYEDIT_OWNERTRUST);
958        if (rc == TRUE) {
959            msg_box (dlg, _("Key status changed."), _("Key Edit"), MB_OK);
960            key->update = 1;
961        }
962        return rc;
963    }
964    
965    
966    /* Check if the given key is supposed to have IDEA
967       for secret key protection. */
968  static int  static int
969  is_idea_protect_algo (const char * keyid)  is_idea_protect_algo (const char *keyid)
970  {  {
971      winpt_key_s k;      winpt_key_s k;
972      const unsigned char *sym_prefs;      const unsigned char *sym_prefs;
# Line 848  is_idea_protect_algo (const char * keyid Line 975  is_idea_protect_algo (const char * keyid
975      memset (&k, 0, sizeof (k));      memset (&k, 0, sizeof (k));
976      if (winpt_get_pubkey (keyid, &k))      if (winpt_get_pubkey (keyid, &k))
977          BUG (NULL);          BUG (NULL);
978        if (!k.is_v3)
979            return 0;
980      sym_prefs = k.ext->sym_prefs;      sym_prefs = k.ext->sym_prefs;
981        /* Assume that only v3 keys have no symmetric cipher
982           preferences and thus IDEA is explicit. */
983      if (!sym_prefs)      if (!sym_prefs)
984          return 1; /* assume that only v3 keys have no symmetric cipher preferences          return 1;
                      and thus IDEA is explicit. */  
985      for (n = 0; sym_prefs[n]; n++)      for (n = 0; sym_prefs[n]; n++)
986          ;          ;
987      if ((n == 0 || n == 1) && *sym_prefs == 0x01)      if ((n == 0 || n == 1) && *sym_prefs == 0x01)
988          return 1;          return 1;
989      return 0;      return 0;
990  } /* is_idea_protect_algo */  }
991    
992    
993  BOOL  BOOL
994  keyedit_change_passwd( winpt_key_t k, HWND dlg )  keyedit_change_passwd (winpt_key_t k, HWND dlg)
995  {  {
996      GpgKeyEdit *ke;      gpgme_error_t err;
997      gpgme_error_t ec;          GpgKeyEdit ke;
998      char *old_pass = NULL, *new_pass = NULL;      char *old_pass = NULL;
999        char *new_pass = NULL;
1000      int cancel = 0;      int cancel = 0;
1001    
1002      if( !k->key_pair ) {      if (!k->key_pair) {
1003          msg_box( dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR );          msg_box (dlg, _("There is no secret key available!"),
1004                     _("Key Edit"), MB_ERR);
1005          return FALSE;          return FALSE;
1006      }      }
1007    
1008      if( !idea_available && is_idea_protect_algo( k->keyid ) ) {      if (!idea_available && is_idea_protect_algo (k->keyid)) {
1009          msg_box( dlg, _("Cannot change passphrase because the key\n"          msg_box (dlg, _("Cannot change passphrase because the key\n"
1010                          "is protected with the IDEA encryption algorithm."),                          "is protected with the IDEA encryption algorithm."),
1011                          _("Key Edit"), MB_ERR );                          _("Key Edit"), MB_ERR);
1012          return FALSE;          return FALSE;
1013      }      }
1014    
1015      if( k->is_protected ) {      if (k->is_protected) {
1016          old_pass = request_passphrase( _("Current (old) Passphrase"), 1, &cancel );          old_pass = request_passphrase (_("Current (old) Passphrase"),
1017          if( cancel )                                         PASSDLG_INIT, &cancel);
1018            if (cancel)
1019              return FALSE;              return FALSE;
1020      }      }
1021      new_pass = request_passphrase( _("New Passphrase" ), 1, &cancel );      new_pass = request_passphrase2 (_("New Passphrase" ),
1022      if( cancel ) {                                      PASSDLG_INIT|PASSDLG_WARN_UTF8, &cancel);
1023          free_if_alloc( old_pass );      if (cancel) {
1024            sfree_if_alloc (old_pass);
1025          return FALSE;          return FALSE;
1026      }      }
1027    
1028      if( is_8bit_string( new_pass ) ) {      if (strlen (new_pass) == 0) {
1029          msg_box( dlg, _("The passphrase contains 8-bit characters.\n"          cancel = msg_box (dlg, _("Are you sure that you really don't want a passphrase?\n"
1030                           "It is not suggested to use charset specific characters."),                                   "This is propably a bad idea, continue?"),
1031                           _("Key Edit"), MB_ERR );                              _("Key Edit"), MB_WARN_ASK);
1032          free_if_alloc( old_pass );          if (cancel != IDYES) {
1033          free_if_alloc( new_pass );              sfree_if_alloc (old_pass);
1034          return FALSE;              sfree_if_alloc (new_pass);
1035                return FALSE;
1036            }
1037      }      }
1038    
1039      ke = new GpgKeyEdit (k->keyid);      ke.setKeyID (k->keyid);
1040      if (!ke)      ke.setPassphrase (k->is_protected? old_pass : NULL);
1041          BUG (NULL);      if (!k->is_protected)
1042            ke.setNoPassphrase (true);
1043      ke->setPassphrase (k->is_protected? old_pass : NULL);      err = ke.changePassphrase (new_pass, 1);
1044      ec = ke->changePassphrase (new_pass, 0);      if (err)
1045      if( ec )          msg_box (dlg, gpgme_strerror (err), _("Change Password"), MB_ERR);
         msg_box (dlg, gpgme_strerror (ec), _("Change Passwd"), MB_ERR);  
1046      else      else
1047          msg_box (dlg, _("Passphrase successfully changed."),  _("GnuPG status"), MB_OK);          msg_box (dlg, _("Passphrase successfully changed."),  _("GnuPG status"), MB_OK);
1048      sfree_if_alloc (old_pass);      sfree_if_alloc (old_pass);
1049      sfree_if_alloc (new_pass);      sfree_if_alloc (new_pass);
1050      delete ke;  
1051      return TRUE;      return TRUE;
1052  }  }
1053    
1054                    
1055    /* Initialize sub key list from key @k and return
1056       the new listview control. */
1057  listview_ctrl_t  listview_ctrl_t
1058  subkey_list_init( HWND dlg, winpt_key_t k )  subkey_list_init (HWND dlg, winpt_key_t k)
1059  {  {
1060      LV_ITEM lvi;      LV_ITEM lvi;
     gpgme_key_t key;  
1061      gpgme_subkey_t sub;      gpgme_subkey_t sub;
1062      struct listview_column_s cols[] = {      struct listview_column_s cols[] = {
1063          {0, 80, (char *)_("Description")},          {0, 80, (char *)_("Description")},
# Line 938  subkey_list_init( HWND dlg, winpt_key_t Line 1074  subkey_list_init( HWND dlg, winpt_key_t
1074      listview_ctrl_t lv;      listview_ctrl_t lv;
1075      char buf[256], tmp[128];      char buf[256], tmp[128];
1076      const char *t;      const char *t;
1077      int nkeys = 0, rc = 0, i, bits;          int nkeys = 0, i;
1078    
1079      if( get_pubkey( k->keyid, &key ) ) {      nkeys = count_subkeys (k->ctx);
1080          msg_box( dlg, _("Could not find key."), _("Key Edit"), MB_ERR );      if (!nkeys)
1081          return NULL;          BUG (NULL); /* should never happen. */
     }  
     nkeys = count_subkeys (key);  
     if( !nkeys ) {  
         msg_box( dlg, _("No subkey(s) found."), _("Key Edit"), MB_ERR );  
         return NULL;  
     }  
           
     rc  = listview_new( &lv );  
     if( rc )  
         BUG( dlg );  
1082                    
1083      lv->ctrl = GetDlgItem( dlg, IDC_KEYEDIT_KEYLIST );      listview_new (&lv, GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST));
1084      for( i = 0; cols[i].fieldname != NULL; i++ )          for (i = 0; cols[i].fieldname != NULL; i++)
1085          listview_add_column( lv, &cols[i] );          listview_add_column (lv, &cols[i]);
1086                    
1087      for( i = 0; i < nkeys; i++ ) {      for (i = 0, sub = k->ctx->subkeys; i < nkeys; i++, sub = sub->next) {
1088          listview_add_item( lv, "" );          listview_add_item (lv, "");
1089          listview_add_sub_item( lv, 0, 1, "" );          listview_add_sub_item (lv, 0, 1, "");
1090          memset( &lvi, 0, sizeof lvi );          memset (&lvi, 0, sizeof (lvi));
1091          lvi.mask = LVIF_PARAM;            lvi.mask = LVIF_PARAM;  
1092          lvi.lParam = (LPARAM )key;          lvi.lParam = (LPARAM)sub;
1093          if( ListView_SetItem( lv->ctrl, &lvi ) == FALSE )          if (ListView_SetItem (lv->ctrl, &lvi) == FALSE)
1094              return NULL;              BUG (NULL);
1095      }      }
1096                    
1097      listview_set_ext_style( lv );      listview_set_ext_style (lv);
1098      for( i = 0, sub = key->subkeys; i < nkeys; i++, sub = sub->next ) {      for (i = 0, sub = k->ctx->subkeys; i < nkeys; i++, sub = sub->next) {
1099          memset( buf, 0, sizeof buf );          _snprintf (buf, DIM (buf)-1, "%d-bit %s", sub->length,
1100                                    get_key_pubalgo (sub->pubkey_algo));
1101          bits = sub->length;          listview_add_sub_item (lv, i, SUBK_COL_DESC, buf);
         _snprintf( tmp, sizeof tmp-1, "%d-bit ", bits );  
         strcat( buf, tmp );  
   
         _snprintf( tmp, sizeof tmp-1, "%s", get_key_pubalgo (sub->pubkey_algo));  
         strcat( buf, tmp );  
           
         listview_add_sub_item( lv, i, 0, buf );  
1102          t = sub->keyid;          t = sub->keyid;
1103          if( !t )          assert (t != NULL);
1104              t = "DEADBEEFDEADBEEF";          _snprintf (tmp, DIM (tmp)-1, "0x%s", t+8);
1105          _snprintf( tmp, sizeof tmp-1, "0x%s", t+8 );          listview_add_sub_item (lv, i, SUBK_COL_KEYID, tmp);
         listview_add_sub_item( lv, i, 1, tmp );  
1106    
1107          t = get_key_created (sub->timestamp);          t = get_key_created (sub->timestamp);
1108          if( !t )          if (!t)
1109              t = "????" "-??" "-??";              t = "????" "-??" "-??";
1110          listview_add_sub_item( lv, i, 2, t );          listview_add_sub_item (lv, i, SUBK_COL_CREATION, t);
1111    
1112          if( sub->expires ) {          if (sub->expires) {
1113              t = get_key_created (sub->expires);              t = get_key_created (sub->expires);
1114              listview_add_sub_item( lv, i, 3, t );              listview_add_sub_item (lv, i, SUBK_COL_EXPIRES, t);
1115          }          }
1116          else          else
1117              listview_add_sub_item( lv, i, 3, _("Never") );              listview_add_sub_item (lv, i, SUBK_COL_EXPIRES, _("Never"));
1118            if (sub->expired)
         if( sub->expired )  
1119              t = _("Expired");              t = _("Expired");
1120          else if( sub->revoked )          else if (sub->revoked)
1121              t = _("Revoked");              t = _("Revoked");
1122          else          else
1123              t = _("OK");              t = _("OK");
1124          listview_add_sub_item( lv, i, 4, t );          listview_add_sub_item (lv, i, SUBK_COL_STATUS, t);
1125    
1126          if (sub->can_certify) t = "*"; else t = "";          if (sub->can_certify) t = "*"; else t = "";
1127          listview_add_sub_item (lv, i, 5, t);          listview_add_sub_item (lv, i, SUBK_COL_C_FLAG, t);
1128          if (sub->can_sign) t = "*"; else t = "";          if (sub->can_sign) t = "*"; else t = "";
1129          listview_add_sub_item( lv, i, 6, t );          listview_add_sub_item (lv, i, SUBK_COL_S_FLAG, t);
1130          if (sub->can_encrypt) t = "*"; else t = "";          if (sub->can_encrypt) t = "*"; else t = "";
1131          listview_add_sub_item( lv, i, 7, t );          listview_add_sub_item (lv, i, SUBK_COL_E_FLAG, t);
1132          if (sub->can_authenticate) t = "*"; else t = "";          if (sub->can_authenticate) t = "*"; else t = "";
1133          listview_add_sub_item (lv, i, 8, t);          listview_add_sub_item (lv, i, SUBK_COL_A_FLAG, t);
1134      }      }
1135      return lv;      return lv;
1136  } /* subkey_list_init */  }
1137    
1138    
1139  static listview_ctrl_t  static listview_ctrl_t
1140  userid_list_init (HWND dlg, winpt_key_t k)  userid_list_init (HWND dlg, winpt_key_t k)
1141  {  {
1142      listview_ctrl_t lv = NULL;      listview_ctrl_t lv = NULL;
     gpgme_key_t key;  
1143      gpgme_key_sig_t ks;      gpgme_key_sig_t ks;
1144      gpgme_user_id_t u;      struct native_uid_s *u;
1145      int nuids = 0, rc, j, u_attr;      int nuids = 0, j, u_attr;
1146      struct listview_column_s cols[] = {      struct listview_column_s cols[] = {
1147          {0,  72, (char *)_("Validity")},          {0,  72, (char *)_("Validity")},
1148          {1, 150, (char *)_("Name")},          {1, 150, (char *)_("Name")},
# Line 1035  userid_list_init (HWND dlg, winpt_key_t Line 1151  userid_list_init (HWND dlg, winpt_key_t
1151          {0, 0, 0}          {0, 0, 0}
1152      };          };    
1153      const char *attr;      const char *attr;
   
     if (get_pubkey( k->keyid, &key)) {  
         msg_box( dlg, _("Could not find key."), _("Key Edit"), MB_ERR );  
         return NULL;  
     }  
1154            
1155      nuids = count_userids (key);      nuids = count_userids (k->ctx);
1156      if (!nuids) {      if (!nuids)
1157          msg_box (dlg, _("No user ID(s) found."), _("Key Edit"), MB_ERR);          BUG (NULL); /* should never happen. */
         return NULL;  
     }  
1158                    
1159      rc = listview_new (&lv);      listview_new (&lv, GetDlgItem (dlg, IDC_KEYEDIT_UIDLIST));
1160      if( rc )      for (j = 0; cols[j].fieldname != NULL; j++)
1161          BUG( dlg );                  listview_add_column (lv, &cols[j]);
     lv->ctrl = GetDlgItem( dlg, IDC_KEYEDIT_UIDLIST );  
     for( j = 0; cols[j].fieldname != NULL; j++ )  
         listview_add_column( lv, &cols[j] );  
1162                    
1163      for( j = 0; j < nuids; j++ ) {                for (j = 0; j < nuids; j++) {
1164          listview_add_item( lv, " " );          listview_add_item (lv, " ");
1165          listview_add_sub_item( lv, 0, 1, " " );                  listview_add_sub_item (lv, 0, 1, " " );        
1166      }      }
1167    
1168      listview_set_ext_style (lv);      listview_set_ext_style (lv);
1169      for (j = 0, u=key->uids; j < nuids; u=u->next, j++) {      for (j = 0, u=k->ext->uids; j < nuids; u=u->next, j++) {
1170          if (u->revoked)          if (u->revoked)
1171              attr = _("Revoked");              attr = _("Revoked");
1172          else {          else {
1173              u_attr = (int)u->validity;              u_attr = (int)u->validity;
1174              attr = get_key_trust2 (NULL, u_attr, 0, 0);              attr = get_key_trust2 (NULL, u_attr, 0, 0);
1175          }          }
1176          listview_add_sub_item( lv, j, 0, (char *)attr );                  listview_add_sub_item (lv, j, UID_COL_VALID, (char *)attr);
   
1177          /* XXX: add comment if available */          /* XXX: add comment if available */
1178          attr = u->name;          listview_add_sub_item (lv, j, UID_COL_NAME,
1179          if (attr) {                                 u->name? u->name : _("Invalid user ID"));
1180              char * uid = utf8_to_wincp (attr, strlen (attr));          if (u->email)
1181              if (uid) {              listview_add_sub_item (lv, j, UID_COL_EMAIL, u->email);
                 listview_add_sub_item( lv, j, 1, uid );  
                 free( uid );  
             }  
         }  
         else  
             listview_add_sub_item( lv, j, 1, _("Invalid user ID") );  
         attr = u->email;  
         if (attr)  
             listview_add_sub_item (lv, j, 2, attr);  
1182    
1183          ks = get_selfsig (u, k->keyid+2, 1);          ks = get_selfsig (u->signatures, k->keyid, 1);
1184          if (ks)          if (ks)
1185              listview_add_sub_item (lv, j, 3, get_key_created (ks->timestamp));              listview_add_sub_item (lv, j, UID_COL_CREATION,
1186                                       get_key_created (ks->timestamp));
1187      }      }
1188      if( !k->key_pair ) {      if (!k->key_pair) {
1189          CheckDlgButton( dlg, IDC_KEYUID_ADD, BST_INDETERMINATE );          CheckDlgButton (dlg, IDC_KEYUID_ADD, BST_INDETERMINATE);
1190          CheckDlgButton( dlg, IDC_KEYUID_REVOKE, BST_INDETERMINATE );              CheckDlgButton (dlg, IDC_KEYUID_REVOKE, BST_INDETERMINATE);
1191      }      }
1192      return lv;      return lv;
1193  } /* userid_list_init */  }
1194    
1195    
1196  static void  static void
1197  do_init_cmdlist( HWND dlg )  do_init_cmdlist (HWND dlg, int is_keypair)
1198  {  {    
1199      const char *cmdlist[] = {      const char *s;
1200          "ADDKEY",      int i;
         "ADDUID",  
         "ADDPHOTO",  
         "ADDREVOKER",  
         /*"FPR",*/  
         "DELUID",  
         "DELKEY",  
         "DELPHOTO",  
         /*"DELSIG",*/  
         "EXPIRE",  
         /*"PREF",*/  
         "SHOWPREF",  
         /*"SETPREF",*/  
         "PASSWD",  
         "PRIMARY",  
         "TRUST",  
         /*"REVSIG",*/  
         "REVUID",  
         "REVKEY",  
         "DISABLE",  
         "ENABLE",  
         "SHOWPHOTO",  
         NULL  
     };  
     const char * s;  
     int i = 0;  
1201    
1202      for( i = 0; (s=cmdlist[i]); i++ ) {      for (i = 0; (s=cmdlist[i].name); i++) {
1203          SendDlgItemMessage( dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,          if (is_keypair)
1204                              (LPARAM)(char *)s );              SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,
1205                                    (LPARAM)(char *)s);
1206            else if (!cmdlist[i].need_pair)
1207                SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,
1208                                    (LPARAM)(char *)s);
1209      }      }
1210      SendDlgItemMessage( dlg, IDC_KEYEDIT_CMD, CB_SETCURSEL, 0, 0 );      SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_SETCURSEL, 0, 0);
1211  } /* do_init_cmdlist */  }
1212    
1213    
1214    /* Return 1 if the requested command is RFC2440. */
1215  static int  static int
1216  is_cmd_openpgp( int cmdid )  is_cmd_openpgp (int cmdid)
1217  {  {
1218      switch( cmdid ) {      switch (cmdid) {
1219      case CMD_ADDKEY:      case CMD_ADDKEY:
1220      case CMD_ADDPHOTO:      case CMD_ADDPHOTO:
1221      case CMD_ADDREVOKER:      case CMD_ADDREVOKER:
1222      case CMD_DELPHOTO:      case CMD_SETPREF:
     /*case CMD_SHOWPHOTO:*/  
     /*case CMD_SETPREF:*/  
1223          return 1;          return 1;
1224      }      }
1225      return 0;      return 0;
1226  } /* is_cmd_openpgp */  }
1227    
1228    
1229    /* Display a message box with a short description of the commands. */
1230  static void  static void
1231  do_show_help( HWND dlg )  do_show_help (HWND dlg)
1232  {  {
1233      char helptext[2048];      const char *help;
1234    
1235        help =
1236            _(
1237             "ADDUID      add a user ID\r\n"
1238             "ADDPHOTO    add a photo ID\r\n"
1239             "DELUID      delete a user ID\r\n"
1240             "ADDKEY      add a secondary key\r\n"
1241             "DELKEY      delete a secondary key\r\n"
1242             "ADDREVOKER  add a revocation key\r\n"
1243             "EXPIRE      change the expire date\r\n"
1244             "SHOWPREF    list preferences (verbose)\r\n"
1245             /*"SETPREF     update specific algorithm preferences\r\n"*/
1246             "PASSWD      change the passphrase\r\n"
1247             "PRIMARY     flag user ID as primary\r\n"
1248             "TRUST       change the ownertrust\r\n"
1249             "REVUID      revoke a user ID\r\n"
1250             "REVKEY      revoke a secondary key\r\n"
1251             "DISABLE     disable a key\r\n"
1252             "ENABLE      enable a key\r\n"
1253             "SIGN        sign a user-id (exportable)\r\n"
1254             "LSIGN       sign a user-id (non-exportable)\r\n"
1255             "CLEAN       remove unusable signatures from key\r\n"
1256             "MINIMIZE    remove all signatures from key\r\n"
1257             );
1258        msg_box (dlg, help, _("Key Edit Help"), MB_OK);
1259    }
1260    
1261    
1262    static gpgme_subkey_t
1263    get_subkey_bypos (const char *keyid, int idx)
1264    {
1265        gpgme_key_t key;
1266    
1267        if (get_pubkey (keyid, &key))
1268            return NULL;
1269        return get_nth_key (key, idx);
1270    }
1271    
     _snprintf( helptext, sizeof helptext-1,  
         _(/*"FPR            \t\tshow fingerprint\r\n"*/  
          "ADDUID   \t\tadd a user ID\r\n"  
          "ADDPHOTO  \t\tadd a photo ID\r\n"  
          "DELUID    \t\tdelete a user ID\r\n"  
          "ADDKEY    \t\tadd a secondard key\r\n"  
          "DELKEY    \t\tdelete a secondary key\r\n"  
          "ADDREVOKER\t\tadd a revocation key\r\n"  
          /*"DELSIG    \t\tdelete signatures\r\n"*/  
          "EXPIRE    \t\tchange the expire date\r\n"  
          /*"PREF            \t\tlist preferences (expert)\r\n"  
          "SHOWPREF  \t\tlist preferences (verbose)\r\n"  
          "SETPREF   \t\tset preference list\r\n"*/  
          "UPDPREF   \t\tupdated preferences\r\n"  
          "PASSWD    \t\tchange the passphrase\r\n"  
          "PRIMARY   \t\tflag user ID as primary\r\n"  
          "TRUST     \t\tchange the ownertrust\r\n"  
          /*"REVSIG    \t\trevoke signatures\r\n"*/  
          "REVUID    \t\trevoke a user ID\r\n"  
          "REVKEY    \t\trevoke a secondary key\r\n"  
          "DISABLE   \t\tdisable a key\r\n"  
          "ENABLE    \t\tenable a key\r\n"  
          /*"SHOWPHOTO \t\tshow photo ID\r\n"*/) );  
     msg_box( dlg, helptext, _("Key Edit Help"), MB_OK );  
 } /* do_show_help */  
1272    
1273    
1274  static int  static int
1275  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)
1276  {  {
1277      gpgme_error_t err;      gpgme_error_t err;
1278      GpgKeyEdit *ke;      gpgme_subkey_t subk;
1279      int j, id;      GpgKeyEdit ke;
1280        int pos, id;
1281        const char *warn;
1282      char tmp[64];      char tmp[64];
1283    
1284      if (!k->key_pair)      if (!k->key_pair)
1285          return FALSE; /* XXX: shall we allow to modify non-secret keys?? */          return FALSE;
1286    
1287      if( listview_count_items( lv, 0 ) == 1 ) {      if (listview_count_items (lv, 0) == 1) {
1288          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);
1289          return FALSE;          return FALSE;
1290      }      }
1291      if( (j = listview_get_curr_pos( lv )) == -1 ) {      pos = listview_get_curr_pos (lv);
1292          msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );      if (pos == -1) {
1293            msg_box (dlg, _("Please select a key."), _("Key Edit"), MB_ERR);
1294          return FALSE;          return FALSE;
1295      }      }
1296      if( j == 0 ) {      if (pos == 0) {
1297          msg_box( dlg, _("Primary subkey can not be deleted!"), _("Key Edit"), MB_ERR );          msg_box (dlg, _("Primary key can not be deleted!"), _("Key Edit"), MB_ERR);
1298          return FALSE;          return FALSE;
1299      }      }
1300        
1301      listview_get_item_text( lv, j, 0, tmp, sizeof tmp -1 );      listview_get_item_text (lv, pos, 0, tmp, DIM (tmp) -1);
1302      id = log_box( _("Key Edit"), MB_YESNO|MB_ICONWARNING,      subk = get_subkey_bypos (k->keyid, pos);
1303                      _("\"Subkey %s.\"\n\n"      /* Issue different warning for the different key capabilities. */
1304                        "Anything encrypted to the selected subkey will no longer\n"      if (subk->can_encrypt)
1305                        "be able to be decrypted.\n\n"          warn = _("Anything encrypted to the selected subkey cannot be\n"
1306                        "Do you really want to delete this subkey?"), tmp );                   "decrypted any longer.");
1307      if( id == IDNO )      else if (subk->can_sign || subk->can_certify)
1308            warn = _("Anything signed by the selected subkey cannot be\n"
1309                     "verified any longer.");
1310        else
1311            warn = ""; /* just get rid of the warning. */
1312    
1313        id = log_box (_("Key Edit"), MB_YESNO|MB_ICONWARNING,
1314                      _("\"Subkey %s.\"\n\n%s\n\n"
1315                        "Do you really want to delete this subkey?"),
1316                      tmp, warn);
1317        if (id == IDNO)
1318          return FALSE;          return FALSE;
1319    
1320      ke = new GpgKeyEdit (k->keyid);      ke.setKeyID (k->keyid);
1321      if (!ke)      err = ke.delKey (pos);
         BUG (NULL);  
     err = ke->delKey (j);  
1322      if (err)      if (err)
1323          msg_box (dlg, gpgme_strerror (err), _("Delete Subkey"), MB_ERR);          msg_box (dlg, gpgme_strerror (err), _("Delete Subkey"), MB_ERR);
1324      else {      else {
1325          listview_del_item (lv, j);          listview_del_item (lv, pos);
1326          k->update = 1;          k->update = 1;
1327          status_box (dlg, _("Subkey successfully deleted."), _("GnuPG status"));          status_box (dlg, _("Subkey successfully deleted."), _("GnuPG status"));
1328      }      }
     delete ke;  
1329      return err? FALSE : TRUE;      return err? FALSE : TRUE;
1330  } /* do_editkey_delkey */  }
1331    
1332    
1333  /* Set the expiration date for the selected key in list view @lv.  /* Set the expiration date for the selected key in list view @lv.
# Line 1238  static int Line 1336  static int
1336  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)
1337  {  {
1338      gpgme_error_t err;      gpgme_error_t err;
1339      GpgKeyEdit *ke;      GpgKeyEdit ke;
1340      date_s udd = {0};      date_s udd = {0};
1341      char buf[256], * pass = NULL;      char buf[256], * pass = NULL;
1342      int j, cancel = 0;      time_t exp;
1343        int pos, cancel = 0;
1344    
1345      if (!k->key_pair) {      if (!k->key_pair) {
1346          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);
1347          return FALSE;          return FALSE;
1348      }      }
1349      if ((j = listview_get_curr_pos (lv)) == -1) {      pos = listview_get_curr_pos (lv);
1350          msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );      if (pos == -1) {
1351            msg_box (dlg, _("Please select a key."), _("Key Edit"), MB_ERR);
1352          return FALSE;          return FALSE;
1353      }      }
1354    
1355      /* If a key already expired, it is possible the user wants to      /* If a key already expired, it is possible the user wants to
1356         set a new expiration date.. */           set a new expiration date.. */
1357      listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, sizeof buf -1);      listview_get_item_text (lv, pos, SUBK_COL_STATUS, buf, DIM (buf)-1);
1358      if (!strcmp (buf, _("Expired"))) {      if (!strcmp (buf, _("Expired"))) {
1359          cancel = msg_box (dlg, _("Key already expired.\n\n"          cancel = msg_box (dlg, _("Key already expired.\n\n"
1360                            "Do you want to change the expiration date?"),                            "Do you want to change the expiration date?"),
# Line 1264  do_editkey_expire (winpt_key_t k, HWND d Line 1364  do_editkey_expire (winpt_key_t k, HWND d
1364          cancel = 0;          cancel = 0;
1365      }      }
1366    
1367      memset (&udd, 0, sizeof udd);      memset (&udd, 0, sizeof (udd));
1368      udd.text = _("Key Expiration Date");      udd.text = _("Key Expiration Date");
1369      dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_DATE, dlg,          dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_DATE, dlg,    
1370                        date_dlg_proc, (LPARAM)&udd,                        date_dlg_proc, (LPARAM)&udd,
# Line 1272  do_editkey_expire (winpt_key_t k, HWND d Line 1372  do_editkey_expire (winpt_key_t k, HWND d
1372      if (udd.cancel == 1)      if (udd.cancel == 1)
1373          return FALSE;          return FALSE;
1374      if (!keygen_check_date (&udd.st)) {      if (!keygen_check_date (&udd.st)) {
1375          msg_box (dlg, _("The date you have chosen lies in the past."),          msg_box (dlg, _("The date you have chosen has already passed."),
1376                   _("Key Edit"), MB_ERR);                   _("Key Edit"), MB_ERR);
1377          return FALSE;          return FALSE;
1378      }      }
1379      if( k->is_protected ) {      if (k->is_protected) {
1380          pass = request_passphrase (_("Key Edit"), 1, &cancel);          pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
1381          if (cancel)          if (cancel)
1382              return FALSE;              return FALSE;
1383      }      }
1384        exp = w32_mktime (&udd.st);
1385    
1386      ke = new GpgKeyEdit (k->keyid);      ke.setKeyID (k->keyid);
     if (!ke)  
         BUG (NULL);  
1387      if (k->is_protected)      if (k->is_protected)
1388          ke->setPassphrase (pass);          ke.setPassphrase (pass);
1389      err = ke->setKeyExpireDate (j, diff_time (NULL, &udd.st), true);      else
1390            ke.setNoPassphrase (true);
1391        err = ke.setKeyExpireDate (pos, exp, false);
1392      if (err)      if (err)
1393          msg_box (dlg, gpgme_strerror (err), _("Expire Subkey"), MB_ERR);          msg_box (dlg, gpgme_strerror (err), _("Expire Subkey"), MB_ERR);
1394      else {      else {
1395          _snprintf (buf, sizeof buf - 1, "%04d-%02d-%02d",                _snprintf (buf, DIM (buf)-1, "%s", get_key_created (exp));
1396                     udd.st.wYear, udd.st.wMonth, udd.st.wDay);          listview_add_sub_item (lv, pos, SUBK_COL_EXPIRES, buf);
         listview_add_sub_item (lv, j, SUBK_COL_EXPIRES, buf);  
1397          k->update = 1;          k->update = 1;
1398          msg_box (dlg, _("Subkey expire date successfully set."),          msg_box (dlg, _("Subkey expire date successfully set."),
1399                   _("GnuPG status"), MB_OK);                   _("GnuPG status"), MB_OK);
1400      }      }
1401      sfree_if_alloc (pass);      sfree_if_alloc (pass);
     delete ke;  
1402      return TRUE;      return TRUE;
1403  }  }
1404    
# Line 1311  static int Line 1410  static int
1410  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)
1411  {  {
1412      gpgme_error_t err;      gpgme_error_t err;
1413      GpgKeyEdit *ke;      GpgKeyEdit ke;
1414      char buf[256];      char buf[256];
1415      char *pass = NULL;      char *pass = NULL;
1416      int j, cancel = 0;      int j, cancel = 0;
# Line 1333  do_editkey_revoke (winpt_key_t k, HWND d Line 1432  do_editkey_revoke (winpt_key_t k, HWND d
1432          return FALSE;          return FALSE;
1433      }      }
1434                            
1435      listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, sizeof (buf)-1);      listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, DIM (buf)-1);
1436      if (!strcmp (buf, _("Revoked"))) {      if (!strcmp (buf, _("Revoked"))) {
1437          msg_box (dlg, _("Key already revoked."), _("Key Edit"), MB_ERR);          msg_box (dlg, _("Key already revoked."), _("Key Edit"), MB_ERR);
1438          return FALSE;          return FALSE;
1439      }      }
1440            
1441      if (k->is_protected) {      if (k->is_protected) {
1442          pass = request_passphrase (_("Key Edit"), 1, &cancel);          pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
1443          if (cancel)          if (cancel)
1444              return FALSE;                        return FALSE;          
1445      }      }
1446    
1447      ke = new GpgKeyEdit (k->keyid);      ke.setKeyID (k->keyid);
     if (!ke)  
         BUG (NULL);  
1448      if (k->is_protected)      if (k->is_protected)
1449          ke->setPassphrase (pass);          ke.setPassphrase (pass);
1450      err = ke->revokeSubkey (j, 0, NULL);      else
1451            ke.setNoPassphrase (true);
1452        err = ke.revokeSubkey (j, 0, NULL);
1453      if (err)      if (err)
1454          msg_box( dlg, gpgme_strerror (err), _("Revoke Subkey"), MB_ERR);          msg_box( dlg, gpgme_strerror (err), _("Revoke Subkey"), MB_ERR);
1455      else {      else {
# Line 1359  do_editkey_revoke (winpt_key_t k, HWND d Line 1458  do_editkey_revoke (winpt_key_t k, HWND d
1458          msg_box( dlg, _("Subkey successfully revoked."), _("GnuPG Status"), MB_OK );          msg_box( dlg, _("Subkey successfully revoked."), _("GnuPG Status"), MB_OK );
1459      }      }
1460      sfree_if_alloc (pass);      sfree_if_alloc (pass);
     delete ke;  
1461      return TRUE;      return TRUE;
1462  }  }
1463    
# Line 1370  int Line 1468  int
1468  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)
1469  {  {
1470      gpgme_error_t err;      gpgme_error_t err;
1471      GpgKeyEdit *ke;      GpgKeyEdit ke;
1472      char buf[256], t[512];      char buf[128], email[128];
1473      char *pass=NULL;      char inf[512];
1474        char *pass = NULL;
1475      int cancel = 0, id = 0, j;      int cancel = 0, id = 0, j;
1476    
1477      if (!k->key_pair) {      if (!k->key_pair) {
1478          msg_box( dlg, _("There is no secret key available!"), _("Revoke user ID"), MB_ERR );          msg_box (dlg, _("There is no secret key available!"),
1479                     _("Revoke user ID"), MB_ERR);
1480          return FALSE;          return FALSE;
1481      }      }
1482    
1483      if( listview_count_items( lv, 0 ) == 1 ) {      if (listview_count_items (lv, 0) == 1) {
1484          msg_box( dlg, _("Key has only one user ID."), _("Key Edit"), MB_ERR );            msg_box (dlg, _("Key has only one user ID."), _("Key Edit"), MB_ERR);  
1485          return FALSE;          return FALSE;
1486      }      }
1487    
1488      if( (j = listview_get_curr_pos( lv )) == -1 ) {      if( (j = listview_get_curr_pos( lv )) == -1 ) {
1489          msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );            msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1490          return FALSE;            return FALSE;  
1491      }      }
1492                            
1493      listview_get_item_text( lv, j, 0, buf, sizeof buf - 1 );      listview_get_item_text( lv, j, UID_COL_VALID, buf, DIM (buf) - 1);
1494      if( strstr( buf, _("Revoked") ) ) {      if (strstr (buf, _("Revoked"))) {
1495          msg_box( dlg, _("This user ID has been already revoked."), _("Key Edit"), MB_INFO );          msg_box (dlg, _("This user ID has been already revoked."),
1496                     _("Key Edit"), MB_INFO);
1497          return FALSE;          return FALSE;
1498      }      }
1499                            
1500      listview_get_item_text (lv, j, 1, buf, sizeof buf -1);      listview_get_item_text (lv, j, UID_COL_NAME, buf, sizeof buf -1);
1501      _snprintf( t, sizeof t -1, _("user ID \"%s\".\n\n"      _snprintf (inf, DIM (inf) -1, _("user ID \"%s\".\n\n"
1502                  "Do you really want to revoke this user ID?"), buf );                 "Do you really want to revoke this user ID?"), buf);
1503      if( msg_box( dlg, t, _("Key Edit"), MB_WARN_ASK) == IDNO )      if (msg_box (dlg, inf, _("Key Edit"), MB_WARN_ASK) == IDNO)
1504          return FALSE;          return FALSE;
1505      if( k->is_protected ) {      if (k->is_protected) {
1506          pass = request_passphrase (_("Key Edit"), 1, &cancel);          pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
1507          if (cancel)          if (cancel)
1508              return FALSE;                        return FALSE;          
1509      }      }
1510      listview_get_item_text (lv, j, 2, buf, sizeof (buf)-1);      listview_get_item_text (lv, j, UID_COL_EMAIL, email, DIM (email)-1);
1511      id = do_find_userid (k->keyid, buf, NULL);      listview_get_item_text (lv, j, UID_COL_NAME, buf, DIM (buf)-1);
1512        id = do_find_userid (k->keyid, email, buf, NULL);
1513      if (id == -1)      if (id == -1)
1514          BUG (NULL);          BUG (NULL);
1515    
1516      ke = new GpgKeyEdit (k->keyid);      ke.setKeyID (k->keyid);
     if (!ke)  
         BUG (NULL);  
1517      if (k->is_protected)      if (k->is_protected)
1518          ke->setPassphrase (pass);          ke.setPassphrase (pass);
1519      err = ke->revokeUserid (id);      else
1520            ke.setNoPassphrase (true);
1521        err = ke.revokeUserid (id);
1522      if (err)      if (err)
1523          msg_box (dlg, gpgme_strerror (err), _("Revoke Signature"), MB_ERR);          msg_box (dlg, gpgme_strerror (err), _("Revoke User ID"), MB_ERR);
1524      else {      else {
1525          listview_add_sub_item (lv, j, 0, _("Revoked"));          listview_add_sub_item (lv, j, 0, _("Revoked"));
1526          k->update = 1;          k->update = 1;
1527          status_box (dlg, _("User ID successfully revoked"), _("GnuPG Status"));          status_box (dlg, _("User ID successfully revoked"), _("GnuPG Status"));
1528      }      }
1529      sfree_if_alloc (pass);      sfree_if_alloc (pass);
     delete ke;  
1530      return err? FALSE : TRUE;      return err? FALSE : TRUE;
1531  }  }
1532    
# Line 1433  do_editkey_revuid (winpt_key_t k, HWND d Line 1534  do_editkey_revuid (winpt_key_t k, HWND d
1534  static int  static int
1535  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)
1536  {  {
1537      gpgme_error_t rc;      gpgme_error_t err;
1538      GpgKeyEdit *ke;      GpgKeyEdit ke;
1539      char buf[256], * pass = NULL, * prefs;      gpg_uid_info_t uidinf = NULL;
1540      int j, id, cancel=0, flags=0;      char buf[256], *pass = NULL, *prefs = NULL;
1541        int pos, id, cancel=0, flags=0;
1542    
1543      if ((j = listview_get_curr_pos (lv)) == -1) {      pos = listview_get_curr_pos (lv);
1544        if (pos == -1) {
1545          msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);          msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1546          return FALSE;          return FALSE;
1547      }      }
1548      listview_get_item_text (lv, j, 2, buf, sizeof buf-1);      listview_get_item_text (lv, pos, 2, buf, DIM (buf)-1);
1549      id = do_find_userid (k->keyid, buf, NULL);      id = do_find_userid (k->keyid, buf, NULL, &uidinf);
1550      if (id == -1)      if (id == -1)
1551          BUG (dlg);          BUG (NULL);
1552      if (k->is_protected) {      if (k->is_protected) {
1553          pass = request_passphrase (_("Key Edit"), 1, &cancel);          pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
1554            gpg_uid_info_release (uidinf);
1555          if (cancel)          if (cancel)
1556              return FALSE;              return FALSE;
1557      }      }
1558    
1559      ke = new GpgKeyEdit (k->keyid);      get_userid_preflist (uidinf->prefs, &prefs, &flags);
1560      if (!ke)      gpg_uid_info_release (uidinf);
1561          BUG (NULL);      if (!prefs) {
1562      if (k->is_protected)          sfree_if_alloc (pass);
1563          ke->setPassphrase (pass);          return FALSE;
1564        }
     get_userid_preflist (&prefs, &flags);  
1565    
1566      rc = ke->setUseridPreferences (id, prefs);      ke.setKeyID (k->keyid);
1567      /* XXX */      if (k->is_protected)
1568            ke.setPassphrase (pass);
1569        else
1570            ke.setNoPassphrase (true);    
1571        err = ke.setUseridPreferences (id, prefs);
1572        if (err)
1573            msg_box (dlg, gpgme_strerror (err), _("Set user ID preferences"), MB_ERR);
1574        else {
1575            k->update = 1;
1576            status_box (dlg, _("User ID preferences successfully updated"), _("GnuPG Status"));
1577        }
1578    
1579      sfree_if_alloc (pass);      sfree_if_alloc (pass);
1580      free_if_alloc (prefs);      free_if_alloc (prefs);
1581      delete ke;      return err? FALSE: TRUE;
     return 0;  
1582  }  }
1583    
1584    
# Line 1474  static int Line 1586  static int
1586  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)
1587  {  {
1588      gpgme_error_t err;      gpgme_error_t err;
1589      GpgKeyEdit *ke;      GpgKeyEdit ke;
1590      int j, id, cancel=0;      int j, id, cancel=0;
1591      char buf[256], * pass = NULL;      char valid[32];
1592        char buf[256], *pass = NULL;
1593    
1594      if (listview_count_items (lv, 0) == 1)      if (listview_count_items (lv, 0) == 1)
1595          return TRUE;          return TRUE;
1596      if ((j = listview_get_curr_pos (lv)) == -1) {      if ((j = listview_get_curr_pos (lv)) == -1) {
1597          msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );          msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1598          return FALSE;          return FALSE;
1599      }      }
1600      listview_get_item_text (lv, j, 2, buf, sizeof buf-1);      listview_get_item_text (lv, j, UID_COL_VALID, valid, DIM (valid)-1);
1601      id = do_find_userid (k->keyid, buf, NULL);      if (!strcmp (valid, _("Revoked")))
1602            return FALSE;
1603        listview_get_item_text (lv, j, UID_COL_EMAIL, buf, DIM (buf)-1);
1604        id = do_find_userid (k->keyid, buf, NULL, NULL);
1605      if (id == -1)      if (id == -1)
1606          BUG (dlg);          BUG (NULL);
1607      if (k->is_protected) {      if (k->is_protected) {
1608          pass = request_passphrase (_("Key Edit"), 1, &cancel);          pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
1609          if( cancel )          if (cancel)
1610              return FALSE;              return FALSE;
1611      }      }
1612    
1613      ke = new GpgKeyEdit (k->keyid);      ke.setKeyID (k->keyid);
1614      if (k->is_protected)      if (k->is_protected)
1615          ke->setPassphrase (pass);          ke.setPassphrase (pass);
1616      err = ke->setPrimaryUserid (id);      else
1617            ke.setNoPassphrase (true);
1618        err = ke.setPrimaryUserid (id);
1619      if (err)      if (err)
1620          msg_box (dlg, gpgme_strerror (err), _("Primary"), MB_ERR);          msg_box (dlg, gpgme_strerror (err), _("Primary"), MB_ERR);
1621      else {      else {
# Line 1506  do_editkey_primary (winpt_key_t k, HWND Line 1624  do_editkey_primary (winpt_key_t k, HWND
1624      }      }
1625    
1626      sfree_if_alloc (pass);      sfree_if_alloc (pass);
     delete ke;  
1627      return err? FALSE : TRUE;      return err? FALSE : TRUE;
1628  }  }
1629    
1630    
1631    
1632    #define CIPHER  11
1633    #define HASH    11
1634    #define COMPR    4
1635    
1636  static int  static int
1637  parse_preflist (HWND dlg, const char *list)  parse_preflist (HWND dlg, const char *list)
1638  {  {
1639      char *p, buf[128] = {0}, *pbuf = buf;      char buf[128] = {0};
1640      const char *ciphers[11] = {0, "IDEA", "3DES", "CAST5", "BLOWFISH", 0, 0, "AES", "AES192", "AES256", "TWOFISH"};      char *p, *pbuf = buf;
1641      const char *hash[11] = {0, "MD5", "SHA1", "RMD160", 0, 0, 0, 0, "SHA256", "SHA384", "SHA512"};      const char *ciphers[CIPHER] = {"", "IDEA", "3DES",
1642      const char *compress[4] = {0, "ZIP", "ZLIB", "BZIP2"};                                     "CAST5", "BLOWFISH", "", "",
1643                                       "AES", "AES192", "AES256", "TWOFISH"};
1644        const char *hash[HASH] = {"", "MD5", "SHA1", "RMD160", "",
1645                                  "", "", "", "SHA256", "SHA384", "SHA512"};
1646        const char *compress[COMPR] = {"", "ZIP", "ZLIB", "BZIP2"};
1647      int n=0;      int n=0;
1648    
1649      strncpy (buf, list, 127);      strncpy (buf, list, 127);
# Line 1527  parse_preflist (HWND dlg, const char *li Line 1653  parse_preflist (HWND dlg, const char *li
1653          n++;          n++;
1654          switch (*p) {          switch (*p) {
1655          case 'S':          case 'S':
1656              SendDlgItemMessage (dlg, IDC_SHOWPREF_CIPHERS, LB_ADDSTRING, 0, (LPARAM)(const char*)ciphers[algid % 11]);              SendDlgItemMessage (dlg, IDC_SHOWPREF_CIPHERS, LB_ADDSTRING, 0,
1657                                    (LPARAM)(const char*)ciphers[algid % CIPHER]);
1658              break;              break;
1659    
1660          case 'H':          case 'H':
1661              SendDlgItemMessage (dlg, IDC_SHOWPREF_HASH, LB_ADDSTRING, 0, (LPARAM)(const char*)hash[algid % 10]);              SendDlgItemMessage (dlg, IDC_SHOWPREF_HASH, LB_ADDSTRING, 0,
1662                                    (LPARAM)(const char*)hash[algid % HASH]);
1663              break;              break;
1664    
1665          case 'Z':          case 'Z':
1666              SendDlgItemMessage (dlg, IDC_SHOWPREF_ZIP, LB_ADDSTRING, 0, (LPARAM)(const char*)compress[algid % 4]);              SendDlgItemMessage (dlg, IDC_SHOWPREF_ZIP, LB_ADDSTRING, 0,
1667                                    (LPARAM)(const char*)compress[algid % COMPR]);
1668              break;              break;
1669    
1670          default:          default:
# Line 1551  parse_preflist (HWND dlg, const char *li Line 1680  parse_preflist (HWND dlg, const char *li
1680  BOOL CALLBACK  BOOL CALLBACK
1681  showpref_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  showpref_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1682  {  {
1683      static keyedit_callback_s *cb = NULL;      static keyedit_cb_t cb = NULL;
1684      gpg_uid_info_t inf=NULL;      gpg_uid_info_t inf=NULL, u;
1685        gpgme_key_t key;
1686      char buf[128];      char buf[128];
1687      int pos;      int pos;
1688    
1689      switch (msg) {      switch (msg) {
1690      case WM_INITDIALOG:      case WM_INITDIALOG:
1691          cb = (keyedit_callback_s *)lparam;          cb = (keyedit_cb_t)lparam;
1692          if (cb == NULL)          if (!cb)
1693              BUG (dlg);              BUG (NULL);
1694          listview_get_item_text (cb->lv, listview_get_curr_pos (cb->lv), 2, buf, DIM (buf)-1);          key = (gpgme_key_t)cb->opaque;
1695          SetDlgItemText (dlg, IDC_SHOWPREF_INFO, buf);          listview_get_item_text (cb->lv, cb->lv_pos,
1696          pos = do_find_userid (((winpt_key_t)cb->opaque)->keyid, buf, &inf);                                  UID_COL_EMAIL, buf, DIM (buf)-1);
1697          if (inf) {          pos = do_find_userid (cb->keyid, buf, NULL, &inf);
1698              const char *prefs = inf->prefs;          if (pos < 0 || !inf) {
             if (prefs && *prefs) {  
                 if (parse_preflist (dlg, prefs) <= 0)  
                     pos = -1;  
             }  
             else  
                 pos = -1;  
1699              gpg_uid_info_release (inf);              gpg_uid_info_release (inf);
1700              if (pos == -1) {              EndDialog (dlg, FALSE);
1701                  msg_box (dlg, _("No preferences available."), _("Key Edit"), MB_ERR);              break;
1702                  EndDialog (dlg, TRUE);          }
1703            for (u=inf; u; u = u->next) {
1704                if (u->index == pos && u->prefs && *u->prefs) {
1705                    _snprintf (buf, DIM (buf)-1, "%s", u->name);
1706                    SetDlgItemText (dlg, IDC_SHOWPREF_INFO, buf);
1707                    if (parse_preflist (dlg, u->prefs) <= 0)
1708                        pos = -1;
1709                    if (u->flags.mdc)
1710                        CheckDlgButton (dlg, IDC_SHOWPREF_MDC, BST_CHECKED);
1711                    break;
1712              }              }
             if (inf->flags.mdc)  
                 CheckDlgButton (dlg, IDC_SHOWPREF_MDC, BST_CHECKED);  
1713          }          }
1714            gpg_uid_info_release (inf);
1715            if (pos == -1) {        
1716                msg_box (dlg, _("No preferences available."), _("Key Edit"), MB_ERR);
1717                EndDialog (dlg, FALSE);
1718                break;
1719            }
1720            SetDlgItemText (dlg, IDC_SHOWPREF_MDC, _("MDC feature"));
1721            SetDlgItemText (dlg, IDC_SHOWPREF_PREFINF, _("Preferences"));
1722            SetDlgItemText (dlg, IDC_SHOWPREF_UIDHINT, _("user ID:"));
1723          SetWindowText (dlg, _("Key Preferences"));          SetWindowText (dlg, _("Key Preferences"));
1724          SetForegroundWindow (dlg);          SetForegroundWindow (dlg);
1725            center_window (dlg, cb->parent);
1726          break;          break;
1727    
1728      case WM_COMMAND:      case WM_COMMAND:
# Line 1589  showpref_dlg_proc (HWND dlg, UINT msg, W Line 1730  showpref_dlg_proc (HWND dlg, UINT msg, W
1730          case IDOK:          case IDOK:
1731              EndDialog (dlg, TRUE);              EndDialog (dlg, TRUE);
1732              break;              break;
1733    
1734            case IDCANCEL:
1735                EndDialog (dlg, FALSE);
1736                break;
1737          }          }
1738          break;          break;
1739      }      }
# Line 1599  showpref_dlg_proc (HWND dlg, UINT msg, W Line 1744  showpref_dlg_proc (HWND dlg, UINT msg, W
1744  static int  static int
1745  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)
1746  {  {
1747      struct keyedit_callback_s cb;      struct keyedit_cb_s cb;
1748        char status[32];
1749    
1750      if (k->is_v3)      if (k->is_v3)
1751          return TRUE;          return TRUE;
# Line 1608  do_editkey_showpref (winpt_key_t k, HWND Line 1754  do_editkey_showpref (winpt_key_t k, HWND
1754          msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);          msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1755          return FALSE;          return FALSE;
1756      }      }
   
1757      memset (&cb, 0, sizeof (cb));      memset (&cb, 0, sizeof (cb));
1758        cb.parent = dlg;
1759        cb.opaque = k->ctx;
1760        cb.keyid = k->keyid;
1761      cb.lv = lv;      cb.lv = lv;
1762      cb.opaque = k;      cb.lv_pos = listview_get_curr_pos (lv);
1763    
1764        listview_get_item_text (lv, cb.lv_pos, UID_COL_VALID,
1765                                status, DIM (status)-1);
1766        if (!strcmp (status, _("Revoked")))
1767            return TRUE;
1768        
1769      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_SHOWPREF, dlg,      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_SHOWPREF, dlg,
1770                      showpref_dlg_proc, (LPARAM)&cb);                      showpref_dlg_proc, (LPARAM)&cb);
1771      return TRUE;      return TRUE;
# Line 1622  static int Line 1776  static int
1776  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)
1777  {  {
1778      gpgme_error_t err;      gpgme_error_t err;
1779      GpgKeyEdit *ke;      GpgKeyEdit ke;
1780      char buf[256], t[512];      char email[128], name[128];
1781      int j, id = 0;      char inf[384];
1782        int pos, id = 0;
1783    
1784      if (!k->key_pair)      if (!k->key_pair)
1785          return FALSE; /* XXX: see do_editkey_delsubkey */          return FALSE;
1786    
1787      if( listview_count_items( lv, 0 ) == 1 ) {      if (listview_count_items (lv, 0) == 1) {
1788          msg_box( dlg, _("Primary user ID can not be deleted!"), _("Key Edit"), MB_ERR );          msg_box (dlg, _("Primary user ID can not be deleted!"),
1789                     _("Key Edit"), MB_ERR);
1790          return FALSE;          return FALSE;
1791      }      }
1792      if( (j = listview_get_curr_pos( lv )) == -1 ) {      pos = listview_get_curr_pos (lv);
1793          msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );      if (pos == -1) {
1794            msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1795          return FALSE;          return FALSE;
1796      }      }
1797            
1798      /* XXX: add a hint that also all signatures will be deleted? */      listview_get_item_text (lv, pos, UID_COL_NAME, name, DIM(name) -1);
1799      listview_get_item_text( lv, j, 1, buf, DIM(buf) -1 );      _snprintf (inf, DIM (inf)-1, _("user ID \"%s\".\n\n"
1800      _snprintf( t, DIM (t)-1, _("user ID \"%s\".\n\n"                                     "All signatures on this user ID will be also deleted."
1801                                 "Do you really want to delete this user ID?"),                                     "\n\n"
1802                                 buf);                                     "Do you really want to delete this user ID?"),
1803      if( msg_box( dlg, t, _("Key Edit"), MB_YESNO|MB_ICONWARNING ) == IDNO )                                 name);
1804        if (msg_box (dlg, inf, _("Key Edit"), MB_YESNO|MB_ICONWARNING) == IDNO)
1805          return FALSE;          return FALSE;
1806            
1807      listview_get_item_text (lv, j, 2, buf, DIM (buf)-1);      listview_get_item_text (lv, pos, UID_COL_EMAIL, email, DIM (email)-1);
1808      id = do_find_userid (k->keyid, buf, NULL);      listview_get_item_text (lv, pos, UID_COL_NAME, name, DIM (name)-1);
1809        id = do_find_userid (k->keyid, email, name, NULL);
1810      if (id == -1)      if (id == -1)
         BUG (dlg);  
   
     ke = new GpgKeyEdit (k->keyid);  
     if (!ke)  
1811          BUG (NULL);          BUG (NULL);
1812    
1813      err = ke->delUserid (id);      ke.setKeyID (k->keyid);
1814      if( err )      err = ke.delUserid (id);
1815          msg_box( dlg, gpgme_strerror (err), _("Delete user ID"), MB_ERR );      if (err)
1816            msg_box (dlg, gpgme_strerror (err), _("Delete User ID"), MB_ERR);
1817      else {      else {
1818          listview_del_item( lv, j );          listview_del_item (lv, pos);
1819          k->update = 1;          k->update = 1;
1820          status_box( dlg, _("User ID successfully deleted"), _("GnuPG Status") );          status_box (dlg, _("User ID successfully deleted"), _("GnuPG Status"));
1821      }      }
     delete ke;  
1822      return err? FALSE : TRUE;      return err? FALSE : TRUE;
1823  } /* do_editkey_deluid */  }
   
1824    
1825    
1826    /* Subclass routine for the subkey listview control to allow shortcuts. */
1827  static BOOL CALLBACK  static BOOL CALLBACK
1828  subkey_subclass_proc( HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam )  subkey_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1829  {  {
1830      switch( msg ) {      int virt_key = 0;
1831        winpt_key_t key;
1832    
1833        switch (msg) {
1834      case WM_KEYUP:      case WM_KEYUP:
1835          int virt_key = (int)wparam;          virt_key = (int)wparam;
1836          switch( virt_key ) {                  key = (winpt_key_t)keyedit_subkey_proc.opaque;
1837            if (!key || !key->key_pair)
1838                break;
1839    
1840            switch (virt_key) {
1841          case VK_DELETE:          case VK_DELETE:
1842              SendDlgItemMessage( keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,              SendDlgItemMessage (keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
1843                                  CB_SETCURSEL, CMD_DELKEY, 0 );                                  CB_SETCURSEL, CMD_DELKEY, 0);
1844              send_cmd_id( keyedit_subkey_proc.dlg, IDOK );              send_cmd_id (keyedit_subkey_proc.dlg, IDOK);
1845              break;              break;
1846    
1847          case VK_INSERT:          case VK_INSERT:
1848              SendDlgItemMessage( keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,              SendDlgItemMessage (keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
1849                                  CB_SETCURSEL, CMD_ADDKEY, 0 );                                  CB_SETCURSEL, CMD_ADDKEY, 0);
1850              send_cmd_id( keyedit_subkey_proc.dlg, IDOK );              send_cmd_id (keyedit_subkey_proc.dlg, IDOK);
1851              break;              break;
1852          }          }
1853      }      }
1854      return CallWindowProc( keyedit_subkey_proc.old, dlg, msg, wparam, lparam );      return CallWindowProc (keyedit_subkey_proc.old, dlg, msg, wparam, lparam);
1855  } /* subkey_subclass_proc */  }
1856    
1857    
1858  static BOOL CALLBACK  static BOOL CALLBACK
1859  uid_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  uid_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1860  {  {
1861      switch( msg ) {      int virt_key = 0;
1862        winpt_key_t key;
1863    
1864        switch (msg) {
1865      case WM_KEYUP:      case WM_KEYUP:
1866          int virt_key = (int)wparam;          virt_key = (int)wparam;
1867            key = (winpt_key_t)keyedit_uid_proc.opaque;
1868            if (!key || !key->key_pair)
1869                break;
1870    
1871          switch (virt_key) {          switch (virt_key) {
1872          case VK_DELETE:          case VK_DELETE:
1873              SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,              SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
# Line 1713  uid_subclass_proc (HWND dlg, UINT msg, W Line 1882  uid_subclass_proc (HWND dlg, UINT msg, W
1882              break;              break;
1883          }          }
1884      }      }
1885      return CallWindowProc( keyedit_uid_proc.old, dlg, msg, wparam, lparam );      return CallWindowProc (keyedit_uid_proc.old, dlg, msg, wparam, lparam);
1886  } /* uid_subclass_proc */  }
1887    
1888    
1889    /* Enable the key @k when @enable is 1, disable it otherwise. */
1890    static void
1891    do_editkey_enable_disable (winpt_key_t k, HWND dlg,
1892                               listview_ctrl_t lv, int enable)
1893    {
1894        km_enable_disable_key (lv, dlg, 0, enable);
1895        k->update = 1;
1896    }
1897    
1898    
1899    static void
1900    do_editkey_minimize (winpt_key_t k, HWND dlg)
1901    {
1902        gpgme_error_t err;
1903        GpgKeyEdit ke;
1904    
1905        ke.setKeyID (k->keyid);
1906        err = ke.minimizeKey ();
1907        if (err)
1908            msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
1909        else {
1910            msg_box (dlg, _("Finished to compact key."), _("Key Edit"), MB_OK);
1911            k->update = 1;
1912        }
1913    }
1914    
1915    
1916    static void
1917    do_editkey_clean (winpt_key_t k, HWND dlg)
1918    {
1919        gpgme_error_t err;
1920        GpgKeyEdit ke;
1921        
1922        ke.setKeyID (k->keyid);
1923        err = ke.cleanKey ();
1924        if (err)
1925            msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);  
1926        else {
1927            msg_box (dlg, _("Finished to compact key."), _("Key Edit"), MB_OK);
1928            k->update = 1;
1929        }
1930    }
1931    
1932    
1933    /* Start the dialog to list and display the status of all
1934       signatures for this key. */
1935    static void
1936    do_editkey_check (winpt_key_t k, HWND dlg)
1937    {
1938        if (!k->ctx)
1939            get_pubkey (k->keyid, &k->ctx);
1940        if (!k->uid && k->ctx)
1941            k->uid = k->ctx->uids->uid;
1942        DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYSIG_TREE, dlg,
1943                        sigtree_dlg_proc, (LPARAM)k);
1944    }
1945    
1946    
1947    static int
1948    do_editkey_sign_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv, int mode)
1949    {
1950        gpgme_error_t err;
1951        winpt_key_s signer;
1952        GpgKeyEdit ke;
1953        char *pass = NULL;
1954        char *defkey;
1955        char email[64], name[128], valid[32];
1956        int uid_index;
1957        int cancel = 0;
1958    
1959        uid_index = listview_get_curr_pos (lv);
1960        if (uid_index == -1) {
1961            msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1962            return FALSE;
1963        }
1964        listview_get_item_text (lv, uid_index, UID_COL_VALID, valid, DIM (valid)-1);
1965        if (!strcmp (valid, _("Revoked")))
1966            return TRUE;
1967        if (mode == CMD_SIGN) {
1968            cancel = msg_box (dlg, _("Do you really want to make this sig exportable?"),
1969                              _("Key Edit"), MB_QUEST_ASK);
1970            if (cancel == IDNO)
1971                return FALSE;
1972        }
1973        listview_get_item_text (lv, uid_index, UID_COL_EMAIL, email, DIM (email)-1);
1974        listview_get_item_text (lv, uid_index, UID_COL_NAME, name, DIM (name)-1);
1975        uid_index = do_find_userid (k->keyid, email, name, NULL);
1976    
1977        defkey = get_gnupg_default_key ();
1978        memset (&signer, 0, sizeof (signer));
1979        if (winpt_get_seckey (defkey, &signer)) {
1980            log_debug ("do_editkey_sign_userid: no default secret key.\r\n");
1981            free_if_alloc (defkey);
1982            return FALSE;
1983        }
1984        if (signer.is_protected) {
1985            pass = request_key_passphrase (signer.ctx, _("Key Edit"), &cancel);
1986            if (cancel)
1987                return FALSE;
1988        }
1989        ke.setKeyID (k->keyid);
1990        if (signer.is_protected)
1991            ke.setPassphrase (pass);
1992        else
1993            ke.setNoPassphrase (true);
1994        ke.setLocalUser (signer.ctx);
1995        err = ke.signUserid (uid_index,
1996                              mode == CMD_SIGN? GPG_EDITKEY_SIGN : GPG_EDITKEY_LSIGN,
1997                              0, NULL);
1998        if (!err) {
1999            msg_box (dlg, _("Key successfully signed."), _("Key Edit"), MB_OK);
2000            k->update = 1;
2001        }
2002        else
2003            msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
2004    
2005        sfree_if_alloc (pass);
2006        return !err? TRUE : FALSE;
2007    }
2008    
2009    
2010    static int
2011    lookup_cmd (HWND dlg)
2012    {
2013        char buf[64];
2014        int i;
2015    
2016        i = SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_GETCURSEL, 0, 0);
2017        if (i == LB_ERR)
2018            return LB_ERR;
2019        GetDlgItemText (dlg, IDC_KEYEDIT_CMD, buf, DIM (buf)-1);
2020        for (i=0; cmdlist[i].name != NULL; i++) {
2021            if (!strcmp (buf, cmdlist[i].name))
2022                return cmdlist[i].id;
2023        }
2024        return LB_ERR;
2025    }
2026    
2027    
2028    
2029    gpgme_error_t key_get_revokers (winpt_key_t key, int reload,
2030                                    gpg_desig_rev_t *r_rev);
2031    
2032    /* Check if the key supports designated revokers and if
2033        secret keys exist to generate such a revoke cert. */
2034    static bool
2035    check_desig_rev (winpt_key_t key)
2036    {
2037        gpg_desig_rev_t rev, u;
2038        struct winpt_key_s sk;
2039    
2040        if (!key->ext->gloflags.has_desig_rev)
2041            return false;
2042        key_get_revokers (key, 0, &rev);
2043        for (u = rev; u; u = u->next) {
2044            memset (&sk, 0, sizeof (sk));
2045            if (!winpt_get_seckey (u->fpr+32, &sk))
2046                return true;
2047        }
2048        return false;
2049    }
2050    
2051    
2052    /* Use the gpg --desig-revoker command to create a revocation
2053       cert for a key that lists our key as a designated revoker. */
2054    static void
2055    gen_desig_revoke_cert (winpt_key_t key, HWND dlg)
2056    {
2057        const char *warn;
2058        char *inf, *p;
2059        int id;
2060    
2061        inf = km_key_get_info (key, 0);
2062        warn = _("Your keys is listed as a designated revoker for the key\n\n"
2063                 "%s\n\n"
2064                 "Are you sure you want to create a revocation certificate\n"
2065                 "which allows you to revoke the key listed above?");
2066        p = new char[strlen (inf)+1+strlen (warn)+1];
2067        sprintf (p, warn, inf);
2068        free_if_alloc (inf);
2069    
2070        id = msg_box (dlg, p, _("Key Edit"), MB_YESNO|MB_ICONWARNING);
2071        free_if_alloc (p);
2072        if (id == IDNO)
2073            return;
2074    
2075        key->internal = 1;
2076        DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYREVOKE, dlg,
2077                        key_revoke_dlg_proc, (LPARAM)key);
2078    }
2079    
2080    
2081    /* Create tooltip control for the listview header. */
2082    static HWND
2083    create_header_tooltip (HWND dlg)
2084    {
2085        TOOLINFO ti;
2086        HWND tt;
2087    
2088        tt = CreateWindow (TOOLTIPS_CLASS, (LPSTR) NULL, TTS_ALWAYSTIP,
2089                            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2090                            CW_USEDEFAULT,
2091                            NULL, (HMENU) NULL, glob_hinst, NULL);
2092        if (!tt)
2093            BUG (NULL);
2094        memset (&ti, 0, sizeof (ti));
2095        ti.cbSize = sizeof (TOOLINFO);
2096        ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS;    
2097        ti.hwnd = dlg;    
2098        ti.uId = (UINT) ListView_GetHeader (GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST));
2099        ti.hinst = 0;
2100        ti.lpszText = (char*)_("Capabilties: C = Certify, S = Sign, E = Encrypt, A = Authenticate");
2101        SendMessage(tt, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
2102        return tt;
2103    }
2104    
2105    
2106    /* Dialog box procedure for the edit key dialog. */
2107  BOOL CALLBACK  BOOL CALLBACK
2108  keyedit_main_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  keyedit_main_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
2109  {  {
2110      static winpt_key_t k;      static winpt_key_t k;
2111      static listview_ctrl_t lvsub = NULL, lvuid = NULL;      static listview_ctrl_t lvsub = NULL, lvuid = NULL;
2112      int cmd, idxsub = 0;      static HWND tt;
2113        int cmd;
2114      HWND item;      HWND item;
2115    
2116      switch( msg ) {      switch (msg) {
2117      case WM_INITDIALOG:      case WM_INITDIALOG:
2118          k = (winpt_key_t)lparam;          k = (winpt_key_t)lparam;
2119          if (!k)          if (!k)
2120              BUG (NULL);              BUG (NULL);
2121          do_init_cmdlist (dlg);          do_init_cmdlist (dlg, k->key_pair);
2122          lvsub = subkey_list_init (dlg, k);          lvsub = subkey_list_init (dlg, k);
         if( !lvsub )  
             BUG( NULL );  
2123          lvuid = userid_list_init (dlg, k);          lvuid = userid_list_init (dlg, k);
2124          if( !lvuid )          item = GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST);
2125              BUG( NULL );          keyedit_subkey_proc.opaque = (void*)k;
         item = GetDlgItem( dlg, IDC_KEYEDIT_KEYLIST );  
2126          keyedit_subkey_proc.dlg = dlg;          keyedit_subkey_proc.dlg = dlg;
2127          keyedit_subkey_proc.current = (WNDPROC)subkey_subclass_proc;          keyedit_subkey_proc.current = (WNDPROC)subkey_subclass_proc;
2128          keyedit_subkey_proc.old = (WNDPROC)GetWindowLong( item, GWL_WNDPROC );          keyedit_subkey_proc.old = (WNDPROC)GetWindowLong (item, GWL_WNDPROC);
2129          if( keyedit_subkey_proc.old ) {          if (keyedit_subkey_proc.old) {
2130              if( !SetWindowLong( item, GWL_WNDPROC, (LONG)keyedit_subkey_proc.current ) ) {              if (!SetWindowLong (item, GWL_WNDPROC,
2131                  msg_box( dlg, _("Could not set subkey window procedure."), _("Key Edit"), MB_ERR );                                  (LONG)keyedit_subkey_proc.current)) {
2132                  BUG( NULL );                  msg_box (dlg, "Could not set subkey window procedure.",
2133                             _("Key Edit"), MB_ERR);
2134                    BUG (NULL);
2135              }              }
2136          }          }
2137          item = GetDlgItem( dlg, IDC_KEYEDIT_UIDLIST );          tt = create_header_tooltip (dlg);
2138            item = GetDlgItem (dlg, IDC_KEYEDIT_UIDLIST);
2139            keyedit_uid_proc.opaque = (void*)k;
2140          keyedit_uid_proc.dlg = dlg;          keyedit_uid_proc.dlg = dlg;
2141          keyedit_uid_proc.current = (WNDPROC)uid_subclass_proc;          keyedit_uid_proc.current = (WNDPROC)uid_subclass_proc;
2142          keyedit_uid_proc.old = (WNDPROC)GetWindowLong( item, GWL_WNDPROC );          keyedit_uid_proc.old = (WNDPROC)GetWindowLong (item, GWL_WNDPROC);
2143          if( keyedit_uid_proc.old ) {          if (keyedit_uid_proc.old) {
2144              if( !SetWindowLong( item, GWL_WNDPROC, (LONG)keyedit_uid_proc.current ) ) {              if (!SetWindowLong (item, GWL_WNDPROC,
2145                  msg_box( dlg, _("Could not set user ID window procedure."), _("Key Edit"), MB_ERR );                                  (LONG)keyedit_uid_proc.current)) {
2146                  BUG( NULL );                  msg_box (dlg, "Could not set user ID window procedure.",
2147                             _("Key Edit"), MB_ERR);
2148                    BUG (NULL);
2149              }              }
2150          }          }
2151          if (!k->key_pair) {          if (k->ctx->revoked) {
2152              EnableWindow (GetDlgItem (dlg, IDC_KEYEDIT_CMD), FALSE);              EnableWindow (GetDlgItem (dlg, IDC_KEYEDIT_CMD), FALSE);
2153              EnableWindow (GetDlgItem (dlg, IDOK), FALSE);              EnableWindow (GetDlgItem (dlg, IDOK), FALSE);
2154          }          }
2155          SetDlgItemText (dlg, IDC_KEYEDIT_CMDINF, _("Command>"));          SetDlgItemText (dlg, IDC_KEYEDIT_CMDINF, _("Command>"));
2156          SetDlgItemText (dlg, IDCANCEL, _("&Close"));          SetDlgItemText (dlg, IDCANCEL, _("&Close"));
2157          SetDlgItemText (dlg, IDC_KEYEDIT_HELP, _("&Help"));          SetDlgItemText (dlg, IDC_KEYEDIT_HELP, _("&Help"));
2158            SetDlgItemText (dlg, IDC_KEYEDIT_REVOKE, _("&Revoke..."));
2159            SetDlgItemText (dlg, IDOK, _("&OK"));
2160            if (!check_desig_rev (k))
2161                ShowWindow (GetDlgItem (dlg, IDC_KEYEDIT_REVOKE), SW_HIDE);
2162          SetWindowText (dlg, _("Key Edit"));          SetWindowText (dlg, _("Key Edit"));
2163                    SetForegroundWindow (dlg);
2164          SetForegroundWindow( dlg );          center_window (dlg, NULL);
         center_window( dlg, NULL );  
2165          return TRUE;          return TRUE;
2166    
2167      case WM_DESTROY:      case WM_DESTROY:
2168          if( lvsub ) {          if (lvsub) {
2169              listview_release( lvsub );              listview_release (lvsub);
2170              lvsub = NULL;              lvsub = NULL;
2171          }          }
2172          if( lvuid ) {          if (lvuid) {
2173              listview_release( lvuid );              listview_release (lvuid);
2174              lvuid = NULL;              lvuid = NULL;
2175          }          }
2176          break;          break;
2177    
2178      case WM_NOTIFY:      case WM_NOTIFY:
2179          NMHDR * notify;          NMHDR *notify;
2180          notify = (NMHDR *)lparam;          notify = (NMHDR *)lparam;
2181          if (notify && notify->code == NM_DBLCLK &&          if (!notify || notify->idFrom != IDC_KEYEDIT_UIDLIST)
2182              notify->idFrom == IDC_KEYEDIT_UIDLIST)              break;
2183            if (notify->code == NM_DBLCLK)
2184              do_editkey_showpref (k, dlg, lvuid);              do_editkey_showpref (k, dlg, lvuid);
2185            else if (notify->code == NM_RCLICK && k->key_pair) {
2186                HMENU hm = LoadMenu (glob_hinst, MAKEINTRESOURCE (IDR_WINPT_KEYEDIT));
2187                HMENU popup = GetSubMenu (hm, 0);
2188                POINT p;
2189    
2190                GetCursorPos (&p);
2191                TrackPopupMenu (popup, TPM_RIGHTALIGN, p.x, p.y, 0, dlg, NULL);
2192                DestroyMenu (hm);
2193                DestroyMenu (popup);
2194            }
2195          break;          break;
2196    
2197      case WM_COMMAND:      case WM_COMMAND:
2198          switch( LOWORD( wparam ) ) {          switch (LOWORD (wparam)) {
2199          case IDOK:          case IDOK:
2200              cmd = SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_GETCURSEL, 0, 0);              cmd = lookup_cmd (dlg);
2201              if (cmd == LB_ERR) {              if (cmd == LB_ERR) {
2202                  msg_box( dlg, _("Please select a command."), _("Key Edit"), MB_INFO );                  msg_box( dlg, _("Please select a command."), _("Key Edit"), MB_INFO );
2203                  return FALSE;                  return FALSE;
2204              }              }
             idxsub = listview_get_curr_pos (lvsub);  
2205              if (k->is_v3 && is_cmd_openpgp (cmd)) {              if (k->is_v3 && is_cmd_openpgp (cmd)) {
2206                  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"),
2207                                  _("Key Edit"), MB_ERR);                                  _("Key Edit"), MB_ERR);
# Line 1809  keyedit_main_dlg_proc (HWND dlg, UINT ms Line 2213  keyedit_main_dlg_proc (HWND dlg, UINT ms
2213              case CMD_ADDKEY: keyedit_add_subkey (k, dlg, lvsub); break;              case CMD_ADDKEY: keyedit_add_subkey (k, dlg, lvsub); break;
2214              case CMD_EXPIRE: do_editkey_expire (k, dlg, lvsub); break;              case CMD_EXPIRE: do_editkey_expire (k, dlg, lvsub); break;
2215              case CMD_REVKEY: do_editkey_revoke (k, dlg, lvsub); break;              case CMD_REVKEY: do_editkey_revoke (k, dlg, lvsub); break;
2216              /*case CMD_SETPREF:do_editkey_setpref( k, dlg, lvuid ); break;*/              case CMD_SETPREF:/*do_editkey_setpref (k, dlg, lvuid);*/ break;
2217              case CMD_ADDUID: keyedit_add_userid( k, dlg, lvuid ); break;              case CMD_ADDUID: keyedit_add_userid( k, dlg, lvuid ); break;
2218              case CMD_ADDREVOKER: keyedit_add_revoker( k, dlg ); break;              case CMD_ADDREVOKER: keyedit_add_revoker( k, dlg ); break;
2219              case CMD_ADDPHOTO: keyedit_add_photo( k, dlg ); break;              case CMD_ADDPHOTO: keyedit_add_photo( k, dlg ); break;
# Line 1817  keyedit_main_dlg_proc (HWND dlg, UINT ms Line 2221  keyedit_main_dlg_proc (HWND dlg, UINT ms
2221              case CMD_DELUID: do_editkey_deluid( k, dlg, lvuid ); break;              case CMD_DELUID: do_editkey_deluid( k, dlg, lvuid ); break;
2222              case CMD_PASSWD: keyedit_change_passwd( k, dlg ); break;              case CMD_PASSWD: keyedit_change_passwd( k, dlg ); break;
2223              case CMD_PRIMARY: do_editkey_primary( k, dlg, lvuid ); break;              case CMD_PRIMARY: do_editkey_primary( k, dlg, lvuid ); break;
2224              case CMD_ENABLE: km_enable_disable_key( lvsub, dlg, idxsub, 1 ); break;              case CMD_ENABLE: do_editkey_enable_disable (k, dlg, lvsub, 1); break;
2225              case CMD_DISABLE: km_enable_disable_key( lvsub, dlg, idxsub, 0 ); break;              case CMD_DISABLE: do_editkey_enable_disable (k, dlg, lvsub, 0); break;
2226                case CMD_CHECK: do_editkey_check (k, dlg); break;
2227                case CMD_TRUST: keyedit_change_ownertrust (k, dlg); break;
2228                case CMD_SIGN:
2229                case CMD_LSIGN: do_editkey_sign_userid (k, dlg,
2230                                                        lvuid, cmd);
2231                                break;
2232                case CMD_CLEAN: do_editkey_clean (k, dlg); break;
2233                case CMD_MINIMIZE: do_editkey_minimize (k, dlg); break;
2234              }              }
2235              break;              break;          
2236    
2237          case IDCANCEL:          case IDCANCEL:
2238              EndDialog (dlg, FALSE);              EndDialog (dlg, FALSE);
# Line 1829  keyedit_main_dlg_proc (HWND dlg, UINT ms Line 2241  keyedit_main_dlg_proc (HWND dlg, UINT ms
2241          case IDC_KEYEDIT_HELP:          case IDC_KEYEDIT_HELP:
2242              do_show_help (dlg);              do_show_help (dlg);
2243              break;              break;
2244    
2245            case IDC_KEYEDIT_REVOKE:
2246                gen_desig_revoke_cert (k, dlg);
2247                break;
2248    
2249            case ID_KEYEDIT_UID_PRIM:
2250                do_editkey_primary (k, dlg, lvuid);
2251                break;
2252    
2253            case ID_KEYEDIT_UID_DEL:
2254                do_editkey_deluid (k, dlg, lvuid);
2255                break;
2256    
2257            case ID_KEYEDIT_UID_REV:
2258                do_editkey_revuid (k, dlg, lvuid);
2259                break;
2260          }          }
2261          break;          break;
2262      }      }
2263      return FALSE;      return FALSE;
2264  } /* keyedit_main_dlg_proc */  }

Legend:
Removed from v.117  
changed lines
  Added in v.314

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26