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

Legend:
Removed from v.24  
changed lines
  Added in v.219

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26