[gnome-keyring] gcr: Add Renderer for Gnupg keys
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring] gcr: Add Renderer for Gnupg keys
- Date: Tue, 27 Sep 2011 15:15:12 +0000 (UTC)
commit 95296d139236df1cb3d916b89f30a1bc31572c1f
Author: Stef Walter <stefw collabora co uk>
Date: Tue Sep 20 11:56:20 2011 +0200
gcr: Add Renderer for Gnupg keys
* Uses the colon style GcrRecord data to render gnupg key.
docs/reference/gcr/gcr-sections.txt | 10 +
gcr/Makefile.am | 6 +
gcr/gcr-gnupg-collection.c | 5 +-
gcr/gcr-gnupg-key.c | 127 +-----
gcr/gcr-gnupg-key.h | 4 -
gcr/gcr-gnupg-records.c | 244 ++++++++++
gcr/gcr-gnupg-records.h | 52 +++
gcr/gcr-gnupg-renderer.c | 852 +++++++++++++++++++++++++++++++++++
gcr/gcr-gnupg-renderer.h | 77 ++++
gcr/gcr-openpgp.c | 55 ++-
gcr/gcr-openpgp.h | 8 +
gcr/gcr-parser.c | 20 +-
gcr/gcr-record.c | 150 ++++---
gcr/gcr-record.h | 33 +-
gcr/gcr-renderer.c | 2 +
gcr/gcr-types.h | 10 +
gcr/tests/test-gnupg-collection.c | 2 +-
gcr/tests/test-gnupg-key.c | 3 +-
gcr/tests/test-openpgp.c | 16 +
gcr/tests/test-record.c | 4 +-
po/POTFILES.in | 1 +
21 files changed, 1439 insertions(+), 242 deletions(-)
---
diff --git a/docs/reference/gcr/gcr-sections.txt b/docs/reference/gcr/gcr-sections.txt
index a881547..08e7dd0 100644
--- a/docs/reference/gcr/gcr-sections.txt
+++ b/docs/reference/gcr/gcr-sections.txt
@@ -611,4 +611,14 @@ GcrCallbackOutputFunc
GcrCallbackOutputStream
GcrCallbackOutputStreamClass
GcrOpenpgpParseFlags
+GCR_GNUPG_RENDERER
+GCR_GNUPG_RENDERER_CLASS
+GCR_GNUPG_RENDERER_GET_CLASS
+GCR_IS_GNUPG_RENDERER
+GCR_IS_GNUPG_RENDERER_CLASS
+GCR_TYPE_GNUPG_RENDERER
+GcrGnupgRenderer
+GcrGnupgRendererClass
+GcrGnupgRendererPrivate
+GcrOpenpgpAlgo
</SECTION>
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index 48c6243..f4f86e0 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -99,6 +99,7 @@ libgcr_base_ GCR_MAJOR@_la_SOURCES = \
gcr-gnupg-collection.c gcr-gnupg-collection.h \
gcr-gnupg-key.c gcr-gnupg-key.h \
gcr-gnupg-process.c gcr-gnupg-process.h \
+ gcr-gnupg-records.c gcr-gnupg-records.h \
gcr-gnupg-util.c gcr-gnupg-util.h \
gcr-library.c gcr-library.h \
gcr-internal.h \
@@ -126,10 +127,13 @@ libgcr_ GCR_MAJOR@_la_SOURCES = \
gcr-certificate-widget.c gcr-certificate-widget.h \
gcr-collection-model.c gcr-collection-model.h \
gcr-combo-selector.c gcr-combo-selector.h \
+ gcr-debug.c gcr-debug.h \
gcr-display-scrolled.c gcr-display-scrolled.h \
gcr-display-view.c gcr-display-view.h \
gcr-failure-renderer.c gcr-failure-renderer.h \
gcr-fingerprint.c gcr-fingerprint.h \
+ gcr-gnupg-renderer.c gcr-gnupg-renderer.h \
+ gcr-gnupg-records.c gcr-gnupg-records.h \
gcr-icons.c gcr-icons.h \
gcr-import-dialog.c gcr-import-dialog.h \
gcr-importer.c gcr-importer.h \
@@ -138,6 +142,8 @@ libgcr_ GCR_MAJOR@_la_SOURCES = \
gcr-list-selector.c gcr-list-selector.h gcr-list-selector-private.h \
gcr-live-search.c gcr-live-search.h \
gcr-memory.c \
+ gcr-memory-icon.c gcr-memory-icon.h \
+ gcr-record.c gcr-record.h \
gcr-renderer.c gcr-renderer.h \
gcr-tree-selector.c gcr-tree-selector.h \
gcr-unlock-options.h \
diff --git a/gcr/gcr-gnupg-collection.c b/gcr/gcr-gnupg-collection.c
index bbcaf20..8e81204 100644
--- a/gcr/gcr-gnupg-collection.c
+++ b/gcr/gcr-gnupg-collection.c
@@ -30,6 +30,7 @@
#include "gcr-gnupg-collection.h"
#include "gcr-gnupg-key.h"
#include "gcr-gnupg-process.h"
+#include "gcr-gnupg-records.h"
#include "gcr-gnupg-util.h"
#include "gcr-internal.h"
#include "gcr-record.h"
@@ -305,7 +306,7 @@ process_records_as_public_key (GcrGnupgCollectionLoad *load, GPtrArray *records,
guint i;
/* Add in any attributes we have loaded */
- fingerprint = _gcr_gnupg_key_get_fingerprint_for_records (records);
+ fingerprint = _gcr_gnupg_records_get_fingerprint (records);
if (fingerprint && load->attributes)
attr_records = g_hash_table_lookup (load->attributes, fingerprint);
if (attr_records) {
@@ -377,7 +378,7 @@ process_records_as_key (GcrGnupgCollectionLoad *load)
records = load->records;
load->records = g_ptr_array_new_with_free_func (_gcr_record_free);
- keyid = _gcr_gnupg_key_get_keyid_for_records (records);
+ keyid = _gcr_gnupg_records_get_keyid (records);
if (keyid) {
schema = _gcr_record_get_schema (records->pdata[0]);
diff --git a/gcr/gcr-gnupg-key.c b/gcr/gcr-gnupg-key.c
index 7f269f1..1d1bc42 100644
--- a/gcr/gcr-gnupg-key.c
+++ b/gcr/gcr-gnupg-key.c
@@ -22,6 +22,7 @@
#include "config.h"
#include "gcr-gnupg-key.h"
+#include "gcr-gnupg-records.h"
#include "gcr-record.h"
#include "gcr-memory-icon.h"
@@ -143,10 +144,10 @@ calculate_name (GcrGnupgKey *self)
{
GcrRecord* record;
- record = _gcr_record_find (self->pv->public_records, GCR_RECORD_SCHEMA_UID);
+ record = _gcr_records_find (self->pv->public_records, GCR_RECORD_SCHEMA_UID);
g_return_val_if_fail (record, NULL);
- return _gcr_record_get_string (record, GCR_RECORD_UID_NAME);
+ return _gcr_record_get_string (record, GCR_RECORD_UID_USERID);
}
static gchar *
@@ -172,23 +173,6 @@ calculate_markup (GcrGnupgKey *self)
return markup;
}
-static const gchar *
-calculate_short_keyid (GcrGnupgKey *self)
-{
- const gchar *keyid;
- gsize length;
-
- keyid = _gcr_gnupg_key_get_keyid_for_records (self->pv->public_records);
- if (keyid == NULL)
- return NULL;
-
- length = strlen (keyid);
- if (length > 8)
- keyid += (length - 8);
-
- return keyid;
-}
-
static void
_gcr_gnupg_key_init (GcrGnupgKey *self)
{
@@ -253,7 +237,7 @@ _gcr_gnupg_key_get_property (GObject *obj, guint prop_id, GValue *value,
g_value_take_string (value, calculate_markup (self));
break;
case PROP_SHORT_KEYID:
- g_value_set_string (value, calculate_short_keyid (self));
+ g_value_set_string (value, _gcr_gnupg_records_get_short_keyid (self->pv->public_records));
break;
case PROP_ICON:
g_value_set_object (value, _gcr_gnupg_key_get_icon (self));
@@ -403,8 +387,8 @@ _gcr_gnupg_key_set_public_records (GcrGnupgKey *self, GPtrArray *records)
/* Check that it matches previous */
if (self->pv->public_records) {
- const gchar *old_keyid = _gcr_gnupg_key_get_keyid_for_records (self->pv->public_records);
- const gchar *new_keyid = _gcr_gnupg_key_get_keyid_for_records (records);
+ const gchar *old_keyid = _gcr_gnupg_records_get_keyid (self->pv->public_records);
+ const gchar *new_keyid = _gcr_gnupg_records_get_keyid (records);
if (g_strcmp0 (old_keyid, new_keyid) != 0) {
g_warning ("it is an error to change a gnupg key so that the "
@@ -458,8 +442,8 @@ _gcr_gnupg_key_set_secret_records (GcrGnupgKey *self, GPtrArray *records)
/* Check that it matches public key */
if (self->pv->public_records && records) {
- const gchar *pub_keyid = _gcr_gnupg_key_get_keyid_for_records (self->pv->public_records);
- const gchar *sec_keyid = _gcr_gnupg_key_get_keyid_for_records (records);
+ const gchar *pub_keyid = _gcr_gnupg_records_get_keyid (self->pv->public_records);
+ const gchar *sec_keyid = _gcr_gnupg_records_get_keyid (records);
if (g_strcmp0 (pub_keyid, sec_keyid) != 0) {
g_warning ("it is an error to create a gnupg key so that the "
@@ -493,98 +477,7 @@ const gchar*
_gcr_gnupg_key_get_keyid (GcrGnupgKey *self)
{
g_return_val_if_fail (GCR_IS_GNUPG_KEY (self), NULL);
- return _gcr_gnupg_key_get_keyid_for_records (self->pv->public_records);
-}
-
-/**
- * _gcr_gnupg_key_get_keyid_for_records:
- * @records: Array of GcrRecord*
- *
- * Get the keyid for some record data.
- *
- * Returns: (transfer none): The keyid.
- */
-const gchar*
-_gcr_gnupg_key_get_keyid_for_records (GPtrArray *records)
-{
- GcrRecord *record;
-
- record = _gcr_record_find (records, GCR_RECORD_SCHEMA_PUB);
- if (record != NULL)
- return _gcr_record_get_raw (record, GCR_RECORD_KEY_KEYID);
- record = _gcr_record_find (records, GCR_RECORD_SCHEMA_SEC);
- if (record != NULL)
- return _gcr_record_get_raw (record, GCR_RECORD_KEY_KEYID);
- return NULL;
-}
-
-/**
- * _gcr_gnupg_key_get_fingerprint_for_records:
- * @records: Array of GcrRecord*
- *
- * Get the fingerprint field for some record data:
- *
- * Returns: (transfer none): The fingerprint.
- */
-const gchar*
-_gcr_gnupg_key_get_fingerprint_for_records (GPtrArray *records)
-{
- GcrRecord *record;
-
- record = _gcr_record_find (records, GCR_RECORD_SCHEMA_FPR);
- if (record != NULL)
- return _gcr_record_get_raw (record, GCR_RECORD_FPR_FINGERPRINT);
- return NULL;
-}
-
-#define TYPE_IMAGE 0x01
-#define IMAGE_HEADER_LEN 0x10
-#define IMAGE_JPEG_SIG "\x10\x00\x01\x01"
-#define IMAGE_JPEG_SIG_LEN 4
-
-static GIcon*
-load_user_attribute_icon (GcrGnupgKey *self)
-{
- GcrRecord *record;
- guchar *data;
- gsize n_data;
- guint type;
- guint i;
-
- for (i = 0; i < self->pv->public_records->len; i++) {
- record = self->pv->public_records->pdata[i];
- if (GCR_RECORD_SCHEMA_XA1 != _gcr_record_get_schema (record))
- continue;
- if (!_gcr_record_get_uint (record, GCR_RECORD_XA1_TYPE, &type))
- continue;
- if (type != TYPE_IMAGE)
- continue;
-
- /* TODO: Validity? */
-
- data = _gcr_record_get_base64 (record, GCR_RECORD_XA1_DATA, &n_data);
- g_return_val_if_fail (data != NULL, NULL);
-
- /* Header is 16 bytes long */
- if (n_data <= IMAGE_HEADER_LEN) {
- g_free (data);
- continue;
- }
-
- /* These are the header bytes. See gnupg doc/DETAILS */
- g_assert (IMAGE_JPEG_SIG_LEN < IMAGE_HEADER_LEN);
- if (memcmp (data, IMAGE_JPEG_SIG, IMAGE_JPEG_SIG_LEN) != 0) {
- g_free (data);
- continue;
- }
-
- /* We have a valid header */
- return G_ICON (_gcr_memory_icon_new_full ("image/jpeg", data,
- n_data, IMAGE_HEADER_LEN,
- g_free));
- }
-
- return NULL;
+ return _gcr_gnupg_records_get_keyid (self->pv->public_records);
}
/**
@@ -601,7 +494,7 @@ _gcr_gnupg_key_get_icon (GcrGnupgKey *self)
g_return_val_if_fail (GCR_IS_GNUPG_KEY (self), NULL);
if (self->pv->icon == NULL) {
- self->pv->icon = load_user_attribute_icon (self);
+ self->pv->icon = _gcr_gnupg_records_get_icon (self->pv->public_records);
if (self->pv->icon == NULL) {
if (self->pv->secret_records)
self->pv->icon = g_themed_icon_new ("gcr-key-pair");
diff --git a/gcr/gcr-gnupg-key.h b/gcr/gcr-gnupg-key.h
index 2564edb..e442632 100644
--- a/gcr/gcr-gnupg-key.h
+++ b/gcr/gcr-gnupg-key.h
@@ -77,10 +77,6 @@ void _gcr_gnupg_key_set_secret_records (GcrGnupgKey *s
GIcon* _gcr_gnupg_key_get_icon (GcrGnupgKey *self);
-const gchar* _gcr_gnupg_key_get_keyid_for_records (GPtrArray *records);
-
-const gchar* _gcr_gnupg_key_get_fingerprint_for_records (GPtrArray *records);
-
G_END_DECLS
#endif /* __GCR_GNUPG_KEY_H__ */
diff --git a/gcr/gcr-gnupg-records.c b/gcr/gcr-gnupg-records.c
new file mode 100644
index 0000000..1389350
--- /dev/null
+++ b/gcr/gcr-gnupg-records.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "gcr-gnupg-records.h"
+#include "gcr-record.h"
+#include "gcr-memory-icon.h"
+
+#include "gck/gck.h"
+
+#include <glib/gi18n-lib.h>
+
+/* Copied from GPGME */
+gboolean
+_gcr_gnupg_records_parse_user_id (const gchar *user_id,
+ gchar **rname,
+ gchar **remail,
+ gchar **rcomment)
+{
+ gchar *src, *tail, *x;
+ int in_name = 0;
+ int in_email = 0;
+ int in_comment = 0;
+ gboolean anything;
+ const gchar *name = NULL;
+ const gchar *email = NULL;
+ const gchar *comment = NULL;
+
+ x = tail = src = g_strdup (user_id);
+
+ while (*src) {
+ if (in_email) {
+ /* Not legal but anyway. */
+ if (*src == '<')
+ in_email++;
+ else if (*src == '>') {
+ if (!--in_email && !email) {
+ email = tail;
+ *src = 0;
+ tail = src + 1;
+ }
+ }
+ } else if (in_comment) {
+ if (*src == '(')
+ in_comment++;
+ else if (*src == ')') {
+ if (!--in_comment && !comment) {
+ comment = tail;
+ *src = 0;
+ tail = src + 1;
+ }
+ }
+ } else if (*src == '<') {
+ if (in_name) {
+ if (!name) {
+ name = tail;
+ *src = 0;
+ tail = src + 1;
+ }
+ in_name = 0;
+ } else
+ tail = src + 1;
+
+ in_email = 1;
+ } else if (*src == '(') {
+ if (in_name) {
+ if (!name) {
+ name = tail;
+ *src = 0;
+ tail = src + 1;
+ }
+ in_name = 0;
+ }
+ in_comment = 1;
+ } else if (!in_name && *src != ' ' && *src != '\t') {
+ in_name = 1;
+ }
+ src++;
+ }
+
+ if (in_name) {
+ if (!name) {
+ name = tail;
+ *src = 0;
+ tail = src + 1;
+ }
+ }
+
+ anything = FALSE;
+
+ if (rname) {
+ *rname = g_strdup (name);
+ if (name) {
+ g_strstrip (*rname);
+ anything = TRUE;
+ }
+ }
+
+ if (remail) {
+ *remail = g_strdup (email);
+ if (email) {
+ g_strstrip (*remail);
+ anything = TRUE;
+ }
+ }
+
+ if (rcomment) {
+ *rcomment = g_strdup (comment);
+ if (comment) {
+ g_strstrip (*rcomment);
+ anything = TRUE;
+ }
+ }
+
+ g_free (x);
+ return anything;
+}
+
+const gchar *
+_gcr_gnupg_records_get_keyid (GPtrArray *records)
+{
+ GcrRecord *record;
+
+ record = _gcr_records_find (records, GCR_RECORD_SCHEMA_PUB);
+ if (record != NULL)
+ return _gcr_record_get_raw (record, GCR_RECORD_KEY_KEYID);
+ record = _gcr_records_find (records, GCR_RECORD_SCHEMA_SEC);
+ if (record != NULL)
+ return _gcr_record_get_raw (record, GCR_RECORD_KEY_KEYID);
+ return NULL;
+}
+
+const gchar *
+_gcr_gnupg_records_get_short_keyid (GPtrArray *records)
+{
+ const gchar *keyid;
+ gsize length;
+
+ keyid = _gcr_gnupg_records_get_keyid (records);
+ if (keyid == NULL)
+ return NULL;
+
+ length = strlen (keyid);
+ if (length > 8)
+ keyid += (length - 8);
+
+ return keyid;
+}
+
+gchar *
+_gcr_gnupg_records_get_user_id (GPtrArray *records)
+{
+ GcrRecord *record;
+
+ record = _gcr_records_find (records, GCR_RECORD_SCHEMA_UID);
+ if (record != NULL)
+ return _gcr_record_get_string (record, GCR_RECORD_UID_USERID);
+ return NULL;
+}
+
+const gchar *
+_gcr_gnupg_records_get_fingerprint (GPtrArray *records)
+{
+ GcrRecord *record;
+
+ record = _gcr_records_find (records, GCR_RECORD_SCHEMA_FPR);
+ if (record != NULL)
+ return _gcr_record_get_raw (record, GCR_RECORD_FPR_FINGERPRINT);
+ return NULL;
+}
+
+#define TYPE_IMAGE 0x01
+#define IMAGE_HEADER_LEN 0x10
+#define IMAGE_JPEG_SIG "\x10\x00\x01\x01"
+#define IMAGE_JPEG_SIG_LEN 4
+
+GIcon *
+_gcr_gnupg_records_get_icon (GPtrArray *records)
+{
+ GcrRecord *record;
+ guchar *data;
+ gsize n_data;
+ guint type;
+ guint i;
+
+ for (i = 0; i < records->len; i++) {
+ record = records->pdata[i];
+ if (GCR_RECORD_SCHEMA_XA1 != _gcr_record_get_schema (record))
+ continue;
+ if (!_gcr_record_get_uint (record, GCR_RECORD_XA1_TYPE, &type))
+ continue;
+ if (type != TYPE_IMAGE)
+ continue;
+
+ /* TODO: Validity? */
+
+ data = _gcr_record_get_base64 (record, GCR_RECORD_XA1_DATA, &n_data);
+ g_return_val_if_fail (data != NULL, NULL);
+
+ /* Header is 16 bytes long */
+ if (n_data <= IMAGE_HEADER_LEN) {
+ g_free (data);
+ continue;
+ }
+
+ /* These are the header bytes. See gnupg doc/DETAILS */
+ g_assert (IMAGE_JPEG_SIG_LEN < IMAGE_HEADER_LEN);
+ if (memcmp (data, IMAGE_JPEG_SIG, IMAGE_JPEG_SIG_LEN) != 0) {
+ g_free (data);
+ continue;
+ }
+
+ /* We have a valid header */
+ return G_ICON (_gcr_memory_icon_new_full ("image/jpeg", data,
+ n_data, IMAGE_HEADER_LEN,
+ g_free));
+ }
+
+ if (_gcr_records_find (records, GCR_RECORD_SCHEMA_SEC))
+ return g_themed_icon_new ("gcr-key-pair");
+ else
+ return g_themed_icon_new ("gcr-key");
+
+ return NULL;
+}
diff --git a/gcr/gcr-gnupg-records.h b/gcr/gcr-gnupg-records.h
new file mode 100644
index 0000000..4a61ff9
--- /dev/null
+++ b/gcr/gcr-gnupg-records.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#if !defined (__GCR_H_INSIDE__) && !defined (GCR_COMPILATION)
+#error "Only <gcr/gcr.h> can be included directly."
+#endif
+
+#ifndef GCR_GNUPG_RECORDS_H
+#define GCR_GNUPG_RECORDS_H
+
+#include <gio/gio.h>
+
+#include "gcr-record.h"
+
+G_BEGIN_DECLS
+
+const gchar * _gcr_gnupg_records_get_keyid (GPtrArray *records);
+
+const gchar * _gcr_gnupg_records_get_short_keyid (GPtrArray *records);
+
+const gchar * _gcr_gnupg_records_get_fingerprint (GPtrArray *records);
+
+gchar * _gcr_gnupg_records_get_user_id (GPtrArray *records);
+
+gboolean _gcr_gnupg_records_parse_user_id (const gchar *user_id,
+ gchar **name,
+ gchar **email,
+ gchar **comment);
+
+GIcon * _gcr_gnupg_records_get_icon (GPtrArray *records);
+
+G_END_DECLS
+
+#endif /* __GCR_GNUPG_RECORD_H__ */
diff --git a/gcr/gcr-gnupg-renderer.c b/gcr/gcr-gnupg-renderer.c
new file mode 100644
index 0000000..c0b6495
--- /dev/null
+++ b/gcr/gcr-gnupg-renderer.c
@@ -0,0 +1,852 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "gcr-display-view.h"
+#include "gcr-icons.h"
+#include "gcr-gnupg-records.h"
+#include "gcr-gnupg-renderer.h"
+#include "gcr-openpgp.h"
+#include "gcr-simple-certificate.h"
+#include "gcr-renderer.h"
+#include "gcr-types.h"
+
+#include "gck/gck.h"
+
+#include "egg/egg-hex.h"
+
+#include <gdk/gdk.h>
+#include <glib/gi18n-lib.h>
+
+#include <stdlib.h>
+
+enum {
+ PROP_0,
+ PROP_RECORDS,
+ PROP_LABEL,
+ PROP_ATTRIBUTES
+};
+
+struct _GcrGnupgRendererPrivate {
+ GPtrArray *records;
+ GckAttributes *attrs;
+ gchar *label;
+};
+
+static void _gcr_gnupg_renderer_iface_init (GcrRendererIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GcrGnupgRenderer, _gcr_gnupg_renderer, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GCR_TYPE_RENDERER, _gcr_gnupg_renderer_iface_init);
+);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static gchar *
+calculate_label (GcrGnupgRenderer *self)
+{
+ gchar *userid;
+ gchar *label;
+
+ if (self->pv->attrs) {
+ if (gck_attributes_find_string (self->pv->attrs, CKA_LABEL, &label))
+ return label;
+ }
+
+ userid = _gcr_gnupg_records_get_user_id (self->pv->records);
+ if (userid != NULL) {
+ if (!_gcr_gnupg_records_parse_user_id (userid, &label, NULL, NULL))
+ label = NULL;
+ }
+
+ if (label != NULL)
+ return label;
+
+ if (self->pv->label)
+ return g_strdup (self->pv->label);
+
+ return g_strdup (_("PGP Key"));
+}
+
+static void
+_gcr_gnupg_renderer_init (GcrGnupgRenderer *self)
+{
+ self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_GNUPG_RENDERER,
+ GcrGnupgRendererPrivate));
+}
+
+static void
+_gcr_gnupg_renderer_finalize (GObject *obj)
+{
+ GcrGnupgRenderer *self = GCR_GNUPG_RENDERER (obj);
+
+ gck_attributes_unref (self->pv->attrs);
+ g_free (self->pv->label);
+ if (self->pv->records)
+ g_ptr_array_unref (self->pv->records);
+
+ G_OBJECT_CLASS (_gcr_gnupg_renderer_parent_class)->finalize (obj);
+}
+
+static void
+_gcr_gnupg_renderer_set_property (GObject *obj,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GcrGnupgRenderer *self = GCR_GNUPG_RENDERER (obj);
+
+ switch (prop_id) {
+ case PROP_RECORDS:
+ _gcr_gnupg_renderer_set_records (self, g_value_get_boxed (value));
+ break;
+ case PROP_LABEL:
+ g_free (self->pv->label);
+ self->pv->label = g_value_dup_string (value);
+ g_object_notify (obj, "label");
+ gcr_renderer_emit_data_changed (GCR_RENDERER (self));
+ break;
+ case PROP_ATTRIBUTES:
+ _gcr_gnupg_renderer_set_attributes (self, g_value_get_boxed (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gcr_gnupg_renderer_get_property (GObject *obj,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GcrGnupgRenderer *self = GCR_GNUPG_RENDERER (obj);
+
+ switch (prop_id) {
+ case PROP_RECORDS:
+ g_value_set_object (value, self->pv->records);
+ break;
+ case PROP_LABEL:
+ g_value_take_string (value, calculate_label (self));
+ break;
+ case PROP_ATTRIBUTES:
+ g_value_set_boxed (value, self->pv->attrs);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gcr_gnupg_renderer_class_init (GcrGnupgRendererClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GckAttributes *registered;
+
+ _gcr_gnupg_renderer_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (GcrGnupgRendererPrivate));
+
+ gobject_class->finalize = _gcr_gnupg_renderer_finalize;
+ gobject_class->set_property = _gcr_gnupg_renderer_set_property;
+ gobject_class->get_property = _gcr_gnupg_renderer_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_RECORDS,
+ g_param_spec_boxed ("records", "Records", "Gnupg records to display",
+ G_TYPE_PTR_ARRAY, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
+ g_param_spec_boxed ("attributes", "Attributes", "Certificate pkcs11 attributes",
+ GCK_TYPE_ATTRIBUTES, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_LABEL,
+ g_param_spec_string ("label", "Label", "Certificate Label",
+ "", G_PARAM_READWRITE));
+
+ /* Register this as a renderer which can be loaded */
+ registered = gck_attributes_new ();
+ gck_attributes_add_ulong (registered, CKA_CLASS, CKO_GCR_GNUPG_RECORDS);
+ gcr_renderer_register (GCR_TYPE_GNUPG_RENDERER, registered);
+ gck_attributes_unref (registered);
+}
+
+static const gchar *
+name_for_algo (guint algo)
+{
+ switch (algo)
+ {
+ case GCR_OPENPGP_ALGO_RSA:
+ case GCR_OPENPGP_ALGO_RSA_E:
+ case GCR_OPENPGP_ALGO_RSA_S:
+ return _("RSA");
+ case GCR_OPENPGP_ALGO_ELG_E:
+ return _("Elgamal");
+ case GCR_OPENPGP_ALGO_DSA:
+ return _("DSA");
+ default:
+ return NULL;
+ }
+}
+
+static const gchar *
+capability_for_code (gchar code)
+{
+ switch (code) {
+ case 'e': case 'E':
+ return _("Encrypt");
+ case 's': case 'S':
+ return _("Sign");
+ case 'c': case 'C':
+ return _("Certify");
+ case 'a': case 'A':
+ return _("Authenticate");
+ case 'D':
+ return _("Disabled");
+ default:
+ return NULL;
+ }
+}
+
+static gchar *
+capabilities_for_codes (const gchar *codes)
+{
+ const gchar *cap;
+ GString *result;
+ guint i;
+
+ result = g_string_new ("");
+ for (i = 0; codes[i] != 0; i++) {
+ if (result->len)
+ g_string_append_unichar (result, GCR_DISPLAY_VIEW_LINE_BREAK);
+ cap = capability_for_code (codes[i]);
+ if (cap != NULL)
+ g_string_append (result, cap);
+ else
+ g_string_append_c (result, codes[i]);
+ }
+ return g_string_free (result, FALSE);
+}
+
+static const gchar *
+status_for_code (gchar code)
+{
+ switch (code) {
+ case 'o':
+ return _("Unknown");
+ case 'i':
+ return _("Invalid");
+ case 'd':
+ return _("Disabled");
+ case 'r':
+ return _("Revoked");
+ case 'e':
+ return _("Expired");
+ case 'q': case '-':
+ return _("Undefined trust");
+ case 'n':
+ return _("Distrusted");
+ case 'm':
+ return _("Marginally trusted");
+ case 'f':
+ return _("Fully trusted");
+ case 'u':
+ return _("Ultimately trusted");
+ default:
+ return NULL;
+ }
+}
+
+#ifdef TODO
+static const gchar *
+description_for_code (gchar code, gboolean *warning)
+{
+ *warning = FALSE;
+ switch (code) {
+ case 'o':
+ *warning = TRUE;
+ return _("This key has not been verified");
+ case 'i':
+ *warning = TRUE;
+ return _("This key is invalid");
+ case 'd':
+ *warning = TRUE;
+ return _("This key has been disabled");
+ case 'r':
+ *warning = TRUE;
+ return _("This key has been revoked");
+ case 'e':
+ *warning = TRUE;
+ return _("This key has expired");
+ case 'q': case '-':
+ return _("The trust in this key is undefined");
+ case 'n':
+ *warning = TRUE;
+ return _("This key is distrusted");
+ case 'm':
+ return _("Marginally trusted");
+ case 'f':
+ return _("Fully trusted");
+ case 'u':
+ return _("Ultimately trusted");
+ default:
+ return NULL;
+ }
+}
+#endif
+
+static void
+append_key_record (GcrGnupgRenderer *self,
+ GcrDisplayView *view,
+ GcrRecord *record,
+ const gchar *title)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ const gchar *value;
+ gchar *display;
+ GDateTime *date;
+ gchar code;
+ guint algo;
+ guint bits;
+
+ _gcr_display_view_append_heading (view, renderer, title);
+
+ /* Key ID */
+ value = _gcr_record_get_raw (record, GCR_RECORD_KEY_KEYID);
+ if (value != NULL)
+ _gcr_display_view_append_value (view, renderer, _("Key ID"), value, TRUE);
+
+ /* Algorithm */
+ if (_gcr_record_get_uint (record, GCR_RECORD_KEY_ALGO, &algo)) {
+ display = NULL;
+ value = name_for_algo (algo);
+ if (value == NULL)
+ value = display = g_strdup_printf ("%u", algo);
+ _gcr_display_view_append_value (view, renderer, _("Algorithm"), value, FALSE);
+ g_free (display);
+ }
+
+ /* Key Size */
+ if (_gcr_record_get_uint (record, GCR_RECORD_KEY_BITS, &bits)) {
+ display = g_strdup_printf ("%u", bits);
+ _gcr_display_view_append_value (view, renderer, _("Key Size"), display, FALSE);
+ g_free (display);
+ }
+
+ /* Created */
+ date = _gcr_record_get_date (record, GCR_RECORD_KEY_TIMESTAMP);
+ if (date != NULL) {
+ display = g_date_time_format (date, "%x");
+ _gcr_display_view_append_value (view, renderer, _("Created"), display, FALSE);
+ g_free (display);
+ g_date_time_unref (date);
+ }
+
+ /* Expiry */
+ date = _gcr_record_get_date (record, GCR_RECORD_KEY_EXPIRY);
+ if (date != NULL) {
+ display = g_date_time_format (date, "%x");
+ _gcr_display_view_append_value (view, renderer, _("Expiry"), display, FALSE);
+ g_free (display);
+ g_date_time_unref (date);
+ }
+
+ /* Capabilities */
+ value = _gcr_record_get_raw (record, GCR_RECORD_PUB_CAPS);
+ if (value != NULL) {
+ display = capabilities_for_codes (value);
+ _gcr_display_view_append_value (view, renderer, _("Capabilities"), display, FALSE);
+ g_free (display);
+ }
+
+ /* Owner Trust */
+ code = _gcr_record_get_char (record, GCR_RECORD_KEY_OWNERTRUST);
+ if (code != 0) {
+ display = NULL;
+ value = status_for_code (code);
+ if (value == NULL) {
+ value = display = g_new0 (gchar, 2);
+ display[0] = code;
+ }
+ _gcr_display_view_append_value (view, renderer, _("Owner trust"), value, FALSE);
+ g_free (display);
+ }
+}
+
+static void
+append_uid_record (GcrGnupgRenderer *self,
+ GcrDisplayView *view,
+ GcrRecord *record)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ gchar *userid;
+ gchar *name;
+ gchar *comment;
+ gchar *email;
+ GDateTime *date;
+ gchar *display;
+
+ _gcr_display_view_append_heading (view, renderer, _("User ID"));
+
+ userid = _gcr_record_get_string (record, GCR_RECORD_UID_USERID);
+ if (userid == NULL) {
+ _gcr_display_view_append_value (view, renderer, _("Value"), _("Unknown"), FALSE);
+ return;
+ }
+
+ if (_gcr_gnupg_records_parse_user_id (userid, &name, &email, &comment)) {
+ if (name != NULL)
+ _gcr_display_view_append_value (view, renderer, _("Name"), name, FALSE);
+ g_free (name);
+ if (email != NULL)
+ _gcr_display_view_append_value (view, renderer, _("Email"), email, FALSE);
+ g_free (email);
+ if (comment != NULL)
+ _gcr_display_view_append_value (view, renderer, _("Comment"), comment, FALSE);
+ g_free (comment);
+
+ /* Unparseable user id */
+ } else {
+ _gcr_display_view_append_value (view, renderer, _("Value"), userid, FALSE);
+ }
+
+ /* Created */
+ date = _gcr_record_get_date (record, GCR_RECORD_UID_TIMESTAMP);
+ if (date != NULL) {
+ display = g_date_time_format (date, "%x");
+ _gcr_display_view_append_value (view, renderer, _("Created"), display, FALSE);
+ g_free (display);
+ g_date_time_unref (date);
+ }
+
+ /* Expiry */
+ date = _gcr_record_get_date (record, GCR_RECORD_UID_EXPIRY);
+ if (date != NULL) {
+ display = g_date_time_format (date, "%x");
+ _gcr_display_view_append_value (view, renderer, _("Expiry"), display, FALSE);
+ g_free (display);
+ g_date_time_unref (date);
+ }
+
+ g_free (userid);
+}
+
+static void
+append_uat_record (GcrGnupgRenderer *self,
+ GcrDisplayView *view,
+ GcrRecord *record)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ gchar **parts;
+ gchar *display;
+ const gchar *value;
+ GDateTime *date;
+
+ _gcr_display_view_append_heading (view, renderer, _("User Attribute"));
+
+ /* Size */
+ value = _gcr_record_get_raw (record, GCR_RECORD_UAT_COUNT_SIZE);
+ if (value != NULL) {
+ parts = g_strsplit (value, " ", 2);
+ if (parts && parts[0] && parts[1])
+ _gcr_display_view_append_value (view, renderer, _("Size"), parts[1], FALSE);
+ g_strfreev (parts);
+ }
+
+ /* Created */
+ date = _gcr_record_get_date (record, GCR_RECORD_KEY_TIMESTAMP);
+ if (date != NULL) {
+ display = g_date_time_format (date, "%x");
+ _gcr_display_view_append_value (view, renderer, _("Created"), display, FALSE);
+ g_free (display);
+ g_date_time_unref (date);
+ }
+
+ /* Expiry */
+ date = _gcr_record_get_date (record, GCR_RECORD_KEY_EXPIRY);
+ if (date != NULL) {
+ display = g_date_time_format (date, "%x");
+ _gcr_display_view_append_value (view, renderer, _("Expiry"), display, FALSE);
+ g_free (display);
+ g_date_time_unref (date);
+ }
+}
+
+static const gchar *
+signature_klass_string (const gchar *klass)
+{
+ char *end;
+ guint val;
+
+ val = strtoul (klass, &end, 16);
+ if (end != klass + 2)
+ return NULL;
+
+ switch (val) {
+ case 0x00:
+ return _("Signature of a binary document");
+ case 0x01:
+ return _("Signature of a canonical text document");
+ case 0x02:
+ return _("Standalone signature");
+ case 0x10:
+ return _("Generic certification of key");
+ case 0x11:
+ return _("Persona certification of key");
+ case 0x12:
+ return _("Casual certification of key");
+ case 0x13:
+ return _("Positive certification of key");
+ case 0x18:
+ return _("Subkey binding signature");
+ case 0x19:
+ return _("Primary key binding signature");
+ case 0x1F:
+ return _("Signature directly on key");
+ case 0x20:
+ return _("Key revocation signature");
+ case 0x28:
+ return _("Subkey revocation signature");
+ case 0x30:
+ return _("Certification revocation signature");
+ case 0x40:
+ return _("Timestamp signature");
+ case 0x50:
+ return _("Third-party confirmation signature");
+ default:
+ return NULL;
+ }
+}
+
+static void
+append_sig_record (GcrGnupgRenderer *self,
+ GcrDisplayView *view,
+ GcrRecord *record,
+ const gchar *keyid)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ const gchar *sigid;
+ gchar *display;
+ const gchar *value;
+ const gchar *klass;
+ guint algo;
+
+ /* Hide self-signatures. There's so many of them */
+ sigid = _gcr_record_get_raw (record, GCR_RECORD_SIG_KEYID);
+ if (sigid && keyid && g_str_equal (sigid, keyid))
+ return;
+
+ _gcr_display_view_append_heading (view, renderer, _("Signature"));
+
+ /* Key ID */
+ if (sigid != NULL)
+ _gcr_display_view_append_value (view, renderer, _("Key ID"), sigid, TRUE);
+
+ /* Algorithm */
+ if (_gcr_record_get_uint (record, GCR_RECORD_SIG_ALGO, &algo)) {
+ display = NULL;
+ value = name_for_algo (algo);
+ if (value == NULL)
+ value = display = g_strdup_printf ("%u", algo);
+ _gcr_display_view_append_value (view, renderer, _("Algorithm"), value, FALSE);
+ g_free (display);
+ }
+
+ /* User ID */
+ display = _gcr_record_get_string (record, GCR_RECORD_SIG_USERID);
+ if (display != NULL)
+ _gcr_display_view_append_value (view, renderer, _("User ID"), display, FALSE);
+ g_free (display);
+
+ /* Signature class */
+ klass = _gcr_record_get_raw (record, GCR_RECORD_SIG_CLASS);
+ if (klass != NULL) {
+ value = NULL;
+ if (strlen (klass) >= 2) {
+ value = signature_klass_string (klass);
+ if (value != NULL) {
+ _gcr_display_view_append_value (view, renderer, _("Class"), value, FALSE);
+ if (klass[2] == 'l')
+ _gcr_display_view_append_value (view, renderer, _("Type"), _("Local only"), FALSE);
+ else if (klass[2] == 'x')
+ _gcr_display_view_append_value (view, renderer, _("Type"), _("Exportable"), FALSE);
+ }
+ }
+ if (value == NULL)
+ _gcr_display_view_append_value (view, renderer, _("Class"), klass, FALSE);
+ }
+}
+
+static void
+append_rvk_record (GcrGnupgRenderer *self,
+ GcrDisplayView *view,
+ GcrRecord *record)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ const gchar *value;
+ gchar *display;
+ guint algo;
+
+ _gcr_display_view_append_heading (view, renderer, _("Revocation Key"));
+
+ /* Algorithm */
+ if (_gcr_record_get_uint (record, GCR_RECORD_RVK_ALGO, &algo)) {
+ display = NULL;
+ value = name_for_algo (algo);
+ if (value == NULL)
+ value = display = g_strdup_printf ("%u", algo);
+ _gcr_display_view_append_value (view, renderer, _("Algorithm"), value, FALSE);
+ g_free (display);
+ }
+
+ value = _gcr_record_get_raw (record, GCR_RECORD_RVK_FINGERPRINT);
+ if (value != NULL)
+ _gcr_display_view_append_value (view, renderer, _("Fingerprint"), value, TRUE);
+}
+
+static void
+append_fpr_record (GcrGnupgRenderer *self,
+ GcrDisplayView *view,
+ GcrRecord *record,
+ GQuark last_schema)
+{
+ GcrRenderer *renderer = GCR_RENDERER (self);
+ const gchar *value;
+ gpointer raw;
+ gsize n_raw;
+
+ if (last_schema != GCR_RECORD_SCHEMA_PUB &&
+ last_schema != GCR_RECORD_SCHEMA_SUB &&
+ last_schema != GCR_RECORD_SCHEMA_SEC &&
+ last_schema != GCR_RECORD_SCHEMA_SSB)
+ return;
+
+ value = _gcr_record_get_raw (record, GCR_RECORD_FPR_FINGERPRINT);
+ if (value != NULL) {
+ raw = egg_hex_decode (value, -1, &n_raw);
+ if (raw != NULL)
+ _gcr_display_view_append_hex (view, renderer, _("Fingerprint"), raw, n_raw);
+ else
+ _gcr_display_view_append_value (view, renderer, _("Fingerprint"), value, TRUE);
+ g_free (raw);
+ }
+}
+
+static void
+_gcr_gnupg_renderer_render (GcrRenderer *renderer,
+ GcrViewer *viewer)
+{
+ GcrGnupgRenderer *self;
+ GcrDisplayView *view;
+ GDateTime *date;
+ const gchar *value;
+ gchar *display;
+ gchar *userid;
+ gchar *email;
+ gchar *comment;
+ GIcon *icon;
+ GQuark schema;
+ GQuark last_schema;
+ gchar code;
+ guint i;
+
+ self = GCR_GNUPG_RENDERER (renderer);
+
+ if (GCR_IS_DISPLAY_VIEW (viewer)) {
+ view = GCR_DISPLAY_VIEW (viewer);
+
+ } else {
+ g_warning ("GcrGnupgRenderer only works with internal specific "
+ "GcrViewer returned by gcr_viewer_new().");
+ return;
+ }
+
+ _gcr_display_view_begin (view, renderer);
+
+ if (self->pv->records == NULL || self->pv->records->len == 0) {
+ _gcr_display_view_end (view, renderer);
+ return;
+ }
+
+ icon = _gcr_gnupg_records_get_icon (self->pv->records);
+ _gcr_display_view_set_icon (view, GCR_RENDERER (self), icon);
+ g_object_unref (icon);
+
+ display = calculate_label (self);
+ _gcr_display_view_append_title (view, renderer, display);
+ g_free (display);
+
+ userid = _gcr_gnupg_records_get_user_id (self->pv->records);
+ if (userid != NULL) {
+ if (_gcr_gnupg_records_parse_user_id (userid, NULL, &email, &comment)) {
+ if (email != NULL)
+ _gcr_display_view_append_content (view, renderer, _("Email"), email);
+ g_free (email);
+ if (comment != NULL)
+ _gcr_display_view_append_content (view, renderer, _("Comment"), comment);
+ g_free (comment);
+ }
+ g_free (userid);
+ }
+
+ value = _gcr_gnupg_records_get_short_keyid (self->pv->records);
+ if (value != NULL)
+ _gcr_display_view_append_content (view, renderer, _("Key ID"), value);
+
+ code = _gcr_record_get_char (self->pv->records->pdata[0], GCR_RECORD_TRUST);
+ if (code != 'e') {
+ date = _gcr_record_get_date (self->pv->records->pdata[0], GCR_RECORD_KEY_EXPIRY);
+ if (date != NULL) {
+ display = g_date_time_format (date, "%x");
+ _gcr_display_view_append_content (view, renderer, _("Expires"), display);
+ g_date_time_unref (date);
+ g_free (display);
+ }
+ }
+
+ /* TODO: Warning */
+
+
+ _gcr_display_view_start_details (view, renderer);
+
+ value = _gcr_gnupg_records_get_keyid (self->pv->records);
+ last_schema = 0;
+
+ for (i = 0; i < self->pv->records->len; i++) {
+ schema = _gcr_record_get_schema (self->pv->records->pdata[i]);
+ if (schema == GCR_RECORD_SCHEMA_PUB)
+ append_key_record (self, view, self->pv->records->pdata[i], _("Public Key"));
+ else if (schema == GCR_RECORD_SCHEMA_SUB)
+ append_key_record (self, view, self->pv->records->pdata[i], _("Public Subkey"));
+ else if (schema == GCR_RECORD_SCHEMA_SEC)
+ append_key_record (self, view, self->pv->records->pdata[i], _("Secret Key"));
+ else if (schema == GCR_RECORD_SCHEMA_SSB)
+ append_key_record (self, view, self->pv->records->pdata[i], _("Secret Subkey"));
+ else if (schema == GCR_RECORD_SCHEMA_UID)
+ append_uid_record (self, view, self->pv->records->pdata[i]);
+ else if (schema == GCR_RECORD_SCHEMA_UAT)
+ append_uat_record (self, view, self->pv->records->pdata[i]);
+ else if (schema == GCR_RECORD_SCHEMA_SIG)
+ append_sig_record (self, view, self->pv->records->pdata[i], value);
+ else if (schema == GCR_RECORD_SCHEMA_RVK)
+ append_rvk_record (self, view, self->pv->records->pdata[i]);
+ else if (schema == GCR_RECORD_SCHEMA_FPR)
+ append_fpr_record (self, view, self->pv->records->pdata[i], last_schema);
+ last_schema = schema;
+ }
+
+ _gcr_display_view_end (view, renderer);
+}
+
+static void
+_gcr_gnupg_renderer_iface_init (GcrRendererIface *iface)
+{
+ iface->render_view = _gcr_gnupg_renderer_render;
+}
+
+GcrGnupgRenderer *
+_gcr_gnupg_renderer_new (GPtrArray *records)
+{
+ g_return_val_if_fail (records != NULL, NULL);
+
+ return g_object_new (GCR_TYPE_GNUPG_RENDERER,
+ "records", records,
+ NULL);
+}
+
+GcrGnupgRenderer *
+_gcr_gnupg_renderer_new_for_attributes (const gchar *label,
+ GckAttributes *attrs)
+{
+ g_return_val_if_fail (attrs != NULL, NULL);
+
+ return g_object_new (GCR_TYPE_GNUPG_RENDERER,
+ "label", label,
+ "attributes", attrs,
+ NULL);
+}
+
+GPtrArray *
+_gcr_gnupg_renderer_get_records (GcrGnupgRenderer *self)
+{
+ g_return_val_if_fail (GCR_IS_GNUPG_RENDERER (self), NULL);
+ return self->pv->records;
+}
+
+void
+_gcr_gnupg_renderer_set_records (GcrGnupgRenderer *self,
+ GPtrArray *records)
+{
+ g_return_if_fail (GCR_IS_GNUPG_RENDERER (self));
+
+ if (records)
+ g_ptr_array_ref (records);
+ if (self->pv->records)
+ g_ptr_array_unref (self->pv->records);
+ self->pv->records = records;
+
+ if (self->pv->attrs) {
+ gck_attributes_unref (self->pv->attrs);
+ self->pv->attrs = NULL;
+ g_object_notify (G_OBJECT (self), "attributes");
+ }
+
+ gcr_renderer_emit_data_changed (GCR_RENDERER (self));
+ g_object_notify (G_OBJECT (self), "records");
+}
+
+GckAttributes*
+_gcr_gnupg_renderer_get_attributes (GcrGnupgRenderer *self)
+{
+ g_return_val_if_fail (GCR_IS_GNUPG_RENDERER (self), NULL);
+ return self->pv->attrs;
+}
+
+void
+_gcr_gnupg_renderer_set_attributes (GcrGnupgRenderer *self,
+ GckAttributes *attrs)
+{
+ GckAttribute *attr;
+ GPtrArray *records;
+
+ g_return_if_fail (GCR_IS_GNUPG_RENDERER (self));
+
+ attr = gck_attributes_find (attrs, CKA_VALUE);
+ g_return_if_fail (attr != NULL);
+ records = _gcr_records_parse_colons (attr->value, attr->length);
+ g_return_if_fail (records != NULL);
+
+ if (attrs)
+ gck_attributes_ref (attrs);
+ gck_attributes_unref (self->pv->attrs);
+ self->pv->attrs = attrs;
+
+ if (self->pv->records)
+ g_ptr_array_unref (self->pv->records);
+ self->pv->records = records;
+ g_object_notify (G_OBJECT (self), "records");
+
+ gcr_renderer_emit_data_changed (GCR_RENDERER (self));
+ g_object_notify (G_OBJECT (self), "attributes");
+
+}
diff --git a/gcr/gcr-gnupg-renderer.h b/gcr/gcr-gnupg-renderer.h
new file mode 100644
index 0000000..0d09c31
--- /dev/null
+++ b/gcr/gcr-gnupg-renderer.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#if !defined (__GCR_H_INSIDE__) && !defined (GCR_COMPILATION)
+#error "Only <gcr/gcr.h> can be included directly."
+#endif
+
+#ifndef __GCR_GNUPG_RENDERER_H__
+#define __GCR_GNUPG_RENDERER_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gcr-record.h"
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_GNUPG_RENDERER (_gcr_gnupg_renderer_get_type ())
+#define GCR_GNUPG_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_GNUPG_RENDERER, GcrGnupgRenderer))
+#define GCR_GNUPG_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_GNUPG_RENDERER, GcrGnupgRendererClass))
+#define GCR_IS_GNUPG_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_GNUPG_RENDERER))
+#define GCR_IS_GNUPG_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_GNUPG_RENDERER))
+#define GCR_GNUPG_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_GNUPG_RENDERER, GcrGnupgRendererClass))
+
+typedef struct _GcrGnupgRenderer GcrGnupgRenderer;
+typedef struct _GcrGnupgRendererClass GcrGnupgRendererClass;
+typedef struct _GcrGnupgRendererPrivate GcrGnupgRendererPrivate;
+
+struct _GcrGnupgRenderer {
+ GObject parent;
+
+ /*< private >*/
+ GcrGnupgRendererPrivate *pv;
+};
+
+struct _GcrGnupgRendererClass {
+ GObjectClass parent_class;
+};
+
+GType _gcr_gnupg_renderer_get_type (void);
+
+GcrGnupgRenderer * _gcr_gnupg_renderer_new (GPtrArray *records);
+
+GcrGnupgRenderer * _gcr_gnupg_renderer_new_for_attributes (const gchar *label,
+ GckAttributes *attrs);
+
+GPtrArray * _gcr_gnupg_renderer_get_records (GcrGnupgRenderer *self);
+
+void _gcr_gnupg_renderer_set_records (GcrGnupgRenderer *self,
+ GPtrArray *records);
+
+GckAttributes * _gcr_gnupg_renderer_get_attributes (GcrGnupgRenderer *self);
+
+void _gcr_gnupg_renderer_set_attributes (GcrGnupgRenderer *self,
+ GckAttributes *attrs);
+
+G_END_DECLS
+
+#endif /* __GCR_GNUPG_RENDERER_H__ */
diff --git a/gcr/gcr-openpgp.c b/gcr/gcr-openpgp.c
index abf6800..7ae5c47 100644
--- a/gcr/gcr-openpgp.c
+++ b/gcr/gcr-openpgp.c
@@ -35,14 +35,6 @@
#include <string.h>
typedef enum {
- OPENPGP_ALGO_RSA = 1,
- OPENPGP_ALGO_RSA_E = 2,
- OPENPGP_ALGO_RSA_S = 3,
- OPENPGP_ALGO_ELG_E = 16,
- OPENPGP_ALGO_DSA = 17
-} OpenpgpPkAlgo;
-
-typedef enum {
OPENPGP_PKT_RESERVED = 0,
OPENPGP_PKT_PUBKEY_ENC = 1,
OPENPGP_PKT_SIGNATURE = 2,
@@ -317,7 +309,8 @@ parse_v3_rsa_bits_and_keyid (const guchar **at,
static gchar *
hash_v4_keyid (const guchar *data,
- const guchar *end)
+ const guchar *end,
+ gchar **fingerprint)
{
gcry_md_hd_t mdh;
gcry_error_t gcry;
@@ -349,6 +342,8 @@ hash_v4_keyid (const guchar *data,
digest = gcry_md_read (mdh, 0);
keyid = egg_hex_encode_full (digest + 12, 8, TRUE, 0, 0);
+ if (fingerprint)
+ *fingerprint = egg_hex_encode_full (digest, 20, TRUE, 0, 0);
gcry_md_close (mdh);
return keyid;
@@ -361,21 +356,21 @@ parse_v4_algo_bits (const guchar **at,
guint16 *bits)
{
switch (algo) {
- case OPENPGP_ALGO_RSA:
- case OPENPGP_ALGO_RSA_E:
- case OPENPGP_ALGO_RSA_S:
+ case GCR_OPENPGP_ALGO_RSA:
+ case GCR_OPENPGP_ALGO_RSA_E:
+ case GCR_OPENPGP_ALGO_RSA_S:
if (!read_mpi (at, end, bits, NULL) ||
!read_mpi (at, end, NULL, NULL))
return FALSE;
return TRUE;
- case OPENPGP_ALGO_DSA:
+ case GCR_OPENPGP_ALGO_DSA:
if (!read_mpi (at, end, bits, NULL) ||
!read_mpi (at, end, NULL, NULL) ||
!read_mpi (at, end, NULL, NULL) ||
!read_mpi (at, end, NULL, NULL))
return FALSE;
return TRUE;
- case OPENPGP_ALGO_ELG_E:
+ case GCR_OPENPGP_ALGO_ELG_E:
if (!read_mpi (at, end, bits, NULL) ||
!read_mpi (at, end, NULL, NULL) ||
!read_mpi (at, end, NULL, NULL))
@@ -390,15 +385,15 @@ static const gchar *
default_caps_for_algo (guint8 algo)
{
switch (algo) {
- case OPENPGP_ALGO_RSA:
+ case GCR_OPENPGP_ALGO_RSA:
return "cse";
- case OPENPGP_ALGO_RSA_E:
+ case GCR_OPENPGP_ALGO_RSA_E:
return "e";
- case OPENPGP_ALGO_RSA_S:
+ case GCR_OPENPGP_ALGO_RSA_S:
return "s";
- case OPENPGP_ALGO_ELG_E:
+ case GCR_OPENPGP_ALGO_ELG_E:
return "e";
- case OPENPGP_ALGO_DSA:
+ case GCR_OPENPGP_ALGO_DSA:
return "sca";
default:
return "";
@@ -422,6 +417,7 @@ parse_public_key_or_subkey (GQuark schema,
guint8 algo;
guint16 bits;
gulong expiry;
+ gchar *fingerprint;
const guchar *data;
/* Start of actual key data in packet */
@@ -455,7 +451,7 @@ parse_public_key_or_subkey (GQuark schema,
} else {
if (!parse_v4_algo_bits (at, end, algo, &bits))
return FALSE;
- keyid = hash_v4_keyid (data, *at);
+ keyid = hash_v4_keyid (data, *at, &fingerprint);
}
record = _gcr_record_new (schema, n_columns, ':');
@@ -472,6 +468,15 @@ parse_public_key_or_subkey (GQuark schema,
}
g_ptr_array_add (records, record);
+
+ if (fingerprint && (schema == GCR_RECORD_SCHEMA_PUB || schema == GCR_RECORD_SCHEMA_SEC)) {
+ record = _gcr_record_new (GCR_RECORD_SCHEMA_FPR, GCR_RECORD_FPR_MAX, ':');
+ _gcr_record_take_raw (record, GCR_RECORD_FPR_FINGERPRINT, fingerprint);
+ g_ptr_array_add (records, record);
+ fingerprint = NULL;
+ }
+
+ g_free (fingerprint);
return TRUE;
}
@@ -520,7 +525,7 @@ parse_user_id (const guchar *beg,
fingerprint = hash_user_id_or_attribute (*at, end);
record = _gcr_record_new (GCR_RECORD_SCHEMA_UID, GCR_RECORD_UID_MAX, ':');
_gcr_record_take_raw (record, GCR_RECORD_UID_FINGERPRINT, fingerprint);
- _gcr_record_set_string (record, GCR_RECORD_UID_NAME, string);
+ _gcr_record_set_string (record, GCR_RECORD_UID_USERID, string);
g_free (string);
g_ptr_array_add (records, record);
@@ -608,11 +613,11 @@ skip_signature_mpis (const guchar **at,
switch (algo) {
/* RSA signature value */
- case OPENPGP_ALGO_RSA:
+ case GCR_OPENPGP_ALGO_RSA:
return read_mpi (at, end, NULL, NULL);
/* DSA values r and s */
- case OPENPGP_ALGO_DSA:
+ case GCR_OPENPGP_ALGO_DSA:
return read_mpi (at, end, NULL, NULL) &&
read_mpi (at, end, NULL, NULL);
default:
@@ -757,7 +762,7 @@ parse_v4_signature_subpacket (const guchar **at,
case OPENPGP_SIG_SIGNER_USERID:
value = g_strndup ((gchar *)*at, end - *at);
- _gcr_record_set_string (record, GCR_RECORD_SIG_NAME, value);
+ _gcr_record_set_string (record, GCR_RECORD_SIG_USERID, value);
g_free (value);
return TRUE;
@@ -1182,7 +1187,7 @@ normalize_key_records (GPtrArray *records)
continue;
}
schema = _gcr_record_get_schema (records->pdata[i]);
- if (schema != GCR_RECORD_SCHEMA_SIG)
+ if (schema != GCR_RECORD_SCHEMA_SIG && schema != GCR_RECORD_SCHEMA_FPR)
_gcr_record_set_char (records->pdata[i], GCR_RECORD_TRUST, trust);
}
}
diff --git a/gcr/gcr-openpgp.h b/gcr/gcr-openpgp.h
index 5ba4267..31fd295 100644
--- a/gcr/gcr-openpgp.h
+++ b/gcr/gcr-openpgp.h
@@ -33,6 +33,14 @@
#include <gck/gck.h>
typedef enum {
+ GCR_OPENPGP_ALGO_RSA = 1,
+ GCR_OPENPGP_ALGO_RSA_E = 2,
+ GCR_OPENPGP_ALGO_RSA_S = 3,
+ GCR_OPENPGP_ALGO_ELG_E = 16,
+ GCR_OPENPGP_ALGO_DSA = 17
+} GcrOpenpgpAlgo;
+
+typedef enum {
GCR_OPENPGP_PARSE_NONE = 0,
GCR_OPENPGP_PARSE_KEYS = 1 << 1,
GCR_OPENPGP_PARSE_NO_RECORDS = 1 << 2,
diff --git a/gcr/gcr-parser.c b/gcr/gcr-parser.c
index 96aedfe..33aaad4 100644
--- a/gcr/gcr-parser.c
+++ b/gcr/gcr-parser.c
@@ -30,6 +30,7 @@
#include "gcr-openpgp.h"
#include "gcr-openssh.h"
#include "gcr-parser.h"
+#include "gcr-record.h"
#include "gcr-types.h"
#include "egg/egg-armor.h"
@@ -292,6 +293,9 @@ parsed_description (GcrParsed *parsed,
case CKO_PUBLIC_KEY:
parsed->description = _("Public Key");
break;
+ case CKO_GCR_GNUPG_RECORDS:
+ parsed->description = _("PGP Key");
+ break;
default:
parsed->description = NULL;
break;
@@ -410,7 +414,7 @@ parsed_fire (GcrParser *self,
GcrParsed *parsed)
{
g_assert (GCR_IS_PARSER (self));
- g_assert (parsed);
+ g_assert (parsed != NULL);
g_assert (parsed == self->pv->parsed);
g_object_notify (G_OBJECT (self), "parsed-description");
@@ -1407,14 +1411,26 @@ on_openpgp_packet (GPtrArray *records,
{
GcrParser *self = GCR_PARSER (user_data);
GcrParsed *parsed;
+ gchar *string;
+
+ /*
+ * If it's an openpgp packet that doesn't contain a key, then
+ * just ignore it here.
+ */
+ if (records->len == 0)
+ return;
parsed = push_parsed (self);
/* All we can do is the packet bounds */
parsing_block (parsed, GCR_FORMAT_OPENPGP_PACKET, outer, n_outer);
- parsing_object (parsed, CKO_DATA);
+ parsing_object (parsed, CKO_GCR_GNUPG_RECORDS);
+ string = _gcr_records_format (records);
+ parsed_attribute (parsed, CKA_VALUE, string, strlen (string));
parsed_fire (self, parsed);
pop_parsed (self, parsed);
+
+ g_free (string);
}
static gint
diff --git a/gcr/gcr-record.c b/gcr/gcr-record.c
index 612dc86..c543e97 100644
--- a/gcr/gcr-record.c
+++ b/gcr/gcr-record.c
@@ -147,22 +147,6 @@ _gcr_record_format (GcrRecord *record)
return g_string_free (string, FALSE);
}
-gchar *
-_gcr_records_format (GPtrArray *records)
-{
- GString *string;
- guint i;
-
- g_return_val_if_fail (records, NULL);
-
- string = g_string_new ("");
- for (i = 0; i < records->len; i++) {
- print_record_to_string (records->pdata[i], string);
- g_string_append_c (string, '\n');
- }
- return g_string_free (string, FALSE);
-}
-
GcrRecord *
_gcr_record_new (GQuark schema,
guint n_columns,
@@ -253,22 +237,6 @@ _gcr_record_parse_spaces (const gchar *line, gssize n_line)
return take_and_parse_internal (record_block_new (line, n_line), ' ', FALSE);
}
-GcrRecord*
-_gcr_record_find (GPtrArray *records, GQuark schema)
-{
- guint i;
-
- g_return_val_if_fail (records, NULL);
- g_return_val_if_fail (schema, NULL);
-
- for (i = 0; i < records->len; i++) {
- if (schema == _gcr_record_get_schema (records->pdata[i]))
- return records->pdata[i];
- }
-
- return NULL;
-}
-
guint
_gcr_record_get_count (GcrRecord *record)
{
@@ -622,60 +590,35 @@ _gcr_record_set_ulong (GcrRecord *record,
record_block_take (escaped, strlen (escaped)));
}
-gboolean
+GDateTime *
_gcr_record_get_date (GcrRecord *record,
- guint column,
- gulong *value)
+ guint column)
{
const gchar *raw;
gulong result;
gchar *end = NULL;
struct tm tm;
- g_return_val_if_fail (record, FALSE);
+ g_return_val_if_fail (record, NULL);
raw = _gcr_record_get_raw (record, column);
if (raw == NULL)
- return FALSE;
+ return NULL;
/* Try to parse as a number */
result = strtoul (raw, &end, 10);
+ if (end != NULL && end[0] == '\0')
+ return g_date_time_new_from_unix_utc (result);
+
+ /* Try to parse as a date */
+ memset (&tm, 0, sizeof (tm));
+ end = strptime (raw, "%Y-%m-%d", &tm);
if (!end || end[0]) {
- /* Try to parse as a date */
- memset (&tm, 0, sizeof (tm));
- end = strptime (raw, "%Y-%m-%d", &tm);
- if (!end || end[0]) {
- _gcr_debug ("invalid date value: %s", raw);
- return FALSE;
- }
- result = timegm (&tm);
+ _gcr_debug ("invalid date value: %s", raw);
+ return NULL;
}
- if (value)
- *value = result;
- return TRUE;
-}
-
-void
-_gcr_record_set_date (GcrRecord *record,
- guint column,
- gulong value)
-{
- GcrRecordBlock *block;
- time_t time;
- struct tm tm;
- gsize len;
-
- g_return_if_fail (record != NULL);
- g_return_if_fail (column < record->n_columns);
-
- time = value;
- gmtime_r (&time, &tm);
- block = record_block_new (NULL, 20);
- len = strftime (block->value, 20, "%Y-%m-%d", &tm);
- g_assert (len < 20);
-
- record_take_column (record, column, block);
+ return g_date_time_new_utc (tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 0, 0, 0);
}
/**
@@ -799,3 +742,70 @@ _gcr_record_get_schema (GcrRecord *record)
return g_quark_try_string (value);
return 0;
}
+
+GcrRecord *
+_gcr_records_find (GPtrArray *records,
+ GQuark schema)
+{
+ guint i;
+
+ g_return_val_if_fail (records, NULL);
+ g_return_val_if_fail (schema, NULL);
+
+ for (i = 0; i < records->len; i++) {
+ if (schema == _gcr_record_get_schema (records->pdata[i]))
+ return records->pdata[i];
+ }
+
+ return NULL;
+}
+
+gchar *
+_gcr_records_format (GPtrArray *records)
+{
+ GString *string;
+ guint i;
+
+ g_return_val_if_fail (records, NULL);
+
+ string = g_string_new ("");
+ for (i = 0; i < records->len; i++) {
+ print_record_to_string (records->pdata[i], string);
+ g_string_append_c (string, '\n');
+ }
+ return g_string_free (string, FALSE);
+}
+
+GPtrArray *
+_gcr_records_parse_colons (gconstpointer data,
+ gssize n_data)
+{
+ GPtrArray *result = NULL;
+ GcrRecordBlock *block;
+ GcrRecord *record;
+ gchar **lines;
+ guint i;
+
+ lines = g_strsplit (data, "\n", n_data);
+ result = g_ptr_array_new_with_free_func (_gcr_record_free);
+
+ for (i = 0; lines[i] != NULL; i++) {
+ block = record_block_take (lines[i], strlen (lines[i]));
+ record = take_and_parse_internal (block, ':', TRUE);
+ if (record == NULL) {
+ g_ptr_array_unref (result);
+ result = NULL;
+ break;
+ }
+ g_ptr_array_add (result, record);
+ }
+
+ /* Free any not done */
+ for (; lines[i] != NULL; i++)
+ g_free (lines[i]);
+
+ /* Individual lines already freed */
+ g_free (lines);
+
+ return result;
+}
diff --git a/gcr/gcr-record.h b/gcr/gcr-record.h
index a9bf6e0..3915375 100644
--- a/gcr/gcr-record.h
+++ b/gcr/gcr-record.h
@@ -87,7 +87,8 @@ typedef enum {
* fpr:::::::::ECAF7590EB3443B5C7CF3ACB6C7EE1B8621CC013:
*/
typedef enum {
- GCR_RECORD_FPR_FINGERPRINT = 9
+ GCR_RECORD_FPR_FINGERPRINT = 9,
+ GCR_RECORD_FPR_MAX = 10
} GcrRecordFprColumns;
/*
@@ -118,8 +119,9 @@ typedef enum {
*/
typedef enum {
GCR_RECORD_UID_TIMESTAMP = 5,
+ GCR_RECORD_UID_EXPIRY = 6,
GCR_RECORD_UID_FINGERPRINT = 7,
- GCR_RECORD_UID_NAME = 9,
+ GCR_RECORD_UID_USERID = 9,
GCR_RECORD_UID_MAX = 10,
} GcrRecordUidColumns;
@@ -133,7 +135,7 @@ typedef enum {
GCR_RECORD_SIG_KEYID = 4,
GCR_RECORD_SIG_TIMESTAMP = 5,
GCR_RECORD_SIG_EXPIRY = 6,
- GCR_RECORD_SIG_NAME = 9,
+ GCR_RECORD_SIG_USERID = 9,
GCR_RECORD_SIG_CLASS = 10,
GCR_RECORD_SIG_MAX = 11,
} GcrRecordSigColumns;
@@ -196,16 +198,8 @@ GcrRecord* _gcr_record_parse_spaces (const gchar *line,
gchar * _gcr_record_format (GcrRecord *record);
-gchar * _gcr_records_format (GPtrArray *records);
-
void _gcr_record_free (gpointer record);
-GcrRecord* _gcr_record_find (GPtrArray *records,
- GQuark schema);
-
-GcrRecord* _gcr_record_rfind (GPtrArray *records,
- GQuark schema);
-
guint _gcr_record_get_count (GcrRecord *record);
gchar _gcr_record_get_char (GcrRecord *record,
@@ -238,13 +232,8 @@ void _gcr_record_set_ulong (GcrRecord *record,
guint column,
gulong value);
-gboolean _gcr_record_get_date (GcrRecord *record,
- guint column,
- gulong *value);
-
-void _gcr_record_set_date (GcrRecord *record,
- guint column,
- gulong value);
+GDateTime * _gcr_record_get_date (GcrRecord *record,
+ guint column);
gpointer _gcr_record_get_base64 (GcrRecord *record,
guint column,
@@ -268,6 +257,14 @@ void _gcr_record_take_raw (GcrRecord *record,
GQuark _gcr_record_get_schema (GcrRecord *record);
+GPtrArray * _gcr_records_parse_colons (gconstpointer data,
+ gssize n_data);
+
+gchar * _gcr_records_format (GPtrArray *records);
+
+GcrRecord * _gcr_records_find (GPtrArray *records,
+ GQuark schema);
+
G_END_DECLS
#endif /* GCR_RECORD_H */
diff --git a/gcr/gcr-renderer.c b/gcr/gcr-renderer.c
index fd50936..dc542a2 100644
--- a/gcr/gcr-renderer.c
+++ b/gcr/gcr-renderer.c
@@ -25,6 +25,7 @@
#include "gcr-renderer.h"
#include "gcr-certificate-renderer.h"
+#include "gcr-gnupg-renderer.h"
#include "gcr-key-renderer.h"
#include "gck/gck.h"
@@ -290,4 +291,5 @@ gcr_renderer_register_well_known (void)
{
g_type_class_unref (g_type_class_ref (GCR_TYPE_CERTIFICATE_RENDERER));
g_type_class_unref (g_type_class_ref (GCR_TYPE_KEY_RENDERER));
+ g_type_class_unref (g_type_class_ref (GCR_TYPE_GNUPG_RENDERER));
}
diff --git a/gcr/gcr-types.h b/gcr/gcr-types.h
index 1cade80..7ac1c38 100644
--- a/gcr/gcr-types.h
+++ b/gcr/gcr-types.h
@@ -87,6 +87,16 @@ typedef enum {
GCR_FORMAT_PEM_PRIVATE_KEY
} GcrDataFormat;
+/*
+ * Special PKCS#11 style attributes that we use internally in GCR.
+ * These are used by GcrParser the most
+ */
+
+enum {
+ /* An object class representing GcrRecord/gnupg-colons style data */
+ CKO_GCR_GNUPG_RECORDS = (CKO_VENDOR_DEFINED | 0x47435200UL /* GCR0 */)
+};
+
G_END_DECLS
#endif /* GCRTYPES_H_ */
diff --git a/gcr/tests/test-gnupg-collection.c b/gcr/tests/test-gnupg-collection.c
index 686e80f..c8304a7 100644
--- a/gcr/tests/test-gnupg-collection.c
+++ b/gcr/tests/test-gnupg-collection.c
@@ -171,7 +171,7 @@ test_load (Test *test, gconstpointer unused)
/* Phillip R. Zimmerman's key should have a photo */
key = g_hash_table_lookup (test->keys, "C7463639B2D7795E");
g_assert (GCR_IS_GNUPG_KEY (key));
- record = _gcr_record_find (_gcr_gnupg_key_get_public_records (key), GCR_RECORD_SCHEMA_XA1);
+ record = _gcr_records_find (_gcr_gnupg_key_get_public_records (key), GCR_RECORD_SCHEMA_XA1);
g_assert (record);
}
diff --git a/gcr/tests/test-gnupg-key.c b/gcr/tests/test-gnupg-key.c
index 152a0c0..5900804 100644
--- a/gcr/tests/test-gnupg-key.c
+++ b/gcr/tests/test-gnupg-key.c
@@ -24,6 +24,7 @@
#include "gcr/gcr-record.h"
#include "gcr/gcr-gnupg-key.h"
+#include "gcr/gcr-gnupg-records.h"
#include "egg/egg-testing.h"
@@ -160,7 +161,7 @@ test_keyid_for_records (Test *test, gconstpointer unused)
{
const gchar *keyid;
- keyid = _gcr_gnupg_key_get_keyid_for_records (test->records);
+ keyid = _gcr_gnupg_records_get_keyid (test->records);
g_assert_cmpstr (keyid, ==, "6C7EE1B8621CC013");
}
diff --git a/gcr/tests/test-openpgp.c b/gcr/tests/test-openpgp.c
index 4c8c1d0..be41f40 100644
--- a/gcr/tests/test-openpgp.c
+++ b/gcr/tests/test-openpgp.c
@@ -43,9 +43,11 @@ typedef struct {
static const gchar *werner_koch_records[] = {
"pub:e:1024:17:68B7AB8957548DCD:899816990:1136043547::o:::sca:\n"
+ "fpr:::::::::6BD9050FD8FC941B43412DCC68B7AB8957548DCD:\n"
"uid:e::::1102866526::B712A25DC2ABEF1579696C2925859931078C2C3E::Werner Koch (gnupg sig) <dd9jn gnu org>:\n",
"pub:e:1024:17:5DE249965B0358A2:921520361:1247335656::o:::sc:\n"
+ "fpr:::::::::A4D94E92B0986AB5EE9DCD755DE249965B0358A2:\n"
"uid:e::::1113145458::F5B5738FAFB7543A01BAB31A6D767FBC789FF8A8::Werner Koch <wk gnupg org>:\n"
"uid:e::::1113145466::60095F7DAD08129CCE39E15BEB6BBE21937E3AA6::Werner Koch <wk g10code com>:\n"
"uid:e::::921520362::392B892CF897AD0F03EB26343C4C20A48B36513E::Werner Koch:\n"
@@ -55,6 +57,7 @@ static const gchar *werner_koch_records[] = {
"sub:e:2048:1:35E52D69C3680A6E:1136137762:1199123362:::::e:\n",
"pub:e:1024:1:53B620D01CE0C630:1136130759:1230738759::o:::sc:\n"
+ "fpr:::::::::7B96D396E6471601754BE4DB53B620D01CE0C630:\n"
"uid:e::::1136130760::142B958D9816ECF810DBB83BD257E5C7DB36C99A::Werner Koch (dist sig) <dd9jn gnu org>:\n",
NULL
@@ -62,10 +65,12 @@ static const gchar *werner_koch_records[] = {
static const gchar *werner_sig_records[] = {
"pub:e:1024:17:68B7AB8957548DCD:899816990:1136043547::o:::sca:\n"
+ "fpr:::::::::6BD9050FD8FC941B43412DCC68B7AB8957548DCD:\n"
"uid:e::::1102866526::B712A25DC2ABEF1579696C2925859931078C2C3E::Werner Koch (gnupg sig) <dd9jn gnu org>:\n"
"sig:::17:68B7AB8957548DCD:1102866526:::::13x:\n",
"pub:e:1024:17:5DE249965B0358A2:921520361:1247335656::o:::sc:\n"
+ "fpr:::::::::A4D94E92B0986AB5EE9DCD755DE249965B0358A2:\n"
"uid:e::::1113145458::F5B5738FAFB7543A01BAB31A6D767FBC789FF8A8::Werner Koch <wk gnupg org>:\n"
"sig:::17:5DE249965B0358A2:1113145458:::::13x:\n"
"uid:e::::1113145466::60095F7DAD08129CCE39E15BEB6BBE21937E3AA6::Werner Koch <wk g10code com>:\n"
@@ -82,6 +87,7 @@ static const gchar *werner_sig_records[] = {
"sig:::17:5DE249965B0358A2:1136137762:::::18x:\n",
"pub:e:1024:1:53B620D01CE0C630:1136130759:1230738759::o:::sc:\n"
+ "fpr:::::::::7B96D396E6471601754BE4DB53B620D01CE0C630:\n"
"uid:e::::1136130760::142B958D9816ECF810DBB83BD257E5C7DB36C99A::Werner Koch (dist sig) <dd9jn gnu org>:\n"
"sig:::1:53B620D01CE0C630:1136130760:::::13x:\n",
@@ -90,18 +96,22 @@ static const gchar *werner_sig_records[] = {
static const gchar *pubring_records[] = {
"pub:o:2048:1:4842D952AFC000FD:1305189489:::o:::scSCE:\n"
+ "fpr:::::::::61A6EA3E0115080227A32EC94842D952AFC000FD:\n"
"uid:o::::1305189489::D449F1605254754B0BBFA424FC34E50609103BBB::Test Number 1 (unlimited) <test-number-1 example com>:\n"
"uid:o::::1305189849::D0A8FA7B15DC4BE3F8F03A49C372F2718C78AFC0::Dr. Strangelove <lovingbomb example com>:\n"
"sub:o:2048:1:4852132BBED15014:1305189489::::::e:\n",
"pub:e:1024:1:268FEE686262C395:1305189628:1305276028::o:::sc:\n"
+ "fpr:::::::::A4853C22EA82C8ADC6692751268FEE686262C395:\n"
"uid:e::::1305189628::2E9D48BD771DA765D2B48A0233D0E8F393F6E839::Test Number 2 (all gone) <test-number-2 example com>:\n"
"sub:e:1024:1:C5877FABF4772E4F:1305189628:1305276028:::::e:\n",
"pub:e:1024:17:68B7AB8957548DCD:899816990:1136043547::o:::sca:\n"
+ "fpr:::::::::6BD9050FD8FC941B43412DCC68B7AB8957548DCD:\n"
"uid:e::::1102866526::B712A25DC2ABEF1579696C2925859931078C2C3E::Werner Koch (gnupg sig) <dd9jn gnu org>:\n",
"pub:e:1024:17:5DE249965B0358A2:921520361:1247335656::o:::sc:\n"
+ "fpr:::::::::A4D94E92B0986AB5EE9DCD755DE249965B0358A2:\n"
"uid:e::::1113145458::F5B5738FAFB7543A01BAB31A6D767FBC789FF8A8::Werner Koch <wk gnupg org>:\n"
"uid:e::::1113145466::60095F7DAD08129CCE39E15BEB6BBE21937E3AA6::Werner Koch <wk g10code com>:\n"
"uid:e::::921520362::392B892CF897AD0F03EB26343C4C20A48B36513E::Werner Koch:\n"
@@ -111,6 +121,7 @@ static const gchar *pubring_records[] = {
"sub:e:2048:1:35E52D69C3680A6E:1136137762:1199123362:::::e:\n",
"pub:o:1024:17:C7463639B2D7795E:978642983:::o:::scSCE:\n"
+ "fpr:::::::::055FC78F112193492C4F37AFC7463639B2D7795E:\n"
"rvk:o::17::::::3FC732041D23E9EA66DDB5009C9DBC21DF74DC61:80:\n"
"uid:o::::978642983::44C6F00AAE524A8955CAB76F2BB16126530BB203::Philip R. Zimmermann <prz mit edu>:\n"
"uid:o::::978643127::BD93DF0D0D564E85F73ECBECFFB1B5BA5FF2838D::Philip R. Zimmermann <prz acm org>:\n"
@@ -120,15 +131,18 @@ static const gchar *pubring_records[] = {
"sub:o:3072:16:C4EB1C56A8E92834:978642983::::::e:\n",
"pub:o:4096:1:DB698D7199242560:1012189561:::o:::scSCEA:\n"
+ "fpr:::::::::7D92FD313AB6F3734CC59CA1DB698D7199242560:\n"
"uid:o::::1012189561::0E5FC22DD5518890217F20F1FF832597932B46C1::David M. Shaw <dshaw jabberwocky com>:\n"
"sub:o:2048:16:AE2827D11643B926:1012189956:1327549956:::::e:\n"
"sub:o:1024:17:E2665C8749E1CBC9:1012190171:1327550171:::::sca:\n",
"pub:o:2048:1:9710B89BCA57AD7C:1102303986:::o:::scSC:\n"
+ "fpr:::::::::50BB6FFC9719DFD2BEBB04C69710B89BCA57AD7C:\n"
"uid:o::::1112650864::A96F758EFD5D67EA9450860C7D15A96DAA1B40E2::PGP Global Directory Verification Key:\n"
"uat:o::::1112650864::83B0B68B95892BBCE32F04BA0FBAC6CEAD4EDE49::1 3422:\n",
"pub:e:1024:1:53B620D01CE0C630:1136130759:1230738759::o:::sc:\n"
+ "fpr:::::::::7B96D396E6471601754BE4DB53B620D01CE0C630:\n"
"uid:e::::1136130760::142B958D9816ECF810DBB83BD257E5C7DB36C99A::Werner Koch (dist sig) <dd9jn gnu org>:\n",
NULL
@@ -136,11 +150,13 @@ static const gchar *pubring_records[] = {
static const gchar *secring_records[] = {
"sec::2048:1:4842D952AFC000FD:1305189489::::::::::\n"
+ "fpr:::::::::61A6EA3E0115080227A32EC94842D952AFC000FD:\n"
"uid:::::::D449F1605254754B0BBFA424FC34E50609103BBB::Test Number 1 (unlimited) <test-number-1 example com>:\n"
"uid:::::::D0A8FA7B15DC4BE3F8F03A49C372F2718C78AFC0::Dr. Strangelove <lovingbomb example com>:\n"
"ssb::2048:1:4852132BBED15014:1305189489::::::::::\n",
"sec::1024:1:268FEE686262C395:1305189628:1305276028:::::::::\n"
+ "fpr:::::::::A4853C22EA82C8ADC6692751268FEE686262C395:\n"
"uid:::::::2E9D48BD771DA765D2B48A0233D0E8F393F6E839::Test Number 2 (all gone) <test-number-2 example com>:\n"
"ssb::1024:1:C5877FABF4772E4F:1305189628::::::::::\n",
diff --git a/gcr/tests/test-record.c b/gcr/tests/test-record.c
index 4a18d44..cfb6593 100644
--- a/gcr/tests/test-record.c
+++ b/gcr/tests/test-record.c
@@ -128,10 +128,10 @@ test_find (void)
uid = _gcr_record_parse_colons ("uid:two", -1);
g_ptr_array_add (records, uid);
- check = _gcr_record_find (records, GCR_RECORD_SCHEMA_PUB);
+ check = _gcr_records_find (records, GCR_RECORD_SCHEMA_PUB);
g_assert (check == pub);
- check = _gcr_record_find (records, GCR_RECORD_SCHEMA_UID);
+ check = _gcr_records_find (records, GCR_RECORD_SCHEMA_UID);
g_assert (check == uid);
g_ptr_array_unref (records);
diff --git a/po/POTFILES.in b/po/POTFILES.in
index a27d835..d10485d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -25,6 +25,7 @@ gcr/gcr-failure-renderer.c
[type: gettext/glade]gcr/gcr-import-dialog.ui
gcr/gcr-gnupg-key.c
gcr/gcr-gnupg-process.c
+gcr/gcr-gnupg-renderer.c
gcr/gcr-importer.c
gcr/gcr-library.c
gcr/gcr-key-renderer.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]