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

Legend:
Removed from v.22  
changed lines
  Added in v.201

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26