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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26