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

Legend:
Removed from v.33  
changed lines
  Added in v.165

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26