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

Contents of /trunk/Src/wptKeylist.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 450 - (show annotations)
Sat May 5 14:00:34 2012 UTC (12 years, 9 months ago) by twoaday
File size: 30390 byte(s)
2012-05-05  Timo Schulz  <twoaday@gmx.net>

     * wptListview.cpp (keylist_listview_notify): Cleanups.
       

1 /* wptKeylist.cpp - Keylist element
2 * Copyright (C) 2001-2006, 2009 Timo Schulz
3 * Copyright (C) 2004 Andreas Jobs
4 *
5 * This file is part of WinPT.
6 *
7 * WinPT is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * WinPT is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 */
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20
21 #include <windows.h>
22 #include <commctrl.h>
23 #include <time.h>
24
25 #include "wptCommonCtl.h"
26 #include "wptTypes.h"
27 #include "wptGPG.h"
28 #include "wptKeylist.h"
29 #include "wptKeyManager.h"
30 #include "wptW32API.h"
31 #include "wptNLS.h"
32 #include "wptErrors.h"
33 #include "wptUTF8.h"
34 #include "wptRegistry.h"
35 #include "wptContext.h"
36 #include "wptVersion.h"
37 #include "resource.h"
38 #include "StringBuffer.h"
39
40
41 struct key_array_s {
42 char keyid[32];
43 int checked;
44 };
45
46
47 static key_array_s*
48 key_array_new (DWORD items)
49 {
50 key_array_s *ka;
51
52 if (items == 0)
53 BUG (NULL);
54 ka = new key_array_s[items + 1];
55 if (!ka)
56 BUG (NULL);
57 for (DWORD i = 0; i < items; i++)
58 ka[i].checked = 0;
59 return ka;
60 }
61
62 static void
63 key_array_release (key_array_s *ka)
64 {
65 free_if_alloc (ka);
66 }
67
68
69 /* Check if the keyid @keyid is in the key array @ka.
70 Return value: 1 if it exists, 0 otherwise. */
71 static int
72 key_array_search (key_array_s *ka, DWORD items, const char *keyid)
73 {
74 for (DWORD i = 0; i < items; i++) {
75 if (!stricmp (keyid, ka[i].keyid))
76 return 1;
77 }
78 return 0;
79 }
80
81
82 /* Return if there is a secret for @key.
83 0 means success. */
84 static int
85 find_secret_key (gpgme_key_t key)
86 {
87 winpt_key_s skey;
88
89 if (!key->subkeys->keyid)
90 return 0;
91 memset (&skey, 0, sizeof (skey));
92 if (winpt_get_seckey (key->subkeys->keyid, &skey))
93 return 0;
94 if (skey.ext && skey.ext->gloflags.divert_to_card)
95 return 2;
96 return skey.ctx? 1 : 0;
97 }
98
99
100 /* Update the gpgme key pointer of a single entry. */
101 static void
102 update_key (keylist_ctrl_t kl, int pos,
103 gpgme_key_t key)
104 {
105 if ((size_t)pos > kl->nkeys)
106 BUG (0);
107 kl->keys[pos] = key;
108 }
109
110
111 /* If @re_sorted == 0, then all keys from the key list control
112 are stored as references in the array.
113 Otherwise we just re-order the references in the array. */
114 static size_t
115 update_keys (keylist_ctrl_t kl, int re_sorted,
116 gpgme_key_t **r_list)
117 {
118 gpgme_key_t *rset;
119 gpgme_key_t key;
120 listview_ctrl_t lv = kl->lv;
121 struct keycache_s *c;
122 size_t k_pos;
123 int nkeys;
124
125 nkeys = listview_count_items (lv, 0);
126 if (!nkeys)
127 BUG (0);
128
129 if (!re_sorted) {
130 rset = (gpgme_key_t*)calloc (nkeys+1, sizeof (gpgme_key_t));
131 *r_list = rset;
132 }
133 else
134 rset = *r_list;
135 k_pos = 0;
136 for (int i = 0; i < nkeys; i++) {
137 key = km_get_key_ptr (kl, i, &c);
138 rset[k_pos++] = key;
139 }
140 return k_pos;
141 }
142
143
144 gpgme_user_id_t
145 get_nth_userid (gpgme_key_t key, int idx)
146 {
147 gpgme_user_id_t t;
148
149 if (!key->uids)
150 return NULL;
151 t = key->uids;
152 while (idx-- && t->next)
153 t = t->next;
154 return t;
155 }
156
157
158 int
159 count_userids (gpgme_key_t key)
160 {
161 gpgme_user_id_t u;
162 int n = 1;
163
164 u = key->uids;
165 if (!u)
166 return 0;
167 while (u->next) {
168 u = u->next;
169 n++;
170 }
171 return n;
172 }
173
174
175 gpgme_subkey_t
176 get_nth_key (gpgme_key_t key, int idx)
177 {
178 gpgme_subkey_t t;
179
180 if (!key->subkeys)
181 return NULL;
182 t = key->subkeys;
183 while (idx-- && t->next)
184 t = t->next;
185 return t;
186 }
187
188
189 int
190 count_subkeys (gpgme_key_t key)
191 {
192 gpgme_subkey_t k;
193 int n = 1;
194
195 k = key->subkeys;
196 if (!k)
197 return 0;
198 while (k->next) {
199 k = k->next;
200 n++;
201 }
202 return n;
203 }
204
205
206 /* Return the self signature of the key @keyid.
207 If first is set, the first self sig will be returned. */
208 gpgme_key_sig_t
209 get_selfsig (gpgme_key_sig_t sigs, const char *keyid, int first)
210 {
211 gpgme_key_sig_t s, self_sig=NULL;
212 long timestamp=0;
213 int off = 0;
214
215 if (strlen (keyid) == 8)
216 off = 8;
217
218 for (s = sigs; s; s = s->next) {
219 if (!strcmp (s->keyid+off, keyid) && s->timestamp > timestamp) {
220 self_sig = s;
221 timestamp = s->timestamp;
222 if (first) /* do not search for later self sigs. */
223 break;
224 }
225 }
226 return self_sig;
227 }
228
229
230 const char*
231 get_key_algo (gpgme_key_t key, int keyidx)
232 {
233 static char algo_id[128];
234 gpgme_subkey_t k;
235 char alg[32];
236 const char *subalg;
237 int n;
238
239 if (keyidx > 0) {
240 k = get_nth_key (key, keyidx-1);
241 subalg = get_key_pubalgo (k->pubkey_algo);
242 _snprintf (algo_id, DIM (algo_id)-1, "%s", subalg);
243 return algo_id;
244 }
245 strcpy (alg, get_key_pubalgo (key->subkeys->pubkey_algo));
246 n = count_subkeys (key);
247 if (n > 1) {
248 do {
249 k = get_nth_key (key, --n);
250 if (k->revoked || k->expired)
251 continue;
252 else
253 break;
254 } while (n > 0);
255 subalg = get_key_pubalgo (k->pubkey_algo);
256 if (k == key->subkeys)
257 _snprintf (algo_id, DIM (algo_id)-1, "%s", subalg);
258 else
259 _snprintf (algo_id, DIM (algo_id)-1, "%s/%s", alg, subalg);
260 return algo_id;
261 }
262 return get_key_pubalgo (key->subkeys->pubkey_algo);
263 }
264
265
266 const char*
267 get_key_created (long timestamp)
268 {
269 static char timebuf[128];
270
271 if (timestamp < 1)
272 return "????" "-??" "-??";
273 if (!get_locale_date (timestamp, timebuf, DIM (timebuf)-1))
274 return "????" "-??" "-??";
275 return timebuf;
276 }
277
278
279 /* Return a string presentation of the time @timestamp. */
280 const char*
281 get_key_expire_date (long timestamp)
282 {
283 static char timebuf[64];
284
285 if (timestamp == 0)
286 return _("Never");
287 if (!get_locale_date (timestamp, timebuf, DIM (timebuf)-1))
288 return "????" "-??" "-??";
289 return timebuf;
290 }
291
292
293 const char*
294 get_key_type (gpgme_key_t key)
295 {
296 int type = find_secret_key (key);
297
298 if (type == 1)
299 return _("Key Pair");
300 else if (type == 2)
301 return _("Key Pair (Card)");
302 return _("Public Key");
303 }
304
305
306 const char*
307 get_key_size (gpgme_key_t key, int keyidx)
308 {
309 static char size_id[64];
310 gpgme_subkey_t k;
311 int n, size_main, size_sub;
312
313 if (keyidx > 0) {
314 k = get_nth_key (key, keyidx-1);
315 size_main = k->length;
316 _snprintf (size_id, DIM (size_id)-1, "%d", size_main);
317 return size_id;
318 }
319 size_main = key->subkeys->length;
320 n = count_subkeys (key);
321 if (n > 1) {
322 k = get_nth_key (key, n-1);
323 size_sub = k->length;
324 _snprintf (size_id, DIM (size_id) - 1, "%d/%d",
325 size_main, size_sub);
326 return size_id;
327 }
328 _snprintf (size_id, DIM (size_id) - 1, "%d", size_main);
329 return size_id;
330 }
331
332
333 const char*
334 get_key_pubalgo2 (gpgme_pubkey_algo_t alg)
335 {
336 switch (alg) {
337 case GPGME_PK_DSA: return "D";
338 case GPGME_PK_RSA: return "R";
339 case GPGME_PK_ELG: return "G";
340 default: return "?";
341 }
342 return "?";
343 }
344
345
346 const char*
347 get_key_pubalgo (gpgme_pubkey_algo_t alg)
348 {
349 switch (alg) {
350 case GPGME_PK_DSA:
351 return "DSA";
352
353 case GPGME_PK_ELG:
354 case GPGME_PK_ELG_E:
355 return "ELG";
356
357 case GPGME_PK_RSA:
358 case GPGME_PK_RSA_S:
359 case GPGME_PK_RSA_E:
360 return "RSA";
361
362 case 0:
363 /* Should never happen */
364 /*BUG (NULL);*/
365
366 default:
367 return "???";
368 }
369
370 return "???";
371 }
372
373
374 const char*
375 get_key_fpr (gpgme_key_t key)
376 {
377 static char fpr_md[64];
378 const char *fpr;
379 char t[16], tmp[40];
380 size_t i;
381
382 memset (fpr_md, 0, sizeof (fpr_md));
383 fpr = key->subkeys->fpr;
384 if (!fpr || !*fpr) {
385 memset (tmp, '0', 40);
386 fpr = tmp;
387 }
388 if (strlen (fpr) == 32) {
389 strcat (fpr_md, " ");
390 for (i=0; i < strlen (fpr)/2; i++) {
391 sprintf (t, "%c%c ", fpr[2*i], fpr[2*i+1]);
392 strcat (fpr_md, t);
393 }
394 }
395 else {
396 strcat (fpr_md, " ");
397 for (i = 0; i < strlen (fpr) / 4; i++) {
398 sprintf (t, "%c%c%c%c ", fpr[4*i], fpr[4*i+1], fpr[4*i+2], fpr[4*i+3]);
399 strcat (fpr_md, t);
400 }
401 }
402 return fpr_md;
403 }
404
405
406 /* Extract the key ID from the fingerprint.
407 A long ID will be converted into a short ID. */
408 const char*
409 get_keyid_from_fpr (const char *fpr)
410 {
411 if (!fpr)
412 return "????????";
413 if (strlen (fpr) == 40)
414 fpr += 32;
415 else if (strlen (fpr) == 32)
416 fpr += 24;
417 else if (strlen (fpr) == 16)
418 fpr += 8;
419 else
420 return "????????";
421 return fpr;
422 }
423
424
425 const char*
426 get_key_trust2 (gpgme_key_t key, int val, int uididx, int listmode)
427 {
428 if (key)
429 val = key->owner_trust; /* uididx?? */
430 switch (val) {
431 case GPGME_VALIDITY_UNKNOWN:
432 case GPGME_VALIDITY_UNDEFINED:
433 return _("None");
434 case GPGME_VALIDITY_NEVER:
435 return _("Never");
436 case GPGME_VALIDITY_MARGINAL:
437 return _("Marginal");
438 case GPGME_VALIDITY_FULL:
439 return _("Full");
440 case GPGME_VALIDITY_ULTIMATE:
441 return _("Ultimate");
442 }
443 return "";
444 }
445
446
447 const char*
448 get_key_trust (gpgme_key_t key, int uididx, int listmode)
449 {
450 return get_key_trust2 (key, 0, uididx, listmode);
451 }
452
453
454 const char*
455 get_key_trust_str (int val)
456 {
457 return get_key_trust2 (NULL, val, 0, 0);
458 }
459
460
461 /* Return the status of the key @key. */
462 char*
463 get_key_status (gpgme_key_t key, int uididx, int listmode)
464 {
465 gpgme_user_id_t u;
466 const char *attr;
467 u32 key_attr =0;
468
469 if (uididx < 0 || count_userids (key) > uididx)
470 uididx = 0;
471 if (listmode) {
472 const char *s;
473 if (key->revoked)
474 s = _("Revoked");
475 else if (key->expired)
476 s = _("Expired");
477 else if (key->disabled)
478 s = _("Disabled");
479 else
480 s = "";
481 /* if the key has a special status, we don't continue to figure out
482 the user-id validities. */
483 if (*s)
484 return m_strdup (s);
485 }
486 u = get_nth_userid (key, uididx);
487 key_attr = u->validity;
488 attr = get_key_trust2 (NULL, key_attr, 0, 0);
489 return m_strdup (attr);
490 }
491
492
493 /* Return human readable description of the key @key. */
494 char*
495 get_key_desc (gpgme_key_t key)
496 {
497 gpgme_key_t sk;
498 const char *state, *alg, *type;
499 char *desc;
500 StringBuffer p;
501
502 state = "";
503 if (key->disabled)
504 state = _("Disabled");
505 if (key->expired)
506 state = _("Expired");
507 if (key->revoked)
508 state = _("Revoked");
509
510 /* If the fingerprint has 32 octets, we assume MD5 and thus
511 an old, version 3, RSA key which is called 'Legacy' by other
512 OpenPGP programs. */
513 if (strlen (key->subkeys->fpr) == 32)
514 alg = "RSA Legacy";
515 else
516 alg = "OpenPGP";
517 type = _("public key");
518 if (!get_seckey (key->subkeys->keyid+8, &sk))
519 type = _("key pair");
520 p = state;
521 p = p + " " + alg + " " + type;
522 desc = m_strdup (p.getBuffer ());
523 return desc;
524 }
525
526
527 /* Integer comparsion of @a and @b.
528 Return values: same as in strcmp. */
529 static inline int
530 int_cmp (int a, int b)
531 {
532 if (a == b) return 0;
533 else if (a > b) return 1;
534 else return -1;
535 return 0;
536 }
537
538
539 /* To allow to sort the keys, we need to take care of
540 the expired/revoke status also. */
541 static int
542 get_ext_validity (gpgme_key_t k)
543 {
544 if (k->revoked)
545 return GPGME_VALIDITY_ULTIMATE+1;
546 else if (k->expired)
547 return GPGME_VALIDITY_ULTIMATE+2;
548 else if (k->disabled)
549 return GPGME_VALIDITY_ULTIMATE+3;
550 return k->uids->validity;
551 }
552
553
554 /* List view sorting callback. */
555 static int CALLBACK
556 keylist_cmp_cb (LPARAM first, LPARAM second, LPARAM sortby)
557 {
558 struct keycache_s *aa, *bb;
559 gpgme_key_t a, b;
560 int cmpresult = 0;
561
562 aa = (struct keycache_s *)first;
563 bb = (struct keycache_s *)second;
564 if (!aa || !bb)
565 BUG (NULL);
566 a = aa->key;
567 b = bb->key;
568
569 switch (sortby & ~KEYLIST_SORT_DESC) {
570 case KEY_SORT_USERID:
571 cmpresult = strcmpi (a->uids->uid, b->uids->uid);
572 break;
573
574 case KEY_SORT_KEYID:
575 cmpresult = strcmpi (a->subkeys->keyid+8,
576 b->subkeys->keyid+8);
577 break;
578
579 case KEY_SORT_VALIDITY:
580 cmpresult = int_cmp (get_ext_validity (a),
581 get_ext_validity (b));
582 break;
583
584 case KEY_SORT_OTRUST:
585 cmpresult = int_cmp (a->owner_trust, b->owner_trust);
586 break;
587
588 case KEY_SORT_IS_SECRET:
589 get_seckey (a->subkeys->keyid, &a);
590 get_seckey (b->subkeys->keyid, &b);
591 cmpresult = int_cmp (a? a->secret : 0, b? b->secret : 0);
592 break;
593
594 case KEY_SORT_LEN:
595 cmpresult = int_cmp (a->subkeys->length,
596 b->subkeys->length);
597 break;
598
599 case KEY_SORT_CREATED:
600 cmpresult = int_cmp (a->subkeys->timestamp,
601 b->subkeys->timestamp);
602 break;
603
604 case KEY_SORT_ALGO:
605 cmpresult = int_cmp (a->subkeys->pubkey_algo,
606 b->subkeys->pubkey_algo);
607 break;
608
609 default:
610 cmpresult = strcmpi (a->uids->uid, b->uids->uid);
611 break;
612 }
613 if (sortby & KEYLIST_SORT_DESC)
614 return (~cmpresult + 1);
615 else
616 return cmpresult;
617 }
618
619
620 int
621 keylist_add_groups (keylist_ctrl_t kl)
622 {
623 return 0;
624 }
625
626
627 /* Synchronize the key array with the contents
628 of the keylist. */
629 void
630 keylist_sync (keylist_ctrl_t kl)
631 {
632 free (kl->keys);
633 kl->nkeys = update_keys (kl, 0, &kl->keys);
634 }
635
636
637 /* Create a listview for listing keys. Use the mode given in @mode
638 and the control is given in @ctrl. */
639 static void
640 keylist_build (listview_ctrl_t *r_lv, HWND ctrl, int mode)
641 {
642 struct listview_column_s klist_enc[] = {
643 {0, 242, (char *)_("User ID")},
644 {1, 80, (char *)_("Key ID")},
645 {3, 46, (char *)_("Size")},
646 {4, 50, (char *)_("Cipher")},
647 {5, 70, (char *)_("Validity")},
648 {0, 0, NULL}
649 };
650 struct listview_column_s klist[] = {
651 {0, 240, (char *)_("User ID")},
652 {1, 78, (char *)_("Key ID")},
653 {2, 52, (char *)_("Type")},
654 {3, 66, (char *)_("Size")},
655 {4, 60, (char *)_("Cipher")},
656 {5, 66, (char *)_("Validity")},
657 {6, 58, (char *)_("Trust")},
658 {7, 72, (char *)_("Creation")},
659 {0, 0, NULL}
660 };
661 HICON ico[8];
662 listview_ctrl_t lv;
663 listview_column_t col;
664 int ncols = 0, ext_chkbox = 0;
665
666 listview_new (&lv, ctrl);
667 if (mode & KEYLIST_ENCRYPT_MIN) {
668 col = klist_enc;
669 ncols = (DIM (klist_enc) - 1);
670 ext_chkbox = 1;
671 }
672 else if (mode & KEYLIST_SIGN) {
673 col = klist_enc;
674 ncols = (DIM (klist_enc) - 1) - 1;
675 ext_chkbox = 1;
676 }
677 else {
678 col = klist;
679 ncols = (DIM (klist) - 1);
680 }
681
682 for (int j = 0; j < ncols; j++)
683 listview_add_column (lv, &col[j]);
684 listview_set_ext_style (lv);
685 if (ext_chkbox)
686 listview_set_chkbox_style (lv);
687 ico[0] = LoadIcon (glob_hinst, (LPCTSTR)IDI_PUBKEY);
688 ico[1] = LoadIcon (glob_hinst, (LPCTSTR)IDI_KEYPAIR);
689 ico[2] = LoadIcon (glob_hinst, (LPCTSTR)IDI_REV_KEYPAIR);
690 ico[3] = LoadIcon (glob_hinst, (LPCTSTR)IDI_REV_PUBKEY);
691 ico[4] = LoadIcon (glob_hinst, (LPCTSTR)IDI_SORT_DOWNARROW);
692 ico[5] = LoadIcon (glob_hinst, (LPCTSTR)IDI_SORT_UPARROW);
693 ico[6] = LoadIcon (glob_hinst, (LPCTSTR)IDI_EXP_PUBKEY);
694 listview_set_image_list (lv, 20, 16, ico, 7);
695 listview_del_all_items (lv);
696 listview_set_grid_style (lv);
697 *r_lv = lv;
698 }
699
700
701 static void
702 keylist_load_keycache (keylist_ctrl_t kl, int mode,
703 gpg_keycache_t pubkc, gpg_keycache_t seckc)
704 {
705 gpgme_key_t key, skey;
706 struct keycache_s *c;
707 const char *keyid;
708
709 gpg_keycache_rewind (pubkc);
710 if (pubkc && seckc) {
711 while (!gpg_keycache_next_key2 (pubkc, 0, &c, &key)) {
712 keyid = key->subkeys->keyid;
713 if (keyid && !gpg_keycache_find_key (seckc, keyid, 0, &skey))
714 keylist_add_key (kl, mode, c, key);
715 }
716 }
717 else if (pubkc) {
718 while (!gpg_keycache_next_key2 (pubkc, 0, &c, &key))
719 keylist_add_key (kl, mode, c, key);
720 }
721 }
722
723
724 /* Load the list view @ctrl with the keys from the cache.
725 Return value: list view context on success. */
726 keylist_ctrl_t
727 keylist_load (HWND ctrl, gpg_keycache_t pubkc, gpg_keycache_t seckc,
728 int mode, int sortby)
729 {
730 keylist_ctrl_t kl;
731
732 kl = new keylist_ctrl_s;
733 keylist_build (&kl->lv, ctrl, mode);
734 keylist_load_keycache (kl, mode, pubkc, seckc);
735 kl->nkeys = update_keys (kl, 0, &kl->keys);
736 keylist_sort (kl, sortby);
737 return kl;
738 }
739
740
741 /* Reload the given key list control @lv. */
742 int
743 keylist_reload (keylist_ctrl_t kl, gpg_keycache_t pubkc, int mode, int sortby)
744 {
745 listview_del_all_items (kl->lv);
746 keylist_load_keycache (kl, mode, pubkc, NULL);
747 /* It is possible that the list shrinks or increases so we need to
748 rebuild the list again. */
749 free (kl->keys); kl->keys = NULL;
750 kl->nkeys = update_keys (kl, 0, &kl->keys);
751 keylist_sort (kl, sortby);
752 return 0;
753 }
754
755
756 void
757 keylist_delete (keylist_ctrl_t kl)
758 {
759 if (!kl)
760 return;
761 if (kl->keys != NULL) {
762 free (kl->keys);
763 kl->keys = NULL;
764 }
765 if (kl->lv != NULL) {
766 listview_release (kl->lv);
767 kl->lv = NULL;
768 }
769 }
770
771
772
773
774 /* Enumeration for possible key icons. */
775 enum key_icontype_t {
776 IMG_KEY_PUB = 0,
777 IMG_KEY_PAIR = 1,
778 IMG_KEY_PAIR_REV = 2,
779 IMG_KEY_PUB_REV = 3,
780 IMG_KEY_PUB_EXP = 6,
781 };
782
783
784 static int
785 key_get_image_id (gpgme_key_t key)
786 {
787 if (find_secret_key (key))
788 return key->revoked ? IMG_KEY_PAIR_REV :IMG_KEY_PAIR;
789 if (key->revoked)
790 return IMG_KEY_PUB_REV;
791 if (key->expired)
792 return IMG_KEY_PUB_EXP;
793 return IMG_KEY_PUB;
794 }
795
796
797 static int
798 do_addkey (listview_ctrl_t lv, struct keycache_s *ctx, gpgme_key_t key,
799 int uididx, int keyidx, int list)
800 {
801 gpgme_user_id_t u;
802 gpgme_subkey_t k;
803 LV_ITEM lvi;
804 char *p;
805 const char *attr;
806 int idx = 0;
807
808 /* we check the pubkey algorithm here to make sure that no ElGamal
809 sign+encrypt key is used in _any_ mode */
810 if (list != 1 && key->subkeys->pubkey_algo == GPGME_PK_ELG) {
811 log_debug ("ElGamal (E+S) key found: %s (%s)\n",
812 key->uids->name, key->subkeys->keyid);
813 return 0;
814 }
815
816 if (listview_add_item2 (lv, " ", (void *)ctx))
817 return WPTERR_GENERAL;
818
819 attr = ctx->uids->uid;
820 memset (&lvi, 0, sizeof lvi);
821 lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
822 lvi.pszText = (char *)attr;
823 lvi.iImage = key_get_image_id (key);
824 lvi.lParam = (LPARAM )ctx;
825 if (ListView_SetItem (lv->ctrl, &lvi) == FALSE)
826 return WPTERR_GENERAL;
827
828 if (uididx == -1) { /* request the primary user-id of the key. */
829 attr = ctx->uids->uid;
830 uididx = 0;
831 }
832 else {
833 u = get_nth_userid (key, uididx);
834 if (!u || u->revoked || uididx < 0)
835 uididx = 0;
836 u = get_nth_userid (key, uididx);
837 attr = u->uid;
838 }
839 if (attr == NULL || strlen (attr) < 5) { /* normal userids are > 5 chars */
840 attr = _("Invalid User ID");
841 listview_add_sub_item (lv, 0, idx++, attr);
842 }
843 else
844 listview_add_sub_item (lv, 0, idx++, attr);
845 k = get_nth_key (key, keyidx);
846 if (k && k->keyid != NULL) {
847 char keyid[16+1];
848
849 _snprintf (keyid, DIM (keyid) -1, "0x%s", k->keyid + 8);
850 listview_add_sub_item (lv, 0, idx++, keyid);
851 }
852 if (list > 0) {
853 DWORD key_attr = find_secret_key (key);
854 if (!key_attr)
855 attr = "pub";
856 else
857 attr = key_attr == 1? "pub/sec" : "pub/crd";
858 listview_add_sub_item (lv, 0, idx++, attr);
859 }
860 if (lv->cols >= 2) {
861 attr = get_key_size (key, list == -1? keyidx+1 : 0);
862 if (attr != NULL)
863 listview_add_sub_item (lv, 0, idx++, attr);
864 }
865 if (lv->cols >= 3) {
866 attr = get_key_algo (key, list == -1? keyidx+1 : 0);
867 if (attr != NULL)
868 listview_add_sub_item( lv, 0, idx++, attr);
869 }
870 if (lv->cols >= 4) {
871 p = get_key_status (key, uididx, list > 0? 1 : 0);
872 if (p != NULL)
873 listview_add_sub_item (lv, 0, idx++, p);
874 free_if_alloc (p);
875 }
876 if (lv->cols >= 5) {
877 attr = get_key_trust (key, uididx, list > 0? 1 : 0);
878 listview_add_sub_item (lv, 0, idx++, attr);
879 }
880 if (lv->cols >= 6) {
881 k = get_nth_key (key, keyidx);
882 if (k->timestamp > 0) {
883 attr = get_key_created (k->timestamp);
884 listview_add_sub_item (lv, 0, idx++, attr);
885 }
886 }
887
888 return 0;
889 }
890
891
892 /* Update a single column @col but for each element in the
893 listview @lv. */
894 void
895 keylist_upd_col (keylist_ctrl_t kl, int col)
896 {
897 gpgme_key_t key;
898 const char *s;
899 char buf[32], *p;
900
901 for (int i=0; i < listview_count_items (kl->lv, 0); i++) {
902 key = km_get_key_ptr (kl, i, NULL);
903 if (!key)
904 continue;
905 switch (col) {
906 case KM_COL_KEYID:
907 _snprintf (buf, DIM (buf)-1, "0x%s", key->subkeys->keyid+8);
908 listview_add_sub_item (kl->lv, i, col, buf);
909 break;
910
911 case KM_COL_CIPHER:
912 s = get_key_algo (key, 0);
913 listview_add_sub_item (kl->lv, i, col, s);
914 break;
915
916 case KM_COL_TYPE:
917 s = find_secret_key (key)? "pub/sec" : "pub";
918 listview_add_sub_item (kl->lv, i, col, s);
919 break;
920
921 case KM_COL_CREAT:
922 s = get_key_created (key->subkeys->timestamp);
923 listview_add_sub_item (kl->lv, i, col, s);
924 break;
925
926 case KM_COL_DESC:
927 p = get_key_desc (key);
928 listview_add_sub_item (kl->lv, i, col, p);
929 free_if_alloc (p);
930 break;
931 }
932 }
933 }
934
935
936 /* Update the listview item at position @pos with the data from
937 the key @key. */
938 void
939 keylist_upd_key (keylist_ctrl_t kl, int pos,
940 struct keycache_s *ctx, gpgme_key_t key)
941 {
942 listview_ctrl_t lv = kl->lv;
943 char *p;
944 char tmp[32];
945
946 listview_set_item2 (lv, pos, (void *)ctx);
947 update_key (kl, pos, key);
948 /* the only mode we support is KEYLIST_LIST in the Key Manager */
949
950 const char *s = ctx->uids->uid;
951 if (s)
952 listview_add_sub_item (lv, pos, KM_COL_UID, s);
953
954 s = key->subkeys->keyid;
955 if (s) {
956 sprintf (tmp, "0x%s", s+8);
957 listview_add_sub_item (lv, pos, KM_COL_KEYID, tmp);
958 }
959
960 s = find_secret_key (key)? "pub/sec" : "pub";
961 listview_add_sub_item (lv, pos, KM_COL_TYPE, s);
962
963 s = get_key_size (key, 0);
964 if (s)
965 listview_add_sub_item (lv, pos, KM_COL_SIZE, s);
966
967 s = get_key_algo (key, 0);
968 if (s)
969 listview_add_sub_item (lv, pos, KM_COL_CIPHER, s);
970
971 p = get_key_status (key, 0, 1);
972 if (p) {
973 listview_add_sub_item (lv, pos, KM_COL_VALID, p);
974 free_if_alloc (p);
975 }
976
977 s = get_key_trust (key, 0, 1);
978 if (s)
979 listview_add_sub_item (lv, pos, KM_COL_TRUST, s);
980
981 long t = key->subkeys->timestamp;
982 s = get_key_created (t);
983 if (s)
984 listview_add_sub_item (lv, pos, KM_COL_CREAT, s);
985 }
986
987
988 int
989 keylist_add_key (keylist_ctrl_t kl, int mode,
990 struct keycache_s *ctx, gpgme_key_t key)
991 {
992 gpgme_subkey_t k;
993 listview_ctrl_t lv = kl->lv;
994 int uids, rc, i;
995
996 /* if the entire key is disabled, just return. */
997 if (key->disabled && !(mode & KEYLIST_LIST))
998 return 0;
999
1000 for (k = key->subkeys, i = 0; i < count_subkeys (key); i++, k = k->next) {
1001 if (k->invalid) {
1002 log_debug ("keylist_add_key: invalid key \"%s\"\n",
1003 key->uids->name);
1004 continue; /* Don't use invalid keys */
1005 }
1006
1007 if (mode & KEYLIST_ALL) {
1008 uids = count_userids (key);
1009 rc = do_addkey (lv, ctx, key, uids, i, 0);
1010 if (rc)
1011 return rc;
1012 }
1013 else if (mode & KEYLIST_LIST)
1014 return do_addkey (lv, ctx, key, -1, i, 1);
1015 else if (mode & KEYLIST_ENCRYPT) {
1016 if (k->can_encrypt && key_is_useable (k)) {
1017 if (mode & KEYLIST_FLAG_FILE) {
1018 rc = do_addkey (lv, ctx, key, -1, i, -1);
1019 if (rc)
1020 return rc;
1021 }
1022 else {
1023 for (uids = 0; uids < count_userids (key); uids++) {
1024 rc = do_addkey (lv, ctx, key, uids, i, -1);
1025 if (rc)
1026 return rc;
1027 }
1028 }
1029 }
1030 }
1031 else if (mode & KEYLIST_ENCRYPT_MIN) {
1032 if (k->can_encrypt && key_is_useable (k)) {
1033 rc = do_addkey (lv, ctx, key, -1, i, -1);
1034 return rc;
1035 }
1036 }
1037 else if (mode & KEYLIST_SIGN) {
1038 if (k->can_sign
1039 && find_secret_key (key)
1040 && key_is_useable (k)) {
1041 rc = do_addkey (lv, ctx, key, -1, i, -1);
1042 if (rc)
1043 return rc;
1044 }
1045 }
1046 }
1047
1048 return 0;
1049 }
1050
1051
1052 int
1053 keylist_sort (keylist_ctrl_t kl, int sortby)
1054 {
1055 int ret = listview_sort_items (kl->lv, sortby, keylist_cmp_cb);
1056 kl->nkeys = update_keys (kl, 1, &kl->keys);
1057 return ret;
1058 }
1059
1060
1061 /* Check that the validity @validity is at least >= marginal. */
1062 static int
1063 key_check_validity (gpgme_key_t key)
1064 {
1065 gpgme_user_id_t u;
1066
1067 for (u=key->uids; u; u =u->next) {
1068 if (u->validity >= GPGME_VALIDITY_MARGINAL)
1069 return -1;
1070 }
1071
1072 return 0;
1073 }
1074
1075
1076 /* Extract all selected recipients from the list @lv and return them
1077 as a vector. @r_force_trust is >= 1 if one of the recipients is not
1078 fully trusted. @r_count returns the number of selected keys.
1079 Return value: the key list on success, NULL otherwise. */
1080 gpgme_key_t*
1081 keylist_get_recipients (keylist_ctrl_t kl, int *r_force_trust, size_t *r_count)
1082
1083 {
1084 gpgme_key_t *keybuf, key;
1085 listview_ctrl_t lv = kl->lv;
1086 key_array_s *ka = NULL;
1087 keycache_s *c;
1088 size_t count = 0;
1089 int force_trust = 0;
1090 int nkeys, ka_pos = 0, rc = 0;
1091 int k_pos=0;
1092
1093 nkeys = listview_count_items (lv, 0);
1094 ka = key_array_new (nkeys);
1095 keybuf = (gpgme_key_t*)calloc (nkeys+1, sizeof (gpgme_key_t));
1096 if (!keybuf)
1097 BUG (NULL);
1098
1099 for (int j = 0; j < nkeys; j++) {
1100 if (listview_get_item_state (lv, j) || nkeys == 1) {
1101 key = km_get_key_ptr (kl, j, &c);
1102 if (!key)
1103 BUG (0);
1104 if (!key_check_validity (key) &&
1105 !key_array_search (ka, ka_pos, key->subkeys->keyid)) {
1106 StringBuffer warn;
1107 warn = warn + c->uids->uid + ":\n\n";
1108 warn = warn +_("It is NOT certain that the key belongs to the person\n"
1109 "named in the user ID. If you *really* know what you are\n"
1110 "doing, you may answer the next question with no\n"
1111 "\nSkip this key?");
1112 rc = msg_box (NULL, warn.getBuffer(), _("Warning"), MB_WARN_ASK);
1113 if (reg_prefs.always_trust || rc == IDNO) {
1114 keybuf[k_pos++] = key;
1115 force_trust++;
1116 ka[ka_pos].checked = 1;
1117 strcpy (ka[ka_pos++].keyid, key->subkeys->keyid);
1118 count++;
1119 }
1120 }
1121 else {
1122 keybuf[k_pos++] = key;
1123 count++;
1124 }
1125 }
1126 }
1127 key_array_release (ka);
1128 if (r_force_trust)
1129 *r_force_trust = force_trust;
1130 if (r_count)
1131 *r_count = count;
1132 return keybuf;
1133 }
1134
1135
1136 static int
1137 keylist_get_keyflags (gpgme_key_t key)
1138 {
1139 int flags = KEYFLAG_NONE;
1140
1141 if (key->revoked)
1142 flags |= KEYFLAG_REVOKED;
1143 if (key->expired)
1144 flags |= KEYFLAG_EXPIRED;
1145 if (key->disabled)
1146 flags |= KEYFLAG_DISABLED;
1147
1148 return flags;
1149 }
1150
1151
1152
1153 gpgme_key_t*
1154 keylist_enum_recipients (keylist_ctrl_t kl, int listype, size_t *r_count)
1155 {
1156 gpgme_key_t *rset;
1157 gpgme_key_t key;
1158 listview_ctrl_t lv = kl->lv;
1159 struct keycache_s *c;
1160 size_t k_pos;
1161 int nkeys, id;
1162
1163 nkeys = listview_count_items (lv, 0);
1164 if (!nkeys)
1165 return 0;
1166 rset = (gpgme_key_t*)calloc (nkeys+1, sizeof (gpgme_key_t));
1167 if (!rset)
1168 BUG (NULL);
1169 k_pos = 0;
1170 for (int i = 0; i < nkeys; i++) {
1171 if (!listview_get_item_state (lv, i))
1172 continue;
1173 key = km_get_key_ptr (kl, i, &c);
1174 switch (listype) {
1175 case KEYLIST_LIST:
1176 if (keylist_get_keyflags (key) & KEYFLAG_REVOKED) {
1177 id = printf_box (_("Recipients"), MB_INFO|MB_YESNO,
1178 _("KeyID %s.\nDo you really want to export a revoked key?"),
1179 c->uids->uid);
1180 if (id == IDNO)
1181 continue;
1182 }
1183 break;
1184 }
1185 rset[k_pos++] = key;
1186 }
1187 if (r_count)
1188 *r_count = k_pos;
1189 return rset;
1190 }
1191
1192
1193 void
1194 seclist_destroy (keylist_t *list)
1195 {
1196 keylist_t l2;
1197
1198 while (*list) {
1199 l2 = (*list)->next;
1200 safe_free (*list);
1201 *list = l2;
1202 }
1203 *list = NULL;
1204 }
1205
1206
1207 void
1208 seclist_init (HWND dlg, int ctlid, int flags, keylist_t *ret_list)
1209 {
1210 gpg_keycache_t kc;
1211 gpgme_key_t key = NULL;
1212 HWND kb;
1213 keylist_t list=NULL, l, l2;
1214 long pos;
1215
1216 SendDlgItemMessage (dlg, ctlid, CB_RESETCONTENT, 0, 0);
1217 kb = GetDlgItem (dlg, ctlid);
1218 kc = keycache_get_ctx (0);
1219 if (!kc)
1220 BUG (0);
1221 gpg_keycache_rewind (kc);
1222
1223 while (!gpg_keycache_next_key (kc, 1, &key)) {
1224 StringBuffer inf;
1225 char *uid;
1226 const char *id;
1227
1228 if (key->disabled || !key_is_useable (key->subkeys))
1229 continue;
1230
1231 if (flags & KEYLIST_FLAG_SHORT)
1232 id = key->uids->name;
1233 else
1234 id = key->uids->uid;
1235 if (!id || !key->subkeys->keyid)
1236 continue;
1237
1238 uid = utf8_to_native (id);
1239 inf = uid;
1240 inf = inf + " (" + get_key_pubalgo (key->subkeys->pubkey_algo) + "/";
1241 inf = inf + "0x" + (key->subkeys->keyid+8) + ")";
1242
1243 combox_add_string (kb, inf.getBuffer ());
1244 safe_free (uid);
1245 l = (struct keylist_s *)calloc (1, sizeof * l);
1246 if (!l)
1247 BUG (0);
1248 l->key = key;
1249 if (!list)
1250 list = l;
1251 else {
1252 for( l2 = list; l2->next; l2 = l2->next )
1253 ;
1254 l2->next = l;
1255 }
1256 }
1257 for (pos = 0, l2=list; pos < SendMessage (kb, CB_GETCOUNT, 0, 0);
1258 pos++, l2=l2->next)
1259 SendMessage (kb, CB_SETITEMDATA, pos, (LPARAM)(DWORD)l2->key);
1260 SendMessage (kb, CB_SETCURSEL, 0, 0);
1261 *ret_list = list;
1262 }
1263
1264
1265 /* Select a secret key from the combo box with the ID @ctlid.
1266 Return the code on success in @ret_key. */
1267 int
1268 seclist_select_key (HWND dlg, int ctlid, gpgme_key_t *ret_key)
1269 {
1270 int pos;
1271 DWORD k = 0;
1272
1273 pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0);
1274 if (pos == CB_ERR) {
1275 msg_box (dlg, _("No key was selected."), _("Secret Key List"), MB_ERR);
1276 *ret_key = NULL;
1277 }
1278 else {
1279 k = SendDlgItemMessage (dlg, ctlid, CB_GETITEMDATA, pos, 0);
1280 *ret_key = (gpgme_key_t)k;
1281 }
1282 return k? 0 : -1;
1283 }
1284
1285
1286 LRESULT
1287 keylist_listview_notify (HWND hwnd, gpgme_key_t *keys,
1288 int ctlid, LPARAM lparam)
1289 {
1290 LPNMHDR lpnmh = (LPNMHDR)lparam;
1291
1292 if (!lpnmh)
1293 BUG (NULL);
1294
1295 /* Make sure the message is for the control and
1296 that we have a key list. */
1297 if (lpnmh->idFrom != (DWORD)ctlid || keys == NULL)
1298 return 0;
1299
1300 switch (lpnmh->code) {
1301 case NM_CUSTOMDRAW:
1302 LPNMLVCUSTOMDRAW lplvcd;
1303 lplvcd = (LPNMLVCUSTOMDRAW)lparam;
1304 if (lplvcd->nmcd.dwDrawStage == CDDS_PREPAINT)
1305 return CDRF_NOTIFYITEMDRAW;
1306
1307 if (lplvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {
1308 int pos = lplvcd->nmcd.dwItemSpec;
1309
1310 gpgme_key_t key = keys[pos];
1311 if (key == NULL)
1312 return CDRF_DODEFAULT;
1313
1314 HWND lv = GetDlgItem (hwnd, ctlid);
1315 HFONT hfont = (HFONT)SendMessage (lv, WM_GETFONT, 0, 0);
1316 LOGFONT lf;
1317 if (!GetObject (hfont, sizeof (lf), &lf))
1318 BUG (NULL);
1319 if (key->revoked)
1320 lf.lfStrikeOut = TRUE;
1321 else if (key->expired)
1322 lf.lfItalic = TRUE;
1323 if (find_secret_key (key))
1324 lf.lfWeight = FW_SEMIBOLD;
1325 hfont = CreateFontIndirect (&lf);
1326 SelectObject (lplvcd->nmcd.hdc, hfont);
1327 if (pos & 1)
1328 lplvcd->clrTextBk = RGB (0xE5, 0xE5, 0xE5);
1329 return CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT;
1330 }
1331
1332 if (lplvcd->nmcd.dwDrawStage == CDDS_ITEMPOSTPAINT) {
1333 HFONT hfont = (HFONT)GetStockObject (DEFAULT_GUI_FONT);
1334 hfont = (HFONT)SelectObject (lplvcd->nmcd.hdc, hfont);
1335 DeleteObject (hfont);
1336 return CDRF_DODEFAULT;
1337 }
1338 return CDRF_DODEFAULT;
1339 }
1340
1341 return 0;
1342 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26