[gnome-keyring] gcr: A rudimentary Gnupg Collection implementation.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring] gcr: A rudimentary Gnupg Collection implementation.
- Date: Wed, 20 Apr 2011 04:35:50 +0000 (UTC)
commit 82700571fd647598dc2258b04ec0e32650f55b2e
Author: Stef Walter <stefw collabora co uk>
Date: Fri Apr 15 19:22:12 2011 +0200
gcr: A rudimentary Gnupg Collection implementation.
* Loads basic GPG keys.
* No splitting of UIDs yet.
* No monitoring yet.
https://bugzilla.gnome.org/show_bug.cgi?id=647885
.gitignore | 5 +
configure.in | 6 +
gcr/Makefile.am | 4 +
gcr/gcr-colons.c | 154 +++++++++
gcr/gcr-colons.h | 74 +++++
gcr/gcr-gnupg-collection.c | 480 +++++++++++++++++++++++++++++
gcr/gcr-gnupg-collection.h | 69 ++++
gcr/gcr-gnupg-key.c | 249 +++++++++++++++
gcr/gcr-gnupg-key.h | 75 +++++
gcr/gcr-util.c | 55 ++++
gcr/gcr-util.h | 41 +++
gcr/tests/Makefile.am | 10 +-
gcr/tests/files/gnupg-homedir/pubring.gpg | Bin 0 -> 19689 bytes
gcr/tests/files/gnupg-homedir/trustdb.gpg | Bin 0 -> 1200 bytes
gcr/tests/frob-gnupg-selector.c | 79 +++++
gcr/tests/test-colons.c | 193 ++++++++++++
gcr/tests/test-gnupg-collection.c | 82 +++++
gcr/tests/test-gnupg-key.c | 132 ++++++++
gcr/tests/test-util.c | 112 +++++++
19 files changed, 1818 insertions(+), 2 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index cae7040..af16c8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -106,14 +106,19 @@ run-tests
/gcr/tests/frob-certificate
/gcr/tests/frob-key
+/gcr/tests/frob-gnupg-selector
/gcr/tests/frob-selector
/gcr/tests/frob-unlock-options
/gcr/tests/test-certificate
/gcr/tests/test-certificate-chain
+/gcr/tests/test-colons
+/gcr/tests/test-gnupg-collection
+/gcr/tests/test-gnupg-key
/gcr/tests/test-parser
/gcr/tests/test-pkcs11-certificate
/gcr/tests/test-simple-certificate
/gcr/tests/test-trust
+/gcr/tests/test-util
/pkcs11/gkm/tests/test-attributes
/pkcs11/gkm/tests/test-credential
diff --git a/configure.in b/configure.in
index dc6fe19..7e145e2 100644
--- a/configure.in
+++ b/configure.in
@@ -359,6 +359,12 @@ fi
AM_CONDITIONAL(WITH_GPG, test "$enable_gpg_agent" != "no")
# --------------------------------------------------------------------
+# GPG support
+
+AC_PATH_PROGS([GNUPG], [gpg gpg2], ["gpg"])
+AC_DEFINE_UNQUOTED([GPG_EXECUTABLE], ["$GNUPG"], [Path to gpg executable.])
+
+# --------------------------------------------------------------------
# Trusted Root Certificates Directory
#
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index 532462c..b2fe94a 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -65,10 +65,13 @@ LIB_SOURCES = \
gcr-certificate-widget.c gcr-certificate-widget.h \
gcr-collection.c gcr-collection.h \
gcr-collection-model.c gcr-collection-model.h \
+ gcr-colons.c gcr-colons.h \
gcr-debug.c gcr-debug.h \
gcr-display-scrolled.c gcr-display-scrolled.h \
gcr-comparable.c gcr-comparable.h \
gcr-display-view.c gcr-display-view.h \
+ gcr-gnupg-collection.c gcr-gnupg-collection.h \
+ gcr-gnupg-key.c gcr-gnupg-key.h \
gcr-icons.c gcr-icons.h \
gcr-import-dialog.c gcr-import-dialog.h \
gcr-importer.c gcr-importer.h \
@@ -86,6 +89,7 @@ LIB_SOURCES = \
gcr-types.h \
gcr-unlock-options.h \
gcr-unlock-options-widget.c gcr-unlock-options-widget.h \
+ gcr-util.c gcr-util.h \
gcr-viewer.c gcr-viewer.h \
$(BUILT_SOURCES)
diff --git a/gcr/gcr-colons.c b/gcr/gcr-colons.c
new file mode 100644
index 0000000..4a54934
--- /dev/null
+++ b/gcr/gcr-colons.c
@@ -0,0 +1,154 @@
+/*
+ * gnome-keyring
+ *
+ * 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-colons.h"
+
+#include <string.h>
+
+#define MAX_COLUMNS 32
+
+struct _GcrColons {
+ gchar *data;
+ gpointer columns[MAX_COLUMNS];
+ guint n_columns;
+};
+
+GcrColons*
+_gcr_colons_parse (const gchar *line, gssize n_line)
+{
+ GcrColons *result;
+ gchar *p;
+
+ g_return_val_if_fail (line, NULL);
+ if (n_line < 0)
+ n_line = strlen (line);
+
+ result = g_slice_new0 (GcrColons);
+ result->data = g_strndup (line, n_line);
+
+ p = result->data;
+ for (;;) {
+ if (result->n_columns >= MAX_COLUMNS) {
+ _gcr_colons_free (result);
+ return NULL;
+ }
+
+ result->columns[result->n_columns] = p;
+ result->n_columns++;
+
+ p = strchr (p, ':');
+ if (p == NULL)
+ break;
+ p[0] = '\0';
+ p++;
+ }
+
+ return result;
+}
+
+GcrColons*
+_gcr_colons_find (GPtrArray *dataset, GQuark schema)
+{
+ guint i;
+
+ g_return_val_if_fail (dataset, NULL);
+ g_return_val_if_fail (schema, NULL);
+
+ for (i = 0; i < dataset->len; i++) {
+ if (schema == _gcr_colons_get_schema (dataset->pdata[i]))
+ return dataset->pdata[i];
+ }
+
+ return NULL;
+}
+
+gchar*
+_gcr_colons_get_string (GcrColons *colons, guint column)
+{
+ const gchar *value;
+ gchar *text;
+ gchar *converted;
+
+ g_return_val_if_fail (colons, NULL);
+
+ value = _gcr_colons_get_raw (colons, column);
+ if (!value)
+ return NULL;
+ text = g_strcompress (value);
+ if (g_utf8_validate (text, -1, NULL))
+ return text;
+
+ converted = g_convert (text, -1, "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
+ g_free (text);
+
+ if (!converted)
+ g_return_val_if_reached (NULL);
+
+ return converted;
+}
+
+const gchar*
+_gcr_colons_get_raw (GcrColons *colons, guint column)
+{
+ g_return_val_if_fail (colons, NULL);
+
+ if (column >= colons->n_columns)
+ return NULL;
+
+ return colons->columns[column];
+}
+
+void
+_gcr_colons_free (gpointer colons)
+{
+ if (!colons)
+ return;
+
+ g_free (((GcrColons*)colons)->data);
+ g_slice_free (GcrColons, colons);
+}
+
+GQuark
+_gcr_colons_get_schema (GcrColons *colons)
+{
+ const gchar *value;
+
+ value = _gcr_colons_get_raw (colons, GCR_COLONS_SCHEMA);
+ if (value != NULL)
+ return g_quark_try_string (value);
+ return 0;
+}
+
+GQuark
+_gcr_colons_get_schema_uid_quark (void)
+{
+ return g_quark_from_static_string ("uid");
+}
+
+GQuark
+_gcr_colons_get_schema_pub_quark (void)
+{
+ return g_quark_from_static_string ("pub");
+}
diff --git a/gcr/gcr-colons.h b/gcr/gcr-colons.h
new file mode 100644
index 0000000..b8a055e
--- /dev/null
+++ b/gcr/gcr-colons.h
@@ -0,0 +1,74 @@
+/*
+ * gnome-keyring
+ *
+ * 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_COLONS_H
+#define GCR_GNUPG_COLONS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define GCR_COLONS_SCHEMA_UID _gcr_colons_get_schema_uid_quark ()
+#define GCR_COLONS_SCHEMA_PUB _gcr_colons_get_schema_pub_quark ()
+
+typedef enum {
+ GCR_COLONS_SCHEMA = 0
+} GcrColonColumns;
+
+typedef enum {
+ GCR_COLONS_PUB_KEYID = 4
+} GcrColonPubColumns;
+
+typedef enum {
+ GCR_COLONS_UID_NAME = 9
+} GcrColonUidColumns;
+
+typedef struct _GcrColons GcrColons;
+
+GcrColons* _gcr_colons_parse (const gchar *line,
+ gssize n_line);
+
+void _gcr_colons_free (gpointer colons);
+
+GcrColons* _gcr_colons_find (GPtrArray *dataset,
+ GQuark schema);
+
+gchar* _gcr_colons_get_string (GcrColons *colons,
+ guint column);
+
+const gchar* _gcr_colons_get_raw (GcrColons *colons,
+ guint column);
+
+GQuark _gcr_colons_get_schema (GcrColons *colons);
+
+GQuark _gcr_colons_get_schema_uid_quark (void) G_GNUC_CONST;
+
+GQuark _gcr_colons_get_schema_pub_quark (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* GCR_GNUPG_COLONS_H */
diff --git a/gcr/gcr-gnupg-collection.c b/gcr/gcr-gnupg-collection.c
new file mode 100644
index 0000000..812a35f
--- /dev/null
+++ b/gcr/gcr-gnupg-collection.c
@@ -0,0 +1,480 @@
+/*
+ * gnome-keyring
+ *
+ * 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-colons.h"
+#include "gcr-collection.h"
+#include "gcr-gnupg-collection.h"
+#include "gcr-gnupg-key.h"
+#include "gcr-internal.h"
+#include "gcr-util.h"
+
+#include "egg/egg-spawn.h"
+
+#include <sys/wait.h>
+#include <string.h>
+
+enum {
+ PROP_0,
+ PROP_DIRECTORY,
+ PROP_MAIN_CONTEXT
+};
+
+struct _GcrGnupgCollectionPrivate {
+ GHashTable *items;
+ gchar *directory;
+};
+
+static void _gcr_collection_iface (GcrCollectionIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GcrGnupgCollection, _gcr_gnupg_collection, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, _gcr_collection_iface)
+);
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+_gcr_gnupg_collection_init (GcrGnupgCollection *self)
+{
+ self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_GNUPG_COLLECTION,
+ GcrGnupgCollectionPrivate);
+
+ self->pv->items = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_object_unref);
+}
+
+static void
+_gcr_gnupg_collection_set_property (GObject *obj, guint prop_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ GcrGnupgCollection *self = GCR_GNUPG_COLLECTION (obj);
+
+ switch (prop_id) {
+ case PROP_DIRECTORY:
+ g_return_if_fail (!self->pv->directory);
+ self->pv->directory = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gcr_gnupg_collection_get_property (GObject *obj, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GcrGnupgCollection *self = GCR_GNUPG_COLLECTION (obj);
+
+ switch (prop_id) {
+ case PROP_DIRECTORY:
+ g_value_set_string (value, self->pv->directory);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+static void
+_gcr_gnupg_collection_dispose (GObject *obj)
+{
+ GcrGnupgCollection *self = GCR_GNUPG_COLLECTION (obj);
+
+ g_hash_table_remove_all (self->pv->items);
+
+ G_OBJECT_CLASS (_gcr_gnupg_collection_parent_class)->dispose (obj);
+}
+
+static void
+_gcr_gnupg_collection_finalize (GObject *obj)
+{
+ GcrGnupgCollection *self = GCR_GNUPG_COLLECTION (obj);
+
+ g_assert (self->pv->items);
+ g_assert (g_hash_table_size (self->pv->items) == 0);
+ g_hash_table_destroy (self->pv->items);
+ self->pv->items = NULL;
+
+ g_free (self->pv->directory);
+ self->pv->directory = NULL;
+
+ G_OBJECT_CLASS (_gcr_gnupg_collection_parent_class)->finalize (obj);
+}
+
+static void
+_gcr_gnupg_collection_class_init (GcrGnupgCollectionClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->get_property = _gcr_gnupg_collection_get_property;
+ gobject_class->set_property = _gcr_gnupg_collection_set_property;
+ gobject_class->dispose = _gcr_gnupg_collection_dispose;
+ gobject_class->finalize = _gcr_gnupg_collection_finalize;
+
+ g_object_class_install_property (gobject_class, PROP_DIRECTORY,
+ g_param_spec_string ("directory", "Directory", "Gnupg Directory",
+ NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (gobject_class, sizeof (GcrGnupgCollectionPrivate));
+ _gcr_initialize ();
+}
+
+static guint
+gcr_gnupg_collection_real_get_length (GcrCollection *coll)
+{
+ GcrGnupgCollection *self = GCR_GNUPG_COLLECTION (coll);
+ return g_hash_table_size (self->pv->items);
+}
+
+static GList*
+gcr_gnupg_collection_real_get_objects (GcrCollection *coll)
+{
+ GcrGnupgCollection *self = GCR_GNUPG_COLLECTION (coll);
+ return g_hash_table_get_keys (self->pv->items);
+}
+
+static void
+_gcr_collection_iface (GcrCollectionIface *iface)
+{
+ iface->get_length = gcr_gnupg_collection_real_get_length;
+ iface->get_objects = gcr_gnupg_collection_real_get_objects;
+}
+
+GcrCollection*
+_gcr_gnupg_collection_new (const gchar *directory)
+{
+ return g_object_new (GCR_TYPE_GNUPG_COLLECTION,
+ "directory", directory,
+ NULL);
+}
+
+typedef struct {
+ GcrGnupgCollection *collection;
+ GPtrArray *dataset;
+ guint spawn_sig;
+ guint child_sig;
+ GPid gnupg_pid;
+ GString *out_data;
+ GString *err_data;
+ GHashTable *difference;
+} GcrGnupgCollectionLoad;
+
+static void
+_gcr_gnupg_collection_load_free (gpointer data)
+{
+ GcrGnupgCollectionLoad *load = data;
+ g_assert (load);
+
+ g_ptr_array_unref (load->dataset);
+ g_string_free (load->err_data, TRUE);
+ g_string_free (load->out_data, TRUE);
+ g_hash_table_destroy (load->difference);
+ g_object_unref (load->collection);
+
+ if (load->spawn_sig)
+ g_source_remove (load->spawn_sig);
+ if (load->child_sig)
+ g_source_remove (load->child_sig);
+ if (load->gnupg_pid) {
+ kill (load->gnupg_pid, SIGTERM);
+ g_spawn_close_pid (load->gnupg_pid);
+ }
+ g_slice_free (GcrGnupgCollectionLoad, load);
+}
+
+static void
+process_dataset_as_key (GcrGnupgCollectionLoad *load)
+{
+ const gchar *keyid;
+ GPtrArray *dataset;
+ GcrGnupgKey *key;
+
+ g_assert (load->dataset->len);
+
+ dataset = load->dataset;
+ load->dataset = g_ptr_array_new_with_free_func (_gcr_colons_free);
+
+ keyid = _gcr_gnupg_key_get_keyid_for_colons (dataset);
+ if (keyid) {
+ /* Note that we've seen this keyid */
+ g_hash_table_remove (load->difference, keyid);
+
+ key = g_hash_table_lookup (load->collection->pv->items, keyid);
+
+ /* Already have this key, just update */
+ if (key) {
+ _gcr_gnupg_key_set_dataset (key, dataset);
+
+ /* Add a new key */
+ } else {
+ key = _gcr_gnupg_key_new (dataset);
+ g_hash_table_insert (load->collection->pv->items, g_strdup (keyid), key);
+ gcr_collection_emit_added (GCR_COLLECTION (load->collection), G_OBJECT (key));
+ }
+
+ } else {
+ g_warning ("parsed gnupg data had no keyid");
+ }
+
+ g_ptr_array_unref (dataset);
+}
+
+static void
+on_line_parse_output (const gchar *line, gpointer user_data)
+{
+ GcrGnupgCollectionLoad *load = user_data;
+ GcrColons *colons;
+ GQuark schema;
+
+ colons = _gcr_colons_parse (line, -1);
+ if (!colons) {
+ g_warning ("invalid gnupg output line: %s", line);
+ return;
+ }
+
+ schema = _gcr_colons_get_schema (colons);
+ if (schema == GCR_COLONS_SCHEMA_PUB) {
+ if (load->dataset->len)
+ process_dataset_as_key (load);
+ g_assert (!load->dataset->len);
+ g_ptr_array_add (load->dataset, colons);
+ colons = NULL;
+ } else if (schema == GCR_COLONS_SCHEMA_UID) {
+ if (load->dataset->len) {
+ g_ptr_array_add (load->dataset, colons);
+ colons = NULL;
+ }
+ }
+
+ if (colons != NULL)
+ _gcr_colons_free (colons);
+}
+
+
+static gboolean
+on_spawn_standard_output (int fd, gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GcrGnupgCollectionLoad *load = g_simple_async_result_get_op_res_gpointer (res);
+ gchar buffer[1024];
+ gssize ret;
+
+ ret = egg_spawn_read_output (fd, buffer, sizeof (buffer));
+ if (ret < 0) {
+ g_warning ("couldn't read output data from prompt process");
+ return FALSE;
+ }
+
+ g_string_append_len (load->out_data, buffer, ret);
+ _gcr_util_parse_lines (load->out_data, FALSE, on_line_parse_output, load);
+
+ return (ret > 0);
+}
+
+static void
+on_line_print_error (const gchar *line, gpointer unused)
+{
+ g_printerr ("%s\n", line);
+}
+
+static gboolean
+on_spawn_standard_error (int fd, gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GcrGnupgCollectionLoad *load = g_simple_async_result_get_op_res_gpointer (res);
+ gchar buffer[1024];
+ gssize ret;
+
+ ret = egg_spawn_read_output (fd, buffer, sizeof (buffer));
+ if (ret < 0) {
+ g_warning ("couldn't read error data from prompt process");
+ return FALSE;
+ }
+
+ g_string_append_len (load->err_data, buffer, ret);
+ _gcr_util_parse_lines (load->err_data, FALSE, on_line_print_error, NULL);
+
+ return ret > 0;
+}
+
+static void
+on_each_difference_remove (gpointer key, gpointer value, gpointer user_data)
+{
+ GcrGnupgCollection *self = GCR_GNUPG_COLLECTION (user_data);
+ GObject *object;
+
+ object = g_hash_table_lookup (self->pv->items, key);
+ if (object != NULL) {
+ g_object_ref (object);
+ g_hash_table_remove (self->pv->items, key);
+ gcr_collection_emit_removed (GCR_COLLECTION (self), object);
+ g_object_unref (object);
+ }
+}
+
+static void
+on_spawn_completed (gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GcrGnupgCollectionLoad *load = g_simple_async_result_get_op_res_gpointer (res);
+
+ /* Should be the last call we receive */
+ g_assert (load->spawn_sig != 0);
+ load->spawn_sig = 0;
+
+ /* Print out any remaining errors */
+ _gcr_util_parse_lines (load->err_data, TRUE, on_line_print_error, NULL);
+
+ /* Process any remaining output */
+ _gcr_util_parse_lines (load->out_data, TRUE, on_line_parse_output, load);
+
+ /* Process last bit as a key, if any */
+ if (load->dataset->len)
+ process_dataset_as_key (load);
+
+ /* Remove any keys that we still have in the difference */
+ g_hash_table_foreach (load->difference, on_each_difference_remove, load->collection);
+
+ g_simple_async_result_complete (res);
+}
+
+static void
+on_child_exited (GPid pid, gint status, gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GcrGnupgCollectionLoad *load = g_simple_async_result_get_op_res_gpointer (res);
+ gint code;
+
+ g_return_if_fail (pid == load->gnupg_pid);
+
+ g_spawn_close_pid (load->gnupg_pid);
+ load->gnupg_pid = 0;
+ load->child_sig = 0;
+
+ if (WIFEXITED (status)) {
+ code = WEXITSTATUS (status);
+ if (code != 0) {
+ g_message ("gnupg process exited with failure code: %d", code);
+ } else if (WIFSIGNALED (status)) {
+ code = WTERMSIG (status);
+ g_message ("gnupg process was killed with signal: %d", code);
+ }
+ }
+}
+
+static EggSpawnCallbacks spawn_callbacks = {
+ NULL,
+ on_spawn_standard_output,
+ on_spawn_standard_error,
+ on_spawn_completed,
+ g_object_unref,
+ NULL
+};
+
+static void
+on_each_item_add_keyid_to_difference (gpointer key, gpointer value, gpointer user_data)
+{
+ GHashTable *difference = user_data;
+ g_hash_table_insert (difference, key, key);
+}
+
+void
+_gcr_gnupg_collection_load_async (GcrGnupgCollection *self, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ GcrGnupgCollectionLoad *load;
+ GError *error = NULL;
+ GPtrArray *argv;
+
+ g_return_if_fail (GCR_IS_GNUPG_COLLECTION (self));
+
+ /* Not yet implemented */
+ g_return_if_fail (cancellable == NULL);
+
+ argv = g_ptr_array_new ();
+ g_ptr_array_add (argv, GPG_EXECUTABLE);
+ g_ptr_array_add (argv, "--list-keys");
+ g_ptr_array_add (argv, "--fixed-list-mode");
+ g_ptr_array_add (argv, "--with-colons");
+ if (self->pv->directory) {
+ g_ptr_array_add (argv, "--homedir");
+ g_ptr_array_add (argv, (gpointer)self->pv->directory);
+ }
+ g_ptr_array_add (argv, NULL);
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ _gcr_gnupg_collection_load_async);
+
+ load = g_slice_new0 (GcrGnupgCollectionLoad);
+ load->dataset = g_ptr_array_new_with_free_func (_gcr_colons_free);
+ load->err_data = g_string_sized_new (128);
+ load->out_data = g_string_sized_new (1024);
+ load->difference = g_hash_table_new (g_str_hash, g_str_equal);
+ load->collection = g_object_ref (self);
+ g_hash_table_foreach (self->pv->items, on_each_item_add_keyid_to_difference,
+ load->difference);
+
+ g_simple_async_result_set_op_res_gpointer (res, load,
+ _gcr_gnupg_collection_load_free);
+
+ load->spawn_sig = egg_spawn_async_with_callbacks (self->pv->directory,
+ (gchar**)argv->pdata, NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD,
+ &load->gnupg_pid,
+ &spawn_callbacks,
+ g_object_ref (res),
+ NULL, &error);
+
+ if (error) {
+ g_simple_async_result_set_from_error (res, error);
+ g_simple_async_result_complete_in_idle (res);
+ } else {
+ load->child_sig = g_child_watch_add_full (G_PRIORITY_DEFAULT,
+ load->gnupg_pid,
+ on_child_exited,
+ g_object_ref (res),
+ g_object_unref);
+ }
+
+ g_object_unref (res);
+}
+
+gboolean
+_gcr_gnupg_collection_load_finish (GcrGnupgCollection *self, GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (GCR_IS_GNUPG_COLLECTION (self), FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ _gcr_gnupg_collection_load_async), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/gcr/gcr-gnupg-collection.h b/gcr/gcr-gnupg-collection.h
new file mode 100644
index 0000000..b2a5d25
--- /dev/null
+++ b/gcr/gcr-gnupg-collection.h
@@ -0,0 +1,69 @@
+/*
+ * gnome-keyring
+ *
+ * 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>
+ */
+
+#ifndef GCR_GNUPG_COLLECTION_H
+#define GCR_GNUPG_COLLECTION_H
+
+#include "gcr.h"
+#include "gcr-collection.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_GNUPG_COLLECTION (_gcr_gnupg_collection_get_type ())
+#define GCR_GNUPG_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_COLLECTION, GcrGnupgCollection))
+#define GCR_GNUPG_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_COLLECTION, GcrGnupgCollectionClass))
+#define GCR_IS_GNUPG_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_COLLECTION))
+#define GCR_IS_GNUPG_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_COLLECTION))
+#define GCR_GNUPG_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_COLLECTION, GcrGnupgCollectionClass))
+
+typedef struct _GcrGnupgCollection GcrGnupgCollection;
+typedef struct _GcrGnupgCollectionClass GcrGnupgCollectionClass;
+typedef struct _GcrGnupgCollectionPrivate GcrGnupgCollectionPrivate;
+
+struct _GcrGnupgCollection {
+ GObject parent;
+ GcrGnupgCollectionPrivate *pv;
+};
+
+struct _GcrGnupgCollectionClass {
+ GObjectClass parent_class;
+};
+
+GType _gcr_gnupg_collection_get_type (void);
+
+GcrCollection* _gcr_gnupg_collection_new (const gchar *directory);
+
+void _gcr_gnupg_collection_load_async (GcrGnupgCollection *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean _gcr_gnupg_collection_load_finish (GcrGnupgCollection *self,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* GCR_GNUPG_COLLECTION_H */
diff --git a/gcr/gcr-gnupg-key.c b/gcr/gcr-gnupg-key.c
new file mode 100644
index 0000000..225d628
--- /dev/null
+++ b/gcr/gcr-gnupg-key.c
@@ -0,0 +1,249 @@
+/*
+ * 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-colons.h"
+#include "gcr-gnupg-key.h"
+
+#include "gck/gck.h"
+
+#include <gdk/gdk.h>
+#include <glib/gi18n-lib.h>
+
+enum {
+ PROP_0,
+ PROP_DATASET,
+ PROP_LABEL,
+ PROP_MARKUP,
+ PROP_DESCRIPTION,
+ PROP_KEYID
+};
+
+struct _GcrGnupgKeyPrivate {
+ GPtrArray *dataset;
+};
+
+G_DEFINE_TYPE (GcrGnupgKey, _gcr_gnupg_key, G_TYPE_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static gchar *
+calculate_name (GcrGnupgKey *self)
+{
+ GcrColons* colons;
+
+ colons = _gcr_colons_find (self->pv->dataset, GCR_COLONS_SCHEMA_UID);
+ g_return_val_if_fail (colons, NULL);
+
+ return _gcr_colons_get_string (colons, GCR_COLONS_UID_NAME);
+}
+
+static gchar *
+calculate_markup (GcrGnupgKey *self)
+{
+ gchar *result = NULL;
+ gchar *name;
+
+ name = calculate_name (self);
+ if (name)
+ result = g_markup_escape_text (name, -1);
+ g_free (name);
+
+ return result;
+}
+
+static const gchar *
+calculate_keyid (GcrGnupgKey *self)
+{
+ const gchar *keyid;
+ gsize length;
+
+ keyid = _gcr_gnupg_key_get_keyid_for_colons (self->pv->dataset);
+ if (keyid == NULL)
+ return NULL;
+
+ length = strlen (keyid);
+ if (length > 8)
+ keyid += (length - 8);
+
+ return keyid;
+}
+
+static void
+_gcr_gnupg_key_init (GcrGnupgKey *self)
+{
+ self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_GNUPG_KEY, GcrGnupgKeyPrivate));
+}
+
+static void
+_gcr_gnupg_key_finalize (GObject *obj)
+{
+ GcrGnupgKey *self = GCR_GNUPG_KEY (obj);
+
+ if (self->pv->dataset)
+ g_ptr_array_free (self->pv->dataset, TRUE);
+ self->pv->dataset = NULL;
+
+ G_OBJECT_CLASS (_gcr_gnupg_key_parent_class)->finalize (obj);
+}
+
+static void
+_gcr_gnupg_key_set_property (GObject *obj, guint prop_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ GcrGnupgKey *self = GCR_GNUPG_KEY (obj);
+
+ switch (prop_id) {
+ case PROP_DATASET:
+ g_return_if_fail (!self->pv->dataset);
+ self->pv->dataset = g_value_dup_boxed (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gcr_gnupg_key_get_property (GObject *obj, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GcrGnupgKey *self = GCR_GNUPG_KEY (obj);
+
+ switch (prop_id) {
+ case PROP_DATASET:
+ g_value_set_boxed (value, self->pv->dataset);
+ break;
+ case PROP_LABEL:
+ g_value_take_string (value, calculate_name (self));
+ break;
+ case PROP_DESCRIPTION:
+ g_value_set_string (value, _("PGP Key"));
+ break;
+ case PROP_MARKUP:
+ g_value_take_string (value, calculate_markup (self));
+ break;
+ case PROP_KEYID:
+ g_value_set_string (value, calculate_keyid (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gcr_gnupg_key_class_init (GcrGnupgKeyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ _gcr_gnupg_key_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (GcrGnupgKeyPrivate));
+
+ gobject_class->finalize = _gcr_gnupg_key_finalize;
+ gobject_class->set_property = _gcr_gnupg_key_set_property;
+ gobject_class->get_property = _gcr_gnupg_key_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_DATASET,
+ g_param_spec_boxed ("dataset", "Dataset", "Colon Dataset",
+ G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_LABEL,
+ g_param_spec_string ("label", "Label", "Key label",
+ "", G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
+ g_param_spec_string ("description", "Description", "Description of object type",
+ "", G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_MARKUP,
+ g_param_spec_string ("markup", "Markup", "Markup which describes key",
+ "", G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_KEYID,
+ g_param_spec_string ("keyid", "Key ID", "Display key identifier",
+ "", G_PARAM_READABLE));
+}
+
+GcrGnupgKey*
+_gcr_gnupg_key_new (GPtrArray *dataset)
+{
+ return g_object_new (GCR_TYPE_GNUPG_KEY, "dataset", dataset, NULL);
+}
+
+
+GPtrArray*
+_gcr_gnupg_key_get_dataset (GcrGnupgKey *self)
+{
+ g_return_val_if_fail (GCR_IS_GNUPG_KEY (self), NULL);
+ return self->pv->dataset;
+}
+
+void
+_gcr_gnupg_key_set_dataset (GcrGnupgKey *self, GPtrArray *dataset)
+{
+ GObject *obj;
+
+ g_return_if_fail (GCR_IS_GNUPG_KEY (self));
+ g_return_if_fail (dataset);
+
+ g_ptr_array_ref (dataset);
+ if (self->pv->dataset)
+ g_ptr_array_unref (self->pv->dataset);
+ self->pv->dataset = dataset;
+
+ obj = G_OBJECT (self);
+ g_object_freeze_notify (obj);
+ g_object_notify (obj, "dataset");
+ g_object_notify (obj, "label");
+ g_object_notify (obj, "markup");
+ g_object_notify (obj, "keyid");
+ g_object_thaw_notify (obj);
+}
+
+const gchar*
+_gcr_gnupg_key_get_keyid_for_colons (GPtrArray *dataset)
+{
+ GcrColons *colons;
+
+ colons = _gcr_colons_find (dataset, GCR_COLONS_SCHEMA_PUB);
+ if (colons == NULL)
+ return NULL;
+
+ return _gcr_colons_get_raw (colons, GCR_COLONS_PUB_KEYID);
+}
+
+const GcrColumn*
+_gcr_gnupg_key_get_columns (void)
+{
+ static GcrColumn columns[] = {
+ { "label", G_TYPE_STRING, G_TYPE_STRING, N_("Name"),
+ GCR_COLUMN_SORTABLE },
+ { "keyid", G_TYPE_STRING, G_TYPE_STRING, N_("Key ID"),
+ GCR_COLUMN_SORTABLE },
+ { NULL }
+ };
+
+ return columns;
+}
diff --git a/gcr/gcr-gnupg-key.h b/gcr/gcr-gnupg-key.h
new file mode 100644
index 0000000..b1b8765
--- /dev/null
+++ b/gcr/gcr-gnupg-key.h
@@ -0,0 +1,75 @@
+/*
+ * 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_KEY_H
+#define GCR_GNUPG_KEY_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gcr-column.h"
+#include "gcr-types.h"
+
+G_BEGIN_DECLS
+
+#define GCR_GNUPG_KEY_COLUMNS (_gcr_gnupg_key_get_columns ())
+#define GCR_TYPE_GNUPG_KEY (_gcr_gnupg_key_get_type ())
+#define GCR_GNUPG_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_GNUPG_KEY, GcrGnupgKey))
+#define GCR_GNUPG_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_GNUPG_KEY, GcrGnupgKeyClass))
+#define GCR_IS_GNUPG_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_GNUPG_KEY))
+#define GCR_IS_GNUPG_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_GNUPG_KEY))
+#define GCR_GNUPG_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_GNUPG_KEY, GcrGnupgKeyClass))
+
+typedef struct _GcrGnupgKey GcrGnupgKey;
+typedef struct _GcrGnupgKeyClass GcrGnupgKeyClass;
+typedef struct _GcrGnupgKeyPrivate GcrGnupgKeyPrivate;
+
+struct _GcrGnupgKey {
+ GObject parent;
+
+ /*< private >*/
+ GcrGnupgKeyPrivate *pv;
+};
+
+struct _GcrGnupgKeyClass {
+ GObjectClass parent_class;
+};
+
+GType _gcr_gnupg_key_get_type (void);
+
+const GcrColumn* _gcr_gnupg_key_get_columns (void);
+
+GcrGnupgKey* _gcr_gnupg_key_new (GPtrArray *dataset);
+
+GPtrArray* _gcr_gnupg_key_get_dataset (GcrGnupgKey *self);
+
+void _gcr_gnupg_key_set_dataset (GcrGnupgKey *self,
+ GPtrArray *dataset);
+
+const gchar* _gcr_gnupg_key_get_keyid_for_colons (GPtrArray *dataset);
+
+G_END_DECLS
+
+#endif /* __GCR_GNUPG_KEY_H__ */
diff --git a/gcr/gcr-util.c b/gcr/gcr-util.c
new file mode 100644
index 0000000..3929d5b
--- /dev/null
+++ b/gcr/gcr-util.c
@@ -0,0 +1,55 @@
+/*
+ * gnome-keyring
+ *
+ * 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-util.h"
+
+#include <string.h>
+
+void
+_gcr_util_parse_lines (GString *string, gboolean last_line,
+ GcrLineCallback callback, gpointer user_data)
+{
+ gchar *ptr;
+ gchar *prev;
+
+ g_return_if_fail (string);
+ g_return_if_fail (callback);
+
+ /* Print all stderr lines as messages */
+ while ((ptr = strchr (string->str, '\n')) != NULL) {
+ *ptr = '\0';
+ prev = ptr - 1;
+ if (*prev == '\r')
+ *prev = '\0';
+
+ (callback) (string->str, user_data);
+ g_string_erase (string, 0, ptr - string->str + 1);
+ }
+
+ if (last_line && string->len) {
+ (callback) (string->str, user_data);
+ g_string_erase (string, 0, string->len);
+ }
+}
diff --git a/gcr/gcr-util.h b/gcr/gcr-util.h
new file mode 100644
index 0000000..a104a8e
--- /dev/null
+++ b/gcr/gcr-util.h
@@ -0,0 +1,41 @@
+/*
+ * gnome-keyring
+ *
+ * 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>
+ */
+
+#ifndef GCR_UTIL_H
+#define GCR_UTIL_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef void (*GcrLineCallback) (const gchar *line,
+ gpointer user_data);
+
+void _gcr_util_parse_lines (GString *string,
+ gboolean last_line,
+ GcrLineCallback callback,
+ gpointer user_data);
+
+G_END_DECLS
+
+#endif /* __GCR_TOKEN_MANAGER_H__ */
diff --git a/gcr/tests/Makefile.am b/gcr/tests/Makefile.am
index b5ff961..9105937 100644
--- a/gcr/tests/Makefile.am
+++ b/gcr/tests/Makefile.am
@@ -5,6 +5,7 @@ INCLUDES = \
-DSRCDIR=$(srcdir) \
-DGCR_API_SUBJECT_TO_CHANGE \
-DGCK_API_SUBJECT_TO_CHANGE \
+ -DGCR_COMPILATION \
$(GLIB_CFLAGS) \
$(GTK_CFLAGS) \
$(LIBGCRYPT_CFLAGS)
@@ -19,12 +20,16 @@ LDADD = \
$(LIBGCRYPT_LIBS)
TEST_PROGS = \
+ test-util \
+ test-simple-certificate \
test-certificate \
test-certificate-chain \
test-pkcs11-certificate \
- test-simple-certificate \
test-trust \
- test-parser
+ test-parser \
+ test-colons \
+ test-gnupg-key \
+ test-gnupg-collection
check_PROGRAMS = $(TEST_PROGS)
@@ -44,6 +49,7 @@ EXTRA_DIST = \
noinst_PROGRAMS = \
frob-certificate \
+ frob-gnupg-selector \
frob-key \
frob-selector \
frob-unlock-options
diff --git a/gcr/tests/files/gnupg-homedir/pubring.gpg b/gcr/tests/files/gnupg-homedir/pubring.gpg
new file mode 100644
index 0000000..a642536
Binary files /dev/null and b/gcr/tests/files/gnupg-homedir/pubring.gpg differ
diff --git a/gcr/tests/files/gnupg-homedir/secring.gpg b/gcr/tests/files/gnupg-homedir/secring.gpg
new file mode 100644
index 0000000..e69de29
diff --git a/gcr/tests/files/gnupg-homedir/trustdb.gpg b/gcr/tests/files/gnupg-homedir/trustdb.gpg
new file mode 100644
index 0000000..0377c97
Binary files /dev/null and b/gcr/tests/files/gnupg-homedir/trustdb.gpg differ
diff --git a/gcr/tests/frob-gnupg-selector.c b/gcr/tests/frob-gnupg-selector.c
new file mode 100644
index 0000000..02fd837
--- /dev/null
+++ b/gcr/tests/frob-gnupg-selector.c
@@ -0,0 +1,79 @@
+/*
+ * gnome-keyring
+ *
+ * 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.h"
+#include "gcr-gnupg-collection.h"
+#include "gcr-gnupg-key.h"
+
+#include <gtk/gtk.h>
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+static void
+on_collection_loaded (GObject *source, GAsyncResult *result, gpointer unused)
+{
+ GError *error = NULL;
+
+ _gcr_gnupg_collection_load_finish (GCR_GNUPG_COLLECTION (source), result, &error);
+ if (error) {
+ g_warning ("collection load failed: %s", error->message);
+ g_clear_error (&error);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ GcrCollection *collection;
+ GcrSelector *selector;
+ GtkDialog *dialog;
+
+ gtk_init (&argc, &argv);
+
+ dialog = GTK_DIALOG (gtk_dialog_new ());
+ g_object_ref_sink (dialog);
+
+ collection = _gcr_gnupg_collection_new (NULL);
+ selector = gcr_selector_new (collection, GCR_GNUPG_KEY_COLUMNS, GCR_SELECTOR_MODE_MULTIPLE);
+
+ gtk_widget_show (GTK_WIDGET (selector));
+ gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (dialog)), GTK_WIDGET (selector));
+
+ _gcr_gnupg_collection_load_async (GCR_GNUPG_COLLECTION (collection), NULL,
+ on_collection_loaded, NULL);
+
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 550, 400);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 20);
+
+ g_object_unref (collection);
+
+ gtk_dialog_run (dialog);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ g_object_unref (dialog);
+
+ return 0;
+}
diff --git a/gcr/tests/test-colons.c b/gcr/tests/test-colons.c
new file mode 100644
index 0000000..1bca077
--- /dev/null
+++ b/gcr/tests/test-colons.c
@@ -0,0 +1,193 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ Copyright (C) 2011 Collabora Ltd.
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. 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/gcr-colons.h"
+
+#include "egg/egg-testing.h"
+
+#include <glib.h>
+
+typedef struct {
+ GcrColons *colons;
+} Test;
+
+static void
+setup (Test *test, gconstpointer unused)
+{
+ test->colons = _gcr_colons_parse ("one:tab\\there::four:f\xfc""nf:", -1);
+}
+
+static void
+teardown (Test *test, gconstpointer unused)
+{
+ _gcr_colons_free (test->colons);
+}
+
+static void
+test_parse (void)
+{
+ GcrColons *colons;
+
+ colons = _gcr_colons_parse ("one:two::four::six", -1);
+ g_assert (colons);
+
+ g_assert_cmpstr (_gcr_colons_get_raw (colons, 0), ==, "one");
+ g_assert_cmpstr (_gcr_colons_get_raw (colons, 1), ==, "two");
+ g_assert_cmpstr (_gcr_colons_get_raw (colons, 2), ==, "");
+ g_assert_cmpstr (_gcr_colons_get_raw (colons, 3), ==, "four");
+ g_assert_cmpstr (_gcr_colons_get_raw (colons, 4), ==, "");
+ g_assert_cmpstr (_gcr_colons_get_raw (colons, 5), ==, "six");
+ g_assert (_gcr_colons_get_raw (colons, 6) == NULL);
+
+ _gcr_colons_free (colons);
+}
+
+static void
+test_parse_part (void)
+{
+ GcrColons *colons;
+
+ colons = _gcr_colons_parse ("one:two::four::six", 8);
+ g_assert (colons);
+
+ g_assert_cmpstr (_gcr_colons_get_raw (colons, 0), ==, "one");
+ g_assert_cmpstr (_gcr_colons_get_raw (colons, 1), ==, "two");
+ g_assert_cmpstr (_gcr_colons_get_raw (colons, 2), ==, "");
+ g_assert (_gcr_colons_get_raw (colons, 3) == NULL);
+
+ _gcr_colons_free (colons);
+}
+
+static void
+test_parse_too_long (void)
+{
+ GcrColons *colons;
+
+ /* Too many columns */
+ colons = _gcr_colons_parse (":::::::::::::::::::::::::::::::::::::::::::::::::::::", -1);
+ g_assert (colons == NULL);
+}
+
+static void
+test_find (void)
+{
+ GcrColons *uid, *pub, *one, *check;
+ GPtrArray *dataset;
+
+ dataset = g_ptr_array_new_with_free_func (_gcr_colons_free);
+
+ one = _gcr_colons_parse ("one:two::four::six", -1);
+ g_ptr_array_add (dataset, one);
+ pub = _gcr_colons_parse ("pub:two", -1);
+ g_ptr_array_add (dataset, pub);
+ uid = _gcr_colons_parse ("uid:two", -1);
+ g_ptr_array_add (dataset, uid);
+
+ check = _gcr_colons_find (dataset, GCR_COLONS_SCHEMA_PUB);
+ g_assert (check == pub);
+
+ check = _gcr_colons_find (dataset, GCR_COLONS_SCHEMA_UID);
+ g_assert (check == uid);
+
+ g_ptr_array_unref (dataset);
+}
+
+static void
+test_get_string (Test *test, gconstpointer unused)
+{
+ gchar *value = _gcr_colons_get_string (test->colons, 1);
+ g_assert (value);
+
+ g_assert_cmpstr (value, ==, "tab\there");
+ g_free (value);
+}
+
+static void
+test_get_string_null (Test *test, gconstpointer unused)
+{
+ gchar *value = _gcr_colons_get_string (test->colons, 35);
+ g_assert (value == NULL);
+}
+
+static void
+test_get_string_latin1 (Test *test, gconstpointer unused)
+{
+ gchar *value = _gcr_colons_get_string (test->colons, 4);
+ g_assert (value);
+
+ g_assert_cmpstr (value, ==, "f\xc3\xbc""nf");
+ g_assert (g_utf8_validate (value, -1, NULL));
+ g_free (value);
+}
+
+static void
+test_free_null (void)
+{
+ _gcr_colons_free (NULL);
+}
+
+static void
+test_get_schema (Test *test, gconstpointer unused)
+{
+ GQuark schema;
+ GQuark check;
+
+ /* Initialize this quark */
+ check = g_quark_from_static_string ("one");
+
+ schema = _gcr_colons_get_schema (test->colons);
+ g_assert (check == schema);
+ g_assert_cmpstr (g_quark_to_string (schema), ==, "one");
+}
+
+static void
+test_schemas (void)
+{
+ GQuark check;
+
+ check = _gcr_colons_get_schema_uid_quark ();
+ g_assert_cmpstr (g_quark_to_string (check), ==, "uid");
+
+ check = _gcr_colons_get_schema_pub_quark ();
+ g_assert_cmpstr (g_quark_to_string (check), ==, "pub");
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/gcr/colons/parse", test_parse);
+ g_test_add_func ("/gcr/colons/parse_part", test_parse_part);
+ g_test_add_func ("/gcr/colons/parse_too_long", test_parse_too_long);
+ g_test_add_func ("/gcr/colons/free_null", test_free_null);
+ g_test_add_func ("/gcr/colons/schemas", test_schemas);
+ g_test_add_func ("/gcr/colons/find", test_find);
+ g_test_add ("/gcr/colons/get_string", Test, NULL, setup, test_get_string, teardown);
+ g_test_add ("/gcr/colons/get_string_null", Test, NULL, setup, test_get_string_null, teardown);
+ g_test_add ("/gcr/colons/get_string_latin1", Test, NULL, setup, test_get_string_latin1, teardown);
+ g_test_add ("/gcr/colons/get_schema", Test, NULL, setup, test_get_schema, teardown);
+
+ return g_test_run ();
+}
diff --git a/gcr/tests/test-gnupg-collection.c b/gcr/tests/test-gnupg-collection.c
new file mode 100644
index 0000000..d156a82
--- /dev/null
+++ b/gcr/tests/test-gnupg-collection.c
@@ -0,0 +1,82 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ Copyright (C) 2010 Collabora Ltd
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. 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/gcr.h"
+#include "gcr/gcr-gnupg-collection.h"
+
+#include "egg/egg-testing.h"
+
+#include <glib.h>
+
+#include <errno.h>
+#include <string.h>
+
+#if 0
+typedef struct {
+
+} Test;
+
+static void
+setup (Test *test, gconstpointer unused)
+{
+
+}
+
+static void
+teardown (Test *test, gconstpointer unused)
+{
+
+}
+#endif
+
+static void
+test_create (void)
+{
+ GcrCollection *collection;
+
+ collection = _gcr_gnupg_collection_new ("files/gnupg-homedir/");
+
+ g_object_unref (collection);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ const gchar *srcdir;
+
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ srcdir = g_getenv ("SRCDIR");
+ if (srcdir && chdir (srcdir) < 0)
+ g_error ("couldn't change directory to: %s: %s", srcdir, g_strerror (errno));
+
+ g_test_add_func ("/gcr/gnupg-collection/create", test_create);
+#if 0
+ g_test_add ("/gcr/certificate/issuer_dn", Test, NULL, setup, test_issuer_dn, teardown);
+#endif
+
+ return g_test_run ();
+}
diff --git a/gcr/tests/test-gnupg-key.c b/gcr/tests/test-gnupg-key.c
new file mode 100644
index 0000000..5f1efac
--- /dev/null
+++ b/gcr/tests/test-gnupg-key.c
@@ -0,0 +1,132 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ Copyright (C) 2011 Collabora Ltd
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. 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/gcr-colons.h"
+#include "gcr/gcr-gnupg-key.h"
+
+#include "egg/egg-testing.h"
+
+#include <glib.h>
+
+#include <errno.h>
+#include <string.h>
+
+typedef struct {
+ GPtrArray *dataset;
+ GcrGnupgKey *key;
+} Test;
+
+static void
+setup (Test *test, gconstpointer unused)
+{
+ GPtrArray *dataset;
+
+ dataset = g_ptr_array_new_with_free_func (_gcr_colons_free);
+ g_ptr_array_add (dataset, _gcr_colons_parse ("pub:f:1024:17:6C7EE1B8621CC013:899817715:1055898235::m:::scESC:", -1));
+ g_ptr_array_add (dataset, _gcr_colons_parse ("fpr:::::::::ECAF7590EB3443B5C7CF3ACB6C7EE1B8621CC013:", -1));
+ g_ptr_array_add (dataset, _gcr_colons_parse ("uid:f::::::::Werner Koch <wk g10code com>:\n", -1));
+ g_ptr_array_add (dataset, _gcr_colons_parse ("uid:f::::::::Werner Koch <wk gnupg org>:\n", -1));
+ g_ptr_array_add (dataset, _gcr_colons_parse ("sub:f:1536:16:06AD222CADF6A6E1:919537416:1036177416:::::e:\n", -1));
+ g_ptr_array_add (dataset, _gcr_colons_parse ("fpr:::::::::CF8BCC4B18DE08FCD8A1615906AD222CADF6A6E1:\n", -1));
+ g_ptr_array_add (dataset, _gcr_colons_parse ("sub:r:1536:20:5CE086B5B5A18FF4:899817788:1025961788:::::esc:\n", -1));
+ g_ptr_array_add (dataset, _gcr_colons_parse ("fpr:::::::::AB059359A3B81F410FCFF97F5CE086B5B5A18FF4:", -1));
+
+ test->key = _gcr_gnupg_key_new (dataset);
+ test->dataset = dataset;
+}
+
+static void
+teardown (Test *test, gconstpointer unused)
+{
+ g_object_unref (test->key);
+ g_ptr_array_unref (test->dataset);
+}
+
+static void
+test_label (Test *test, gconstpointer unused)
+{
+ gchar *label;
+
+ g_object_get (test->key, "label", &label, NULL);
+ g_assert_cmpstr (label, ==, "Werner Koch <wk g10code com>");
+
+ g_free (label);
+}
+
+static void
+test_markup (Test *test, gconstpointer unused)
+{
+ gchar *markup;
+
+ g_object_get (test->key, "markup", &markup, NULL);
+ g_assert_cmpstr (markup, ==, "Werner Koch <wk g10code com>");
+
+ g_free (markup);
+}
+
+static void
+test_description (Test *test, gconstpointer unused)
+{
+ gchar *description;
+
+ g_object_get (test->key, "description", &description, NULL);
+ g_assert_cmpstr (description, ==, "PGP Key");
+
+ g_free (description);
+}
+
+static void
+test_dataset (Test *test, gconstpointer unused)
+{
+ GPtrArray *dataset;
+
+ g_object_get (test->key, "dataset", &dataset, NULL);
+ g_assert (dataset == test->dataset);
+
+ g_ptr_array_unref (dataset);
+}
+
+static void
+test_keyid_for_colons (Test *test, gconstpointer unused)
+{
+ const gchar *keyid;
+
+ keyid = _gcr_gnupg_key_get_keyid_for_colons (test->dataset);
+ g_assert_cmpstr (keyid, ==, "6C7EE1B8621CC013");
+}
+
+int
+main (int argc, char **argv)
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add ("/gcr/gnupg-key/label", Test, NULL, setup, test_label, teardown);
+ g_test_add ("/gcr/gnupg-key/description", Test, NULL, setup, test_description, teardown);
+ g_test_add ("/gcr/gnupg-key/markup", Test, NULL, setup, test_markup, teardown);
+ g_test_add ("/gcr/gnupg-key/dataset", Test, NULL, setup, test_dataset, teardown);
+ g_test_add ("/gcr/gnupg-key/keyid_for_colons", Test, NULL, setup, test_keyid_for_colons, teardown);
+
+ return g_test_run ();
+}
diff --git a/gcr/tests/test-util.c b/gcr/tests/test-util.c
new file mode 100644
index 0000000..015424f
--- /dev/null
+++ b/gcr/tests/test-util.c
@@ -0,0 +1,112 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ Copyright (C) 2011 Collabora Ltd.
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. 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.h"
+#include "gcr/gcr-util.h"
+
+#include <errno.h>
+
+static void
+on_line_parsed_match_template (const gchar *line, gpointer user_data)
+{
+ const gchar ***matching = user_data;
+
+ g_assert (matching);
+ g_assert (*matching);
+
+ /* Must be another line to match */
+ g_assert ((*matching)[0]);
+
+ /* Match this line against expected, and increment to next */
+ g_assert_cmpstr ((*matching)[0], ==, line);
+ (*matching)++;
+}
+
+static void
+test_parse_lines (void)
+{
+ GString *string = g_string_new ("first line\nsecond line\n\nlast line");
+ const gchar *matches[] = { "first line", "second line", "", NULL };
+ const gchar **matching = matches;
+
+ _gcr_util_parse_lines (string, FALSE, on_line_parsed_match_template, &matching);
+
+ /* All lines should have matched */
+ g_assert (*matching == NULL);
+
+ /* The last line should still be here */
+ g_assert_cmpstr (string->str, ==, "last line");
+ g_string_free (string, TRUE);
+}
+
+static void
+test_parse_lines_and_last (void)
+{
+ GString *string = g_string_new ("first line\nsecond line\n\nlast line");
+ const gchar *matches[] = { "first line", "second line", "", "last line", NULL };
+ const gchar **matching = matches;
+
+ _gcr_util_parse_lines (string, FALSE, on_line_parsed_match_template, &matching);
+ _gcr_util_parse_lines (string, TRUE, on_line_parsed_match_template, &matching);
+
+ /* All lines should have matched */
+ g_assert (*matching == NULL);
+
+ /* No more data */
+ g_assert_cmpstr (string->str, ==, "");
+ g_assert_cmpuint (string->len, ==, 0);
+ g_string_free (string, TRUE);
+}
+
+static void
+test_parse_lines_dos (void)
+{
+ GString *string = g_string_new ("first line\r\nsecond line\r\n\r\nlast line");
+ const gchar *matches[] = { "first line", "second line", "", "last line", NULL };
+ const gchar **matching = matches;
+
+ _gcr_util_parse_lines (string, FALSE, on_line_parsed_match_template, &matching);
+ _gcr_util_parse_lines (string, TRUE, on_line_parsed_match_template, &matching);
+
+ /* All lines should have matched */
+ g_assert (*matching == NULL);
+
+ /* No more data */
+ g_assert_cmpstr (string->str, ==, "");
+ g_assert_cmpuint (string->len, ==, 0);
+ g_string_free (string, TRUE);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/gcr/util/test_parse_lines", test_parse_lines);
+ g_test_add_func ("/gcr/util/test_parse_lines_and_last", test_parse_lines_and_last);
+ g_test_add_func ("/gcr/util/test_parse_lines_dos", test_parse_lines_dos);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]