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

Contents of /trunk/Src/wptKeylist.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 133 - (show annotations)
Mon Jan 9 09:15:29 2006 UTC (19 years, 1 month ago) by twoaday
File size: 26054 byte(s)
A lot of minor bug fixes.
New icons.

For a complete history, see the ChangeLog entries.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26