From 8a1eb1f24e2a4624d78d3eeb4ab563d9e48ec865 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Tue, 11 Dec 2012 19:48:07 +0100 Subject: Use the same certificate-viewer as the trust-prompt from eds This way it'll be possible to copy whole files if change in one of them will be done. A real code reuse, rather than copy, would be ideal, but the trust-prompt is just a module for evolution-user-prompter. --- smime/gui/certificate-viewer.c | 725 +++++++++++++++++++++++++++++------------ 1 file changed, 514 insertions(+), 211 deletions(-) (limited to 'smime/gui/certificate-viewer.c') diff --git a/smime/gui/certificate-viewer.c b/smime/gui/certificate-viewer.c index 9f140cadaa..ce96e50d35 100644 --- a/smime/gui/certificate-viewer.c +++ b/smime/gui/certificate-viewer.c @@ -17,359 +17,662 @@ * Chris Toshok * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * */ #ifdef HAVE_CONFIG_H #include #endif -#include "certificate-viewer.h" +#include -#include "e-asn1-object.h" +#include "pk11pub.h" +#include "hasht.h" -#include +#include -#include "e-util/e-util.h" -#include "e-util/e-util-private.h" +#include "e-asn1-object.h" +#include "certificate-viewer.h" -typedef struct { - GtkBuilder *builder; - GtkWidget *dialog; - GtkTreeStore *hierarchy_store, *fields_store; - GtkWidget *hierarchy_tree, *fields_tree; - GtkWidget *field_text; - GtkTextTag *text_tag; +#define CERTIFICATE_VIEWER_PRIV_KEY "CertificateViewerPriv-key" - GList *cert_chain; -} CertificateViewerData; +typedef struct _CertificateViewerPriv +{ + GtkWidget *issued_to_cn; + GtkWidget *issued_to_o; + GtkWidget *issued_to_ou; + GtkWidget *issued_to_serial; + GtkWidget *issued_by_cn; + GtkWidget *issued_by_o; + GtkWidget *issued_by_ou; + GtkWidget *validity_issued_on; + GtkWidget *validity_expires_on; + GtkWidget *fingerprints_sha1; + GtkWidget *fingerprints_md5; + GtkWidget *cert_hierarchy_treeview; + GtkWidget *cert_fields_treeview; + GtkWidget *cert_field_value_textview; + + CERTCertificate *cert; + GSList *issuers; + GtkTextTag *monospace_tag; +} CertificateViewerPriv; static void -free_data (gpointer data, - GObject *where_the_object_was) +free_priv_struct (gpointer ptr) { - CertificateViewerData *cvm = data; + CertificateViewerPriv *priv = ptr; + GSList *iter; - g_list_foreach (cvm->cert_chain, (GFunc) g_object_unref, NULL); - g_list_free (cvm->cert_chain); + if (!priv) + return; - g_object_unref (cvm->builder); - g_free (cvm); -} + if (priv->cert) + CERT_DestroyCertificate (priv->cert); -#define NOT_PART_OF_CERT_MARKUP "<Not part of certificate>" + for (iter = priv->issuers; iter; iter = iter->next) { + CERTCertificate *cert = iter->data; + + if (cert) + CERT_DestroyCertificate (cert); + } + + g_slist_free (priv->issuers); + + g_free (priv); +} static void -fill_in_general (CertificateViewerData *cvm_data, - ECert *cert) +begin_section (GtkGrid *add_to, + const gchar *caption, + gint *from_row, + gint for_rows) { - GtkWidget *label; - const gchar *text; - gchar *markup; - - /* issued to */ - label = e_builder_get_widget (cvm_data->builder, "issued-to-cn"); - if (e_cert_get_cn (cert)) { - gtk_label_set_text (GTK_LABEL (label), e_cert_get_cn (cert)); - } - else { - gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP); - } + GtkWidget *widget; + PangoAttribute *attr; + PangoAttrList *bold; + + g_return_if_fail (add_to != NULL); + g_return_if_fail (caption != NULL); + g_return_if_fail (from_row != NULL); + + bold = pango_attr_list_new (); + attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); + pango_attr_list_insert (bold, attr); + + widget = gtk_label_new (caption); + g_object_set (G_OBJECT (widget), + "hexpand", TRUE, + "halign", GTK_ALIGN_START, + "justify", GTK_JUSTIFY_LEFT, + "attributes", bold, + "ellipsize", PANGO_ELLIPSIZE_NONE, + NULL); - label = e_builder_get_widget (cvm_data->builder, "issued-to-o"); - if (e_cert_get_org (cert)) { - gtk_label_set_text (GTK_LABEL (label), e_cert_get_org (cert)); - } - else { - gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP); - } + pango_attr_list_unref (bold); - label = e_builder_get_widget (cvm_data->builder, "issued-to-ou"); - if (e_cert_get_org_unit (cert)) { - gtk_label_set_text (GTK_LABEL (label), e_cert_get_org_unit (cert)); - } - else { - gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP); - } + gtk_grid_attach (add_to, widget, 0, *from_row, 3, 1); + (*from_row)++; - text = e_cert_get_serial_number (cert); - label = e_builder_get_widget (cvm_data->builder, "issued-to-serial"); - gtk_label_set_text (GTK_LABEL (label), text); + widget = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); + gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 12, 0); - /* issued by */ - label = e_builder_get_widget (cvm_data->builder, "issued-by-cn"); - if (e_cert_get_issuer_cn (cert)) { - gtk_label_set_text (GTK_LABEL (label), e_cert_get_issuer_cn (cert)); - } - else { - gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP); - } + gtk_grid_attach (add_to, widget, 0, *from_row, 1, for_rows); +} - label = e_builder_get_widget (cvm_data->builder, "issued-by-o"); - if (e_cert_get_issuer_org (cert)) { - gtk_label_set_text (GTK_LABEL (label), e_cert_get_issuer_org (cert)); - } - else { - gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP); - } +static GtkWidget * +add_info_label (GtkGrid *add_to, + const gchar *caption, + gint *at_row) +{ + GtkWidget *widget; - label = e_builder_get_widget (cvm_data->builder, "issued-by-ou"); - if (e_cert_get_issuer_org_unit (cert)) { - gtk_label_set_text (GTK_LABEL (label), e_cert_get_issuer_org_unit (cert)); - } - else { - gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP); - } + g_return_val_if_fail (add_to != NULL, NULL); + g_return_val_if_fail (at_row != NULL, NULL); - /* validity */ - label = e_builder_get_widget (cvm_data->builder, "validity-issued-on"); - if (e_cert_get_issued_on (cert)) { - gtk_label_set_text (GTK_LABEL (label), e_cert_get_issued_on (cert)); - } - else { - gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP); - } + if (caption) { + widget = gtk_label_new (caption); + g_object_set (G_OBJECT (widget), + "hexpand", FALSE, + "halign", GTK_ALIGN_START, + "justify", GTK_JUSTIFY_LEFT, + "ellipsize", PANGO_ELLIPSIZE_NONE, + NULL); - label = e_builder_get_widget (cvm_data->builder, "validity-expires-on"); - if (e_cert_get_expires_on (cert)) { - gtk_label_set_text (GTK_LABEL (label), e_cert_get_expires_on (cert)); + gtk_grid_attach (add_to, widget, 1, *at_row, 1, 1); } - else { - gtk_label_set_markup (GTK_LABEL (label), NOT_PART_OF_CERT_MARKUP); + + widget = gtk_label_new (""); + g_object_set (G_OBJECT (widget), + "hexpand", TRUE, + "halign", GTK_ALIGN_START, + "justify", GTK_JUSTIFY_LEFT, + "ellipsize", PANGO_ELLIPSIZE_NONE, + "selectable", caption != NULL, + NULL); + + gtk_grid_attach (add_to, widget, caption ? 2 : 1, *at_row, caption ? 1 : 2, 1); + + (*at_row)++; + + return widget; +} + +static GtkWidget * +add_scrolled_window (GtkGrid *add_to, + const gchar *caption, + gint *at_row, + GtkWidget *add_widget) +{ + GtkWidget *widget; + PangoAttribute *attr; + PangoAttrList *bold; + + g_return_val_if_fail (add_to != NULL, NULL); + g_return_val_if_fail (caption != NULL, NULL); + g_return_val_if_fail (at_row != NULL, NULL); + + bold = pango_attr_list_new (); + attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); + pango_attr_list_insert (bold, attr); + + widget = gtk_label_new (caption); + g_object_set (G_OBJECT (widget), + "hexpand", TRUE, + "halign", GTK_ALIGN_START, + "justify", GTK_JUSTIFY_LEFT, + "attributes", bold, + "ellipsize", PANGO_ELLIPSIZE_NONE, + NULL); + + pango_attr_list_unref (bold); + + gtk_grid_attach (add_to, widget, 0, *at_row, 1, 1); + (*at_row)++; + + widget = gtk_scrolled_window_new (NULL, NULL); + g_object_set (G_OBJECT (widget), + "hexpand", TRUE, + "halign", GTK_ALIGN_FILL, + "vexpand", TRUE, + "valign", GTK_ALIGN_FILL, + "hscrollbar-policy", GTK_POLICY_AUTOMATIC, + "vscrollbar-policy", GTK_POLICY_AUTOMATIC, + "shadow-type", GTK_SHADOW_ETCHED_IN, + NULL); + + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (widget), add_widget); + + gtk_grid_attach (add_to, widget, 0, *at_row, 1, 1); + (*at_row)++; + + return add_widget; +} + +#define FLAG_NONE (0) +#define FLAG_PORT_MEMORY (1 << 0) +#define FLAG_MARKUP (1 << 1) + +static void +set_label_text (GtkWidget *label, + const gchar *not_part_markup, + gchar *text, + guint32 flags) +{ + if (text) { + if ((flags & FLAG_MARKUP) != 0) + gtk_label_set_markup (GTK_LABEL (label), text); + else + gtk_label_set_text (GTK_LABEL (label), text); + + if ((flags & FLAG_PORT_MEMORY) != 0) + PORT_Free (text); + else + g_free (text); + } else { + gtk_label_set_markup (GTK_LABEL (label), not_part_markup); } +} - /* fingerprints */ - markup = g_strdup_printf ("%s", e_cert_get_sha1_fingerprint (cert)); - label = e_builder_get_widget (cvm_data->builder, "fingerprints-sha1"); - gtk_label_set_markup (GTK_LABEL (label), markup); - g_free (markup); +static void +get_cert_times (CERTCertificate *cert, + gchar **issued_on, + gchar **expires_on) +{ + PRTime time_issued_on; + PRTime time_expires_on; + PRExplodedTime explodedTime; + struct tm exploded_tm; + gchar buf[128]; + + g_return_if_fail (cert != NULL); + g_return_if_fail (issued_on != NULL); + g_return_if_fail (expires_on != NULL); + + if (SECSuccess != CERT_GetCertTimes (cert, &time_issued_on, &time_expires_on)) + return; + + PR_ExplodeTime (time_issued_on, PR_LocalTimeParameters, &explodedTime); + exploded_tm.tm_sec = explodedTime.tm_sec; + exploded_tm.tm_min = explodedTime.tm_min; + exploded_tm.tm_hour = explodedTime.tm_hour; + exploded_tm.tm_mday = explodedTime.tm_mday; + exploded_tm.tm_mon = explodedTime.tm_month; + exploded_tm.tm_year = explodedTime.tm_year - 1900; + e_utf8_strftime (buf, sizeof (buf), "%x", &exploded_tm); + *issued_on = g_strdup (buf); + + PR_ExplodeTime (time_expires_on, PR_LocalTimeParameters, &explodedTime); + exploded_tm.tm_sec = explodedTime.tm_sec; + exploded_tm.tm_min = explodedTime.tm_min; + exploded_tm.tm_hour = explodedTime.tm_hour; + exploded_tm.tm_mday = explodedTime.tm_mday; + exploded_tm.tm_mon = explodedTime.tm_month; + exploded_tm.tm_year = explodedTime.tm_year - 1900; + e_utf8_strftime (buf, sizeof (buf), "%x", &exploded_tm); + *expires_on = g_strdup (buf); +} - markup = g_strdup_printf ("%s", e_cert_get_md5_fingerprint (cert)); - label = e_builder_get_widget (cvm_data->builder, "fingerprints-md5"); - gtk_label_set_markup (GTK_LABEL (label), markup); - g_free (markup); +static void +fill_general_page (CertificateViewerPriv *priv) +{ + gchar *not_part_markup; + gchar *issued_on = NULL; + gchar *expires_on = NULL; + gchar *port_str; + guchar fingerprint[128]; + SECItem fpItem; + + g_return_if_fail (priv != NULL); + + not_part_markup = g_strconcat ("<", _("Not part of certificate"), ">", NULL); + + set_label_text (priv->issued_to_cn, not_part_markup, CERT_GetCommonName (&priv->cert->subject), FLAG_PORT_MEMORY); + set_label_text (priv->issued_to_o, not_part_markup, CERT_GetOrgName (&priv->cert->subject), FLAG_PORT_MEMORY); + set_label_text (priv->issued_to_ou, not_part_markup, CERT_GetOrgUnitName (&priv->cert->subject), FLAG_PORT_MEMORY); + set_label_text (priv->issued_to_serial, not_part_markup, CERT_Hexify (&priv->cert->serialNumber, TRUE), FLAG_PORT_MEMORY); + + set_label_text (priv->issued_by_cn, not_part_markup, CERT_GetCommonName (&priv->cert->issuer), FLAG_PORT_MEMORY); + set_label_text (priv->issued_by_o, not_part_markup, CERT_GetOrgName (&priv->cert->issuer), FLAG_PORT_MEMORY); + set_label_text (priv->issued_by_ou, not_part_markup, CERT_GetOrgUnitName (&priv->cert->issuer), FLAG_PORT_MEMORY); + + get_cert_times (priv->cert, &issued_on, &expires_on); + set_label_text (priv->validity_issued_on, not_part_markup, issued_on, FLAG_NONE); + set_label_text (priv->validity_expires_on, not_part_markup, expires_on, FLAG_NONE); + + memset (fingerprint, 0, sizeof fingerprint); + PK11_HashBuf ( + SEC_OID_SHA1, fingerprint, + priv->cert->derCert.data, + priv->cert->derCert.len); + fpItem.data = fingerprint; + fpItem.len = SHA1_LENGTH; + port_str = CERT_Hexify (&fpItem, TRUE); + set_label_text (priv->fingerprints_sha1, not_part_markup, g_strconcat ("", port_str, "", NULL), FLAG_MARKUP); + PORT_Free (port_str); + + memset (fingerprint, 0, sizeof fingerprint); + PK11_HashBuf ( + SEC_OID_MD5, fingerprint, + priv->cert->derCert.data, + priv->cert->derCert.len); + fpItem.data = fingerprint; + fpItem.len = MD5_LENGTH; + port_str = CERT_Hexify (&fpItem, TRUE); + set_label_text (priv->fingerprints_md5, not_part_markup, g_strconcat ("", port_str, "", NULL), FLAG_MARKUP); + PORT_Free (port_str); + + g_free (not_part_markup); } static void -populate_fields_tree (CertificateViewerData *cvm_data, +populate_fields_tree (CertificateViewerPriv *priv, EASN1Object *asn1, GtkTreeIter *root) { + GtkTreeStore *fields_store; GtkTreeIter new_iter; + if (!asn1) + return; + + fields_store = GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->cert_fields_treeview))); + /* first insert a node for the current asn1 */ - gtk_tree_store_insert (cvm_data->fields_store, &new_iter, root, -1); + gtk_tree_store_insert (fields_store, &new_iter, root, -1); gtk_tree_store_set ( - cvm_data->fields_store, &new_iter, + fields_store, &new_iter, 0, e_asn1_object_get_display_name (asn1), 1, asn1, -1); if (e_asn1_object_is_valid_container (asn1)) { GList *children = e_asn1_object_get_children (asn1); + if (children) { - GList *l; - for (l = children; l; l = l->next) { - EASN1Object *subasn1 = l->data; - populate_fields_tree (cvm_data, subasn1, &new_iter); + GList *iter; + for (iter = children; iter; iter = iter->next) { + EASN1Object *subasn1 = iter->data; + + populate_fields_tree (priv, subasn1, &new_iter); } } - g_list_foreach (children, (GFunc) g_object_unref, NULL); - g_list_free (children); + + g_list_free_full (children, g_object_unref); } } static void -hierarchy_selection_changed (GtkTreeSelection *selection, - CertificateViewerData *cvm_data) +hierarchy_selection_changed_cb (GtkTreeSelection *selection, + CertificateViewerPriv *priv) { GtkTreeIter iter; GtkTreeModel *model; - if (gtk_tree_selection_get_selected (selection, - &model, - &iter)) { - EASN1Object *asn1_object; - ECert *cert; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + CERTCertificate *cert; + EASN1Object *asn1; + GtkTreeStore *fields_store; - gtk_tree_model_get ( - model, - &iter, - 1, &cert, - -1); + gtk_tree_model_get (model, &iter, 1, &cert, -1); if (!cert) return; /* display the cert's ASN1 structure */ - asn1_object = e_cert_get_asn1_struct (cert); + asn1 = e_asn1_object_new_from_cert (cert); /* wipe out the old model */ - cvm_data->fields_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); + fields_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_OBJECT); gtk_tree_view_set_model ( - GTK_TREE_VIEW (cvm_data->fields_tree), - GTK_TREE_MODEL (cvm_data->fields_store)); + GTK_TREE_VIEW (priv->cert_fields_treeview), + GTK_TREE_MODEL (fields_store)); /* populate the fields from the newly selected cert */ - populate_fields_tree (cvm_data, asn1_object, NULL); - gtk_tree_view_expand_all (GTK_TREE_VIEW (cvm_data->fields_tree)); - g_object_unref (asn1_object); + populate_fields_tree (priv, asn1, NULL); + gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->cert_fields_treeview)); + if (asn1) + g_object_unref (asn1); /* and blow away the field value */ gtk_text_buffer_set_text ( - gtk_text_view_get_buffer (GTK_TEXT_VIEW (cvm_data->field_text)), + gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->cert_field_value_textview)), "", 0); } } static void -fields_selection_changed (GtkTreeSelection *selection, - CertificateViewerData *cvm_data) +fields_selection_changed_cb (GtkTreeSelection *selection, + CertificateViewerPriv *priv) { GtkTreeIter iter; GtkTreeModel *model; - if (gtk_tree_selection_get_selected (selection, - &model, - &iter)) { - EASN1Object *asn1_object; - const gchar *value; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + EASN1Object *asn1 = NULL; + const gchar *value = NULL; + GtkTextView *textview; + GtkTextBuffer *textbuffer; - gtk_tree_model_get ( - model, - &iter, - 1, &asn1_object, - -1); + gtk_tree_model_get (model, &iter, 1, &asn1, -1); - value = e_asn1_object_get_display_value (asn1_object); + if (asn1) + value = e_asn1_object_get_display_value (asn1); - gtk_text_buffer_set_text ( - gtk_text_view_get_buffer (GTK_TEXT_VIEW (cvm_data->field_text)), - "", 0); + textview = GTK_TEXT_VIEW (priv->cert_field_value_textview); + textbuffer = gtk_text_view_get_buffer (textview); + + gtk_text_buffer_set_text (textbuffer, "", 0); if (value) { GtkTextIter text_iter; - gtk_text_buffer_get_start_iter ( - gtk_text_view_get_buffer (GTK_TEXT_VIEW (cvm_data->field_text)), - &text_iter); + gtk_text_buffer_get_start_iter (textbuffer, &text_iter); - gtk_text_buffer_insert_with_tags ( - gtk_text_view_get_buffer (GTK_TEXT_VIEW (cvm_data->field_text)), - &text_iter, + gtk_text_buffer_insert_with_tags (textbuffer, &text_iter, value, strlen (value), - cvm_data->text_tag, NULL); + priv->monospace_tag, NULL); } + + if (asn1) + g_object_unref (asn1); } } static void -fill_in_details (CertificateViewerData *cvm_data, - ECert *cert) +fill_details_page (CertificateViewerPriv *priv) { - GList *l; + GSList *iter; GtkTreeIter root; GtkTreeSelection *selection; gboolean root_set = FALSE; + GtkTreeStore *hierarchy_store; - /* hook up all the hierarchy tree foo */ - cvm_data->hierarchy_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_OBJECT); - cvm_data->hierarchy_tree = e_builder_get_widget (cvm_data->builder, "cert-hierarchy-treeview"); + g_return_if_fail (priv != NULL); + + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->cert_hierarchy_treeview), FALSE); + + hierarchy_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); gtk_tree_view_set_model ( - GTK_TREE_VIEW (cvm_data->hierarchy_tree), - GTK_TREE_MODEL (cvm_data->hierarchy_store)); + GTK_TREE_VIEW (priv->cert_hierarchy_treeview), + GTK_TREE_MODEL (hierarchy_store)); gtk_tree_view_insert_column_with_attributes ( - GTK_TREE_VIEW (cvm_data->hierarchy_tree), + GTK_TREE_VIEW (priv->cert_hierarchy_treeview), -1, "Cert", gtk_cell_renderer_text_new (), "text", 0, NULL); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (cvm_data->hierarchy_tree)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->cert_hierarchy_treeview)); g_signal_connect ( selection, "changed", - G_CALLBACK (hierarchy_selection_changed), cvm_data); + G_CALLBACK (hierarchy_selection_changed_cb), priv); - /* hook up all the fields tree foo */ - cvm_data->fields_tree = e_builder_get_widget (cvm_data->builder, "cert-fields-treeview"); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->cert_fields_treeview), FALSE); gtk_tree_view_insert_column_with_attributes ( - GTK_TREE_VIEW (cvm_data->fields_tree), + GTK_TREE_VIEW (priv->cert_fields_treeview), -1, "Field", gtk_cell_renderer_text_new (), "text", 0, NULL); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (cvm_data->fields_tree)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->cert_fields_treeview)); g_signal_connect ( selection, "changed", - G_CALLBACK (fields_selection_changed), cvm_data); - - /* hook up all the field display foo */ - cvm_data->field_text = e_builder_get_widget (cvm_data->builder, "cert-field-value-textview"); + G_CALLBACK (fields_selection_changed_cb), priv); /* set the font of the field value viewer to be some fixed - * width font to the hex display doesn't look like ass. */ - cvm_data->text_tag = gtk_text_buffer_create_tag ( - gtk_text_view_get_buffer (GTK_TEXT_VIEW (cvm_data->field_text)), - "mono", - "font", "Mono", - NULL); - - /* initially populate the hierarchy from the cert's chain */ - cvm_data->cert_chain = e_cert_get_chain (cert); - cvm_data->cert_chain = g_list_reverse (cvm_data->cert_chain); - for (l = cvm_data->cert_chain; l; l = l->next) { - ECert *c = l->data; - const gchar *str; + * width font to the hex display looks nice. */ + priv->monospace_tag = gtk_text_buffer_create_tag ( + gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->cert_field_value_textview)), + "mono", "font", "Mono", NULL); + + /* initially populate the hierarchy from the issuers' chain */ + for (iter = priv->issuers; iter; iter = g_slist_next (iter)) { + CERTCertificate *cert = iter->data; + gchar *str; GtkTreeIter new_iter; - str = e_cert_get_cn (c); - if (!str) - str = e_cert_get_subject_name (c); + if (!cert) + continue; + + str = CERT_GetCommonName (&cert->subject); - gtk_tree_store_insert (cvm_data->hierarchy_store, &new_iter, root_set ? &root : NULL, -1); + gtk_tree_store_insert (hierarchy_store, &new_iter, root_set ? &root : NULL, -1); gtk_tree_store_set ( - cvm_data->hierarchy_store, &new_iter, - 0, str, - 1, c, + hierarchy_store, &new_iter, + 0, str ? str : cert->subjectName, + 1, cert, -1); root = new_iter; root_set = TRUE; + + if (str) + PORT_Free (str); + } + + gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->cert_hierarchy_treeview)); +} + +static gchar * +get_window_title (CERTCertificate *cert) +{ + gchar *str; + + g_return_val_if_fail (cert != NULL, NULL); + + if (cert->nickname) + return g_strdup (cert->nickname); + + str = CERT_GetCommonName (&cert->subject); + if (str) { + gchar *title; + + title = g_strdup (str); + PORT_Free (str); + + return title; } - gtk_tree_view_expand_all (GTK_TREE_VIEW (cvm_data->hierarchy_tree)); + return cert->subjectName; } GtkWidget * -certificate_viewer_show (ECert *cert) +certificate_viewer_new (GtkWindow *parent, + const CERTCertificate *cert, + const GSList *issuers_chain_certs) { - CertificateViewerData *cvm_data; - GtkDialog *dialog; - GtkWidget *action_area; + CertificateViewerPriv *priv; + GtkWidget *dialog, *notebook, *widget; + GtkGrid *grid; + gint row; + GSList *iter; gchar *title; - cvm_data = g_new0 (CertificateViewerData, 1); + g_return_val_if_fail (cert != NULL, NULL); + + priv = g_new0 (CertificateViewerPriv, 1); + priv->cert = CERT_DupCertificate ((CERTCertificate *) cert); + priv->issuers = g_slist_copy ((GSList *) issuers_chain_certs); - cvm_data->builder = gtk_builder_new (); - e_load_ui_builder_definition (cvm_data->builder, "smime-ui.ui"); + /* root issuer first, then bottom down to certificate itself */ + priv->issuers = g_slist_reverse (priv->issuers); + priv->issuers = g_slist_append (priv->issuers, priv->cert); - cvm_data->dialog = e_builder_get_widget (cvm_data->builder, "certificate-viewer-dialog"); + for (iter = priv->issuers; iter; iter = g_slist_next (iter)) { + iter->data = CERT_DupCertificate (iter->data); + } - gtk_widget_realize (cvm_data->dialog); + title = get_window_title (priv->cert); - dialog = GTK_DIALOG (cvm_data->dialog); - action_area = gtk_dialog_get_action_area (dialog); - gtk_container_set_border_width (GTK_CONTAINER (action_area), 12); + dialog = gtk_dialog_new_with_buttons (title, parent, + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, + GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, + NULL); - title = g_strdup_printf ( - _("Certificate Viewer: %s"), e_cert_get_window_title (cert)); - gtk_window_set_title (GTK_WINDOW (cvm_data->dialog), title); g_free (title); - fill_in_general (cvm_data, cert); - fill_in_details (cvm_data, cert); + g_object_set_data_full (G_OBJECT (dialog), CERTIFICATE_VIEWER_PRIV_KEY, priv, free_priv_struct); + + notebook = gtk_notebook_new (); + gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), notebook); + gtk_container_set_border_width (GTK_CONTAINER (notebook), 12); + + /* General page */ + row = 0; + grid = GTK_GRID (gtk_grid_new ()); + g_object_set (G_OBJECT (grid), + "hexpand", TRUE, + "halign", GTK_ALIGN_FILL, + "vexpand", FALSE, + "valign", GTK_ALIGN_START, + "border-width", 12, + "row-spacing", 6, + "column-spacing", 6, + NULL); + + begin_section (grid, _("This certificate has been verified for the following uses:"), &row, 4); + + if (!priv->cert->keyUsagePresent || (priv->cert->keyUsage & certificateUsageSSLClient) != 0) { + widget = add_info_label (grid, NULL, &row); + gtk_label_set_text (GTK_LABEL (widget), _("SSL Client Certificate")); + } + + if (!priv->cert->keyUsagePresent || (priv->cert->keyUsage & (certificateUsageSSLServer | certificateUsageSSLCA)) != 0) { + widget = add_info_label (grid, NULL, &row); + gtk_label_set_text (GTK_LABEL (widget), _("SSL Server Certificate")); + } + + if (!priv->cert->keyUsagePresent || (priv->cert->keyUsage & certificateUsageEmailSigner) != 0) { + widget = add_info_label (grid, NULL, &row); + gtk_label_set_text (GTK_LABEL (widget), _("Email Signer Certificate")); + } + + if (!priv->cert->keyUsagePresent || (priv->cert->keyUsage & certificateUsageEmailRecipient) != 0) { + widget = add_info_label (grid, NULL, &row); + gtk_label_set_text (GTK_LABEL (widget), _("Email Recipient Certificate")); + } + + widget = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); + g_object_set (G_OBJECT (widget), + "hexpand", TRUE, + "halign", GTK_ALIGN_FILL, + "vexpand", FALSE, + "valign", GTK_ALIGN_START, + NULL); + + gtk_grid_attach (grid, widget, 0, row, 3, 1); + row++; + + begin_section (grid, _("Issued To"), &row, 4); + priv->issued_to_cn = add_info_label (grid, _("Common Name (CN)"), &row); + priv->issued_to_o = add_info_label (grid, _("Organization (O)"), &row); + priv->issued_to_ou = add_info_label (grid, _("Organizational Unit (OU)"), &row); + priv->issued_to_serial = add_info_label (grid, _("Serial Number"), &row); + + begin_section (grid, _("Issued By"), &row, 3); + priv->issued_by_cn = add_info_label (grid, _("Common Name (CN)"), &row); + priv->issued_by_o = add_info_label (grid, _("Organization (O)"), &row); + priv->issued_by_ou = add_info_label (grid, _("Organizational Unit (OU)"), &row); + + begin_section (grid, _("Validity"), &row, 2); + priv->validity_issued_on = add_info_label (grid, _("Issued On"), &row); + priv->validity_expires_on = add_info_label (grid, _("Expires On"), &row); + + begin_section (grid, _("Fingerprints"), &row, 2); + priv->fingerprints_sha1 = add_info_label (grid, _("SHA1 Fingerprint"), &row); + priv->fingerprints_md5 = add_info_label (grid, _("MD5 Fingerprint"), &row); + + widget = gtk_label_new (_("General")); + gtk_notebook_append_page (GTK_NOTEBOOK (notebook), GTK_WIDGET (grid), widget); + + /* Details page */ + row = 0; + grid = GTK_GRID (gtk_grid_new ()); + g_object_set (G_OBJECT (grid), + "hexpand", TRUE, + "halign", GTK_ALIGN_FILL, + "vexpand", TRUE, + "valign", GTK_ALIGN_FILL, + "border-width", 12, + "row-spacing", 6, + "column-spacing", 6, + NULL); + + priv->cert_hierarchy_treeview = add_scrolled_window (grid, + _("Certificate Hierarchy"), &row, gtk_tree_view_new ()); + + priv->cert_fields_treeview = add_scrolled_window (grid, + _("Certificate Fields"), &row, gtk_tree_view_new ()); + + priv->cert_field_value_textview = add_scrolled_window (grid, + _("Field Value"), &row, gtk_text_view_new ()); + + widget = gtk_label_new (_("Details")); + gtk_notebook_append_page (GTK_NOTEBOOK (notebook), GTK_WIDGET (grid), widget); + + gtk_widget_show_all (notebook); - g_object_weak_ref (G_OBJECT (cvm_data->dialog), free_data, cvm_data); + fill_general_page (priv); + fill_details_page (priv); - /* gtk_widget_show (cvm_data->dialog);*/ - return cvm_data->dialog; + return dialog; } -- cgit v1.2.3