Blame ui/gcr-key-renderer.c

Packit b00eeb
/*
Packit b00eeb
 * Copyright (C) 2010 Stefan Walter
Packit b00eeb
 *
Packit b00eeb
 * This program is free software; you can redistribute it and/or modify
Packit b00eeb
 * it under the terms of the GNU Lesser General Public License as
Packit b00eeb
 * published by the Free Software Foundation; either version 2.1 of
Packit b00eeb
 * the License, or (at your option) any later version.
Packit b00eeb
 *
Packit b00eeb
 * This program is distributed in the hope that it will be useful, but
Packit b00eeb
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit b00eeb
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit b00eeb
 * Lesser General Public License for more details.
Packit b00eeb
 *
Packit b00eeb
 * You should have received a copy of the GNU Lesser General Public
Packit b00eeb
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
#include "config.h"
Packit b00eeb
Packit b00eeb
#include "gcr/gcr-fingerprint.h"
Packit b00eeb
#include "gcr/gcr-icons.h"
Packit b00eeb
#include "gcr/gcr-subject-public-key.h"
Packit b00eeb
Packit b00eeb
#include "gcr-key-renderer.h"
Packit b00eeb
#include "gcr-display-view.h"
Packit b00eeb
#include "gcr-renderer.h"
Packit b00eeb
#include "gcr-viewer.h"
Packit b00eeb
Packit b00eeb
#include "gck/gck.h"
Packit b00eeb
Packit b00eeb
#include "egg/egg-asn1x.h"
Packit b00eeb
Packit b00eeb
#include <gdk/gdk.h>
Packit b00eeb
#include <glib/gi18n-lib.h>
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * GcrKeyRenderer:
Packit b00eeb
 *
Packit b00eeb
 * An implementation of #GcrRenderer which renders keys.
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * GcrKeyRendererClass:
Packit b00eeb
 * @parent_class: The parent class.
Packit b00eeb
 *
Packit b00eeb
 * The class for #GcrKeyRenderer.
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
enum {
Packit b00eeb
	PROP_0,
Packit b00eeb
	PROP_LABEL,
Packit b00eeb
	PROP_ATTRIBUTES,
Packit b00eeb
	PROP_OBJECT
Packit b00eeb
};
Packit b00eeb
Packit b00eeb
struct _GcrKeyRendererPrivate {
Packit b00eeb
	guint key_size;
Packit b00eeb
	gchar *label;
Packit b00eeb
	GckAttributes *attributes;
Packit b00eeb
	GckObject *object;
Packit b00eeb
	GIcon *icon;
Packit b00eeb
	gulong notify_sig;
Packit b00eeb
	GBytes *spk;
Packit b00eeb
};
Packit b00eeb
Packit b00eeb
static void gcr_key_renderer_renderer_iface (GcrRendererIface *iface);
Packit b00eeb
Packit b00eeb
G_DEFINE_TYPE_WITH_CODE (GcrKeyRenderer, gcr_key_renderer, G_TYPE_OBJECT,
Packit b00eeb
                         G_IMPLEMENT_INTERFACE (GCR_TYPE_RENDERER, gcr_key_renderer_renderer_iface));
Packit b00eeb
Packit b00eeb
/* -----------------------------------------------------------------------------
Packit b00eeb
 * INTERNAL
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
static gchar*
Packit b00eeb
calculate_label (GcrKeyRenderer *self)
Packit b00eeb
{
Packit b00eeb
	gchar *label;
Packit b00eeb
Packit b00eeb
	if (self->pv->label)
Packit b00eeb
		return g_strdup (self->pv->label);
Packit b00eeb
Packit b00eeb
	if (self->pv->attributes) {
Packit b00eeb
		if (gck_attributes_find_string (self->pv->attributes, CKA_LABEL, &label))
Packit b00eeb
			return label;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	return g_strdup (_("Key"));
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static GckAttributes *
Packit b00eeb
calculate_attrs (GcrKeyRenderer *self)
Packit b00eeb
{
Packit b00eeb
	if (self->pv->attributes)
Packit b00eeb
		return gck_attributes_ref (self->pv->attributes);
Packit b00eeb
Packit b00eeb
	if (GCK_IS_OBJECT_CACHE (self->pv->object))
Packit b00eeb
		return gck_object_cache_get_attributes (GCK_OBJECT_CACHE (self->pv->object));
Packit b00eeb
Packit b00eeb
	return NULL;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static guchar *
Packit b00eeb
calculate_fingerprint (GcrKeyRenderer *self,
Packit b00eeb
                       GckAttributes *attrs,
Packit b00eeb
                       GChecksumType algorithm,
Packit b00eeb
                       gsize *n_fingerprint)
Packit b00eeb
{
Packit b00eeb
	if (self->pv->spk)
Packit b00eeb
		return gcr_fingerprint_from_subject_public_key_info (g_bytes_get_data (self->pv->spk, NULL),
Packit b00eeb
		                                                     g_bytes_get_size (self->pv->spk),
Packit b00eeb
		                                                     algorithm, n_fingerprint);
Packit b00eeb
Packit b00eeb
	return gcr_fingerprint_from_attributes (attrs, algorithm, n_fingerprint);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
on_subject_public_key (GObject *source,
Packit b00eeb
                       GAsyncResult *result,
Packit b00eeb
                       gpointer user_data)
Packit b00eeb
{
Packit b00eeb
	GcrKeyRenderer *self = GCR_KEY_RENDERER (user_data);
Packit b00eeb
	GError *error = NULL;
Packit b00eeb
	GNode *node;
Packit b00eeb
Packit b00eeb
	node = _gcr_subject_public_key_load_finish (result, &error);
Packit b00eeb
	if (error != NULL) {
Packit b00eeb
		g_message ("couldn't load key information: %s", error->message);
Packit b00eeb
		g_clear_error (&error);
Packit b00eeb
Packit b00eeb
	} else {
Packit b00eeb
		if (self->pv->spk)
Packit b00eeb
			g_bytes_unref (self->pv->spk);
Packit b00eeb
		self->pv->spk = NULL;
Packit b00eeb
Packit b00eeb
		self->pv->spk = egg_asn1x_encode (node, NULL);
Packit b00eeb
		if (self->pv->spk == NULL)
Packit b00eeb
			g_warning ("invalid subjectPublicKey loaded: %s",
Packit b00eeb
			           egg_asn1x_message (node));
Packit b00eeb
		egg_asn1x_destroy (node);
Packit b00eeb
Packit b00eeb
		gcr_renderer_emit_data_changed (GCR_RENDERER (self));
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	g_object_unref (self);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
update_subject_public_key (GcrKeyRenderer *self)
Packit b00eeb
{
Packit b00eeb
	if (self->pv->spk)
Packit b00eeb
		g_bytes_unref (self->pv->spk);
Packit b00eeb
	self->pv->spk = NULL;
Packit b00eeb
Packit b00eeb
	if (!self->pv->object)
Packit b00eeb
		return;
Packit b00eeb
Packit b00eeb
	_gcr_subject_public_key_load_async (self->pv->object, NULL,
Packit b00eeb
	                                    on_subject_public_key,
Packit b00eeb
	                                    g_object_ref (self));
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
on_object_cache_attributes (GObject *obj,
Packit b00eeb
                            GParamSpec *spec,
Packit b00eeb
                            gpointer user_data)
Packit b00eeb
{
Packit b00eeb
	GcrKeyRenderer *self = GCR_KEY_RENDERER (user_data);
Packit b00eeb
	update_subject_public_key (self);
Packit b00eeb
	gcr_renderer_emit_data_changed (GCR_RENDERER (self));
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gcr_key_renderer_init (GcrKeyRenderer *self)
Packit b00eeb
{
Packit b00eeb
	self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_KEY_RENDERER, GcrKeyRendererPrivate));
Packit b00eeb
	self->pv->icon = g_themed_icon_new (GCR_ICON_KEY);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gcr_key_renderer_dispose (GObject *obj)
Packit b00eeb
{
Packit b00eeb
	GcrKeyRenderer *self = GCR_KEY_RENDERER (obj);
Packit b00eeb
Packit b00eeb
	if (self->pv->spk)
Packit b00eeb
		g_bytes_unref (self->pv->spk);
Packit b00eeb
	self->pv->spk = NULL;
Packit b00eeb
Packit b00eeb
	if (self->pv->object && self->pv->notify_sig) {
Packit b00eeb
		g_signal_handler_disconnect (self->pv->object, self->pv->notify_sig);
Packit b00eeb
		self->pv->notify_sig = 0;
Packit b00eeb
	}
Packit b00eeb
	g_clear_object (&self->pv->object);
Packit b00eeb
Packit b00eeb
	G_OBJECT_CLASS (gcr_key_renderer_parent_class)->dispose (obj);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gcr_key_renderer_finalize (GObject *obj)
Packit b00eeb
{
Packit b00eeb
	GcrKeyRenderer *self = GCR_KEY_RENDERER (obj);
Packit b00eeb
Packit b00eeb
	if (self->pv->attributes)
Packit b00eeb
		gck_attributes_unref (self->pv->attributes);
Packit b00eeb
	self->pv->attributes = NULL;
Packit b00eeb
Packit b00eeb
	g_free (self->pv->label);
Packit b00eeb
	self->pv->label = NULL;
Packit b00eeb
Packit b00eeb
	if (self->pv->icon)
Packit b00eeb
		g_object_unref (self->pv->icon);
Packit b00eeb
	self->pv->icon = NULL;
Packit b00eeb
Packit b00eeb
	G_OBJECT_CLASS (gcr_key_renderer_parent_class)->finalize (obj);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gcr_key_renderer_set_property (GObject *obj, guint prop_id, const GValue *value,
Packit b00eeb
                               GParamSpec *pspec)
Packit b00eeb
{
Packit b00eeb
	GcrKeyRenderer *self = GCR_KEY_RENDERER (obj);
Packit b00eeb
Packit b00eeb
	switch (prop_id) {
Packit b00eeb
	case PROP_LABEL:
Packit b00eeb
		g_free (self->pv->label);
Packit b00eeb
		self->pv->label = g_value_dup_string (value);
Packit b00eeb
		g_object_notify (obj, "label");
Packit b00eeb
		gcr_renderer_emit_data_changed (GCR_RENDERER (self));
Packit b00eeb
		break;
Packit b00eeb
	case PROP_ATTRIBUTES:
Packit b00eeb
		gck_attributes_unref (self->pv->attributes);
Packit b00eeb
		self->pv->attributes = g_value_dup_boxed (value);
Packit b00eeb
		gcr_renderer_emit_data_changed (GCR_RENDERER (self));
Packit b00eeb
		break;
Packit b00eeb
	case PROP_OBJECT:
Packit b00eeb
		g_clear_object (&self->pv->object);
Packit b00eeb
		self->pv->object = g_value_dup_object (value);
Packit b00eeb
		if (self->pv->object) {
Packit b00eeb
			gck_attributes_unref (self->pv->attributes);
Packit b00eeb
			self->pv->attributes = NULL;
Packit b00eeb
		}
Packit b00eeb
		if (GCK_IS_OBJECT_CACHE (self->pv->object)) {
Packit b00eeb
			self->pv->notify_sig = g_signal_connect (self->pv->object,
Packit b00eeb
			                                         "notify::attributes",
Packit b00eeb
			                                         G_CALLBACK (on_object_cache_attributes),
Packit b00eeb
			                                         self);
Packit b00eeb
			on_object_cache_attributes (G_OBJECT (self->pv->object), NULL, self);
Packit b00eeb
		}
Packit b00eeb
		g_object_notify (obj, "attributes");
Packit b00eeb
		g_object_notify (obj, "object");
Packit b00eeb
		break;
Packit b00eeb
	default:
Packit b00eeb
		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
Packit b00eeb
		break;
Packit b00eeb
	}
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gcr_key_renderer_get_property (GObject *obj, guint prop_id, GValue *value,
Packit b00eeb
                               GParamSpec *pspec)
Packit b00eeb
{
Packit b00eeb
	GcrKeyRenderer *self = GCR_KEY_RENDERER (obj);
Packit b00eeb
Packit b00eeb
	switch (prop_id) {
Packit b00eeb
	case PROP_LABEL:
Packit b00eeb
		g_value_take_string (value, calculate_label (self));
Packit b00eeb
		break;
Packit b00eeb
	case PROP_ATTRIBUTES:
Packit b00eeb
		g_value_take_boxed (value, calculate_attrs (self));
Packit b00eeb
		break;
Packit b00eeb
	case PROP_OBJECT:
Packit b00eeb
		g_value_set_object (value, self->pv->object);
Packit b00eeb
		break;
Packit b00eeb
	default:
Packit b00eeb
		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
Packit b00eeb
		break;
Packit b00eeb
	}
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gcr_key_renderer_class_init (GcrKeyRendererClass *klass)
Packit b00eeb
{
Packit b00eeb
	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit b00eeb
	GckBuilder builder = GCK_BUILDER_INIT;
Packit b00eeb
Packit b00eeb
	gcr_key_renderer_parent_class = g_type_class_peek_parent (klass);
Packit b00eeb
	g_type_class_add_private (klass, sizeof (GcrKeyRendererPrivate));
Packit b00eeb
Packit b00eeb
	gobject_class->dispose = gcr_key_renderer_dispose;
Packit b00eeb
	gobject_class->finalize = gcr_key_renderer_finalize;
Packit b00eeb
	gobject_class->set_property = gcr_key_renderer_set_property;
Packit b00eeb
	gobject_class->get_property = gcr_key_renderer_get_property;
Packit b00eeb
Packit b00eeb
	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
Packit b00eeb
	g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
Packit b00eeb
Packit b00eeb
	g_object_class_install_property (gobject_class, PROP_OBJECT,
Packit b00eeb
	            g_param_spec_object ("object", "Object", "Key Object", GCK_TYPE_OBJECT,
Packit b00eeb
	                                 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit b00eeb
Packit b00eeb
	/* Register this as a view which can be loaded */
Packit b00eeb
	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PRIVATE_KEY);
Packit b00eeb
	gcr_renderer_register (GCR_TYPE_KEY_RENDERER, gck_builder_end (&builder));
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
Packit b00eeb
{
Packit b00eeb
	GcrKeyRenderer *self;
Packit b00eeb
	GcrDisplayView *view;
Packit b00eeb
	const gchar *text = "";
Packit b00eeb
	GckAttributes *attrs;
Packit b00eeb
	gpointer fingerprint;
Packit b00eeb
	gsize n_fingerprint;
Packit b00eeb
	gchar *display;
Packit b00eeb
	gulong klass;
Packit b00eeb
	gulong key_type;
Packit b00eeb
	guint size;
Packit b00eeb
Packit b00eeb
	self = GCR_KEY_RENDERER (renderer);
Packit b00eeb
Packit b00eeb
	if (GCR_IS_DISPLAY_VIEW (viewer)) {
Packit b00eeb
		view = GCR_DISPLAY_VIEW (viewer);
Packit b00eeb
Packit b00eeb
	} else {
Packit b00eeb
		g_warning ("GcrKeyRenderer only works with internal specific "
Packit b00eeb
		           "GcrViewer returned by gcr_viewer_new().");
Packit b00eeb
		return;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	_gcr_display_view_begin (view, renderer);
Packit b00eeb
Packit b00eeb
	attrs = calculate_attrs (self);
Packit b00eeb
	if (attrs == NULL) {
Packit b00eeb
		_gcr_display_view_end (view, renderer);
Packit b00eeb
		return;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	if (!gck_attributes_find_ulong (attrs, CKA_CLASS, &klass) ||
Packit b00eeb
	    !gck_attributes_find_ulong (attrs, CKA_KEY_TYPE, &key_type)) {
Packit b00eeb
		g_warning ("private key does not have the CKA_CLASS and CKA_KEY_TYPE attributes");
Packit b00eeb
		_gcr_display_view_end (view, renderer);
Packit b00eeb
		gck_attributes_unref (attrs);
Packit b00eeb
		return;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	_gcr_display_view_set_icon (view, renderer, self->pv->icon);
Packit b00eeb
Packit b00eeb
	display = calculate_label (self);
Packit b00eeb
	_gcr_display_view_append_title (view, renderer, display);
Packit b00eeb
	g_free (display);
Packit b00eeb
Packit b00eeb
	if (klass == CKO_PRIVATE_KEY) {
Packit b00eeb
		if (key_type == CKK_RSA)
Packit b00eeb
			text = _("Private RSA Key");
Packit b00eeb
		else if (key_type == CKK_DSA)
Packit b00eeb
			text = _("Private DSA Key");
Packit b00eeb
		else if (key_type == CKK_EC)
Packit b00eeb
			text = _("Private Elliptic Curve Key");
Packit b00eeb
		else
Packit b00eeb
			text = _("Private Key");
Packit b00eeb
	} else if (klass == CKO_PUBLIC_KEY) {
Packit b00eeb
		if (key_type == CKK_RSA)
Packit b00eeb
			text = _("Public DSA Key");
Packit b00eeb
		else if (key_type == CKK_DSA)
Packit b00eeb
			text = _("Public DSA Key");
Packit b00eeb
		else if (key_type == CKK_EC)
Packit b00eeb
			text = _("Public Elliptic Curve Key");
Packit b00eeb
		else
Packit b00eeb
			text = _("Public Key");
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	_gcr_display_view_append_content (view, renderer, text, NULL);
Packit b00eeb
Packit b00eeb
	size = _gcr_subject_public_key_attributes_size (attrs);
Packit b00eeb
	if (size > 0) {
Packit b00eeb
		display = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%u bit", "%u bits", size), size);
Packit b00eeb
		_gcr_display_view_append_content (view, renderer, _("Strength"), display);
Packit b00eeb
		g_free (display);
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	_gcr_display_view_start_details (view, renderer);
Packit b00eeb
Packit b00eeb
	if (key_type == CKK_RSA)
Packit b00eeb
		text = _("RSA");
Packit b00eeb
	else if (key_type == CKK_DSA)
Packit b00eeb
		text = _("DSA");
Packit b00eeb
	else if (key_type == CKK_EC)
Packit b00eeb
		text = _("Elliptic Curve");
Packit b00eeb
	else
Packit b00eeb
		text = _("Unknown");
Packit b00eeb
	_gcr_display_view_append_value (view, renderer, _("Algorithm"), text, FALSE);
Packit b00eeb
Packit b00eeb
	if (size == 0)
Packit b00eeb
		display = g_strdup (_("Unknown"));
Packit b00eeb
	else
Packit b00eeb
		display = g_strdup_printf ("%u", size);
Packit b00eeb
	_gcr_display_view_append_value (view, renderer, _("Size"), display, FALSE);
Packit b00eeb
	g_free (display);
Packit b00eeb
Packit b00eeb
	/* Fingerprints */
Packit b00eeb
	_gcr_display_view_append_heading (view, renderer, _("Fingerprints"));
Packit b00eeb
Packit b00eeb
	fingerprint = calculate_fingerprint (self, attrs, G_CHECKSUM_SHA1, &n_fingerprint);
Packit b00eeb
	if (fingerprint) {
Packit b00eeb
		_gcr_display_view_append_hex (view, renderer, _("SHA1"), fingerprint, n_fingerprint);
Packit b00eeb
		g_free (fingerprint);
Packit b00eeb
	}
Packit b00eeb
	fingerprint = calculate_fingerprint (self, attrs, G_CHECKSUM_SHA256, &n_fingerprint);
Packit b00eeb
	if (fingerprint) {
Packit b00eeb
		_gcr_display_view_append_hex (view, renderer, _("SHA256"), fingerprint, n_fingerprint);
Packit b00eeb
		g_free (fingerprint);
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	_gcr_display_view_end (view, renderer);
Packit b00eeb
	gck_attributes_unref (attrs);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gcr_key_renderer_renderer_iface (GcrRendererIface *iface)
Packit b00eeb
{
Packit b00eeb
	iface->render_view = gcr_key_renderer_real_render;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/* -----------------------------------------------------------------------------
Packit b00eeb
 * PUBLIC
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gcr_key_renderer_new:
Packit b00eeb
 * @label: (allow-none): label describing the key
Packit b00eeb
 * @attrs: (allow-none): key to display, or %NULL
Packit b00eeb
 *
Packit b00eeb
 * Create a new key renderer which renders a given key in the attributes.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full): a newly allocated #GcrKeyRenderer, which should be
Packit b00eeb
 *          freed with g_object_unref()
Packit b00eeb
 */
Packit b00eeb
GcrKeyRenderer*
Packit b00eeb
gcr_key_renderer_new (const gchar *label, GckAttributes *attrs)
Packit b00eeb
{
Packit b00eeb
	return g_object_new (GCR_TYPE_KEY_RENDERER, "label", label, "attributes", attrs, NULL);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gcr_key_renderer_set_attributes:
Packit b00eeb
 * @self: The key renderer
Packit b00eeb
 * @attrs: (allow-none): the attributes to display
Packit b00eeb
 *
Packit b00eeb
 * Get the attributes displayed in the renderer. The attributes should represent
Packit b00eeb
 * either an RSA, DSA, or EC key in PKCS\#11 style.
Packit b00eeb
 */
Packit b00eeb
void
Packit b00eeb
gcr_key_renderer_set_attributes (GcrKeyRenderer *self, GckAttributes *attrs)
Packit b00eeb
{
Packit b00eeb
	g_return_if_fail (GCR_IS_KEY_RENDERER (self));
Packit b00eeb
Packit b00eeb
	if (self->pv->attributes)
Packit b00eeb
		gck_attributes_unref (self->pv->attributes);
Packit b00eeb
	self->pv->attributes = attrs;
Packit b00eeb
	if (self->pv->attributes)
Packit b00eeb
		gck_attributes_ref (self->pv->attributes);
Packit b00eeb
Packit b00eeb
	g_object_notify (G_OBJECT (self), "attributes");
Packit b00eeb
	gcr_renderer_emit_data_changed (GCR_RENDERER (self));
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gcr_key_renderer_get_attributes:
Packit b00eeb
 * @self: The key renderer
Packit b00eeb
 *
Packit b00eeb
 * Get the attributes displayed in the renderer.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer none) (allow-none): the attributes, owned by the renderer
Packit b00eeb
 */
Packit b00eeb
GckAttributes*
Packit b00eeb
gcr_key_renderer_get_attributes (GcrKeyRenderer *self)
Packit b00eeb
{
Packit b00eeb
	g_return_val_if_fail (GCR_IS_KEY_RENDERER (self), NULL);
Packit b00eeb
	return self->pv->attributes;
Packit b00eeb
}