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

Annotation of /trunk/Src/wptKeyEditDlgs.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide annotations)
Fri Oct 28 08:25:30 2005 UTC (19 years, 4 months ago) by werner
File size: 49440 byte(s)
Readded lost changes from revision 40

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26