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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26