[gcr/main: 2/2] gcr-gtk3: Remove all the unused widgets, Rewrite GcrCertificateWidget
- From: Corentin Noël <corentinnoel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcr/main: 2/2] gcr-gtk3: Remove all the unused widgets, Rewrite GcrCertificateWidget
- Date: Tue, 7 Dec 2021 15:39:17 +0000 (UTC)
commit b6d0f33af2bbda8acb7ba510f82e5eb8f52f6698
Author: Corentin Noël <corentin noel collabora com>
Date: Tue Dec 7 16:36:23 2021 +0100
gcr-gtk3: Remove all the unused widgets, Rewrite GcrCertificateWidget
The UI is now aligned with the GTK4 version.
Keep GcrSecureEntryBuffer as there is no GTK3 version in GTK.
gcr-gtk3/GcrUi-3.metadata | 5 -
gcr-gtk3/eggimagemenuitem.c | 734 ------------
gcr-gtk3/eggimagemenuitem.h | 80 --
gcr-gtk3/frob-combo-selector.c | 98 --
gcr-gtk3/frob-gnupg-selector.c | 94 --
gcr-gtk3/frob-import-button.c | 251 ----
gcr-gtk3/frob-key.c | 88 --
gcr-gtk3/frob-prompt.c | 279 -----
gcr-gtk3/frob-request.c | 97 --
gcr-gtk3/frob-system-prompt.c | 145 ---
gcr-gtk3/frob-tree-selector.c | 212 ----
gcr-gtk3/frob-unlock-options.c | 83 --
gcr-gtk3/gcr-certificate-exporter.c | 570 ---------
gcr-gtk3/gcr-certificate-exporter.h | 74 --
gcr-gtk3/gcr-certificate-renderer-private.h | 49 -
gcr-gtk3/gcr-certificate-renderer.c | 925 ---------------
gcr-gtk3/gcr-certificate-renderer.h | 73 --
gcr-gtk3/gcr-certificate-request-renderer.c | 531 ---------
gcr-gtk3/gcr-certificate-request-renderer.h | 71 --
gcr-gtk3/gcr-certificate-widget.c | 733 +++++++++---
gcr-gtk3/gcr-certificate-widget.h | 64 +-
gcr-gtk3/gcr-collection-model.c | 1654 ---------------------------
gcr-gtk3/gcr-collection-model.h | 102 --
gcr-gtk3/gcr-combo-selector.c | 250 ----
gcr-gtk3/gcr-combo-selector.h | 67 --
gcr-gtk3/gcr-crypto-types.xml | 1 +
gcr-gtk3/gcr-dialog-util.c | 171 ---
gcr-gtk3/gcr-dialog-util.h | 40 -
gcr-gtk3/gcr-display-scrolled.c | 173 ---
gcr-gtk3/gcr-display-scrolled.h | 57 -
gcr-gtk3/gcr-display-view.c | 1232 --------------------
gcr-gtk3/gcr-display-view.h | 116 --
gcr-gtk3/gcr-failure-renderer.c | 228 ----
gcr-gtk3/gcr-failure-renderer.h | 67 --
gcr-gtk3/gcr-gnupg-renderer.c | 852 --------------
gcr-gtk3/gcr-gnupg-renderer.h | 77 --
gcr-gtk3/gcr-gtk3.h | 17 -
gcr-gtk3/gcr-import-button.c | 592 ----------
gcr-gtk3/gcr-import-button.h | 74 --
gcr-gtk3/gcr-key-renderer.c | 481 --------
gcr-gtk3/gcr-key-renderer.h | 66 --
gcr-gtk3/gcr-key-widget.c | 210 ----
gcr-gtk3/gcr-key-widget.h | 61 -
gcr-gtk3/gcr-list-selector-private.h | 39 -
gcr-gtk3/gcr-list-selector.c | 442 -------
gcr-gtk3/gcr-list-selector.h | 71 --
gcr-gtk3/gcr-live-search.c | 656 -----------
gcr-gtk3/gcr-live-search.h | 84 --
gcr-gtk3/gcr-pkcs11-import-dialog.c | 271 -----
gcr-gtk3/gcr-pkcs11-import-dialog.h | 62 -
gcr-gtk3/gcr-pkcs11-import-dialog.ui | 255 -----
gcr-gtk3/gcr-pkcs11-import-interaction.c | 249 ----
gcr-gtk3/gcr-pkcs11-import-interaction.h | 38 -
gcr-gtk3/gcr-prompt-dialog.c | 1060 -----------------
gcr-gtk3/gcr-prompt-dialog.h | 63 -
gcr-gtk3/gcr-renderer.c | 309 -----
gcr-gtk3/gcr-renderer.h | 88 --
gcr-gtk3/gcr-section.c | 204 ++++
gcr-gtk3/gcr-section.h | 29 +
gcr-gtk3/gcr-tree-selector.c | 346 ------
gcr-gtk3/gcr-tree-selector.h | 70 --
gcr-gtk3/gcr-unlock-options-widget.c | 501 --------
gcr-gtk3/gcr-unlock-options-widget.h | 82 --
gcr-gtk3/gcr-unlock-options-widget.ui | 117 --
gcr-gtk3/gcr-unlock-renderer.c | 345 ------
gcr-gtk3/gcr-unlock-renderer.h | 83 --
gcr-gtk3/gcr-viewer-widget.c | 680 -----------
gcr-gtk3/gcr-viewer-widget.h | 62 -
gcr-gtk3/gcr-viewer.c | 181 ---
gcr-gtk3/gcr-viewer.h | 85 --
gcr-gtk3/meson.build | 50 +-
gcr-gtk4/meson.build | 3 -
tools/frob-unlock.c | 123 --
tools/gcr-prompter-tool.c | 258 -----
tools/gcr-prompter.desktop.in.in | 9 -
tools/gcr-viewer-tool.c | 126 --
tools/gcr-viewer-window.c | 201 ----
tools/gcr-viewer-window.h | 68 --
tools/gcr-viewer.desktop.in.in | 7 -
tools/gtk3/meson.build | 7 +
tools/gtk3/viewer.c | 139 +++
{gcr-gtk4/viewer => tools/gtk4}/meson.build | 2 +-
{gcr-gtk4/viewer => tools/gtk4}/viewer.c | 2 +-
tools/meson.build | 70 +-
84 files changed, 984 insertions(+), 18397 deletions(-)
---
diff --git a/gcr-gtk3/gcr-certificate-widget.c b/gcr-gtk3/gcr-certificate-widget.c
index bfc6b36..e5fefdc 100644
--- a/gcr-gtk3/gcr-certificate-widget.c
+++ b/gcr-gtk3/gcr-certificate-widget.c
@@ -1,172 +1,500 @@
/*
- * Copyright (C) 2010 Stefan Walter
- *
- * 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 version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * Copyright 2021 Collabora Ltd.
+ * Copyright Corentin Noël <corentin noel collabora com>
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
-#include "gcr/gcr-certificate.h"
+#include <glib/gi18n-lib.h>
-#include "gcr-certificate-renderer.h"
-#include "gcr-certificate-widget.h"
-#include "gcr-renderer.h"
-#include "gcr-viewer.h"
+#include <gcr-gtk3/gcr-certificate-widget.h>
+#include "gcr/gcr-certificate-extensions.h"
+#include "gcr/gcr-fingerprint.h"
+#include "gcr/gcr-oids.h"
-#include "gck/gck.h"
+#include "gcr-section.h"
-#include <gdk/gdk.h>
-#include <glib/gi18n-lib.h>
+#include "egg/egg-asn1x.h"
+#include "egg/egg-asn1-defs.h"
+#include "egg/egg-dn.h"
+#include "egg/egg-oid.h"
+#include "egg/egg-hex.h"
-/**
- * GcrCertificateWidget:
- *
- * A widget that can be used to display a certificate.
- *
- * A certificate widget is normally in a collapsed state showing only
- * details, but can be expanded by the user.
- *
- * Use [ctor CertificateWidget new] to create a new certificate widget. Only
- * one certificate can be displayed. It contains a [iface@Viewer] internally
- * and [class@CertificateRenderer] is used to render the certificate to the
- * viewer.
- *
- * To show more than one certificate in a view, create the viewer and
- * add renderers to it.
- */
+struct _GcrCertificateWidget
+{
+ GtkBox parent_instance;
-enum {
- PROP_0,
- PROP_CERTIFICATE,
- PROP_ATTRIBUTES
+ GcrCertificate *certificate;
+ GtkWidget *reveal_button;
+ GtkWidget *revealer;
+ GtkWidget *secondary_info;
+ GtkSizeGroup *size_group;
};
-struct _GcrCertificateWidgetPrivate {
- GcrViewer *viewer;
- GcrCertificateRenderer *renderer;
+G_DEFINE_TYPE (GcrCertificateWidget, gcr_certificate_widget, GTK_TYPE_BOX)
+
+enum {
+ PROP_CERTIFICATE = 1,
+ N_PROPERTIES
};
-G_DEFINE_TYPE_WITH_PRIVATE (GcrCertificateWidget, gcr_certificate_widget, GTK_TYPE_BIN);
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
-/* -----------------------------------------------------------------------------
- * OBJECT
- */
+static void
+gcr_certificate_widget_finalize (GObject *object)
+{
+ GcrCertificateWidget *self = (GcrCertificateWidget *)object;
+
+ g_clear_object (&self->size_group);
+
+ G_OBJECT_CLASS (gcr_certificate_widget_parent_class)->finalize (object);
+}
-static GObject*
-gcr_certificate_widget_constructor (GType type, guint n_props, GObjectConstructParam *props)
+static void
+gcr_certificate_widget_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- GObject *obj = G_OBJECT_CLASS (gcr_certificate_widget_parent_class)->constructor (type, n_props,
props);
- GcrCertificateWidget *self = NULL;
+ GcrCertificateWidget *self = GCR_CERTIFICATE_WIDGET (object);
- g_return_val_if_fail (obj, NULL);
+ switch (prop_id)
+ {
+ case PROP_CERTIFICATE:
+ g_value_set_object (value, gcr_certificate_widget_get_certificate (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
- self = GCR_CERTIFICATE_WIDGET (obj);
+static void
+gcr_certificate_widget_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GcrCertificateWidget *self = GCR_CERTIFICATE_WIDGET (object);
- self->pv->viewer = gcr_viewer_new_scrolled ();
- gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->pv->viewer));
- gtk_widget_show (GTK_WIDGET (self->pv->viewer));
+ switch (prop_id)
+ {
+ case PROP_CERTIFICATE:
+ gcr_certificate_widget_set_certificate (self, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
- gcr_viewer_add_renderer (self->pv->viewer, GCR_RENDERER (self->pv->renderer));
- return obj;
+static void
+gcr_certificate_widget_class_init (GcrCertificateWidgetClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gcr_certificate_widget_finalize;
+ object_class->get_property = gcr_certificate_widget_get_property;
+ object_class->set_property = gcr_certificate_widget_set_property;
+
+ obj_properties[PROP_CERTIFICATE] =
+ g_param_spec_object ("certificate",
+ "Certificate",
+ "Certificate to display.",
+ GCR_TYPE_CERTIFICATE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class,
+ N_PROPERTIES,
+ obj_properties);
+}
+
+static void
+on_reveal_button_clicked (GtkWidget *button,
+ GcrCertificateWidget *self)
+{
+ g_assert (GCR_IS_CERTIFICATE_WIDGET (self));
+ gtk_widget_hide (button);
+ gtk_revealer_set_reveal_child (GTK_REVEALER (self->revealer), TRUE);
}
static void
gcr_certificate_widget_init (GcrCertificateWidget *self)
{
- self->pv = gcr_certificate_widget_get_instance_private (self);
- self->pv->renderer = gcr_certificate_renderer_new (NULL);
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL);
+ self->reveal_button = gtk_button_new_with_label ("…");
+ gtk_widget_set_halign (self->reveal_button, GTK_ALIGN_CENTER);
+ gtk_box_pack_end (GTK_BOX (self), self->reveal_button, FALSE, TRUE, 0);
+ self->secondary_info = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ self->revealer = g_object_new (GTK_TYPE_REVEALER,
+ "child", self->secondary_info,
+ "transition-type", GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN,
+ NULL);
+ gtk_box_pack_end (GTK_BOX (self), self->revealer, FALSE, TRUE, 0);
+ g_signal_connect (self->reveal_button, "clicked", G_CALLBACK (on_reveal_button_clicked), self);
+ self->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+}
+
+static GtkWidget*
+_gcr_certificate_widget_add_section (GcrCertificateWidget *self,
+ const gchar *title,
+ GIcon *icon,
+ gboolean important)
+{
+ GtkWidget *widget;
+
+ g_assert (GCR_IS_CERTIFICATE_WIDGET (self));
+
+ if (icon)
+ widget = gcr_section_new_with_icon (title, icon);
+ else
+ widget = gcr_section_new (title);
+
+ gtk_size_group_add_widget (self->size_group, widget);
+ if (important)
+ gtk_box_pack_start (GTK_BOX (self), widget, FALSE, TRUE, 0);
+ else
+ gtk_container_add (GTK_CONTAINER (self->secondary_info), widget);
+
+ return widget;
+}
+
+static GtkWidget*
+create_value_label (const gchar *label)
+{
+ return g_object_new (GTK_TYPE_LABEL,
+ "label", label,
+ "xalign", 1.0,
+ "halign", GTK_ALIGN_END,
+ "hexpand", TRUE,
+ "selectable", TRUE,
+ "wrap", TRUE,
+ NULL);
+}
+
+static gchar*
+calculate_label (GcrCertificateWidget *self)
+{
+ gchar *label;
+
+ label = gcr_certificate_get_subject_cn (self->certificate);
+ if (label != NULL)
+ return label;
+
+ return g_strdup (_("Certificate"));
}
static void
-gcr_certificate_widget_finalize (GObject *obj)
+on_parsed_dn_part (guint index,
+ GQuark oid,
+ GNode *value,
+ gpointer user_data)
{
- GcrCertificateWidget *self = GCR_CERTIFICATE_WIDGET (obj);
+ GtkWidget *section = user_data;
+ const gchar *attr;
+ const gchar *desc;
+ gchar *field = NULL;
+ gchar *display;
+
+ attr = egg_oid_get_name (oid);
+ desc = egg_oid_get_description (oid);
+
+ /* Combine them into something sane */
+ if (attr && desc) {
+ if (strcmp (attr, desc) == 0)
+ field = g_strdup (attr);
+ else
+ field = g_strdup_printf ("%s (%s)", attr, desc);
+ } else if (!attr && !desc) {
+ field = g_strdup ("");
+ } else if (attr) {
+ field = g_strdup (attr);
+ } else if (desc) {
+ field = g_strdup (desc);
+ } else {
+ g_assert_not_reached ();
+ }
- g_assert (self->pv->renderer);
- g_object_unref (self->pv->renderer);
- self->pv->renderer = NULL;
+ display = egg_dn_print_value (oid, value);
+ if (display == NULL)
+ display = g_strdup ("");
- g_assert (self->pv->viewer);
- self->pv->viewer = NULL;
+ gcr_section_add_child (GCR_SECTION (section), field, create_value_label (display));
- G_OBJECT_CLASS (gcr_certificate_widget_parent_class)->finalize (obj);
+ g_free (field);
+ g_free (display);
+}
+
+static inline gchar *
+hex_encode_bytes (GBytes *bytes)
+{
+ gsize size;
+ gconstpointer data = g_bytes_get_data (bytes, &size);
+ return egg_hex_encode_full (data, size, TRUE, " ", 1);
}
static void
-gcr_certificate_widget_set_property (GObject *obj, guint prop_id, const GValue *value,
- GParamSpec *pspec)
+append_subject_public_key (GcrCertificateWidget *self,
+ GcrSection *section,
+ GNode *subject_public_key)
{
- GcrCertificateWidget *self = GCR_CERTIFICATE_WIDGET (obj);
+ guint key_nbits;
+ const gchar *text;
+ gchar *display;
+ GBytes *value;
+ guchar *raw;
+ gsize n_raw;
+ GQuark oid;
+ guint bits;
+
+ key_nbits = gcr_certificate_get_key_size (self->certificate);
+
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (subject_public_key,
+ "algorithm", "algorithm", NULL));
+ text = egg_oid_get_description (oid);
+ gcr_section_add_child (section, _("Key Algorithm"), create_value_label (text));
+
+ value = egg_asn1x_get_element_raw (egg_asn1x_node (subject_public_key,
+ "algorithm", "parameters", NULL));
+ if (value) {
+ display = hex_encode_bytes (value);
+ gcr_section_add_child (section, _("Key Parameters"), create_value_label (display));
+ g_clear_pointer (&display, g_free);
+ g_bytes_unref (value);
+ }
- switch (prop_id) {
- case PROP_CERTIFICATE:
- gcr_certificate_widget_set_certificate (self, g_value_get_object (value));
- break;
- case PROP_ATTRIBUTES:
- gcr_certificate_widget_set_attributes (self, g_value_get_boxed (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
- break;
+ if (key_nbits > 0) {
+ display = g_strdup_printf ("%u", key_nbits);
+ gcr_section_add_child (section, _("Key Size"), create_value_label (display));
+ g_clear_pointer (&display, g_free);
}
+
+ value = egg_asn1x_get_element_raw (subject_public_key);
+ raw = gcr_fingerprint_from_subject_public_key_info (g_bytes_get_data (value, NULL),
+ g_bytes_get_size (value),
+ G_CHECKSUM_SHA1, &n_raw);
+ g_bytes_unref (value);
+ display = egg_hex_encode_full (raw, n_raw, TRUE, " ", 1);
+ g_free (raw);
+ gcr_section_add_child (section, _("Key SHA1 Fingerprint"), create_value_label (text));
+ g_clear_pointer (&display, g_free);
+
+ value = egg_asn1x_get_bits_as_raw (egg_asn1x_node (subject_public_key, "subjectPublicKey", NULL),
&bits);
+ display = egg_hex_encode_full (g_bytes_get_data (value, NULL), bits / 8, TRUE, " ", 1);
+ gcr_section_add_child (section, _("Public Key"), create_value_label (text));
+ g_clear_pointer (&display, g_free);
+ g_bytes_unref (value);
}
-static void
-gcr_certificate_widget_get_property (GObject *obj, guint prop_id, GValue *value,
- GParamSpec *pspec)
+static GcrSection *
+append_extension_basic_constraints (GcrCertificateWidget *self,
+ GBytes *data)
{
- GcrCertificateWidget *self = GCR_CERTIFICATE_WIDGET (obj);
+ GcrSection *section;
+ gboolean is_ca = FALSE;
+ gint path_len = -1;
+ gchar *number;
- switch (prop_id) {
- case PROP_CERTIFICATE:
- g_value_set_object (value, gcr_certificate_widget_get_certificate (self));
- break;
- case PROP_ATTRIBUTES:
- g_value_set_boxed (value, gcr_certificate_widget_get_attributes (self));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
- break;
+ if (!_gcr_certificate_extension_basic_constraints (data, &is_ca, &path_len))
+ return NULL;
+
+ section = GCR_SECTION (_gcr_certificate_widget_add_section (self, _("Basic Constraints"), NULL,
FALSE));
+ gcr_section_add_child (section, _("Certificate Authority"), create_value_label (is_ca ? _("Yes") :
_("No")));
+
+ number = g_strdup_printf ("%d", path_len);
+ gcr_section_add_child (section, _("Max Path Length"), create_value_label (path_len < 0 ?
_("Unlimited") : number));
+ g_free (number);
+
+ return section;
+}
+
+static GcrSection *
+append_extension_extended_key_usage (GcrCertificateWidget *self,
+ GBytes *data)
+{
+ GcrSection *section;
+ GQuark *oids;
+ GString *text;
+ guint i;
+
+ oids = _gcr_certificate_extension_extended_key_usage (data);
+ if (oids == NULL)
+ return NULL;
+
+ text = g_string_new ("");
+ for (i = 0; oids[i] != 0; i++) {
+ if (i > 0)
+ g_string_append_unichar (text, '\n');
+ g_string_append (text, egg_oid_get_description (oids[i]));
}
+
+ g_free (oids);
+
+ section = GCR_SECTION (_gcr_certificate_widget_add_section (self, _("Extended Key Usage"), NULL,
FALSE));
+ gcr_section_add_child (section, _("Allowed Purposes"), create_value_label (text->str));
+
+ g_string_free (text, TRUE);
+
+ return section;
}
-static void
-gcr_certificate_widget_class_init (GcrCertificateWidgetClass *klass)
+static GcrSection *
+append_extension_subject_key_identifier (GcrCertificateWidget *self,
+ GBytes *data)
{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GcrSection *section;
+ gpointer keyid;
+ gsize n_keyid;
+
+ keyid = _gcr_certificate_extension_subject_key_identifier (data, &n_keyid);
+ if (keyid == NULL)
+ return NULL;
- gcr_certificate_widget_parent_class = g_type_class_peek_parent (klass);
+ section = GCR_SECTION (_gcr_certificate_widget_add_section (self, _("Subject Key Identifier"), NULL,
FALSE));
+ gchar *display = egg_hex_encode_full (keyid, n_keyid, TRUE, " ", 1);
+ g_free (keyid);
+ gcr_section_add_child (section, _("Key Identifier"), create_value_label (display));
+ g_free (display);
- gobject_class->constructor = gcr_certificate_widget_constructor;
- gobject_class->finalize = gcr_certificate_widget_finalize;
- gobject_class->set_property = gcr_certificate_widget_set_property;
- gobject_class->get_property = gcr_certificate_widget_get_property;
+ return section;
+}
+
+static const struct {
+ guint usage;
+ const gchar *description;
+} usage_descriptions[] = {
+ { GCR_KEY_USAGE_DIGITAL_SIGNATURE, N_("Digital signature") },
+ { GCR_KEY_USAGE_NON_REPUDIATION, N_("Non repudiation") },
+ { GCR_KEY_USAGE_KEY_ENCIPHERMENT, N_("Key encipherment") },
+ { GCR_KEY_USAGE_DATA_ENCIPHERMENT, N_("Data encipherment") },
+ { GCR_KEY_USAGE_KEY_AGREEMENT, N_("Key agreement") },
+ { GCR_KEY_USAGE_KEY_CERT_SIGN, N_("Certificate signature") },
+ { GCR_KEY_USAGE_CRL_SIGN, N_("Revocation list signature") },
+ { GCR_KEY_USAGE_ENCIPHER_ONLY, N_("Encipher only") },
+ { GCR_KEY_USAGE_DECIPHER_ONLY, N_("Decipher only") }
+};
- g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
- g_param_spec_object("certificate", "Certificate", "Certificate to display.",
- GCR_TYPE_CERTIFICATE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+static GcrSection *
+append_extension_key_usage (GcrCertificateWidget *self,
+ GBytes *data)
+{
+ GcrSection *section;
+ gulong key_usage;
+ GString *text;
+ guint i;
+
+ if (!_gcr_certificate_extension_key_usage (data, &key_usage))
+ return NULL;
+
+ text = g_string_new ("");
+
+ for (i = 0; i < G_N_ELEMENTS (usage_descriptions); i++) {
+ if (key_usage & usage_descriptions[i].usage) {
+ if (text->len > 0)
+ g_string_append_unichar (text, '\n');
+ g_string_append (text, _(usage_descriptions[i].description));
+ }
+ }
- g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
- g_param_spec_boxed ("attributes", "Attributes", "Attributes which contain the certificate",
- GCK_TYPE_ATTRIBUTES,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ section = GCR_SECTION (_gcr_certificate_widget_add_section (self, _("Key Usage"), NULL, FALSE));
+ gcr_section_add_child (section, _("Usages"), create_value_label (text->str));
+
+ g_string_free (text, TRUE);
+
+ return section;
}
-/* -----------------------------------------------------------------------------
- * PUBLIC
- */
+static GcrSection *
+append_extension_subject_alt_name (GcrCertificateWidget *self,
+ GBytes *data)
+{
+ GcrSection *section;
+ GArray *general_names;
+ GcrGeneralName *general;
+ guint i;
+
+ general_names = _gcr_certificate_extension_subject_alt_name (data);
+ if (general_names == NULL)
+ return FALSE;
+
+ section = GCR_SECTION (_gcr_certificate_widget_add_section (self, _("Subject Alternative Names"),
NULL, FALSE));
+
+ for (i = 0; i < general_names->len; i++) {
+ general = &g_array_index (general_names, GcrGeneralName, i);
+ if (general->display == NULL) {
+ gchar *display = hex_encode_bytes (general->raw);
+ gcr_section_add_child (section, general->description, create_value_label (display));
+ g_free (display);
+ } else
+ gcr_section_add_child (section, general->description, create_value_label
(general->display));
+ }
+
+ _gcr_general_names_free (general_names);
+
+ return section;
+}
+
+static GcrSection *
+append_extension_hex (GcrCertificateWidget *self,
+ GQuark oid,
+ GBytes *value)
+{
+ GcrSection *section;
+ const gchar *text;
+ gchar *display;
+
+ section = GCR_SECTION (_gcr_certificate_widget_add_section (self, _("Extension"), NULL, FALSE));
+
+ /* Extension type */
+ text = egg_oid_get_description (oid);
+ gcr_section_add_child (section, _("Identifier"), create_value_label (text));
+ display = hex_encode_bytes (value);
+ gcr_section_add_child (section, _("Value"), create_value_label (display));
+ g_free (display);
+
+ return section;
+}
+
+static void
+append_extension (GcrCertificateWidget *self,
+ GNode *node)
+{
+ GQuark oid;
+ GBytes *value;
+ gboolean critical;
+ GcrSection *section = NULL;
+
+ /* Dig out the OID */
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (node, "extnID", NULL));
+ g_return_if_fail (oid);
+
+ /* Extension value */
+ value = egg_asn1x_get_string_as_bytes (egg_asn1x_node (node, "extnValue", NULL));
+
+ /* The custom parsers */
+ if (oid == GCR_OID_BASIC_CONSTRAINTS)
+ section = append_extension_basic_constraints (self, value);
+ else if (oid == GCR_OID_EXTENDED_KEY_USAGE)
+ section = append_extension_extended_key_usage (self, value);
+ else if (oid == GCR_OID_SUBJECT_KEY_IDENTIFIER)
+ section = append_extension_subject_key_identifier (self, value);
+ else if (oid == GCR_OID_KEY_USAGE)
+ section = append_extension_key_usage (self, value);
+ else if (oid == GCR_OID_SUBJECT_ALT_NAME)
+ section = append_extension_subject_alt_name (self, value);
+
+ /* Otherwise the default raw display */
+ if (!section) {
+ section = append_extension_hex (self, oid, value);
+ }
+
+ /* Critical */
+ if (section && egg_asn1x_get_boolean (egg_asn1x_node (node, "critical", NULL), &critical)) {
+ gcr_section_add_child (section, _("Critical"), create_value_label (critical ? _("Yes") :
_("No")));
+ }
+
+ g_bytes_unref (value);
+}
/**
* gcr_certificate_widget_new:
@@ -174,9 +502,10 @@ gcr_certificate_widget_class_init (GcrCertificateWidgetClass *klass)
*
* Create a new certificate widget which displays a given certificate.
*
- * Returns: (transfer full): a new certificate widget
+ * Returns: (transfer full): a newly allocated #GcrCertificateWidget, which
+ * should be freed with g_object_unref()
*/
-GcrCertificateWidget *
+GtkWidget *
gcr_certificate_widget_new (GcrCertificate *certificate)
{
return g_object_new (GCR_TYPE_CERTIFICATE_WIDGET, "certificate", certificate, NULL);
@@ -194,7 +523,7 @@ GcrCertificate *
gcr_certificate_widget_get_certificate (GcrCertificateWidget *self)
{
g_return_val_if_fail (GCR_IS_CERTIFICATE_WIDGET (self), NULL);
- return gcr_certificate_renderer_get_certificate (self->pv->renderer);
+ return self->certificate;
}
/**
@@ -207,38 +536,142 @@ gcr_certificate_widget_get_certificate (GcrCertificateWidget *self)
void
gcr_certificate_widget_set_certificate (GcrCertificateWidget *self, GcrCertificate *certificate)
{
+ GtkWidget *section, *label;
+ PangoAttrList *attributes;
+ gchar *display;
+ GIcon *icon;
+ GBytes *bytes, *number;
+ GNode *asn, *subject_public_key;
+ GQuark oid;
+ gconstpointer data;
+ gsize n_data;
+ GDate date;
+ gulong version;
+ guint bits, index;
+
g_return_if_fail (GCR_IS_CERTIFICATE_WIDGET (self));
- gcr_certificate_renderer_set_certificate (self->pv->renderer, certificate);
-}
-/**
- * gcr_certificate_widget_get_attributes:
- * @self: The certificate widget
- *
- * Get the attributes displayed in the widget. The attributes should contain
- * a certificate.
- *
- * Returns: (nullable) (transfer none): the attributes, owned by the widget
- */
-GckAttributes *
-gcr_certificate_widget_get_attributes (GcrCertificateWidget *self)
-{
- g_return_val_if_fail (GCR_IS_CERTIFICATE_WIDGET (self), NULL);
- return gcr_renderer_get_attributes (GCR_RENDERER (self->pv->renderer));
-}
+ g_set_object (&self->certificate, certificate);
-/**
- * gcr_certificate_widget_set_attributes:
- * @self: The certificate widget
- * @attrs: (nullable): the attributes to display
- *
- * Set the attributes displayed in the widget. The attributes should contain
- * a certificate.
- */
-void
-gcr_certificate_widget_set_attributes (GcrCertificateWidget *self,
- GckAttributes *attrs)
-{
- g_return_if_fail (GCR_IS_CERTIFICATE_WIDGET (self));
- gcr_renderer_set_attributes (GCR_RENDERER (self->pv->renderer), attrs);
+ data = gcr_certificate_get_der_data (self->certificate, &n_data);
+ if (!data) {
+ g_set_object (&self->certificate, NULL);
+ }
+
+ icon = gcr_certificate_get_icon (self->certificate);
+ display = calculate_label (self);
+ section = _gcr_certificate_widget_add_section (self, display, icon, TRUE);
+ g_clear_pointer (&display, g_free);
+ g_object_unref (icon);
+
+ bytes = g_bytes_new_static (data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", bytes);
+ g_bytes_unref (bytes);
+
+ display = egg_dn_read_part (egg_asn1x_node (asn, "tbsCertificate", "subject", "rdnSequence", NULL),
"CN");
+ gcr_section_add_child (GCR_SECTION (section), _("Identity"), create_value_label (display));
+ g_clear_pointer (&display, g_free);
+
+ display = egg_dn_read_part (egg_asn1x_node (asn, "tbsCertificate", "issuer", "rdnSequence", NULL),
"CN");
+ gcr_section_add_child (GCR_SECTION (section), _("Verified by"), create_value_label (display));
+ g_clear_pointer (&display, g_free);
+
+ if (egg_asn1x_get_time_as_date (egg_asn1x_node (asn, "tbsCertificate", "validity", "notAfter", NULL),
&date)) {
+ display = g_malloc0 (128);
+ if (!g_date_strftime (display, 128, "%x", &date))
+ g_return_if_reached ();
+ gcr_section_add_child (GCR_SECTION (section), _("Expires"), create_value_label (display));
+ g_clear_pointer (&display, g_free);
+ }
+
+ /* The subject */
+ section = _gcr_certificate_widget_add_section (self, _("Subject Name"), NULL, FALSE);
+ egg_dn_parse (egg_asn1x_node (asn, "tbsCertificate", "subject", "rdnSequence", NULL),
on_parsed_dn_part, section);
+
+ /* The Issuer */
+ section = _gcr_certificate_widget_add_section (self, _("Issuer Name"), NULL, FALSE);
+ egg_dn_parse (egg_asn1x_node (asn, "tbsCertificate", "issuer", "rdnSequence", NULL),
on_parsed_dn_part, section);
+
+ /* The Issued Parameters */
+ section = _gcr_certificate_widget_add_section (self, _("Issued Certificate"), NULL, FALSE);
+
+ if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "tbsCertificate", "version", NULL),
&version)) {
+ g_critical ("Unable to parse certificate version");
+ } else {
+ display = g_strdup_printf ("%lu", version + 1);
+ gcr_section_add_child (GCR_SECTION (section), _("Version"), create_value_label (display));
+ g_clear_pointer (&display, g_free);
+ }
+
+ number = egg_asn1x_get_integer_as_raw (egg_asn1x_node (asn, "tbsCertificate", "serialNumber", NULL));
+ if (!number) {
+ g_critical ("Unable to parse certificate serial number");
+ } else {
+ display = hex_encode_bytes (number);
+ gcr_section_add_child (GCR_SECTION (section), _("Serial Number"), create_value_label
(display));
+ g_clear_pointer (&display, g_free);
+ g_bytes_unref (number);
+ }
+
+ display = g_malloc0 (128);
+ if (egg_asn1x_get_time_as_date (egg_asn1x_node (asn, "tbsCertificate", "validity", "notBefore",
NULL), &date)) {
+ if (!g_date_strftime (display, 128, "%x", &date))
+ g_return_if_reached ();
+ gcr_section_add_child (GCR_SECTION (section), _("Not Valid Before"), create_value_label
(display));
+ }
+ if (egg_asn1x_get_time_as_date (egg_asn1x_node (asn, "tbsCertificate", "validity", "notAfter", NULL),
&date)) {
+ if (!g_date_strftime (display, 128, "%x", &date))
+ g_return_if_reached ();
+ gcr_section_add_child (GCR_SECTION (section), _("Not Valid After"), create_value_label
(display));
+ }
+ g_clear_pointer (&display, g_free);
+
+ /* Fingerprints */
+ section = _gcr_certificate_widget_add_section (self, _("Certificate Fingerprints"), NULL, FALSE);
+ display = g_compute_checksum_for_bytes (G_CHECKSUM_SHA1, bytes);
+ gcr_section_add_child (GCR_SECTION (section), "SHA1", create_value_label (display));
+ g_clear_pointer (&display, g_free);
+ display = g_compute_checksum_for_bytes (G_CHECKSUM_MD5, bytes);
+ gcr_section_add_child (GCR_SECTION (section), "MD5", create_value_label (display));
+ g_clear_pointer (&display, g_free);
+
+ /* Public Key Info */
+ section = _gcr_certificate_widget_add_section (self, _("Public Key Info"), NULL, FALSE);
+ subject_public_key = egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo", NULL);
+ append_subject_public_key (self, GCR_SECTION (section), subject_public_key);
+
+ /* Extensions */
+ for (index = 1; TRUE; ++index) {
+ GNode *extension = egg_asn1x_node (asn, "tbsCertificate", "extensions", index, NULL);
+ if (extension == NULL)
+ break;
+ append_extension (self, extension);
+ }
+
+ /* Signature */
+ section = _gcr_certificate_widget_add_section (self, _("Signature"), NULL, FALSE);
+
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "signatureAlgorithm", "algorithm", NULL));
+ gcr_section_add_child (GCR_SECTION (section), _("Signature Algorithm"), create_value_label
(egg_oid_get_description (oid)));
+
+ bytes = egg_asn1x_get_element_raw (egg_asn1x_node (asn, "signatureAlgorithm", "parameters", NULL));
+ if (bytes) {
+ display = hex_encode_bytes (bytes);
+ gcr_section_add_child (GCR_SECTION (section), _("Signature Parameters"), create_value_label
(display));
+ g_clear_pointer (&display, g_free);
+ g_bytes_unref (bytes);
+ }
+
+ bytes = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "signature", NULL), &bits);
+ display = egg_hex_encode_full (g_bytes_get_data (bytes, NULL), bits / 8, TRUE, " ", 1);
+ g_bytes_unref (bytes);
+ label = create_value_label (display);
+ attributes = pango_attr_list_new ();
+ pango_attr_list_insert (attributes, pango_attr_family_new ("Monospace"));
+ gtk_label_set_attributes (GTK_LABEL (label), attributes);
+ pango_attr_list_unref (attributes);
+ gcr_section_add_child (GCR_SECTION (section), _("Signature"), label);
+ g_clear_pointer (&display, g_free);
+
+ egg_asn1x_destroy (asn);
}
diff --git a/gcr-gtk3/gcr-certificate-widget.h b/gcr-gtk3/gcr-certificate-widget.h
index c6727a6..dab5a82 100644
--- a/gcr-gtk3/gcr-certificate-widget.h
+++ b/gcr-gtk3/gcr-certificate-widget.h
@@ -1,22 +1,12 @@
/*
- * Copyright (C) 2010 Stefan Walter
- *
- * 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 version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * Copyright 2021 Collabora Ltd.
+ * Copyright 2010 Stefan Walter
+ * Copyright Corentin Noël <corentin noel collabora com>
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
#if !defined (__GCR_INSIDE_HEADER__) && !defined (GCR_COMPILATION)
-#error "Only <gcr/gcr.h> or <gcr/gcr-base.h> can be included directly."
+#error "Only <gcr/gcr.h> can be included directly."
#endif
#ifndef __GCR_CERTIFICATE_WIDGET_H__
@@ -24,49 +14,19 @@
#include <glib-object.h>
#include <gtk/gtk.h>
-
-#include "gcr/gcr-certificate.h"
-#include "gcr/gcr-types.h"
+#include <gcr/gcr-certificate.h>
G_BEGIN_DECLS
-#define GCR_TYPE_CERTIFICATE_WIDGET (gcr_certificate_widget_get_type ())
-#define GCR_CERTIFICATE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GCR_TYPE_CERTIFICATE_WIDGET, GcrCertificateWidget))
-#define GCR_CERTIFICATE_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
GCR_TYPE_CERTIFICATE_WIDGET, GcrCertificateWidgetClass))
-#define GCR_IS_CERTIFICATE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GCR_TYPE_CERTIFICATE_WIDGET))
-#define GCR_IS_CERTIFICATE_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GCR_TYPE_CERTIFICATE_WIDGET))
-#define GCR_CERTIFICATE_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GCR_TYPE_CERTIFICATE_WIDGET, GcrCertificateWidgetClass))
-
-typedef struct _GcrCertificateWidget GcrCertificateWidget;
-typedef struct _GcrCertificateWidgetClass GcrCertificateWidgetClass;
-typedef struct _GcrCertificateWidgetPrivate GcrCertificateWidgetPrivate;
-
-struct _GcrCertificateWidget {
- /*< private >*/
- GtkBin parent;
- GcrCertificateWidgetPrivate *pv;
-};
-
-struct _GcrCertificateWidgetClass {
- /*< private >*/
- GtkBinClass parent_class;
-};
-
-GType gcr_certificate_widget_get_type (void);
-
-GcrCertificateWidget* gcr_certificate_widget_new (GcrCertificate *certificate);
-
-GcrCertificate* gcr_certificate_widget_get_certificate (GcrCertificateWidget *self);
-
-void gcr_certificate_widget_set_certificate (GcrCertificateWidget *self,
- GcrCertificate *certificate);
+#define GCR_TYPE_CERTIFICATE_WIDGET gcr_certificate_widget_get_type ()
+G_DECLARE_FINAL_TYPE (GcrCertificateWidget, gcr_certificate_widget, GCR, CERTIFICATE_WIDGET, GtkBox)
-GckAttributes * gcr_certificate_widget_get_attributes (GcrCertificateWidget *self);
+GtkWidget *gcr_certificate_widget_new (GcrCertificate *certificate);
-void gcr_certificate_widget_set_attributes (GcrCertificateWidget *self,
- GckAttributes *attrs);
+GcrCertificate *gcr_certificate_widget_get_certificate (GcrCertificateWidget *self);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC (GcrCertificateWidget, g_object_unref)
+void gcr_certificate_widget_set_certificate (GcrCertificateWidget *self,
+ GcrCertificate *certificate);
G_END_DECLS
diff --git a/gcr-gtk3/gcr-crypto-types.xml b/gcr-gtk3/gcr-crypto-types.xml
index 4b5037b..2f402c9 100644
--- a/gcr-gtk3/gcr-crypto-types.xml
+++ b/gcr-gtk3/gcr-crypto-types.xml
@@ -166,3 +166,4 @@
</magic>
</mime-type>
</mime-info>
+
diff --git a/gcr-gtk3/gcr-gtk3.h b/gcr-gtk3/gcr-gtk3.h
index 67b99d8..53b5850 100644
--- a/gcr-gtk3/gcr-gtk3.h
+++ b/gcr-gtk3/gcr-gtk3.h
@@ -32,25 +32,8 @@
#define __GCR_INSIDE_HEADER__
-#include <gcr-gtk3/gcr-certificate-renderer.h>
#include <gcr-gtk3/gcr-certificate-widget.h>
-#include <gcr-gtk3/gcr-collection-model.h>
-#include <gcr-gtk3/gcr-combo-selector.h>
-#include <gcr-gtk3/gcr-enum-types.h>
-#include <gcr-gtk3/gcr-key-renderer.h>
-#include <gcr-gtk3/gcr-key-widget.h>
-#include <gcr-gtk3/gcr-failure-renderer.h>
-#include <gcr-gtk3/gcr-key-renderer.h>
-#include <gcr-gtk3/gcr-key-widget.h>
-#include <gcr-gtk3/gcr-import-button.h>
-#include <gcr-gtk3/gcr-list-selector.h>
-#include <gcr-gtk3/gcr-prompt-dialog.h>
-#include <gcr-gtk3/gcr-renderer.h>
#include <gcr-gtk3/gcr-secure-entry-buffer.h>
-#include <gcr-gtk3/gcr-tree-selector.h>
-#include <gcr-gtk3/gcr-unlock-options-widget.h>
-#include <gcr-gtk3/gcr-viewer.h>
-#include <gcr-gtk3/gcr-viewer-widget.h>
#undef __GCR_INSIDE_HEADER__
diff --git a/gcr-gtk3/gcr-section.c b/gcr-gtk3/gcr-section.c
new file mode 100644
index 0000000..24c1502
--- /dev/null
+++ b/gcr-gtk3/gcr-section.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2021 Collabora Ltd.
+ * Copyright Corentin Noël <corentin noel collabora com>
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "gcr-section.h"
+
+struct _GcrSection
+{
+ GtkGrid parent_instance;
+
+ GtkWidget *frame;
+ GtkWidget *label;
+ GtkWidget *image;
+ GtkWidget *listbox;
+ GtkSizeGroup *size_group;
+};
+
+G_DEFINE_TYPE (GcrSection, gcr_section, GTK_TYPE_GRID)
+
+enum {
+ PROP_TITLE = 1,
+ PROP_ICON,
+ N_PROPERTIES
+};
+
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
+static void
+gcr_section_dispose (GObject *object)
+{
+ GcrSection *self = (GcrSection *)object;
+
+ g_clear_object (&self->size_group);
+ /* g_clear_pointer (&self->label, gtk_widget_unparent); */
+ /* g_clear_pointer (&self->image, gtk_widget_unparent); */
+ /* g_clear_pointer (&self->frame, gtk_widget_unparent); */
+
+ G_OBJECT_CLASS (gcr_section_parent_class)->dispose (object);
+}
+
+static void
+gcr_section_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GcrSection *self = GCR_SECTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ g_value_set_string (value, gtk_label_get_label (GTK_LABEL (self->label)));
+ break;
+ case PROP_ICON:
+ {
+ GIcon *icon;
+ gtk_image_get_gicon (GTK_IMAGE (self->image), &icon, NULL);
+ g_value_set_object (value, icon);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gcr_section_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GcrSection *self = GCR_SECTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ gtk_label_set_label (GTK_LABEL (self->label), g_value_get_string (value));
+ break;
+ case PROP_ICON:
+ if (!self->image)
+ {
+ self->image = gtk_image_new ();
+ gtk_grid_attach (GTK_GRID (self), self->image, 1, 0, 1, 1);
+ gtk_container_child_set (GTK_CONTAINER (self), self->frame, "width", 2, NULL);
+ }
+
+ gtk_image_set_from_gicon (GTK_IMAGE (self->image), g_value_get_object (value),
GTK_ICON_SIZE_BUTTON);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gcr_section_class_init (GcrSectionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gcr_section_dispose;
+ object_class->get_property = gcr_section_get_property;
+ object_class->set_property = gcr_section_set_property;
+ obj_properties[PROP_TITLE] =
+ g_param_spec_string ("title",
+ "Title",
+ "The title of the section",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_ICON] =
+ g_param_spec_object ("icon",
+ "Icon",
+ "The Icon to use",
+ G_TYPE_ICON,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class,
+ N_PROPERTIES,
+ obj_properties);
+}
+
+static void
+gcr_section_init (GcrSection *self)
+{
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL);
+ self->label = gtk_label_new (NULL);
+ g_object_set (G_OBJECT (self->label),
+ "margin-start", 12,
+ "margin-end", 12,
+ "margin-top", 8,
+ "margin-bottom", 8,
+ "xalign", 0.0,
+ "halign", GTK_ALIGN_START,
+ "hexpand", TRUE,
+ NULL);
+ gtk_style_context_add_class (gtk_widget_get_style_context (self->label), "heading");
+ gtk_style_context_add_class (gtk_widget_get_style_context (self->label), "h4");
+ self->listbox = gtk_list_box_new ();
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (self->listbox), GTK_SELECTION_NONE);
+ self->frame = gtk_frame_new (NULL);
+ g_object_set (G_OBJECT (self->frame),
+ "child", self->listbox,
+ "hexpand", TRUE,
+ NULL);
+ self->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ gtk_container_add (GTK_CONTAINER (self), self->label);
+ gtk_container_add (GTK_CONTAINER (self), self->frame);
+
+ g_object_set (self,
+ "margin-start", 12,
+ "margin-end", 12,
+ "margin-top", 8,
+ "margin-bottom", 8,
+ NULL);
+}
+
+GtkWidget *
+gcr_section_new (const gchar *title)
+{
+ return g_object_new (GCR_TYPE_SECTION, "title", title, NULL);
+}
+
+GtkWidget *
+gcr_section_new_with_icon (const gchar *title,
+ GIcon *icon)
+{
+ return g_object_new (GCR_TYPE_SECTION, "title", title, "icon", icon, NULL);
+}
+
+void
+gcr_section_add_child (GcrSection *self,
+ const gchar *description,
+ GtkWidget *child)
+{
+ GtkWidget *row, *box, *label;
+ g_return_if_fail (GCR_IS_SECTION (self));
+
+ row = gtk_list_box_row_new ();
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ gtk_container_add (GTK_CONTAINER (row), box);
+ label = gtk_label_new (description);
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ g_object_set (label,
+ "margin-start", 12,
+ "margin-end", 12,
+ "margin-top", 8,
+ "margin-bottom", 8,
+ "xalign", 0.0,
+ "halign", GTK_ALIGN_START,
+ NULL);
+ gtk_style_context_add_class (gtk_widget_get_style_context (label), "caption");
+ g_object_set (child,
+ "margin-start", 12,
+ "margin-end", 12,
+ "margin-top", 8,
+ "margin-bottom", 8,
+ "halign", GTK_ALIGN_END,
+ NULL);
+ gtk_size_group_add_widget (self->size_group, label);
+ gtk_container_add (GTK_CONTAINER (box), label);
+ gtk_container_add (GTK_CONTAINER (box), child);
+ gtk_container_add (GTK_CONTAINER (self->listbox), row);
+}
diff --git a/gcr-gtk3/gcr-section.h b/gcr-gtk3/gcr-section.h
new file mode 100644
index 0000000..69950cc
--- /dev/null
+++ b/gcr-gtk3/gcr-section.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 Collabora Ltd.
+ * Copyright Corentin Noël <corentin noel collabora com>
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GCR_SECTION_H__
+#define __GCR_SECTION_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_SECTION gcr_section_get_type()
+G_DECLARE_FINAL_TYPE (GcrSection, gcr_section, GCR, SECTION, GtkGrid)
+
+GtkWidget *gcr_section_new (const gchar *title);
+GtkWidget *gcr_section_new_with_icon (const gchar *title,
+ GIcon *icon);
+
+void gcr_section_add_child (GcrSection *self,
+ const gchar *description,
+ GtkWidget *child);
+
+G_END_DECLS
+
+#endif /* __GCR_SECTION_H__ */
diff --git a/gcr-gtk3/meson.build b/gcr-gtk3/meson.build
index 8382dda..fd997a6 100644
--- a/gcr-gtk3/meson.build
+++ b/gcr-gtk3/meson.build
@@ -3,56 +3,18 @@ subdir('icons')
gcr_gtk3_headers_install_dir = 'gcr-@0@'.format(gcr_major_version) / 'gcr-gtk3'
gcr_gtk3_public_sources = files(
- 'gcr-certificate-renderer.c',
'gcr-certificate-widget.c',
- 'gcr-collection-model.c',
- 'gcr-combo-selector.c',
- 'gcr-failure-renderer.c',
- 'gcr-key-renderer.c',
- 'gcr-key-widget.c',
- 'gcr-import-button.c',
- 'gcr-list-selector.c',
- 'gcr-prompt-dialog.c',
- 'gcr-renderer.c',
'gcr-secure-entry-buffer.c',
- 'gcr-tree-selector.c',
- 'gcr-unlock-options-widget.c',
- 'gcr-viewer.c',
- 'gcr-viewer-widget.c',
)
gcr_gtk3_private_sources = files(
- 'eggimagemenuitem.c',
- 'gcr-certificate-exporter.c',
- 'gcr-certificate-request-renderer.c',
- 'gcr-dialog-util.c',
- 'gcr-display-scrolled.c',
- 'gcr-display-view.c',
- 'gcr-gnupg-renderer.c',
- 'gcr-live-search.c',
- 'gcr-pkcs11-import-dialog.c',
- 'gcr-pkcs11-import-interaction.c',
- 'gcr-unlock-renderer.c',
+ 'gcr-section.c',
)
gcr_gtk3_headers = files(
'gcr-gtk3.h',
- 'gcr-certificate-renderer.h',
'gcr-certificate-widget.h',
- 'gcr-collection-model.h',
- 'gcr-combo-selector.h',
- 'gcr-failure-renderer.h',
- 'gcr-key-renderer.h',
- 'gcr-key-widget.h',
- 'gcr-import-button.h',
- 'gcr-list-selector.h',
- 'gcr-prompt-dialog.h',
- 'gcr-renderer.h',
'gcr-secure-entry-buffer.h',
- 'gcr-tree-selector.h',
- 'gcr-unlock-options-widget.h',
- 'gcr-viewer.h',
- 'gcr-viewer-widget.h',
)
# Generated sources
@@ -160,7 +122,6 @@ if get_option('introspection')
gcr_vapi,
'gtk+-3.0'
],
- metadata_dirs: meson.current_source_dir(),
vapi_dirs: [
build_root / 'gck',
build_root / 'gcr',
@@ -181,15 +142,6 @@ install_data('gcr-crypto-types.xml',
# Manual UI testing programs
gcr_gtk3_manual_tests = [
'frob-certificate',
- 'frob-combo-selector',
- 'frob-gnupg-selector',
- 'frob-import-button',
- 'frob-key',
- 'frob-tree-selector',
- 'frob-prompt',
- 'frob-request',
- 'frob-system-prompt',
- 'frob-unlock-options',
]
gcr_gtk3_test_cflags = [
diff --git a/gcr-gtk4/meson.build b/gcr-gtk4/meson.build
index fd07150..cae5c81 100644
--- a/gcr-gtk4/meson.build
+++ b/gcr-gtk4/meson.build
@@ -128,6 +128,3 @@ if get_option('introspection')
install: true,
)
endif
-
-# gcr-viewer-gtk4
-subdir('viewer')
diff --git a/tools/gtk3/meson.build b/tools/gtk3/meson.build
new file mode 100644
index 0000000..e2da60f
--- /dev/null
+++ b/tools/gtk3/meson.build
@@ -0,0 +1,7 @@
+gcr_viewer_gtk3 = executable('gcr-viewer-gtk3',
+ 'viewer.c',
+ dependencies: [ gcr_gtk3_dep, gcr_gtk3_deps ],
+ c_args: gcr_gtk3_cflags,
+ include_directories: config_h_dir,
+ install: true,
+)
diff --git a/tools/gtk3/viewer.c b/tools/gtk3/viewer.c
new file mode 100644
index 0000000..e8e6e7c
--- /dev/null
+++ b/tools/gtk3/viewer.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2011,2021 Collabora Ltd.
+ * Copyright Corentin Noël <corentin noel collabora com>
+ * Copyright Stef Walter <stefw collabora co uk>
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gcr-gtk3/gcr-gtk3.h>
+
+#include "config.h"
+
+static gchar **remaining_args = NULL;
+
+static gboolean
+print_version_and_exit (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ g_print("%s -- %s\n", _("GCR Certificate Viewer"), VERSION);
+ exit (0);
+ return TRUE;
+}
+
+static const GOptionEntry options[] = {
+ { "version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+ print_version_and_exit, N_("Show the application's version"), NULL},
+ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY,
+ &remaining_args, NULL, N_("[file...]") },
+ { NULL }
+};
+
+static void
+on_parser_parsed (GcrParser *parser,
+ gpointer user_data)
+{
+ GcrCertificate **cert = user_data;
+ GckAttributes *attributes;
+ const GckAttribute *attr;
+
+ attributes = gcr_parser_get_parsed_attributes (parser);
+ attr = gck_attributes_find (attributes, CKA_VALUE);
+ *cert = gcr_simple_certificate_new (attr->value, attr->length);
+}
+
+GcrCertificate *
+simple_certificate_new_from_file (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GcrCertificate *cert = NULL;
+ GcrParser *parser;
+ GBytes *bytes;
+
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_return_val_if_fail (!error || !*error, NULL);
+
+
+ bytes = g_file_load_bytes (file, cancellable, NULL, error);
+ if (!bytes) {
+ return NULL;
+ }
+
+ parser = gcr_parser_new ();
+ g_signal_connect (parser, "parsed", G_CALLBACK (on_parser_parsed), &cert);
+ if (!gcr_parser_parse_bytes (parser, bytes, error)) {
+ g_bytes_unref (bytes);
+ g_object_unref (parser);
+ g_object_unref (cert);
+ return NULL;
+ }
+
+ g_bytes_unref (bytes);
+ g_object_unref (parser);
+ return cert;
+}
+
+
+static void
+activate (GtkApplication* app,
+ gpointer user_data)
+{
+ GtkWidget *window;
+ GtkWidget *box;
+ GtkWidget *scrolled;
+ GCancellable *cancellable = NULL;
+
+ window = gtk_application_window_new (app);
+ gtk_window_set_title (GTK_WINDOW (window), "Window");
+ gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ g_object_set (G_OBJECT (scrolled),
+ "child", box,
+ "hscrollbar-policy", GTK_POLICY_NEVER,
+ NULL);
+
+ if (remaining_args) {
+ for (int i = 0; remaining_args[i] != NULL; ++i) {
+ GFile *file;
+ GError *error = NULL;
+ GcrCertificate *certificate;
+ GtkWidget *widget;
+
+ file = g_file_new_for_commandline_arg (remaining_args[i]);
+ certificate = simple_certificate_new_from_file (file, cancellable, &error);
+ g_object_unref (file);
+ widget = gcr_certificate_widget_new (GCR_CERTIFICATE (certificate));
+ g_object_unref (certificate);
+ gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
+ gtk_container_add (GTK_CONTAINER (box), widget);
+ }
+
+ g_clear_pointer (&remaining_args, g_strfreev);
+ remaining_args = NULL;
+ }
+
+ gtk_container_add (GTK_CONTAINER (window), scrolled);
+ gtk_widget_show_all (window);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ GtkApplication *app;
+ int status;
+
+ app = gtk_application_new ("org.gnome.GcrViewerGtk4", G_APPLICATION_FLAGS_NONE);
+ g_application_add_main_option_entries (G_APPLICATION (app), options);
+ g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
+ status = g_application_run (G_APPLICATION (app), argc, argv);
+ g_object_unref (app);
+
+ return status;
+}
diff --git a/gcr-gtk4/viewer/meson.build b/tools/gtk4/meson.build
similarity index 75%
rename from gcr-gtk4/viewer/meson.build
rename to tools/gtk4/meson.build
index c33fae9..f15e00b 100644
--- a/gcr-gtk4/viewer/meson.build
+++ b/tools/gtk4/meson.build
@@ -1,4 +1,4 @@
-gcr_viewer = executable('gcr-viewer-gtk4',
+gcr_viewer_gtk4 = executable('gcr-viewer-gtk4',
'viewer.c',
dependencies: [ gcr_gtk4_dep, gcr_gtk4_deps ],
c_args: gcr_gtk4_cflags,
diff --git a/gcr-gtk4/viewer/viewer.c b/tools/gtk4/viewer.c
similarity index 98%
rename from gcr-gtk4/viewer/viewer.c
rename to tools/gtk4/viewer.c
index 986cecd..9440b28 100644
--- a/gcr-gtk4/viewer/viewer.c
+++ b/tools/gtk4/viewer.c
@@ -20,7 +20,7 @@ print_version_and_exit (const gchar *option_name,
gpointer data,
GError **error)
{
- g_print("%s -- %s\n", _("GCR Certificate and Key Viewer"), VERSION);
+ g_print("%s -- %s\n", _("GCR Certificate Viewer"), VERSION);
exit (0);
return TRUE;
}
diff --git a/tools/meson.build b/tools/meson.build
index a8d2309..4db190e 100644
--- a/tools/meson.build
+++ b/tools/meson.build
@@ -1,65 +1,7 @@
-# gcr-viewer
-gcr_viewer = executable('gcr-viewer',
- 'gcr-viewer-tool.c',
- 'gcr-viewer-window.c',
- dependencies: [ gcr_gtk3_dep, gcr_gtk3_deps ],
- c_args: gcr_gtk3_cflags,
- include_directories: config_h_dir,
- install: true,
-)
+if get_option('gtk3')
+ subdir('gtk3')
+endif
-i18n.merge_file(
- input: configure_file(
- input: 'gcr-viewer.desktop.in.in',
- output: '@BASENAME@',
- configuration: { 'bindir': gcr_prefix / get_option('bindir') },
- ),
- output: '@BASENAME@',
- type: 'desktop',
- po_dir: podir,
- install: true,
- install_dir: get_option('datadir') / 'applications',
-)
-
-# gcr-prompter
-gcr_prompter = executable('gcr-prompter',
- 'gcr-prompter-tool.c',
- dependencies: [ gcr_gtk3_dep, gcr_gtk3_deps ],
- c_args: gcr_gtk3_cflags,
- include_directories: config_h_dir,
- install: true,
- install_dir: get_option('libexecdir'),
-)
-
-i18n.merge_file(
- input: configure_file(
- input: 'gcr-prompter.desktop.in.in',
- output: '@BASENAME@',
- configuration: { 'libexecdir': gcr_prefix / get_option('libexecdir') },
- ),
- output: '@BASENAME@',
- type: 'desktop',
- po_dir: podir,
- install: true,
- install_dir: get_option('datadir') / 'applications',
-)
-
-
-# Manual UI testing programs
-gcr_tools_manual_tests = [
- 'frob-unlock',
-]
-
-gcr_tools_test_cflags = [
- '-DSRCDIR="@0@"'.format(source_root),
-]
-
-foreach _test : gcr_tools_manual_tests
- test_bin = executable('test-'+_test,
- '@0@.c'.format(_test),
- 'gcr-viewer-window.c',
- dependencies: [ gcr_gtk3_deps, gcr_gtk3_dep ],
- c_args: [ gcr_gtk3_cflags, gcr_tools_test_cflags ],
- include_directories: config_h_dir,
- )
-endforeach
+if get_option('gtk4')
+ subdir('gtk4')
+endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]