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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26