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

Annotation of /trunk/Src/wptKeyEditDlgs.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 208 - (hide annotations)
Mon May 1 12:22:18 2006 UTC (18 years, 10 months ago) by twoaday
File size: 59563 byte(s)
See ChangeLog.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26