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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26