[gnome-keyring/ui-widgets: 1/7] Rework how the importer and parser work together.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring/ui-widgets: 1/7] Rework how the importer and parser work together.
- Date: Fri, 27 Aug 2010 03:24:35 +0000 (UTC)
commit dd767066b8db5d0b601001ad24c1bd0a34182947
Author: Stef Walter <stef memberwebs com>
Date: Sun Jun 20 01:11:48 2010 +0000
Rework how the importer and parser work together.
* Parser becomes a general source for objects.
gcr/gcr-importer.c | 424 ++++++++++++++++--------------------------------
gcr/gcr-importer.h | 18 +-
gcr/gcr-marshal.list | 1 +
gcr/gcr-parser.c | 302 ++++++++++++++++++++++++++++++++++
gcr/gcr-parser.h | 16 ++
tool/gkr-tool-import.c | 10 +-
6 files changed, 481 insertions(+), 290 deletions(-)
---
diff --git a/gcr/gcr-importer.c b/gcr/gcr-importer.c
index 8fcc3f6..68c94b8 100644
--- a/gcr/gcr-importer.c
+++ b/gcr/gcr-importer.c
@@ -24,6 +24,7 @@
#include "gcr-import-dialog.h"
#include "gcr-importer.h"
#include "gcr-internal.h"
+#include "gcr-marshal.h"
#include "gcr-parser.h"
#include <glib/gi18n-lib.h>
@@ -31,11 +32,11 @@
enum {
PROP_0,
PROP_SLOT,
- PROP_PARSER,
PROP_PROMPT_BEHAVIOR
};
enum {
+ QUEUED,
IMPORTED,
LAST_SIGNAL
};
@@ -54,10 +55,8 @@ struct _GcrImporterPrivate {
/* State data during import */
gboolean processing;
GCancellable *cancel;
- GInputStream *input;
gboolean prompted;
gboolean async;
- GByteArray *buffer;
GP11Session *session;
GQueue queue;
@@ -72,8 +71,6 @@ static void state_complete (GcrImporter *self, gboolean async);
static void state_create_object (GcrImporter *self, gboolean async);
static void state_open_session (GcrImporter *self, gboolean async);
static void state_initialize_pin (GcrImporter *self, gboolean async);
-static void state_parse_buffer (GcrImporter *self, gboolean async);
-static void state_read_buffer (GcrImporter *self, gboolean async);
static void gcr_importer_async_result (GAsyncResultIface *iface);
G_DEFINE_TYPE_WITH_CODE (GcrImporter, gcr_importer, G_TYPE_OBJECT,
@@ -89,11 +86,7 @@ static void
cleanup_state_data (GcrImporter *self)
{
GP11Attributes *attrs;
-
- if (self->pv->buffer)
- g_byte_array_free (self->pv->buffer, TRUE);
- self->pv->buffer = NULL;
-
+
if (self->pv->session)
g_object_unref (self->pv->session);
self->pv->session = NULL;
@@ -101,11 +94,7 @@ cleanup_state_data (GcrImporter *self)
while ((attrs = g_queue_pop_head (&self->pv->queue)) != NULL)
gp11_attributes_unref (attrs);
g_assert (g_queue_is_empty (&self->pv->queue));
-
- if (self->pv->input)
- g_object_unref (self->pv->input);
- self->pv->input = NULL;
-
+
if (self->pv->cancel)
g_object_unref (self->pv->cancel);
self->pv->cancel = NULL;
@@ -132,6 +121,103 @@ next_state (GcrImporter *self, void (*state) (GcrImporter*, gboolean))
(state) (self, self->pv->async);
}
+static const gchar*
+prepare_auth_primary (CK_OBJECT_CLASS klass)
+{
+ if (klass == CKO_PRIVATE_KEY)
+ return _("Enter password to unlock the private key");
+ else if (klass == CKO_CERTIFICATE)
+ return _("Enter password to unlock the certificate");
+ else
+ return _("Enter password to unlock");
+}
+
+static gchar*
+prepare_auth_secondary (CK_OBJECT_CLASS klass, const gchar *label)
+{
+ if (label == NULL) {
+ if (klass == CKO_PRIVATE_KEY) {
+ /* TRANSLATORS: The key is locked. */
+ return g_strdup (_("In order to import the private key, it must be unlocked"));
+ } else if (klass == CKO_CERTIFICATE) {
+ /* TRANSLATORS: The certificate is locked. */
+ return g_strdup (_("In order to import the certificate, it must be unlocked"));
+ } else {
+ /* TRANSLATORS: The data is locked. */
+ return g_strdup (_("In order to import the data, it must be unlocked"));
+ }
+ } else {
+ if (klass == CKO_PRIVATE_KEY) {
+ /* TRANSLATORS: The key is locked. */
+ return g_strdup_printf (_("In order to import the private key '%s', it must be unlocked"), label);
+ } else if (klass == CKO_CERTIFICATE) {
+ /* TRANSLATORS: The certificate is locked. */
+ return g_strdup_printf (_("In order to import the certificate '%s', it must be unlocked"), label);
+ } else {
+ /* TRANSLATORS: The object '%s' is locked. */
+ return g_strdup_printf (_("In order to import '%s', it must be unlocked"), label);
+ }
+ }
+}
+
+static void
+on_parser_parsed (GcrParser *parser, GcrImporter *self)
+{
+ GP11Attributes *attrs;
+
+ g_return_if_fail (GCR_IS_PARSER (parser));
+ g_return_if_fail (GCR_IS_IMPORTER (self));
+
+ attrs = gcr_parser_get_parsed_attributes (parser);
+ g_return_if_fail (attrs);
+
+ gcr_importer_queue (self, gcr_parser_get_parsed_label (parser), attrs);
+}
+
+static gboolean
+on_parser_authenticate (GcrParser *parser, gint count, GcrImporter *self)
+{
+ GcrImportDialog *dialog;
+ GP11Attributes *attrs;
+ const gchar *password;
+ gchar *text, *label;
+ GP11Slot *slot;
+ gulong klass;
+
+ dialog = _gcr_import_dialog_new ();
+
+ if (self->pv->slot)
+ _gcr_import_dialog_set_selected_slot (dialog, self->pv->slot);
+
+ /* Figure out the text for the dialog */
+ attrs = gcr_parser_get_parsed_attributes (parser);
+ g_return_val_if_fail (attrs, FALSE);
+
+ if (!gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass))
+ klass = (gulong)-1;
+ if (!gp11_attributes_find_string (attrs, CKA_LABEL, &label))
+ label = NULL;
+
+ text = prepare_auth_secondary (klass, label);
+ _gcr_import_dialog_set_primary_text (dialog, prepare_auth_primary (klass));
+ _gcr_import_dialog_set_secondary_text (dialog, text);
+ g_free (label);
+ g_free (text);
+
+ if (!_gcr_import_dialog_run (dialog, NULL))
+ return FALSE;
+
+ slot = _gcr_import_dialog_get_selected_slot (dialog);
+ gcr_importer_set_slot (self, slot);
+
+ password = _gcr_import_dialog_get_password (dialog);
+ gcr_parser_add_password (parser, password);
+
+ g_object_unref (dialog);
+ self->pv->prompted = TRUE;
+ return TRUE;
+}
+
/* ---------------------------------------------------------------------------------
* COMPLETE
*/
@@ -425,216 +511,6 @@ state_import_prompt (GcrImporter *self, gboolean async)
}
}
-/* ---------------------------------------------------------------------------------
- * PARSING
- */
-
-static const gchar*
-prepare_auth_primary (CK_OBJECT_CLASS klass)
-{
- if (klass == CKO_PRIVATE_KEY)
- return _("Enter password to unlock the private key");
- else if (klass == CKO_CERTIFICATE)
- return _("Enter password to unlock the certificate");
- else
- return _("Enter password to unlock");
-}
-
-static gchar*
-prepare_auth_secondary (CK_OBJECT_CLASS klass, const gchar *label)
-{
- if (label == NULL) {
- if (klass == CKO_PRIVATE_KEY) {
- /* TRANSLATORS: The key is locked. */
- return g_strdup (_("In order to import the private key, it must be unlocked"));
- } else if (klass == CKO_CERTIFICATE) {
- /* TRANSLATORS: The certificate is locked. */
- return g_strdup (_("In order to import the certificate, it must be unlocked"));
- } else {
- /* TRANSLATORS: The data is locked. */
- return g_strdup (_("In order to import the data, it must be unlocked"));
- }
- } else {
- if (klass == CKO_PRIVATE_KEY) {
- /* TRANSLATORS: The key is locked. */
- return g_strdup_printf (_("In order to import the private key '%s', it must be unlocked"), label);
- } else if (klass == CKO_CERTIFICATE) {
- /* TRANSLATORS: The certificate is locked. */
- return g_strdup_printf (_("In order to import the certificate '%s', it must be unlocked"), label);
- } else {
- /* TRANSLATORS: The object '%s' is locked. */
- return g_strdup_printf (_("In order to import '%s', it must be unlocked"), label);
- }
- }
-}
-
-static void
-on_parser_parsed (GcrParser *parser, GcrImporter *self)
-{
- GP11Attributes *attrs;
-
- g_return_if_fail (GCR_IS_PARSER (parser));
- g_return_if_fail (GCR_IS_IMPORTER (self));
-
- attrs = gcr_parser_get_parsed_attributes (parser);
- g_return_if_fail (attrs);
- g_queue_push_tail (&self->pv->queue, gp11_attributes_ref (attrs));
-}
-
-static gboolean
-on_parser_authenticate (GcrParser *parser, gint count, GcrImporter *self)
-{
- GcrImportDialog *dialog;
- GP11Attributes *attrs;
- const gchar *password;
- gchar *text, *label;
- GP11Slot *slot;
- gulong klass;
-
- dialog = _gcr_import_dialog_new ();
-
- if (self->pv->slot)
- _gcr_import_dialog_set_selected_slot (dialog, self->pv->slot);
-
- /* Figure out the text for the dialog */
- attrs = gcr_parser_get_parsed_attributes (parser);
- g_return_val_if_fail (attrs, FALSE);
-
- if (!gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass))
- klass = (gulong)-1;
- if (!gp11_attributes_find_string (attrs, CKA_LABEL, &label))
- label = NULL;
-
- text = prepare_auth_secondary (klass, label);
- _gcr_import_dialog_set_primary_text (dialog, prepare_auth_primary (klass));
- _gcr_import_dialog_set_secondary_text (dialog, text);
- g_free (label);
- g_free (text);
-
- if (!_gcr_import_dialog_run (dialog, NULL))
- return FALSE;
-
- slot = _gcr_import_dialog_get_selected_slot (dialog);
- gcr_importer_set_slot (self, slot);
-
- password = _gcr_import_dialog_get_password (dialog);
- gcr_parser_add_password (parser, password);
-
- g_object_unref (dialog);
- self->pv->prompted = TRUE;
- return TRUE;
-}
-
-static void
-state_parse_buffer (GcrImporter *self, gboolean async)
-{
- GError *error = NULL;
- GcrParser *parser;
- gulong parsed_conn;
- gulong auth_conn;
- gboolean ret;
-
- g_assert (GCR_IS_IMPORTER (self));
- g_assert (self->pv->buffer);
-
- parser = gcr_importer_get_parser (self);
- g_object_ref (parser);
-
- /* Listen in to the parser */
- parsed_conn = g_signal_connect (parser, "parsed", G_CALLBACK (on_parser_parsed), self);
- auth_conn = g_signal_connect (parser, "authenticate", G_CALLBACK (on_parser_authenticate), self);
-
- ret = gcr_parser_parse_data (parser, self->pv->buffer->data, self->pv->buffer->len, &error);
-
- /* An optimization to free data early as possible */
- g_byte_array_free (self->pv->buffer, TRUE);
- self->pv->buffer = NULL;
-
- g_signal_handler_disconnect (parser, parsed_conn);
- g_signal_handler_disconnect (parser, auth_conn);
- g_object_unref (parser);
-
- if (ret == TRUE) {
- next_state (self, state_import_prompt);
- } else {
- g_propagate_error (&self->pv->error, error);
- next_state (self, state_failure);
- }
-}
-
-/* ---------------------------------------------------------------------------------
- * BUFFER READING
- */
-
-static void
-complete_read_buffer (GcrImporter *self, gssize count, GError *error)
-{
- g_assert (GCR_IS_IMPORTER (self));
- g_assert (self->pv->buffer);
-
- /* A failure */
- if (count == -1) {
- g_propagate_error (&self->pv->error, error);
- next_state (self, state_failure);
- } else {
-
- g_return_if_fail (count >= 0 && count <= BLOCK);
- g_byte_array_set_size (self->pv->buffer, self->pv->buffer->len - (BLOCK - count));
-
- /* Finished reading */
- if (count == 0) {
-
- /* Optimization, unref input early */
- g_object_unref (self->pv->input);
- self->pv->input = NULL;
-
- next_state (self, state_parse_buffer);
-
- /* Read the next block */
- } else {
- next_state (self, state_read_buffer);
- }
- }
-
-}
-
-static void
-on_read_buffer (GObject *obj, GAsyncResult *res, gpointer user_data)
-{
- GError *error = NULL;
- gssize count;
-
- count = g_input_stream_read_finish (G_INPUT_STREAM (obj), res, &error);
- complete_read_buffer (user_data, count, error);
-}
-
-static void
-state_read_buffer (GcrImporter *self, gboolean async)
-{
- GError *error = NULL;
- gssize count;
- gsize at;
-
- g_assert (GCR_IS_IMPORTER (self));
- g_assert (G_IS_INPUT_STREAM (self->pv->input));
-
- if (!self->pv->buffer)
- self->pv->buffer = g_byte_array_sized_new (BLOCK);
-
- at = self->pv->buffer->len;
- g_byte_array_set_size (self->pv->buffer, at + BLOCK);
-
- if (async) {
- g_input_stream_read_async (self->pv->input, self->pv->buffer->data + at,
- BLOCK, G_PRIORITY_DEFAULT, self->pv->cancel,
- on_read_buffer, self);
- } else {
- count = g_input_stream_read (self->pv->input, self->pv->buffer->data + at,
- BLOCK, self->pv->cancel, &error);
- complete_read_buffer (self, count, error);
- }
-}
-
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -693,9 +569,6 @@ gcr_importer_set_property (GObject *obj, guint prop_id, const GValue *value,
GcrImporter *self = GCR_IMPORTER (obj);
switch (prop_id) {
- case PROP_PARSER:
- gcr_importer_set_parser (self, g_value_get_object (value));
- break;
case PROP_SLOT:
gcr_importer_set_slot (self, g_value_get_object (value));
break;
@@ -715,9 +588,6 @@ gcr_importer_get_property (GObject *obj, guint prop_id, GValue *value,
GcrImporter *self = GCR_IMPORTER (obj);
switch (prop_id) {
- case PROP_PARSER:
- g_value_set_object (value, gcr_importer_get_parser (self));
- break;
case PROP_SLOT:
g_value_set_object (value, gcr_importer_get_slot (self));
break;
@@ -742,19 +612,20 @@ gcr_importer_class_init (GcrImporterClass *klass)
gobject_class->get_property = gcr_importer_get_property;
g_type_class_add_private (gobject_class, sizeof (GcrImporterPrivate));
-
- g_object_class_install_property (gobject_class, PROP_PARSER,
- g_param_spec_object ("parser", "Parser", "Parser used to parse imported data",
- GCR_TYPE_PARSER, G_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class, PROP_PARSER,
+
+ g_object_class_install_property (gobject_class, PROP_SLOT,
g_param_spec_object ("slot", "Slot", "PKCS#11 slot to import data into",
GP11_TYPE_SLOT, G_PARAM_READWRITE));
-
+
g_object_class_install_property (gobject_class, PROP_PROMPT_BEHAVIOR,
g_param_spec_int ("prompt-behavior", "Prompt Behavior", "Import Prompt Behavior",
0, G_MAXINT, GCR_IMPORTER_PROMPT_NEEDED, G_PARAM_READWRITE));
-
+
+ signals[QUEUED] = g_signal_new ("queued", GCR_TYPE_IMPORTER,
+ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GcrImporterClass, queued),
+ NULL, NULL, _gcr_marshal_VOID__STRING_BOXED,
+ G_TYPE_NONE, 1, G_TYPE_STRING, GP11_TYPE_ATTRIBUTES);
+
signals[IMPORTED] = g_signal_new ("imported", GCR_TYPE_IMPORTER,
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GcrImporterClass, imported),
NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
@@ -794,28 +665,6 @@ gcr_importer_new (void)
return g_object_new (GCR_TYPE_IMPORTER, NULL);
}
-GcrParser*
-gcr_importer_get_parser (GcrImporter *self)
-{
- g_return_val_if_fail (GCR_IS_IMPORTER (self), NULL);
- if (!self->pv->parser)
- self->pv->parser = gcr_parser_new ();
- return self->pv->parser;
-}
-
-void
-gcr_importer_set_parser (GcrImporter *self, GcrParser *parser)
-{
- g_return_if_fail (GCR_IS_IMPORTER (self));
-
- if (parser)
- g_object_ref (parser);
- if (self->pv->parser)
- g_object_unref (self->pv->parser);
- self->pv->parser = parser;
- g_object_notify (G_OBJECT (self), "parser");
-}
-
GP11Slot*
gcr_importer_get_slot (GcrImporter *self)
{
@@ -852,26 +701,22 @@ gcr_importer_set_prompt_behavior (GcrImporter *self, GcrImporterPromptBehavior b
}
gboolean
-gcr_importer_import (GcrImporter *self, GInputStream *input,
- GCancellable *cancel, GError **error)
+gcr_importer_import (GcrImporter *self, GCancellable *cancel, GError **error)
{
g_return_val_if_fail (GCR_IS_IMPORTER (self), FALSE);
- g_return_val_if_fail (G_IS_INPUT_STREAM (input), FALSE);
g_return_val_if_fail (!error || !*error, FALSE);
g_return_val_if_fail (!self->pv->processing, FALSE);
-
+
cleanup_import_data (self);
-
- self->pv->input = g_object_ref (input);
+
if (cancel)
self->pv->cancel = g_object_ref (cancel);
self->pv->processing = TRUE;
self->pv->async = FALSE;
-
- next_state (self, state_read_buffer);
-
+
+ next_state (self, state_import_prompt);
+
g_assert (!self->pv->processing);
- g_assert (!self->pv->input);
g_assert (!self->pv->cancel);
if (!self->pv->succeeded) {
@@ -884,24 +729,22 @@ gcr_importer_import (GcrImporter *self, GInputStream *input,
}
void
-gcr_importer_import_async (GcrImporter *self, GInputStream *input, GCancellable *cancel,
+gcr_importer_import_async (GcrImporter *self, GCancellable *cancel,
GAsyncReadyCallback callback, gpointer user_data)
{
g_return_if_fail (GCR_IS_IMPORTER (self));
- g_return_if_fail (G_IS_INPUT_STREAM (input));
g_return_if_fail (!self->pv->processing);
-
+
cleanup_import_data (self);
-
- self->pv->input = g_object_ref (input);
+
if (cancel)
self->pv->cancel = g_object_ref (cancel);
self->pv->processing = TRUE;
self->pv->async = TRUE;
self->pv->callback = callback;
self->pv->user_data = user_data;
-
- next_state (self, state_read_buffer);
+
+ next_state (self, state_import_prompt);
g_assert (self->pv->processing);
}
@@ -913,9 +756,8 @@ gcr_importer_import_finish (GcrImporter *self, GAsyncResult *res, GError **error
g_return_val_if_fail (!error || !*error, FALSE);
g_return_val_if_fail (!self->pv->processing, FALSE);
- g_assert (!self->pv->input);
g_assert (!self->pv->cancel);
-
+
if (!self->pv->succeeded) {
g_propagate_error (error, self->pv->error);
self->pv->error = NULL;
@@ -924,3 +766,25 @@ gcr_importer_import_finish (GcrImporter *self, GAsyncResult *res, GError **error
return TRUE;
}
+
+
+void
+gcr_importer_listen (GcrImporter *self, GcrParser *parser)
+{
+ g_return_if_fail (GCR_IS_IMPORTER (self));
+ g_return_if_fail (GCR_IS_PARSER (self));
+
+ /* Listen in to the parser */
+ g_signal_connect_object (parser, "parsed", G_CALLBACK (on_parser_parsed), self, 0);
+ g_signal_connect_object (parser, "authenticate", G_CALLBACK (on_parser_authenticate), self, 0);
+}
+
+void
+gcr_importer_queue (GcrImporter *self, const gchar *label, GP11Attributes *attrs)
+{
+ g_return_if_fail (GCR_IS_IMPORTER (self));
+ g_return_if_fail (attrs);
+
+ g_queue_push_tail (&self->pv->queue, gp11_attributes_ref (attrs));
+ g_signal_emit (self, signals[QUEUED], 0, label, attrs);
+}
diff --git a/gcr/gcr-importer.h b/gcr/gcr-importer.h
index 358b302..2d9f794 100644
--- a/gcr/gcr-importer.h
+++ b/gcr/gcr-importer.h
@@ -53,9 +53,9 @@ struct _GcrImporter {
struct _GcrImporterClass {
GObjectClass parent_class;
-
+
/* signals */
-
+ void (*queued) (GcrImporter *self, const gchar *label, struct _GP11Attributes *attrs);
void (*imported) (GcrImporter *self, struct _GP11Object *object);
};
@@ -63,11 +63,6 @@ GType gcr_importer_get_type (void);
GcrImporter* gcr_importer_new (void);
-GcrParser* gcr_importer_get_parser (GcrImporter *self);
-
-void gcr_importer_set_parser (GcrImporter *self,
- GcrParser *parser);
-
struct _GP11Slot* gcr_importer_get_slot (GcrImporter *self);
void gcr_importer_set_slot (GcrImporter *self,
@@ -78,13 +73,18 @@ GcrImporterPromptBehavior gcr_importer_get_prompt_behavior (GcrImporter *self
void gcr_importer_set_prompt_behavior (GcrImporter *self,
GcrImporterPromptBehavior behavior);
+void gcr_importer_queue (GcrImporter *self,
+ const gchar *label,
+ struct _GP11Attributes *attrs);
+
+void gcr_importer_listen (GcrImporter *self,
+ GcrParser *parser);
+
gboolean gcr_importer_import (GcrImporter *self,
- GInputStream *input,
GCancellable *cancel,
GError **error);
void gcr_importer_import_async (GcrImporter *self,
- GInputStream *input,
GCancellable *cancel,
GAsyncReadyCallback callback,
gpointer user_data);
diff --git a/gcr/gcr-marshal.list b/gcr/gcr-marshal.list
index 8ff8506..a448d71 100644
--- a/gcr/gcr-marshal.list
+++ b/gcr/gcr-marshal.list
@@ -1 +1,2 @@
BOOLEAN:INT
+VOID:STRING,BOXED
diff --git a/gcr/gcr-parser.c b/gcr/gcr-parser.c
index 3d7febe..86ffe11 100644
--- a/gcr/gcr-parser.c
+++ b/gcr/gcr-parser.c
@@ -1665,3 +1665,305 @@ gcr_parser_get_parsed_label (GcrParser *self)
g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
return self->pv->parsed_label;
}
+
+/* ---------------------------------------------------------------------------------
+ * STREAM PARSING
+ */
+
+#define GCR_TYPE_PARSING (gcr_parsing_get_type ())
+#define GCR_PARSING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_PARSING, GcrParsing))
+#define GCR_IS_PARSING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_PARSING))
+
+typedef struct _GcrParsing {
+ GObjectClass parent;
+
+ GcrParser *parser;
+ gboolean async;
+ GCancellable *cancel;
+
+ /* Failure information */
+ GError *error;
+ gboolean complete;
+
+ /* Operation state */
+ GInputStream *input;
+ GByteArray *buffer;
+
+ /* Async callback stuff */
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+
+} GcrParsing;
+
+typedef struct _GcrParsingClass {
+ GObjectClass parent_class;
+} GcrParsingClass;
+
+/* State forward declarations */
+static void state_cancelled (GcrParsing *self, gboolean async);
+static void state_failure (GcrParsing *self, gboolean async);
+static void state_complete (GcrParsing *self, gboolean async);
+static void state_parse_buffer (GcrParsing *self, gboolean async);
+static void state_read_buffer (GcrParsing *self, gboolean async);
+
+/* Other forward declarations */
+static GType gcr_parsing_get_type (void) G_GNUC_CONST;
+static void gcr_parsing_async_result_init (GAsyncResultIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GcrParsing, gcr_parsing, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, gcr_parsing_async_result_init));
+
+#define BLOCK 4096
+
+static void
+next_state (GcrParsing *self, void (*state) (GcrParsing*, gboolean))
+{
+ g_assert (GCR_IS_PARSING (self));
+ g_assert (state);
+
+ if (self->cancel && g_cancellable_is_cancelled (self->cancel))
+ state = state_cancelled;
+
+ (state) (self, self->async);
+}
+
+static void
+state_complete (GcrParsing *self, gboolean async)
+{
+ g_assert (GCR_IS_PARSING (self));
+ g_assert (!self->complete);
+ self->complete = TRUE;
+ if (async && self->callback != NULL)
+ (self->callback) (G_OBJECT (self->parser), G_ASYNC_RESULT (self), self->user_data);
+}
+
+static void
+state_failure (GcrParsing *self, gboolean async)
+{
+ g_assert (GCR_IS_PARSING (self));
+ g_assert (self->error);
+ next_state (self, state_complete);
+}
+
+static void
+state_cancelled (GcrParsing *self, gboolean async)
+{
+ g_assert (GCR_IS_PARSING (self));
+ if (self->cancel && g_cancellable_is_cancelled (self->cancel))
+ g_cancellable_cancel (self->cancel);
+ if (self->error)
+ g_error_free (self->error);
+ self->error = g_error_new_literal (GCR_DATA_ERROR, GCR_ERROR_CANCELLED, _("The operation was cancelled"));
+ next_state (self, state_failure);
+}
+
+static void
+state_parse_buffer (GcrParsing *self, gboolean async)
+{
+ GError *error = NULL;
+ gboolean ret;
+
+ g_assert (GCR_IS_PARSING (self));
+ g_assert (self->buffer);
+
+ ret = gcr_parser_parse_data (self->parser, self->buffer->data, self->buffer->len, &error);
+
+ if (ret == TRUE) {
+ next_state (self, state_complete);
+ } else {
+ g_propagate_error (&self->error, error);
+ next_state (self, state_failure);
+ }
+}
+
+static void
+complete_read_buffer (GcrParsing *self, gssize count, GError *error)
+{
+ g_assert (GCR_IS_IMPORTER (self));
+ g_assert (self->buffer);
+
+ /* A failure */
+ if (count == -1) {
+ g_propagate_error (&self->error, error);
+ next_state (self, state_failure);
+ } else {
+
+ g_return_if_fail (count >= 0 && count <= BLOCK);
+ g_byte_array_set_size (self->buffer, self->buffer->len - (BLOCK - count));
+
+ /* Finished reading */
+ if (count == 0)
+ next_state (self, state_parse_buffer);
+
+ /* Read the next block */
+ else
+ next_state (self, state_read_buffer);
+ }
+
+}
+
+static void
+on_read_buffer (GObject *obj, GAsyncResult *res, gpointer user_data)
+{
+ GError *error = NULL;
+ gssize count;
+
+ count = g_input_stream_read_finish (G_INPUT_STREAM (obj), res, &error);
+ complete_read_buffer (user_data, count, error);
+}
+
+static void
+state_read_buffer (GcrParsing *self, gboolean async)
+{
+ GError *error = NULL;
+ gssize count;
+ gsize at;
+
+ g_assert (GCR_IS_IMPORTER (self));
+ g_assert (G_IS_INPUT_STREAM (self->input));
+
+ if (!self->buffer)
+ self->buffer = g_byte_array_sized_new (BLOCK);
+
+ at = self->buffer->len;
+ g_byte_array_set_size (self->buffer, at + BLOCK);
+
+ if (async) {
+ g_input_stream_read_async (self->input, self->buffer->data + at,
+ BLOCK, G_PRIORITY_DEFAULT, self->cancel,
+ on_read_buffer, self);
+ } else {
+ count = g_input_stream_read (self->input, self->buffer->data + at,
+ BLOCK, self->cancel, &error);
+ complete_read_buffer (self, count, error);
+ }
+}
+
+static void
+gcr_parsing_init (GcrParsing *self)
+{
+
+}
+
+static void
+gcr_parsing_finalize (GObject *obj)
+{
+ GcrParsing *self = GCR_PARSING (obj);
+
+ g_object_unref (self->parser);
+ self->parser = NULL;
+
+ g_object_unref (self->input);
+ self->input = NULL;
+
+ if (self->cancel)
+ g_object_unref (self->cancel);
+ self->cancel = NULL;
+
+ g_clear_error (&self->error);
+
+ if (self->buffer)
+ g_byte_array_free (self->buffer, TRUE);
+ self->buffer = NULL;
+
+ G_OBJECT_CLASS (gcr_parsing_parent_class)->finalize (obj);
+}
+
+static void
+gcr_parsing_class_init (GcrParsingClass *klass)
+{
+ G_OBJECT_CLASS (klass)->finalize = gcr_parsing_finalize;
+}
+
+static gpointer
+gcr_parsing_real_get_user_data (GAsyncResult *base)
+{
+ g_return_val_if_fail (GCR_IS_PARSING (base), NULL);
+ return GCR_PARSING (base)->user_data;
+}
+
+static GObject*
+gcr_parsing_real_get_source_object (GAsyncResult *base)
+{
+ g_return_val_if_fail (GCR_IS_PARSING (base), NULL);
+ return G_OBJECT (GCR_PARSING (base)->parser);
+}
+
+static void
+gcr_parsing_async_result_init (GAsyncResultIface *iface)
+{
+ iface->get_source_object = gcr_parsing_real_get_source_object;
+ iface->get_user_data = gcr_parsing_real_get_user_data;
+}
+
+static GcrParsing*
+gcr_parsing_new (GcrParser *parser, GInputStream *input, GCancellable *cancel)
+{
+ GcrParsing *self;
+
+ g_assert (GCR_IS_PARSER (parser));
+ g_assert (G_IS_INPUT_STREAM (input));
+
+ self = g_object_new (GCR_TYPE_PARSING, NULL);
+ self->parser = g_object_ref (parser);
+ self->input = g_object_ref (input);
+ if (cancel)
+ self->cancel = g_object_ref (cancel);
+
+ return self;
+}
+
+gboolean
+gcr_parser_parse_stream (GcrParser *self, GInputStream *input, GCancellable *cancel,
+ GError **error)
+{
+ GcrParsing *parsing;
+
+ g_return_val_if_fail (GCR_IS_PARSER (self), FALSE);
+ g_return_val_if_fail (G_IS_INPUT_STREAM (self), FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ parsing = gcr_parsing_new (self, input, cancel);
+ parsing->async = FALSE;
+
+ next_state (parsing, state_read_buffer);
+ g_assert (parsing->complete);
+
+ return gcr_parser_parse_stream_finish (self, G_ASYNC_RESULT (parsing), error);
+}
+
+void
+gcr_parser_parse_stream_async (GcrParser *self, GInputStream *input, GCancellable *cancel,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GcrParsing *parsing;
+
+ g_return_if_fail (GCR_IS_PARSER (self));
+ g_return_if_fail (G_IS_INPUT_STREAM (self));
+
+ parsing = gcr_parsing_new (self, input, cancel);
+ parsing->async = TRUE;
+ parsing->callback = callback;
+ parsing->user_data = user_data;
+
+ next_state (parsing, state_read_buffer);
+}
+
+gboolean
+gcr_parser_parse_stream_finish (GcrParser *self, GAsyncResult *res, GError **error)
+{
+ GcrParsing *parsing;
+
+ g_return_val_if_fail (GCR_IS_PARSING (res), FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ parsing = GCR_PARSING (res);
+ g_return_val_if_fail (parsing->complete, FALSE);
+
+ if (parsing->error) {
+ g_propagate_error (error, parsing->error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/gcr/gcr-parser.h b/gcr/gcr-parser.h
index 55c7671..c890eff 100644
--- a/gcr/gcr-parser.h
+++ b/gcr/gcr-parser.h
@@ -23,6 +23,7 @@
#define __GCR_PARSER_H__
#include <glib-object.h>
+#include <gio/gio.h>
#include "gcr-types.h"
@@ -74,6 +75,21 @@ gboolean gcr_parser_parse_data (GcrParser *self,
gsize n_data,
GError **err);
+gboolean gcr_parser_parse_stream (GcrParser *self,
+ GInputStream *input,
+ GCancellable *cancel,
+ GError **error);
+
+void gcr_parser_parse_stream_async (GcrParser *self,
+ GInputStream *input,
+ GCancellable *cancel,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gcr_parser_parse_stream_finish (GcrParser *self,
+ GAsyncResult *res,
+ GError **error);
+
void gcr_parser_add_password (GcrParser *self,
const gchar *password);
diff --git a/tool/gkr-tool-import.c b/tool/gkr-tool-import.c
index 74bbfab..99c3890 100644
--- a/tool/gkr-tool-import.c
+++ b/tool/gkr-tool-import.c
@@ -98,6 +98,7 @@ int
gkr_tool_import (int argc, char *argv[])
{
GcrImporter *importer;
+ GcrParser *parser;
GError *error = NULL;
GInputStream *input;
gboolean res;
@@ -129,8 +130,15 @@ gkr_tool_import (int argc, char *argv[])
gkr_tool_handle_error (&error, "couldn't read file: %s", *imp);
ret = 1;
} else {
- res = gcr_importer_import (importer, input, NULL, &error);
+ parser = gcr_parser_new ();
+ gcr_importer_listen (importer, parser);
+ res = gcr_parser_parse_stream (parser, input, NULL, &error);
g_object_unref (input);
+ g_object_unref (parser);
+
+ if (res == TRUE)
+ res = gcr_importer_import (importer, NULL, &error);
+
if (res == FALSE) {
if (!error || error->code != GCR_ERROR_CANCELLED)
gkr_tool_handle_error (&error, "couldn't import file: %s", *imp);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]