2009-01-06 [colin] 3.7.0cvs15
[claws.git] / src / plugins / pgpcore / select-keys.c
index 924881cf87009c40cac63c5cc52b9f630b64966d..c2000358fefe6018ab064123a34dbba75cf49830 100644 (file)
@@ -1,9 +1,9 @@
 /* select-keys.c - GTK+ based key selection
- *      Copyright (C) 2001-2006 Werner Koch (dd9jn) and the Sylpheed-Claws team
+ *      Copyright (C) 2001-2007 Werner Koch (dd9jn) and the Claws Mail team
  *
  * This program 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
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -12,8 +12,8 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
  */
 
 #ifdef HAVE_CONFIG_H
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gdk/gdkkeysyms.h>
-#include <gtk/gtkmain.h>
-#include <gtk/gtkwidget.h>
-#include <gtk/gtkwindow.h>
-#include <gtk/gtkscrolledwindow.h>
-#include <gtk/gtkvbox.h>
-#include <gtk/gtkhbox.h>
-#include <gtk/gtkclist.h>
-#include <gtk/gtklabel.h>
-#include <gtk/gtkentry.h>
-#include <gtk/gtkhbbox.h>
-#include <gtk/gtkbutton.h>
-#include <gtk/gtkstock.h>
-
+#include <gtk/gtk.h>
 #include "select-keys.h"
 #include "utils.h"
 #include "gtkutils.h"
@@ -65,7 +53,7 @@ struct select_keys_s {
     int okay;
     GtkWidget *window;
     GtkLabel *toplabel;
-    GtkCList *clist;
+    GtkCMCList *clist;
     const char *pattern;
     unsigned int num_keys;
     gpgme_key_t *kset;
@@ -77,7 +65,7 @@ struct select_keys_s {
 };
 
 
-static void set_row (GtkCList *clist, gpgme_key_t key);
+static void set_row (GtkCMCList *clist, gpgme_key_t key, gpgme_protocol_t proto);
 static gpgme_key_t fill_clist (struct select_keys_s *sk, const char *pattern,
                        gpgme_protocol_t proto);
 static void create_dialog (struct select_keys_s *sk);
@@ -95,7 +83,7 @@ static void sort_keys (struct select_keys_s *sk, enum col_titles column);
 static void sort_keys_name (GtkWidget *widget, gpointer data);
 static void sort_keys_email (GtkWidget *widget, gpointer data);
 
-static gboolean use_untrusted (gpgme_key_t);
+static gboolean use_untrusted (gpgme_key_t, gpgme_protocol_t proto);
 
 static void
 update_progress (struct select_keys_s *sk, int running, const char *pattern)
@@ -138,7 +126,7 @@ gpgmegtk_recipient_selection (GSList *recp_names, SelectionResult *result,
     do {
         sk.pattern = recp_names? recp_names->data:NULL;
        sk.proto = proto;
-        gtk_clist_clear (sk.clist);
+        gtk_cmclist_clear (sk.clist);
         key = fill_clist (&sk, sk.pattern, proto);
         update_progress (&sk, 0, sk.pattern);
        if (!key) {
@@ -155,7 +143,7 @@ gpgmegtk_recipient_selection (GSList *recp_names, SelectionResult *result,
                sk.result = KEY_SELECTION_OK;
                gpgme_release (sk.select_ctx);
                sk.select_ctx = NULL;
-               printf("used %s\n", key->uids->email);
+               debug_print("used %s\n", key->uids->email);
        }
        key = NULL;
         if (recp_names)
@@ -184,19 +172,20 @@ destroy_key (gpointer data)
 }
 
 static void
-set_row (GtkCList *clist, gpgme_key_t key)
+set_row (GtkCMCList *clist, gpgme_key_t key, gpgme_protocol_t proto)
 {
     const char *s;
     const char *text[N_COL_TITLES];
     char *algo_buf;
     int row;
     gsize by_read = 0, by_written = 0;
-    gchar *ret_str;
+    gchar *ret_str = NULL;
 
     /* first check whether the key is capable of encryption which is not
      * the case for revoked, expired or sign-only keys */
-    if (!key->can_encrypt)
+    if (!key->can_encrypt || key->revoked || key->expired)
         return;
+
     algo_buf = g_strdup_printf ("%du/%s", 
          key->subkeys->length,
          gpgme_pubkey_algo_name(key->subkeys->pubkey_algo) );
@@ -207,17 +196,38 @@ set_row (GtkCList *clist, gpgme_key_t key)
         s += 8; /* show only the short keyID */
     text[COL_KEYID] = s;
 
+
     s = key->uids->name;
-    if (!s || !strlen(s))
+    if (!s || !*s)
         s = key->uids->uid;
-    ret_str = g_locale_to_utf8 (s, strlen(s), &by_read, &by_written, NULL);
+    if (proto == GPGME_PROTOCOL_CMS) {
+       if (strstr(s, ",CN="))
+               s = strstr(s, ",CN=")+4;
+       else if (strstr(s, "CN="))
+               s = strstr(s, "CN=")+3;
+    } 
+    
+    ret_str = NULL;
+    if (!g_utf8_validate(s, -1, NULL))
+           ret_str = g_locale_to_utf8 (s, strlen(s), &by_read, &by_written, NULL);
     if (ret_str && by_written) {
         s = ret_str;
     }
     text[COL_NAME] = s;
 
-    s = key->uids->email;
-    ret_str = g_locale_to_utf8 (s, strlen(s), &by_read, &by_written, NULL);
+    if (proto == GPGME_PROTOCOL_CMS && (!key->uids->email || !*key->uids->email)) {
+       gpgme_user_id_t uid = key->uids->next;
+       if (uid)
+               s = uid->email;
+       else
+               s = key->uids->email;
+    } else {
+        s = key->uids->email;
+    }
+    
+    ret_str = NULL;
+    if (!g_utf8_validate(s, -1, NULL))
+           ret_str = g_locale_to_utf8 (s, strlen(s), &by_read, &by_written, NULL);
     if (ret_str && by_written) {
         s = ret_str;
     }
@@ -226,37 +236,37 @@ set_row (GtkCList *clist, gpgme_key_t key)
     switch (key->uids->validity)
       {
       case GPGME_VALIDITY_UNDEFINED:
-        s = "q";
+        s = _("Undefined");
         break;
       case GPGME_VALIDITY_NEVER:
-        s = "n";
+        s = _("Never");
         break;
       case GPGME_VALIDITY_MARGINAL:
-        s = "m";
+        s = _("Marginal");
         break;
       case GPGME_VALIDITY_FULL:
-        s = "f";
+        s = _("Full");
         break;
       case GPGME_VALIDITY_ULTIMATE:
-        s = "u";
+        s = _("Ultimate");
         break;
       case GPGME_VALIDITY_UNKNOWN:
       default:
-        s = "?";
+        s = _("Unknown");
         break;
       }
     text[COL_VALIDITY] = s;
 
-    row = gtk_clist_append (clist, (gchar**)text);
+    row = gtk_cmclist_append (clist, (gchar**)text);
     g_free (algo_buf);
 
-    gtk_clist_set_row_data_full (clist, row, key, destroy_key);
+    gtk_cmclist_set_row_data_full (clist, row, key, destroy_key);
 }
 
 static gpgme_key_t 
 fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t proto)
 {
-    GtkCList *clist;
+    GtkCMCList *clist;
     gpgme_ctx_t ctx;
     gpgme_error_t err;
     gpgme_key_t key;
@@ -270,7 +280,7 @@ fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t prot
 
     debug_print ("select_keys:fill_clist:  pattern '%s' proto %d\n", pattern, proto);
 
-    /*gtk_clist_freeze (select_keys.clist);*/
+    /*gtk_cmclist_freeze (select_keys.clist);*/
     err = gpgme_new (&ctx);
     g_assert (!err);
 
@@ -287,18 +297,28 @@ fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t prot
                      pattern, gpgme_strerror (err));
         sk->select_ctx = NULL;
         gpgme_release(ctx);
-        return FALSE;
+        return NULL;
     }
     update_progress (sk, ++running, pattern);
     while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) {
        gpgme_user_id_t uid = key->uids;
+       if (!key->can_encrypt || key->revoked || key->expired)
+               continue;
         debug_print ("%% %s:%d:  insert\n", __FILE__ ,__LINE__ );
-        set_row (clist, key ); 
+        set_row (clist, key, proto ); 
        for (; uid; uid = uid->next) {
-               if (!strcmp(pattern, uid->email)) {
+               gchar *raw_mail = NULL;
+
+               if (!uid->email)
+                       continue;
+               raw_mail = g_strdup(uid->email);
+               extract_address(raw_mail);
+               if (!strcasecmp(pattern, raw_mail)) {
                        exact_match = TRUE;
+                       g_free(raw_mail);
                        break;
                }
+               g_free(raw_mail);
        }
        num_results++;
        last_key = key;
@@ -310,7 +330,7 @@ fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t prot
  
     if (exact_match == TRUE && num_results == 1) {
            if (last_key->uids->validity < GPGME_VALIDITY_FULL && 
-               !use_untrusted(last_key))
+               !use_untrusted(last_key, proto))
                    exact_match = FALSE;
     }
 
@@ -324,7 +344,7 @@ fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t prot
            sk->select_ctx = NULL;
            gpgme_release (ctx);
     }
-    /*gtk_clist_thaw (select_keys.clist);*/
+    /*gtk_cmclist_thaw (select_keys.clist);*/
     return (exact_match == TRUE && num_results == 1 ? last_key:NULL);
 }
 
@@ -342,7 +362,7 @@ create_dialog (struct select_keys_s *sk)
     const char *titles[N_COL_TITLES];
 
     g_assert (!sk->window);
-    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    window = gtkut_window_new (GTK_WINDOW_TOPLEVEL, "select-keys");
     gtk_widget_set_size_request (window, 520, 280);
     gtk_container_set_border_width (GTK_CONTAINER (window), 8);
     gtk_window_set_title (GTK_WINDOW (window), _("Select Keys"));
@@ -375,20 +395,20 @@ create_dialog (struct select_keys_s *sk)
     titles[COL_KEYID]    = _("Key ID");
     titles[COL_NAME]     = _("Name");
     titles[COL_EMAIL]    = _("Address");
-    titles[COL_VALIDITY] = _("Val");
+    titles[COL_VALIDITY] = _("Trust");
 
-    clist = gtk_clist_new_with_titles (N_COL_TITLES, (char**)titles);
+    clist = gtk_cmclist_new_with_titles (N_COL_TITLES, (char**)titles);
     gtk_container_add (GTK_CONTAINER (scrolledwin), clist);
-    gtk_clist_set_column_width (GTK_CLIST(clist), COL_ALGO,      72);
-    gtk_clist_set_column_width (GTK_CLIST(clist), COL_KEYID,     76);
-    gtk_clist_set_column_width (GTK_CLIST(clist), COL_NAME,     130);
-    gtk_clist_set_column_width (GTK_CLIST(clist), COL_EMAIL,    130);
-    gtk_clist_set_column_width (GTK_CLIST(clist), COL_VALIDITY,  20);
-    gtk_clist_set_selection_mode (GTK_CLIST(clist), GTK_SELECTION_BROWSE);
-    g_signal_connect (G_OBJECT(GTK_CLIST(clist)->column[COL_NAME].button),
+    gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_ALGO,      72);
+    gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_KEYID,     76);
+    gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_NAME,     130);
+    gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_EMAIL,    130);
+    gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_VALIDITY,  20);
+    gtk_cmclist_set_selection_mode (GTK_CMCLIST(clist), GTK_SELECTION_BROWSE);
+    g_signal_connect (G_OBJECT(GTK_CMCLIST(clist)->column[COL_NAME].button),
                      "clicked",
                       G_CALLBACK(sort_keys_name), sk);
-    g_signal_connect (G_OBJECT(GTK_CLIST(clist)->column[COL_EMAIL].button),
+    g_signal_connect (G_OBJECT(GTK_CMCLIST(clist)->column[COL_EMAIL].button),
                      "clicked",
                       G_CALLBACK(sort_keys_email), sk);
 
@@ -396,9 +416,9 @@ create_dialog (struct select_keys_s *sk)
     gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 
     gtkut_stock_button_set_create (&bbox, 
-                                   &select_btn, _("Select"),
-                                  &other_btn, _("Other"),
-                                  &dont_encrypt_btn, _("Don't encrypt"));
+                                   &select_btn, _("_Select"),
+                                  &other_btn, _("_Other"),
+                                  &dont_encrypt_btn, _("Do_n't encrypt"));
     
     cancel_btn = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
     GTK_WIDGET_SET_FLAGS(cancel_btn, GTK_CAN_DEFAULT);
@@ -421,7 +441,7 @@ create_dialog (struct select_keys_s *sk)
 
     sk->window = window;
     sk->toplabel = GTK_LABEL (label);
-    sk->clist  = GTK_CLIST (clist);
+    sk->clist  = GTK_CMCLIST (clist);
 }
 
 
@@ -486,10 +506,10 @@ select_btn_cb (GtkWidget *widget, gpointer data)
         return;
     }
     row = GPOINTER_TO_INT(sk->clist->selection->data);
-    key = gtk_clist_get_row_data(sk->clist, row);
+    key = gtk_cmclist_get_row_data(sk->clist, row);
     if (key) {
         if ( key->uids->validity < GPGME_VALIDITY_FULL ) {
-            use_key = use_untrusted(key);
+            use_key = use_untrusted(key, sk->proto);
             if (!use_key) {
                 debug_print ("** Key untrusted, will not encrypt");
                 return;
@@ -555,10 +575,15 @@ other_btn_cb (GtkWidget *widget, gpointer data)
 
 
 static gboolean
-use_untrusted (gpgme_key_t key)
+use_untrusted (gpgme_key_t key, gpgme_protocol_t proto)
 {
     AlertValue aval;
-    gchar *buf = g_strdup_printf(_("The key of '%s' is not fully trusted.\n"
+    gchar *buf = NULL;
+    
+    if (proto != GPGME_PROTOCOL_OpenPGP)
+       return TRUE;
+
+    buf = g_strdup_printf(_("The key of '%s' is not fully trusted.\n"
               "If you choose to encrypt the message with this key you don't\n"
               "know for sure that it will go to the person you mean it to.\n"
               "Do you trust it enough to use it anyway?"), key->uids->email);
@@ -575,10 +600,10 @@ use_untrusted (gpgme_key_t key)
 
 
 static gint 
-cmp_name (GtkCList *clist, gconstpointer pa, gconstpointer pb)
+cmp_name (GtkCMCList *clist, gconstpointer pa, gconstpointer pb)
 {
-    gpgme_key_t a = ((GtkCListRow *)pa)->data;
-    gpgme_key_t b = ((GtkCListRow *)pb)->data;
+    gpgme_key_t a = ((GtkCMCListRow *)pa)->data;
+    gpgme_key_t b = ((GtkCMCListRow *)pb)->data;
     const char *sa, *sb;
     
     sa = a? a->uids->name : NULL;
@@ -591,10 +616,10 @@ cmp_name (GtkCList *clist, gconstpointer pa, gconstpointer pb)
 }
 
 static gint 
-cmp_email (GtkCList *clist, gconstpointer pa, gconstpointer pb)
+cmp_email (GtkCMCList *clist, gconstpointer pa, gconstpointer pb)
 {
-    gpgme_key_t a = ((GtkCListRow *)pa)->data;
-    gpgme_key_t b = ((GtkCListRow *)pb)->data;
+    gpgme_key_t a = ((GtkCMCListRow *)pa)->data;
+    gpgme_key_t b = ((GtkCMCListRow *)pb)->data;
     const char *sa, *sb;
     
     sa = a? a->uids->email : NULL;
@@ -609,14 +634,14 @@ cmp_email (GtkCList *clist, gconstpointer pa, gconstpointer pb)
 static void
 sort_keys ( struct select_keys_s *sk, enum col_titles column)
 {
-    GtkCList *clist = sk->clist;
+    GtkCMCList *clist = sk->clist;
 
     switch (column) {
       case COL_NAME:
-        gtk_clist_set_compare_func (clist, cmp_name);
+        gtk_cmclist_set_compare_func (clist, cmp_name);
         break;
       case COL_EMAIL:
-        gtk_clist_set_compare_func (clist, cmp_email);
+        gtk_cmclist_set_compare_func (clist, cmp_email);
         break;
       default:
         return;
@@ -631,8 +656,8 @@ sort_keys ( struct select_keys_s *sk, enum col_titles column)
         sk->sort_type = GTK_SORT_ASCENDING;
 
     sk->sort_column = column;
-    gtk_clist_set_sort_type (clist, sk->sort_type);
-    gtk_clist_sort (clist);
+    gtk_cmclist_set_sort_type (clist, sk->sort_type);
+    gtk_cmclist_sort (clist);
 }
 
 static void