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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26