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

Legend:
Removed from v.22  
changed lines
  Added in v.164

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26