/[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 36 by werner, Thu Oct 27 15:25:13 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 <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    
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, NULL,
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        unlink (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    int
692    km_send_to_mail_recipient( listview_ctrl_t lv, HWND dlg )
693    {
694    #if 0 /*FIXME*/
695        gpgme_key_t key;
696        gpgme_ctx_t ctx=NULL;
697        gpgme_recipients_t rset=NULL;
698        gpgme_error_t rc;
699        const char * s;
700        char keyid[32], tmp[192+256], * p =NULL;
701        int pos;
702    
703        if( listview_count_items( lv, 1 ) > 1 ) {
704            msg_box( dlg, _("Please only select one key."), _("Key Manager"), MB_INFO|MB_OK );
705            return WPTERR_GENERAL;
706        }
707        pos = listview_get_curr_pos( lv );
708        if( pos == -1 ) {
709            msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );
710            return WPTERR_GENERAL;
711        }
712        listview_get_item_text( lv, pos, 1, keyid, sizeof keyid-1 );
713        if( get_pubkey( keyid, &key ) )
714            BUG( NULL );
715        s = key->uids->name;
716        GetTempPath (sizeof tmp-1, tmp);
717        strncat (tmp, s, sizeof tmp-200);
718        strncat (tmp, ".asc", sizeof tmp-200);
719        p = fm_quote_file (tmp);
720    
721        rc = gpgme_recipients_new (&rset);
722        if (!rc)
723            rc = gpgme_recipients_add_name (rset, keyid);
724        if (!rc)
725            rc = gpgme_new (&ctx);
726        if (!rc) {
727            gpgme_set_armor (ctx, 1);
728            rc = gpgme_op_file_export (ctx, rset, p);
729        }
730        if (rc)
731            msg_box (dlg, gpgme_strerror (rc), _("Key Manager"), MB_ERR);
732        else
733            mapi_send_pubkey (keyid, tmp);
734    
735        free_if_alloc (p);
736        gpgme_recipients_release (rset);
737        gpgme_release (ctx);
738        return rc;
739    #endif
740        return 0;
741    }
742    
743    
744    static void
745    km_refresh_one_key (listview_ctrl_t lv, HWND dlg, int pos)
746    {
747        int idx;
748        char keyid[32];
749        const char *t;
750    
751        if (pos != 0)
752            idx = pos;
753        else
754            idx = listview_get_curr_pos (lv);
755        if (idx != -1)
756        {
757            listview_get_item_text (lv, idx, 1, keyid, sizeof keyid - 1);
758            t = keyid;
759            if (!strncmp (keyid, "0x", 2))
760                t += 2;
761            hkp_recv_key (dlg, default_keyserver, default_keyserver_port, t, 0, KM_KS_REFRESH);
762        }
763    }
764    
765    
766    void
767    km_refresh_from_keyserver (listview_ctrl_t lv, HWND dlg)
768    {
769        int idx, id, i;
770        
771        if (kserver_check_inet_connection ())
772        {
773            msg_box (dlg, _("Could not connect to keyserver, abort procedure."),
774                     _("Key Manager"), MB_ERR);
775            return;
776        }
777        idx = listview_count_items (lv, 0);
778        if (listview_count_items (lv, 1) == idx) {
779            id = msg_box (dlg, _("Do you really want to refresh all keys in the keyring?"), _("Key Manager"), MB_YESNO);
780            if (id == IDNO)
781                return;
782            for (i = 0; i < idx; i++)
783                km_refresh_one_key (lv, dlg, i);
784        }
785        else if (idx == 1)
786            km_refresh_one_key (lv, dlg, 0);
787        else {
788            for (i=0; i < listview_count_items (lv, 0); i++) {
789                if (listview_get_item_state (lv, i))
790                    km_refresh_one_key (lv, dlg, i);
791            }
792        }
793    } /* km_refresh_from_keyserver */
794    
795    
796    void
797    km_set_clip_info (const char *uid)
798    {    
799        char buf[256];
800        
801        key_get_clip_info (uid, buf, 255);    
802        set_clip_text (NULL, buf, strlen (buf));
803    } /* km_set_clip_info */
804    
805    
806    
807    /* Return TRUE if the key in the list @lv at pos @pos is an
808       old version 3 key. */
809    int
810    km_key_is_v3 (listview_ctrl_t lv, int pos)
811    {
812        gpgme_key_t pk;
813        char keyid[32];
814    
815        listview_get_item_text (lv, pos, 1, keyid, sizeof keyid-1);
816        if (get_pubkey (keyid, &pk))
817            BUG (NULL);
818        if (strlen (pk->subkeys->fpr) == 32 &&
819            pk->subkeys->pubkey_algo == GPGME_PK_RSA)
820            return -1;
821        return 0;
822    }
823    
824    
825    /* Update the default key entry in the status bar for dialog @dlg. */
826    void
827    km_update_default_key_str (HWND dlg)
828    {
829        char *keyid, defkeyinf[512];
830        const char *fmt;
831        
832        /* XXX: also show the name? */
833        keyid = get_gnupg_default_key ();
834        if (!keyid)
835            BUG (0);
836        if( (keyid[0] >= 'A' && keyid[0] <= 'Z') || (keyid[0] >= 'a' && keyid[0] <= 'z')
837            || (keyid[0] == '0' && keyid[1] == 'x') )
838            fmt = _("Default Key: %s");
839        else
840            fmt = _("Default Key: 0x%s");
841        _snprintf (defkeyinf, sizeof defkeyinf - 1, fmt, keyid);
842        SendMessage (dlg, SB_SETTEXT, 0, (LPARAM)defkeyinf);
843        free_if_alloc (keyid);
844    }
845    
846    
847    /* Count all keys and show from @lv results in the status bar @sb. */
848    void
849    km_complete_status_bar (HWND sb, listview_ctrl_t lv)
850    {
851        char txt_sec[128], txt_pub[128];
852        int nkeys = 0, nsec = 0, i;
853    
854        nkeys = listview_count_items (lv, 0);
855        for (i = 0; i < nkeys; i++) {
856            if (km_check_for_seckey (lv, i, NULL))
857                nsec++;
858        }
859        _snprintf (txt_sec, sizeof (txt_sec)-1, _("%d secret keys"), nsec);
860        _snprintf (txt_pub, sizeof (txt_pub)-1, _("%d keys"), nkeys);
861        SendMessage (sb, SB_SETTEXT, 1, (LPARAM)txt_sec);
862        SendMessage (sb, SB_SETTEXT, 2, (LPARAM)txt_pub);
863    }
864    
865    
866    /* Set trust of selected key in @lv (at @pos) to ultimate. */
867    int
868    km_set_implicit_trust (HWND dlg, listview_ctrl_t lv, int pos)
869    {
870        GpgKeyEdit *ke;
871        gpgme_error_t err;    
872        char keyid[32];
873    
874        listview_get_item_text (lv, pos, 1, keyid, 31);
875    
876        ke = new GpgKeyEdit (keyid);
877        if (!ke)
878            BUG (0);
879    
880        err = ke->setTrust (GPGME_VALIDITY_ULTIMATE);
881        if (err)
882            msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
883        else
884            show_msg (dlg, 1500, _("GnuPG Status: Finished"));
885    
886        delete ke;
887        return (int)err;
888    }
889    
890    
891    void
892    km_find_key (HWND dlg, listview_ctrl_t lv)
893    {
894        int oldpos = listview_get_curr_pos (lv);
895        int n;
896        char *name = get_input_dialog (dlg, _("Search"), _("Search for:"));
897        if (name == NULL)
898            return;
899        if (oldpos < 0)
900            oldpos = 0;
901        n = listview_find (lv, name);
902        if (n != -1) {
903            listview_select_one (lv, n);
904            listview_scroll (lv, oldpos, n);
905        }
906        else {
907            const char *s = _("String pattern \"%s\" not found.");
908            char *p = new char[strlen (s) + strlen (name) + 2];
909            if (!p)
910                BUG (0);
911            sprintf (p, s, name);
912            msg_box (dlg, p, _("Key Manager"), MB_INFO);
913            free_if_alloc (p);
914        }
915        free_if_alloc (name);
916    }
917    
918    
919    
920    void
921    km_dump_key (gpgme_key_t key)
922    {
923    #if _DEBUG
924        log_box ("DEBUG", MB_OK,
925                 "%d %d %s %d\n%s", key->subkeys->length,
926                 key->subkeys->pubkey_algo,
927                 key->subkeys->keyid,
928                 key->subkeys->timestamp,
929                 key->uids->uid);
930    #endif
931    }
932    
933    #if 0
934    gpg_optfile_t
935    km_groupdb_open (void)
936    {      
937        gpg_optfile_t opt;
938        char * optfile;
939        int err = 0;
940        
941        optfile = get_gnupg_cfgfile();
942        if( !optfile )
943            BUG( NULL );
944        if( parse_gpg_options( optfile, &opt ) )
945            err = 1;
946        free_if_alloc( optfile );
947        return err? NULL : opt;
948    } /* km_groupdb_open */
949    
950    
951    int
952    km_groupdb_expand_recipients( const char *name, gpgme_recipients_t rset )
953    {  
954        gpg_keycache_t kc;
955        gpgme_key_t pk;
956        gpg_optfile_t opt;
957        gpg_group_t grp;    
958        gpg_member_t mbr;
959        int no_trust = 0, n;
960    
961        kc = keycache_get_ctx( 1 );
962        if( !kc )
963            BUG( NULL );
964    
965        opt = km_groupdb_open( );
966        if( !opt )
967            return WPTERR_FILE_OPEN;
968        
969        grp = find_group( opt, name );
970        if( !grp )
971            return WPTERR_GENERAL;
972        
973        /* we are paranoid and check that all group members exist in the
974           key cache. there is no need that it is really the real key, but
975           an entry should be available. the rest is up to GPG. */
976        for( mbr = grp->list; mbr; mbr = mbr->next ) {
977            if( gpgme_keycache_find_key( kc, mbr->name, 0, &pk ) )
978                BUG( NULL );
979            n = count_userids (pk);
980            while( n-- ) {
981                gpgme_user_id_t u = get_nth_userid (pk, n);
982                const char * s =  u->uid;
983                if( s && stristr( s, mbr->name )
984                    && u->validity < 3 )
985                    no_trust++;
986            }
987        }
988    
989        gpgme_recipients_add_name( rset, name );
990        release_gpg_options( opt );
991        
992        return no_trust;
993    } /* km_groupdb_expand_recipients */
994    
995    
996    static HTREEITEM
997    km_tv_insert_item( HWND tree, HTREEITEM parent, const char *text )
998    {
999        TVINSERTSTRUCT tvis;
1000        HTREEITEM node;
1001        
1002        memset( &tvis, 0, sizeof tvis );
1003        tvis.hParent = parent;
1004        tvis.hInsertAfter = TVI_LAST;
1005        tvis.item.mask = TVIF_TEXT;
1006        tvis.item.pszText = (char *)text;
1007        node = TreeView_InsertItem( tree, &tvis );
1008        return node;
1009    } /* km_tv_insert_item */
1010    
1011    
1012    int
1013    km_groups_new( km_group_t *r_gc, HWND ctrl )
1014    {
1015        km_group_t gc;
1016        
1017        gc = new km_group_s;
1018        if (!gc)
1019            BUG (NULL);
1020        gc->tree = ctrl;
1021        gc->gh = km_groupdb_open ();
1022        *r_gc = gc;
1023        return 0;
1024    } /* km_groups_new */
1025    
1026    
1027    void
1028    km_groups_sync( km_group_t gc )
1029    {
1030        char * optfile;
1031    
1032        optfile = get_gnupg_cfgfile ();
1033        if( !optfile )
1034            BUG( NULL );
1035        commit_gpg_options( optfile, gc->gh );
1036        free_if_alloc( optfile );
1037        gc->need_sync = 0;
1038    } /* km_groups_sync */
1039    
1040    
1041    void
1042    km_groups_release (km_group_t gc)
1043    {
1044        if( gc ) {
1045            /* xxx: this reset the default key (sync=1) */
1046            gc->need_sync=0;
1047            if (gc->need_sync)
1048                km_groups_sync (gc);
1049            if (gc->gh)
1050                release_gpg_options( gc->gh );
1051            gc->gh = NULL;
1052            gc->tree = NULL;
1053            delete gc;
1054        }    
1055    } /* km_groups_release */
1056    
1057    
1058    int
1059    km_groups_load( km_group_t gc )
1060    {    
1061        HTREEITEM n;
1062        gpg_group_t grp, g;
1063        gpg_member_t mbr;
1064        u32 gid = 0;
1065        
1066        if( !gc->gh )
1067            return 0;
1068        grp = gc->gh->grp;
1069        if( !grp )
1070            return 0; /* no groups */
1071            
1072        for( g = grp; g; g = g->next ) {
1073            n = km_tv_insert_item( gc->tree, NULL, g->name );
1074            for( mbr = g->list; mbr; mbr = mbr->next ) {
1075                if( mbr->used && mbr->name )
1076                    km_tv_insert_item( gc->tree, n, mbr->name );
1077            }
1078        }
1079        DragAcceptFiles( gc->tree, TRUE );
1080        gc->need_sync = 0;
1081        return 0;
1082    } /* km_groups_load */
1083    
1084    
1085    int
1086    km_groups_add( km_group_t gc, listview_ctrl_t lv, int km_index )
1087    {
1088        TVITEM tvi;
1089        char uid[128], valid[64], text[128];
1090        int i_valid;
1091        
1092        memset( &tvi, 0, sizeof tvi );
1093        tvi.hItem = TreeView_GetSelection( gc->tree );
1094        tvi.pszText = text;
1095        tvi.cchTextMax = sizeof text -1;
1096        tvi.mask = TVIF_TEXT;
1097        TreeView_GetItem( gc->tree, &tvi );
1098        
1099        
1100        listview_get_item_text( lv, km_index, 0, uid, sizeof uid -1 );
1101        listview_get_item_text( lv, km_index, 5, valid, sizeof valid -1 );
1102        
1103        if( strstr( valid, "Ultimate" ) )
1104            i_valid = 5;    
1105        else if( !strstr( valid, "Full" ) )
1106            i_valid = 4;
1107        else if( !strstr( valid, "Marginal" ) )
1108            i_valid = 3;
1109        else
1110            i_valid = 0;
1111        
1112        /* we can't add the full name. one way would be to use the first
1113           text until a space appears.
1114        group_add_entry(&gc->gh, gid, i_valid, uid);
1115        treeview_add_item(gc->tree, tvi.hItem, uid);
1116        */
1117        gc->need_sync = 1;
1118        
1119        return 0;
1120    } /* km_groups_add */
1121    
1122    
1123    static int
1124    km_groups_del_main( km_group_t gc )
1125    {
1126        TVITEM tvi;
1127        char text[128];
1128        int id;
1129        
1130        memset( &tvi, 0, sizeof tvi );
1131        tvi.hItem = TreeView_GetSelection( gc->tree );
1132        tvi.pszText = text;
1133        tvi.cchTextMax = sizeof text -1;
1134        tvi.mask = TVIF_TEXT;
1135        TreeView_GetItem( gc->tree, &tvi );
1136                                
1137        id = log_box( _("Key Manager"), MB_INFO_ASK,
1138                       _("Do you really want to delete this group?\n\n%s"), text);
1139        if( id == IDNO )
1140            return 0;
1141        delete_group( gc->gh, text );    
1142        TreeView_DeleteItem( gc->tree, &tvi );
1143        gc->need_sync = 1;
1144        
1145        return 0;
1146    } /* km_groups_del */
1147    
1148    
1149    static int
1150    km_groups_del_entry( km_group_t gc )
1151    {
1152        TVITEM tvi;
1153        HTREEITEM root;
1154        int id;
1155        char text[128], info[256];
1156        gpg_group_t  grp = NULL;
1157        
1158        memset( &tvi, 0, sizeof tvi );
1159        tvi.hItem = TreeView_GetSelection( gc->tree );
1160        tvi.pszText = text;
1161        tvi.cchTextMax = sizeof text-1;
1162        tvi.mask = TVIF_TEXT;
1163        TreeView_GetItem( gc->tree, &tvi );
1164        
1165        _snprintf( info, sizeof info -1,
1166                  _("Do you really want to delete this entry?\n\n%s"), text );
1167        
1168        id = msg_box( gc->tree, info, _("Key Manager"), MB_INFO_ASK );
1169        if( id == IDNO )
1170            return 0;
1171    
1172        root = TreeView_GetParent( gc->tree, tvi.hItem );
1173        if( root ) {
1174        }
1175        
1176        delete_member( gc->gh, /*fixme*/NULL, text );
1177        TreeView_DeleteItem( gc->tree, &tvi );
1178        gc->need_sync = 1;
1179        return 0;
1180    } /* km_groups_del_entry */
1181    
1182    
1183    int
1184    km_groups_del( km_group_t gc )
1185    {
1186        if ( TreeView_GetParent( gc->tree, TreeView_GetSelection( gc->tree ) ) )
1187            return km_groups_del_entry( gc );
1188        else
1189            return km_groups_del_main( gc );
1190    } /* km_groups_del */
1191    #endif

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26