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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26