aboutsummaryrefslogblamecommitdiffstats
path: root/smime/gui/certificate-manager.c
blob: 97d0a1d919de5f688c08c8f6cc8e523abc79f988 (plain) (tree)

























































































































































































































































































































































                                                                                                                  
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 *  Authors: Chris Toshok <toshok@ximian.com>
 *
 *  Copyright (C) 2003 Ximian, Inc. (www.ximian.com)
 *
 *  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
 *  (at your option) any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
 *
 */

#define GLADE_FILE_NAME "smime-ui.glade"

#include <gtk/gtkcontainer.h>
#include <gtk/gtktreeview.h>
#include <gtk/gtktreestore.h>
#include <gtk/gtktreemodelsort.h>
#include <gtk/gtkcellrenderertext.h>

#include <libgnome/gnome-i18n.h>

#include <glade/glade.h>
#include "evolution-config-control.h"
#include "certificate-manager.h"

#include "e-cert.h"

#include "nss.h"
#include <cms.h>
#include <cert.h>
#include <certdb.h>
#include <pkcs11.h>
#include <pk11func.h>

typedef struct {
    GladeXML *gui;

    GtkWidget *yourcerts_treeview;
    GtkTreeStore *yourcerts_treemodel;
    GHashTable *yourcerts_root_hash;

    GtkWidget *contactcerts_treeview;
    GtkTreeStore *contactcerts_treemodel;
    GHashTable *contactcerts_root_hash;

    GtkWidget *authoritycerts_treeview;
    GtkTreeStore *authoritycerts_treemodel;
    GHashTable *authoritycerts_root_hash;
} CertificateManagerData;

typedef enum {
    USER_CERT,
    CONTACT_CERT,
    CA_CERT
} CertType;

static void
initialize_yourcerts_ui (CertificateManagerData *cfm)
{
    GtkCellRenderer *cell = gtk_cell_renderer_text_new ();

    gtk_tree_view_append_column (GTK_TREE_VIEW (cfm->yourcerts_treeview),
                     gtk_tree_view_column_new_with_attributes (_("Certificate Name"),
                                           cell,
                                           "text", 0,
                                           NULL));

    gtk_tree_view_append_column (GTK_TREE_VIEW (cfm->yourcerts_treeview),
                     gtk_tree_view_column_new_with_attributes (_("Purposes"),
                                           cell,
                                           "text", 1,
                                           NULL));

    gtk_tree_view_append_column (GTK_TREE_VIEW (cfm->yourcerts_treeview),
                     gtk_tree_view_column_new_with_attributes (_("Serial Number"),
                                           cell,
                                           "text", 2,
                                           NULL));

    gtk_tree_view_append_column (GTK_TREE_VIEW (cfm->yourcerts_treeview),
                     gtk_tree_view_column_new_with_attributes (_("Expires"),
                                           cell,
                                           "text", 3,
                                           NULL));

    cfm->yourcerts_treemodel = gtk_tree_store_new (4,
                               G_TYPE_STRING,
                               G_TYPE_STRING,
                               G_TYPE_STRING,
                               G_TYPE_STRING);

    gtk_tree_view_set_model (GTK_TREE_VIEW (cfm->yourcerts_treeview),
                 GTK_TREE_MODEL (cfm->yourcerts_treemodel));

    cfm->yourcerts_root_hash = g_hash_table_new (g_str_hash, g_str_equal);
}

static void
initialize_contactcerts_ui (CertificateManagerData *cfm)
{
    GtkCellRenderer *cell = gtk_cell_renderer_text_new ();

    gtk_tree_view_append_column (GTK_TREE_VIEW (cfm->contactcerts_treeview),
                     gtk_tree_view_column_new_with_attributes (_("Certificate Name"),
                                           cell,
                                           "text", 0,
                                           NULL));

    gtk_tree_view_append_column (GTK_TREE_VIEW (cfm->contactcerts_treeview),
                     gtk_tree_view_column_new_with_attributes (_("E-Mail Address"),
                                           cell,
                                           "text", 1,
                                           NULL));

    gtk_tree_view_append_column (GTK_TREE_VIEW (cfm->contactcerts_treeview),
                     gtk_tree_view_column_new_with_attributes (_("Purposes"),
                                           cell,
                                           "text", 2,
                                           NULL));

    cfm->contactcerts_treemodel = gtk_tree_store_new (3,
                              G_TYPE_STRING,
                              G_TYPE_STRING,
                              G_TYPE_STRING);
    
    gtk_tree_view_set_model (GTK_TREE_VIEW (cfm->contactcerts_treeview),
                 GTK_TREE_MODEL (cfm->contactcerts_treemodel));

    cfm->contactcerts_root_hash = g_hash_table_new (g_str_hash, g_str_equal);
}

static gint
iter_string_compare (GtkTreeModel *model,
             GtkTreeIter  *a,
             GtkTreeIter  *b,
             gpointer      user_data)
{
    char *string1, *string2;

    gtk_tree_model_get (model, a,
                0, &string1,
                -1);

    gtk_tree_model_get (model, b,
                0, &string2,
                -1);

    return g_utf8_collate (string1, string2);
}

static void
initialize_authoritycerts_ui (CertificateManagerData *cfm)
{
    GtkCellRenderer *cell = gtk_cell_renderer_text_new ();

    gtk_tree_view_append_column (GTK_TREE_VIEW (cfm->authoritycerts_treeview),
                     gtk_tree_view_column_new_with_attributes (_("Certificate Name"),
                                           cell,
                                           "text", 0,
                                           NULL));

    cfm->authoritycerts_treemodel = gtk_tree_store_new (1,
                                G_TYPE_STRING);

    gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (cfm->authoritycerts_treemodel),
                     0,
                     iter_string_compare, NULL, NULL);

    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (cfm->authoritycerts_treemodel),
                          0,
                          GTK_SORT_ASCENDING);

    gtk_tree_view_set_model (GTK_TREE_VIEW (cfm->authoritycerts_treeview),
                 GTK_TREE_MODEL (cfm->authoritycerts_treemodel));

    cfm->authoritycerts_root_hash = g_hash_table_new (g_str_hash, g_str_equal);
}

static CertType
get_cert_type (ECert *cert)
{
    const char *nick = e_cert_get_nickname (cert);
    const char *email = e_cert_get_email (cert);

    if (e_cert_is_ca_cert (cert))
        return CA_CERT;

    /* XXX more stuff in here */
    else
        return USER_CERT;
}

typedef void (*AddCertCb)(CertificateManagerData *cfm, ECert *cert);

static void
add_user_cert (CertificateManagerData *cfm, ECert *cert)
{
    GtkTreeIter iter;
    GtkTreeIter *parent_iter = NULL;
    const char *organization = e_cert_get_org (cert);
    const char *common_name;

    if (organization) {
        parent_iter = g_hash_table_lookup (cfm->yourcerts_root_hash, organization);
        if (!parent_iter) {
            /* create a new toplevel node */
            gtk_tree_store_append (GTK_TREE_STORE (cfm->yourcerts_treemodel), &iter, NULL);
        
            gtk_tree_store_set (GTK_TREE_STORE (cfm->yourcerts_treemodel), &iter,
                        0, organization, -1);

            /* now copy it off into parent_iter and insert it into
               the hashtable */
            parent_iter = gtk_tree_iter_copy (&iter);
            g_hash_table_insert (cfm->yourcerts_root_hash, g_strdup (organization), parent_iter);
        }
    }

    gtk_tree_store_append (GTK_TREE_STORE (cfm->yourcerts_treemodel), &iter, parent_iter);

    common_name = e_cert_get_cn (cert);
    if (common_name) {
        gtk_tree_store_set (GTK_TREE_STORE (cfm->yourcerts_treemodel), &iter,
                    0, common_name, -1);
    }
    else
        gtk_tree_store_set (GTK_TREE_STORE (cfm->yourcerts_treemodel), &iter,
                    0, e_cert_get_nickname (cert), -1);
}

static void
add_contact_cert (CertificateManagerData *cfm, ECert *cert)
{
    /* nothing yet */
}

static void
add_ca_cert (CertificateManagerData *cfm, ECert *cert)
{
    GtkTreeIter iter;
    GtkTreeIter *parent_iter = NULL;
    const char *organization = e_cert_get_org (cert);
    const char *common_name;

    if (organization) {
        parent_iter = g_hash_table_lookup (cfm->authoritycerts_root_hash, organization);
        if (!parent_iter) {
            /* create a new toplevel node */
            gtk_tree_store_append (GTK_TREE_STORE (cfm->authoritycerts_treemodel), &iter, NULL);
        
            gtk_tree_store_set (GTK_TREE_STORE (cfm->authoritycerts_treemodel), &iter,
                        0, organization, -1);

            /* now copy it off into parent_iter and insert it into
               the hashtable */
            parent_iter = gtk_tree_iter_copy (&iter);
            g_hash_table_insert (cfm->authoritycerts_root_hash, g_strdup (organization), parent_iter);
        }
    }


    gtk_tree_store_append (GTK_TREE_STORE (cfm->authoritycerts_treemodel), &iter, parent_iter);

    common_name = e_cert_get_cn (cert);
    if (common_name) {
        gtk_tree_store_set (GTK_TREE_STORE (cfm->authoritycerts_treemodel), &iter,
                    0, common_name, -1);
    }
    else
        gtk_tree_store_set (GTK_TREE_STORE (cfm->authoritycerts_treemodel), &iter,
                    0, e_cert_get_nickname (cert), -1);
}

static void
load_certs (CertificateManagerData *cfm,
        CertType type,
        AddCertCb add_cert)
{
    CERTCertList *certList;
    CERTCertListNode *node;

    certList = PK11_ListCerts (PK11CertListUnique, NULL);

    printf ("certList = %p\n", certList);

    for (node = CERT_LIST_HEAD(certList);
         !CERT_LIST_END(node, certList);
         node = CERT_LIST_NEXT(node)) {
        ECert *cert = e_cert_new ((CERTCertificate*)node->cert);
        if (get_cert_type(cert) == type) {
            printf ("cert (nickname = '%s') matches\n", e_cert_get_nickname (cert));
            add_cert (cfm, cert);
        }
        /* XXX we leak cert */
    }

}

static void
populate_ui (CertificateManagerData *cfm)
{
    load_certs (cfm, USER_CERT, add_user_cert);
    load_certs (cfm, CONTACT_CERT, add_contact_cert);
    load_certs (cfm, CA_CERT, add_ca_cert);
}

EvolutionConfigControl*
certificate_manager_config_control_new (void)
{
    CertificateManagerData *cfm_data = g_new0 (CertificateManagerData, 1);
    GtkWidget *control_widget;

    /* XXX this should happen someplace else, and shouldn't
       reference my default mozilla profile :) */
    NSS_InitReadWrite ("/home/toshok/.mozilla/default/xuvq7jx3.slt");

    cfm_data->gui = glade_xml_new (EVOLUTION_GLADEDIR "/" GLADE_FILE_NAME, NULL, NULL);

    cfm_data->yourcerts_treeview = glade_xml_get_widget (cfm_data->gui, "yourcerts-treeview");
    cfm_data->contactcerts_treeview = glade_xml_get_widget (cfm_data->gui, "contactcerts-treeview");
    cfm_data->authoritycerts_treeview = glade_xml_get_widget (cfm_data->gui, "authoritycerts-treeview");

    initialize_yourcerts_ui(cfm_data);
    initialize_contactcerts_ui(cfm_data);
    initialize_authoritycerts_ui(cfm_data);

    populate_ui (cfm_data);

    control_widget = glade_xml_get_widget (cfm_data->gui, "cert-manager-notebook");
    gtk_widget_ref (control_widget);

    gtk_container_remove (GTK_CONTAINER (control_widget->parent), control_widget);

    return evolution_config_control_new (control_widget);
}