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

Annotation of /trunk/Src/wptKeyEditDlgs.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (hide annotations)
Fri Oct 28 07:15:26 2005 UTC (19 years, 4 months ago) by twoaday
File size: 49369 byte(s)
A lot of bug fixes. See ChangeLog.

1 werner 36 /* wptKeyEditDlgs.cpp - GPG key edit dialogs
2     * Copyright (C) 2002-2005 Timo Schulz
3     *
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    
21     #include <windows.h>
22     #include <commctrl.h>
23     #include "../resource.h"
24    
25     #include "wptTypes.h"
26     #include "wptW32API.h"
27     #include "wptVersion.h"
28     #include "wptGPG.h"
29     #include "wptCommonCtl.h"
30     #include "wptContext.h"
31     #include "wptDlgs.h"
32     #include "wptNLS.h"
33     #include "wptUTF8.h"
34     #include "wptErrors.h"
35     #include "wptKeylist.h"
36     #include "wptKeyManager.h"
37     #include "wptRegistry.h"
38     #include "wptKeyEdit.h"
39    
40     /* All edit key commands. */
41     enum keyedit_commands {
42     CMD_ADDKEY = 0,
43     CMD_ADDUID,
44     CMD_ADDPHOTO,
45     CMD_ADDREVOKER,
46     /*CMD_FPR,*/
47     CMD_DELUID,
48     CMD_DELKEY,
49     CMD_DELPHOTO,
50     /*CMD_DELSIG,*/
51     CMD_EXPIRE,
52     /*CMD_PREF,*/
53     CMD_SHOWPREF,
54     /*CMD_SETPREF,*/
55     /*CMD_UPDPREF,*/
56     CMD_PASSWD,
57     CMD_PRIMARY,
58     CMD_TRUST,
59     /*CMD_REVSIG,*/
60     CMD_REVUID,
61     CMD_REVKEY,
62     CMD_DISABLE,
63     CMD_ENABLE,
64     /*CMD_SHOWPHOTO,*/
65     };
66    
67    
68     /* Symbolic ids for the subkey columns. */
69     enum subk_col_t {
70     SUBK_COL_DESC = 0,
71     SUBK_COL_KEYID = 1,
72     SUBK_COL_CREATION = 2,
73     SUBK_COL_EXPIRES = 3,
74     SUBK_COL_STATUS = 4,
75     SUBK_COL_C_FLAG = 5,
76     SUBK_COL_S_FLAG = 6,
77     SUBK_COL_E_FLAG = 7,
78     SUBK_COL_A_FLAG = 8
79     };
80    
81     /* Symbolic ids for the userid columns. */
82     enum uid_col_t {
83     UID_COL_VALID = 0,
84     UID_COL_NAME = 1,
85     UID_COL_EMAIL = 2,
86     UID_COL_CREATION = 3
87     };
88    
89     struct keyedit_callback_s {
90     const char *keyid;
91     const char *pass;
92     listview_ctrl_t lv;
93     void *opaque;
94     unsigned int finished:1;
95     };
96     typedef struct keyedit_callback_s KEYEDIT_CB;
97    
98     struct keygen_callback_s {
99     int bits;
100     int algo;
101     u32 expire;
102     char *fpr;
103     };
104     typedef struct keygen_callback_s KEYGEN_CB;
105    
106    
107     static subclass_s keyedit_subkey_proc;
108     static subclass_s keyedit_uid_proc;
109    
110     int keygen_check_date (SYSTEMTIME *st);
111     void get_userid_preflist (char **r_prefs, int * r_flags);
112     char* get_subkey_fingerprint (const char *keyid);
113    
114    
115     /* Associate each key with a combo box entry.
116     Skip the key in @k. */
117     static void
118     do_init_keylist (HWND dlg, winpt_key_t k)
119     {
120     gpg_keycache_t pub;
121     gpgme_key_t key;
122     const char * s, * kid;
123     char * u;
124     int i, n;
125    
126     pub = keycache_get_ctx (1);
127     if (!pub)
128     BUG (0);
129    
130     gpg_keycache_rewind (pub);
131     while( !gpg_keycache_next_key( pub, 0, &key ) ) {
132     s = key->uids->uid;
133     kid = key->subkeys->keyid;
134     if (!s || !strcmp (kid+8, k->keyid+2))
135     continue;
136     u = utf8_to_wincp (s, strlen (s));
137     SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_ADDSTRING,
138     0, (WPARAM)(char *)u);
139     free (u);
140     }
141     gpg_keycache_rewind (pub);
142     n = SendDlgItemMessage( dlg, IDC_ADDREV_KEYLIST, CB_GETCOUNT, 0, 0 );
143     for (i = 0; i < n; i++) {
144     gpg_keycache_next_key (pub, 0, &key);
145     SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETITEMDATA,
146     (WPARAM)(int)i, (LPARAM)key);
147     }
148     SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETCURSEL, 0, 0);
149     }
150    
151    
152     /* Add a new user-id to the list view @lv. */
153     static void
154     do_add_new_userid (listview_ctrl_t lv,
155     const char * name, const char *email, const char * comment)
156     {
157     char * p;
158     size_t n;
159    
160     n = strlen (name) + strlen (email) + 16;
161     if (comment)
162     n += strlen (comment);
163     p = new char[n+1];
164     if (!p)
165     BUG( NULL );
166     if (comment)
167     sprintf (p, "%s (%s)", name, comment);
168     else
169     sprintf (p, "%s", name);
170    
171     listview_add_item (lv, "");
172     listview_add_sub_item (lv, 0, 0, _("Ultimate" ));
173     listview_add_sub_item (lv, 0, 1, p);
174     listview_add_sub_item (lv, 0, 2, email && *email? email : "");
175     listview_add_sub_item (lv, 0, 3, get_key_created (time (NULL)));
176     free_if_alloc (p);
177     } /* do_add_new_userid */
178    
179    
180     static void
181     do_add_new_subkey (listview_ctrl_t lv, KEYGEN_CB *keygen, unsigned int flags)
182     {
183     char info[128], keyid[32];
184     const char * expdate, * s;
185     int n;
186    
187     expdate = keygen->expire? get_key_expire_date (keygen->expire) : _("Never");
188     _snprintf (info, sizeof info-1, "%d-bit %s",
189     keygen->bits,
190     get_key_pubalgo ((gpgme_pubkey_algo_t)keygen->algo));
191     _snprintf (keyid, sizeof keyid-1, "0x%s", keygen->fpr+32);
192     n = listview_count_items (lv, 0);
193     listview_add_item_pos (lv, n);
194     listview_add_sub_item (lv, n, 0, info);
195     listview_add_sub_item (lv, n, 1, keyid);
196     listview_add_sub_item (lv, n, 2, get_key_created (time (NULL)));
197     listview_add_sub_item (lv, n, 3, expdate);
198     if (flags & KM_FLAG_REVOKED) s = _("Revoked");
199     else if (flags & KM_FLAG_EXPIRED) s = _("Expired");
200     else s = _("OK");
201     listview_add_sub_item (lv, n, 4, s);
202     } /* do_add_new_subkey */
203    
204    
205     /* Try to find the GPG edit key index which belongs to the user ID
206     given by @name. If @r_inf != NULL, the info context will be returned.
207     Return value: index of the user ID or -1 on error. */
208     static int
209     do_find_userid (const char *keyid, const char *name, gpg_uid_info_t *r_inf)
210     {
211     GpgKeyEdit *ke;
212     gpgme_error_t err;
213     gpg_uid_info_t inf, ui;
214     int pos = -1;
215    
216     ke = new GpgKeyEdit (keyid);
217     if (!ke)
218     BUG (NULL);
219     err = ke->getUseridInfo (&inf);
220     delete ke;
221     if (err) {
222     log_box (_("user ID"), MB_ERR,
223     _("Could not get key information for: \"%s\":\n%s"),
224     name, gpgme_strerror (err));
225     return -1;
226     }
227    
228     for (ui = inf; ui; ui = ui->next) {
229     if (!strcmp (ui->email, name)) {
230     pos = ui->index;
231     break;
232     }
233     }
234     if (r_inf)
235     *r_inf = inf;
236     else
237     gpg_uid_info_release (inf);
238     return pos;
239     }
240    
241    
242     /* Dialog box procedure to add a photo. */
243     BOOL CALLBACK
244     keyedit_addphoto_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
245     {
246     static winpt_key_t k;
247     GpgKeyEdit *ke;
248     gpgme_error_t ec;
249     const char * s;
250     char pwd[128], file[128];
251     int id;
252    
253     switch( msg ) {
254     case WM_INITDIALOG:
255     k = (winpt_key_t)lparam;
256     if (!k)
257     BUG (NULL);
258     SetDlgItemText (dlg, IDC_ADDPHOTO_INF, _("Remember that the image is stored within your public key. If you use a very large picture, your key will become very large as well! Keeping the image close to 240x288 is a good size to use."));
259     SetDlgItemText (dlg, IDC_ADDPHOTO_FILEINF, _("Pick an image to use for your photo ID.\nThe image must be a JPEG file."));
260     SetDlgItemText (dlg, IDC_ADDPHOTO_PWDINF, _("Passphrase"));
261     SetForegroundWindow( dlg );
262     break;
263    
264     case WM_DESTROY:
265     break;
266    
267     case WM_SYSCOMMAND:
268     if( LOWORD (wparam) == SC_CLOSE )
269     EndDialog( dlg, TRUE );
270     break;
271    
272     case WM_COMMAND:
273     switch( LOWORD( wparam ) ) {
274    
275     case IDC_ADDPHOTO_SELFILE:
276     s = get_filename_dlg( dlg, FILE_OPEN, _("Select Image File"), _("JPEG Files (*.jpg, *.jpeg)\0*.jpg;*.jpeg\0\0"), NULL );
277     if( s && *s )
278     SetDlgItemText( dlg, IDC_ADDPHOTO_FILE, s );
279     break;
280    
281     case IDOK:
282     if( !GetDlgItemText( dlg, IDC_ADDPHOTO_FILE, file, sizeof file-1 ) ){
283     msg_box( dlg, _("Please enter a file name."), _("Add Photo"), MB_ERR );
284     return FALSE;
285     }
286     if( get_file_size( file ) == 0 || get_file_size( file ) > 6144 ) {
287     id = msg_box( dlg, _("The JPEG is really large.\n"
288     "Are you sure you want to use it?"),
289     _("Add Photo"), MB_YESNO|MB_INFO );
290     if( id == IDNO )
291     return TRUE;
292     }
293     if( k->is_protected ) {
294     if( !GetDlgItemText( dlg, IDC_ADDPHOTO_PASS, pwd, sizeof pwd-1 ) ) {
295     msg_box( dlg, _("Please enter a passphrase."), _("Add Photo"), MB_ERR );
296     return FALSE;
297     }
298     }
299     ke = new GpgKeyEdit (k->keyid);
300     if (!ke)
301     BUG (NULL);
302    
303     if (k->is_protected)
304     ke->setPassphrase (pwd);
305     ec = ke->addPhotoid (file);
306     delete ke;
307     memset (pwd, 0, sizeof pwd);
308     if (ec) {
309     msg_box (dlg, gpgme_strerror (ec), _("Add Photo"), MB_ERR );
310     return FALSE;
311     }
312     else {
313     k->update = 1;
314     msg_box (dlg, _("Photo successfully added."), _("GnuPG Status"), MB_OK);
315     }
316     EndDialog (dlg, TRUE);
317     break;
318    
319     case IDCANCEL:
320     EndDialog (dlg, FALSE);
321     break;
322     }
323     break;
324     }
325     return FALSE;
326     }
327    
328    
329     /* Dialog box procedure to add a designated revoker. */
330     BOOL CALLBACK
331     keyedit_addrevoker_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
332     {
333     static winpt_key_t k;
334     static gpgme_key_t seckey;
335     GpgKeyEdit *ke;
336     gpgme_error_t err;
337     char uid[128], pwd[128];
338    
339    
340     switch( msg ) {
341     case WM_INITDIALOG:
342     k = (winpt_key_t)lparam;
343     if( !k )
344     BUG( NULL );
345     if( get_seckey( k->keyid, &seckey ) )
346     BUG( NULL );
347     if (!k->is_protected)
348     EnableWindow (GetDlgItem (dlg, IDC_ADDREV_PASS), FALSE);
349     do_init_keylist (dlg, k);
350     SetDlgItemText (dlg, IDC_ADDREV_INF, _("Appointing a key as designated revoker cannot be undone."));
351     SetDlgItemText (dlg, IDC_ADDREV_KEYINF, _("Public key"));
352     SetDlgItemText (dlg, IDC_ADDREV_PWDINF, _("Passphrase"));
353     SetForegroundWindow( dlg );
354     break;
355    
356     case WM_DESTROY:
357     break;
358    
359     case WM_SYSCOMMAND:
360     if( LOWORD (wparam) == SC_CLOSE )
361     EndDialog( dlg, TRUE );
362     break;
363    
364     case WM_COMMAND:
365     switch( LOWORD( wparam ) ) {
366     case IDOK:
367     if( !GetDlgItemText( dlg, IDC_ADDREV_KEYLIST, uid, sizeof uid-1 ) ) {
368     msg_box( dlg, _("Please select a user ID."), _("Add Revoker"), MB_ERR );
369     return FALSE;
370     }
371    
372     if( k->is_protected ) {
373     if( !GetDlgItemText( dlg, IDC_ADDREV_PASS, pwd, sizeof pwd-1 ) ) {
374     msg_box( dlg, _("Please enter the passphrase."), _("Add Revoker"), MB_ERR );
375     return FALSE;
376     }
377     }
378     ke = new GpgKeyEdit (k->keyid);
379     if (k->is_protected)
380     ke->setPassphrase (pwd);
381     err = ke->addDesignatedRevoker (uid);
382     delete ke;
383     memset (pwd, 0, sizeof pwd);
384     if (err) {
385     msg_box (dlg, gpgme_strerror (err), _("Add Revoker"), MB_ERR);
386     return TRUE;
387     }
388     else {
389     k->update = 1;
390     msg_box (dlg, _("Revoker successfully addded."), _("GnuPG Status"), MB_OK);
391     }
392     EndDialog( dlg, TRUE );
393     break;
394    
395     case IDCANCEL:
396     EndDialog( dlg, FALSE );
397     break;
398     }
399     break;
400     }
401     return FALSE;
402     }
403    
404    
405     /* Dialog box procedure to add a new user-ID. */
406     BOOL CALLBACK
407     keyedit_adduid_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
408     {
409     static KEYEDIT_CB *ctx;
410     gpgme_error_t err;
411     GpgKeyEdit *ke;
412     char *utf8_name = NULL;
413     char name[128], email[128], comment[128];
414     int rc;
415    
416     switch ( msg ) {
417     case WM_INITDIALOG:
418     ctx = (KEYEDIT_CB *)lparam;
419     if( !ctx )
420     dlg_fatal_error(dlg, "Could not get dialog param!");
421     #ifndef LANG_DE
422     SetWindowText (dlg, _("Add new User ID"));
423     SetDlgItemText (dlg, IDC_ADDUID_INFNAME, _("&Name"));
424     SetDlgItemText (dlg, IDC_ADDUID_INFEMAIL, _("&Email"));
425     SetDlgItemText (dlg, IDC_ADDUID_INFCOMMENT, _("&Comment"));
426     #endif
427     SetForegroundWindow (dlg);
428     return FALSE;
429    
430     case WM_SYSCOMMAND:
431     if (LOWORD (wparam) == SC_CLOSE) {
432     EndDialog(dlg, TRUE);
433     }
434     return FALSE;
435    
436     case WM_COMMAND:
437     switch ( LOWORD( wparam ) ) {
438     case IDOK:
439     rc = GetDlgItemText( dlg, IDC_ADDUID_NAME, name, sizeof name-1 );
440     if (!rc || rc < 5) {
441     msg_box( dlg, _("Please enter a name (min. 5 chars.)"), _("UserID"), MB_ERR );
442     return FALSE;
443     }
444     if (strchr (name, '@')) {
445     msg_box( dlg, _("Please enter the email address in the email field and not in the name field"), _("UserID"), MB_INFO );
446     return FALSE;
447     }
448    
449     if( !GetDlgItemText( dlg, IDC_ADDUID_EMAIL, email, sizeof email -1 ) ) {
450     msg_box( dlg, _("Please enter an email address."), _("UserID"), MB_ERR );
451     return FALSE;
452     }
453     if( !strchr( email, '@' ) || strchr (email, ' ')) {
454     msg_box( dlg, _("Invalid email address."), _("UserID"), MB_ERR );
455     return FALSE;
456     }
457    
458     rc = GetDlgItemText( dlg, IDC_ADDUID_COMMENT, comment, sizeof comment -1 );
459    
460     /* XXX: something is wrong with the encoding :-( */
461     utf8_name = wincp_to_utf8 (name, strlen (name));
462    
463     ke = new GpgKeyEdit (ctx->keyid);
464     if (!ke)
465     BUG (NULL);
466     if (ctx->pass)
467     ke->setPassphrase (ctx->pass);
468     err = ke->addUserid (utf8_name? utf8_name : name,
469     rc > 0? comment : NULL, email);
470     if (err)
471     msg_box (dlg, gpgme_strerror (err), _("UserID"), MB_ERR);
472     else {
473     msg_box (dlg, _("user ID successfully added."), _("GnuPG Status"), MB_OK);
474     ctx->finished = 1;
475     }
476     delete ke;
477     free (utf8_name);
478     if (!err && ctx->lv)
479     do_add_new_userid (ctx->lv, name, email, rc?comment : NULL);
480     EndDialog (dlg, TRUE);
481     return TRUE;
482    
483     case IDCANCEL:
484     EndDialog (dlg, FALSE);
485     return FALSE;
486     }
487     break;
488     }
489    
490     return FALSE;
491     }
492    
493    
494     static int
495     diff_time (HWND dt, SYSTEMTIME *in_exp)
496     {
497     SYSTEMTIME exp, now;
498     double e=0, n=0;
499    
500     if (in_exp)
501     memcpy (&exp, in_exp, sizeof (SYSTEMTIME));
502     else
503     DateTime_GetSystemtime (dt, &exp);
504     GetSystemTime (&now);
505     SystemTimeToVariantTime (&exp, &e);
506     SystemTimeToVariantTime (&now, &n);
507     if (n > e)
508     return 0;
509     return (int)(e-n);
510     }
511    
512    
513     static void
514     init_keysize_box (HWND dlg, int ctlid)
515     {
516     const char *sizelist[] = {
517     "1024", "1536", "2048", "2560", "3072", "3854", "4096", NULL
518     };
519     int i;
520     for (i=0; sizelist[i] != NULL; i++)
521     SendDlgItemMessage (dlg, ctlid, CB_ADDSTRING, 0, (LPARAM)(char*)sizelist[i]);
522     SendDlgItemMessage (dlg, ctlid, CB_SETCURSEL, (WPARAM)2, 0);
523     }
524    
525     static int
526     get_keysize_from_box (HWND dlg, int ctlid)
527     {
528     int pos;
529     char buf[32];
530    
531     pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0);
532     if (pos == CB_ERR)
533     return -1;
534     SendDlgItemMessage (dlg, ctlid, CB_GETLBTEXT, pos, (LPARAM)(char*)buf);
535     return atol (buf);
536     }
537    
538    
539     BOOL CALLBACK
540     keyedit_addsubkey_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
541     {
542     static KEYEDIT_CB *ctx;
543     static KEYGEN_CB *keygen;
544     GpgKeyEdit *ke;
545     gpgme_error_t err;
546     HWND lb;
547     int index, size, valid;
548    
549     switch (msg) {
550     case WM_INITDIALOG:
551     ctx = (KEYEDIT_CB *)lparam;
552     if (!ctx)
553     dlg_fatal_error (dlg, "Could not get dialog param!");
554     keygen = (KEYGEN_CB *)ctx->opaque;
555     #ifndef LANG_DE
556     SetWindowText (dlg, _("Add new Subkey"));
557     SetDlgItemText (dlg, IDC_ADDSUBKEY_INFALGO, _("Key type"));
558     SetDlgItemText (dlg, IDC_ADDSUBKEY_INFSIZE, _("Size in bits"));
559     SetDlgItemText (dlg, IDC_ADDSUBKEY_INFVALID, _("Key expiration"));
560     #endif
561     lb = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
562     listbox_add_string (lb, "DSA (sign only)");
563     listbox_add_string (lb, "ElGamal (encrypt only)");
564     listbox_add_string (lb, "RSA (sign only)");
565     listbox_add_string (lb, "RSA (encrypt only)");
566     CheckDlgButton (dlg, IDC_ADDSUBKEY_EXPIRE, BST_CHECKED);
567     EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
568     init_keysize_box (dlg, IDC_ADDSUBKEY_SIZE);
569     SetForegroundWindow( dlg );
570     return FALSE;
571    
572     case WM_SYSCOMMAND:
573     if( LOWORD (wparam) == SC_CLOSE ) {
574     EndDialog( dlg, TRUE );
575     }
576     return FALSE;
577    
578     case WM_COMMAND:
579     if (HIWORD (wparam) == BN_CLICKED && LOWORD (wparam) == IDC_ADDSUBKEY_EXPIRE) {
580     if (IsDlgButtonChecked (dlg, IDC_ADDSUBKEY_EXPIRE))
581     EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
582     else
583     EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), TRUE);
584     }
585     if (HIWORD (wparam) == LBN_SELCHANGE && LOWORD (wparam) == IDC_ADDSUBKEY_ALGO) {
586     index = SendMessage ((HWND)lparam, LB_GETCURSEL, 0, 0);
587     if (index == 0)
588     SendDlgItemMessage (dlg, IDC_ADDSUBKEY_SIZE, CB_SETCURSEL, 0, 0);
589     }
590    
591     switch ( LOWORD(wparam) ) {
592     case IDOK:
593     lb = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
594     switch (listbox_get_cursel (lb)) {
595     case 0: index = 2; break;
596     case 1: index = 4; break;
597     case 2: index = 5; break;
598     case 3: index = 6; break;
599     default:
600     msg_box( dlg, _("Please select one entry."), _("Add Subkey"), MB_ERR );
601     return FALSE;
602     }
603     size = get_keysize_from_box (dlg, IDC_ADDSUBKEY_SIZE);
604     if (index == 2 && size != 1024) {
605     msg_box( dlg,_("DSS uses a fixed keysize of 1024. Size changed."), _("Add Subkey"), MB_INFO );
606     size = 1024;
607     }
608     valid = diff_time (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), NULL);
609    
610     keygen->bits = size;
611     switch (index) {
612     case 2: keygen->algo = GPGME_PK_DSA; break;
613     case 4: keygen->algo = GPGME_PK_ELG_E; break;
614     case 5: keygen->algo = GPGME_PK_RSA_S; break;
615     case 6: keygen->algo = GPGME_PK_RSA_E; break;
616     }
617     if (valid > 0)
618     keygen->expire = time (NULL) + valid*24*60*60;
619    
620     ke = new GpgKeyEdit (ctx->keyid);
621     if (!ke)
622     BUG (NULL);
623     ke->setCallback (keygen_cb, NULL);
624     if (ctx->pass)
625     ke->setPassphrase (ctx->pass);
626     keygen_cb_dlg_create ();
627    
628     err = ke->addSubkey ((gpgme_pubkey_algo_t)index, size, valid);
629     keygen->fpr = get_subkey_fingerprint (ctx->keyid);
630     keygen_cb_dlg_destroy ();
631     keygen_cb (NULL, NULL, 0, 0, 0); /* flush */
632     if (err)
633     msg_box (dlg, gpgme_strerror (err), _("Add Subkey"), MB_ERR);
634     else {
635     msg_box (dlg, _("Subkey successfully added."), _("GnuPG Status"), MB_OK);
636     if (ctx->lv)
637     do_add_new_subkey (ctx->lv, keygen, /*XXXk->flags*/0);
638     ctx->finished = 1;
639     }
640     delete ke;
641     EndDialog (dlg, TRUE);
642     return TRUE;
643    
644     case IDCANCEL:
645     EndDialog( dlg, FALSE );
646     return FALSE;
647     }
648     break;
649     }
650    
651     return FALSE;
652     } /* keyedit_addsubkey_dlg_proc */
653    
654    
655     BOOL
656     keyedit_add_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
657     {
658     KEYEDIT_CB cb;
659     char *pass = NULL;
660     int cancel = 0;
661    
662     if (!k->key_pair) {
663     msg_box( dlg, _("There is no secret key available!"), _("Add user ID"), MB_ERR );
664     return FALSE;
665     }
666    
667     if (k->is_protected) {
668     pass = request_passphrase( _("Key Edit"), 1, &cancel );
669     if (cancel)
670     return FALSE;
671     }
672    
673     memset (&cb, 0, sizeof cb);
674     cb.pass = k->is_protected? pass : NULL;
675     cb.lv = lv;
676     cb.keyid = k->keyid;
677     dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDUID,
678     dlg, keyedit_adduid_dlg_proc,
679     (LPARAM)&cb, _("Add user ID"),
680     IDS_WINPT_KEYEDIT_ADDUID);
681    
682     if (cb.finished)
683     k->update = 1;
684    
685     sfree_if_alloc (pass);
686     return TRUE;
687     }
688    
689    
690     char*
691     get_subkey_fingerprint (const char *keyid)
692     {
693     static char fpr[40];
694     gpgme_error_t err;
695     gpgme_key_t key, main;
696     gpgme_ctx_t ctx;
697     gpgme_subkey_t last_sk, k, new_sk;
698     int n;
699    
700     err = gpgme_new (&ctx);
701     if (err)
702     return NULL;
703     err = gpgme_get_key (ctx, keyid, &key, 0);
704     if (err)
705     return NULL;
706     /* XXX: this is very slow and complicated */
707    
708     n = count_subkeys (key);
709     last_sk = get_nth_key (key, n-1);
710     new_sk = (gpgme_subkey_t)calloc (1, sizeof *new_sk);
711     if (!new_sk)
712     BUG (NULL);
713     memcpy (new_sk, last_sk, sizeof *last_sk);
714     new_sk->fpr = strdup (last_sk->fpr);
715     new_sk->keyid = strdup (last_sk->keyid);
716    
717     get_pubkey (keyid, &main);
718     for (k=main->subkeys; k->next; k=k->next)
719     ;
720     k->next = new_sk;
721    
722     gpgme_key_release (key);
723     return new_sk->fpr;
724     }
725    
726    
727     BOOL
728     keyedit_add_subkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
729     {
730     KEYEDIT_CB cb;
731     KEYGEN_CB keygen;
732     char *pass = NULL;
733     int cancel = 0;
734    
735     if (!k->key_pair) {
736     msg_box (dlg, _("There is no secret key available!"), _("Add Subkey"), MB_ERR);
737     return FALSE;
738     }
739     if (k->is_protected) {
740     pass = request_passphrase (_("Key Edit"), 1, &cancel);
741     if (cancel)
742     return FALSE;
743     }
744    
745     memset (&keygen, 0, sizeof (keygen));
746     memset (&cb, 0, sizeof (cb));
747     cb.keyid = k->keyid;
748     cb.pass = k->is_protected? pass : NULL;
749     cb.opaque = &keygen;
750     dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDSUBKEY,
751     dlg, keyedit_addsubkey_dlg_proc,
752     (LPARAM)&cb, _("Add new Subkey"),
753     IDS_WINPT_KEYEDIT_ADDSUBKEY);
754     if (cb.finished)
755     k->update = 1;
756    
757     sfree_if_alloc (pass);
758     return cb.finished? TRUE: FALSE;
759     }
760    
761    
762     BOOL
763     keyedit_set_pref_keyserver (winpt_key_t k, HWND dlg)
764     {
765     GpgKeyEdit *ke;
766     gpgme_error_t err;
767     struct URL_ctx_s *url;
768     char *pass;
769    
770     url = (struct URL_ctx_s *)get_keyserver_URL_dlg (dlg);
771     if (url->cancel == 1) {
772     delete url;
773     return FALSE;
774     }
775    
776     pass = request_passphrase (_("Key Edit"), 1, &url->cancel);
777     if (url->cancel) {
778     delete url;
779     return FALSE;
780     }
781    
782     ke = new GpgKeyEdit (k->keyid);
783     if (!ke)
784     BUG (NULL);
785     ke->setPassphrase (pass);
786     err = ke->setPreferredKeyserver (0 /* XXX */, url->url);
787     if (!err)
788     msg_box (dlg, _("Preferred keyserver successfully set."), _("Key Edit"), MB_OK);
789    
790     sfree_if_alloc (pass);
791     delete ke;
792     delete url;
793     return err == 0? 0 : WPTERR_GENERAL;
794     }
795    
796    
797     /* Add a photo-ID to the key specified in @k. @dlg is the handle of
798     the calling dialog. */
799     BOOL
800     keyedit_add_photo (winpt_key_t k, HWND dlg)
801     {
802     if (!k->key_pair) {
803     msg_box (dlg, _("There is no secret key available!"), _("Add Photo"), MB_ERR);
804     return FALSE;
805     }
806     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDPHOTO, dlg,
807     keyedit_addphoto_dlg_proc, (LPARAM)k);
808     return TRUE;
809     }
810    
811    
812     BOOL
813     keyedit_add_revoker (winpt_key_t k, HWND dlg)
814     {
815     if( !k->key_pair ) {
816     msg_box( dlg, _("There is no secret key available!"), _("Add Revoker"), MB_ERR );
817     return FALSE;
818     }
819     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDREV, dlg,
820     keyedit_addrevoker_dlg_proc, (LPARAM)k);
821     return TRUE;
822     } /* keyedit_add_revoker */
823    
824    
825     static int
826     is_idea_protect_algo (const char * keyid)
827     {
828     winpt_key_s k;
829     const unsigned char *sym_prefs;
830     size_t n;
831    
832     memset (&k, 0, sizeof (k));
833     if (winpt_get_pubkey (keyid, &k))
834     BUG (NULL);
835     sym_prefs = k.ext->sym_prefs;
836     if (!sym_prefs)
837     return 1; /* assume that only v3 keys have no symmetric cipher preferences
838     and thus IDEA is explicit. */
839     for (n = 0; sym_prefs[n]; n++)
840     ;
841     if ((n == 0 || n == 1) && *sym_prefs == 0x01)
842     return 1;
843     return 0;
844     } /* is_idea_protect_algo */
845    
846    
847     BOOL
848     keyedit_change_passwd( winpt_key_t k, HWND dlg )
849     {
850     GpgKeyEdit *ke;
851     gpgme_error_t ec;
852     char *old_pass = NULL, *new_pass = NULL;
853     int cancel = 0;
854    
855     if( !k->key_pair ) {
856     msg_box( dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR );
857     return FALSE;
858     }
859    
860     if( !idea_available && is_idea_protect_algo( k->keyid ) ) {
861     msg_box( dlg, _("Cannot change passphrase because the key\n"
862     "is protected with the IDEA encryption algorithm."),
863     _("Key Edit"), MB_ERR );
864     return FALSE;
865     }
866    
867     if( k->is_protected ) {
868     old_pass = request_passphrase( _("Current (old) Passphrase"), 1, &cancel );
869     if( cancel )
870     return FALSE;
871     }
872     new_pass = request_passphrase( _("New Passphrase" ), 1, &cancel );
873     if( cancel ) {
874     free_if_alloc( old_pass );
875     return FALSE;
876     }
877    
878     if( is_8bit_string( new_pass ) ) {
879     msg_box( dlg, _("The passphrase contains 8-bit characters.\n"
880     "It is not suggested to use charset specific characters."),
881     _("Key Edit"), MB_ERR );
882     free_if_alloc( old_pass );
883     free_if_alloc( new_pass );
884     return FALSE;
885     }
886    
887     ke = new GpgKeyEdit (k->keyid);
888     if (!ke)
889     BUG (NULL);
890    
891     ke->setPassphrase (k->is_protected? old_pass : NULL);
892     ec = ke->changePassphrase (new_pass, 0);
893     if( ec )
894     msg_box (dlg, gpgme_strerror (ec), _("Change Passwd"), MB_ERR);
895     else
896     msg_box (dlg, _("Passphrase successfully changed."), _("GnuPG status"), MB_OK);
897     sfree_if_alloc (old_pass);
898     sfree_if_alloc (new_pass);
899     delete ke;
900     return TRUE;
901     }
902    
903    
904     listview_ctrl_t
905     subkey_list_init( HWND dlg, winpt_key_t k )
906     {
907     LV_ITEM lvi;
908     gpgme_key_t key;
909     gpgme_subkey_t sub;
910     struct listview_column_s cols[] = {
911     {0, 80, (char *)_("Description")},
912     {1, 78, (char *)_("Key ID")},
913     {2, 66, (char *)_("Creation")},
914     {3, 66, (char *)_("Expires")},
915     {4, 64, (char *)_("Status")},
916     {5, 16, "C"/*ertify*/},
917     {6, 16, "S"/*ign*/},
918     {7, 16, "E"/*ncrypt*/},
919     {8, 16, "A"/*uth*/},
920     {0, 0, 0}
921     };
922     listview_ctrl_t lv;
923     char buf[256], tmp[128];
924     const char *t;
925     int nkeys = 0, rc = 0, i, bits;
926    
927     if( get_pubkey( k->keyid, &key ) ) {
928     msg_box( dlg, _("Could not find key."), _("Key Edit"), MB_ERR );
929     return NULL;
930     }
931     nkeys = count_subkeys (key);
932     if( !nkeys ) {
933     msg_box( dlg, _("No subkey(s) found."), _("Key Edit"), MB_ERR );
934     return NULL;
935     }
936    
937     rc = listview_new( &lv );
938     if( rc )
939     BUG( dlg );
940    
941     lv->ctrl = GetDlgItem( dlg, IDC_KEYEDIT_KEYLIST );
942     for( i = 0; cols[i].fieldname != NULL; i++ )
943     listview_add_column( lv, &cols[i] );
944    
945     for( i = 0; i < nkeys; i++ ) {
946     listview_add_item( lv, "" );
947     listview_add_sub_item( lv, 0, 1, "" );
948     memset( &lvi, 0, sizeof lvi );
949     lvi.mask = LVIF_PARAM;
950     lvi.lParam = (LPARAM )key;
951     if( ListView_SetItem( lv->ctrl, &lvi ) == FALSE )
952     return NULL;
953     }
954    
955     listview_set_ext_style( lv );
956     for( i = 0, sub = key->subkeys; i < nkeys; i++, sub = sub->next ) {
957     memset( buf, 0, sizeof buf );
958    
959     bits = sub->length;
960     _snprintf( tmp, sizeof tmp-1, "%d-bit ", bits );
961     strcat( buf, tmp );
962    
963     _snprintf( tmp, sizeof tmp-1, "%s", get_key_pubalgo (sub->pubkey_algo));
964     strcat( buf, tmp );
965    
966     listview_add_sub_item( lv, i, 0, buf );
967     t = sub->keyid;
968     if( !t )
969     t = "DEADBEEFDEADBEEF";
970     _snprintf( tmp, sizeof tmp-1, "0x%s", t+8 );
971     listview_add_sub_item( lv, i, 1, tmp );
972    
973     t = get_key_created (sub->timestamp);
974     if( !t )
975     t = "????-??-??";
976     listview_add_sub_item( lv, i, 2, t );
977    
978     if( sub->expires ) {
979     t = get_key_created (sub->expires);
980     listview_add_sub_item( lv, i, 3, t );
981     }
982     else
983     listview_add_sub_item( lv, i, 3, _("Never") );
984    
985     if( sub->expired )
986     t = _("Expired");
987     else if( sub->revoked )
988     t = _("Revoked");
989     else
990     t = _("OK");
991     listview_add_sub_item( lv, i, 4, t );
992    
993     if (sub->can_certify) t = "*"; else t = "";
994     listview_add_sub_item (lv, i, 5, t);
995     if (sub->can_sign) t = "*"; else t = "";
996     listview_add_sub_item( lv, i, 6, t );
997     if (sub->can_encrypt) t = "*"; else t = "";
998     listview_add_sub_item( lv, i, 7, t );
999     if (sub->can_authenticate) t = "*"; else t = "";
1000     listview_add_sub_item (lv, i, 8, t);
1001     }
1002     return lv;
1003     } /* subkey_list_init */
1004    
1005    
1006     static listview_ctrl_t
1007     userid_list_init (HWND dlg, winpt_key_t k)
1008     {
1009     listview_ctrl_t lv = NULL;
1010     gpgme_key_t key;
1011     gpgme_key_sig_t ks;
1012     gpgme_user_id_t u;
1013     int nuids = 0, rc, j, u_attr;
1014     struct listview_column_s cols[] = {
1015     {0, 72, (char *)_("Validity")},
1016     {1, 150, (char *)_("Name")},
1017     {2, 110, (char *)_("Email")},
1018     {3, 76, (char *)_("Creation")},
1019     {0, 0, 0}
1020     };
1021     const char *attr;
1022    
1023     if (get_pubkey( k->keyid, &key)) {
1024     msg_box( dlg, _("Could not find key."), _("Key Edit"), MB_ERR );
1025     return NULL;
1026     }
1027    
1028     nuids = count_userids (key);
1029     if (!nuids) {
1030     msg_box (dlg, _("No user ID(s) found."), _("Key Edit"), MB_ERR);
1031     return NULL;
1032     }
1033    
1034     rc = listview_new (&lv);
1035     if( rc )
1036     BUG( dlg );
1037     lv->ctrl = GetDlgItem( dlg, IDC_KEYEDIT_UIDLIST );
1038     for( j = 0; cols[j].fieldname != NULL; j++ )
1039     listview_add_column( lv, &cols[j] );
1040    
1041     for( j = 0; j < nuids; j++ ) {
1042     listview_add_item( lv, " " );
1043     listview_add_sub_item( lv, 0, 1, " " );
1044     }
1045    
1046     listview_set_ext_style (lv);
1047     for (j = 0, u=key->uids; j < nuids; u=u->next, j++) {
1048     if (u->revoked)
1049     attr = _("Revoked");
1050     else {
1051     u_attr = (int)u->validity;
1052     attr = get_key_trust2 (NULL, u_attr, 0, 0);
1053     }
1054     listview_add_sub_item( lv, j, 0, (char *)attr );
1055    
1056     /* XXX: add comment if available */
1057     attr = u->name;
1058     if (attr) {
1059     char * uid = utf8_to_wincp (attr, strlen (attr));
1060     if (uid) {
1061     listview_add_sub_item( lv, j, 1, uid );
1062     free( uid );
1063     }
1064     }
1065     else
1066     listview_add_sub_item( lv, j, 1, _("Invalid user ID") );
1067     attr = u->email;
1068     if (attr)
1069     listview_add_sub_item (lv, j, 2, attr);
1070    
1071     ks = get_selfsig (u, k->keyid+2, 1);
1072     if (ks)
1073     listview_add_sub_item (lv, j, 3, get_key_created (ks->timestamp));
1074     }
1075     if( !k->key_pair ) {
1076     CheckDlgButton( dlg, IDC_KEYUID_ADD, BST_INDETERMINATE );
1077     CheckDlgButton( dlg, IDC_KEYUID_REVOKE, BST_INDETERMINATE );
1078     }
1079     return lv;
1080     } /* userid_list_init */
1081    
1082    
1083     static void
1084     do_init_cmdlist( HWND dlg )
1085     {
1086     const char *cmdlist[] = {
1087     "ADDKEY",
1088     "ADDUID",
1089     "ADDPHOTO",
1090     "ADDREVOKER",
1091     /*"FPR",*/
1092     "DELUID",
1093     "DELKEY",
1094     "DELPHOTO",
1095     /*"DELSIG",*/
1096     "EXPIRE",
1097     /*"PREF",*/
1098     "SHOWPREF",
1099     /*"SETPREF",*/
1100     "PASSWD",
1101     "PRIMARY",
1102     "TRUST",
1103     /*"REVSIG",*/
1104     "REVUID",
1105     "REVKEY",
1106     "DISABLE",
1107     "ENABLE",
1108     "SHOWPHOTO",
1109     NULL
1110     };
1111     const char * s;
1112     int i = 0;
1113    
1114     for( i = 0; (s=cmdlist[i]); i++ ) {
1115     SendDlgItemMessage( dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,
1116     (LPARAM)(char *)s );
1117     }
1118     SendDlgItemMessage( dlg, IDC_KEYEDIT_CMD, CB_SETCURSEL, 0, 0 );
1119     } /* do_init_cmdlist */
1120    
1121    
1122     static int
1123     is_cmd_openpgp( int cmdid )
1124     {
1125     switch( cmdid ) {
1126     case CMD_ADDKEY:
1127     case CMD_ADDPHOTO:
1128     case CMD_ADDREVOKER:
1129     case CMD_DELPHOTO:
1130     /*case CMD_SHOWPHOTO:*/
1131     /*case CMD_SETPREF:*/
1132     return 1;
1133     }
1134     return 0;
1135     } /* is_cmd_openpgp */
1136    
1137    
1138     static void
1139     do_show_help( HWND dlg )
1140     {
1141     char helptext[2048];
1142    
1143     _snprintf( helptext, sizeof helptext-1,
1144     _(/*"FPR \t\tshow fingerprint\r\n"*/
1145     "ADDUID \t\tadd a user ID\r\n"
1146     "ADDPHOTO \t\tadd a photo ID\r\n"
1147     "DELUID \t\tdelete a user ID\r\n"
1148     "ADDKEY \t\tadd a secondard key\r\n"
1149     "DELKEY \t\tdelete a secondary key\r\n"
1150     "ADDREVOKER\t\tadd a revocation key\r\n"
1151     /*"DELSIG \t\tdelete signatures\r\n"*/
1152     "EXPIRE \t\tchange the expire date\r\n"
1153     /*"PREF \t\tlist preferences (expert)\r\n"
1154     "SHOWPREF \t\tlist preferences (verbose)\r\n"
1155     "SETPREF \t\tset preference list\r\n"*/
1156     "UPDPREF \t\tupdated preferences\r\n"
1157     "PASSWD \t\tchange the passphrase\r\n"
1158     "PRIMARY \t\tflag user ID as primary\r\n"
1159     "TRUST \t\tchange the ownertrust\r\n"
1160     /*"REVSIG \t\trevoke signatures\r\n"*/
1161     "REVUID \t\trevoke a user ID\r\n"
1162     "REVKEY \t\trevoke a secondary key\r\n"
1163     "DISABLE \t\tdisable a key\r\n"
1164     "ENABLE \t\tenable a key\r\n"
1165     /*"SHOWPHOTO \t\tshow photo ID\r\n"*/) );
1166     msg_box( dlg, helptext, _("Key Edit Help"), MB_OK );
1167     } /* do_show_help */
1168    
1169    
1170     static int
1171     do_editkey_delkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1172     {
1173     gpgme_error_t err;
1174     GpgKeyEdit *ke;
1175     int j, id;
1176     char tmp[64];
1177    
1178     if (!k->key_pair)
1179     return FALSE; /* XXX: shall we allow to modify non-secret keys?? */
1180    
1181     if( listview_count_items( lv, 0 ) == 1 ) {
1182     msg_box( dlg, _("Primary key can not be deleted!"), _("Key Edit"), MB_ERR);
1183     return FALSE;
1184     }
1185     if( (j = listview_get_curr_pos( lv )) == -1 ) {
1186     msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
1187     return FALSE;
1188     }
1189     if( j == 0 ) {
1190     msg_box( dlg, _("Primary subkey can not be deleted!"), _("Key Edit"), MB_ERR );
1191     return FALSE;
1192     }
1193    
1194     listview_get_item_text( lv, j, 0, tmp, sizeof tmp -1 );
1195     id = log_box( _("Key Edit"), MB_YESNO|MB_ICONWARNING,
1196     _("\"Subkey %s.\"\n\n"
1197     "Anything encrypted to the selected subkey will no longer\n"
1198     "be able to be decrypted.\n\n"
1199     "Do you really want to delete this subkey?"), tmp );
1200     if( id == IDNO )
1201     return FALSE;
1202    
1203     ke = new GpgKeyEdit (k->keyid);
1204     if (!ke)
1205     BUG (NULL);
1206     err = ke->delKey (j);
1207     if (err)
1208     msg_box (dlg, gpgme_strerror (err), _("Delete Subkey"), MB_ERR);
1209     else {
1210     listview_del_item (lv, j);
1211     k->update = 1;
1212     status_box (dlg, _("Subkey successfully deleted."), _("GnuPG status"));
1213     }
1214     delete ke;
1215     return err? FALSE : TRUE;
1216     } /* do_editkey_delkey */
1217    
1218    
1219     /* Set the expiration date for the selected key in list view @lv.
1220     Return value: TRUE on success. */
1221     static int
1222     do_editkey_expire (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1223     {
1224     gpgme_error_t err;
1225     GpgKeyEdit *ke;
1226     date_s udd = {0};
1227     char buf[256], * pass = NULL;
1228     int j, cancel = 0;
1229    
1230     if (!k->key_pair) {
1231 twoaday 41 msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
1232 werner 36 return FALSE;
1233     }
1234 twoaday 41 if ((j = listview_get_curr_pos (lv)) == -1) {
1235 werner 36 msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
1236     return FALSE;
1237     }
1238 twoaday 41
1239     /* If a key already expired, it is possible the user wants to
1240     set a new expiration date.. */
1241     listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, sizeof buf -1);
1242     if (!strcmp (buf, _("Expired"))) {
1243     cancel = msg_box (dlg, _("Key already expired.\n\n"
1244     "Do you want to change the expiration date?"),
1245     _("Key Edit"), MB_QUEST_ASK);
1246     if (cancel == IDNO)
1247     return FALSE;
1248     cancel = 0;
1249 werner 36 }
1250 twoaday 41
1251 werner 36 memset (&udd, 0, sizeof udd);
1252     udd.text = _("Key Expiration Date");
1253     dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_DATE, dlg,
1254     date_dlg_proc, (LPARAM)&udd,
1255     _("Key Expiration Date"), IDS_WINPT_DATE);
1256     if (udd.cancel == 1)
1257     return FALSE;
1258     if (!keygen_check_date (&udd.st)) {
1259     msg_box (dlg, _("The date you have chosen lies in the past."),
1260     _("Key Edit"), MB_ERR);
1261     return FALSE;
1262     }
1263     if( k->is_protected ) {
1264 twoaday 41 pass = request_passphrase (_("Key Edit"), 1, &cancel);
1265     if (cancel)
1266 werner 36 return FALSE;
1267     }
1268    
1269     ke = new GpgKeyEdit (k->keyid);
1270     if (!ke)
1271     BUG (NULL);
1272     if (k->is_protected)
1273     ke->setPassphrase (pass);
1274     err = ke->setKeyExpireDate (j, diff_time (NULL, &udd.st), true);
1275     if (err)
1276     msg_box (dlg, gpgme_strerror (err), _("Expire Subkey"), MB_ERR);
1277     else {
1278     _snprintf (buf, sizeof buf - 1, "%04d-%02d-%02d",
1279     udd.st.wYear, udd.st.wMonth, udd.st.wDay);
1280     listview_add_sub_item (lv, j, SUBK_COL_EXPIRES, buf);
1281     k->update = 1;
1282     msg_box (dlg, _("Subkey expire date successfully set."),
1283     _("GnuPG status"), MB_OK);
1284     }
1285     sfree_if_alloc (pass);
1286     delete ke;
1287     return TRUE;
1288     }
1289    
1290    
1291     /* Revoke the selected key in the list view @lv. @k contains
1292     control information about the global key.
1293     Return value: TRUE on success. */
1294     static int
1295     do_editkey_revoke (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1296     {
1297     gpgme_error_t err;
1298     GpgKeyEdit *ke;
1299     char buf[256];
1300     char *pass = NULL;
1301     int j, cancel = 0;
1302    
1303     if (!k->key_pair) {
1304     msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
1305     return FALSE;
1306     }
1307    
1308     if ((j = listview_get_curr_pos (lv)) == -1) {
1309     msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
1310     return FALSE;
1311     }
1312     else if (listview_count_items (lv, 0) == 1) {
1313     msg_box( dlg, _("No subkeys were found, if you want to revoke the\n"
1314     "whole key, please use the Key Manager command directly.\n\n"
1315     "This command is only available to revoke single subkeys"),
1316     _("Key Edit"), MB_INFO );
1317     return FALSE;
1318     }
1319    
1320     listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, sizeof (buf)-1);
1321     if (!strcmp (buf, _("Revoked"))) {
1322     msg_box (dlg, _("Key already revoked."), _("Key Edit"), MB_ERR);
1323     return FALSE;
1324     }
1325    
1326     if (k->is_protected) {
1327     pass = request_passphrase (_("Key Edit"), 1, &cancel);
1328     if (cancel)
1329     return FALSE;
1330     }
1331    
1332     ke = new GpgKeyEdit (k->keyid);
1333     if (!ke)
1334     BUG (NULL);
1335     if (k->is_protected)
1336     ke->setPassphrase (pass);
1337     err = ke->revokeSubkey (j, 0, NULL);
1338     if (err)
1339     msg_box( dlg, gpgme_strerror (err), _("Revoke Subkey"), MB_ERR);
1340     else {
1341     listview_add_sub_item (lv, j, SUBK_COL_STATUS, _("Revoked"));
1342     k->update = 1;
1343     msg_box( dlg, _("Subkey successfully revoked."), _("GnuPG Status"), MB_OK );
1344     }
1345     sfree_if_alloc (pass);
1346     delete ke;
1347     return TRUE;
1348     }
1349    
1350    
1351     /* Revoked the selected userid in list view @lv.
1352     Return value: TRUE on success. */
1353     int
1354     do_editkey_revuid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1355     {
1356     gpgme_error_t err;
1357     GpgKeyEdit *ke;
1358     char buf[256], t[512], * pass;
1359     int cancel = 0, id = 0, j;
1360    
1361     if (!k->key_pair) {
1362     msg_box( dlg, _("There is no secret key available!"), _("Revoke user ID"), MB_ERR );
1363     return FALSE;
1364     }
1365    
1366     if( listview_count_items( lv, 0 ) == 1 ) {
1367     msg_box( dlg, _("Key has only one user ID."), _("Key Edit"), MB_ERR );
1368     return FALSE;
1369     }
1370    
1371     if( (j = listview_get_curr_pos( lv )) == -1 ) {
1372     msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1373     return FALSE;
1374     }
1375    
1376     listview_get_item_text( lv, j, 0, buf, sizeof buf - 1 );
1377     if( strstr( buf, _("Revoked") ) ) {
1378     msg_box( dlg, _("This user ID has been already revoked."), _("Key Edit"), MB_INFO );
1379     return FALSE;
1380     }
1381    
1382     listview_get_item_text (lv, j, 1, buf, sizeof buf -1);
1383     _snprintf( t, sizeof t -1, _("user ID \"%s\".\n\n"
1384     "Do you really want to revoke this user ID?"), buf );
1385     if( msg_box( dlg, t, _("Key Edit"), MB_WARN_ASK) == IDNO )
1386     return FALSE;
1387     if( k->is_protected ) {
1388     pass = request_passphrase (_("Key Edit"), 1, &cancel);
1389     if( cancel )
1390     return FALSE;
1391     }
1392     listview_get_item_text (lv, j, 2, buf, sizeof (buf)-1);
1393     id = do_find_userid (k->keyid, buf, NULL);
1394     if (id == -1)
1395     BUG (NULL);
1396    
1397     ke = new GpgKeyEdit (k->keyid);
1398     if (!ke)
1399     BUG (NULL);
1400     if (k->is_protected)
1401     ke->setPassphrase (pass);
1402     err = ke->revokeUserid (id);
1403     if (err)
1404     msg_box (dlg, gpgme_strerror (err), _("Revoke Signature"), MB_ERR);
1405     else {
1406     listview_add_sub_item (lv, j, 0, _("Revoked"));
1407     k->update = 1;
1408     status_box (dlg, _("User ID successfully revoked"), _("GnuPG Status"));
1409     }
1410     sfree_if_alloc (pass);
1411     delete ke;
1412     return err? FALSE : TRUE;
1413     }
1414    
1415    
1416     static int
1417     do_editkey_setpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1418     {
1419     gpgme_error_t rc;
1420     GpgKeyEdit *ke;
1421     char buf[256], * pass = NULL, * prefs;
1422     int j, id, cancel=0, flags=0;
1423    
1424     if ((j = listview_get_curr_pos (lv)) == -1) {
1425     msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1426     return FALSE;
1427     }
1428     listview_get_item_text (lv, j, 2, buf, sizeof buf-1);
1429     id = do_find_userid (k->keyid, buf, NULL);
1430     if (id == -1)
1431     BUG (dlg);
1432     if (k->is_protected) {
1433     pass = request_passphrase (_("Key Edit"), 1, &cancel);
1434     if (cancel)
1435     return FALSE;
1436     }
1437    
1438     ke = new GpgKeyEdit (k->keyid);
1439     if (!ke)
1440     BUG (NULL);
1441     if (k->is_protected)
1442     ke->setPassphrase (pass);
1443    
1444     get_userid_preflist (&prefs, &flags);
1445    
1446     rc = ke->setUseridPreferences (id, prefs);
1447     /* XXX */
1448    
1449     sfree_if_alloc (pass);
1450     free_if_alloc (prefs);
1451     delete ke;
1452     return 0;
1453     }
1454    
1455    
1456     static int
1457     do_editkey_primary (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1458     {
1459     gpgme_error_t err;
1460     GpgKeyEdit *ke;
1461     int j, id, cancel=0;
1462     char buf[256], * pass = NULL;
1463    
1464     if (listview_count_items (lv, 0) == 1)
1465     return TRUE;
1466     if ((j = listview_get_curr_pos (lv)) == -1) {
1467     msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1468     return FALSE;
1469     }
1470     listview_get_item_text (lv, j, 2, buf, sizeof buf-1);
1471     id = do_find_userid (k->keyid, buf, NULL);
1472     if (id == -1)
1473     BUG (dlg);
1474     if (k->is_protected) {
1475     pass = request_passphrase (_("Key Edit"), 1, &cancel);
1476     if( cancel )
1477     return FALSE;
1478     }
1479    
1480     ke = new GpgKeyEdit (k->keyid);
1481     if (k->is_protected)
1482     ke->setPassphrase (pass);
1483     err = ke->setPrimaryUserid (id);
1484     if (err)
1485     msg_box (dlg, gpgme_strerror (err), _("Primary"), MB_ERR);
1486     else {
1487     k->update = 1;
1488     status_box (dlg, _("User ID successfully flagged"), _("GnuPG Status"));
1489     }
1490    
1491     sfree_if_alloc (pass);
1492     delete ke;
1493     return err? FALSE : TRUE;
1494     }
1495    
1496    
1497     static int
1498     parse_preflist (HWND dlg, const char *list)
1499     {
1500     char *p, buf[128] = {0}, *pbuf = buf;
1501     const char *ciphers[11] = {0, "IDEA", "3DES", "CAST5", "BLOWFISH", 0, 0, "AES", "AES192", "AES256", "TWOFISH"};
1502     const char *hash[11] = {0, "MD5", "SHA1", "RMD160", 0, 0, 0, 0, "SHA256", "SHA384", "SHA512"};
1503     const char *compress[4] = {0, "ZIP", "ZLIB", "BZIP2"};
1504     int n=0;
1505    
1506     strncpy (buf, list, 127);
1507     p = strtok (pbuf, " ");
1508     while (p != NULL) {
1509     int algid = atol (p+1);
1510     n++;
1511     switch (*p) {
1512     case 'S':
1513     SendDlgItemMessage (dlg, IDC_SHOWPREF_CIPHERS, LB_ADDSTRING, 0, (LPARAM)(const char*)ciphers[algid % 11]);
1514     break;
1515    
1516     case 'H':
1517     SendDlgItemMessage (dlg, IDC_SHOWPREF_HASH, LB_ADDSTRING, 0, (LPARAM)(const char*)hash[algid % 10]);
1518     break;
1519    
1520     case 'Z':
1521     SendDlgItemMessage (dlg, IDC_SHOWPREF_ZIP, LB_ADDSTRING, 0, (LPARAM)(const char*)compress[algid % 4]);
1522     break;
1523    
1524     default:
1525     n--;
1526     }
1527     p = strtok (NULL, " ");
1528     }
1529     return n;
1530     }
1531    
1532    
1533     /* Dialog box procedure to show the key preferences. */
1534     BOOL CALLBACK
1535     showpref_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1536     {
1537     static keyedit_callback_s *cb = NULL;
1538     gpg_uid_info_t inf=NULL;
1539     char buf[128];
1540     int pos;
1541    
1542     switch (msg) {
1543     case WM_INITDIALOG:
1544     cb = (keyedit_callback_s *)lparam;
1545     if (cb == NULL)
1546     BUG (dlg);
1547     listview_get_item_text (cb->lv, listview_get_curr_pos (cb->lv), 2, buf, DIM (buf)-1);
1548     SetDlgItemText (dlg, IDC_SHOWPREF_INFO, buf);
1549     pos = do_find_userid (((winpt_key_t)cb->opaque)->keyid, buf, &inf);
1550     if (inf) {
1551     const char *prefs = inf->prefs;
1552     if (prefs && *prefs) {
1553     if (parse_preflist (dlg, prefs) <= 0)
1554     pos = -1;
1555     }
1556     else
1557     pos = -1;
1558     gpg_uid_info_release (inf);
1559     if (pos == -1) {
1560     msg_box (dlg, _("No preferences available."), _("Key Edit"), MB_ERR);
1561     EndDialog (dlg, TRUE);
1562     }
1563     if (inf->flags.mdc)
1564     CheckDlgButton (dlg, IDC_SHOWPREF_MDC, BST_CHECKED);
1565     }
1566     SetWindowText (dlg, _("Key Preferences"));
1567     SetForegroundWindow (dlg);
1568     break;
1569    
1570     case WM_COMMAND:
1571     switch (LOWORD (wparam)) {
1572     case IDOK:
1573     EndDialog (dlg, TRUE);
1574     break;
1575     }
1576     break;
1577     }
1578     return FALSE;
1579     }
1580    
1581    
1582     static int
1583     do_editkey_showpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1584     {
1585     struct keyedit_callback_s cb;
1586    
1587     if (k->is_v3)
1588     return TRUE;
1589    
1590     if (listview_get_curr_pos (lv) == -1) {
1591     msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1592     return FALSE;
1593     }
1594    
1595     memset (&cb, 0, sizeof (cb));
1596     cb.lv = lv;
1597     cb.opaque = k;
1598     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_SHOWPREF, dlg,
1599     showpref_dlg_proc, (LPARAM)&cb);
1600     return TRUE;
1601     }
1602    
1603    
1604     static int
1605     do_editkey_deluid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1606     {
1607     gpgme_error_t err;
1608     GpgKeyEdit *ke;
1609     char buf[256], t[512];
1610     int j, id = 0;
1611    
1612     if (!k->key_pair)
1613     return FALSE; /* XXX: see do_editkey_delsubkey */
1614    
1615     if( listview_count_items( lv, 0 ) == 1 ) {
1616     msg_box( dlg, _("Primary user ID can not be deleted!"), _("Key Edit"), MB_ERR );
1617     return FALSE;
1618     }
1619     if( (j = listview_get_curr_pos( lv )) == -1 ) {
1620     msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1621     return FALSE;
1622     }
1623    
1624     /* XXX: add a hint that also all signatures will be deleted? */
1625     listview_get_item_text( lv, j, 1, buf, DIM(buf) -1 );
1626     _snprintf( t, DIM (t)-1, _("user ID \"%s\".\n\n"
1627     "Do you really want to delete this user ID?"),
1628     buf);
1629     if( msg_box( dlg, t, _("Key Edit"), MB_YESNO|MB_ICONWARNING ) == IDNO )
1630     return FALSE;
1631    
1632     listview_get_item_text (lv, j, 2, buf, DIM (buf)-1);
1633     id = do_find_userid (k->keyid, buf, NULL);
1634     if (id == -1)
1635     BUG (dlg);
1636    
1637     ke = new GpgKeyEdit (k->keyid);
1638     if (!ke)
1639     BUG (NULL);
1640    
1641     err = ke->delUserid (id);
1642     if( err )
1643     msg_box( dlg, gpgme_strerror (err), _("Delete user ID"), MB_ERR );
1644     else {
1645     listview_del_item( lv, j );
1646     k->update = 1;
1647     status_box( dlg, _("User ID successfully deleted"), _("GnuPG Status") );
1648     }
1649     delete ke;
1650     return err? FALSE : TRUE;
1651     } /* do_editkey_deluid */
1652    
1653    
1654    
1655     static BOOL CALLBACK
1656     subkey_subclass_proc( HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam )
1657     {
1658     switch( msg ) {
1659     case WM_KEYUP:
1660     int virt_key = (int)wparam;
1661     switch( virt_key ) {
1662     case VK_DELETE:
1663     SendDlgItemMessage( keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
1664     CB_SETCURSEL, CMD_DELKEY, 0 );
1665     send_cmd_id( keyedit_subkey_proc.dlg, IDOK );
1666     break;
1667    
1668     case VK_INSERT:
1669     SendDlgItemMessage( keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
1670     CB_SETCURSEL, CMD_ADDKEY, 0 );
1671     send_cmd_id( keyedit_subkey_proc.dlg, IDOK );
1672     break;
1673     }
1674     }
1675     return CallWindowProc( keyedit_subkey_proc.old, dlg, msg, wparam, lparam );
1676     } /* subkey_subclass_proc */
1677    
1678    
1679     static BOOL CALLBACK
1680     uid_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1681     {
1682     switch( msg ) {
1683     case WM_KEYUP:
1684     int virt_key = (int)wparam;
1685     switch (virt_key) {
1686     case VK_DELETE:
1687     SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
1688     CB_SETCURSEL, CMD_DELUID, 0);
1689     send_cmd_id (keyedit_uid_proc.dlg, IDOK);
1690     break;
1691    
1692     case VK_INSERT:
1693     SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
1694     CB_SETCURSEL, CMD_ADDUID, 0);
1695     send_cmd_id (keyedit_uid_proc.dlg, IDOK);
1696     break;
1697     }
1698     }
1699     return CallWindowProc( keyedit_uid_proc.old, dlg, msg, wparam, lparam );
1700     } /* uid_subclass_proc */
1701    
1702    
1703     BOOL CALLBACK
1704     keyedit_main_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1705     {
1706     static winpt_key_t k;
1707     static listview_ctrl_t lvsub = NULL, lvuid = NULL;
1708     int cmd, idxsub = 0;
1709     HWND item;
1710    
1711     switch( msg ) {
1712     case WM_INITDIALOG:
1713     k = (winpt_key_t)lparam;
1714     if (!k)
1715     BUG (NULL);
1716     do_init_cmdlist (dlg);
1717     lvsub = subkey_list_init (dlg, k);
1718     if( !lvsub )
1719     BUG( NULL );
1720     lvuid = userid_list_init (dlg, k);
1721     if( !lvuid )
1722     BUG( NULL );
1723     item = GetDlgItem( dlg, IDC_KEYEDIT_KEYLIST );
1724     keyedit_subkey_proc.dlg = dlg;
1725     keyedit_subkey_proc.current = (WNDPROC)subkey_subclass_proc;
1726     keyedit_subkey_proc.old = (WNDPROC)GetWindowLong( item, GWL_WNDPROC );
1727     if( keyedit_subkey_proc.old ) {
1728     if( !SetWindowLong( item, GWL_WNDPROC, (LONG)keyedit_subkey_proc.current ) ) {
1729     msg_box( dlg, _("Could not set subkey window procedure."), _("Key Edit"), MB_ERR );
1730     BUG( NULL );
1731     }
1732     }
1733     item = GetDlgItem( dlg, IDC_KEYEDIT_UIDLIST );
1734     keyedit_uid_proc.dlg = dlg;
1735     keyedit_uid_proc.current = (WNDPROC)uid_subclass_proc;
1736     keyedit_uid_proc.old = (WNDPROC)GetWindowLong( item, GWL_WNDPROC );
1737     if( keyedit_uid_proc.old ) {
1738     if( !SetWindowLong( item, GWL_WNDPROC, (LONG)keyedit_uid_proc.current ) ) {
1739     msg_box( dlg, _("Could not set user ID window procedure."), _("Key Edit"), MB_ERR );
1740     BUG( NULL );
1741     }
1742     }
1743     if (!k->key_pair) {
1744     EnableWindow (GetDlgItem (dlg, IDC_KEYEDIT_CMD), FALSE);
1745     EnableWindow (GetDlgItem (dlg, IDOK), FALSE);
1746     }
1747     SetDlgItemText (dlg, IDC_KEYEDIT_CMDINF, _("Command>"));
1748     SetForegroundWindow( dlg );
1749     center_window( dlg, NULL );
1750     return TRUE;
1751    
1752     case WM_DESTROY:
1753     if( lvsub ) {
1754     listview_release( lvsub );
1755     lvsub = NULL;
1756     }
1757     if( lvuid ) {
1758     listview_release( lvuid );
1759     lvuid = NULL;
1760     }
1761     break;
1762    
1763     case WM_NOTIFY:
1764     NMHDR * notify;
1765     notify = (NMHDR *)lparam;
1766     if (notify && notify->code == NM_DBLCLK &&
1767     notify->idFrom == IDC_KEYEDIT_UIDLIST)
1768     do_editkey_showpref (k, dlg, lvuid);
1769     break;
1770    
1771     case WM_COMMAND:
1772     switch( LOWORD( wparam ) ) {
1773     case IDOK:
1774     cmd = SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_GETCURSEL, 0, 0);
1775     if (cmd == LB_ERR) {
1776     msg_box( dlg, _("Please select a command."), _("Key Edit"), MB_INFO );
1777     return FALSE;
1778     }
1779     idxsub = listview_get_curr_pos (lvsub);
1780     if (k->is_v3 && is_cmd_openpgp (cmd)) {
1781     msg_box (dlg, _("This command cannot be used with PGP 2 (v3) keys.\n"),
1782     _("Key Edit"), MB_ERR);
1783     return FALSE;
1784     }
1785     switch (cmd) {
1786     case CMD_SHOWPREF: do_editkey_showpref (k, dlg, lvuid); break;
1787     case CMD_DELKEY: do_editkey_delkey (k, dlg, lvsub); break;
1788     case CMD_ADDKEY: keyedit_add_subkey (k, dlg, lvsub); break;
1789     case CMD_EXPIRE: do_editkey_expire (k, dlg, lvsub); break;
1790     case CMD_REVKEY: do_editkey_revoke (k, dlg, lvsub); break;
1791     /*case CMD_SETPREF:do_editkey_setpref( k, dlg, lvuid ); break;*/
1792     case CMD_ADDUID: keyedit_add_userid( k, dlg, lvuid ); break;
1793     case CMD_ADDREVOKER: keyedit_add_revoker( k, dlg ); break;
1794     case CMD_ADDPHOTO: keyedit_add_photo( k, dlg ); break;
1795     case CMD_REVUID: do_editkey_revuid( k, dlg, lvuid ); break;
1796     case CMD_DELUID: do_editkey_deluid( k, dlg, lvuid ); break;
1797     case CMD_PASSWD: keyedit_change_passwd( k, dlg ); break;
1798     case CMD_PRIMARY: do_editkey_primary( k, dlg, lvuid ); break;
1799     case CMD_ENABLE: km_enable_disable_key( lvsub, dlg, idxsub, 1 ); break;
1800     case CMD_DISABLE: km_enable_disable_key( lvsub, dlg, idxsub, 0 ); break;
1801     }
1802     break;
1803    
1804     case IDCANCEL:
1805     EndDialog (dlg, FALSE);
1806     break;
1807    
1808     case IDC_KEYEDIT_HELP:
1809     do_show_help (dlg);
1810     break;
1811     }
1812     break;
1813     }
1814     return FALSE;
1815 twoaday 41 } /* keyedit_main_dlg_proc */

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26