[evolution-data-server] libedataserverui: Add a widget to show certificate information
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] libedataserverui: Add a widget to show certificate information
- Date: Thu, 11 Aug 2022 16:18:11 +0000 (UTC)
commit 5fe79c2c6451819faf8f8b00a135489897757686
Author: Milan Crha <mcrha redhat com>
Date: Thu Aug 11 17:58:33 2022 +0200
libedataserverui: Add a widget to show certificate information
It hides implementation detail where the certificate information
is taken from, and which widget is used for it internally.
po/POTFILES.in | 1 +
src/libedataserverui/CMakeLists.txt | 4 +
src/libedataserverui/e-certificate-widget.c | 727 ++++++++++++++++++++++++++++
src/libedataserverui/e-certificate-widget.h | 76 +++
src/libedataserverui/libedataserverui.h.in | 1 +
5 files changed, 809 insertions(+)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f57c6a347..295c153dc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -210,6 +210,7 @@ src/libedataserver/e-time-utils.c
src/libedataserver/e-webdav-discover.c
src/libedataserver/e-webdav-session.c
src/libedataserverui/e-buffer-tagger.c
+src/libedataserverui/e-certificate-widget.c
src/libedataserverui/e-credentials-prompter.c
src/libedataserverui/e-credentials-prompter-impl-oauth2.c
src/libedataserverui/e-credentials-prompter-impl-password.c
diff --git a/src/libedataserverui/CMakeLists.txt b/src/libedataserverui/CMakeLists.txt
index 0eaa9c278..cef206bed 100644
--- a/src/libedataserverui/CMakeLists.txt
+++ b/src/libedataserverui/CMakeLists.txt
@@ -13,6 +13,7 @@ configure_file(
set(SOURCES
e-buffer-tagger.c
e-cell-renderer-color.c
+ e-certificate-widget.c
e-credentials-prompter.c
e-credentials-prompter-impl.c
e-credentials-prompter-impl-oauth2.c
@@ -28,6 +29,7 @@ set(HEADERS
${CMAKE_CURRENT_BINARY_DIR}/libedataserverui${UI_VERSION}.h
e-buffer-tagger.h
e-cell-renderer-color.h
+ e-certificate-widget.h
e-credentials-prompter.h
e-credentials-prompter-impl.h
e-credentials-prompter-impl-oauth2.h
@@ -172,6 +174,7 @@ configure_file(
set(SOURCES
e-buffer-tagger.c
e-cell-renderer-color.c
+ e-certificate-widget.c
e-credentials-prompter.c
e-credentials-prompter-impl.c
e-credentials-prompter-impl-oauth2.c
@@ -187,6 +190,7 @@ set(HEADERS
${CMAKE_CURRENT_BINARY_DIR}/libedataserverui${UI_VERSION}.h
e-buffer-tagger.h
e-cell-renderer-color.h
+ e-certificate-widget.h
e-credentials-prompter.h
e-credentials-prompter-impl.h
e-credentials-prompter-impl-oauth2.h
diff --git a/src/libedataserverui/e-certificate-widget.c b/src/libedataserverui/e-certificate-widget.c
new file mode 100644
index 000000000..f4693f2bc
--- /dev/null
+++ b/src/libedataserverui/e-certificate-widget.c
@@ -0,0 +1,727 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * SPDX-FileCopyrightText: (C) 2022 Red Hat (www.redhat.com)
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+/**
+ * SECTION: e-certificate-widget
+ * @short_description: A widget to show a certificate
+ *
+ * The #ECertificateWidget shows information about the provided certificate.
+ **/
+
+#include "evolution-data-server-config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <cert.h>
+#include <pk11func.h>
+#include <nss.h>
+
+#include "libedataserver/libedataserver.h"
+
+#include "e-certificate-widget.h"
+
+struct _ECertificateWidgetPrivate {
+ GtkWidget *grid;
+ GHashTable *section_labels; /* index to keys[] ~> GtkLabel * */
+ GHashTable *key_widgets; /* index to keys[] ~> KeyWidgets * */
+};
+
+#if GTK_CHECK_VERSION(4, 0, 0)
+G_DEFINE_TYPE_WITH_PRIVATE (ECertificateWidget, e_certificate_widget, GTK_TYPE_BOX)
+#else
+G_DEFINE_TYPE_WITH_PRIVATE (ECertificateWidget, e_certificate_widget, GTK_TYPE_SCROLLED_WINDOW)
+#endif
+
+static gchar *
+ecw_dup_from_cert_name (const CERTName *name,
+ gchar *(*get_func) (const CERTName *name))
+{
+ gchar *value, *in_cert;
+
+ in_cert = get_func (name);
+ if (!in_cert)
+ return NULL;
+
+ value = g_strdup (in_cert);
+
+ PORT_Free (in_cert);
+
+ return value;
+}
+
+static gchar *
+ecw_dup_subject_common_name (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->subject, CERT_GetCommonName);
+}
+
+static gchar *
+ecw_dup_subject_nickname (CERTCertificate *cert)
+{
+ return g_strdup (cert->nickname);
+}
+
+static gchar *
+ecw_dup_subject_name (CERTCertificate *cert)
+{
+ return g_strdup (cert->subjectName);
+}
+
+static gchar *
+ecw_dup_identity (CERTCertificate *cert)
+{
+ gchar *value;
+
+ value = ecw_dup_subject_common_name (cert);
+ if (value && *value)
+ return value;
+
+ g_free (value);
+
+ value = ecw_dup_subject_nickname (cert);
+ if (value && *value)
+ return value;
+
+ g_free (value);
+
+ return ecw_dup_subject_name (cert);
+}
+
+static gchar *
+ecw_dup_subject_email (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->subject, CERT_GetCertEmailAddress);
+}
+
+static gchar *
+ecw_dup_subject_country (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->subject, CERT_GetCountryName);
+}
+
+static gchar *
+ecw_dup_subject_state (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->subject, CERT_GetStateName);
+}
+
+static gchar *
+ecw_dup_subject_locality (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->subject, CERT_GetLocalityName);
+}
+
+static gchar *
+ecw_dup_subject_org (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->subject, CERT_GetOrgName);
+}
+
+static gchar *
+ecw_dup_subject_org_unit (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->subject, CERT_GetOrgUnitName);
+}
+
+static gchar *
+ecw_dup_subject_domain_component_name (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->subject, CERT_GetDomainComponentName);
+}
+
+static gchar *
+ecw_dup_subject_alternative_emails (CERTCertificate *cert)
+{
+ const gchar *email;
+ gchar *main_email;
+ GString *str = NULL;
+
+ main_email = ecw_dup_subject_email (cert);
+
+ for (email = CERT_GetFirstEmailAddress (cert); email; email = CERT_GetNextEmailAddress (cert, email))
{
+ if (g_strcmp0 (email, main_email) == 0)
+ continue;
+
+ if (!str) {
+ str = g_string_new (email);
+ } else {
+ g_string_append_c (str, '\n');
+ g_string_append (str, email);
+ }
+ }
+
+ g_free (main_email);
+
+ return str ? g_string_free (str, FALSE) : NULL;
+}
+
+static gchar *
+ecw_dup_issuer_common_name (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->issuer, CERT_GetCommonName);
+}
+
+static gchar *
+ecw_dup_issuer_name (CERTCertificate *cert)
+{
+ return g_strdup (cert->issuerName);
+}
+
+static gchar *
+ecw_dup_issuer (CERTCertificate *cert)
+{
+ gchar *value;
+
+ value = ecw_dup_issuer_common_name (cert);
+ if (value && *value)
+ return value;
+
+ g_free (value);
+
+ return ecw_dup_issuer_name (cert);
+}
+
+static gchar *
+ecw_dup_issuer_email (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->issuer, CERT_GetCertEmailAddress);
+}
+
+static gchar *
+ecw_dup_issuer_country (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->issuer, CERT_GetCountryName);
+}
+
+static gchar *
+ecw_dup_issuer_state (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->issuer, CERT_GetStateName);
+}
+
+static gchar *
+ecw_dup_issuer_locality (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->issuer, CERT_GetLocalityName);
+}
+
+static gchar *
+ecw_dup_issuer_org (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->issuer, CERT_GetOrgName);
+}
+
+static gchar *
+ecw_dup_issuer_org_unit (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->issuer, CERT_GetOrgUnitName);
+}
+
+static gchar *
+ecw_dup_issuer_domain_component_name (CERTCertificate *cert)
+{
+ return ecw_dup_from_cert_name (&cert->issuer, CERT_GetDomainComponentName);
+}
+
+static gchar *
+ecw_dup_time (PRTime *prtime)
+{
+ PRExplodedTime explodedTime;
+ struct tm exploded_tm;
+ gchar buffer[512];
+ gsize wrote;
+
+ memset (&exploded_tm, 0, sizeof (struct tm));
+
+ PR_ExplodeTime (*prtime, 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;
+
+ wrote = e_strftime (buffer, sizeof (buffer), "%c", &exploded_tm);
+
+ if (!wrote)
+ return NULL;
+
+ return g_strndup (buffer, wrote);
+}
+
+static gchar *
+ecw_dup_not_before (CERTCertificate *cert)
+{
+ PRTime not_before;
+ PRTime not_after;
+
+ if (SECSuccess != CERT_GetCertTimes (cert, ¬_before, ¬_after))
+ return NULL;
+
+ return ecw_dup_time (¬_before);
+}
+
+static gchar *
+ecw_dup_not_after (CERTCertificate *cert)
+{
+ PRTime not_before;
+ PRTime not_after;
+
+ if (SECSuccess != CERT_GetCertTimes (cert, ¬_before, ¬_after))
+ return NULL;
+
+ return ecw_dup_time (¬_after);
+}
+
+static gchar *
+ecw_dup_usage (CERTCertificate *cert)
+{
+ struct {
+ gint bit;
+ const gchar *text;
+ } usageinfo[] = {
+ /* x509 certificate usage types */
+ { certificateUsageEmailSigner, N_("Digital Signature") },
+ { certificateUsageEmailRecipient, N_("Key Encipherment") }
+ };
+
+ GString *str = NULL;
+ gint ii;
+
+ for (ii = 0; ii < G_N_ELEMENTS (usageinfo); ii++) {
+ if ((cert->keyUsage & usageinfo[ii].bit) != 0) {
+ if (!str)
+ str = g_string_new ("");
+ if (str->len != 0)
+ g_string_append (str, ", ");
+ g_string_append (str, _(usageinfo[ii].text));
+ }
+ }
+
+ return str ? g_string_free (str, FALSE) : NULL;
+}
+
+static gchar *
+ecw_dup_hexify (const guchar *data,
+ guint data_len)
+{
+ gchar *hexified, *value;
+ SECItem item;
+
+ if (!data|| !data_len)
+ return NULL;
+
+ item.data = (guchar *) data;
+ item.len = data_len;
+
+ hexified = CERT_Hexify (&item, TRUE);
+
+ value = g_strdup (hexified);
+
+ if (hexified)
+ PORT_Free (hexified);
+
+ return value;
+}
+
+static gchar *
+ecw_dup_version (CERTCertificate *cert)
+{
+ return ecw_dup_hexify (cert->version.data, cert->version.len);
+}
+
+static gchar *
+ecw_dup_serial_number (CERTCertificate *cert)
+{
+ return ecw_dup_hexify (cert->serialNumber.data, cert->serialNumber.len);
+}
+
+static gchar *
+ecw_dup_subject_key_id (CERTCertificate *cert)
+{
+ return ecw_dup_hexify (cert->subjectKeyID.data, cert->subjectKeyID.len);
+}
+
+static gchar *
+ecw_dup_signature_alg (CERTCertificate *cert)
+{
+ SECOidTag tag;
+ const gchar *description;
+
+ tag = SECOID_GetAlgorithmTag (&cert->signature);
+
+ if (tag == SEC_OID_UNKNOWN)
+ return NULL;
+
+ description = SECOID_FindOIDTagDescription (tag);
+
+ return g_strdup (description);
+}
+
+static gchar *
+ecw_dup_fingerprint_sha256 (CERTCertificate *cert)
+{
+ guchar fingerprint[SHA256_LENGTH + 1];
+
+ memset (fingerprint, 0, sizeof fingerprint);
+ PK11_HashBuf (SEC_OID_SHA256, fingerprint, cert->derCert.data, cert->derCert.len);
+
+ return ecw_dup_hexify (fingerprint, SHA256_LENGTH);
+}
+
+static gchar *
+ecw_dup_public_key_alg (CERTCertificate *cert)
+{
+ SECOidTag tag;
+ const gchar *description;
+
+ tag = SECOID_GetAlgorithmTag (&cert->subjectPublicKeyInfo.algorithm);
+
+ if (tag == SEC_OID_UNKNOWN)
+ return NULL;
+
+ description = SECOID_FindOIDTagDescription (tag);
+
+ return g_strdup (description);
+}
+
+static struct _SectionKey {
+ const gchar *section_caption; /* non-NULL, to start a new section */
+ const gchar *name;
+ gchar * (*dup_value) (CERTCertificate *cert);
+} keys[] = {
+ { N_("Certificate"), N_("Identity"), ecw_dup_identity },
+ { NULL, N_("Issuer"), ecw_dup_issuer },
+ { NULL, N_("Expires on"), ecw_dup_not_after },
+ { N_("Subject"), N_("Common Name"), ecw_dup_subject_common_name },
+ { NULL, N_("Nickname"), ecw_dup_subject_nickname },
+ { NULL, N_("Email"), ecw_dup_subject_email },
+ { NULL, N_("Organization"), ecw_dup_subject_org },
+ { NULL, N_("Organization Unit"), ecw_dup_subject_org_unit },
+ { NULL, N_("Country"), ecw_dup_subject_country },
+ { NULL, N_("State"), ecw_dup_subject_state },
+ { NULL, N_("Locality"), ecw_dup_subject_locality },
+ { NULL, N_("Domain Component Name"), ecw_dup_subject_domain_component_name },
+ { NULL, N_("Alternative Emails"), ecw_dup_subject_alternative_emails },
+ { N_("Issuer"), N_("Common Name"), ecw_dup_issuer_common_name },
+ { NULL, N_("Email"), ecw_dup_issuer_email },
+ { NULL, N_("Organization"), ecw_dup_issuer_org },
+ { NULL, N_("Organization Unit"), ecw_dup_issuer_org_unit },
+ { NULL, N_("Country"), ecw_dup_issuer_country },
+ { NULL, N_("State"), ecw_dup_issuer_state },
+ { NULL, N_("Locality"), ecw_dup_issuer_locality },
+ { NULL, N_("Domain Component Name"), ecw_dup_issuer_domain_component_name },
+ { N_("Details"), N_("Not Before"), ecw_dup_not_before },
+ { NULL, N_("Not After"), ecw_dup_not_after },
+ { NULL, N_("Usage"), ecw_dup_usage },
+ { NULL, N_("Version"), ecw_dup_version },
+ { NULL, N_("Serial Number"), ecw_dup_serial_number },
+ { NULL, N_("Key ID"), ecw_dup_subject_key_id },
+ { NULL, N_("Signature Algorithm"), ecw_dup_signature_alg },
+ { NULL, N_("SHA-256 Fingerprint"), ecw_dup_fingerprint_sha256 },
+ { N_("Public Key"), N_("Algorithm"), ecw_dup_public_key_alg }
+};
+
+typedef struct _KeyWidgets {
+ GtkWidget *name;
+ GtkWidget *value;
+} KeyWidgets;
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+static void
+e_certificate_widget_show_all (GtkWidget *widget)
+{
+ gtk_widget_show (widget);
+}
+#endif
+
+static void
+e_certificate_widget_finalize (GObject *object)
+{
+ ECertificateWidget *self = E_CERTIFICATE_WIDGET (object);
+
+ g_hash_table_destroy (self->priv->section_labels);
+ g_hash_table_destroy (self->priv->key_widgets);
+
+ /* Chain up to parent's method */
+ G_OBJECT_CLASS (e_certificate_widget_parent_class)->finalize (object);
+}
+
+static void
+e_certificate_widget_class_init (ECertificateWidgetClass *klass)
+{
+ GObjectClass *object_class;
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ GtkWidgetClass *widget_class;
+#endif
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = e_certificate_widget_finalize;
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->show_all = e_certificate_widget_show_all;
+#endif
+}
+
+static void
+e_certificate_widget_init (ECertificateWidget *self)
+{
+ GtkWidget *scrolled_window;
+
+ self->priv = e_certificate_widget_get_instance_private (self);
+ self->priv->section_labels = g_hash_table_new (g_direct_hash, g_direct_equal);
+ self->priv->key_widgets = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+
+#if GTK_CHECK_VERSION(4, 0, 0)
+ scrolled_window = gtk_scrolled_window_new ();
+ gtk_box_append (GTK_BOX (self), scrolled_window);
+#else
+ scrolled_window = GTK_WIDGET (self);
+#endif
+
+ g_object_set (scrolled_window,
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ "min-content-height", 100,
+#if GTK_CHECK_VERSION(4, 0, 0)
+ "has-frame", FALSE,
+#else
+ "shadow-type", GTK_SHADOW_NONE,
+#endif
+ NULL);
+
+ self->priv->grid = gtk_grid_new ();
+
+ g_object_set (self->priv->grid,
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "column-spacing", 8,
+ "row-spacing", 4,
+ NULL);
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (scrolled_window), "view");
+
+#if GTK_CHECK_VERSION(4, 0, 0)
+ gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled_window), self->priv->grid);
+#else
+ gtk_container_add (GTK_CONTAINER (scrolled_window), self->priv->grid);
+#endif
+}
+
+/**
+ * e_certificate_widget_new:
+ *
+ * Creates a new #ECertificateWidget
+ *
+ * Returns: (transfer full): a new #ECertificateWidget
+ *
+ * Since: 3.46
+ **/
+GtkWidget *
+e_certificate_widget_new (void)
+{
+ return g_object_new (E_TYPE_CERTIFICATE_WIDGET, NULL);
+}
+
+/**
+ * e_certificate_widget_set_der:
+ * @self: an #ECertificateWidget
+ * @der_data: (nullable): certificate data in DER format, or %NULL
+ * @der_data_len: length of the @der_data
+ *
+ * Updates the content of the @self with the certificate information
+ * described by the @der_data of the length @der_data_len in the DER
+ * format.
+ *
+ * The content of the @self is cleared when the @der_data is %NULL.
+ *
+ * Since: 3.46
+ **/
+void
+e_certificate_widget_set_der (ECertificateWidget *self,
+ gconstpointer der_data,
+ guint der_data_len)
+{
+ CERTCertificate *cert;
+ PangoAttrList *attrs = NULL;
+ GtkGrid *grid;
+ guint ii, section_start = 0, row = 0;
+ gboolean anything_in_section = FALSE;
+
+ g_return_if_fail (E_IS_CERTIFICATE_WIDGET (self));
+
+ if (!der_data) {
+ gtk_widget_hide (self->priv->grid);
+ return;
+ }
+
+ /* The app may or may not have initialized NSS on its own; if not, initialize it now */
+ if (!NSS_IsInitialized ())
+ NSS_NoDB_Init (g_get_tmp_dir ());
+
+ cert = CERT_DecodeCertFromPackage ((gchar *) der_data, der_data_len);
+
+ if (!cert) {
+ gtk_widget_hide (self->priv->grid);
+ return;
+ }
+
+ gtk_widget_show (self->priv->grid);
+
+ grid = GTK_GRID (self->priv->grid);
+
+ for (ii = 0; ii < G_N_ELEMENTS (keys); ii++) {
+ KeyWidgets *key_widgets;
+ gchar *value;
+
+ if (ii > 0 && keys[ii].section_caption != NULL) {
+ GtkWidget *section_label;
+
+ section_label = g_hash_table_lookup (self->priv->section_labels, GUINT_TO_POINTER
(section_start));
+ if (section_label)
+ gtk_widget_set_visible (section_label, anything_in_section);
+
+ anything_in_section = FALSE;
+ section_start = ii;
+ }
+
+ if (keys[ii].section_caption && !g_hash_table_contains (self->priv->section_labels,
GUINT_TO_POINTER (ii))) {
+ GtkWidget *label;
+
+ if (!attrs) {
+ attrs = pango_attr_list_new ();
+ pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+ }
+
+ label = gtk_label_new (_(keys[ii].section_caption));
+
+ g_object_set (label,
+ "halign", GTK_ALIGN_START,
+ "margin-start", 8,
+ "margin-end", 8,
+ "margin-top", 8,
+ "attributes", attrs,
+ "xalign", 0.0,
+ NULL);
+
+ gtk_grid_attach (grid, label, 0, row, 2, 1);
+ row++;
+
+ g_hash_table_insert (self->priv->section_labels, GUINT_TO_POINTER (ii), label);
+
+ if (ii > 0)
+ gtk_widget_set_margin_top (label, 16);
+ }
+
+ key_widgets = g_hash_table_lookup (self->priv->key_widgets, GUINT_TO_POINTER (ii));
+
+ if (!key_widgets) {
+ key_widgets = g_new0 (KeyWidgets, 1);
+ key_widgets->name = gtk_label_new (_(keys[ii].name));
+ key_widgets->value = gtk_label_new ("");
+
+ g_hash_table_insert (self->priv->key_widgets, GUINT_TO_POINTER (ii), key_widgets);
+
+ g_object_set (key_widgets->name,
+ "halign", GTK_ALIGN_END,
+ "valign", GTK_ALIGN_START,
+ "margin-start", 12,
+ "justify", GTK_JUSTIFY_RIGHT,
+ "xalign", 1.0,
+ NULL);
+
+ g_object_set (key_widgets->value,
+ "halign", GTK_ALIGN_START,
+ "valign", GTK_ALIGN_START,
+ "xalign", 0.0,
+ "margin-end", 12,
+ "max-width-chars", 80,
+ "wrap", TRUE,
+ "selectable", TRUE,
+ NULL);
+
+ gtk_grid_attach (grid, key_widgets->name, 0, row, 1, 1);
+ gtk_grid_attach (grid, key_widgets->value, 1, row, 1, 1);
+ row++;
+ }
+
+ value = keys[ii].dup_value (cert);
+
+ if (value && *value) {
+ anything_in_section = TRUE;
+
+ gtk_label_set_label (GTK_LABEL (key_widgets->value), value);
+
+ gtk_widget_show (key_widgets->name);
+ gtk_widget_show (key_widgets->value);
+ } else {
+ gtk_widget_hide (key_widgets->name);
+ gtk_widget_hide (key_widgets->value);
+ }
+
+ g_free (value);
+ }
+
+ if (ii > 0) {
+ GtkWidget *section_label;
+
+ section_label = g_hash_table_lookup (self->priv->section_labels, GUINT_TO_POINTER
(section_start));
+ if (section_label)
+ gtk_widget_set_visible (section_label, anything_in_section);
+ }
+
+ CERT_DestroyCertificate (cert);
+ g_clear_pointer (&attrs, pango_attr_list_unref);
+}
+
+/**
+ * e_certificate_widget_set_pem:
+ * @self: an #ECertificateWidget
+ * @pem_data: (nullable): certificate data in PEM format, or %NULL
+ *
+ * Updates the content of the @self with the certificate information
+ * described by the @pem_data in the PEM format.
+ *
+ * The content of the @self is cleared when the @pem_data is %NULL.
+ *
+ * Since: 3.46
+ **/
+void
+e_certificate_widget_set_pem (ECertificateWidget *self,
+ const gchar *pem_data)
+{
+ GTlsCertificate *tls_cert;
+ GByteArray *der_bytes = NULL;
+
+ g_return_if_fail (E_IS_CERTIFICATE_WIDGET (self));
+
+ if (!pem_data) {
+ e_certificate_widget_set_der (self, NULL, 0);
+ return;
+ }
+
+ tls_cert = g_tls_certificate_new_from_pem (pem_data, -1, NULL);
+
+ if (!tls_cert) {
+ e_certificate_widget_set_der (self, NULL, 0);
+ return;
+ }
+
+ g_object_get (tls_cert, "certificate", &der_bytes, NULL);
+
+ e_certificate_widget_set_der (self, der_bytes ? der_bytes->data : NULL, der_bytes ? der_bytes->len :
0);
+
+ g_clear_pointer (&der_bytes, g_byte_array_unref);
+ g_clear_object (&tls_cert);
+}
diff --git a/src/libedataserverui/e-certificate-widget.h b/src/libedataserverui/e-certificate-widget.h
new file mode 100644
index 000000000..6ed868b69
--- /dev/null
+++ b/src/libedataserverui/e-certificate-widget.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * SPDX-FileCopyrightText: (C) 2022 Red Hat (www.redhat.com)
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef E_CERTIFICATE_WIDGET_H
+#define E_CERTIFICATE_WIDGET_H
+
+#include <gtk/gtk.h>
+
+#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
+#if GTK_CHECK_VERSION(4, 0, 0)
+#error "Only <libedataserverui4/libedataserverui4.h> should be included directly."
+#else
+#error "Only <libedataserverui/libedataserverui.h> should be included directly."
+#endif
+#endif
+
+/* Standard GObject macros */
+#define E_TYPE_CERTIFICATE_WIDGET \
+ (e_certificate_widget_get_type ())
+#define E_CERTIFICATE_WIDGET(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_CERTIFICATE_WIDGET, ECertificateWidget))
+#define E_CERTIFICATE_WIDGET_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_CERTIFICATE_WIDGET, ECertificateWidgetClass))
+#define E_IS_CERTIFICATE_WIDGET(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_CERTIFICATE_WIDGET))
+#define E_IS_CERTIFICATE_WIDGET_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE ((cls), E_TYPE_CERTIFICATE_WIDGET))
+#define E_CERTIFICATE_WIDGET_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_CERTIFICATE_WIDGET, ECertificateWidgetClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ECertificateWidget ECertificateWidget;
+typedef struct _ECertificateWidgetClass ECertificateWidgetClass;
+typedef struct _ECertificateWidgetPrivate ECertificateWidgetPrivate;
+
+/**
+ * ECertificateWidget:
+ *
+ * Since: 3.46
+ **/
+struct _ECertificateWidget {
+#if GTK_CHECK_VERSION(4, 0, 0)
+ GtkBox parent;
+#else
+ GtkScrolledWindow parent;
+#endif
+ ECertificateWidgetPrivate *priv;
+};
+
+struct _ECertificateWidgetClass {
+#if GTK_CHECK_VERSION(4, 0, 0)
+ GtkBoxClass parent_class;
+#else
+ GtkScrolledWindowClass parent_class;
+#endif
+};
+
+GType e_certificate_widget_get_type (void) G_GNUC_CONST;
+GtkWidget * e_certificate_widget_new (void);
+void e_certificate_widget_set_der (ECertificateWidget *self,
+ gconstpointer cert_data,
+ guint cert_data_len);
+void e_certificate_widget_set_pem (ECertificateWidget *self,
+ const gchar *pem_data);
+
+G_END_DECLS
+
+#endif /* E_CERTIFICATE_WIDGET_H */
diff --git a/src/libedataserverui/libedataserverui.h.in b/src/libedataserverui/libedataserverui.h.in
index 53a793cee..6ca8a357a 100644
--- a/src/libedataserverui/libedataserverui.h.in
+++ b/src/libedataserverui/libedataserverui.h.in
@@ -22,6 +22,7 @@
#include <libedataserverui@UI_VERSION@/e-buffer-tagger.h>
#include <libedataserverui@UI_VERSION@/e-cell-renderer-color.h>
+#include <libedataserverui@UI_VERSION@/e-certificate-widget.h>
#include <libedataserverui@UI_VERSION@/e-credentials-prompter.h>
#include <libedataserverui@UI_VERSION@/e-credentials-prompter-impl.h>
#include <libedataserverui@UI_VERSION@/e-credentials-prompter-impl-oauth2.h>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]