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

Contents of /trunk/Src/wptKeylist.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26