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

Diff of /trunk/Src/wptKeylist.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.25  
changed lines
  Added in v.328

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26