/[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 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 = 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);      int rc = 0;
599          while (!err) {          
600              err = gpgme_keycache_next_key (pubkc, 0, &key);      listview_new (&lv, ctrl);
601              if (!err)      if (mode & KEYLIST_ENCRYPT_MIN) {
602                  keylist_add_key (lv, mode, key);          col = klist_enc;
603          }          n = (DIM(klist_enc) -1);
604      }          ext_chk = 1;
605  } /* keylist_load_keycache */      }  
606        else if ((mode & KEYLIST_SIGN)) {
607            col = klist_enc;
608  listview_ctrl_t          n = (DIM(klist_enc) - 1) - 1;
609  keylist_load (HWND ctrl, gpgme_keycache_t pubkc, gpgme_keycache_t seckc,          ext_chk = 1;
610                int mode, int sortby)      }
611  {          else {
612      listview_ctrl_t lv;          col = klist;
613      int rc = 0;              n = (DIM(klist) - 1);
614        }
615      rc = keylist_build (&lv, ctrl, mode);      
616      if (rc)      for (j = 0; j < n; j++)
617          return NULL;                      listview_add_column (lv, &col[j]);    
618      keylist_load_keycache (lv, mode, pubkc, seckc);      listview_set_ext_style (lv);
619      keylist_sort (lv, sortby);      if (ext_chk)
620      if ((mode & KEYLIST_ENCRYPT) || (mode & KEYLIST_ENCRYPT_MIN))          listview_set_chkbox_style (lv);
621          keylist_add_groups (lv);      ico[0] = LoadIcon (glob_hinst, (LPCTSTR)IDI_PUBKEY);
622      return lv;      ico[1] = LoadIcon (glob_hinst, (LPCTSTR)IDI_KEYPAIR);
623  } /* keylist_load */      listview_set_image_list (lv, 22, 14, ico, 2);
624        listview_del_all_items (lv);
625    
626  int      *r_lv = lv;
627  keylist_reload( listview_ctrl_t lv, gpgme_keycache_t pubkc, int mode, int sortby )      return 0;
628  {  }
629      listview_del_all( lv );  
630      keylist_load_keycache( lv, mode, pubkc, NULL );  
631      keylist_sort( lv, sortby );  static void
632      return 0;  keylist_load_keycache (listview_ctrl_t lv, int mode,
633  } /* keylist_reload */                         gpg_keycache_t pubkc, gpg_keycache_t seckc)
634    {
635        gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
636  void      gpgme_key_t key, skey;
637  keylist_delete( listview_ctrl_t lv )      struct keycache_s *c;
638  {      const char *keyid;
639      if( lv ) {  
640          listview_release( lv );      if (pubkc && seckc) {
641      }          gpg_keycache_rewind (pubkc);
642  } /* keylist_delete */          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 int                  keylist_add_key (lv, mode, c, key);
646  find_secret_key( gpgme_key_t key )          }      
647  {      }
648      const char * keyid;      else if (pubkc) {
649      gpgme_key_t skey;            gpg_keycache_rewind (pubkc);
650            while (!err) {    
651      keyid = key->subkeys->keyid;              err = gpg_keycache_next_key2 (pubkc, 0, &c, &key);
652      if (!keyid)              if (!err)
653          return 0;                  keylist_add_key (lv, mode, c, key);
654      get_seckey (keyid, &skey);          }
655      return skey? 1 : 0;      }
656  } /* find_secret_key */  }
657    
658    
659  static int  /* Load the list view @ctrl with the keys from the cache.
660  do_addkey (listview_ctrl_t lv, gpgme_key_t key, int uididx, int keyidx, int list)     Return value: list view context on success. */
661  {      listview_ctrl_t
662      LV_ITEM lvi;  keylist_load (HWND ctrl, gpg_keycache_t pubkc, gpg_keycache_t seckc,
663      gpgme_user_id_t u;                int mode, int sortby)
664      gpgme_subkey_t k;  {    
665      char fmt[128];      listview_ctrl_t lv;
666      const char *attr;      int rc = 0;    
667      u32 key_attr;  
668      int idx = 0;          rc = keylist_build (&lv, ctrl, mode);
669        if (rc)
670      /* we check the pubkey algorithm here to make sure that no ElGamal          return NULL;            
671         sign+encrypt key is used in _any_ mode */      keylist_load_keycache (lv, mode, pubkc, seckc);
672      if (list != 1 && key->subkeys->pubkey_algo == GPGME_PK_ELG) {      keylist_sort (lv, sortby);
673          log_debug ("ElGamal (E+S) key found: %s (%s)\n",      if (mode & KEYLIST_ENCRYPT_MIN)
674                      key->uids->name, key->subkeys->keyid);          keylist_add_groups (lv);
675          return 0;      return lv;
676      }      }
677    
678            
679      if (listview_add_item2 (lv, " ", (void *)key))        /* Reload the given key list control @lv. */
680          return WPTERR_GENERAL;  int
681            keylist_reload (listview_ctrl_t lv, gpg_keycache_t pubkc, int mode, int sortby)
682      attr = key->uids->uid;  {
683      memset( &lvi, 0, sizeof lvi );      listview_del_all_items (lv);
684      lvi.mask = LVIF_TEXT | LVIF_PARAM;      keylist_load_keycache (lv, mode, pubkc, NULL);
685      lvi.pszText = (char *)attr;      keylist_sort (lv, sortby);
686      lvi.lParam = (LPARAM )key;      return 0;
687      if( ListView_SetItem( lv->ctrl, &lvi ) == FALSE )    }
688          return WPTERR_GENERAL;  
689            
690      if( uididx == -1 ) { /* request the primary user-id of the key. */  void
691          attr = key->uids->uid;  keylist_delete (listview_ctrl_t lv)
692          uididx = 0;  {
693      }      if (lv) {
694      else {          listview_release (lv);
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);  
699          attr = key->uids->uid;  /* Return if there is a secret for @key.
700      }     0 means success. */
701      if( attr == NULL || strlen( attr ) < 5 ) { /* normal userids are >= 5 chars */  static int
702          attr = _("Invalid User ID");  find_secret_key (gpgme_key_t key)
703          listview_add_sub_item( lv, 0, idx++, attr );  {
704      }        const char *keyid;
705      else {      winpt_key_s skey;
706          char * uid = utf8_to_wincp (attr, strlen (attr));      
707          if (uid) {      memset (&skey, 0, sizeof (skey));
708              listview_add_sub_item( lv, 0, idx++, uid );      keyid = key->subkeys->keyid;
709              free (uid);      if (!keyid)
710          }          return 0;
711      }      winpt_get_seckey (keyid, &skey);
712      k = get_nth_key (key, keyidx);      if (skey.ext && skey.ext->gloflags.divert_to_card)
713      if( k && k->keyid ) {          return 2;
714          _snprintf( fmt, sizeof fmt -1, "0x%s", k->keyid + 8 );      return skey.ctx? 1 : 0;
715          listview_add_sub_item( lv, 0, idx++, fmt );  }
716      }  
717      if (list > 0) {  
718          attr = find_secret_key (key)? "pub/sec" : "pub";  static int
719          if (strchr( attr, '/')) {  do_addkey (listview_ctrl_t lv, struct keycache_s *ctx, gpgme_key_t key,
720              struct winpt_key_s k;             int uididx, int keyidx, int list)
721              winpt_get_seckey (key->subkeys->keyid, &k);  {    
722              if (k.ext->gloflags.divert_to_card)      LV_ITEM lvi;
723                  attr = "pub/crd";      gpgme_user_id_t u;
724          }      gpgme_subkey_t k;
725          listview_add_sub_item( lv, 0, idx++, attr );      char fmt[128], *p;
726      }      const char *attr;
727      if (lv->cols >= 2) {      u32 key_attr;
728          attr = get_key_size (key, list == -1? keyidx+1 : 0);      int idx = 0;    
729          if (attr)  
730              listview_add_sub_item (lv, 0, idx++, attr);      /* we check the pubkey algorithm here to make sure that no ElGamal
731      }         sign+encrypt key is used in _any_ mode */
732      if (lv->cols >= 3) {      if (list != 1 && key->subkeys->pubkey_algo == GPGME_PK_ELG) {
733          attr = get_key_algo (key, list == -1? keyidx+1 : 0);          log_debug ("ElGamal (E+S) key found: %s (%s)\n",
734          if (attr)                     key->uids->name, key->subkeys->keyid);
735              listview_add_sub_item( lv, 0, idx++, attr);          return 0;
736      }      }
737      if( lv->cols >= 4 ) {  
738          char * status = get_key_status( key, uididx, list > 0? 1 : 0 );      if (listview_add_item2 (lv, " ", (void *)ctx))
739          if (!status)          return WPTERR_GENERAL;
740              return WPTERR_GENERAL;  
741          listview_add_sub_item( lv, 0, idx++, status );      attr = ctx->uids->uid;
742          free_if_alloc( status );      memset (&lvi, 0, sizeof lvi);
743      }      lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
744      if (lv->cols >= 5) {      lvi.pszText = (char *)attr;
745          const char * s = get_key_trust (key, uididx, list > 0? 1 : 0);      lvi.iImage = find_secret_key (key)? 1 : 0;
746          listview_add_sub_item (lv, 0, idx++, s);      lvi.lParam = (LPARAM )ctx;
747      }      if (ListView_SetItem (lv->ctrl, &lvi) == FALSE)
748      if( lv->cols >= 6 ) {          return WPTERR_GENERAL;
749          k = get_nth_key (key, keyidx);          
750          key_attr = k->timestamp;      if (uididx == -1) { /* request the primary user-id of the key. */
751          if( key_attr ) {          attr = ctx->uids->uid;
752              attr = get_key_created (key_attr);          uididx = 0;
753              listview_add_sub_item( lv, 0, idx++, attr );      }
754          }            else {
755      }          u = get_nth_userid (key, uididx);
756            if (!u || u->revoked || uididx < 0)
757      return 0;              uididx = 0;
758  } /* do_addkey */          u = get_nth_userid (key, uididx);
759            attr = u->uid;
760        }
761  void      if (attr == NULL || strlen (attr) < 5) { /* normal userids are > 5 chars */
762  keylist_upd_key (listview_ctrl_t lv, int pos, gpgme_key_t key)          attr = _("Invalid User ID");
763  {          listview_add_sub_item (lv, 0, idx++, attr);
764      const char *s;      }  
765      char tmp[32];      else        
766            listview_add_sub_item (lv, 0, idx++, attr);
767      listview_set_item2 (lv, pos, (void *)key);      k = get_nth_key (key, keyidx);
768      /* the only mode we support is KYLIST_LIST in the Key Manager */      if (k && k->keyid) {
769                _snprintf (fmt, sizeof fmt -1, "0x%s", k->keyid + 8);
770      s = key->uids->uid;          listview_add_sub_item (lv, 0, idx++, fmt);
771      if (s)      }
772          listview_add_sub_item (lv, pos, 0, s);      if (list > 0) {
773            key_attr = find_secret_key (key);
774      s = key->subkeys->keyid;          if (!key_attr)
775      if (s) {              attr = "pub";
776          sprintf (tmp, "0x%s", s+8);          else
777          listview_add_sub_item (lv, pos, 1, tmp);              attr = key_attr == 1? "pub/sec" : "pub/crd";
778      }          listview_add_sub_item (lv, 0, idx++, attr);
779        }
780      s = find_secret_key (key)? "pub/sec" : "pub";      if (lv->cols >= 2) {
781      listview_add_sub_item (lv, pos, 2, s);          attr = get_key_size (key, list == -1? keyidx+1 : 0);
782            if (attr)
783      s = get_key_size (key, 0);              listview_add_sub_item (lv, 0, idx++, attr);
784      if (s)      }
785          listview_add_sub_item (lv, pos, 3, s);      if (lv->cols >= 3) {
786            attr = get_key_algo (key, list == -1? keyidx+1 : 0);
787      s = get_key_algo (key, 0);          if (attr)
788      if (s)              listview_add_sub_item( lv, 0, idx++, attr);
789          listview_add_sub_item (lv, pos, 4, s);      }
790        if (lv->cols >= 4) {
791      s = get_key_status (key, 0, 1);          p = get_key_status( key, uididx, list > 0? 1 : 0 );
792      if (s)          if (!p)
793          listview_add_sub_item (lv, pos, 5, s);              return WPTERR_GENERAL;
794            listview_add_sub_item (lv, 0, idx++, p);
795      s = get_key_trust (key, 0, 1);          free_if_alloc (p);
796      if (s)      }
797          listview_add_sub_item (lv, pos, 6, s);      if (lv->cols >= 5) {
798            attr = get_key_trust (key, uididx, list > 0? 1 : 0);
799      long t = key->subkeys->timestamp;          listview_add_sub_item (lv, 0, idx++, attr);
800      s = get_key_created (t);      }
801      if (s)      if( lv->cols >= 6 ) {
802          listview_add_sub_item (lv, pos, 7, s);          k = get_nth_key (key, keyidx);
803  }          key_attr = k->timestamp;
804            if( key_attr ) {
805                attr = get_key_created (key_attr);
806  int              listview_add_sub_item( lv, 0, idx++, attr );
807  keylist_add_key (listview_ctrl_t lv, int mode, gpgme_key_t key)          }      
808  {      }
809      int uids, rc = 0, i, n = 0;  
810      gpgme_subkey_t k;      return 0;
811    }
812      for (k=key->subkeys, i = 0; i < count_subkeys (key); i++, k=k->next) {  
813          if (k->invalid) {  
814              log_debug ("keylist_add_key: invalid key %s\n", key->uids->name);  /* Update a single column @col but for each element in the
815              continue; /* Don't use invalid keys */     listview @lv. */
816          }  void
817    keylist_upd_col (listview_ctrl_t lv, int col)
818          if (mode & KEYLIST_ALL) {  {
819              uids = count_userids (key);      gpgme_key_t key;
820              rc = do_addkey (lv, key, uids, i, 0);      const char *s;
821              if( rc )      char buf[32], *p;
822                  return rc;      int i;
823          }  
824          else if (mode & KEYLIST_LIST)      for (i=0; i < listview_count_items (lv, 0); i++) {
825              return do_addkey (lv, key, -1, i, 1);          key = km_get_key_ptr (lv, i, NULL);
826          else if (mode & KEYLIST_ENCRYPT) {          if (!key)
827              if (k->can_encrypt && key_is_useable (k)) {              continue;
828                  if (mode & KEYLIST_FLAG_FILE) {          switch (col) {
829                      rc = do_addkey (lv, key, -1, i, -1);          case KM_COL_KEYID:
830                      if (rc)              _snprintf (buf, sizeof (buf)-1, "0x%s", key->subkeys->keyid+8);
831                          return rc;              listview_add_sub_item (lv, i, col, buf);
832                  }              break;
833                  else {  
834                      for( uids = 0;  uids < count_userids (key); uids++ ) {          case KM_COL_CIPHER:
835                          rc = do_addkey( lv, key, uids, i, -1 );              s = get_key_algo (key, 0);
836                          if( rc )              listview_add_sub_item (lv, i, col, s);
837                              return rc;              break;
838                      }  
839                  }          case KM_COL_TYPE:
840              }              s = find_secret_key (key)? "pub/sec" : "pub";
841          }              listview_add_sub_item (lv, i, col, s);
842          else if (mode & KEYLIST_ENCRYPT_MIN) {              break;
843              if( k->can_encrypt && key_is_useable (k))  
844              {          case KM_COL_CREAT:
845                  rc = do_addkey (lv, key, -1, i, -1);              s = get_key_created (key->subkeys->timestamp);
846                  return rc;              listview_add_sub_item (lv, i, col, s);
847              }              break;
848          }        
849          else if (mode & KEYLIST_SIGN) {          case KM_COL_DESC:
850              if ( k->can_sign              p = get_key_desc (key);
851                  && find_secret_key( key )              listview_add_sub_item (lv, i, col, p);
852                  && key_is_useable (k))              free_if_alloc (p);
853              {              break;
854                  rc = do_addkey (lv, key, -1, i, -1);          }
855                  if( rc )      }
856                      return rc;    }
857              }  
858          }        
859      }  /* Update the listview item at position @pos with the data from
860       the key @key. */
861      return rc;    void
862  } /* keylist_add_key */  keylist_upd_key (listview_ctrl_t lv, int pos,
863                     struct keycache_s *ctx, gpgme_key_t key)
864    {
865  int      const char *s;
866  keylist_sort (listview_ctrl_t lv, int sortby)      char *p;
867  {            char tmp[32];
868      return listview_sort_items( lv, sortby, keylist_cmp_cb );  
869  } /* keylist_sort */      listview_set_item2 (lv, pos, (void *)ctx);
870        /* the only mode we support is KEYLIST_LIST in the Key Manager */
871        
872  static int      s = ctx->uids->uid;
873  key_check_validity (const char *validity)      if (s)
874  {              listview_add_sub_item (lv, pos, KM_COL_UID, s);
875      if (strstr (validity, "Unknown")  
876          || strstr (validity, "Undefined")      s = key->subkeys->keyid;
877          || strstr (validity, "Never"))      if (s) {
878          return 0;            sprintf (tmp, "0x%s", s+8);
879      return 1;          listview_add_sub_item (lv, pos, KM_COL_KEYID, tmp);
880  } /* key_check_validity */      }
881    
882        s = find_secret_key (key)? "pub/sec" : "pub";
883  gpgme_key_t*      listview_add_sub_item (lv, pos, KM_COL_TYPE, s);
884  keylist_get_recipients (listview_ctrl_t lv, int *r_force_trust, int *r_count)  
885  {      s = get_key_size (key, 0);
886      int count = 0, force_trust = 0;      if (s)
887      int n, j, ka_pos = 0, rc = 0;          listview_add_sub_item (lv, pos, KM_COL_SIZE, s);
888      int k_pos=0;  
889      char keyid[32], valid[32], id[100];      s = get_key_algo (key, 0);
890      key_array_s *ka = NULL;      if (s)
891      gpgme_key_t *keybuf;          listview_add_sub_item (lv, pos, KM_COL_CIPHER, s);
892    
893      n = listview_count_items( lv, 0 );      p = get_key_status (key, 0, 1);
894      ka = key_array_new( n );      if (p) {
895      if ( !ka )          listview_add_sub_item (lv, pos, KM_COL_VALID, p);
896          BUG (NULL);          free_if_alloc (p);
897        }
898      keybuf = (gpgme_key_t*)calloc (n, sizeof (gpgme_key_t));  
899      if (!keybuf)      s = get_key_trust (key, 0, 1);
900          BUG (NULL);      if (s)
901                    listview_add_sub_item (lv, pos, KM_COL_TRUST, s);
902      for( j = 0; j < n; j++ ) {  
903          if( listview_get_item_state( lv, j ) || n == 1 ) {      long t = key->subkeys->timestamp;
904              listview_get_item_text( lv, j, 1, keyid, sizeof keyid - 1 );                              s = get_key_created (t);
905              listview_get_item_text( lv, j, 4, valid, sizeof valid -1 );      if (s)
906              listview_get_item_text( lv, j, 0, id, sizeof id-1 );          listview_add_sub_item (lv, pos, KM_COL_CREAT, s);
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 );  
910                  if( rc )  int
911                      force_trust++;  keylist_add_key (listview_ctrl_t lv, int mode,
912              }*/                   struct keycache_s *ctx, gpgme_key_t key)
913              if( !key_check_validity( valid )  {
914                      && !key_array_search( ka, ka_pos, keyid ) ) {      int uids, rc = 0, i;
915                  char *warn = new char[512+strlen (id) + 1];      gpgme_subkey_t k;
916                  if (!warn)  
917                      BUG (0);      /* if the entire key is disabled, just return. */
918                  sprintf (warn,      if (key->disabled && !(mode & KEYLIST_LIST))
919                      _("It is NOT certain that the key belongs to the person\n"          return 0;
920                        "named in the user ID.  If you *really* know what you are\n"  
921                        "doing, you may answer the next question with yes\n"      for (k=key->subkeys, i = 0; i < count_subkeys (key); i++, k=k->next) {
922                        "\n"          if (k->invalid) {
923                        "Use \"%s\" anyway?"), id);              log_debug ("keylist_add_key: invalid key \"%s\"\n", key->uids->name);
924                  if (reg_prefs.always_trust)              continue; /* Don't use invalid keys */
925                      rc = IDYES;          }
926                  else  
927                      rc = msg_box (NULL, warn, _("Recipients"), MB_ERR_ASK);          if (mode & KEYLIST_ALL) {
928                  if (rc == IDYES) {              uids = count_userids (key);
929                      gpgme_key_t k;              rc = do_addkey (lv, ctx, key, uids, i, 0);
930                      get_pubkey (keyid, &k);              if (rc)
931                      keybuf[k_pos++] = k;                  return rc;
932                      force_trust++;          }
933                      ka[ka_pos].checked = 1;          else if (mode & KEYLIST_LIST)
934                      strcpy (ka[ka_pos++].keyid, keyid);              return do_addkey (lv, ctx, key, -1, i, 1);
935                      count++;          else if (mode & KEYLIST_ENCRYPT) {
936                  }              if (k->can_encrypt && key_is_useable (k)) {
937                  free_if_alloc (warn);                  if (mode & KEYLIST_FLAG_FILE) {
938              }                      rc = do_addkey (lv, ctx, key, -1, i, -1);
939              else {                      if (rc)
940                  gpgme_key_t k;                          return rc;
941                  listview_get_item_text( lv, j, 1, keyid, sizeof keyid -1 );                  }
942                  get_pubkey (keyid, &k);                  else {
943                  keybuf[k_pos++] = k;                      for (uids = 0;  uids < count_userids (key); uids++) {
944                  count++;                                  rc = do_addkey (lv, ctx, key, uids, i, -1);
945              }                          if (rc)
946          }                              return rc;
947      }                      }
948      key_array_release (ka);                  }
949      if (r_force_trust)              }
950          *r_force_trust = force_trust;          }
951      if (r_count)          else if (mode & KEYLIST_ENCRYPT_MIN) {
952          *r_count = count;              if( k->can_encrypt && key_is_useable (k))
953      return keybuf;              {
954  } /* keylist_get_recipients */                  rc = do_addkey (lv, ctx, key, -1, i, -1);
955                    return rc;
956                }
957  static int          }      
958  keylist_get_keyflags (const char *buf, size_t buflen)          else if (mode & KEYLIST_SIGN) {
959  {              if (k->can_sign
960      int c = 0, flags = 0;                  && find_secret_key (key)
961                    && key_is_useable (k)) {
962      if( *buf != '[' )                  rc = do_addkey (lv, ctx, key, -1, i, -1);
963          return KEYFLAG_NONE;                  if (rc)
964      while (buf && c != ']')                      return rc;  
965      {              }
966          c = *buf++;          }      
967          if (c == 'R')      }
968              flags |= KEYFLAG_REVOKED;  
969          if (c == 'E')      return rc;  
970              flags |= KEYFLAG_EXPIRED;  }
971          if (c == 'D')  
972              flags |= KEYFLAG_DISABLED;  
973      }  int
974    keylist_sort (listview_ctrl_t lv, int sortby)
975      return flags;  {
976  } /* keylist_get_keyflags */      return listview_sort_items (lv, sortby, keylist_cmp_cb);
977    }
978    
979  gpgme_key_t*  
980  keylist_enum_recipients (listview_ctrl_t lv,  int listype, int *r_count)  /* Check that the validity @validity is at least >= marginal. */
981  {  static int
982      gpgme_key_t* rset;  key_check_validity (gpgme_key_t key)
983      gpgme_key_t k;  {
984      int i, n, id, k_pos=0;      gpgme_user_id_t u;
985      char keyid[32], t[128], t2[128];  
986        for (u=key->uids; u; u =u->next) {
987      n = listview_count_items( lv, 0 );          if (u->validity >= GPGME_VALIDITY_MARGINAL)
988      if (!n)              return -1;
989          return 0;      }
990      rset = (gpgme_key_t*)calloc (n, sizeof (gpgme_key_t));  
991      if (!rset)      return 0;
992          BUG (NULL);  }
993      for( i = 0; i < n; i++ ) {  
994          if( !listview_get_item_state( lv, i ) )  
995              continue;  /* Extract all selected recipients from the list @lv and return them
996          listview_get_item_text( lv, i, 1, keyid, sizeof keyid - 1 );     as a vector. @r_force_trust is >= 1 if one of the recipients is not
997          switch( listype ) {     fully trusted. @r_count returns the number of selected keys.
998          case KEYLIST_LIST:     Return value: the key list on success, NULL otherwise. */
999              listview_get_item_text( lv, i, 5, t, sizeof t - 1 );  gpgme_key_t*
1000              if( keylist_get_keyflags( t, strlen( t ) ) & KEYFLAG_REVOKED ) {  keylist_get_recipients (listview_ctrl_t lv, int *r_force_trust, int *r_count)
1001                  _snprintf( t2, sizeof t2 -1,  {
1002                              _("KeyID %s.\nDo you really want to export a revoked key?"), keyid );      key_array_s *ka = NULL;
1003                  id = msg_box( lv->ctrl, t2, _("Recipients"), MB_INFO|MB_YESNO );      keycache_s *c;
1004                  if( id == IDNO )      gpgme_key_t *keybuf, key;
1005                      continue;                int count = 0, force_trust = 0;
1006              }      int n, j, ka_pos = 0, rc = 0;
1007              break;      int k_pos=0;
1008          }  
1009          get_pubkey (keyid, &k);      n = listview_count_items (lv, 0);
1010          rset[k_pos++] = k;      
1011      }      ka = key_array_new (n);
1012      if (r_count)      if (!ka)
1013          *r_count = k_pos;          BUG (NULL);
1014      return rset;  
1015  } /* keylist_enum_recipients */      keybuf = (gpgme_key_t*)calloc (n+1, sizeof (gpgme_key_t));
1016        if (!keybuf)
1017            BUG (NULL);
1018  void          
1019  seclist_destroy (keylist_t * list)      for (j = 0; j < n; j++) {
1020  {          if (listview_get_item_state (lv, j) || n == 1) {
1021      keylist_t l2;              key = km_get_key_ptr (lv, j, &c);
1022      while (*list) {              if (!key)
1023          l2 = (*list)->next;                  BUG (0);
1024          safe_free (*list);              if (!key_check_validity (key) &&
1025          *list = l2;                      !key_array_search (ka, ka_pos, key->subkeys->keyid)) {
1026      }                  char *warn = new char[512+strlen (c->uids->uid) + 1];
1027      list = NULL;                  if (!warn)
1028  } /* seclist_destroy */                      BUG (0);
1029                    sprintf (warn,
1030                        _("It is NOT certain that the key belongs to the person\n"
1031  void                        "named in the user ID.  If you *really* know what you are\n"
1032  seclist_init (HWND dlg, int ctlid, int flags, keylist_t * ret_list)                        "doing, you may answer the next question with yes\n"
1033  {                            "\n"
1034      gpgme_keycache_t kc = NULL;                        "Use \"%s\" anyway?"), c->uids->uid);
1035      gpgme_key_t key = NULL;                  if (reg_prefs.always_trust)
1036      HWND kb;                      rc = IDYES;
1037      keylist_t list=NULL, l, l2;                      else
1038      long pos = 0;                      rc = msg_box (NULL, warn, _("Recipients"), MB_ERR_ASK);
1039                    if (rc == IDYES) {
1040      SendDlgItemMessage (dlg, ctlid, CB_RESETCONTENT, 0, 0);                      keybuf[k_pos++] = key;
1041      kb = GetDlgItem (dlg, ctlid);                      force_trust++;
1042      kc = keycache_get_ctx (0);                      ka[ka_pos].checked = 1;
1043      if (!kc)                      strcpy (ka[ka_pos++].keyid, key->subkeys->keyid);
1044          BUG (0);                      count++;
1045      gpgme_keycache_rewind (kc);                  }
1046                        free_if_alloc (warn);
1047      while (!gpgme_keycache_next_key (kc, 1, &key)) {              }
1048          char * inf = NULL, * uid = NULL;              else {
1049          const char * id;                  keybuf[k_pos++] = key;
1050          const char * keyid;                  count++;        
1051          int algo;              }
1052          size_t size = 0;          }
1053        }
1054          if (flags & KEYLIST_FLAG_SHORT)      key_array_release (ka);
1055              id = key->uids->name;      if (r_force_trust)
1056          else          *r_force_trust = force_trust;
1057              id = key->uids->uid;      if (r_count)
1058          keyid = key->subkeys->keyid;          *r_count = count;
1059          algo = key->subkeys->pubkey_algo;      return keybuf;
1060          if (!id || !keyid)  }
1061              continue; /* fixme: error? */        
1062          if (!key_is_useable (key->subkeys))  
1063              continue;  static int
1064    keylist_get_keyflags (gpgme_key_t key)
1065          uid = utf8_to_wincp (id, strlen (id));  {
1066          size = strlen( uid ) + strlen( keyid ) + 32;      int flags = KEYFLAG_NONE;
1067          inf = new char[size+1];  
1068          if( !inf )      if (key->revoked)
1069              BUG( NULL );          flags |= KEYFLAG_REVOKED;
1070          _snprintf (inf, size, _("%s (%s/0x%s)"), uid,      if (key->expired)
1071                     get_key_pubalgo (key->subkeys->pubkey_algo), keyid + 8);          flags |= KEYFLAG_EXPIRED;
1072          combox_add_string (kb, inf);      if (key->disabled)
1073          free_if_alloc (inf);          flags |= KEYFLAG_DISABLED;
1074          free (uid);  
1075          l = (struct keylist_s *)calloc (1, sizeof * l);      return flags;
1076          if (!l)  }
1077              BUG (0);  
1078          l->key = key;  
1079          if (!list)  gpgme_key_t*
1080              list = l;  keylist_enum_recipients (listview_ctrl_t lv,  int listype, int *r_count)
1081          else {  {
1082              for( l2 = list; l2->next; l2 = l2->next )      struct keycache_s *c;
1083                  ;      gpgme_key_t *rset;
1084              l2->next = l;      gpgme_key_t key;
1085          }      int i, n, id, k_pos=0;
1086      }  
1087      for( pos = 0, l2=list; pos < SendMessage( kb, CB_GETCOUNT, 0, 0 ); pos++, l2=l2->next )      n = listview_count_items (lv, 0);
1088          SendMessage( kb, CB_SETITEMDATA, pos, (LPARAM)(DWORD)l2->key );      if (!n)
1089      SendMessage( kb, CB_SETCURSEL, 0, 0 );          return 0;
1090      *ret_list = list;      rset = (gpgme_key_t*)calloc (n+1, sizeof (gpgme_key_t));
1091  } /* seclist_init */      if (!rset)
1092                    BUG (NULL);
1093        for (i = 0; i < n; i++) {
1094  int          if (!listview_get_item_state (lv, i))
1095  seclist_select_key (HWND dlg, int ctlid, gpgme_key_t * ret_key)              continue;
1096  {          key = km_get_key_ptr (lv, i, &c);
1097      int pos;          switch (listype) {
1098      DWORD k = 0;          case KEYLIST_LIST:
1099                if (keylist_get_keyflags (key) & KEYFLAG_REVOKED) {
1100      pos = SendDlgItemMessage( dlg, ctlid, CB_GETCURSEL, 0, 0 );                  id = printf_box (_("Recipients"), MB_INFO|MB_YESNO,
1101      if( pos == CB_ERR ) {                  _("KeyID %s.\nDo you really want to export a revoked key?"),
1102          msg_box( dlg, _("No key was selected."), _("Secret Key List"), MB_ERR );                                   c->uids->uid);
1103          *ret_key = NULL;                  if (id == IDNO)
1104      }                      continue;
1105      else {              }
1106          k = SendDlgItemMessage( dlg, ctlid, CB_GETITEMDATA, pos, 0 );              break;
1107          *ret_key = (gpgme_key_t)k;          }
1108      }          rset[k_pos++] = key;
1109      return k? 0 : -1;      }
1110  } /* seclist_dlg_proc */      if (r_count)
1111            *r_count = k_pos;
1112        return rset;
1113    }
1114    
1115    
1116    void
1117    seclist_destroy (keylist_t *list)
1118    {
1119        keylist_t l2;
1120        while (*list) {
1121            l2 = (*list)->next;
1122            safe_free (*list);
1123            *list = l2;    
1124        }
1125        list = NULL;
1126    }
1127    
1128    
1129    void
1130    seclist_init (HWND dlg, int ctlid, int flags, keylist_t * ret_list)
1131    {    
1132        gpg_keycache_t kc = NULL;
1133        gpgme_key_t key = NULL;
1134        HWND kb;
1135        keylist_t list=NULL, l, l2;    
1136        long pos = 0;
1137    
1138        SendDlgItemMessage (dlg, ctlid, CB_RESETCONTENT, 0, 0);
1139        kb = GetDlgItem (dlg, ctlid);
1140        kc = keycache_get_ctx (0);
1141        if (!kc)
1142            BUG (0);
1143        gpg_keycache_rewind (kc);
1144        
1145        while (!gpg_keycache_next_key (kc, 1, &key)) {
1146            char *inf = NULL, *uid = NULL;
1147            const char *id;
1148            const char *keyid;
1149            int algo;
1150            size_t size = 0;
1151    
1152            if (flags & KEYLIST_FLAG_SHORT)
1153                id = key->uids->name;
1154            else
1155                id = key->uids->uid;
1156            keyid = key->subkeys->keyid;
1157            algo = key->subkeys->pubkey_algo;
1158            if (!id || !keyid)
1159                continue;
1160            if (key->disabled || !key_is_useable (key->subkeys))
1161                continue;
1162    
1163            uid = utf8_to_native (id);
1164            size = strlen (uid) + strlen (keyid) + 32;
1165            inf = new char[size+1];
1166            if (!inf)
1167                BUG (NULL);
1168            _snprintf (inf, size, "%s (%s/0x%s)", uid,
1169                       get_key_pubalgo (key->subkeys->pubkey_algo), keyid + 8);
1170            combox_add_string (kb, inf);
1171            free_if_alloc (inf);
1172            free (uid);
1173            l = (struct keylist_s *)calloc (1, sizeof * l);
1174            if (!l)
1175                BUG (0);
1176            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.24  
changed lines
  Added in v.208

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26