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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26