/[winpt]/trunk/Src/wptKeyManager.cpp
ViewVC logotype

Diff of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 20 by twoaday, Wed Jul 27 11:17:22 2005 UTC revision 77 by twoaday, Mon Nov 14 15:01:01 2005 UTC
# Line 1  Line 1 
1  /* wptKeyManager.cpp - Handy functions for the Key Manager dialog  /* wptKeyManager.cpp - Handy functions for the Key Manager dialog
2   *      Copyright (C) 2001-2005 Timo Schulz   *      Copyright (C) 2001-2005 Timo Schulz
3   *   *      Copyright (C) 2005 g10 Code GmbH
4   * This file is part of WinPT.   *
5   *   * This file is part of WinPT.
6   * WinPT is free software; you can redistribute it and/or   *
7   * modify it under the terms of the GNU General Public License   * WinPT is free software; you can redistribute it and/or
8   * as published by the Free Software Foundation; either version 2   * modify it under the terms of the GNU General Public License
9   * of the License, or (at your option) any later version.   * as published by the Free Software Foundation; either version 2
10   *     * of the License, or (at your option) any later version.
11   * WinPT is distributed in the hope that it will be useful,   *  
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * WinPT is distributed in the hope that it will be useful,
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * General Public License for more details.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   *   * General Public License for more details.
16   * You should have received a copy of the GNU General Public License   *
17   * along with WinPT; if not, write to the Free Software Foundation,   * You should have received a copy of the GNU General Public License
18   * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA   * along with WinPT; if not, write to the Free Software Foundation,
19   */   * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  #include <windows.h>   */
21  #include <commctrl.h>  #ifdef HAVE_CONFIG_H
22  #include <stdio.h>  #include <config.h>
23  #include <io.h>  #endif
24    
25  #include "../resource.h"  #include <windows.h>
26  #include "wptTypes.h"  #include <commctrl.h>
27  #include "wptW32API.h"  #include <stdio.h>
28  #include "wptVersion.h"  
29  #include "wptCommonCtl.h"  #include "gpgme.h"
30  #include "wptNLS.h"  #include "resource.h"
31  #include "wptErrors.h"  #include "wptTypes.h"
32  #include "wptGPG.h"  #include "wptW32API.h"
33  #include "wptContext.h"  #include "wptVersion.h"
34  #include "wptKeylist.h"  #include "wptCommonCtl.h"
35  #include "wptFileManager.h"  #include "wptNLS.h"
36  #include "wptDlgs.h"  #include "wptErrors.h"
37  #include "wptKeyserver.h"  #include "wptContext.h"
38  #include "wptKeyManager.h"  #include "wptGPG.h"
39  #include "wptKeylist.h"  #include "wptKeylist.h"
40  #include "wptHTTP.h"  #include "wptFileManager.h"
41    #include "wptDlgs.h"
42    #include "wptKeyserver.h"
43  static void  #include "wptKeyManager.h"
44  km_get_clip_info (const char *uid, char *buf, size_t buflen)  #include "wptKeylist.h"
45  {  #include "wptHTTP.h"
46      gpgme_key_t pk;  #include "wptKeyEdit.h"
47      unsigned long a, algo;  #include "wptImport.h"
48    #include "wptCrypto.h"
49      if (get_pubkey (uid, &pk))  
50          BUG (0);  
51        /* Return a user friendly key representation in @buf of
52      a = gpgme_key_get_ulong_attr (pk, GPGME_ATTR_CREATED, NULL, 0);     the key given by @keyid. */
53      algo = gpgme_key_get_ulong_attr (pk, GPGME_ATTR_ALGO, NULL, 0);  static void
54      _snprintf (buf, buflen-1,  key_get_clip_info (const char *keyid, char *buf, size_t buflen)
55                 "pub %04d%s/%s %s %s\r\n"  {
56                 "    Primary key fingerprint: %s\r\n",        gpgme_key_t pk;
57          gpgme_key_get_ulong_attr (pk, GPGME_ATTR_LEN, NULL, 0),  
58          gpgme_key_expand_attr (GPGME_ATTR_ALGO_SHORT, algo),      if (get_pubkey (keyid, &pk))
59          gpgme_key_get_string_attr (pk, GPGME_ATTR_KEYID, NULL, 0) + 8,            BUG (NULL);
60          gpgme_key_expand_attr (GPGME_ATTR_CREATED, a ),      _snprintf (buf, buflen-1,
61          gpgme_key_get_string_attr (pk, GPGME_ATTR_USERID, NULL, 0),                 "pub %04d%s/%s %s %s\r\n"
62          get_key_fpr (pk));                 "    Primary key fingerprint: %s\r\n",
63  }                 pk->subkeys->length,
64                   get_key_pubalgo (pk->subkeys->pubkey_algo),
65                   pk->subkeys->keyid+8,
66  char*                 get_key_created (pk->subkeys->timestamp),
67  km_quote_uid (const char * uid)                 pk->uids->uid,
68  {                     get_key_fpr (pk));
69      char * q = new char[strlen (uid) + 4];  }
70      if (!q)  
71          BUG (NULL);  
72      _snprintf (q, strlen (uid) + 3, "\"%s\"", uid);  #if 0
73      return q;  /* Quoted the user-id given by @uid. If @uid is already
74  } /* km_quote_uid */     quoted @uid is returned without any modifications.
75       Return value: quoted @uid. */
76    char*
77  int  km_quote_uid (const char *uid)
78  km_check_for_seckey (listview_ctrl_t lv, int pos, int * utrust)  {    
79  {      char *q;
80      char t[32], t2[64];  
81      int type = 0;      if (*uid == '"' && uid[strlen (uid)-1] == '"')
82                return m_strdup (uid);
83      listview_get_item_text (lv, pos, 5, t, sizeof (t) - 1);      q = new char[strlen (uid) + 4];
84      listview_get_item_text (lv, pos, 2, t2, sizeof (t2) - 1);      if (!q)
85      if (!strcmp (t2, "pub/sec"))          BUG (NULL);
86          type = 1;      _snprintf (q, strlen (uid) + 3, "\"%s\"", uid);
87      else if (!strcmp (t2, "pub/crd"))      return q;
88          type = 2;  }
89      if (stristr (t, "ultimate") && utrust)  #endif
90          *utrust = 1;  
91      return type;  
92  } /* km_check_for_seckey */  /* Check if list view @lv contains a secret key at position @pos.
93       If utrust is valid, set it to 1 if the key is valid -1 otherwise.
94       Return value: 1 normal key, 2 smart card key. */
95  int  int
96  km_check_if_protected( listview_ctrl_t lv, int pos )  km_check_for_seckey (listview_ctrl_t lv, int pos, int *utrust)
97  {  {
98      gpgme_key_t key;      char t[32], t2[64];
99      char keyid[32];          int type = 0;
100            
101      listview_get_item_text( lv, pos, 1, keyid, sizeof keyid-1 );      if (utrust)
102      if( get_pubkey( keyid, &key ) )          *utrust = 0;
103          BUG( NULL );          listview_get_item_text (lv, pos, 5, t, DIM (t)-1);
104      return gpgme_key_get_ulong_attr( key, GPGME_ATTR_IS_PROTECTED, NULL, 0 );      listview_get_item_text (lv, pos, 2, t2, DIM (t2)-1);
105  } /* km_check_if_protected */      if (!strcmp (t2, "pub/sec"))
106            type = 1;
107        else if (!strcmp (t2, "pub/crd"))
108  int          type = 2;
109  km_check_key_status (listview_ctrl_t lv, int pos)      if ((strstr (t, "Expired") || strstr (t, "Revoked")) && utrust)
110  {          *utrust = -1;
111      char t[128];      else if (stristr (t, "Ultimate") && utrust)
112      int i = 1;          *utrust = 1;
113            return type;
114      listview_get_item_text( lv, pos, 5, t, sizeof t - 1 );  }
115      if( t[0] == '[' && t[1] == ']' )  
116          return 1;  
117      for( i = 0; t[i] != ']'; i++ ) {  /* Check if the key at position @pos is protected with a passwd. */
118          if( t[i] == 'E' )  int
119              msg_box(lv->ctrl, _("This key has expired!\n"  km_check_if_protected (listview_ctrl_t lv, int pos)
120                                  "Key check failed."), _("Key Manager"), MB_ERR );  {
121          else if( t[i] == 'R' )      gpgme_key_t key;
122              msg_box(lv->ctrl, _("This key has been revoked by its owner!\n"      winpt_key_s k;
123                                  "Key check failed."), _("Key Manager"), MB_ERR );  
124      }      key = (gpgme_key_t)listview_get_item2 (lv, pos);
125        if (!key)
126      return 0;          return 1; /* assume yes */
127  } /* km_check_key_status */      winpt_get_pubkey (key->subkeys->keyid, &k);
128        return k.is_protected;
129    }
130  int  
131  km_get_key_status( listview_ctrl_t lv, int pos )  
132  {  int
133      char t[128];  km_check_key_status (listview_ctrl_t lv, int pos)
134      int i, flags = 0;  {
135        int flags = km_get_key_status (lv, pos);
136      if( pos == -1 )      
137          return 0;      if (flags & KM_FLAG_EXPIRED) {
138      listview_get_item_text( lv, pos, 5, t, sizeof t-1 );          msg_box (lv->ctrl, _("This key has expired!\n"  
139      for( i = 0; t[i] != ']'; i++ ) {                               "Key check failed."), _("Key Manager"), MB_ERR);
140          if( t[i] == 'E' )          return -1;
141              flags |= KM_FLAG_EXPIRED;      }
142          if( t[i] == 'R' )      else if (flags & KM_FLAG_REVOKED) {
143              flags |= KM_FLAG_REVOKED;          msg_box (lv->ctrl, _("This key has been revoked by its owner!\n"
144          if( t[i] == 'D' )                               "Key check failed."), _("Key Manager"), MB_ERR);
145              flags |= KM_FLAG_DISABLED;          return -1;
146      }      }
147      return flags;  
148  } /* km_get_key_status */      return 0;
149    } /* km_check_key_status */
150    
151  int  
152  km_enable_disable_key (listview_ctrl_t lv, HWND dlg, int pos, int enable)  int
153  {  km_get_key_status (listview_ctrl_t lv, int pos)
154      gpgme_ctx_t ctx;  {
155      gpgme_editkey_t ek;      gpgme_key_t key;
156      gpgme_error_t err;      int flags = 0;
157      int edit_id;  
158      char keyid[32];      if (pos == -1)
159            return 0;
160      listview_get_item_text( lv, pos, 1, keyid, DIM (keyid)-1 );      key = (gpgme_key_t)listview_get_item2 (lv, pos);
161      err = gpgme_editkey_new( &ek );      if (key == NULL)
162      if( err )          return 0;
163          BUG( NULL );  
164      if( enable ) {      if (key->expired)
165          gpgme_editkey_enable_set (ek);          flags |= KM_FLAG_EXPIRED;
166          edit_id = GPGME_EDITKEY_ENABLE;      if (key->revoked)
167      }          flags |= KM_FLAG_REVOKED;
168      else {      if (key->disabled)
169          gpgme_editkey_disable_set (ek);          flags |= KM_FLAG_DISABLED;
170          edit_id = GPGME_EDITKEY_DISABLE;      return flags;
171      }  } /* km_get_key_status */
172      err = gpgme_new (&ctx);  
173      if( err )  
174          BUG( NULL );  /* Interface to enable or disable a key (@enable = 1 then enable).
175      gpgme_set_edit_ctx (ctx, ek, edit_id);     The key is retrieved from a list control @lv at the pos @pos. */
176      err = gpgme_op_editkey (ctx, keyid);  int
177      if( !err ) {  km_enable_disable_key (listview_ctrl_t lv, HWND dlg, int pos, int enable)
178          show_msg( dlg, 1500, _("Key status changed.") );  {
179          keycache_set_reload( 1 );      GpgKeyEdit *ke;
180      }      gpgme_error_t err;
181      else      char keyid[32];
182          msg_box( dlg, gpgme_strerror( err ), _("Key Manager"), MB_ERR );  
183        listview_get_item_text (lv, pos, 1, keyid, DIM (keyid)-1);
184      gpgme_release (ctx);  
185      gpgme_editkey_release (ek);      ke = new GpgKeyEdit (keyid);
186      return err? WPTERR_GENERAL : 0;      if (!ke)
187  } /* km_enable_disable_key */          BUG (NULL);
188    
189        err = enable? ke->enable () : ke->disable ();
190  int      if (!err) {
191  km_clip_export (HWND dlg, listview_ctrl_t lv)          show_msg (dlg, 1500, _("Key status changed."));
192  {          keycache_set_reload (1); /* XXX: set update flag */
193      gpgme_error_t err;      }
194      gpgme_recipients_t rset;      else
195      int rc, id = 0, n = 0;          msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
196            delete ke;
197      rset = keylist_enum_recipients (lv, KEYLIST_LIST);      return err? WPTERR_GENERAL : 0;
198      n = gpgme_recipients_count (rset);  }
199      if (!n) {  
200          msg_box (dlg, _("No key was selected for export."), _("Key Manager"), MB_ERR);  
201          rc = WPTERR_GENERAL;  
202          goto leave;  /* Create a string that contain all keyids from
203      }     the key list @rset separated by a space. */
204        char*
205      err = gpgme_op_clip_export (rset);  gpg_keylist_to_pattern (gpgme_key_t *rset, int n)
206      if (err) {  {
207          msg_box( dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);      char *p;
208          rc = WPTERR_GENERAL;      int i;
209          goto leave;  
210      }      if (!n)
211      if (n == 1) {          return NULL;
212          const char *s;      p = (char *)calloc (1, n*(16+1)+n+2);
213          char buf[256];      if (!p)
214          s = gpgme_recipients_get_name (rset, 0);          BUG (NULL);
215          km_get_clip_info (s, buf, 255);      for (i=0; i < n; i++) {
216          set_clip_text2 (NULL, buf, strlen (buf), 0);          strcat (p, rset[i]->subkeys->keyid);
217      }          strcat (p, " ");
218        }
219      show_msg (dlg, 1500, _("GnuPG Status: Finished"));      return p;
220        }
221  leave:  
222      gpgme_recipients_release (rset);  
223      return rc;  /* Export the keys given in @rset to the clipboard.
224  } /* km_clip_export */     Return value: 0 on success. */
225    static gpgme_error_t
226    gpg_clip_export (gpgme_key_t *rset, int n)
227  int  {
228  km_privkey_export( HWND dlg, listview_ctrl_t lv, const char *fname )      gpgme_error_t err = 0;
229  {      gpgme_ctx_t ctx = NULL;
230      gpgme_recipients_t rset;      gpgme_data_t keydata = NULL;
231      gpgme_data_t keydata;      char *patt=NULL;
232      gpgme_error_t err;      
233      gpgme_ctx_t ctx;      err = gpgme_new (&ctx);
234      size_t n = 0;      if (err)
235            return err;
236      rset = keylist_enum_recipients( lv, KEYLIST_LIST );      gpgme_set_armor (ctx, 1);          
237      n = gpgme_recipients_count( rset );      err = gpgme_data_new (&keydata);
238      if( !n ) {      if (err)
239          msg_box( dlg, _("No key was selected for export."), _("Key Manager"), MB_ERR );          goto leave;
240          return WPTERR_GENERAL;  
241      }      patt = gpg_keylist_to_pattern (rset, n);
242      if( n > 1 ) {      if (!patt) {
243          msg_box( dlg, _("Only one secret key can be exported."), _("Key Manager"), MB_ERR );          err = gpg_error (GPG_ERR_ENOMEM);
244          return 0; /* we checked this before, so we just quit */          goto leave;
245      }      }
246      err = gpgme_data_new( &keydata );  
247      if( err )      err = gpgme_op_export (ctx, patt, 0, keydata);
248          BUG( dlg );      if (err)
249      err = gpgme_new( &ctx );          goto leave;
250      if( err )  
251          BUG( dlg );      gpg_data_release_and_set_clipboard (keydata, 1);
252      gpgme_control( ctx, GPGME_CTRL_ARMOR, 1 );  
253      gpgme_control( ctx, GPGME_CTRL_WITH_SECRET_KEY, 1 );  leave:
254        if (patt)
255      err = gpgme_op_export( ctx, rset, keydata );          free (patt);
256      if( err ) {      gpgme_release (ctx);
257          msg_box( dlg, gpgme_strerror( err ), _("Key Manager"), MB_ERR );      return err;
258          goto leave;  }
259      }  
260    
261      log_box( _("Key Manager"), MB_OK,  /* Export the selected keys in @lv to the clipboard. */
262               _("Secret key successfully saved in '%s'."), fname );  int
263        km_clip_export (HWND dlg, listview_ctrl_t lv)
264  leave:  {
265      err = gpgme_data_release_and_set_file( keydata, fname );      gpgme_error_t err;
266      if( err )      gpgme_key_t *rset;
267          log_box( _("Key Manager"), MB_OK,      char buf[256];
268                   _("Could not save data to '%s'."), fname );      int n=0;
269      gpgme_release( ctx );      int rc=0;
270        
271      return (int)err;      rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);
272  } /* km_privkey_export */      if (!n) {
273            msg_box (dlg, _("No key was selected for export."), _("Key Manager"), MB_ERR);
274            rc = WPTERR_GENERAL;
275  int          goto leave;
276  km_file_export (HWND dlg, listview_ctrl_t lv, const char * fname)      }
277  {      
278      gpgme_recipients_t rset;      err = gpg_clip_export (rset, n);
279      gpgme_data_t keydata;            if (err) {
280      gpgme_error_t err;          msg_box( dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
281      gpgme_ctx_t ctx;          rc = WPTERR_GENERAL;
282            goto leave;
283      rset = keylist_enum_recipients( lv, KEYLIST_LIST );      }
284      if( !gpgme_recipients_count( rset ) ) {      if (n == 1) {
285          msg_box( dlg, _("No key was selected for export."), _("Key Manager"), MB_ERR );          key_get_clip_info (rset[0]->subkeys->keyid, buf, sizeof (buf)-1);
286          return WPTERR_GENERAL;          set_clip_text2 (NULL, buf, strlen (buf), 0);
287      }      }
288        
289      err = gpgme_data_new( &keydata );      show_msg (dlg, 1500, _("GnuPG Status: Finished"));
290      if( err )      
291          BUG( dlg );  leave:
292      err = gpgme_new( &ctx );      free (rset);
293      if( err )      return rc;
294          BUG( dlg );  } /* km_clip_export */
295      gpgme_control( ctx, GPGME_CTRL_ARMOR, 1 );  
296      gpgme_set_comment (ctx, "Generated by WinPT "PGM_VERSION);  
297        /* Export the selected secret key from @lv into @fname.
298      err = gpgme_op_export( ctx, rset, keydata );     It is only allowed to export a single secret key. */
299      if( err ) {  int
300          msg_box( dlg, gpgme_strerror( err ), _("Key Manager"), MB_ERR );  km_privkey_export (HWND dlg, listview_ctrl_t lv, const char *fname)
301          goto leave;  {
302      }      gpgme_key_t *rset;
303                gpgme_error_t err;
304      log_box( _("Key Manager"), MB_OK,      int n = 0;
305               _("Key(s) successfully saved in '%s'."), fname );  
306            rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);
307  leave:      if (!n) {
308      err = gpgme_data_release_and_set_file( keydata, fname );          msg_box (dlg, _("No key was selected for export."),
309      if( err )                   _("Key Manager"), MB_ERR);
310          log_box( _("Key Manager"), MB_OK,          return WPTERR_GENERAL;
311                   _("Could not save data to '%s'."), fname );          }
312      gpgme_release( ctx );      if (n > 1) {
313            msg_box (dlg, _("Only one secret key can be exported."),
314      return (int)err;                   _("Key Manager"), MB_ERR);
315  } /* km_file_export */          free (rset);
316            return 0; /* we checked this before, so we just quit */
317        }
318  static int  
319  extract_dash_escaped_key (void)      err = gpg_export_seckey (rset[0]->subkeys->keyid, fname);
320  {      if (err)
321      gpgme_data_t inp, plain;          msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
322      gpgme_error_t err;      else
323            log_box (_("Key Manager"), MB_OK,
324      err = gpgme_data_new_from_clipboard (&inp);                   _("Secret key successfully saved in '%s'."), fname);
325      if (err) {  
326          msg_box (NULL, gpgme_strerror( err ), _("Key Manager"), MB_ERR);      free (rset);
327          return -1;      return err? WPTERR_GENERAL : 0;
328      }  }
329      gpgme_data_extract_plaintext (inp, &plain);  
330      gpgme_data_release (inp);  
331      gpgme_data_release_and_set_clipboard (plain);  int
332    km_file_export (HWND dlg, listview_ctrl_t lv, const char * fname)
333      return 0;  {
334  } /* extract_dash_escaped_key */      gpgme_key_t *rset;
335        gpgme_data_t keydata;      
336        gpgme_error_t err;
337  int      gpgme_ctx_t ctx;
338  km_clip_import( HWND dlg )      char *patt;
339  {      int n;
340      gpgme_error_t err;  
341      gpgme_pgptype_t pgptype;      rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);
342      int id;      if (!n) {
343      int has_data = 0;          msg_box (dlg, _("No key was selected for export."),
344                         _("Key Manager"), MB_ERR);
345      if( !gpgme_clip_istext_avail( &has_data ) && !has_data ) {          return WPTERR_GENERAL;
346          msg_box( dlg, winpt_strerror( WPTERR_CLIP_ISEMPTY ), _("Key Manager"), MB_ERR );      }
347          return WPTERR_CLIP_ISEMPTY;      
348      }      err = gpgme_data_new (&keydata);
349      err = gpgme_clip_is_secured( &pgptype, &has_data );      if (err)
350      if( err )          BUG (NULL);
351          msg_box( dlg, gpgme_strerror( err ), _("Key Manager"), MB_ERR );      err = gpgme_new (&ctx);
352      if( !has_data ) {      if (err)
353          msg_box( dlg, _("No valid OpenPGP data found."), _("Key Manager"), MB_ERR );          BUG (NULL);
354          return WPTERR_GENERAL;      gpgme_set_armor (ctx, 1);
355      }  
356      if( !(pgptype & GPGME_PGP_PUBKEY) && !(pgptype & GPGME_PGP_SECKEY) ) {      /*gpgme_set_comment (ctx, "Generated by WinPT "PGM_VERSION);*/
357          msg_box( dlg, _("No valid OpenPGP keys found."), _("Key Manager"), MB_ERR );      patt = gpg_keylist_to_pattern (rset, n);
358          return WPTERR_GENERAL;      
359      }      err = gpgme_op_export( ctx, patt, 0, keydata);
360      if( pgptype & GPGME_PGP_DASH_ESCAPED ) {      if( err ) {
361          id = msg_box( dlg, _("The key you want to import is dash escacped.\n"          msg_box( dlg, gpgme_strerror( err ), _("Key Manager"), MB_ERR );
362                               "Do you want to extract the key?"),          goto leave;
363                        _("Key Manager"), MB_YESNO );      }
364          if( id == IDYES )          
365              extract_dash_escaped_key( );      log_box( _("Key Manager"), MB_OK,
366          else               _("Key(s) successfully saved in '%s'."), fname );
367              msg_box( dlg, _("Cannot import dash escaped OpenPGP keys."), _("Key Manager"), MB_INFO );      
368      }  leave:
369        err = gpg_data_release_and_set_file( keydata, fname );
370      dialog_box_param( glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,      if (err)
371                        clip_import_dlg_proc, NULL,          log_box (_("Key Manager"), MB_OK,
372                        _("Key Import"), IDS_WINPT_IMPORT );                   _("Could not save data to '%s'."), fname);
373        gpgme_release (ctx);
374      return 0;      free (patt);
375  } /* km_clip_import */      return (int)err;
376    } /* km_file_export */
377    
378  int  
379  km_http_import (HWND dlg, const char * url)  static int
380  {  extract_dash_escaped_key (void)
381      FILE * fp;  {
382      char * p;      gpgme_data_t inp, plain;
383      char tmpdir[500];      gpgme_error_t err;
384      http_hd_t hd;  
385      int statcode;      err = gpg_data_new_from_clipboard (&inp, 0);
386      int rc = 0;      if (err) {
387            msg_box (NULL, gpgme_strerror( err ), _("Key Manager"), MB_ERR);
388      if (strncmp (url, "http://", 7)) {          return -1;
389          log_box (_("Key Import HTTP"), MB_ERR, _("Invalid HTTP URL: %s"), url);      }
390          return WPTERR_GENERAL;      gpg_data_extract_plaintext (inp, &plain);
391      }      gpg_data_release_and_set_clipboard (plain, 0);
392        gpgme_data_release (inp);
393      GetTempPath (499, tmpdir);  
394      p = make_filename (tmpdir, "file_http", "tmp");      return 0;
395      if (!p)  } /* extract_dash_escaped_key */
396          BUG (0);  
397      fp = fopen (p, "wb");  
398      if (fp == NULL) {  /* Import keys from the clipboard. */
399          free_if_alloc (p);  int
400          log_box (_("Key Import HTTP"), MB_ERR, "%s: %s", p, winpt_strerror (WPTERR_FILE_CREAT));  km_clip_import (HWND dlg)
401          return WPTERR_FILE_CREAT;  {
402      }      gpgme_error_t err;
403      /* parse URL */      int pgptype;
404      rc = http_send_request2 (url, &hd);      int id;
405      if (!rc)      int has_data = 0;
406          rc = http_parse_response (hd, &statcode);      
407      if (!rc)      if (!gpg_clip_istext_avail (&has_data) && !has_data) {
408          rc = http_parse_data (hd, fp);          msg_box( dlg, winpt_strerror (WPTERR_CLIP_ISEMPTY), _("Key Manager"), MB_ERR);
409      http_hd_free (hd);          return WPTERR_CLIP_ISEMPTY;
410      fclose (fp);      }
411      if (rc) {      err = gpg_clip_is_secured (&pgptype, &has_data);
412          free_if_alloc (p);      if (err)
413          msg_box (dlg, http_strerror (rc), _("Key Import HTTP"), MB_ERR);          msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
414          return WPTERR_GENERAL;      if (!has_data) {
415      }          msg_box (dlg, _("No valid OpenPGP data found."), _("Key Manager"), MB_ERR);
416      km_file_import (dlg, p);          return WPTERR_GENERAL;
417      free_if_alloc (p);      }
418      return 0;      if (!(pgptype & PGP_PUBKEY) && !(pgptype & PGP_SECKEY)) {
419  }          msg_box (dlg, _("No valid OpenPGP keys found."), _("Key Manager"), MB_ERR);
420            return WPTERR_GENERAL;
421  int      }
422  km_file_import( HWND dlg, const char * fname )      if (pgptype & PGP_DASH_ESCAPED) {
423  {          id = msg_box (dlg, _("The key you want to import is dash escacped.\n"
424      gpgme_data_t keydata = NULL;                               "Do you want to extract the key?"),
425      gpgme_ctx_t ctx;                        _("Key Manager"), MB_YESNO);
426      gpgme_error_t err;          if (id == IDYES)
427      fm_state_s fm_stat;              extract_dash_escaped_key ();
428      int import_res[14];          else
429                    msg_box (dlg, _("Cannot import dash escaped OpenPGP keys."),
430      memset( &fm_stat, 0, sizeof fm_stat );                       _("Key Manager"), MB_INFO);
431      fm_stat.opaque = m_strdup( fname );      }
432        
433      dialog_box_param( glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,      dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
434                        file_import_dlg_proc, (LPARAM)&fm_stat,                        clip_import_dlg_proc, 0,
435                        _("File Import"), IDS_WINPT_IMPORT );                        _("Key Import"), IDS_WINPT_IMPORT);
436      if( fm_stat.cancel == 1 )  
437          return WPTERR_GENERAL;      return 0;
438        }
439      err = gpgme_new( &ctx );  
440      if( err )  
441          BUG( dlg );  /* Import a key from the http URL @url. */
442      gpgme_control( ctx, GPGME_CTRL_FORCETRUST, 1 );  int
443      err = gpgme_data_new_from_file (&keydata, fname);  km_http_import (HWND dlg, const char *url)
444      if( err ) {  {
445          msg_box( dlg, _("Could not read key-data from file."), _("Key Manager"), MB_ERR );      http_hd_t hd;
446          goto leave;      FILE *fp;
447      }      char *p;
448            char tmpfile[500];
449      err = gpgme_op_import( ctx, NULL, keydata );      int statcode;
450      if( err ) {      int rc = 0;
451          msg_box( dlg, gpgme_strerror( err ), _("Key Manager"), MB_ERR );  
452          goto leave;      if (strncmp (url, "http://", 7)) {
453      }          log_box (_("Key Import HTTP"), MB_ERR, _("Invalid HTTP URL: %s"), url);
454                return WPTERR_GENERAL;
455      gpgme_get_import_status( ctx, import_res, NULL );      }
456      print_import_status( import_res, fm_stat.implist_revcert );  
457      if( import_res[GPGME_IMPSTAT_NOSELFSIG] > 0  ) {      GetTempPath (sizeof (tmpfile)-128, tmpfile);
458          msg_box( dlg, _("Key without a self signature was dectected!\n"      p = make_filename (tmpfile, "winpt_file_http", "tmp");
459                          "(This key is NOT usable for encryption, etc)\n"      if (!p)
460                          "\n"              BUG (0);
461                          "Cannot import these key(s)!"), _("Import"), MB_INFO );      fp = fopen (p, "wb");
462      }      if (!fp) {
463                free_if_alloc (p);
464  leave:                  log_box (_("Key Import HTTP"), MB_ERR, "%s: %s", p, winpt_strerror (WPTERR_FILE_CREAT));
465      gpgme_data_release( keydata );          return WPTERR_FILE_CREAT;
466      gpgme_release( ctx );      }
467      free_if_alloc( fm_stat.opaque );  
468      return (int)err;      /* parse URL */
469  } /* km_file_import */      rc = http_send_request2 (url, &hd);
470        if (!rc)
471            rc = http_parse_response (hd, &statcode);
472  static void      if (!rc)
473  delete_keys_from_cache (gpgme_recipients_t rset)          rc = http_parse_data (hd, fp);
474  {      http_hd_free (hd);
475      gpgme_keycache_t pub = keycache_get_ctx (1);      fclose (fp);
476      void * ctx =NULL;      if (rc) {  
477      const char * s;          msg_box (dlg, winpt_strerror (rc), _("Key Import HTTP"), MB_ERR);
478            rc = WPTERR_GENERAL;
479      gpgme_recipients_enum_open (rset, &ctx);      }
480      while ((s = gpgme_recipients_enum_read (rset, &ctx)))      km_file_import (dlg, p);
481          gpgme_keycache_delete_key (pub, s);      remove (p);
482      gpgme_recipients_enum_close (rset, &ctx);      free_if_alloc (p);
483  } /* delete_keys_from_cache */      return rc;
484    }
485    
486  int  
487  km_delete_keys (listview_ctrl_t lv, HWND dlg)  /* Import a key from the given file @fname.
488  {     On success an import statistics dialog is shown. */
489      gpgme_error_t err;  int
490      gpgme_recipients_t rset;  km_file_import (HWND dlg, const char *fname)
491      char keyid[32], uid[256], date[64], keylen[64];      {
492      int with_seckey, seckey_type=0;      gpgme_data_t keydata = NULL;
493      int i, rc, n;      gpgme_ctx_t ctx;
494            gpgme_error_t err;    
495      if( listview_get_curr_pos( lv ) == -1 ) {      fm_state_s fm_stat;
496          msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );      gpgme_import_result_t res;
497          return WPTERR_GENERAL;      
498      }      memset (&fm_stat, 0, sizeof (fm_stat));
499            fm_stat.opaque = m_strdup (fname);
500      err = gpgme_recipients_new (&rset);      
501      if (err)      dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
502          BUG (0);                        file_import_dlg_proc, (LPARAM)&fm_stat,
503      n = listview_count_items (lv, 0);                        _("File Import"), IDS_WINPT_IMPORT);
504      for( i = 0; i < n; i++ ) {      if (fm_stat.cancel == 1) {
505          if( listview_get_item_state( lv, i ) ) {          free_if_alloc (fm_stat.opaque);
506              listview_get_item_text( lv, i, 0, uid, sizeof uid - 1 );          return WPTERR_GENERAL;
507              listview_get_item_text( lv, i, 1, keyid, sizeof keyid - 1 );      }
508              listview_get_item_text( lv, i, 3, keylen, sizeof keylen - 1 );      
509              listview_get_item_text( lv, i, 7, date, sizeof date - 1 );      err = gpgme_new (&ctx);
510              seckey_type = km_check_for_seckey( lv, i, NULL );      if (err)
511              if( !seckey_type ) {          BUG (NULL);
512                  rc = log_box( _("Key Manager"), MB_YESNO|MB_ICONWARNING,      err = gpgme_data_new_from_file (&keydata, fname, 1);
513                                _("Do you really want to delete this key?\n\n"      if (err) {
514                                  "pub %s %s %s\n"          msg_box (dlg, _("Could not read key-data from file."),
515                                  "  \"%s\""), keylen, keyid, date, uid );                   _("Key Manager"), MB_ERR);
516                  if( rc == IDYES )          goto leave;
517                      gpgme_recipients_add_name( rset, keyid );      }
518                  with_seckey = 0;      
519              }      SetCursor (LoadCursor (NULL, IDC_WAIT));
520              else {      err = gpgme_op_import (ctx, keydata);
521                  rc = log_box( _("Key Manager"), MB_YESNO|MB_ICONWARNING,                      SetCursor (LoadCursor (NULL, IDC_ARROW));
522                                _("Do you really want to delete this KEY PAIR?\n\n"      if (err) {
523                                  "Please remember that you are not able to decrypt\n"          msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
524                                  "messages you stored with this key any longer.\n"          goto leave;
525                                  "\n"      }    
526                                  "pub/sec %s %s %s\n"  
527                                  "  \"%s\""), keylen, keyid, date, uid );      res = gpgme_op_import_result (ctx);
528                  if( rc == IDYES ) {      if (res->new_revocations == 0 && fm_stat.import.revcert == 1)
529                      if( seckey_type == 2 )          res->new_revocations = 1;
530                          msg_box( dlg, _("The actual secret key is stored on a smartcard.\n"      if (res->secret_imported == 0 && fm_stat.import.has_seckey == 1)
531                                          "Only the public key and the secret key \n"          res->secret_imported = 1;
532                                          "placeholder will be deleted.\n"), _("Key Manager"), MB_OK );  
533                      gpgme_recipients_add_name( rset, keyid );      print_import_status (res);
534                  }      if (res->no_user_id > 0) {
535                  with_seckey = 1;          msg_box (dlg, _("Key without a self signature was dectected!\n"
536              }                          "(This key is NOT usable for encryption, etc)\n"
537          }                          "\n"    
538      }                          "Cannot import these key(s)!"), _("Import"), MB_INFO);
539            }
540      if (!gpgme_recipients_count (rset)) {  
541          gpgme_recipients_release (rset);  leave:
542          return 0;      gpgme_data_release (keydata);
543      }      gpgme_release (ctx);
544            free_if_alloc (fm_stat.opaque);
545      err = gpgme_op_delete_keys (rset, with_seckey);      return (int)err;
546      if (err) {  }
547          if (err == GPGME_Invalid_Key)  
548              msg_box (dlg, _("No such key."), _("Key Manager"), MB_INFO);  
549          else if (err == GPGME_Conflict)  /* Mark the keys in @rset as deleted in the keycache. */
550              msg_box (dlg, _("Must delete secret key first."), _("Key Manager"), MB_INFO);  static void
551          else  delete_keys_from_cache (gpgme_key_t *rset, size_t n)
552              msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);  {
553          return FALSE;      gpg_keycache_t pub = keycache_get_ctx (1);
554      }      int i=0;
555      show_msg (dlg, 1500, _("GnuPG Status: Finished"));  
556      listview_del_items (lv);      while (n-- > 0)
557      if (keyring_check_last_access ())          gpg_keycache_delete_key (pub, rset[i++]->subkeys->keyid);
558          keycache_set_reload (1);  }
559      delete_keys_from_cache (rset);  
560      gpgme_recipients_release (rset);  
561    /* Delete all selected keys from the list view @lv. */
562      return (int)err;  int
563  } /* km_delete_keys */  km_delete_keys (listview_ctrl_t lv, HWND dlg)
564    {
565        gpgme_error_t err;
566  int      gpgme_ctx_t ctx;
567  km_send_to_keyserver (listview_ctrl_t lv, HWND dlg, const char * host, u16 port)      gpgme_key_t *rset, k;
568  {      char keyid[32], uid[256], date[64], keylen[64];    
569      char keyid[32];      int with_seckey=0, seckey_type=0, confirm=0;
570      const char *t;      int i, rc, n, k_pos=0;
571      int id;      
572            if (listview_get_curr_pos (lv) == -1) {
573      id = listview_get_curr_pos( lv );          msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
574      if( id == -1 ) {          return WPTERR_GENERAL;
575          msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );      }
576          return WPTERR_GENERAL;          
577      }      if (listview_count_items (lv, 1) > 8) {
578            i = msg_box (NULL, _("Do you really want to confirm each key?"),
579      listview_get_item_text( lv, id, 1, keyid, sizeof keyid - 1 );                       _("Delete Confirmation"), MB_YESNOCANCEL|MB_ICONQUESTION);
580      id = log_box (_("Key Manager"), MB_YESNO,          if (i == IDCANCEL)
581                    _("Do you really want to send '%s' to keyserver %s?"),              return 0;
582                      keyid, host);          if (i != IDNO)
583      if (id == IDYES) {              confirm = 1;
584          t = keyid;      }
585          if (!strncmp (keyid, "0x", 2))      else
586              t += 2;          confirm = 1;
587          hkp_send_key (dlg, host, port, t);  
588      }      n = listview_count_items (lv, 0);
589        rset = (gpgme_key_t *)calloc (n+1, sizeof (gpgme_key_t));
590      return 0;      if (!rset)
591  } /* km_send_to_keyserver */          BUG (NULL);
592        for( i = 0; i < n; i++ ) {
593            if( listview_get_item_state( lv, i ) ) {
594  int              listview_get_item_text( lv, i, 0, uid, sizeof uid - 1 );
595  km_send_to_mail_recipient( listview_ctrl_t lv, HWND dlg )              listview_get_item_text( lv, i, 1, keyid, sizeof keyid - 1 );
596  {              listview_get_item_text( lv, i, 3, keylen, sizeof keylen - 1 );
597      gpgme_key_t key;              listview_get_item_text( lv, i, 7, date, sizeof date - 1 );
598      gpgme_ctx_t ctx=NULL;              seckey_type = km_check_for_seckey (lv, i, NULL);
599      gpgme_recipients_t rset=NULL;              if (confirm && !seckey_type) {
600      gpgme_error_t rc;                  rc = log_box( _("Key Manager"), MB_YESNO|MB_ICONWARNING,
601      const char * s;                                _("Do you really want to delete this key?\n\n"
602      char keyid[32], tmp[192+256], * p =NULL;                                  "pub %s %s %s\n"
603      int pos;                                  "  \"%s\""), keylen, keyid, date, uid );
604                    if (rc == IDYES) {
605      if( listview_count_items( lv, 1 ) > 1 ) {                      get_pubkey (keyid, &k);
606          msg_box( dlg, _("Please only select one key."), _("Key Manager"), MB_INFO|MB_OK );                      rset[k_pos++] = k;
607          return WPTERR_GENERAL;                  }
608      }                  with_seckey = 0;
609      pos = listview_get_curr_pos( lv );              }
610      if( pos == -1 ) {              else if (confirm) {
611          msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );                  rc = log_box( _("Key Manager"), MB_YESNO|MB_ICONWARNING,                
612          return WPTERR_GENERAL;                                _("Do you really want to delete this KEY PAIR?\n\n"
613      }                                  "Please remember that you are not able to decrypt\n"
614      listview_get_item_text( lv, pos, 1, keyid, sizeof keyid-1 );                                  "messages you stored with this key any longer.\n"
615      if( get_pubkey( keyid, &key ) )                                  "\n"
616          BUG( NULL );                                  "pub/sec %s %s %s\n"
617      s = gpgme_key_get_string_attr( key, GPGME_ATTR_NAME, NULL, 0 );                                  "  \"%s\""), keylen, keyid, date, uid );
618      GetTempPath (sizeof tmp-1, tmp);                  if( rc == IDYES ) {
619      strncat (tmp, s, sizeof tmp-200);                      if (seckey_type == 2)
620      strncat (tmp, ".asc", sizeof tmp-200);                          msg_box( dlg, _("The actual secret key is stored on a smartcard.\n"
621      p = fm_quote_file (tmp);                                          "Only the public key and the secret key \n"
622                                            "placeholder will be deleted.\n"), _("Key Manager"), MB_OK );
623      rc = gpgme_recipients_new( &rset );                      get_pubkey (keyid, &k);
624      if( !rc )                      rset[k_pos++] = k;
625          rc = gpgme_recipients_add_name( rset, keyid );                  }
626      if( !rc )                  with_seckey = 1;
627          rc = gpgme_new( &ctx );              }
628      if( !rc ) {              else {
629          gpgme_control( ctx, GPGME_CTRL_ARMOR, 1 );                  with_seckey = 1;
630          rc = gpgme_op_file_export( ctx, rset, p );                  get_pubkey (keyid, &k);
631      }                  rset[k_pos++] = k;
632      if( rc )              }
633          msg_box( dlg, gpgme_strerror( rc ), _("Key Manager"), MB_ERR );          }
634      else      }
635          mapi_send_pubkey (keyid, tmp);      
636      free_if_alloc( p );      if (k_pos == 0) {
637      gpgme_recipients_release( rset );          free (rset);
638      gpgme_release( ctx );              return 0;
639      return rc;      }
640  }  
641        err = gpgme_new (&ctx);
642        if (err)
643  static void          BUG (NULL);
644  km_refresh_one_key (listview_ctrl_t lv, HWND dlg, int pos)      n=k_pos;
645  {      for (i=0; i < k_pos; i++) {
646      int idx;          err = gpgme_op_delete (ctx, rset[i], with_seckey);
647      char keyid[32];          if (err)
648      const char *t;              msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
649            else
650      if (pos != 0)              n--;
651          idx = pos;      }
652      else      if (n == 0)
653          idx = listview_get_curr_pos (lv);          show_msg (dlg, 1500, _("GnuPG Status: Finished"));
654      if (idx != -1)      gpgme_release (ctx);
655      {      listview_del_items (lv);
656          listview_get_item_text (lv, idx, 1, keyid, sizeof keyid - 1);      delete_keys_from_cache (rset, k_pos);
657          t = keyid;      free (rset);
658          if (!strncmp (keyid, "0x", 2))  
659              t += 2;      return (int)err;
660          hkp_recv_key (dlg, default_keyserver, default_keyserver_port, t, 0, KM_KS_REFRESH);  }
661      }  
662  }  
663    int
664    km_send_to_keyserver (listview_ctrl_t lv, HWND dlg, const char * host, u16 port)
665  void  {
666  km_refresh_from_keyserver (listview_ctrl_t lv, HWND dlg)      char keyid[32];
667  {      const char *t;
668      int idx, id, i;      int id;
669            
670      if (kserver_check_inet_connection ())      id = listview_get_curr_pos( lv );
671      {      if( id == -1 ) {
672          msg_box (dlg, _("Could not connect to keyserver, abort procedure."),          msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );
673                   _("Key Manager"), MB_ERR);          return WPTERR_GENERAL;
674          return;      }
675      }  
676      idx = listview_count_items (lv, 0);      listview_get_item_text( lv, id, 1, keyid, sizeof keyid - 1 );
677      if (listview_count_items (lv, 1) == idx) {      id = log_box (_("Key Manager"), MB_YESNO,
678          id = msg_box (dlg, _("Do you really want to refresh all keys in the keyring?"), _("Key Manager"), MB_YESNO);                    _("Do you really want to send '%s' to keyserver %s?"),
679          if (id == IDNO)                      keyid, host);
680              return;      if (id == IDYES) {
681          for (i = 0; i < idx; i++)          t = keyid;
682              km_refresh_one_key (lv, dlg, i);          if (!strncmp (keyid, "0x", 2))
683      }              t += 2;
684      else if (idx == 1)          hkp_send_key (dlg, host, port, t);
685          km_refresh_one_key (lv, dlg, 0);      }
686      else {  
687          for (i=0; i < listview_count_items (lv, 0); i++) {      return 0;
688              if (listview_get_item_state (lv, i))  } /* km_send_to_keyserver */
689                  km_refresh_one_key (lv, dlg, i);  
690          }  
691      }  /* Send the selected key in @lv via MAPI to a mail recipient. */
692  } /* km_refresh_from_keyserver */  int
693    km_send_to_mail_recipient (listview_ctrl_t lv, HWND dlg)
694    {
695  void      gpgme_key_t key;
696  km_set_clip_info( const char *uid )      gpgme_ctx_t ctx=NULL;
697  {          gpgme_data_t out;
698      char buf[256];      gpgme_error_t rc;
699            const char *s;
700      km_get_clip_info (uid, buf, 255);          char keyid[32], tmp[192+256];
701      set_clip_text( NULL, buf, strlen( buf ) );      int pos;
702  } /* km_set_clip_info */  
703        if (listview_count_items (lv, 1 ) > 1) {
704            msg_box (dlg, _("Please only select one key."),
705                     _("Key Manager"), MB_INFO|MB_OK);
706  int          return WPTERR_GENERAL;
707  km_key_is_v3 (listview_ctrl_t lv, int pos)      }
708  {      pos = listview_get_curr_pos (lv);
709      gpgme_key_t pk;      if (pos == -1) {
710      char keyid[32];          msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
711            return WPTERR_GENERAL;
712      listview_get_item_text (lv, pos, 1, keyid, sizeof keyid-1);      }
713      if (get_pubkey (keyid, &pk))      listview_get_item_text(lv, pos, 1, keyid, sizeof keyid-1);
714          BUG (NULL);      if (get_pubkey (keyid, &key))
715      return gpgme_key_get_ulong_attr (pk, GPGME_ATTR_VERSION, NULL, 0);          BUG (NULL);
716  } /* km_key_is_v3 */      s = key->uids->name;
717        GetTempPath (sizeof tmp-1, tmp);
718        strncat (tmp, s, sizeof tmp-200);
719  void      strncat (tmp, ".asc", sizeof tmp-200);
720  km_update_default_key_str (HWND dlg, int * ret_len)  
721  {      rc = gpgme_new (&ctx);
722      char * keyid, defkeyinf[512];      if (rc)
723      const char * fmt;          BUG (NULL);
724            rc = gpgme_data_new (&out);
725      keyid = get_gnupg_default_key ();      if (rc)
726      if (!keyid)          BUG (NULL);
727          BUG (0);  
728      if( (keyid[0] >= 'A' && keyid[0] <= 'Z') || (keyid[0] >= 'a' && keyid[0] <= 'z')      gpgme_set_armor (ctx, 1);
729          || (keyid[0] == '0' && keyid[1] == 'x') )      rc = gpgme_op_export (ctx, key->subkeys->keyid, 0, out);
730          fmt = _("Default Key: %s");      if (rc)
731      else          msg_box (dlg, gpgme_strerror (rc), _("Key Manager"), MB_ERR);
732          fmt = _("Default Key: 0x%s");      else
733      _snprintf( defkeyinf, sizeof defkeyinf - 1, fmt, keyid );          mapi_send_pubkey (keyid, tmp);
734      SetWindowText( dlg, defkeyinf );  
735      *ret_len = strlen( defkeyinf );      gpg_data_release_and_set_file (out, tmp);
736      free_if_alloc( keyid );      gpgme_release (ctx);
737  } /* km_return_default_key_str */      return rc;
738    }
739    
740  void  
741  km_complete_status_bar( HWND sb, listview_ctrl_t lv, int startpos )  static void
742  {  km_refresh_one_key (listview_ctrl_t lv, HWND dlg, int pos)
743      char text[384];  {
744      int nkeys = 0, nsec = 0, i;      int idx;
745        char keyid[32];
746      GetWindowText( sb, text, sizeof text -1 );      const char *t;
747      nkeys = listview_count_items( lv, 0 );  
748      for( i = 0; i < nkeys; i++ ) {      if (pos != 0)
749          if( km_check_for_seckey( lv, i, NULL ) )          idx = pos;
750              nsec++;      else
751      }          idx = listview_get_curr_pos (lv);
752      _snprintf( text+startpos, sizeof text-1, "                %d keys (%d secret keys)", nkeys, nsec );      if (idx != -1)
753      SetWindowText( sb, text );      {
754  } /* km_complete_status_bar */          listview_get_item_text (lv, idx, 1, keyid, sizeof keyid - 1);
755            t = keyid;
756            if (!strncmp (keyid, "0x", 2))
757  void              t += 2;
758  km_set_implicit_trust (HWND dlg, listview_ctrl_t lv, int pos)          hkp_recv_key (dlg, default_keyserver, default_keyserver_port, t, 0, KM_KS_REFRESH);
759  {      }
760      gpgme_error_t err;  }
761      gpgme_ctx_t ctx;  
762      gpgme_editkey_t ek;  
763      char keyid[32];  void
764    km_refresh_from_keyserver (listview_ctrl_t lv, HWND dlg)
765      listview_get_item_text (lv, pos, 1, keyid, 31);  {
766      err = gpgme_new (&ctx);      int idx, id, i;
767      if (err)      
768          BUG (0);      if (kserver_check_inet_connection ())
769      err = gpgme_editkey_new (&ek);      {
770      if (err)          msg_box (dlg, _("Could not connect to keyserver, abort procedure."),
771          BUG (0);                   _("Key Manager"), MB_ERR);
772      gpgme_set_edit_ctx (ctx, ek, GPGME_EDITKEY_TRUST);          return;
773      gpgme_editkey_trust_set (ek, 5);      }
774        idx = listview_count_items (lv, 0);
775      err = gpgme_op_editkey (ctx, keyid);      if (listview_count_items (lv, 1) == idx) {
776      if (err)          id = msg_box (dlg, _("Do you really want to refresh all keys in the keyring?"), _("Key Manager"), MB_YESNO);
777          msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);          if (id == IDNO)
778      else {              return;
779          show_msg (dlg, 1500, _("GnuPG Status: Finished"));          for (i = 0; i < idx; i++)
780          keycache_set_reload (1);              km_refresh_one_key (lv, dlg, i);
781      }      }
782        else if (idx == 1)
783      gpgme_release (ctx);          km_refresh_one_key (lv, dlg, 0);
784      gpgme_editkey_release (ek);          else {
785  }          for (i=0; i < listview_count_items (lv, 0); i++) {
786                if (listview_get_item_state (lv, i))
787                    km_refresh_one_key (lv, dlg, i);
788  gpg_optfile_t          }
789  km_groupdb_open( void )      }
790  {        } /* km_refresh_from_keyserver */
791      gpg_optfile_t opt;  
792      char * optfile;  
793      int err = 0;  void
794        km_set_clip_info (const char *uid)
795      optfile = get_gnupg_cfgfile();  {    
796      if( !optfile )      char buf[256];
797          BUG( NULL );      
798      if( parse_gpg_options( optfile, &opt ) )      key_get_clip_info (uid, buf, 255);    
799          err = 1;      set_clip_text (NULL, buf, strlen (buf));
800      free_if_alloc( optfile );  } /* km_set_clip_info */
801      return err? NULL : opt;  
802  } /* km_groupdb_open */  
803    
804    /* Return TRUE if the key in the list @lv at pos @pos is an
805  int     old version 3 key. */
806  km_groupdb_expand_recipients( const char *name, gpgme_recipients_t rset )  int
807  {    km_key_is_v3 (listview_ctrl_t lv, int pos)
808      gpgme_keycache_t kc;  {
809      gpgme_key_t pk;      gpgme_key_t pk;
810      gpg_optfile_t opt;      char keyid[32];
811      gpg_group_t grp;      
812      gpg_member_t mbr;      listview_get_item_text (lv, pos, 1, keyid, sizeof keyid-1);
813      int no_trust = 0, n;      if (get_pubkey (keyid, &pk))
814            BUG (NULL);
815      kc = keycache_get_ctx( 1 );      if (strlen (pk->subkeys->fpr) == 32 &&
816      if( !kc )          pk->subkeys->pubkey_algo == GPGME_PK_RSA)
817          BUG( NULL );          return -1;
818        return 0;
819      opt = km_groupdb_open( );  }
820      if( !opt )  
821          return WPTERR_FILE_OPEN;  
822        /* Update the default key entry in the status bar for dialog @dlg. */
823      grp = find_group( opt, name );  void
824      if( !grp )  km_update_default_key_str (HWND dlg)
825          return WPTERR_GENERAL;  {
826            char *keyid, defkeyinf[512];
827      /* we are paranoid and check that all group members exist in the      const char *fmt;
828         key cache. there is no need that it is really the real key, but      
829         an entry should be available. the rest is up to GPG. */      /* XXX: also show the name? */
830      for( mbr = grp->list; mbr; mbr = mbr->next ) {      keyid = get_gnupg_default_key ();
831          if( gpgme_keycache_find_key( kc, mbr->name, 0, &pk ) )      if (!keyid)
832              BUG( NULL );          return;
833          n = gpgme_key_count_items( pk, GPGME_ATTR_USERID );      if( (keyid[0] >= 'A' && keyid[0] <= 'Z') || (keyid[0] >= 'a' && keyid[0] <= 'z')
834          while( n-- ) {          || (keyid[0] == '0' && keyid[1] == 'x') )
835              const char * s = gpgme_key_get_string_attr( pk, GPGME_ATTR_USERID, NULL, n );          fmt = _("Default Key: %s");
836              if( s && stristr( s, mbr->name )      else
837                  && gpgme_key_get_ulong_attr( pk, GPGME_ATTR_VALIDITY, NULL, n ) < 3 )          fmt = _("Default Key: 0x%s");
838                  no_trust++;      _snprintf (defkeyinf, sizeof defkeyinf - 1, fmt, keyid);
839          }      SendMessage (dlg, SB_SETTEXT, 0, (LPARAM)defkeyinf);
840      }      free_if_alloc (keyid);
841    }
842      gpgme_recipients_add_name( rset, name );  
843      release_gpg_options( opt );  
844        /* Count all keys and show from @lv results in the status bar @sb. */
845      return no_trust;  void
846  } /* km_groupdb_expand_recipients */  km_complete_status_bar (HWND sb, listview_ctrl_t lv)
847    {
848        char txt_sec[128], txt_pub[128];
849  static HTREEITEM      int nkeys = 0, nsec = 0, i;
850  km_tv_insert_item( HWND tree, HTREEITEM parent, const char *text )  
851  {      nkeys = listview_count_items (lv, 0);
852      TVINSERTSTRUCT tvis;      for (i = 0; i < nkeys; i++) {
853      HTREEITEM node;          if (km_check_for_seckey (lv, i, NULL))
854                    nsec++;
855      memset( &tvis, 0, sizeof tvis );      }
856      tvis.hParent = parent;      _snprintf (txt_sec, sizeof (txt_sec)-1, _("%d secret keys"), nsec);
857      tvis.hInsertAfter = TVI_LAST;      _snprintf (txt_pub, sizeof (txt_pub)-1, _("%d keys"), nkeys);
858      tvis.item.mask = TVIF_TEXT;      SendMessage (sb, SB_SETTEXT, 1, (LPARAM)txt_sec);
859      tvis.item.pszText = (char *)text;      SendMessage (sb, SB_SETTEXT, 2, (LPARAM)txt_pub);
860      node = TreeView_InsertItem( tree, &tvis );  }
861      return node;  
862  } /* km_tv_insert_item */  
863    /* Set trust of selected key in @lv (at @pos) to ultimate. */
864    int
865  int  km_set_implicit_trust (HWND dlg, listview_ctrl_t lv, int pos)
866  km_groups_new( km_group_t *r_gc, HWND ctrl )  {
867  {      GpgKeyEdit *ke;
868      km_group_t gc;      gpgme_error_t err;    
869            char keyid[32];
870      gc = new km_group_s;  
871      if (!gc)      listview_get_item_text (lv, pos, 1, keyid, 31);
872          BUG (NULL);  
873      gc->tree = ctrl;      ke = new GpgKeyEdit (keyid);
874      gc->gh = km_groupdb_open ();      if (!ke)
875      *r_gc = gc;          BUG (0);
876      return 0;  
877  } /* km_groups_new */      err = ke->setTrust (GPGME_VALIDITY_ULTIMATE);
878        if (err)
879            msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
880  void      else
881  km_groups_sync( km_group_t gc )          show_msg (dlg, 1500, _("GnuPG Status: Finished"));
882  {  
883      char * optfile;      delete ke;
884        return (int)err;
885      optfile = get_gnupg_cfgfile ();  }
886      if( !optfile )  
887          BUG( NULL );  
888      commit_gpg_options( optfile, gc->gh );  void
889      free_if_alloc( optfile );  km_find_key (HWND dlg, listview_ctrl_t lv)
890      gc->need_sync = 0;  {
891  } /* km_groups_sync */      int oldpos = listview_get_curr_pos (lv);
892        int n;
893        char *name = get_input_dialog (dlg, _("Search"), _("Search for:"));
894  void      if (name == NULL)
895  km_groups_release (km_group_t gc)          return;
896  {      if (oldpos < 0)
897      if( gc ) {          oldpos = 0;
898          /* xxx: this reset the default key (sync=1) */      n = listview_find (lv, name);
899          gc->need_sync=0;      if (n != -1) {
900          if (gc->need_sync)          listview_select_one (lv, n);
901              km_groups_sync (gc);          listview_scroll (lv, oldpos, n);
902          if (gc->gh)      }
903              release_gpg_options( gc->gh );      else {
904          gc->gh = NULL;          const char *s = _("String pattern \"%s\" not found.");
905          gc->tree = NULL;          char *p = new char[strlen (s) + strlen (name) + 2];
906          delete gc;          if (!p)
907      }                  BUG (0);
908  } /* km_groups_release */          sprintf (p, s, name);
909            msg_box (dlg, p, _("Key Manager"), MB_INFO);
910            free_if_alloc (p);
911  int      }
912  km_groups_load( km_group_t gc )      free_if_alloc (name);
913  {      }
914      HTREEITEM n;  
915      gpg_group_t grp, g;  
916      gpg_member_t mbr;  
917      u32 gid = 0;  void
918        km_dump_key (gpgme_key_t key)
919      if( !gc->gh )  {
920          return 0;  #if _DEBUG
921      grp = gc->gh->grp;      log_box ("DEBUG", MB_OK,
922      if( !grp )               "%d %d %s %d\n%s", key->subkeys->length,
923          return 0; /* no groups */               key->subkeys->pubkey_algo,
924                         key->subkeys->keyid,
925      for( g = grp; g; g = g->next ) {               key->subkeys->timestamp,
926          n = km_tv_insert_item( gc->tree, NULL, g->name );               key->uids->uid);
927          for( mbr = g->list; mbr; mbr = mbr->next ) {  #endif
928              if( mbr->used && mbr->name )  }
929                  km_tv_insert_item( gc->tree, n, mbr->name );  
930          }  #if 0
931      }  gpg_optfile_t
932      DragAcceptFiles( gc->tree, TRUE );  km_groupdb_open (void)
933      gc->need_sync = 0;  {      
934      return 0;      gpg_optfile_t opt;
935  } /* km_groups_load */      char * optfile;
936        int err = 0;
937        
938  int      optfile = get_gnupg_cfgfile();
939  km_groups_add( km_group_t gc, listview_ctrl_t lv, int km_index )      if( !optfile )
940  {          BUG( NULL );
941      TVITEM tvi;      if( parse_gpg_options( optfile, &opt ) )
942      char uid[128], valid[64], text[128];          err = 1;
943      int i_valid;      free_if_alloc( optfile );
944            return err? NULL : opt;
945      memset( &tvi, 0, sizeof tvi );  } /* km_groupdb_open */
946      tvi.hItem = TreeView_GetSelection( gc->tree );  
947      tvi.pszText = text;  
948      tvi.cchTextMax = sizeof text -1;  int
949      tvi.mask = TVIF_TEXT;  km_groupdb_expand_recipients( const char *name, gpgme_recipients_t rset )
950      TreeView_GetItem( gc->tree, &tvi );  {  
951            gpg_keycache_t kc;
952            gpgme_key_t pk;
953      listview_get_item_text( lv, km_index, 0, uid, sizeof uid -1 );      gpg_optfile_t opt;
954      listview_get_item_text( lv, km_index, 5, valid, sizeof valid -1 );      gpg_group_t grp;    
955            gpg_member_t mbr;
956      if( strstr( valid, "Ultimate" ) )      int no_trust = 0, n;
957          i_valid = 5;      
958      else if( !strstr( valid, "Full" ) )      kc = keycache_get_ctx( 1 );
959          i_valid = 4;      if( !kc )
960      else if( !strstr( valid, "Marginal" ) )          BUG( NULL );
961          i_valid = 3;  
962      else      opt = km_groupdb_open( );
963          i_valid = 0;      if( !opt )
964                return WPTERR_FILE_OPEN;
965      /* we can't add the full name. one way would be to use the first      
966         text until a space appears.      grp = find_group( opt, name );
967      group_add_entry(&gc->gh, gid, i_valid, uid);      if( !grp )
968      treeview_add_item(gc->tree, tvi.hItem, uid);          return WPTERR_GENERAL;
969      */      
970      gc->need_sync = 1;      /* we are paranoid and check that all group members exist in the
971               key cache. there is no need that it is really the real key, but
972      return 0;         an entry should be available. the rest is up to GPG. */
973  } /* km_groups_add */      for( mbr = grp->list; mbr; mbr = mbr->next ) {
974            if( gpgme_keycache_find_key( kc, mbr->name, 0, &pk ) )
975                BUG( NULL );
976  static int          n = count_userids (pk);
977  km_groups_del_main( km_group_t gc )          while( n-- ) {
978  {              gpgme_user_id_t u = get_nth_userid (pk, n);
979      TVITEM tvi;              const char * s =  u->uid;
980      char text[128];              if( s && stristr( s, mbr->name )
981      int id;                  && u->validity < 3 )
982                        no_trust++;
983      memset( &tvi, 0, sizeof tvi );          }
984      tvi.hItem = TreeView_GetSelection( gc->tree );      }
985      tvi.pszText = text;  
986      tvi.cchTextMax = sizeof text -1;      gpgme_recipients_add_name( rset, name );
987      tvi.mask = TVIF_TEXT;      release_gpg_options( opt );
988      TreeView_GetItem( gc->tree, &tvi );      
989                                    return no_trust;
990      id = log_box( _("Key Manager"), MB_INFO_ASK,  } /* km_groupdb_expand_recipients */
991                     _("Do you really want to delete this group?\n\n%s"), text);  
992      if( id == IDNO )  
993          return 0;  static HTREEITEM
994      delete_group( gc->gh, text );      km_tv_insert_item( HWND tree, HTREEITEM parent, const char *text )
995      TreeView_DeleteItem( gc->tree, &tvi );  {
996      gc->need_sync = 1;      TVINSERTSTRUCT tvis;
997            HTREEITEM node;
998      return 0;      
999  } /* km_groups_del */      memset( &tvis, 0, sizeof tvis );
1000        tvis.hParent = parent;
1001        tvis.hInsertAfter = TVI_LAST;
1002  static int      tvis.item.mask = TVIF_TEXT;
1003  km_groups_del_entry( km_group_t gc )      tvis.item.pszText = (char *)text;
1004  {      node = TreeView_InsertItem( tree, &tvis );
1005      TVITEM tvi;      return node;
1006      HTREEITEM root;  } /* km_tv_insert_item */
1007      int id;  
1008      char text[128], info[256];  
1009      gpg_group_t  grp = NULL;  int
1010        km_groups_new( km_group_t *r_gc, HWND ctrl )
1011      memset( &tvi, 0, sizeof tvi );  {
1012      tvi.hItem = TreeView_GetSelection( gc->tree );      km_group_t gc;
1013      tvi.pszText = text;      
1014      tvi.cchTextMax = sizeof text-1;      gc = new km_group_s;
1015      tvi.mask = TVIF_TEXT;      if (!gc)
1016      TreeView_GetItem( gc->tree, &tvi );          BUG (NULL);
1017            gc->tree = ctrl;
1018      _snprintf( info, sizeof info -1,      gc->gh = km_groupdb_open ();
1019                _("Do you really want to delete this entry?\n\n%s"), text );      *r_gc = gc;
1020            return 0;
1021      id = msg_box( gc->tree, info, _("Key Manager"), MB_INFO_ASK );  } /* km_groups_new */
1022      if( id == IDNO )  
1023          return 0;  
1024    void
1025      root = TreeView_GetParent( gc->tree, tvi.hItem );  km_groups_sync( km_group_t gc )
1026      if( root ) {  {
1027      }      char * optfile;
1028        
1029      delete_member( gc->gh, /*fixme*/NULL, text );      optfile = get_gnupg_cfgfile ();
1030      TreeView_DeleteItem( gc->tree, &tvi );      if( !optfile )
1031      gc->need_sync = 1;          BUG( NULL );
1032      return 0;      commit_gpg_options( optfile, gc->gh );
1033  } /* km_groups_del_entry */      free_if_alloc( optfile );
1034        gc->need_sync = 0;
1035    } /* km_groups_sync */
1036  int  
1037  km_groups_del( km_group_t gc )  
1038  {  void
1039      if ( TreeView_GetParent( gc->tree, TreeView_GetSelection( gc->tree ) ) )  km_groups_release (km_group_t gc)
1040          return km_groups_del_entry( gc );  {
1041      else      if( gc ) {
1042          return km_groups_del_main( gc );          /* xxx: this reset the default key (sync=1) */
1043  } /* km_groups_del */          gc->need_sync=0;
1044            if (gc->need_sync)
1045                km_groups_sync (gc);
1046            if (gc->gh)
1047                release_gpg_options( gc->gh );
1048            gc->gh = NULL;
1049            gc->tree = NULL;
1050            delete gc;
1051        }    
1052    } /* km_groups_release */
1053    
1054    
1055    int
1056    km_groups_load( km_group_t gc )
1057    {    
1058        HTREEITEM n;
1059        gpg_group_t grp, g;
1060        gpg_member_t mbr;
1061        u32 gid = 0;
1062        
1063        if( !gc->gh )
1064            return 0;
1065        grp = gc->gh->grp;
1066        if( !grp )
1067            return 0; /* no groups */
1068            
1069        for( g = grp; g; g = g->next ) {
1070            n = km_tv_insert_item( gc->tree, NULL, g->name );
1071            for( mbr = g->list; mbr; mbr = mbr->next ) {
1072                if( mbr->used && mbr->name )
1073                    km_tv_insert_item( gc->tree, n, mbr->name );
1074            }
1075        }
1076        DragAcceptFiles( gc->tree, TRUE );
1077        gc->need_sync = 0;
1078        return 0;
1079    } /* km_groups_load */
1080    
1081    
1082    int
1083    km_groups_add( km_group_t gc, listview_ctrl_t lv, int km_index )
1084    {
1085        TVITEM tvi;
1086        char uid[128], valid[64], text[128];
1087        int i_valid;
1088        
1089        memset( &tvi, 0, sizeof tvi );
1090        tvi.hItem = TreeView_GetSelection( gc->tree );
1091        tvi.pszText = text;
1092        tvi.cchTextMax = sizeof text -1;
1093        tvi.mask = TVIF_TEXT;
1094        TreeView_GetItem( gc->tree, &tvi );
1095        
1096        
1097        listview_get_item_text( lv, km_index, 0, uid, sizeof uid -1 );
1098        listview_get_item_text( lv, km_index, 5, valid, sizeof valid -1 );
1099        
1100        if( strstr( valid, "Ultimate" ) )
1101            i_valid = 5;    
1102        else if( !strstr( valid, "Full" ) )
1103            i_valid = 4;
1104        else if( !strstr( valid, "Marginal" ) )
1105            i_valid = 3;
1106        else
1107            i_valid = 0;
1108        
1109        /* we can't add the full name. one way would be to use the first
1110           text until a space appears.
1111        group_add_entry(&gc->gh, gid, i_valid, uid);
1112        treeview_add_item(gc->tree, tvi.hItem, uid);
1113        */
1114        gc->need_sync = 1;
1115        
1116        return 0;
1117    } /* km_groups_add */
1118    
1119    
1120    static int
1121    km_groups_del_main( km_group_t gc )
1122    {
1123        TVITEM tvi;
1124        char text[128];
1125        int id;
1126        
1127        memset( &tvi, 0, sizeof tvi );
1128        tvi.hItem = TreeView_GetSelection( gc->tree );
1129        tvi.pszText = text;
1130        tvi.cchTextMax = sizeof text -1;
1131        tvi.mask = TVIF_TEXT;
1132        TreeView_GetItem( gc->tree, &tvi );
1133                                
1134        id = log_box( _("Key Manager"), MB_INFO_ASK,
1135                       _("Do you really want to delete this group?\n\n%s"), text);
1136        if( id == IDNO )
1137            return 0;
1138        delete_group( gc->gh, text );    
1139        TreeView_DeleteItem( gc->tree, &tvi );
1140        gc->need_sync = 1;
1141        
1142        return 0;
1143    } /* km_groups_del */
1144    
1145    
1146    static int
1147    km_groups_del_entry( km_group_t gc )
1148    {
1149        TVITEM tvi;
1150        HTREEITEM root;
1151        int id;
1152        char text[128], info[256];
1153        gpg_group_t  grp = NULL;
1154        
1155        memset( &tvi, 0, sizeof tvi );
1156        tvi.hItem = TreeView_GetSelection( gc->tree );
1157        tvi.pszText = text;
1158        tvi.cchTextMax = sizeof text-1;
1159        tvi.mask = TVIF_TEXT;
1160        TreeView_GetItem( gc->tree, &tvi );
1161        
1162        _snprintf( info, sizeof info -1,
1163                  _("Do you really want to delete this entry?\n\n%s"), text );
1164        
1165        id = msg_box( gc->tree, info, _("Key Manager"), MB_INFO_ASK );
1166        if( id == IDNO )
1167            return 0;
1168    
1169        root = TreeView_GetParent( gc->tree, tvi.hItem );
1170        if( root ) {
1171        }
1172        
1173        delete_member( gc->gh, /*fixme*/NULL, text );
1174        TreeView_DeleteItem( gc->tree, &tvi );
1175        gc->need_sync = 1;
1176        return 0;
1177    } /* km_groups_del_entry */
1178    
1179    
1180    int
1181    km_groups_del( km_group_t gc )
1182    {
1183        if ( TreeView_GetParent( gc->tree, TreeView_GetSelection( gc->tree ) ) )
1184            return km_groups_del_entry( gc );
1185        else
1186            return km_groups_del_main( gc );
1187    } /* km_groups_del */
1188    #endif

Legend:
Removed from v.20  
changed lines
  Added in v.77

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26