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

Legend:
Removed from v.88  
changed lines
  Added in v.236

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26