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

Contents of /trunk/Src/wptKeylist.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 150 - (show annotations)
Wed Jan 18 11:52:45 2006 UTC (19 years, 1 month ago) by twoaday
File size: 26153 byte(s)
2006-01-18  Timo Schulz  <ts@g10code.com>
 
        * wptListview.cpp (listview_del_sel_items): Fixed index
        calculation. This fixed a lot of problems with the KM listview
        update.
        (listview_del_all): Renamed to...
        (listview_del_all_items): ..this. Changed all callers.
        * wptKeyManagerDlg.cpp (keymanager_dlg_proc): Just refresh
        list when file import contained new/updated keys.
        * wptKeyManager.cpp (km_file_import): Indicate if the
        import contained any new/update keys.
        * wptClipImportDlg.cpp (print_import_status): Just mark
        keys which actually changed.
         


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 else if (k->disabled)
433 return GPGME_VALIDITY_ULTIMATE+3;
434 return k->uids->validity;
435 }
436
437
438 /* List view sorting callback. */
439 static int CALLBACK
440 keylist_cmp_cb (LPARAM first, LPARAM second, LPARAM sortby)
441 {
442 gpgme_key_t a, b;
443 int cmpresult = 0;
444
445 a = (gpgme_key_t)first;
446 b = (gpgme_key_t)second;
447 if (!a || !b)
448 BUG (NULL);
449
450 switch (sortby & ~KEYLIST_SORT_DESC) {
451 case KEY_SORT_USERID:
452 cmpresult = strcmpi (a->uids->uid, b->uids->uid);
453 break;
454
455 case KEY_SORT_KEYID:
456 cmpresult = strcmpi (a->subkeys->keyid+8,
457 b->subkeys->keyid+8);
458 break;
459
460 case KEY_SORT_VALIDITY:
461 cmpresult = int_cmp (get_ext_validity (a),
462 get_ext_validity (b));
463 break;
464
465 case KEY_SORT_OTRUST:
466 cmpresult = int_cmp (a->owner_trust, b->owner_trust);
467 break;
468
469 case KEY_SORT_IS_SECRET:
470 get_seckey (a->subkeys->keyid, &a);
471 get_seckey (b->subkeys->keyid, &b);
472 cmpresult = int_cmp (a? a->secret : 0, b? b->secret : 0);
473 break;
474
475 case KEY_SORT_LEN:
476 cmpresult = int_cmp (a->subkeys->length,
477 b->subkeys->length);
478 break;
479
480 case KEY_SORT_CREATED:
481 cmpresult = int_cmp (a->subkeys->timestamp,
482 b->subkeys->timestamp);
483 break;
484
485 case KEY_SORT_ALGO:
486 cmpresult = int_cmp (a->subkeys->pubkey_algo,
487 b->subkeys->pubkey_algo);
488 break;
489
490 default:
491 cmpresult = strcmpi (a->uids->uid, b->uids->uid);
492 break;
493 }
494 if (sortby & KEYLIST_SORT_DESC)
495 return (~cmpresult + 1);
496 else
497 return cmpresult;
498 }
499
500
501 #if 0
502 /* Return the validity of the group @grp. */
503 static const char*
504 calc_validity (gpg_group_t grp)
505 {
506 int valid = 0;
507 gpg_member_t mbr;
508 gpgme_key_t key;
509
510 for (mbr = grp->list; mbr; mbr = mbr->next) {
511 if (get_pubkey (mbr->name, &key))
512 continue;
513 valid = key->uids->validity;
514 switch (valid) {
515 case GPGME_VALIDITY_MARGINAL:
516 case GPGME_VALIDITY_NEVER:
517 case GPGME_VALIDITY_UNDEFINED:
518 return get_key_trust2 (NULL, valid, 0, 0);
519 }
520 }
521 return _("Full");
522 }
523 #endif
524
525
526 int
527 keylist_add_groups (listview_ctrl_t lv)
528 {
529 return 0;
530 }
531
532
533 /* Create a listview for listing keys. Use the mode given in @mode
534 and the control is given in @ctrl. */
535 static int
536 keylist_build (listview_ctrl_t *r_lv, HWND ctrl, int mode)
537 {
538 struct listview_column_s klist_enc[] = {
539 {0, 242, (char *)_("User ID")},
540 {1, 80, (char *)_("Key ID")},
541 {3, 46, (char *)_("Size")},
542 {4, 50, (char *)_("Cipher")},
543 {5, 70, (char *)_("Validity")},
544 {0, 0, NULL}
545 };
546 struct listview_column_s klist[] = {
547 {0, 240, (char *)_("User ID")},
548 {1, 78, (char *)_("Key ID")},
549 {2, 52, (char *)_("Type")},
550 {3, 66, (char *)_("Size")},
551 {4, 60, (char *)_("Cipher")},
552 {5, 66, (char *)_("Validity")},
553 {6, 58, (char *)_("Trust")},
554 {7, 72, (char *)_("Creation")},
555 {0, 0, NULL}
556 };
557 HICON ico[2];
558 listview_ctrl_t lv;
559 listview_column_t col;
560 int j, n = 0;
561 int rc = 0;
562
563 rc = listview_new (&lv);
564 if (rc)
565 return rc;
566
567 lv->ctrl = ctrl;
568 if ((mode & KEYLIST_ENCRYPT) || (mode & KEYLIST_ENCRYPT_MIN)) {
569 col = klist_enc;
570 n = (DIM(klist_enc) -1);
571 }
572 else if ((mode & KEYLIST_SIGN)) {
573 col = klist_enc;
574 n = (DIM(klist_enc) - 1) - 1;
575 }
576 else {
577 col = klist;
578 n = (DIM(klist) - 1);
579 }
580
581 for (j = 0; j < n; j++)
582 listview_add_column (lv, &col[j]);
583 listview_set_ext_style (lv);
584 ico[0] = LoadIcon (glob_hinst, (LPCTSTR)IDI_PUBKEY);
585 ico[1] = LoadIcon (glob_hinst, (LPCTSTR)IDI_KEYPAIR);
586 listview_set_image_list (lv, ico, 2);
587 listview_del_all_items (lv);
588
589 *r_lv = lv;
590 return 0;
591 }
592
593
594 static void
595 keylist_load_keycache (listview_ctrl_t lv, int mode,
596 gpg_keycache_t pubkc, gpg_keycache_t seckc)
597 {
598 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
599 gpgme_key_t key, skey;
600 const char * keyid;
601
602 if (pubkc && seckc) {
603 gpg_keycache_rewind (pubkc);
604 while (!gpg_keycache_next_key (pubkc, 0, &key)) {
605 keyid = key->subkeys->keyid;
606 if (keyid && !gpg_keycache_find_key (seckc, keyid, 0, &skey))
607 keylist_add_key (lv, mode, key);
608 }
609 }
610 else if (pubkc) {
611 gpg_keycache_rewind (pubkc);
612 while (!err) {
613 err = gpg_keycache_next_key (pubkc, 0, &key);
614 if (!err)
615 keylist_add_key (lv, mode, key);
616 }
617 }
618 }
619
620
621 /* Load the list view @ctrl with the keys from the cache.
622 Return value: list view context on success. */
623 listview_ctrl_t
624 keylist_load (HWND ctrl, gpg_keycache_t pubkc, gpg_keycache_t seckc,
625 int mode, int sortby)
626 {
627 listview_ctrl_t lv;
628 int rc = 0;
629
630 rc = keylist_build (&lv, ctrl, mode);
631 if (rc)
632 return NULL;
633 keylist_load_keycache (lv, mode, pubkc, seckc);
634 keylist_sort (lv, sortby);
635 if ((mode & KEYLIST_ENCRYPT) || (mode & KEYLIST_ENCRYPT_MIN))
636 keylist_add_groups (lv);
637 return lv;
638 }
639
640
641 /* Reload the given key list control @lv. */
642 int
643 keylist_reload (listview_ctrl_t lv, gpg_keycache_t pubkc, int mode, int sortby)
644 {
645 listview_del_all_items (lv);
646 keylist_load_keycache( lv, mode, pubkc, NULL );
647 keylist_sort (lv, sortby);
648 return 0;
649 }
650
651
652 void
653 keylist_delete (listview_ctrl_t lv)
654 {
655 if (lv) {
656 listview_release (lv);
657 }
658 }
659
660
661 /* Return if there is a secret for @key.
662 0 means success. */
663 static int
664 find_secret_key (gpgme_key_t key)
665 {
666 const char *keyid;
667 winpt_key_s skey;
668
669 memset (&skey, 0, sizeof (skey));
670 keyid = key->subkeys->keyid;
671 if (!keyid)
672 return 0;
673 winpt_get_seckey (keyid, &skey);
674 if (skey.ext && skey.ext->gloflags.divert_to_card)
675 return 2;
676 return skey.ctx? 1 : 0;
677 }
678
679
680 static int
681 do_addkey (listview_ctrl_t lv, gpgme_key_t key, int uididx, int keyidx, int list)
682 {
683 LV_ITEM lvi;
684 gpgme_user_id_t u;
685 gpgme_subkey_t k;
686 char fmt[128], *p;
687 const char *attr;
688 u32 key_attr;
689 int idx = 0;
690
691 /* we check the pubkey algorithm here to make sure that no ElGamal
692 sign+encrypt key is used in _any_ mode */
693 if (list != 1 && key->subkeys->pubkey_algo == GPGME_PK_ELG) {
694 log_debug ("ElGamal (E+S) key found: %s (%s)\n",
695 key->uids->name, key->subkeys->keyid);
696 return 0;
697 }
698
699 if (listview_add_item2 (lv, " ", (void *)key))
700 return WPTERR_GENERAL;
701
702 attr = key->uids->uid;
703 memset (&lvi, 0, sizeof lvi);
704 lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
705 lvi.pszText = (char *)attr;
706 lvi.iImage = find_secret_key (key)? 1 : 0;
707 lvi.lParam = (LPARAM )key;
708 if (ListView_SetItem (lv->ctrl, &lvi) == FALSE)
709 return WPTERR_GENERAL;
710
711 if (uididx == -1) { /* request the primary user-id of the key. */
712 attr = key->uids->uid;
713 uididx = 0;
714 }
715 else {
716 u = get_nth_userid (key, uididx);
717 if (!u || u->revoked || uididx < 0)
718 uididx = 0;
719 u = get_nth_userid (key, uididx);
720 attr = u->uid;
721 }
722 if (attr == NULL || strlen (attr) < 5) { /* normal userids are > 5 chars */
723 attr = _("Invalid User ID");
724 listview_add_sub_item (lv, 0, idx++, attr);
725 }
726 else {
727 char *uid = utf8_to_wincp (attr, strlen (attr));
728 if (uid) {
729 listview_add_sub_item (lv, 0, idx++, uid);
730 free (uid);
731 }
732 }
733 k = get_nth_key (key, keyidx);
734 if (k && k->keyid) {
735 _snprintf (fmt, sizeof fmt -1, "0x%s", k->keyid + 8);
736 listview_add_sub_item( lv, 0, idx++, fmt );
737 }
738 if (list > 0) {
739 key_attr = find_secret_key (key);
740 if (!key_attr)
741 attr = "pub";
742 else
743 attr = key_attr == 1? "pub/sec" : "pub/crd";
744 listview_add_sub_item (lv, 0, idx++, attr);
745 }
746 if (lv->cols >= 2) {
747 attr = get_key_size (key, list == -1? keyidx+1 : 0);
748 if (attr)
749 listview_add_sub_item (lv, 0, idx++, attr);
750 }
751 if (lv->cols >= 3) {
752 attr = get_key_algo (key, list == -1? keyidx+1 : 0);
753 if (attr)
754 listview_add_sub_item( lv, 0, idx++, attr);
755 }
756 if( lv->cols >= 4 ) {
757 p = get_key_status( key, uididx, list > 0? 1 : 0 );
758 if (!p)
759 return WPTERR_GENERAL;
760 listview_add_sub_item (lv, 0, idx++, p);
761 free_if_alloc (p);
762 }
763 if (lv->cols >= 5) {
764 attr = get_key_trust (key, uididx, list > 0? 1 : 0);
765 listview_add_sub_item (lv, 0, idx++, attr);
766 }
767 if( lv->cols >= 6 ) {
768 k = get_nth_key (key, keyidx);
769 key_attr = k->timestamp;
770 if( key_attr ) {
771 attr = get_key_created (key_attr);
772 listview_add_sub_item( lv, 0, idx++, attr );
773 }
774 }
775
776 return 0;
777 }
778
779
780 /* Update a single column @col but for each element in the
781 listview @lv. */
782 void
783 keylist_upd_col (listview_ctrl_t lv, int col)
784 {
785 gpgme_key_t key;
786 const char *s;
787 char buf[32];
788 int i;
789
790 for (i=0; i < listview_count_items (lv, 0); i++) {
791 key = (gpgme_key_t)listview_get_item2 (lv, i);
792 if (!key)
793 continue;
794 switch (col) {
795 case KM_COL_KEYID:
796 _snprintf (buf, sizeof (buf)-1, "0x%s", key->subkeys->keyid+8);
797 listview_add_sub_item (lv, i, col, buf);
798 break;
799
800 case KM_COL_CIPHER:
801 s = get_key_algo (key, 0);
802 listview_add_sub_item (lv, i, col, s);
803 break;
804
805 case KM_COL_TYPE:
806 s = find_secret_key (key)? "pub/sec" : "pub";
807 listview_add_sub_item (lv, i, col, s);
808 break;
809
810 case KM_COL_CREAT:
811 s = get_key_created (key->subkeys->timestamp);
812 listview_add_sub_item (lv, i, col, s);
813 break;
814 }
815 }
816 }
817
818
819 /* Update the listview item at position @pos with the data from
820 the key @key. */
821 void
822 keylist_upd_key (listview_ctrl_t lv, int pos, gpgme_key_t key)
823 {
824 const char *s;
825 char *uid;
826 char tmp[32];
827
828 listview_set_item2 (lv, pos, (void *)key);
829 /* the only mode we support is KYLIST_LIST in the Key Manager */
830
831 s = key->uids->uid;
832 if (s) {
833 uid = utf8_to_wincp2 (s);
834 listview_add_sub_item (lv, pos, 0, uid);
835 free (uid);
836 }
837
838 s = key->subkeys->keyid;
839 if (s) {
840 sprintf (tmp, "0x%s", s+8);
841 listview_add_sub_item (lv, pos, 1, tmp);
842 }
843
844 s = find_secret_key (key)? "pub/sec" : "pub";
845 listview_add_sub_item (lv, pos, 2, s);
846
847 s = get_key_size (key, 0);
848 if (s)
849 listview_add_sub_item (lv, pos, 3, s);
850
851 s = get_key_algo (key, 0);
852 if (s)
853 listview_add_sub_item (lv, pos, 4, s);
854
855 s = get_key_status (key, 0, 1);
856 if (s)
857 listview_add_sub_item (lv, pos, 5, s);
858
859 s = get_key_trust (key, 0, 1);
860 if (s)
861 listview_add_sub_item (lv, pos, 6, s);
862
863 long t = key->subkeys->timestamp;
864 s = get_key_created (t);
865 if (s)
866 listview_add_sub_item (lv, pos, 7, s);
867 }
868
869
870 int
871 keylist_add_key (listview_ctrl_t lv, int mode, gpgme_key_t key)
872 {
873 int uids, rc = 0, i;
874 gpgme_subkey_t k;
875
876 /* if the entire key is disabled, just return. */
877 if (key->disabled && !(mode & KEYLIST_LIST))
878 return 0;
879
880 for (k=key->subkeys, i = 0; i < count_subkeys (key); i++, k=k->next) {
881 if (k->invalid) {
882 log_debug ("keylist_add_key: invalid key \"%s\"\n", key->uids->name);
883 continue; /* Don't use invalid keys */
884 }
885
886 if (mode & KEYLIST_ALL) {
887 uids = count_userids (key);
888 rc = do_addkey (lv, key, uids, i, 0);
889 if (rc)
890 return rc;
891 }
892 else if (mode & KEYLIST_LIST)
893 return do_addkey (lv, key, -1, i, 1);
894 else if (mode & KEYLIST_ENCRYPT) {
895 if (k->can_encrypt && key_is_useable (k)) {
896 if (mode & KEYLIST_FLAG_FILE) {
897 rc = do_addkey (lv, key, -1, i, -1);
898 if (rc)
899 return rc;
900 }
901 else {
902 for (uids = 0; uids < count_userids (key); uids++) {
903 rc = do_addkey (lv, key, uids, i, -1);
904 if (rc)
905 return rc;
906 }
907 }
908 }
909 }
910 else if (mode & KEYLIST_ENCRYPT_MIN) {
911 if( k->can_encrypt && key_is_useable (k))
912 {
913 rc = do_addkey (lv, key, -1, i, -1);
914 return rc;
915 }
916 }
917 else if (mode & KEYLIST_SIGN) {
918 if (k->can_sign
919 && find_secret_key (key)
920 && key_is_useable (k)) {
921 rc = do_addkey (lv, key, -1, i, -1);
922 if (rc)
923 return rc;
924 }
925 }
926 }
927
928 return rc;
929 }
930
931
932 int
933 keylist_sort (listview_ctrl_t lv, int sortby)
934 {
935 return listview_sort_items (lv, sortby, keylist_cmp_cb);
936 }
937
938
939 /* Check that the validity @validity is at least >= marginal. */
940 static int
941 key_check_validity (gpgme_key_t key)
942 {
943 gpgme_user_id_t u;
944
945 for (u=key->uids; u; u =u->next) {
946 if (u->validity >= GPGME_VALIDITY_MARGINAL)
947 return -1;
948 }
949
950 return 0;
951 }
952
953
954 /* Extract all selected recipients from the list @lv and return them
955 as a vector. @r_force_trust is >= 1 if one of the recipients is not
956 fully trusted. @r_count returns the number of selected keys.
957 Return value: the key list on success, NULL otherwise. */
958 gpgme_key_t*
959 keylist_get_recipients (listview_ctrl_t lv, int *r_force_trust, int *r_count)
960 {
961 key_array_s *ka = NULL;
962 gpgme_key_t *keybuf, key;
963 int count = 0, force_trust = 0;
964 int n, j, ka_pos = 0, rc = 0;
965 int k_pos=0;
966
967 n = listview_count_items (lv, 0);
968
969 ka = key_array_new (n);
970 if (!ka)
971 BUG (NULL);
972
973 keybuf = (gpgme_key_t*)calloc (n, sizeof (gpgme_key_t));
974 if (!keybuf)
975 BUG (NULL);
976
977 for (j = 0; j < n; j++) {
978 if (listview_get_item_state (lv, j) || n == 1) {
979 key = (gpgme_key_t)listview_get_item2 (lv, j);
980 if (!key)
981 BUG (0);
982 if (!key_check_validity (key) &&
983 !key_array_search (ka, ka_pos, key->subkeys->keyid)) {
984 char *warn = new char[512+strlen (key->uids->uid) + 1];
985 if (!warn)
986 BUG (0);
987 sprintf (warn,
988 _("It is NOT certain that the key belongs to the person\n"
989 "named in the user ID. If you *really* know what you are\n"
990 "doing, you may answer the next question with yes\n"
991 "\n"
992 "Use \"%s\" anyway?"), key->uids->uid);
993 if (reg_prefs.always_trust)
994 rc = IDYES;
995 else
996 rc = msg_box (NULL, warn, _("Recipients"), MB_ERR_ASK);
997 if (rc == IDYES) {
998 keybuf[k_pos++] = key;
999 force_trust++;
1000 ka[ka_pos].checked = 1;
1001 strcpy (ka[ka_pos++].keyid, key->subkeys->keyid);
1002 count++;
1003 }
1004 free_if_alloc (warn);
1005 }
1006 else {
1007 keybuf[k_pos++] = key;
1008 count++;
1009 }
1010 }
1011 }
1012 key_array_release (ka);
1013 if (r_force_trust)
1014 *r_force_trust = force_trust;
1015 if (r_count)
1016 *r_count = count;
1017 return keybuf;
1018 }
1019
1020
1021 static int
1022 keylist_get_keyflags (gpgme_key_t key)
1023 {
1024 int flags = KEYFLAG_NONE;
1025
1026 if (key->revoked)
1027 flags |= KEYFLAG_REVOKED;
1028 if (key->expired)
1029 flags |= KEYFLAG_EXPIRED;
1030 if (key->disabled)
1031 flags |= KEYFLAG_DISABLED;
1032
1033 return flags;
1034 }
1035
1036
1037 gpgme_key_t*
1038 keylist_enum_recipients (listview_ctrl_t lv, int listype, int *r_count)
1039 {
1040 gpgme_key_t *rset;
1041 gpgme_key_t key;
1042 int i, n, id, k_pos=0;
1043
1044 n = listview_count_items (lv, 0);
1045 if (!n)
1046 return 0;
1047 rset = (gpgme_key_t*)calloc (n, sizeof (gpgme_key_t));
1048 if (!rset)
1049 BUG (NULL);
1050 for (i = 0; i < n; i++) {
1051 if (!listview_get_item_state (lv, i))
1052 continue;
1053 key = (gpgme_key_t)listview_get_item2 (lv, i);
1054 if (!key)
1055 BUG (0);
1056 switch (listype) {
1057 case KEYLIST_LIST:
1058 if (keylist_get_keyflags (key) & KEYFLAG_REVOKED) {
1059 id = printf_box (_("Recipients"), MB_INFO|MB_YESNO,
1060 _("KeyID %s.\nDo you really want to export a revoked key?"),
1061 key->uids->uid);
1062 if (id == IDNO)
1063 continue;
1064 }
1065 break;
1066 }
1067 rset[k_pos++] = key;
1068 }
1069 if (r_count)
1070 *r_count = k_pos;
1071 return rset;
1072 }
1073
1074
1075 void
1076 seclist_destroy (keylist_t *list)
1077 {
1078 keylist_t l2;
1079 while (*list) {
1080 l2 = (*list)->next;
1081 safe_free (*list);
1082 *list = l2;
1083 }
1084 list = NULL;
1085 }
1086
1087
1088 void
1089 seclist_init (HWND dlg, int ctlid, int flags, keylist_t * ret_list)
1090 {
1091 gpg_keycache_t kc = NULL;
1092 gpgme_key_t key = NULL;
1093 HWND kb;
1094 keylist_t list=NULL, l, l2;
1095 long pos = 0;
1096
1097 SendDlgItemMessage (dlg, ctlid, CB_RESETCONTENT, 0, 0);
1098 kb = GetDlgItem (dlg, ctlid);
1099 kc = keycache_get_ctx (0);
1100 if (!kc)
1101 BUG (0);
1102 gpg_keycache_rewind (kc);
1103
1104 while (!gpg_keycache_next_key (kc, 1, &key)) {
1105 char *inf = NULL, *uid = NULL;
1106 const char *id;
1107 const char *keyid;
1108 int algo;
1109 size_t size = 0;
1110
1111 if (flags & KEYLIST_FLAG_SHORT)
1112 id = key->uids->name;
1113 else
1114 id = key->uids->uid;
1115 keyid = key->subkeys->keyid;
1116 algo = key->subkeys->pubkey_algo;
1117 if (!id || !keyid)
1118 continue;
1119 if (key->disabled || !key_is_useable (key->subkeys))
1120 continue;
1121
1122 uid = utf8_to_wincp (id, strlen (id));
1123 size = strlen (uid) + strlen (keyid) + 32;
1124 inf = new char[size+1];
1125 if (!inf)
1126 BUG (NULL);
1127 _snprintf (inf, size, "%s (%s/0x%s)", uid,
1128 get_key_pubalgo (key->subkeys->pubkey_algo), keyid + 8);
1129 combox_add_string (kb, inf);
1130 free_if_alloc (inf);
1131 free (uid);
1132 l = (struct keylist_s *)calloc (1, sizeof * l);
1133 if (!l)
1134 BUG (0);
1135 l->key = key;
1136 if (!list)
1137 list = l;
1138 else {
1139 for( l2 = list; l2->next; l2 = l2->next )
1140 ;
1141 l2->next = l;
1142 }
1143 }
1144 for (pos = 0, l2=list; pos < SendMessage (kb, CB_GETCOUNT, 0, 0);
1145 pos++, l2=l2->next)
1146 SendMessage (kb, CB_SETITEMDATA, pos, (LPARAM)(DWORD)l2->key);
1147 SendMessage (kb, CB_SETCURSEL, 0, 0);
1148 *ret_list = list;
1149 }
1150
1151
1152 /* Select a secret key from the combo box with the ID @ctlid.
1153 Return the code on success in @ret_key. */
1154 int
1155 seclist_select_key (HWND dlg, int ctlid, gpgme_key_t *ret_key)
1156 {
1157 int pos;
1158 DWORD k = 0;
1159
1160 pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0);
1161 if (pos == CB_ERR) {
1162 msg_box (dlg, _("No key was selected."), _("Secret Key List"), MB_ERR);
1163 *ret_key = NULL;
1164 }
1165 else {
1166 k = SendDlgItemMessage (dlg, ctlid, CB_GETITEMDATA, pos, 0);
1167 *ret_key = (gpgme_key_t)k;
1168 }
1169 return k? 0 : -1;
1170 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26