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

Legend:
Removed from v.32  
changed lines
  Added in v.273

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26