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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26