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

Annotation of /trunk/Src/wptKeyEditDlgs.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 36 - (hide annotations)
Thu Oct 27 15:25:13 2005 UTC (19 years, 4 months ago) by werner
File size: 49250 byte(s)
First set of changes to use autotools for building.
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     #ifdef HAVE_CONFIG_H
22     #include <config.h>
23     #endif
24    
25     #include <windows.h>
26     #include <windows.h>
27     #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     msg_box( dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR );
1237     return FALSE;
1238     }
1239     if ( (j = listview_get_curr_pos( lv )) == -1 ) {
1240     msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
1241     return FALSE;
1242     }
1243    
1244     listview_get_item_text( lv, j, SUBK_COL_STATUS, buf, sizeof buf -1 );
1245     if( !strcmp( buf, _("Expired") ) ) {
1246     msg_box( dlg, _("Key already expired!"), _("Key Edit"), MB_ERR );
1247     return FALSE;
1248     }
1249     memset (&udd, 0, sizeof udd);
1250     udd.text = _("Key Expiration Date");
1251     dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_DATE, dlg,
1252     date_dlg_proc, (LPARAM)&udd,
1253     _("Key Expiration Date"), IDS_WINPT_DATE);
1254     if (udd.cancel == 1)
1255     return FALSE;
1256     if (!keygen_check_date (&udd.st)) {
1257     msg_box (dlg, _("The date you have chosen lies in the past."),
1258     _("Key Edit"), MB_ERR);
1259     return FALSE;
1260     }
1261     if( k->is_protected ) {
1262     pass = request_passphrase (_("Key Edit"), 1, &cancel );
1263     if( cancel )
1264     return FALSE;
1265     }
1266    
1267     ke = new GpgKeyEdit (k->keyid);
1268     if (!ke)
1269     BUG (NULL);
1270     if (k->is_protected)
1271     ke->setPassphrase (pass);
1272     err = ke->setKeyExpireDate (j, diff_time (NULL, &udd.st), true);
1273     if (err)
1274     msg_box (dlg, gpgme_strerror (err), _("Expire Subkey"), MB_ERR);
1275     else {
1276     _snprintf (buf, sizeof buf - 1, "%04d-%02d-%02d",
1277     udd.st.wYear, udd.st.wMonth, udd.st.wDay);
1278     listview_add_sub_item (lv, j, SUBK_COL_EXPIRES, buf);
1279     k->update = 1;
1280     msg_box (dlg, _("Subkey expire date successfully set."),
1281     _("GnuPG status"), MB_OK);
1282     }
1283     sfree_if_alloc (pass);
1284     delete ke;
1285     return TRUE;
1286     }
1287    
1288    
1289     /* Revoke the selected key in the list view @lv. @k contains
1290     control information about the global key.
1291     Return value: TRUE on success. */
1292     static int
1293     do_editkey_revoke (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1294     {
1295     gpgme_error_t err;
1296     GpgKeyEdit *ke;
1297     char buf[256];
1298     char *pass = NULL;
1299     int j, cancel = 0;
1300    
1301     if (!k->key_pair) {
1302     msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
1303     return FALSE;
1304     }
1305    
1306     if ((j = listview_get_curr_pos (lv)) == -1) {
1307     msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
1308     return FALSE;
1309     }
1310     else if (listview_count_items (lv, 0) == 1) {
1311     msg_box( dlg, _("No subkeys were found, if you want to revoke the\n"
1312     "whole key, please use the Key Manager command directly.\n\n"
1313     "This command is only available to revoke single subkeys"),
1314     _("Key Edit"), MB_INFO );
1315     return FALSE;
1316     }
1317    
1318     listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, sizeof (buf)-1);
1319     if (!strcmp (buf, _("Revoked"))) {
1320     msg_box (dlg, _("Key already revoked."), _("Key Edit"), MB_ERR);
1321     return FALSE;
1322     }
1323    
1324     if (k->is_protected) {
1325     pass = request_passphrase (_("Key Edit"), 1, &cancel);
1326     if (cancel)
1327     return FALSE;
1328     }
1329    
1330     ke = new GpgKeyEdit (k->keyid);
1331     if (!ke)
1332     BUG (NULL);
1333     if (k->is_protected)
1334     ke->setPassphrase (pass);
1335     err = ke->revokeSubkey (j, 0, NULL);
1336     if (err)
1337     msg_box( dlg, gpgme_strerror (err), _("Revoke Subkey"), MB_ERR);
1338     else {
1339     listview_add_sub_item (lv, j, SUBK_COL_STATUS, _("Revoked"));
1340     k->update = 1;
1341     msg_box( dlg, _("Subkey successfully revoked."), _("GnuPG Status"), MB_OK );
1342     }
1343     sfree_if_alloc (pass);
1344     delete ke;
1345     return TRUE;
1346     }
1347    
1348    
1349     /* Revoked the selected userid in list view @lv.
1350     Return value: TRUE on success. */
1351     int
1352     do_editkey_revuid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1353     {
1354     gpgme_error_t err;
1355     GpgKeyEdit *ke;
1356     char buf[256], t[512], * pass;
1357     int cancel = 0, id = 0, j;
1358    
1359     if (!k->key_pair) {
1360     msg_box( dlg, _("There is no secret key available!"), _("Revoke user ID"), MB_ERR );
1361     return FALSE;
1362     }
1363    
1364     if( listview_count_items( lv, 0 ) == 1 ) {
1365     msg_box( dlg, _("Key has only one user ID."), _("Key Edit"), MB_ERR );
1366     return FALSE;
1367     }
1368    
1369     if( (j = listview_get_curr_pos( lv )) == -1 ) {
1370     msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1371     return FALSE;
1372     }
1373    
1374     listview_get_item_text( lv, j, 0, buf, sizeof buf - 1 );
1375     if( strstr( buf, _("Revoked") ) ) {
1376     msg_box( dlg, _("This user ID has been already revoked."), _("Key Edit"), MB_INFO );
1377     return FALSE;
1378     }
1379    
1380     listview_get_item_text (lv, j, 1, buf, sizeof buf -1);
1381     _snprintf( t, sizeof t -1, _("user ID \"%s\".\n\n"
1382     "Do you really want to revoke this user ID?"), buf );
1383     if( msg_box( dlg, t, _("Key Edit"), MB_WARN_ASK) == IDNO )
1384     return FALSE;
1385     if( k->is_protected ) {
1386     pass = request_passphrase (_("Key Edit"), 1, &cancel);
1387     if( cancel )
1388     return FALSE;
1389     }
1390     listview_get_item_text (lv, j, 2, buf, sizeof (buf)-1);
1391     id = do_find_userid (k->keyid, buf, NULL);
1392     if (id == -1)
1393     BUG (NULL);
1394    
1395     ke = new GpgKeyEdit (k->keyid);
1396     if (!ke)
1397     BUG (NULL);
1398     if (k->is_protected)
1399     ke->setPassphrase (pass);
1400     err = ke->revokeUserid (id);
1401     if (err)
1402     msg_box (dlg, gpgme_strerror (err), _("Revoke Signature"), MB_ERR);
1403     else {
1404     listview_add_sub_item (lv, j, 0, _("Revoked"));
1405     k->update = 1;
1406     status_box (dlg, _("User ID successfully revoked"), _("GnuPG Status"));
1407     }
1408     sfree_if_alloc (pass);
1409     delete ke;
1410     return err? FALSE : TRUE;
1411     }
1412    
1413    
1414     static int
1415     do_editkey_setpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1416     {
1417     gpgme_error_t rc;
1418     GpgKeyEdit *ke;
1419     char buf[256], * pass = NULL, * prefs;
1420     int j, id, cancel=0, flags=0;
1421    
1422     if ((j = listview_get_curr_pos (lv)) == -1) {
1423     msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1424     return FALSE;
1425     }
1426     listview_get_item_text (lv, j, 2, buf, sizeof buf-1);
1427     id = do_find_userid (k->keyid, buf, NULL);
1428     if (id == -1)
1429     BUG (dlg);
1430     if (k->is_protected) {
1431     pass = request_passphrase (_("Key Edit"), 1, &cancel);
1432     if (cancel)
1433     return FALSE;
1434     }
1435    
1436     ke = new GpgKeyEdit (k->keyid);
1437     if (!ke)
1438     BUG (NULL);
1439     if (k->is_protected)
1440     ke->setPassphrase (pass);
1441    
1442     get_userid_preflist (&prefs, &flags);
1443    
1444     rc = ke->setUseridPreferences (id, prefs);
1445     /* XXX */
1446    
1447     sfree_if_alloc (pass);
1448     free_if_alloc (prefs);
1449     delete ke;
1450     return 0;
1451     }
1452    
1453    
1454     static int
1455     do_editkey_primary (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1456     {
1457     gpgme_error_t err;
1458     GpgKeyEdit *ke;
1459     int j, id, cancel=0;
1460     char buf[256], * pass = NULL;
1461    
1462     if (listview_count_items (lv, 0) == 1)
1463     return TRUE;
1464     if ((j = listview_get_curr_pos (lv)) == -1) {
1465     msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1466     return FALSE;
1467     }
1468     listview_get_item_text (lv, j, 2, buf, sizeof buf-1);
1469     id = do_find_userid (k->keyid, buf, NULL);
1470     if (id == -1)
1471     BUG (dlg);
1472     if (k->is_protected) {
1473     pass = request_passphrase (_("Key Edit"), 1, &cancel);
1474     if( cancel )
1475     return FALSE;
1476     }
1477    
1478     ke = new GpgKeyEdit (k->keyid);
1479     if (k->is_protected)
1480     ke->setPassphrase (pass);
1481     err = ke->setPrimaryUserid (id);
1482     if (err)
1483     msg_box (dlg, gpgme_strerror (err), _("Primary"), MB_ERR);
1484     else {
1485     k->update = 1;
1486     status_box (dlg, _("User ID successfully flagged"), _("GnuPG Status"));
1487     }
1488    
1489     sfree_if_alloc (pass);
1490     delete ke;
1491     return err? FALSE : TRUE;
1492     }
1493    
1494    
1495     static int
1496     parse_preflist (HWND dlg, const char *list)
1497     {
1498     char *p, buf[128] = {0}, *pbuf = buf;
1499     const char *ciphers[11] = {0, "IDEA", "3DES", "CAST5", "BLOWFISH", 0, 0, "AES", "AES192", "AES256", "TWOFISH"};
1500     const char *hash[11] = {0, "MD5", "SHA1", "RMD160", 0, 0, 0, 0, "SHA256", "SHA384", "SHA512"};
1501     const char *compress[4] = {0, "ZIP", "ZLIB", "BZIP2"};
1502     int n=0;
1503    
1504     strncpy (buf, list, 127);
1505     p = strtok (pbuf, " ");
1506     while (p != NULL) {
1507     int algid = atol (p+1);
1508     n++;
1509     switch (*p) {
1510     case 'S':
1511     SendDlgItemMessage (dlg, IDC_SHOWPREF_CIPHERS, LB_ADDSTRING, 0, (LPARAM)(const char*)ciphers[algid % 11]);
1512     break;
1513    
1514     case 'H':
1515     SendDlgItemMessage (dlg, IDC_SHOWPREF_HASH, LB_ADDSTRING, 0, (LPARAM)(const char*)hash[algid % 10]);
1516     break;
1517    
1518     case 'Z':
1519     SendDlgItemMessage (dlg, IDC_SHOWPREF_ZIP, LB_ADDSTRING, 0, (LPARAM)(const char*)compress[algid % 4]);
1520     break;
1521    
1522     default:
1523     n--;
1524     }
1525     p = strtok (NULL, " ");
1526     }
1527     return n;
1528     }
1529    
1530    
1531     /* Dialog box procedure to show the key preferences. */
1532     BOOL CALLBACK
1533     showpref_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1534     {
1535     static keyedit_callback_s *cb = NULL;
1536     gpg_uid_info_t inf=NULL;
1537     char buf[128];
1538     int pos;
1539    
1540     switch (msg) {
1541     case WM_INITDIALOG:
1542     cb = (keyedit_callback_s *)lparam;
1543     if (cb == NULL)
1544     BUG (dlg);
1545     listview_get_item_text (cb->lv, listview_get_curr_pos (cb->lv), 2, buf, DIM (buf)-1);
1546     SetDlgItemText (dlg, IDC_SHOWPREF_INFO, buf);
1547     pos = do_find_userid (((winpt_key_t)cb->opaque)->keyid, buf, &inf);
1548     if (inf) {
1549     const char *prefs = inf->prefs;
1550     if (prefs && *prefs) {
1551     if (parse_preflist (dlg, prefs) <= 0)
1552     pos = -1;
1553     }
1554     else
1555     pos = -1;
1556     gpg_uid_info_release (inf);
1557     if (pos == -1) {
1558     msg_box (dlg, _("No preferences available."), _("Key Edit"), MB_ERR);
1559     EndDialog (dlg, TRUE);
1560     }
1561     if (inf->flags.mdc)
1562     CheckDlgButton (dlg, IDC_SHOWPREF_MDC, BST_CHECKED);
1563     }
1564     SetWindowText (dlg, _("Key Preferences"));
1565     SetForegroundWindow (dlg);
1566     break;
1567    
1568     case WM_COMMAND:
1569     switch (LOWORD (wparam)) {
1570     case IDOK:
1571     EndDialog (dlg, TRUE);
1572     break;
1573     }
1574     break;
1575     }
1576     return FALSE;
1577     }
1578    
1579    
1580     static int
1581     do_editkey_showpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1582     {
1583     struct keyedit_callback_s cb;
1584    
1585     if (k->is_v3)
1586     return TRUE;
1587    
1588     if (listview_get_curr_pos (lv) == -1) {
1589     msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
1590     return FALSE;
1591     }
1592    
1593     memset (&cb, 0, sizeof (cb));
1594     cb.lv = lv;
1595     cb.opaque = k;
1596     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_SHOWPREF, dlg,
1597     showpref_dlg_proc, (LPARAM)&cb);
1598     return TRUE;
1599     }
1600    
1601    
1602     static int
1603     do_editkey_deluid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
1604     {
1605     gpgme_error_t err;
1606     GpgKeyEdit *ke;
1607     char buf[256], t[512];
1608     int j, id = 0;
1609    
1610     if (!k->key_pair)
1611     return FALSE; /* XXX: see do_editkey_delsubkey */
1612    
1613     if( listview_count_items( lv, 0 ) == 1 ) {
1614     msg_box( dlg, _("Primary user ID can not be deleted!"), _("Key Edit"), MB_ERR );
1615     return FALSE;
1616     }
1617     if( (j = listview_get_curr_pos( lv )) == -1 ) {
1618     msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
1619     return FALSE;
1620     }
1621    
1622     /* XXX: add a hint that also all signatures will be deleted? */
1623     listview_get_item_text( lv, j, 1, buf, DIM(buf) -1 );
1624     _snprintf( t, DIM (t)-1, _("user ID \"%s\".\n\n"
1625     "Do you really want to delete this user ID?"),
1626     buf);
1627     if( msg_box( dlg, t, _("Key Edit"), MB_YESNO|MB_ICONWARNING ) == IDNO )
1628     return FALSE;
1629    
1630     listview_get_item_text (lv, j, 2, buf, DIM (buf)-1);
1631     id = do_find_userid (k->keyid, buf, NULL);
1632     if (id == -1)
1633     BUG (dlg);
1634    
1635     ke = new GpgKeyEdit (k->keyid);
1636     if (!ke)
1637     BUG (NULL);
1638    
1639     err = ke->delUserid (id);
1640     if( err )
1641     msg_box( dlg, gpgme_strerror (err), _("Delete user ID"), MB_ERR );
1642     else {
1643     listview_del_item( lv, j );
1644     k->update = 1;
1645     status_box( dlg, _("User ID successfully deleted"), _("GnuPG Status") );
1646     }
1647     delete ke;
1648     return err? FALSE : TRUE;
1649     } /* do_editkey_deluid */
1650    
1651    
1652    
1653     static BOOL CALLBACK
1654     subkey_subclass_proc( HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam )
1655     {
1656     switch( msg ) {
1657     case WM_KEYUP:
1658     int virt_key = (int)wparam;
1659     switch( virt_key ) {
1660     case VK_DELETE:
1661     SendDlgItemMessage( keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
1662     CB_SETCURSEL, CMD_DELKEY, 0 );
1663     send_cmd_id( keyedit_subkey_proc.dlg, IDOK );
1664     break;
1665    
1666     case VK_INSERT:
1667     SendDlgItemMessage( keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
1668     CB_SETCURSEL, CMD_ADDKEY, 0 );
1669     send_cmd_id( keyedit_subkey_proc.dlg, IDOK );
1670     break;
1671     }
1672     }
1673     return CallWindowProc( keyedit_subkey_proc.old, dlg, msg, wparam, lparam );
1674     } /* subkey_subclass_proc */
1675    
1676    
1677     static BOOL CALLBACK
1678     uid_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1679     {
1680     switch( msg ) {
1681     case WM_KEYUP:
1682     int virt_key = (int)wparam;
1683     switch (virt_key) {
1684     case VK_DELETE:
1685     SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
1686     CB_SETCURSEL, CMD_DELUID, 0);
1687     send_cmd_id (keyedit_uid_proc.dlg, IDOK);
1688     break;
1689    
1690     case VK_INSERT:
1691     SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
1692     CB_SETCURSEL, CMD_ADDUID, 0);
1693     send_cmd_id (keyedit_uid_proc.dlg, IDOK);
1694     break;
1695     }
1696     }
1697     return CallWindowProc( keyedit_uid_proc.old, dlg, msg, wparam, lparam );
1698     } /* uid_subclass_proc */
1699    
1700    
1701     BOOL CALLBACK
1702     keyedit_main_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1703     {
1704     static winpt_key_t k;
1705     static listview_ctrl_t lvsub = NULL, lvuid = NULL;
1706     int cmd, idxsub = 0;
1707     HWND item;
1708    
1709     switch( msg ) {
1710     case WM_INITDIALOG:
1711     k = (winpt_key_t)lparam;
1712     if (!k)
1713     BUG (NULL);
1714     do_init_cmdlist (dlg);
1715     lvsub = subkey_list_init (dlg, k);
1716     if( !lvsub )
1717     BUG( NULL );
1718     lvuid = userid_list_init (dlg, k);
1719     if( !lvuid )
1720     BUG( NULL );
1721     item = GetDlgItem( dlg, IDC_KEYEDIT_KEYLIST );
1722     keyedit_subkey_proc.dlg = dlg;
1723     keyedit_subkey_proc.current = (WNDPROC)subkey_subclass_proc;
1724     keyedit_subkey_proc.old = (WNDPROC)GetWindowLong( item, GWL_WNDPROC );
1725     if( keyedit_subkey_proc.old ) {
1726     if( !SetWindowLong( item, GWL_WNDPROC, (LONG)keyedit_subkey_proc.current ) ) {
1727     msg_box( dlg, _("Could not set subkey window procedure."), _("Key Edit"), MB_ERR );
1728     BUG( NULL );
1729     }
1730     }
1731     item = GetDlgItem( dlg, IDC_KEYEDIT_UIDLIST );
1732     keyedit_uid_proc.dlg = dlg;
1733     keyedit_uid_proc.current = (WNDPROC)uid_subclass_proc;
1734     keyedit_uid_proc.old = (WNDPROC)GetWindowLong( item, GWL_WNDPROC );
1735     if( keyedit_uid_proc.old ) {
1736     if( !SetWindowLong( item, GWL_WNDPROC, (LONG)keyedit_uid_proc.current ) ) {
1737     msg_box( dlg, _("Could not set user ID window procedure."), _("Key Edit"), MB_ERR );
1738     BUG( NULL );
1739     }
1740     }
1741     if (!k->key_pair) {
1742     EnableWindow (GetDlgItem (dlg, IDC_KEYEDIT_CMD), FALSE);
1743     EnableWindow (GetDlgItem (dlg, IDOK), FALSE);
1744     }
1745     SetDlgItemText (dlg, IDC_KEYEDIT_CMDINF, _("Command>"));
1746     SetForegroundWindow( dlg );
1747     center_window( dlg, NULL );
1748     return TRUE;
1749    
1750     case WM_DESTROY:
1751     if( lvsub ) {
1752     listview_release( lvsub );
1753     lvsub = NULL;
1754     }
1755     if( lvuid ) {
1756     listview_release( lvuid );
1757     lvuid = NULL;
1758     }
1759     break;
1760    
1761     case WM_NOTIFY:
1762     NMHDR * notify;
1763     notify = (NMHDR *)lparam;
1764     if (notify && notify->code == NM_DBLCLK &&
1765     notify->idFrom == IDC_KEYEDIT_UIDLIST)
1766     do_editkey_showpref (k, dlg, lvuid);
1767     break;
1768    
1769     case WM_COMMAND:
1770     switch( LOWORD( wparam ) ) {
1771     case IDOK:
1772     cmd = SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_GETCURSEL, 0, 0);
1773     if (cmd == LB_ERR) {
1774     msg_box( dlg, _("Please select a command."), _("Key Edit"), MB_INFO );
1775     return FALSE;
1776     }
1777     idxsub = listview_get_curr_pos (lvsub);
1778     if (k->is_v3 && is_cmd_openpgp (cmd)) {
1779     msg_box (dlg, _("This command cannot be used with PGP 2 (v3) keys.\n"),
1780     _("Key Edit"), MB_ERR);
1781     return FALSE;
1782     }
1783     switch (cmd) {
1784     case CMD_SHOWPREF: do_editkey_showpref (k, dlg, lvuid); break;
1785     case CMD_DELKEY: do_editkey_delkey (k, dlg, lvsub); break;
1786     case CMD_ADDKEY: keyedit_add_subkey (k, dlg, lvsub); break;
1787     case CMD_EXPIRE: do_editkey_expire (k, dlg, lvsub); break;
1788     case CMD_REVKEY: do_editkey_revoke (k, dlg, lvsub); break;
1789     /*case CMD_SETPREF:do_editkey_setpref( k, dlg, lvuid ); break;*/
1790     case CMD_ADDUID: keyedit_add_userid( k, dlg, lvuid ); break;
1791     case CMD_ADDREVOKER: keyedit_add_revoker( k, dlg ); break;
1792     case CMD_ADDPHOTO: keyedit_add_photo( k, dlg ); break;
1793     case CMD_REVUID: do_editkey_revuid( k, dlg, lvuid ); break;
1794     case CMD_DELUID: do_editkey_deluid( k, dlg, lvuid ); break;
1795     case CMD_PASSWD: keyedit_change_passwd( k, dlg ); break;
1796     case CMD_PRIMARY: do_editkey_primary( k, dlg, lvuid ); break;
1797     case CMD_ENABLE: km_enable_disable_key( lvsub, dlg, idxsub, 1 ); break;
1798     case CMD_DISABLE: km_enable_disable_key( lvsub, dlg, idxsub, 0 ); break;
1799     }
1800     break;
1801    
1802     case IDCANCEL:
1803     EndDialog (dlg, FALSE);
1804     break;
1805    
1806     case IDC_KEYEDIT_HELP:
1807     do_show_help (dlg);
1808     break;
1809     }
1810     break;
1811     }
1812     return FALSE;
1813     } /* keyedit_main_dlg_proc */

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26