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

Annotation of /trunk/Src/wptKeyEditDlgs.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 215 - (hide annotations)
Wed May 17 07:10:46 2006 UTC (18 years, 9 months ago) by twoaday
File size: 59284 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26