[evolution] Use the same certificate-viewer as the trust-prompt from eds



commit 8a1eb1f24e2a4624d78d3eeb4ab563d9e48ec865
Author: Milan Crha <mcrha redhat com>
Date:   Tue Dec 11 19:48:07 2012 +0100

    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.

 em-format/e-mail-formatter-secure-button.c |   21 +-
 po/POTFILES.in                             |    1 +
 smime/gui/ca-trust-dialog.c                |    8 +-
 smime/gui/ca-trust-dialog.h                |    6 +-
 smime/gui/certificate-manager.c            |   33 +-
 smime/gui/certificate-manager.h            |    4 +
 smime/gui/certificate-viewer.c             |  725 ++++++++++++++++-------
 smime/gui/certificate-viewer.h             |   13 +-
 smime/gui/smime-ui.ui                      |  708 ---------------------
 smime/lib/e-asn1-object.c                  |  914 +++++++++++++++++++++++-----
 smime/lib/e-asn1-object.h                  |   45 +-
 smime/lib/e-cert.c                         |  769 +-----------------------
 smime/lib/e-cert.h                         |    2 +-
 13 files changed, 1369 insertions(+), 1880 deletions(-)
---
diff --git a/em-format/e-mail-formatter-secure-button.c b/em-format/e-mail-formatter-secure-button.c
index f5f51d2..2b61a74 100644
--- a/em-format/e-mail-formatter-secure-button.c
+++ b/em-format/e-mail-formatter-secure-button.c
@@ -27,7 +27,7 @@
 #include <e-util/e-util.h>
 
 #if defined (HAVE_NSS) && defined (ENABLE_SMIME)
-#include "certificate-viewer.h"
+#include "certificate-manager.h"
 #include "e-cert-db.h"
 #endif
 
@@ -101,7 +101,7 @@ emfe_secure_button_format (EMailFormatterExtension *extension,
 #if defined (HAVE_NSS) && defined (ENABLE_SMIME)
 static void
 viewcert_clicked (GtkWidget *button,
-                  GtkWidget *parent)
+                  GtkWidget *grid)
 {
 	CamelCipherCertInfo *info = g_object_get_data ((GObject *) button, "e-cert-info");
 	ECert *ec = NULL;
@@ -110,18 +110,19 @@ viewcert_clicked (GtkWidget *button,
 		ec = e_cert_new (CERT_DupCertificate (info->cert_data));
 
 	if (ec != NULL) {
-		GtkWidget *w = certificate_viewer_show (ec);
+		GtkWidget *dialog, *parent;
 
-		/* oddly enough certificate_viewer_show doesn't ... */
-		gtk_widget_show (w);
+		parent = gtk_widget_get_toplevel (grid);
+		if (!parent || !GTK_IS_WINDOW (parent))
+			parent = NULL;
+
+		dialog = e_cert_manager_new_certificate_viewer ((GtkWindow *) parent, ec);
+
+		gtk_widget_show (dialog);
 		g_signal_connect (
-			w, "response",
+			dialog, "response",
 			G_CALLBACK (gtk_widget_destroy), NULL);
 
-		if (w && parent)
-			gtk_window_set_transient_for (
-				(GtkWindow *) w, (GtkWindow *) parent);
-
 		g_object_unref (ec);
 	} else {
 		g_warning (
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f405d61..cb65d2e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -427,6 +427,7 @@ smime/gui/cert-trust-dialog.c
 smime/gui/component.c
 smime/gui/e-cert-selector.c
 [type: gettext/glade]smime/gui/smime-ui.ui
+smime/lib/e-asn1-object.c
 smime/lib/e-cert.c
 smime/lib/e-cert-db.c
 smime/lib/e-pkcs12.c
diff --git a/smime/gui/ca-trust-dialog.c b/smime/gui/ca-trust-dialog.c
index 7037b26..332b92b 100644
--- a/smime/gui/ca-trust-dialog.c
+++ b/smime/gui/ca-trust-dialog.c
@@ -26,7 +26,7 @@
 #endif
 
 #include "ca-trust-dialog.h"
-#include "certificate-viewer.h"
+#include "certificate-manager.h"
 
 #include <glib/gi18n.h>
 
@@ -60,12 +60,14 @@ catd_response (GtkWidget *w,
 {
 	switch (id) {
 	case GTK_RESPONSE_ACCEPT: {
-		GtkWidget *dialog = certificate_viewer_show (data->cert);
+		GtkWidget *dialog;
+
+		dialog = e_cert_manager_new_certificate_viewer (GTK_WINDOW (data->dialog), data->cert);
 
 		g_signal_stop_emission_by_name (w, "response");
-		gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->dialog));
 		gtk_dialog_run (GTK_DIALOG (dialog));
 		gtk_widget_destroy (dialog);
+
 		break; }
 	}
 }
diff --git a/smime/gui/ca-trust-dialog.h b/smime/gui/ca-trust-dialog.h
index 8b7d945..62b842d 100644
--- a/smime/gui/ca-trust-dialog.h
+++ b/smime/gui/ca-trust-dialog.h
@@ -21,8 +21,8 @@
  *
  */
 
-#ifndef _CA_TRUST_DIALOG_H_
-#define _CA_TRUST_DIALOG_H
+#ifndef CA_TRUST_DIALOG_H
+#define CA_TRUST_DIALOG_H
 
 #include <gtk/gtk.h>
 #include "e-cert.h"
@@ -32,4 +32,4 @@ GtkWidget * ca_trust_dialog_show (ECert *cert, gboolean importing);
 void       ca_trust_dialog_set_trust (GtkWidget *widget, gboolean ssl, gboolean email, gboolean objsign);
 void       ca_trust_dialog_get_trust (GtkWidget *widget, gboolean *ssl, gboolean *email, gboolean *objsign);
 
-#endif /* _CA_TRUST_DIALOG_H_ */
+#endif /* CA_TRUST_DIALOG_H */
diff --git a/smime/gui/certificate-manager.c b/smime/gui/certificate-manager.c
index 548c9c7..109bbba 100644
--- a/smime/gui/certificate-manager.c
+++ b/smime/gui/certificate-manager.c
@@ -531,7 +531,13 @@ view_cert (GtkWidget *button,
 			-1);
 
 		if (cert) {
-			GtkWidget *dialog = certificate_viewer_show (cert);
+			GtkWidget *dialog, *parent;
+
+			parent = gtk_widget_get_toplevel (button);
+			if (!parent || !GTK_IS_WINDOW (parent))
+				parent = NULL;
+
+			dialog = e_cert_manager_new_certificate_viewer ((GtkWindow *) parent, cert);
 			g_signal_connect (
 				dialog, "response",
 				G_CALLBACK (gtk_widget_destroy), NULL);
@@ -1107,3 +1113,28 @@ e_cert_manager_config_new (EPreferencesWindow *window)
 
 	return GTK_WIDGET (ecmc);
 }
+
+GtkWidget *
+e_cert_manager_new_certificate_viewer (GtkWindow *parent,
+				       ECert *cert)
+{
+	GtkWidget *dialog;
+	GList *chain, *citer;
+	GSList *issuers = NULL;
+
+	g_return_val_if_fail (cert != NULL, NULL);
+
+	chain = e_cert_get_issuers_chain (cert);
+	for (citer = chain; citer; citer = g_list_next (citer)) {
+		issuers = g_slist_append (issuers, e_cert_get_internal_cert (citer->data));
+	}
+
+	dialog = certificate_viewer_new ((GtkWindow *) parent,
+		e_cert_get_internal_cert (cert),
+		issuers);
+
+	g_list_free_full (chain, g_object_unref);
+	g_slist_free (issuers);
+
+	return dialog;
+}
diff --git a/smime/gui/certificate-manager.h b/smime/gui/certificate-manager.h
index 2eba92c..0f74d30 100644
--- a/smime/gui/certificate-manager.h
+++ b/smime/gui/certificate-manager.h
@@ -65,6 +65,10 @@ GType	  e_cert_manager_config_get_type (void) G_GNUC_CONST;
 
 GtkWidget *e_cert_manager_config_new (EPreferencesWindow *window);
 
+struct _ECert; /* forward declaration */
+GtkWidget *e_cert_manager_new_certificate_viewer (GtkWindow *parent,
+						  struct _ECert *cert);
+
 G_END_DECLS
 
 #endif /* _CERTIFICATE_MANAGER_H_ */
diff --git a/smime/gui/certificate-viewer.c b/smime/gui/certificate-viewer.c
index 9f140ca..ce96e50 100644
--- a/smime/gui/certificate-viewer.c
+++ b/smime/gui/certificate-viewer.c
@@ -17,359 +17,662 @@
  *		Chris Toshok <toshok ximian com>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#include "certificate-viewer.h"
+#include <glib/gi18n.h>
 
-#include "e-asn1-object.h"
+#include "pk11pub.h"
+#include "hasht.h"
 
-#include <glib/gi18n.h>
+#include <libedataserver/libedataserver.h>
 
-#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 "<i>&lt;Not part of certificate&gt;</i>"
+	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 ("<tt>%s</tt>", 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 ("<tt>%s</tt>", 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 ("<i>&lt;", _("Not part of certificate"), "&gt;</i>", 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 ("<tt>", port_str, "</tt>", 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 ("<tt>", port_str, "</tt>", 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;
 }
diff --git a/smime/gui/certificate-viewer.h b/smime/gui/certificate-viewer.h
index d452b76..41f2c83 100644
--- a/smime/gui/certificate-viewer.h
+++ b/smime/gui/certificate-viewer.h
@@ -17,15 +17,16 @@
  *		Chris Toshok <toshok ximian com>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
  */
 
-#ifndef _CERTIFICATE_VIEWER_H_
-#define _CERTIFICATE_VIEWER_H
+#ifndef CERTIFICATE_VIEWER_H
+#define CERTIFICATE_VIEWER_H
 
 #include <gtk/gtk.h>
-#include "e-cert.h"
+#include <cert.h>
 
-GtkWidget * certificate_viewer_show (ECert *cert);
+GtkWidget *	certificate_viewer_new	(GtkWindow *parent,
+					 const CERTCertificate *cert,
+					 const GSList *issuers_chain_certs);
 
-#endif /* _CERTIFICATE_VIEWER_H_ */
+#endif /* CERTIFICATE_VIEWER_H */
diff --git a/smime/gui/smime-ui.ui b/smime/gui/smime-ui.ui
index 0ad3f47..5622c4d 100644
--- a/smime/gui/smime-ui.ui
+++ b/smime/gui/smime-ui.ui
@@ -16,714 +16,6 @@
       </row>
     </data>
   </object>
-  <object class="GtkDialog" id="certificate-viewer-dialog">
-    <property name="title">dialog1</property>
-    <property name="window_position">center</property>
-    <property name="type_hint">dialog</property>
-    <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox1">
-        <property name="visible">True</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <object class="GtkNotebook" id="notebook1">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="border_width">12</property>
-            <child>
-              <object class="GtkVBox" id="vbox1">
-                <property name="visible">True</property>
-                <property name="border_width">6</property>
-                <property name="orientation">vertical</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkFrame" id="frame1">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">none</property>
-                    <child>
-                      <object class="GtkVBox" id="vbox2">
-                        <property name="visible">True</property>
-                        <property name="border_width">6</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkLabel" id="ssl-client-cert-verified-label">
-                            <property name="visible">True</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">SSL Client Certificate</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="ssl-server-cert-verified-label">
-                            <property name="visible">True</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">SSL Server Certificate</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="email-signer-cert-verified-label">
-                            <property name="visible">True</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">Email Signer Certificate</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="email-recipient-cert-verified-label">
-                            <property name="visible">True</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">Email Recipient Certificate</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">3</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="label3">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">This certificate has been verified for the following uses:</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHSeparator" id="hseparator1">
-                    <property name="visible">True</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkTable" id="table3">
-                    <property name="visible">True</property>
-                    <property name="border_width">3</property>
-                    <property name="n_rows">15</property>
-                    <property name="n_columns">2</property>
-                    <property name="column_spacing">6</property>
-                    <child>
-                      <object class="GtkLabel" id="label25">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="yalign">1</property>
-                        <property name="ypad">3</property>
-                        <property name="label" translatable="yes">Issued To</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="right_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label26">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">Common Name (CN)</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label27">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">Organization (O)</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label28">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">Organizational Unit (OU)</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label29">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">Serial Number</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label31">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">Common Name (CN)</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label32">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">Organization (O)</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">7</property>
-                        <property name="bottom_attach">8</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label33">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">Organizational Unit (OU)</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">8</property>
-                        <property name="bottom_attach">9</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label36">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">Issued On</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">10</property>
-                        <property name="bottom_attach">11</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label37">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">Expires On</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">11</property>
-                        <property name="bottom_attach">12</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label30">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="yalign">1</property>
-                        <property name="ypad">3</property>
-                        <property name="label" translatable="yes">Issued By</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">5</property>
-                        <property name="bottom_attach">6</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label35">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="ypad">3</property>
-                        <property name="label" translatable="yes">Fingerprints</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">12</property>
-                        <property name="bottom_attach">13</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label38">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">SHA1 Fingerprint</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">13</property>
-                        <property name="bottom_attach">14</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label39">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="label" translatable="yes">MD5 Fingerprint</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">14</property>
-                        <property name="bottom_attach">15</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="issued-to-o">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="issued-to-ou">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="issued-to-serial">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="issued-by-cn">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="issued-by-o">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">7</property>
-                        <property name="bottom_attach">8</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="issued-by-ou">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">8</property>
-                        <property name="bottom_attach">9</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="validity-issued-on">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">10</property>
-                        <property name="bottom_attach">11</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="validity-expires-on">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">11</property>
-                        <property name="bottom_attach">12</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="fingerprints-sha1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">13</property>
-                        <property name="bottom_attach">14</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="fingerprints-md5">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">14</property>
-                        <property name="bottom_attach">15</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="issued-to-cn">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">&lt;Not Part of Certificate&gt;</property>
-                        <property name="selectable">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label34">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="ypad">3</property>
-                        <property name="label" translatable="yes">Validity</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">9</property>
-                        <property name="bottom_attach">10</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label1">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">General</property>
-              </object>
-              <packing>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkVBox" id="vbox3">
-                <property name="visible">True</property>
-                <property name="border_width">6</property>
-                <property name="orientation">vertical</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkFrame" id="frame4">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">none</property>
-                    <child>
-                      <object class="GtkScrolledWindow" id="scrolledwindow1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="border_width">6</property>
-                        <property name="hscrollbar_policy">automatic</property>
-                        <property name="vscrollbar_policy">automatic</property>
-                        <property name="shadow_type">in</property>
-                        <child>
-                          <object class="GtkTreeView" id="cert-hierarchy-treeview">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="headers_visible">False</property>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="label51">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Certificate Hierarchy</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkFrame" id="frame5">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">none</property>
-                    <child>
-                      <object class="GtkScrolledWindow" id="scrolledwindow2">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="border_width">6</property>
-                        <property name="hscrollbar_policy">automatic</property>
-                        <property name="vscrollbar_policy">automatic</property>
-                        <property name="shadow_type">in</property>
-                        <child>
-                          <object class="GtkTreeView" id="cert-fields-treeview">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="headers_visible">False</property>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="label52">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Certificate Fields</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkFrame" id="frame6">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">none</property>
-                    <child>
-                      <object class="GtkScrolledWindow" id="scrolledwindow3">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="border_width">6</property>
-                        <property name="hscrollbar_policy">automatic</property>
-                        <property name="vscrollbar_policy">automatic</property>
-                        <property name="shadow_type">etched-in</property>
-                        <child>
-                          <object class="GtkTextView" id="cert-field-value-textview">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="editable">False</property>
-                            <property name="cursor_visible">False</property>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="label53">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Field Value</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label2">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">Details</property>
-              </object>
-              <packing>
-                <property name="position">1</property>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area1">
-            <property name="visible">True</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="closebutton1">
-                <property name="label">gtk-close</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="-7">closebutton1</action-widget>
-    </action-widgets>
-  </object>
   <object class="GtkWindow" id="cert-manager-config-control">
     <property name="title">window1</property>
     <child>
diff --git a/smime/lib/e-asn1-object.c b/smime/lib/e-asn1-object.c
index 5344151..7e5f27c 100644
--- a/smime/lib/e-asn1-object.c
+++ b/smime/lib/e-asn1-object.c
@@ -39,13 +39,18 @@
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
  */
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
+#include <glib/gi18n.h>
+
 #include "e-asn1-object.h"
 
-#include "secasn1.h"
+#include "pk11func.h"
+#include "certdb.h"
+#include "hasht.h"
 
 #define E_ASN1_OBJECT_GET_PRIVATE(obj) \
 	(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -67,220 +72,793 @@ struct _EASN1ObjectPrivate {
 
 G_DEFINE_TYPE (EASN1Object, e_asn1_object, G_TYPE_OBJECT)
 
-static void
-e_asn1_object_finalize (GObject *object)
+static gboolean
+get_int_value (SECItem *versionItem,
+               gulong *version)
 {
-	EASN1ObjectPrivate *priv;
+	SECStatus srv;
+	srv = SEC_ASN1DecodeInteger (versionItem,version);
+	if (srv != SECSuccess) {
+		g_warning ("could not decode version of cert");
+		return FALSE;
+	}
+	return TRUE;
+}
 
-	priv = E_ASN1_OBJECT_GET_PRIVATE (object);
+static gboolean
+process_version (SECItem *versionItem,
+                 EASN1Object **retItem)
+{
+	EASN1Object *item = e_asn1_object_new ();
+	gulong version;
 
-	g_free (priv->display_name);
-	g_free (priv->value);
+	e_asn1_object_set_display_name (item, _("Version"));
 
-	g_list_free_full (priv->children, (GDestroyNotify) g_object_unref);
+	/* Now to figure out what version this certificate is. */
 
-	/* Chain up to parent's finalize() method. */
-	G_OBJECT_CLASS (e_asn1_object_parent_class)->finalize (object);
+	if (versionItem->data) {
+		if (!get_int_value (versionItem, &version))
+			return FALSE;
+	} else {
+		/* If there is no version present in the cert, then rfc2459
+		 * says we default to v1 (0) */
+		version = 0;
+	}
+
+	switch (version) {
+	case 0:
+		e_asn1_object_set_display_value (item, _("Version 1"));
+		break;
+	case 1:
+		e_asn1_object_set_display_value (item, _("Version 2"));
+		break;
+	case 2:
+		e_asn1_object_set_display_value (item, _("Version 3"));
+		break;
+	default:
+		g_warning ("Bad value for cert version");
+		return FALSE;
+	}
+
+	*retItem = item;
+	return TRUE;
 }
 
-static void
-e_asn1_object_class_init (EASN1ObjectClass *class)
+static gboolean
+process_serial_number_der (SECItem *serialItem,
+                           EASN1Object **retItem)
 {
-	GObjectClass *object_class;
+	gchar *serialNumber;
+	EASN1Object *item = e_asn1_object_new ();
 
-	g_type_class_add_private (class, sizeof (EASN1ObjectPrivate));
+	e_asn1_object_set_display_name (item, _("Serial Number"));
 
-	object_class = G_OBJECT_CLASS (class);
-	object_class->finalize = e_asn1_object_finalize;
+	serialNumber = CERT_Hexify (serialItem, 1);
+
+	e_asn1_object_set_display_value (item, serialNumber);
+	PORT_Free (serialNumber); /* XXX the right free to use? */
+
+	*retItem = item;
+	return TRUE;
 }
 
-static void
-e_asn1_object_init (EASN1Object *asn1)
+static gboolean
+get_default_oid_format (SECItem *oid,
+                        gchar **text)
 {
-	asn1->priv = E_ASN1_OBJECT_GET_PRIVATE (asn1);
-
-	asn1->priv->valid_container = TRUE;
+	GString *str;
+	gulong val = oid->data[0];
+	guint ii = val % 40;
+
+	val /= 40;
+
+	str = g_string_new ("");
+	g_string_append_printf (str, "%lu %u ", val, ii);
+
+	val = 0;
+	for (ii = 1; ii < oid->len; ii++) {
+		/* In this loop, we have to parse a DER formatted
+		 * If the first bit is a 1, then the integer is
+		 * represented by more than one byte.  If the
+		 * first bit is set then we continue on and add
+		 * the values of the later bytes until we get
+		 * a byte without the first bit set.
+		*/
+		gulong jj;
+
+		jj = oid->data[ii];
+		val = (val << 7) | (jj & 0x7f);
+		if (jj & 0x80)
+			continue;
+		g_string_append_printf (str, "%lu ", val);
+
+		val = 0;
+  }
+
+  *text = g_string_free (str, FALSE);
+
+  return TRUE;
 }
 
-/* This function is used to interpret an integer that
- * was encoded in a DER buffer. This function is used
- * when converting a DER buffer into a nsIASN1Object
- * structure.  This interprets the buffer in data
- * as defined by the DER (Distinguised Encoding Rules) of
- * ASN1.
-*/
-static gint
-get_integer_256 (guchar *data,
-                 guint nb)
+static gboolean
+get_oid_text (SECItem *oid,
+              gchar **text)
 {
-	gint val;
+	SECOidTag oidTag = SECOID_FindOIDTag (oid);
+	gchar *temp;
 
-	switch (nb) {
-	case 1:
-		val = data[0];
+	switch (oidTag) {
+	case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
+		*text = g_strdup (_("PKCS #1 MD2 With RSA Encryption"));
 		break;
-	case 2:
-		val = (data[0] << 8) | data[1];
+	case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
+		*text = g_strdup (_("PKCS #1 MD5 With RSA Encryption"));
+		break;
+	case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
+		*text = g_strdup (_("PKCS #1 SHA-1 With RSA Encryption"));
+		break;
+	case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
+		*text = g_strdup (_("PKCS #1 SHA-256 With RSA Encryption"));
+		break;
+	case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
+		*text = g_strdup (_("PKCS #1 SHA-384 With RSA Encryption"));
+		break;
+	case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
+		*text = g_strdup (_("PKCS #1 SHA-512 With RSA Encryption"));
+		break;
+	case SEC_OID_AVA_COUNTRY_NAME:
+		*text = g_strdup ("C");
+		break;
+	case SEC_OID_AVA_COMMON_NAME:
+		*text = g_strdup ("CN");
+		break;
+	case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
+		*text = g_strdup ("OU");
+		break;
+	case SEC_OID_AVA_ORGANIZATION_NAME:
+		*text = g_strdup ("O");
+		break;
+	case SEC_OID_AVA_LOCALITY:
+		*text = g_strdup ("L");
+		break;
+	case SEC_OID_AVA_DN_QUALIFIER:
+		*text = g_strdup ("DN");
+		break;
+	case SEC_OID_AVA_DC:
+		*text = g_strdup ("DC");
+		break;
+	case SEC_OID_AVA_STATE_OR_PROVINCE:
+		*text = g_strdup ("ST");
+		break;
+	case SEC_OID_PKCS1_RSA_ENCRYPTION:
+		*text = g_strdup (_("PKCS #1 RSA Encryption"));
+		break;
+	case SEC_OID_X509_KEY_USAGE:
+		*text = g_strdup (_("Certificate Key Usage"));
 		break;
-	case 3:
-		val = (data[0] << 16) | (data[1] << 8) | data[2];
+	case SEC_OID_NS_CERT_EXT_CERT_TYPE:
+		*text = g_strdup (_("Netscape Certificate Type"));
 		break;
-	case 4:
-		val = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+	case SEC_OID_X509_AUTH_KEY_ID:
+		*text = g_strdup (_("Certificate Authority Key Identifier"));
+		break;
+	case SEC_OID_RFC1274_UID:
+		*text = g_strdup ("UID");
+		break;
+	case SEC_OID_PKCS9_EMAIL_ADDRESS:
+		*text = g_strdup ("E");
 		break;
 	default:
-		return -1;
-	}
+		if (!get_default_oid_format (oid, &temp))
+			return FALSE;
 
-	return val;
+		*text = g_strdup_printf (_("Object Identifier (%s)"), temp);
+		g_free (temp);
+
+		break;
+	}
+	return TRUE;
 }
 
-/* This function is used to retrieve the lenght of a DER encoded
- * item.  It looks to see if this a multibyte length and then
- * interprets the buffer accordingly to get the actual length value.
- * This funciton is used mostly while parsing the DER headers.
- *
- * A DER encoded item has the following structure:
- *
- * <tag><length<data consisting of lenght bytes>
- */
-static guint32
-get_der_item_length (guchar *data,
-                     guchar *end,
-                     gulong *bytesUsed,
-                     gboolean *indefinite)
-{
-	guchar lbyte = *data++;
-	PRInt32 length = -1;
-
-	*indefinite = FALSE;
-	if (lbyte >= 0x80) {
-		/* Multibyte length */
-		guint nb = (guint) (lbyte & 0x7f);
-		if (nb > 4) {
-			return -1;
+static gboolean
+process_raw_bytes (SECItem *data,
+                   gchar **text)
+{
+	/* This function is used to display some DER bytes
+	 * that we have not added support for decoding.
+	 * It prints the value of the byte out into a
+	 * string that can later be displayed as a byte
+	 * string.  We place a new line after 24 bytes
+	 * to break up extermaly long sequence of bytes.
+	*/
+	GString *str = g_string_new ("");
+	PRUint32 i;
+
+	for (i = 0; i < data->len; i++) {
+		g_string_append_printf (str, "%02x ", data->data[i]);
+		if ((i + 1) % 16 == 0) {
+			g_string_append (str, "\n");
 		}
-		if (nb > 0) {
+	}
+	*text = g_string_free (str, FALSE);
+	return TRUE;
+}
 
-			if ((data + nb) > end) {
-				return -1;
-			}
-			length = get_integer_256 (data, nb);
-			if (length < 0)
-				return -1;
-		} else {
-			*indefinite = TRUE;
-			length = 0;
-		}
-		*bytesUsed = nb+1;
+static gboolean
+process_sec_algorithm_id (SECAlgorithmID *algID,
+                          EASN1Object **retSequence)
+{
+	EASN1Object *sequence = e_asn1_object_new ();
+	gchar *text = NULL;
+
+	*retSequence = NULL;
+
+	get_oid_text (&algID->algorithm, &text);
+
+	if (!algID->parameters.len ||
+		algID->parameters.data[0] == E_ASN1_OBJECT_TYPE_NULL) {
+		e_asn1_object_set_display_value (sequence, text);
+		e_asn1_object_set_valid_container (sequence, FALSE);
 	} else {
-		length = lbyte;
-		*bytesUsed = 1;
+		EASN1Object *subitem;
+
+		subitem = e_asn1_object_new ();
+		e_asn1_object_set_display_name (subitem, _("Algorithm Identifier"));
+		e_asn1_object_set_display_value (subitem, text);
+		e_asn1_object_append_child (sequence, subitem);
+		g_object_unref (subitem);
+
+		g_free (text);
+
+		subitem = e_asn1_object_new ();
+		e_asn1_object_set_display_name (subitem, _("Algorithm Parameters"));
+		process_raw_bytes (&algID->parameters, &text);
+		e_asn1_object_set_display_value (subitem, text);
+		e_asn1_object_append_child (sequence, subitem);
+		g_object_unref (subitem);
 	}
-	return length;
+
+	g_free (text);
+	*retSequence = sequence;
+	return TRUE;
 }
 
 static gboolean
-build_from_der (EASN1Object *parent,
-                gchar *data,
-                gchar *end)
+process_subject_public_key_info (CERTSubjectPublicKeyInfo *spki,
+                                 EASN1Object *parentSequence)
 {
-	gulong bytesUsed;
-	gboolean indefinite;
-	PRInt32 len;
-	PRUint32 type;
-	guchar code, tagnum;
-	EASN1Object *asn1object = NULL;
+	EASN1Object *spkiSequence = e_asn1_object_new ();
+	EASN1Object *sequenceItem;
+	EASN1Object *printableItem;
+	SECItem data;
+	gchar *text = NULL;
+
+	e_asn1_object_set_display_name (spkiSequence, _("Subject Public Key Info"));
+
+	if (!process_sec_algorithm_id (&spki->algorithm, &sequenceItem))
+		return FALSE;
+
+	e_asn1_object_set_display_name (sequenceItem, _("Subject Public Key Algorithm"));
+
+	e_asn1_object_append_child (spkiSequence, sequenceItem);
 
-	if (data >= end)
+	/* The subjectPublicKey field is encoded as a bit string.
+	 * ProcessRawBytes expects the lenght to be in bytes, so
+	 * let's convert the lenght into a temporary SECItem.
+	*/
+	data.data = spki->subjectPublicKey.data;
+	data.len  = spki->subjectPublicKey.len / 8;
+
+	process_raw_bytes (&data, &text);
+	printableItem = e_asn1_object_new ();
+
+	e_asn1_object_set_display_value (printableItem, text);
+	e_asn1_object_set_display_name (printableItem, _("Subject's Public Key"));
+	e_asn1_object_append_child (spkiSequence, printableItem);
+	g_object_unref (printableItem);
+	g_free (text);
+
+	e_asn1_object_append_child (parentSequence, spkiSequence);
+	g_object_unref (spkiSequence);
+
+	return TRUE;
+}
+
+static gboolean
+process_ns_cert_type_extensions (SECItem *extData,
+                                 GString *text)
+{
+	SECItem decoded;
+	guchar nsCertType;
+
+	decoded.data = NULL;
+	decoded.len  = 0;
+	if (SECSuccess != SEC_ASN1DecodeItem (NULL, &decoded,
+					     SEC_ASN1_GET (SEC_BitStringTemplate), extData)) {
+		g_string_append (text, _("Error: Unable to process extension"));
 		return TRUE;
+	}
 
-	/*
-	 * A DER item has the form of |tag|len|data
-	 * tag is one byte and describes the type of elment
-	 * we are dealing with.
-	 * len is a DER encoded gint telling us how long the data is
-	 * data is a buffer that is len bytes long and has to be
-	 * interpreted according to its type.
-	 */
+	nsCertType = decoded.data[0];
 
-	while (data < end) {
-		code = *data;
-		tagnum = code & SEC_ASN1_TAGNUM_MASK;
+	PORT_Free (decoded.data); /* XXX right free? */
 
-		/*
-		 * NOTE: This code does not (yet) handle the high-tag-number form!
-		 */
-		if (tagnum == SEC_ASN1_HIGH_TAG_NUMBER) {
-			return FALSE;
+	if (nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
+		g_string_append (text, _("SSL Client Certificate"));
+		g_string_append (text, "\n");
+	}
+	if (nsCertType & NS_CERT_TYPE_SSL_SERVER) {
+		g_string_append (text, _("SSL Server Certificate"));
+		g_string_append (text, "\n");
+	}
+	if (nsCertType & NS_CERT_TYPE_EMAIL) {
+		g_string_append (text, _("Email"));
+		g_string_append (text, "\n");
+	}
+	if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING) {
+		g_string_append (text, _("Object Signer"));
+		g_string_append (text, "\n");
+	}
+	if (nsCertType & NS_CERT_TYPE_SSL_CA) {
+		g_string_append (text, _("SSL Certificate Authority"));
+		g_string_append (text, "\n");
+	}
+	if (nsCertType & NS_CERT_TYPE_EMAIL_CA) {
+		g_string_append (text, _("Email Certificate Authority"));
+		g_string_append (text, "\n");
+	}
+	if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING_CA) {
+		g_string_append (text, _("Object Signer"));
+		g_string_append (text, "\n");
+	}
+	return TRUE;
+}
+
+static gboolean
+process_key_usage_extensions (SECItem *extData,
+                              GString *text)
+{
+	SECItem decoded;
+	guchar keyUsage;
+
+	decoded.data = NULL;
+	decoded.len  = 0;
+	if (SECSuccess != SEC_ASN1DecodeItem (NULL, &decoded,
+					     SEC_ASN1_GET (SEC_BitStringTemplate), extData)) {
+		g_string_append (text, _("Error: Unable to process extension"));
+		return TRUE;
+	}
+
+	keyUsage = decoded.data[0];
+	PORT_Free (decoded.data); /* XXX right free? */
+
+	if (keyUsage & KU_DIGITAL_SIGNATURE) {
+		g_string_append (text, _("Signing"));
+		g_string_append (text, "\n");
+	}
+	if (keyUsage & KU_NON_REPUDIATION) {
+		g_string_append (text, _("Non-repudiation"));
+		g_string_append (text, "\n");
+	}
+	if (keyUsage & KU_KEY_ENCIPHERMENT) {
+		g_string_append (text, _("Key Encipherment"));
+		g_string_append (text, "\n");
+	}
+	if (keyUsage & KU_DATA_ENCIPHERMENT) {
+		g_string_append (text, _("Data Encipherment"));
+		g_string_append (text, "\n");
+	}
+	if (keyUsage & KU_KEY_AGREEMENT) {
+		g_string_append (text, _("Key Agreement"));
+		g_string_append (text, "\n");
+	}
+	if (keyUsage & KU_KEY_CERT_SIGN) {
+		g_string_append (text, _("Certificate Signer"));
+		g_string_append (text, "\n");
+	}
+	if (keyUsage & KU_CRL_SIGN) {
+		g_string_append (text, _("CRL Signer"));
+		g_string_append (text, "\n");
+	}
+
+	return TRUE;
+}
+
+static gboolean
+process_extension_data (SECOidTag oidTag,
+                        SECItem *extData,
+                        GString *str)
+{
+	gboolean rv;
+	switch (oidTag) {
+	case SEC_OID_NS_CERT_EXT_CERT_TYPE:
+		rv = process_ns_cert_type_extensions (extData, str);
+		break;
+	case SEC_OID_X509_KEY_USAGE:
+		rv = process_key_usage_extensions (extData, str);
+		break;
+	default: {
+		gchar *text;
+		rv = process_raw_bytes (extData, &text);
+		g_string_append (str, text);
+		g_free (text);
+		break;
+	}
+	}
+	return rv;
+}
+
+static gboolean
+process_single_extension (CERTCertExtension *extension,
+                          EASN1Object **retExtension)
+{
+	GString *str = g_string_new ("");
+	gchar *text;
+	EASN1Object *extensionItem;
+	SECOidTag oidTag = SECOID_FindOIDTag (&extension->id);
+
+	get_oid_text (&extension->id, &text);
+
+	extensionItem = e_asn1_object_new ();
+
+	e_asn1_object_set_display_name (extensionItem, text);
+	g_free (text);
+
+	if (extension->critical.data != NULL) {
+		if (extension->critical.data[0]) {
+			g_string_append (str, _("Critical"));
+		} else {
+			g_string_append (str, _("Not Critical"));
 		}
-		data++;
-		len = get_der_item_length (
-			(guchar *) data, (guchar *) end,
-			&bytesUsed, &indefinite);
-		data += bytesUsed;
-		if ((len < 0) || ((data + len) > end))
+	} else {
+		g_string_append (str, _("Not Critical"));
+	}
+	g_string_append (str, "\n");
+	if (!process_extension_data (oidTag, &extension->value, str)) {
+		g_string_free (str, TRUE);
+		return FALSE;
+	}
+
+	e_asn1_object_set_display_value (extensionItem, str->str);
+	g_string_free (str, TRUE);
+	*retExtension = extensionItem;
+	return TRUE;
+}
+
+static gboolean
+process_extensions (CERTCertExtension **extensions,
+                    EASN1Object *parentSequence)
+{
+	EASN1Object *extensionSequence = e_asn1_object_new ();
+	PRInt32 i;
+
+	e_asn1_object_set_display_name (extensionSequence, _("Extensions"));
+
+	for (i = 0; extensions[i] != NULL; i++) {
+		EASN1Object *newExtension;
+
+		if (!process_single_extension (extensions[i],
+					       &newExtension))
 			return FALSE;
 
-		if (code & SEC_ASN1_CONSTRUCTED) {
-			if (len > 0 || indefinite) {
-				switch (code & SEC_ASN1_CLASS_MASK) {
-				case SEC_ASN1_UNIVERSAL:
-					type = tagnum;
-					break;
-				case SEC_ASN1_APPLICATION:
-					type = E_ASN1_OBJECT_TYPE_APPLICATION;
-					break;
-				case SEC_ASN1_CONTEXT_SPECIFIC:
-					type = E_ASN1_OBJECT_TYPE_CONTEXT_SPECIFIC;
-					break;
-				case SEC_ASN1_PRIVATE:
-					type = E_ASN1_OBJECT_TYPE_PRIVATE;
-					break;
-				default:
-					g_warning ("bad DER");
-					return FALSE;
-				}
-
-				asn1object = e_asn1_object_new ();
-				asn1object->priv->tag = tagnum;
-				asn1object->priv->type = type;
-
-				if (!build_from_der (
-					asn1object, data,
-					(len == 0) ? end : data + len)) {
-					g_object_unref (asn1object);
-					return FALSE;
-				}
-			}
-		} else {
-			asn1object = e_asn1_object_new ();
+		e_asn1_object_append_child (extensionSequence, newExtension);
+	}
+	e_asn1_object_append_child (parentSequence, extensionSequence);
+	return TRUE;
+}
 
-			asn1object->priv->type = tagnum;
-			asn1object->priv->tag = tagnum;
+static gboolean
+process_name (CERTName *name,
+              gchar **value)
+{
+	CERTRDN ** rdns;
+	CERTRDN ** rdn;
+	CERTAVA ** avas;
+	CERTAVA * ava;
+	SECItem *decodeItem = NULL;
+	GString *final_string = g_string_new ("");
+
+	gchar *type;
+	GString *avavalue;
+	gchar *temp;
+	CERTRDN **lastRdn;
+
+	rdns = name->rdns;
+
+	/* find last RDN */
+	lastRdn = rdns;
+	while (*lastRdn) lastRdn++;
+
+	/* The above whille loop will put us at the last member
+	 * of the array which is a NULL pointer.  So let's back
+	 * up one spot so that we have the last non-NULL entry in
+	 * the array in preparation for traversing the
+	 * RDN's (Relative Distinguished Name) in reverse order.
+	 */
+	lastRdn--;
 
-			/*printableItem->SetData((gchar *)data, len);*/
+	/*
+	 * Loop over name contents in _reverse_ RDN order appending to string
+	 * When building the Ascii string, NSS loops over these entries in
+	 * reverse order, so I will as well.  The difference is that NSS
+	 * will always place them in a one line string separated by commas,
+	 * where I want each entry on a single line.  I can't just use a comma
+	 * as my delimitter because it is a valid character to have in the
+	 * value portion of the AVA and could cause trouble when parsing.
+	 */
+	for (rdn = lastRdn; rdn >= rdns; rdn--) {
+		avas = (*rdn)->avas;
+		while ((ava = *avas++) != 0) {
+			if (!get_oid_text (&ava->type, &type))
+				return FALSE;
+
+			/* This function returns a string in UTF8 format. */
+			decodeItem = CERT_DecodeAVAValue (&ava->value);
+			if (!decodeItem) {
+				g_free (type);
+				return FALSE;
+			}
+
+			avavalue = g_string_new_len (
+				(gchar *) decodeItem->data, decodeItem->len);
+
+			SECITEM_FreeItem (decodeItem, PR_TRUE);
+
+			/* Translators: This string is used in Certificate
+			 * details for fields like Issuer or Subject, which
+			 * shows the field name on the left and its respective
+			 * value on the right, both as stored in the
+			 * certificate itself.  You probably do not need to
+			 * change this string, unless changing the order of
+			 * name and value.  As a result example:
+			 * "OU = VeriSign Trust Network" */
+			temp = g_strdup_printf (_("%s = %s"), type, avavalue->str);
+
+			g_string_append (final_string, temp);
+			g_string_append (final_string, "\n");
+			g_string_free (avavalue, TRUE);
+			g_free (temp);
+			g_free (type);
 		}
-		data += len;
+	}
+	*value = g_string_free (final_string, FALSE);
+	return TRUE;
+}
+
+static gboolean
+create_tbs_certificate_asn1_struct (CERTCertificate *cert,
+                                    EASN1Object **seq)
+{
+	/*
+	**   TBSCertificate  ::=  SEQUENCE  {
+	**        version         [0]  EXPLICIT Version DEFAULT v1,
+	**        serialNumber         CertificateSerialNumber,
+	**        signature            AlgorithmIdentifier,
+	**        issuer               Name,
+	**        validity             Validity,
+	**        subject              Name,
+	**        subjectPublicKeyInfo SubjectPublicKeyInfo,
+	**        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+	**                             -- If present, version shall be v2 or v3
+	**        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+	**                             -- If present, version shall be v2 or v3
+	**        extensions      [3]  EXPLICIT Extensions OPTIONAL
+	**                             -- If present, version shall be v3
+	**        }
+	**
+	** This is the ASN1 structure we should be dealing with at this point.
+	** The code in this method will assert this is the structure we're dealing
+	** and then add more user friendly text for that field.
+	*/
+	EASN1Object *sequence = e_asn1_object_new ();
+	gchar *text;
+	EASN1Object *subitem;
+	SECItem data;
+
+	e_asn1_object_set_display_name (sequence, _("Certificate"));
+
+	if (!process_version (&cert->version, &subitem))
+		return FALSE;
+	e_asn1_object_append_child (sequence, subitem);
+	g_object_unref (subitem);
+
+	if (!process_serial_number_der (&cert->serialNumber, &subitem))
+		return FALSE;
+	e_asn1_object_append_child (sequence, subitem);
+	g_object_unref (subitem);
+
+	if (!process_sec_algorithm_id (&cert->signature, &subitem))
+		return FALSE;
+	e_asn1_object_set_display_name (subitem, _("Certificate Signature Algorithm"));
+	e_asn1_object_append_child (sequence, subitem);
+	g_object_unref (subitem);
+
+	process_name (&cert->issuer, &text);
+	subitem = e_asn1_object_new ();
+	e_asn1_object_set_display_value (subitem, text);
+	g_free (text);
+
+	e_asn1_object_set_display_name (subitem, _("Issuer"));
+	e_asn1_object_append_child (sequence, subitem);
+	g_object_unref (subitem);
+
+#ifdef notyet
+	nsCOMPtr < nsIASN1Sequence> validitySequence = new nsNSSASN1Sequence ();
+	nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpValidity").get (),
+					    text);
+	validitySequence->SetDisplayName (text);
+	asn1Objects->AppendElement (validitySequence, PR_FALSE);
+	nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpNotBefore").get (),
+					    text);
+	nsCOMPtr < nsIX509CertValidity> validityData;
+	GetValidity (getter_AddRefs (validityData));
+	PRTime notBefore, notAfter;
+
+	validityData->GetNotBefore (&notBefore);
+	validityData->GetNotAfter (&notAfter);
+	validityData = 0;
+	rv = ProcessTime (notBefore, text.get (), validitySequence);
+	if (NS_FAILED (rv))
+		return rv;
+
+	nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpNotAfter").get (),
+					    text);
+	rv = ProcessTime (notAfter, text.get (), validitySequence);
+	if (NS_FAILED (rv))
+		return rv;
+#endif
+
+	subitem = e_asn1_object_new ();
+	e_asn1_object_set_display_name (subitem, _("Subject"));
+
+	process_name (&cert->subject, &text);
+	e_asn1_object_set_display_value (subitem, text);
+	g_free (text);
+	e_asn1_object_append_child (sequence, subitem);
+	g_object_unref (subitem);
+
+	if (!process_subject_public_key_info (&cert->subjectPublicKeyInfo, sequence))
+		return FALSE;
+
+	/* Is there an issuerUniqueID? */
+	if (cert->issuerID.data) {
+		/* The issuerID is encoded as a bit string.
+		 * The function ProcessRawBytes expects the
+		 * length to be in bytes, so let's convert the
+		 * length in a temporary SECItem
+		*/
+		data.data = cert->issuerID.data;
+		data.len  = cert->issuerID.len / 8;
+
+		subitem = e_asn1_object_new ();
+
+		e_asn1_object_set_display_name (subitem, _("Issuer Unique ID"));
+		process_raw_bytes (&data, &text);
+		e_asn1_object_set_display_value (subitem, text);
+		g_free (text);
 
-		parent->priv->children = g_list_append (parent->priv->children, asn1object);
+		e_asn1_object_append_child (sequence, subitem);
 	}
 
+	if (cert->subjectID.data) {
+		/* The subjectID is encoded as a bit string.
+		 * The function ProcessRawBytes expects the
+		 * length to be in bytes, so let's convert the
+		 * length in a temporary SECItem
+		*/
+		data.data = cert->issuerID.data;
+		data.len  = cert->issuerID.len / 8;
+
+		subitem = e_asn1_object_new ();
+
+		e_asn1_object_set_display_name (subitem, _("Subject Unique ID"));
+		process_raw_bytes (&data, &text);
+		e_asn1_object_set_display_value (subitem, text);
+		g_free (text);
+
+		e_asn1_object_append_child (sequence, subitem);
+	}
+	if (cert->extensions) {
+		if (!process_extensions (cert->extensions, sequence))
+			return FALSE;
+	}
+
+	*seq = sequence;
+
 	return TRUE;
 }
 
-EASN1Object *
-e_asn1_object_new_from_der (gchar *data,
-                            guint32 len)
+static gboolean
+fill_asn1_from_cert (EASN1Object *asn1,
+		     CERTCertificate *cert)
 {
-	EASN1Object *obj = g_object_new (E_TYPE_ASN1_OBJECT, NULL);
+	EASN1Object *sequence;
+	SECItem temp;
+	gchar *text;
 
-	if (!build_from_der (obj, data, data + len)) {
-		g_object_unref (obj);
-		return NULL;
+	g_return_val_if_fail (asn1 != NULL, FALSE);
+	g_return_val_if_fail (cert != NULL, FALSE);
+
+	if (cert->nickname) {
+		e_asn1_object_set_display_name (asn1, cert->nickname);
+	} else {
+		gchar *str;
+
+		str = CERT_GetCommonName (&cert->subject);
+		if (str) {
+			e_asn1_object_set_display_name (asn1, str);
+			PORT_Free (str);
+		} else {
+			e_asn1_object_set_display_name (asn1, cert->subjectName);
+		}
 	}
 
-	return obj;
+	/* This sequence will be contain the tbsCertificate, signatureAlgorithm,
+	 * and signatureValue. */
+
+	if (!create_tbs_certificate_asn1_struct (cert, &sequence))
+		return FALSE;
+	e_asn1_object_append_child (asn1, sequence);
+	g_object_unref (sequence);
+
+	if (!process_sec_algorithm_id (&cert->signatureWrap.signatureAlgorithm, &sequence))
+		return FALSE;
+	e_asn1_object_set_display_name (
+		sequence, _("Certificate Signature Algorithm"));
+	e_asn1_object_append_child (asn1, sequence);
+	g_object_unref (sequence);
+
+	sequence = e_asn1_object_new ();
+	e_asn1_object_set_display_name (
+		sequence, _("Certificate Signature Value"));
+
+	/* The signatureWrap is encoded as a bit string.
+	 * The function ProcessRawBytes expects the
+	 * length to be in bytes, so let's convert the
+	 * length in a temporary SECItem */
+	temp.data = cert->signatureWrap.signature.data;
+	temp.len  = cert->signatureWrap.signature.len / 8;
+	process_raw_bytes (&temp, &text);
+	e_asn1_object_set_display_value (sequence, text);
+	e_asn1_object_append_child (asn1, sequence);
+	g_free (text);
+
+	return TRUE;
+}
+
+static void
+e_asn1_object_finalize (GObject *object)
+{
+	EASN1ObjectPrivate *priv;
+
+	priv = E_ASN1_OBJECT_GET_PRIVATE (object);
+
+	g_free (priv->display_name);
+	g_free (priv->value);
+
+	g_list_free_full (priv->children, (GDestroyNotify) g_object_unref);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_asn1_object_parent_class)->finalize (object);
+}
+
+static void
+e_asn1_object_class_init (EASN1ObjectClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (class, sizeof (EASN1ObjectPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->finalize = e_asn1_object_finalize;
+}
+
+static void
+e_asn1_object_init (EASN1Object *asn1)
+{
+	asn1->priv = E_ASN1_OBJECT_GET_PRIVATE (asn1);
+
+	asn1->priv->valid_container = TRUE;
 }
 
 EASN1Object *
@@ -289,6 +867,22 @@ e_asn1_object_new (void)
 	return E_ASN1_OBJECT (g_object_new (E_TYPE_ASN1_OBJECT, NULL));
 }
 
+EASN1Object *
+e_asn1_object_new_from_cert (CERTCertificate *cert)
+{
+	EASN1Object *asn1;
+
+	g_return_val_if_fail (cert != NULL, NULL);
+
+	asn1 = e_asn1_object_new ();
+	if (!fill_asn1_from_cert (asn1, cert)) {
+		g_object_unref (asn1);
+		return NULL;
+	}
+
+	return asn1;
+}
+
 void
 e_asn1_object_set_valid_container (EASN1Object *obj,
                                    gboolean flag)
diff --git a/smime/lib/e-asn1-object.h b/smime/lib/e-asn1-object.h
index 3582496..39b79a7 100644
--- a/smime/lib/e-asn1-object.h
+++ b/smime/lib/e-asn1-object.h
@@ -1,5 +1,4 @@
 /*
- *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -18,15 +17,14 @@
  *		Chris Toshok <toshok ximian com>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
  */
 
-#ifndef _E_ASN1_OBJECT_H_
-#define _E_ASN1_OBJECT_H_
+#ifndef E_ASN1_OBJECT_H
+#define E_ASN1_OBJECT_H
 
 #include <glib-object.h>
 
-#include <nspr.h>
+#include <cert.h>
 
 #define E_TYPE_ASN1_OBJECT            (e_asn1_object_get_type ())
 #define E_ASN1_OBJECT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_ASN1_OBJECT, EASN1Object))
@@ -85,22 +83,27 @@ struct _EASN1ObjectClass {
 	void (*_ecert_reserved4) (void);
 };
 
-EASN1Object     *e_asn1_object_new_from_der       (gchar *data, guint32 len);
-EASN1Object     *e_asn1_object_new                (void);
-
-void             e_asn1_object_set_valid_container (EASN1Object *obj, gboolean flag);
-gboolean         e_asn1_object_is_valid_container  (EASN1Object *obj);
-PRUint32         e_asn1_object_get_asn1_type       (EASN1Object *obj);
-PRUint32         e_asn1_object_get_asn1_tag        (EASN1Object *obj);
-GList           *e_asn1_object_get_children        (EASN1Object *obj);
-void             e_asn1_object_append_child        (EASN1Object *parent, EASN1Object *child);
-void             e_asn1_object_set_display_name    (EASN1Object *obj, const gchar *name);
-const gchar      *e_asn1_object_get_display_name    (EASN1Object *obj);
-void             e_asn1_object_set_display_value   (EASN1Object *obj, const gchar *value);
-const gchar      *e_asn1_object_get_display_value   (EASN1Object *obj);
+GType		e_asn1_object_get_type			(void);
+EASN1Object *	e_asn1_object_new			(void);
+EASN1Object *	e_asn1_object_new_from_cert		(CERTCertificate *cert);
 
-void             e_asn1_object_get_data            (EASN1Object *obj, gchar **data, guint32 *len);
+void		e_asn1_object_set_valid_container	(EASN1Object *obj,
+							 gboolean flag);
+gboolean	e_asn1_object_is_valid_container	(EASN1Object *obj);
+PRUint32	e_asn1_object_get_asn1_type		(EASN1Object *obj);
+PRUint32	e_asn1_object_get_asn1_tag		(EASN1Object *obj);
+GList *		e_asn1_object_get_children		(EASN1Object *obj);
+void		e_asn1_object_append_child		(EASN1Object *parent,
+							 EASN1Object *child);
+void		e_asn1_object_set_display_name		(EASN1Object *obj,
+							 const gchar *name);
+const gchar *	e_asn1_object_get_display_name		(EASN1Object *obj);
+void		e_asn1_object_set_display_value		(EASN1Object *obj,
+							 const gchar *value);
+const gchar *	e_asn1_object_get_display_value		(EASN1Object *obj);
 
-GType            e_asn1_object_get_type (void);
+void		e_asn1_object_get_data			(EASN1Object *obj,
+							 gchar **data,
+							 guint32 *len);
 
-#endif /* _E_ASN1_OBJECT_H_ */
+#endif /* E_ASN1_OBJECT_H */
diff --git a/smime/lib/e-cert.c b/smime/lib/e-cert.c
index cd92062..969b43c 100644
--- a/smime/lib/e-cert.c
+++ b/smime/lib/e-cert.c
@@ -435,18 +435,14 @@ e_cert_get_md5_fingerprint (ECert *cert)
 }
 
 GList *
-e_cert_get_chain (ECert *ecert)
+e_cert_get_issuers_chain (ECert *ecert)
 {
-	GList *l = NULL;
-
-	g_object_ref (ecert);
+	GList *issuers = NULL;
 
 	while (ecert) {
 		CERTCertificate *cert = e_cert_get_internal_cert (ecert);
 		CERTCertificate *next_cert;
 
-		l = g_list_append (l, ecert);
-
 		if (SECITEM_CompareItem (&cert->derIssuer, &cert->derSubject) == SECEqual)
 			break;
 
@@ -456,9 +452,14 @@ e_cert_get_chain (ECert *ecert)
 
 		/* next_cert has a reference already */
 		ecert = e_cert_new (next_cert);
+
+		if (ecert) {
+			/* the first is issuer of the original ecert */
+			issuers = g_list_append (issuers, ecert);
+		}
 	}
 
-	return l;
+	return issuers;
 }
 
 ECert *
@@ -482,760 +483,16 @@ e_cert_get_ca_cert (ECert *ecert)
 		return e_cert_new (cert);
 }
 
-static gboolean
-get_int_value (SECItem *versionItem,
-               gulong *version)
-{
-	SECStatus srv;
-	srv = SEC_ASN1DecodeInteger (versionItem,version);
-	if (srv != SECSuccess) {
-		g_warning ("could not decode version of cert");
-		return FALSE;
-	}
-	return TRUE;
-}
-
-static gboolean
-process_version (SECItem *versionItem,
-                 EASN1Object **retItem)
-{
-	EASN1Object *item = e_asn1_object_new ();
-	gulong version;
-
-	e_asn1_object_set_display_name (item, _("Version"));
-
-	/* Now to figure out what version this certificate is. */
-
-	if (versionItem->data) {
-		if (!get_int_value (versionItem, &version))
-			return FALSE;
-	} else {
-		/* If there is no version present in the cert, then rfc2459
-		 * says we default to v1 (0) */
-		version = 0;
-	}
-
-	switch (version) {
-	case 0:
-		e_asn1_object_set_display_value (item, _("Version 1"));
-		break;
-	case 1:
-		e_asn1_object_set_display_value (item, _("Version 2"));
-		break;
-	case 2:
-		e_asn1_object_set_display_value (item, _("Version 3"));
-		break;
-	default:
-		g_warning ("Bad value for cert version");
-		return FALSE;
-	}
-
-	*retItem = item;
-	return TRUE;
-}
-
-static gboolean
-process_serial_number_der (SECItem *serialItem,
-                           EASN1Object **retItem)
-{
-	gchar *serialNumber;
-	EASN1Object *item = e_asn1_object_new ();
-
-	e_asn1_object_set_display_name (item, _("Serial Number"));
-
-	serialNumber = CERT_Hexify (serialItem, 1);
-
-	e_asn1_object_set_display_value (item, serialNumber);
-	PORT_Free (serialNumber); /* XXX the right free to use? */
-
-	*retItem = item;
-	return TRUE;
-}
-
-static gboolean
-get_default_oid_format (SECItem *oid,
-                        gchar **text)
-{
-	gchar buf[300];
-	guint len;
-	gint written;
-
-	gulong val  = oid->data[0];
-	guint  i    = val % 40;
-	val /= 40;
-	written = PR_snprintf (buf, 300, "%lu %u ", val, i);
-	if (written < 0)
-		return FALSE;
-	len = written;
-
-	val = 0;
-	for (i = 1; i < oid->len; ++i) {
-		/* In this loop, we have to parse a DER formatted
-		 * If the first bit is a 1, then the integer is
-		 * represented by more than one byte.  If the
-		 * first bit is set then we continue on and add
-		 * the values of the later bytes until we get
-		 * a byte without the first bit set.
-		*/
-		gulong j;
-
-		j = oid->data[i];
-		val = (val << 7) | (j & 0x7f);
-		if (j & 0x80)
-			continue;
-		written = PR_snprintf (&buf[len], sizeof (buf) - len, "%lu ", val);
-		if (written < 0)
-			return FALSE;
-
-		len += written;
-		if (len >= sizeof (buf))
-			g_warning ("OID data to big to display in 300 chars.");
-		val = 0;
-  }
-
-  *text = g_strdup (buf);
-  return TRUE;
-}
-
-static gboolean
-get_oid_text (SECItem *oid,
-              gchar **text)
-{
-	SECOidTag oidTag = SECOID_FindOIDTag (oid);
-	gchar *temp;
-
-	switch (oidTag) {
-	case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
-		*text = g_strdup (_("PKCS #1 MD2 With RSA Encryption"));
-		break;
-	case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
-		*text = g_strdup (_("PKCS #1 MD5 With RSA Encryption"));
-		break;
-	case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
-		*text = g_strdup (_("PKCS #1 SHA-1 With RSA Encryption"));
-		break;
-	case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
-		*text = g_strdup (_("PKCS #1 SHA-256 With RSA Encryption"));
-		break;
-	case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
-		*text = g_strdup (_("PKCS #1 SHA-384 With RSA Encryption"));
-		break;
-	case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
-		*text = g_strdup (_("PKCS #1 SHA-512 With RSA Encryption"));
-		break;
-	case SEC_OID_AVA_COUNTRY_NAME:
-		*text = g_strdup ("C");
-		break;
-	case SEC_OID_AVA_COMMON_NAME:
-		*text = g_strdup ("CN");
-		break;
-	case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
-		*text = g_strdup ("OU");
-		break;
-	case SEC_OID_AVA_ORGANIZATION_NAME:
-		*text = g_strdup ("O");
-		break;
-	case SEC_OID_AVA_LOCALITY:
-		*text = g_strdup ("L");
-		break;
-	case SEC_OID_AVA_DN_QUALIFIER:
-		*text = g_strdup ("DN");
-		break;
-	case SEC_OID_AVA_DC:
-		*text = g_strdup ("DC");
-		break;
-	case SEC_OID_AVA_STATE_OR_PROVINCE:
-		*text = g_strdup ("ST");
-		break;
-	case SEC_OID_PKCS1_RSA_ENCRYPTION:
-		*text = g_strdup (_("PKCS #1 RSA Encryption"));
-		break;
-	case SEC_OID_X509_KEY_USAGE:
-		*text = g_strdup (_("Certificate Key Usage"));
-		break;
-	case SEC_OID_NS_CERT_EXT_CERT_TYPE:
-		*text = g_strdup (_("Netscape Certificate Type"));
-		break;
-	case SEC_OID_X509_AUTH_KEY_ID:
-		*text = g_strdup (_("Certificate Authority Key Identifier"));
-		break;
-	case SEC_OID_RFC1274_UID:
-		*text = g_strdup ("UID");
-		break;
-	case SEC_OID_PKCS9_EMAIL_ADDRESS:
-		*text = g_strdup ("E");
-		break;
-	default:
-		if (!get_default_oid_format (oid, &temp))
-			return FALSE;
-
-		*text = g_strdup_printf (_("Object Identifier (%s)"), temp);
-		g_free (temp);
-
-		break;
-	}
-	return TRUE;
-}
-
-static gboolean
-process_raw_bytes (SECItem *data,
-                   gchar **text)
-{
-	/* This function is used to display some DER bytes
-	 * that we have not added support for decoding.
-	 * It prints the value of the byte out into a
-	 * string that can later be displayed as a byte
-	 * string.  We place a new line after 24 bytes
-	 * to break up extermaly long sequence of bytes.
-	*/
-	GString *str = g_string_new ("");
-	PRUint32 i;
-	gchar buffer[5];
-	for (i = 0; i < data->len; i++) {
-		PR_snprintf (buffer, 5, "%02x ", data->data[i]);
-		g_string_append (str, buffer);
-		if ((i + 1) % 16 == 0) {
-			g_string_append (str, "\n");
-		}
-	}
-	*text = g_string_free (str, FALSE);
-	return TRUE;
-}
-
-static gboolean
-process_sec_algorithm_id (SECAlgorithmID *algID,
-                          EASN1Object **retSequence)
-{
-	EASN1Object *sequence = e_asn1_object_new ();
-	gchar *text;
-
-	*retSequence = NULL;
-
-	get_oid_text (&algID->algorithm, &text);
-
-	if (!algID->parameters.len ||
-		algID->parameters.data[0] == E_ASN1_OBJECT_TYPE_NULL) {
-		e_asn1_object_set_display_value (sequence, text);
-		e_asn1_object_set_valid_container (sequence, FALSE);
-	} else {
-		EASN1Object *subitem;
-
-		subitem = e_asn1_object_new ();
-		e_asn1_object_set_display_name (subitem, _("Algorithm Identifier"));
-		e_asn1_object_set_display_value (subitem, text);
-		e_asn1_object_append_child (sequence, subitem);
-		g_object_unref (subitem);
-
-		g_free (text);
-
-		subitem = e_asn1_object_new ();
-		e_asn1_object_set_display_name (subitem, _("Algorithm Parameters"));
-		process_raw_bytes (&algID->parameters, &text);
-		e_asn1_object_set_display_value (subitem, text);
-		e_asn1_object_append_child (sequence, subitem);
-		g_object_unref (subitem);
-	}
-
-	g_free (text);
-	*retSequence = sequence;
-	return TRUE;
-}
-
-static gboolean
-process_subject_public_key_info (CERTSubjectPublicKeyInfo *spki,
-                                 EASN1Object *parentSequence)
-{
-	EASN1Object *spkiSequence = e_asn1_object_new ();
-	EASN1Object *sequenceItem;
-	EASN1Object *printableItem;
-	SECItem data;
-	gchar *text;
-
-	e_asn1_object_set_display_name (spkiSequence, _("Subject Public Key Info"));
-
-	if (!process_sec_algorithm_id (&spki->algorithm, &sequenceItem))
-		return FALSE;
-
-	e_asn1_object_set_display_name (sequenceItem, _("Subject Public Key Algorithm"));
-
-	e_asn1_object_append_child (spkiSequence, sequenceItem);
-
-	/* The subjectPublicKey field is encoded as a bit string.
-	 * ProcessRawBytes expects the lenght to be in bytes, so
-	 * let's convert the lenght into a temporary SECItem.
-	*/
-	data.data = spki->subjectPublicKey.data;
-	data.len  = spki->subjectPublicKey.len / 8;
-
-	process_raw_bytes (&data, &text);
-	printableItem = e_asn1_object_new ();
-
-	e_asn1_object_set_display_value (printableItem, text);
-	e_asn1_object_set_display_name (printableItem, _("Subject's Public Key"));
-	e_asn1_object_append_child (spkiSequence, printableItem);
-	g_object_unref (printableItem);
-
-	e_asn1_object_append_child (parentSequence, spkiSequence);
-	g_object_unref (spkiSequence);
-
-	return TRUE;
-}
-
-static gboolean
-process_ns_cert_type_extensions (SECItem *extData,
-                                 GString *text)
-{
-	SECItem decoded;
-	guchar nsCertType;
-
-	decoded.data = NULL;
-	decoded.len  = 0;
-	if (SECSuccess != SEC_ASN1DecodeItem (NULL, &decoded,
-					     SEC_ASN1_GET (SEC_BitStringTemplate), extData)) {
-		g_string_append (text, _("Error: Unable to process extension"));
-		return TRUE;
-	}
-
-	nsCertType = decoded.data[0];
-
-	PORT_Free (decoded.data); /* XXX right free? */
-
-	if (nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
-		g_string_append (text, _("SSL Client Certificate"));
-		g_string_append (text, "\n");
-	}
-	if (nsCertType & NS_CERT_TYPE_SSL_SERVER) {
-		g_string_append (text, _("SSL Server Certificate"));
-		g_string_append (text, "\n");
-	}
-	if (nsCertType & NS_CERT_TYPE_EMAIL) {
-		g_string_append (text, _("Email"));
-		g_string_append (text, "\n");
-	}
-	if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING) {
-		g_string_append (text, _("Object Signer"));
-		g_string_append (text, "\n");
-	}
-	if (nsCertType & NS_CERT_TYPE_SSL_CA) {
-		g_string_append (text, _("SSL Certificate Authority"));
-		g_string_append (text, "\n");
-	}
-	if (nsCertType & NS_CERT_TYPE_EMAIL_CA) {
-		g_string_append (text, _("Email Certificate Authority"));
-		g_string_append (text, "\n");
-	}
-	if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING_CA) {
-		g_string_append (text, _("Object Signer"));
-		g_string_append (text, "\n");
-	}
-	return TRUE;
-}
-
-static gboolean
-process_key_usage_extensions (SECItem *extData,
-                              GString *text)
-{
-	SECItem decoded;
-	guchar keyUsage;
-
-	decoded.data = NULL;
-	decoded.len  = 0;
-	if (SECSuccess != SEC_ASN1DecodeItem (NULL, &decoded,
-					     SEC_ASN1_GET (SEC_BitStringTemplate), extData)) {
-		g_string_append (text, _("Error: Unable to process extension"));
-		return TRUE;
-	}
-
-	keyUsage = decoded.data[0];
-	PORT_Free (decoded.data); /* XXX right free? */
-
-	if (keyUsage & KU_DIGITAL_SIGNATURE) {
-		g_string_append (text, _("Signing"));
-		g_string_append (text, "\n");
-	}
-	if (keyUsage & KU_NON_REPUDIATION) {
-		g_string_append (text, _("Non-repudiation"));
-		g_string_append (text, "\n");
-	}
-	if (keyUsage & KU_KEY_ENCIPHERMENT) {
-		g_string_append (text, _("Key Encipherment"));
-		g_string_append (text, "\n");
-	}
-	if (keyUsage & KU_DATA_ENCIPHERMENT) {
-		g_string_append (text, _("Data Encipherment"));
-		g_string_append (text, "\n");
-	}
-	if (keyUsage & KU_KEY_AGREEMENT) {
-		g_string_append (text, _("Key Agreement"));
-		g_string_append (text, "\n");
-	}
-	if (keyUsage & KU_KEY_CERT_SIGN) {
-		g_string_append (text, _("Certificate Signer"));
-		g_string_append (text, "\n");
-	}
-	if (keyUsage & KU_CRL_SIGN) {
-		g_string_append (text, _("CRL Signer"));
-		g_string_append (text, "\n");
-	}
-
-	return TRUE;
-}
-
-static gboolean
-process_extension_data (SECOidTag oidTag,
-                        SECItem *extData,
-                        GString *str)
-{
-	gboolean rv;
-	switch (oidTag) {
-	case SEC_OID_NS_CERT_EXT_CERT_TYPE:
-		rv = process_ns_cert_type_extensions (extData, str);
-		break;
-	case SEC_OID_X509_KEY_USAGE:
-		rv = process_key_usage_extensions (extData, str);
-		break;
-	default: {
-		gchar *text;
-		rv = process_raw_bytes (extData, &text);
-		g_string_append (str, text);
-		g_free (text);
-		break;
-	}
-	}
-	return rv;
-}
-
-static gboolean
-process_single_extension (CERTCertExtension *extension,
-                          EASN1Object **retExtension)
-{
-	GString *str = g_string_new ("");
-	gchar *text;
-	EASN1Object *extensionItem;
-	SECOidTag oidTag = SECOID_FindOIDTag (&extension->id);
-
-	get_oid_text (&extension->id, &text);
-
-	extensionItem = e_asn1_object_new ();
-
-	e_asn1_object_set_display_name (extensionItem, text);
-	g_free (text);
-
-	if (extension->critical.data != NULL) {
-		if (extension->critical.data[0]) {
-			g_string_append (str, _("Critical"));
-		} else {
-			g_string_append (str, _("Not Critical"));
-		}
-	} else {
-		g_string_append (str, _("Not Critical"));
-	}
-	g_string_append (str, "\n");
-	if (!process_extension_data (oidTag, &extension->value, str)) {
-		g_string_free (str, TRUE);
-		return FALSE;
-	}
-
-	e_asn1_object_set_display_value (extensionItem, str->str);
-	g_string_free (str, TRUE);
-	*retExtension = extensionItem;
-	return TRUE;
-}
-
-static gboolean
-process_extensions (CERTCertExtension **extensions,
-                    EASN1Object *parentSequence)
-{
-	EASN1Object *extensionSequence = e_asn1_object_new ();
-	PRInt32 i;
-
-	e_asn1_object_set_display_name (extensionSequence, _("Extensions"));
-
-	for (i = 0; extensions[i] != NULL; i++) {
-		EASN1Object *newExtension;
-
-		if (!process_single_extension (extensions[i],
-					       &newExtension))
-			return FALSE;
-
-		e_asn1_object_append_child (extensionSequence, newExtension);
-	}
-	e_asn1_object_append_child (parentSequence, extensionSequence);
-	return TRUE;
-}
-
-static gboolean
-process_name (CERTName *name,
-              gchar **value)
-{
-	CERTRDN ** rdns;
-	CERTRDN ** rdn;
-	CERTAVA ** avas;
-	CERTAVA * ava;
-	SECItem *decodeItem = NULL;
-	GString *final_string = g_string_new ("");
-
-	gchar *type;
-	GString *avavalue;
-	gchar *temp;
-	CERTRDN **lastRdn;
-
-	rdns = name->rdns;
-
-	/* find last RDN */
-	lastRdn = rdns;
-	while (*lastRdn) lastRdn++;
-
-	/* The above whille loop will put us at the last member
-	 * of the array which is a NULL pointer.  So let's back
-	 * up one spot so that we have the last non-NULL entry in
-	 * the array in preparation for traversing the
-	 * RDN's (Relative Distinguished Name) in reverse order.
-	 */
-	lastRdn--;
-
-	/*
-	 * Loop over name contents in _reverse_ RDN order appending to string
-	 * When building the Ascii string, NSS loops over these entries in
-	 * reverse order, so I will as well.  The difference is that NSS
-	 * will always place them in a one line string separated by commas,
-	 * where I want each entry on a single line.  I can't just use a comma
-	 * as my delimitter because it is a valid character to have in the
-	 * value portion of the AVA and could cause trouble when parsing.
-	 */
-	for (rdn = lastRdn; rdn >= rdns; rdn--) {
-		avas = (*rdn)->avas;
-		while ((ava = *avas++) != 0) {
-			if (!get_oid_text (&ava->type, &type))
-				return FALSE;
-
-			/* This function returns a string in UTF8 format. */
-			decodeItem = CERT_DecodeAVAValue (&ava->value);
-			if (!decodeItem) {
-				return FALSE;
-			}
-
-			avavalue = g_string_new_len (
-				(gchar *) decodeItem->data, decodeItem->len);
-
-			SECITEM_FreeItem (decodeItem, PR_TRUE);
-
-			/* Translators: This string is used in Certificate
-			 * details for fields like Issuer or Subject, which
-			 * shows the field name on the left and its respective
-			 * value on the right, both as stored in the
-			 * certificate itself.  You probably do not need to
-			 * change this string, unless changing the order of
-			 * name and value.  As a result example:
-			 * "OU = VeriSign Trust Network" */
-			temp = g_strdup_printf (_("%s = %s"), type, avavalue->str);
-
-			g_string_append (final_string, temp);
-			g_string_append (final_string, "\n");
-			g_string_free (avavalue, TRUE);
-			g_free (temp);
-		}
-	}
-	*value = g_string_free (final_string, FALSE);
-	return TRUE;
-}
-
-static gboolean
-create_tbs_certificate_asn1_struct (ECert *cert,
-                                    EASN1Object **seq)
-{
-	/*
-	**   TBSCertificate  ::=  SEQUENCE  {
-	**        version         [0]  EXPLICIT Version DEFAULT v1,
-	**        serialNumber         CertificateSerialNumber,
-	**        signature            AlgorithmIdentifier,
-	**        issuer               Name,
-	**        validity             Validity,
-	**        subject              Name,
-	**        subjectPublicKeyInfo SubjectPublicKeyInfo,
-	**        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
-	**                             -- If present, version shall be v2 or v3
-	**        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
-	**                             -- If present, version shall be v2 or v3
-	**        extensions      [3]  EXPLICIT Extensions OPTIONAL
-	**                             -- If present, version shall be v3
-	**        }
-	**
-	** This is the ASN1 structure we should be dealing with at this point.
-	** The code in this method will assert this is the structure we're dealing
-	** and then add more user friendly text for that field.
-	*/
-	EASN1Object *sequence = e_asn1_object_new ();
-	gchar *text;
-	EASN1Object *subitem;
-	SECItem data;
-
-	e_asn1_object_set_display_name (sequence, _("Certificate"));
-
-	if (!process_version (&cert->priv->cert->version, &subitem))
-		return FALSE;
-	e_asn1_object_append_child (sequence, subitem);
-	g_object_unref (subitem);
-
-	if (!process_serial_number_der (&cert->priv->cert->serialNumber, &subitem))
-		return FALSE;
-	e_asn1_object_append_child (sequence, subitem);
-	g_object_unref (subitem);
-
-	if (!process_sec_algorithm_id (&cert->priv->cert->signature, &subitem))
-		return FALSE;
-	e_asn1_object_set_display_name (subitem, _("Certificate Signature Algorithm"));
-	e_asn1_object_append_child (sequence, subitem);
-	g_object_unref (subitem);
-
-	process_name (&cert->priv->cert->issuer, &text);
-	subitem = e_asn1_object_new ();
-	e_asn1_object_set_display_value (subitem, text);
-	g_free (text);
-
-	e_asn1_object_set_display_name (subitem, _("Issuer"));
-	e_asn1_object_append_child (sequence, subitem);
-	g_object_unref (subitem);
-
-#ifdef notyet
-	nsCOMPtr < nsIASN1Sequence> validitySequence = new nsNSSASN1Sequence ();
-	nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpValidity").get (),
-					    text);
-	validitySequence->SetDisplayName (text);
-	asn1Objects->AppendElement (validitySequence, PR_FALSE);
-	nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpNotBefore").get (),
-					    text);
-	nsCOMPtr < nsIX509CertValidity> validityData;
-	GetValidity (getter_AddRefs (validityData));
-	PRTime notBefore, notAfter;
-
-	validityData->GetNotBefore (&notBefore);
-	validityData->GetNotAfter (&notAfter);
-	validityData = 0;
-	rv = ProcessTime (notBefore, text.get (), validitySequence);
-	if (NS_FAILED (rv))
-		return rv;
-
-	nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpNotAfter").get (),
-					    text);
-	rv = ProcessTime (notAfter, text.get (), validitySequence);
-	if (NS_FAILED (rv))
-		return rv;
-#endif
-
-	subitem = e_asn1_object_new ();
-	e_asn1_object_set_display_name (subitem, _("Subject"));
-
-	process_name (&cert->priv->cert->subject, &text);
-	e_asn1_object_set_display_value (subitem, text);
-	g_free (text);
-	e_asn1_object_append_child (sequence, subitem);
-	g_object_unref (subitem);
-
-	if (!process_subject_public_key_info (
-		&cert->priv->cert->subjectPublicKeyInfo, sequence))
-		return FALSE;
-
-	/* Is there an issuerUniqueID? */
-	if (cert->priv->cert->issuerID.data) {
-		/* The issuerID is encoded as a bit string.
-		 * The function ProcessRawBytes expects the
-		 * length to be in bytes, so let's convert the
-		 * length in a temporary SECItem
-		*/
-		data.data = cert->priv->cert->issuerID.data;
-		data.len  = cert->priv->cert->issuerID.len / 8;
-
-		subitem = e_asn1_object_new ();
-
-		e_asn1_object_set_display_name (subitem, _("Issuer Unique ID"));
-		process_raw_bytes (&data, &text);
-		e_asn1_object_set_display_value (subitem, text);
-		g_free (text);
-
-		e_asn1_object_append_child (sequence, subitem);
-	}
-
-	if (cert->priv->cert->subjectID.data) {
-		/* The subjectID is encoded as a bit string.
-		 * The function ProcessRawBytes expects the
-		 * length to be in bytes, so let's convert the
-		 * length in a temporary SECItem
-		*/
-		data.data = cert->priv->cert->issuerID.data;
-		data.len  = cert->priv->cert->issuerID.len / 8;
-
-		subitem = e_asn1_object_new ();
-
-		e_asn1_object_set_display_name (subitem, _("Subject Unique ID"));
-		process_raw_bytes (&data, &text);
-		e_asn1_object_set_display_value (subitem, text);
-		g_free (text);
-
-		e_asn1_object_append_child (sequence, subitem);
-	}
-	if (cert->priv->cert->extensions) {
-		if (!process_extensions (cert->priv->cert->extensions, sequence))
-			return FALSE;
-	}
-
-	*seq = sequence;
-
-	return TRUE;
-}
-
-static gboolean
-create_asn1_struct (ECert *cert)
-{
-	EASN1Object *sequence;
-	SECItem temp;
-	gchar *text;
-
-	cert->priv->asn1 = e_asn1_object_new ();
-
-	e_asn1_object_set_display_name (cert->priv->asn1, e_cert_get_window_title (cert));
-
-	/* This sequence will be contain the tbsCertificate, signatureAlgorithm,
-	 * and signatureValue. */
-
-	if (!create_tbs_certificate_asn1_struct (cert, &sequence))
-		return FALSE;
-	e_asn1_object_append_child (cert->priv->asn1, sequence);
-	g_object_unref (sequence);
-
-	if (!process_sec_algorithm_id (
-		&cert->priv->cert->signatureWrap.signatureAlgorithm, &sequence))
-		return FALSE;
-	e_asn1_object_set_display_name (
-		sequence, _("Certificate Signature Algorithm"));
-	e_asn1_object_append_child (cert->priv->asn1, sequence);
-	g_object_unref (sequence);
-
-	sequence = e_asn1_object_new ();
-	e_asn1_object_set_display_name (
-		sequence, _("Certificate Signature Value"));
-
-	/* The signatureWrap is encoded as a bit string.
-	 * The function ProcessRawBytes expects the
-	 * length to be in bytes, so let's convert the
-	 * length in a temporary SECItem */
-	temp.data = cert->priv->cert->signatureWrap.signature.data;
-	temp.len  = cert->priv->cert->signatureWrap.signature.len / 8;
-	process_raw_bytes (&temp, &text);
-	e_asn1_object_set_display_value (sequence, text);
-	e_asn1_object_append_child (cert->priv->asn1, sequence);
-	g_free (text);
-
-	return TRUE;
-}
-
 EASN1Object *
 e_cert_get_asn1_struct (ECert *cert)
 {
 	if (!cert->priv->asn1)
-		create_asn1_struct (cert);
+		cert->priv->asn1 = e_asn1_object_new_from_cert (cert->priv->cert);
+
+	if (cert->priv->asn1)
+		return g_object_ref (cert->priv->asn1);
 
-	return g_object_ref (cert->priv->asn1);
+	return NULL;
 }
 
 gboolean
diff --git a/smime/lib/e-cert.h b/smime/lib/e-cert.h
index 4159c40..0096336 100644
--- a/smime/lib/e-cert.h
+++ b/smime/lib/e-cert.h
@@ -95,7 +95,7 @@ const gchar *          e_cert_get_serial_number    (ECert *cert);
 const gchar *          e_cert_get_sha1_fingerprint (ECert *cert);
 const gchar *          e_cert_get_md5_fingerprint  (ECert *cert);
 
-GList *               e_cert_get_chain       (ECert *cert);
+GList *               e_cert_get_issuers_chain     (ECert *cert);
 ECert *              e_cert_get_ca_cert     (ECert *ecert);
 EASN1Object *         e_cert_get_asn1_struct (ECert *cert);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]