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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26