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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26