[seahorse] Reimplement export functionality
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [seahorse] Reimplement export functionality
- Date: Mon, 28 Nov 2011 11:29:42 +0000 (UTC)
commit 27614a2257ac0c663eb1372631c1870852eff05f
Author: Stef Walter <stefw collabora co uk>
Date: Mon Nov 28 12:23:16 2011 +0100
Reimplement export functionality
* SeahorseExportable interface on an object indicates export capability.
* SeahorseExporter represents a format for a given set of objects.
* Multiple objects can be combined using seahorse_exportable_add_object()
if the format supports it.
* So far only implemented one certificate exporter.
libseahorse/Makefile.am | 2 +
libseahorse/seahorse-exportable.c | 427 ++++++++++++++++++++++++++
libseahorse/seahorse-exportable.h | 72 +++++
libseahorse/seahorse-exporter.c | 273 +++++++++++++++++
libseahorse/seahorse-exporter.h | 101 +++++++
libseahorse/seahorse-key-manager-store.c | 88 ++----
libseahorse/seahorse-place.c | 168 -----------
libseahorse/seahorse-place.h | 37 ---
libseahorse/seahorse-util.c | 285 +++---------------
libseahorse/seahorse-util.h | 19 +-
libseahorse/seahorse-viewer.c | 165 +++--------
pgp/Makefile.am | 1 +
pgp/seahorse-gpg-op.c | 53 ++--
pgp/seahorse-gpg-op.h | 2 +-
pgp/seahorse-gpgme-exporter.c | 445 ++++++++++++++++++++++++++++
pgp/seahorse-gpgme-exporter.h | 47 +++
pgp/seahorse-gpgme-key.c | 48 +++-
pgp/seahorse-gpgme-keyring.c | 152 +----------
pgp/seahorse-hkp-source.c | 48 ++--
pgp/seahorse-ldap-source.c | 56 ++--
pgp/seahorse-pgp-key-properties.c | 82 ++----
pgp/seahorse-server-source.c | 10 +-
pgp/seahorse-server-source.h | 8 +-
pgp/seahorse-transfer.c | 67 +++--
pkcs11/Makefile.am | 1 +
pkcs11/seahorse-certificate-der-exporter.c | 245 +++++++++++++++
pkcs11/seahorse-certificate-der-exporter.h | 41 +++
pkcs11/seahorse-certificate.c | 27 ++-
pkcs11/seahorse-pkcs11-properties.c | 22 ++-
po/POTFILES.in | 4 +
src/seahorse-key-manager.ui | 2 +
ssh/Makefile.am | 1 +
ssh/seahorse-ssh-exporter.c | 321 ++++++++++++++++++++
ssh/seahorse-ssh-exporter.h | 42 +++
ssh/seahorse-ssh-key-properties.c | 77 ++---
ssh/seahorse-ssh-key.c | 37 ++-
ssh/seahorse-ssh-key.h | 2 +
ssh/seahorse-ssh-operation.c | 114 +++-----
ssh/seahorse-ssh-source.c | 82 -----
39 files changed, 2464 insertions(+), 1210 deletions(-)
---
diff --git a/libseahorse/Makefile.am b/libseahorse/Makefile.am
index 83f1c4d..d1a4b15 100644
--- a/libseahorse/Makefile.am
+++ b/libseahorse/Makefile.am
@@ -37,6 +37,8 @@ libseahorse_la_SOURCES = \
seahorse-context.c seahorse-context.h \
seahorse-debug.c seahorse-debug.h \
seahorse-delete-dialog.c seahorse-delete-dialog.h \
+ seahorse-exportable.c seahorse-exportable.h \
+ seahorse-exporter.c seahorse-exporter.h \
seahorse-icons.c seahorse-icons.h \
seahorse-key-manager-store.c seahorse-key-manager-store.h \
seahorse-object.c seahorse-object.h \
diff --git a/libseahorse/seahorse-exportable.c b/libseahorse/seahorse-exportable.c
new file mode 100644
index 0000000..ad4bad5
--- /dev/null
+++ b/libseahorse/seahorse-exportable.c
@@ -0,0 +1,427 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2004,2005 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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.
+ */
+
+#include "config.h"
+
+#include "seahorse-exportable.h"
+#include "seahorse-exporter.h"
+
+#include <glib/gi18n.h>
+
+#include <string.h>
+
+typedef SeahorseExportableIface SeahorseExportableInterface;
+
+G_DEFINE_INTERFACE (SeahorseExportable, seahorse_exportable, G_TYPE_OBJECT);
+
+GList *
+seahorse_exportable_create_exporters (SeahorseExportable *exportable,
+ SeahorseExporterType type)
+{
+ SeahorseExportableIface *iface;
+
+ g_return_val_if_fail (SEAHORSE_IS_EXPORTABLE (exportable), NULL);
+
+ iface = SEAHORSE_EXPORTABLE_GET_INTERFACE (exportable);
+ g_return_val_if_fail (iface->create_exporters, NULL);
+
+ return iface->create_exporters (exportable, type);
+}
+
+typedef struct {
+ GMainLoop *loop;
+ GAsyncResult *result;
+} WaitClosure;
+
+static WaitClosure *
+wait_closure_new (void)
+{
+ WaitClosure *closure;
+
+ closure = g_slice_new0 (WaitClosure);
+ closure->loop = g_main_loop_new (NULL, FALSE);
+
+ return closure;
+}
+
+static void
+wait_closure_free (WaitClosure *closure)
+{
+ g_clear_object (&closure->result);
+ g_main_loop_unref (closure->loop);
+ g_slice_free (WaitClosure, closure);
+}
+
+static void
+on_wait_complete (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ WaitClosure *closure = user_data;
+ g_assert (closure->result == NULL);
+ closure->result = g_object_ref (result);
+ g_main_loop_quit (closure->loop);
+}
+
+static void
+seahorse_exportable_default_init (SeahorseExportableIface *iface)
+{
+ static gboolean initialized = FALSE;
+ if (!initialized) {
+ initialized = TRUE;
+ }
+}
+
+guint
+seahorse_exportable_export_to_directory_wait (GList *objects,
+ const gchar *directory,
+ GError **error)
+{
+ SeahorseExporter *exporter;
+ WaitClosure *closure;
+ GList *exporters;
+ guint count = 0;
+ gboolean ret;
+ gchar *filename;
+ gchar *name;
+ GFile *file;
+ GList *l;
+
+ g_return_val_if_fail (directory != NULL, 0);
+ g_return_val_if_fail (error == NULL || *error == NULL, 0);
+
+ closure = wait_closure_new ();
+
+ for (l = objects; l != NULL; l = g_list_next (l)) {
+ if (!SEAHORSE_IS_EXPORTABLE (l->data))
+ continue;
+
+ exporters = seahorse_exportable_create_exporters (SEAHORSE_EXPORTABLE (l->data),
+ SEAHORSE_EXPORTER_ANY);
+ if (!exporters)
+ continue;
+
+ exporter = g_object_ref (exporters->data);
+ g_list_free_full (exporters, g_object_unref);
+
+ name = seahorse_exporter_get_filename (exporter);
+ filename = g_build_filename (directory, name, NULL);
+ g_free (name);
+
+ file = g_file_new_for_uri (filename);
+ seahorse_exporter_export_to_file_async (exporter, file, FALSE,
+ NULL, on_wait_complete, closure);
+ g_object_unref (file);
+
+ g_main_loop_run (closure->loop);
+
+ ret = seahorse_exporter_export_to_file_finish (exporter, closure->result, error);
+ g_object_unref (closure->result);
+ closure->result = NULL;
+
+ g_object_unref (exporter);
+ g_free (filename);
+
+ if (ret)
+ count++;
+ else
+ break;
+ }
+
+ wait_closure_free (closure);
+ return count;
+}
+
+guint
+seahorse_exportable_export_to_text_wait (GList *objects,
+ gpointer *data,
+ gsize *size,
+ GError **error)
+{
+ SeahorseExporter *exporter = NULL;
+ WaitClosure *closure;
+ GList *exporters = NULL;
+ guint count, total;
+ GList *l, *e;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, 0);
+ g_return_val_if_fail (data != NULL, 0);
+ g_return_val_if_fail (size != NULL, 0);
+
+ for (l = objects; l != NULL; l = g_list_next (l)) {
+ if (!SEAHORSE_IS_EXPORTABLE (l->data))
+ continue;
+
+ /* If we've already found exporters, then add to those */
+ if (exporters) {
+ for (e = exporters; e != NULL; e = g_list_next (e))
+ seahorse_exporter_add_object (e->data, l->data);
+
+ /* Otherwise try and create new exporters for this object */
+ } else {
+ exporters = seahorse_exportable_create_exporters (SEAHORSE_EXPORTABLE (l->data),
+ SEAHORSE_EXPORTER_TEXTUAL);
+ }
+ }
+
+ /* Find the exporter than has the most objects */
+ for (e = exporters, total = 0, exporter = NULL;
+ e != NULL; e = g_list_next (e)) {
+ count = g_list_length (seahorse_exporter_get_objects (e->data));
+ if (count > total) {
+ total = count;
+ g_clear_object (&exporter);
+ exporter = g_object_ref (e->data);
+ }
+ }
+
+ g_list_free_full (exporters, g_object_unref);
+
+ if (exporter) {
+ closure = wait_closure_new ();
+
+ seahorse_exporter_export_async (exporter, NULL, on_wait_complete, closure);
+
+ g_main_loop_run (closure->loop);
+
+ *data = seahorse_exporter_export_finish (exporter, closure->result, size, error);
+ if (*data == NULL)
+ total = 0;
+
+ wait_closure_free (closure);
+ g_object_unref (exporter);
+ }
+
+ return total;
+}
+
+guint
+seahorse_exportable_export_to_prompt_wait (GList *objects,
+ GtkWindow *parent,
+ GError **error)
+{
+ SeahorseExporter *exporter;
+ gchar *directory = NULL;
+ WaitClosure *closure;
+ GHashTable *pending;
+ GList *exporters;
+ guint count = 0;
+ gboolean ret;
+ GList *l, *e, *x;
+ GList *exported;
+ GFile *file;
+
+ g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), 0);
+ g_return_val_if_fail (error == NULL || *error == NULL, 0);
+
+ /* A table for monitoring which objects are still pending */
+ pending = g_hash_table_new (g_direct_hash, g_direct_equal);
+ for (l = objects; l != NULL; l = g_list_next (l))
+ g_hash_table_replace (pending, l->data, l->data);
+
+ closure = wait_closure_new ();
+
+ for (l = objects; l != NULL; l = g_list_next (l)) {
+ if (!g_hash_table_lookup (pending, l->data))
+ continue;
+
+ if (!SEAHORSE_IS_EXPORTABLE (l->data)) {
+ g_hash_table_remove (pending, l->data);
+ continue;
+ }
+
+ exporters = seahorse_exportable_create_exporters (SEAHORSE_EXPORTABLE (l->data),
+ SEAHORSE_EXPORTER_ANY);
+ if (!exporters)
+ continue;
+
+ /* Now go and add all pending to each exporter */
+ for (x = objects; x != NULL; x = g_list_next (x)) {
+ if (x->data == l->data)
+ continue;
+ if (g_hash_table_lookup (pending, x->data)) {
+ for (e = exporters; e != NULL; e = g_list_next (e))
+ seahorse_exporter_add_object (e->data, x->data);
+ }
+ }
+
+ /* Now show a prompt choosing between the exporters */
+ ret = seahorse_exportable_prompt (exporters, parent,
+ &directory, &file, &exporter);
+
+ g_list_free_full (exporters, g_object_unref);
+
+ if (!ret)
+ break;
+
+ seahorse_exporter_export_to_file_async (exporter, file, TRUE,
+ NULL, on_wait_complete, closure);
+
+ g_main_loop_run (closure->loop);
+
+ ret = seahorse_exporter_export_to_file_finish (exporter, closure->result, error);
+ g_object_unref (closure->result);
+ closure->result = NULL;
+
+ if (ret) {
+ exported = seahorse_exporter_get_objects (exporter);
+ for (e = exported; e != NULL; e = g_list_next (e)) {
+ g_hash_table_remove (pending, e->data);
+ count++;
+ }
+ }
+
+ g_object_unref (file);
+ g_object_unref (exporter);
+
+ if (!ret)
+ break;
+ }
+
+ g_free (directory);
+ wait_closure_free (closure);
+ g_hash_table_destroy (pending);
+ return count;
+
+}
+
+static gchar *
+calculate_basename (GFile *file,
+ const gchar *extension)
+{
+ gchar *basename = g_file_get_basename (file);
+ gchar *name;
+ gchar *cut;
+
+ cut = strrchr (basename, '.');
+ if (cut != NULL)
+ cut[0] = '\0';
+
+ name = g_strdup_printf ("%s%s", basename, extension);
+ g_free (basename);
+
+ return name;
+}
+
+static void
+on_filter_changed (GObject *obj,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GHashTable *filters = user_data;
+ GtkFileChooser *chooser = GTK_FILE_CHOOSER (obj);
+ SeahorseExporter *exporter;
+ GtkFileFilter *filter;
+ const gchar *extension;
+ gchar *basename;
+ gchar *name;
+ GFile *file;
+
+ filter = gtk_file_chooser_get_filter (chooser);
+ g_return_if_fail (filter != NULL);
+
+ exporter = g_hash_table_lookup (filters, filter);
+ g_return_if_fail (exporter != NULL);
+
+ name = seahorse_exporter_get_filename (exporter);
+ g_return_if_fail (name != NULL);
+
+ extension = strrchr (name, '.');
+ if (extension) {
+ file = gtk_file_chooser_get_file (chooser);
+ if (file) {
+ basename = calculate_basename (file, extension);
+ g_object_unref (file);
+ if (basename)
+ gtk_file_chooser_set_current_name (chooser, basename);
+ g_free (basename);
+ } else {
+ gtk_file_chooser_set_current_name (chooser, name);
+ }
+ }
+
+ g_free (name);
+}
+
+gboolean
+seahorse_exportable_prompt (GList *exporters,
+ GtkWindow *parent,
+ gchar **directory,
+ GFile **file,
+ SeahorseExporter **exporter)
+{
+ GtkWidget *widget;
+ GtkDialog *dialog;
+ GtkFileChooser *chooser;
+ GHashTable *filters;
+ GtkFileFilter *first = NULL;
+ GtkFileFilter *filter;
+ gboolean result = FALSE;
+ GList *e;
+
+ g_return_val_if_fail (exporters != NULL, FALSE);
+ g_return_val_if_fail (parent == NULL || GTK_WINDOW (parent), FALSE);
+ g_return_val_if_fail (file != NULL, FALSE);
+ g_return_val_if_fail (exporter != NULL, FALSE);
+
+ widget = gtk_file_chooser_dialog_new (NULL, parent, GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("Export"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ dialog = GTK_DIALOG (widget);
+ chooser = GTK_FILE_CHOOSER (widget);
+
+ gtk_dialog_set_default_response (dialog, GTK_RESPONSE_ACCEPT);
+ gtk_file_chooser_set_local_only (chooser, FALSE);
+ gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE);
+
+ if (directory && *directory != NULL)
+ gtk_file_chooser_set_current_folder (chooser, *directory);
+
+ filters = g_hash_table_new (g_direct_hash, g_direct_equal);
+ for (e = exporters; e != NULL; e = g_list_next (e)) {
+ filter = seahorse_exporter_get_file_filter (e->data);
+ g_hash_table_replace (filters, filter, e->data);
+ gtk_file_chooser_add_filter (chooser, filter);
+ if (first == NULL)
+ first = filter;
+ }
+
+ g_signal_connect (chooser, "notify::filter", G_CALLBACK (on_filter_changed), filters);
+ gtk_file_chooser_set_filter (chooser, first);
+
+ if (gtk_dialog_run (dialog) == GTK_RESPONSE_ACCEPT) {
+ *file = gtk_file_chooser_get_file (chooser);
+ filter = gtk_file_chooser_get_filter (chooser);
+ *exporter = g_object_ref (g_hash_table_lookup (filters, filter));
+ if (directory) {
+ g_free (*directory);
+ *directory = g_strdup (gtk_file_chooser_get_current_folder (chooser));
+ }
+ result = TRUE;
+ }
+
+ g_hash_table_destroy (filters);
+ gtk_widget_destroy (widget);
+ return result;
+}
diff --git a/libseahorse/seahorse-exportable.h b/libseahorse/seahorse-exportable.h
new file mode 100644
index 0000000..4474151
--- /dev/null
+++ b/libseahorse/seahorse-exportable.h
@@ -0,0 +1,72 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Exportable, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef __SEAHORSE_EXPORTABLE_H__
+#define __SEAHORSE_EXPORTABLE_H__
+
+#include "seahorse-exporter.h"
+
+#include <gio/gio.h>
+
+#include <gtk/gtk.h>
+
+#define SEAHORSE_TYPE_EXPORTABLE (seahorse_exportable_get_type ())
+#define SEAHORSE_EXPORTABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_EXPORTABLE, SeahorseExportable))
+#define SEAHORSE_IS_EXPORTABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_EXPORTABLE))
+#define SEAHORSE_EXPORTABLE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SEAHORSE_TYPE_EXPORTABLE, SeahorseExportableIface))
+
+typedef struct _SeahorseExportable SeahorseExportable;
+typedef struct _SeahorseExportableIface SeahorseExportableIface;
+
+struct _SeahorseExportableIface {
+ GTypeInterface parent;
+
+ GList * (* create_exporters) (SeahorseExportable *exportable,
+ SeahorseExporterType type);
+};
+
+GType seahorse_exportable_get_type (void) G_GNUC_CONST;
+
+GList * seahorse_exportable_create_exporters (SeahorseExportable *exportable,
+ SeahorseExporterType type);
+
+guint seahorse_exportable_export_to_directory_wait (GList *objects,
+ const gchar *directory,
+ GError **error);
+
+guint seahorse_exportable_export_to_text_wait (GList *objects,
+ gpointer *data,
+ gsize *size,
+ GError **error);
+
+guint seahorse_exportable_export_to_prompt_wait (GList *objects,
+ GtkWindow *parent,
+ GError **error);
+
+gboolean seahorse_exportable_prompt (GList *exporters,
+ GtkWindow *parent,
+ gchar **directory,
+ GFile **file,
+ SeahorseExporter **exporter);
+
+#endif /* __SEAHORSE_EXPORTABLE_H__ */
diff --git a/libseahorse/seahorse-exporter.c b/libseahorse/seahorse-exporter.c
new file mode 100644
index 0000000..a0f89cf
--- /dev/null
+++ b/libseahorse/seahorse-exporter.c
@@ -0,0 +1,273 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2004,2005 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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.
+ */
+
+#include "config.h"
+
+#include "seahorse-exporter.h"
+#include "seahorse-util.h"
+
+typedef SeahorseExporterIface SeahorseExporterInterface;
+
+G_DEFINE_INTERFACE (SeahorseExporter, seahorse_exporter, G_TYPE_OBJECT);
+
+static void
+seahorse_exporter_default_init (SeahorseExporterIface *iface)
+{
+ static gboolean initialized = FALSE;
+ if (!initialized) {
+ g_object_interface_install_property (iface,
+ g_param_spec_string ("filename", "File name", "File name",
+ NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_string ("content-type", "Content type", "Content type",
+ NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_object ("file-filter", "File filter", "File chooser filter",
+ GTK_TYPE_FILE_FILTER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ initialized = TRUE;
+ }
+}
+
+gchar *
+seahorse_exporter_get_filename (SeahorseExporter *exporter)
+{
+ gchar *filename = NULL;
+
+ g_return_val_if_fail (SEAHORSE_IS_EXPORTER (exporter), NULL);
+
+ g_object_get (exporter, "filename", &filename, NULL);
+ return filename;
+}
+
+gchar *
+seahorse_exporter_get_content_type (SeahorseExporter *exporter)
+{
+ gchar *content_type = NULL;
+
+ g_return_val_if_fail (SEAHORSE_IS_EXPORTER (exporter), NULL);
+
+ g_object_get (exporter, "content-type", &content_type, NULL);
+ return content_type;
+}
+
+GtkFileFilter *
+seahorse_exporter_get_file_filter (SeahorseExporter *exporter)
+{
+ GtkFileFilter *filter = NULL;
+
+ g_return_val_if_fail (SEAHORSE_IS_EXPORTER (exporter), NULL);
+
+ g_object_get (exporter, "file-filter", &filter, NULL);
+ return filter;
+}
+
+GList *
+seahorse_exporter_get_objects (SeahorseExporter *exporter)
+{
+ SeahorseExporterIface *iface;
+
+ g_return_val_if_fail (SEAHORSE_IS_EXPORTER (exporter), NULL);
+
+ iface = SEAHORSE_EXPORTER_GET_INTERFACE (exporter);
+ g_return_val_if_fail (iface->get_objects != NULL, NULL);
+
+ return (iface->get_objects) (exporter);
+}
+
+gboolean
+seahorse_exporter_add_object (SeahorseExporter *exporter,
+ GObject *object)
+{
+ SeahorseExporterIface *iface;
+
+ g_return_val_if_fail (SEAHORSE_IS_EXPORTER (exporter), FALSE);
+ g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
+
+ iface = SEAHORSE_EXPORTER_GET_INTERFACE (exporter);
+ g_return_val_if_fail (iface->add_object != NULL, FALSE);
+
+ return (iface->add_object) (exporter, object);
+}
+
+void
+seahorse_exporter_export_async (SeahorseExporter *exporter,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SeahorseExporterIface *iface;
+
+ g_return_if_fail (SEAHORSE_IS_EXPORTER (exporter));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ iface = SEAHORSE_EXPORTER_GET_INTERFACE (exporter);
+ g_return_if_fail (iface->export_async != NULL);
+
+ (iface->export_async) (exporter, cancellable, callback, user_data);
+}
+
+gpointer
+seahorse_exporter_export_finish (SeahorseExporter *exporter,
+ GAsyncResult *result,
+ gsize *size,
+ GError **error)
+{
+ SeahorseExporterIface *iface;
+
+ g_return_val_if_fail (SEAHORSE_IS_EXPORTER (exporter), NULL);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (size != NULL, NULL);
+
+ iface = SEAHORSE_EXPORTER_GET_INTERFACE (exporter);
+ g_return_val_if_fail (iface->export_finish != NULL, NULL);
+
+ return (iface->export_finish) (exporter, result, size, error);
+}
+
+typedef struct {
+ GCancellable *cancellable;
+ gboolean overwrite;
+ guint unique;
+ gpointer data;
+ gsize size;
+ GFile *file;
+} FileClosure;
+
+static void
+file_closure_free (gpointer data)
+{
+ FileClosure *closure = data;
+ g_clear_object (&closure->cancellable);
+ g_object_unref (closure->file);
+ g_free (closure->data);
+ g_free (closure);
+}
+
+static void
+on_export_replace (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ FileClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GError *error = NULL;
+ GFile *file;
+
+ if (g_file_replace_contents_finish (closure->file, result, NULL, &error)) {
+ g_simple_async_result_complete (res);
+
+ /* Not overwriting, and the file existed, try another file name */
+ } else if (!closure->overwrite && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WRONG_ETAG)) {
+ file = seahorse_util_file_increment_unique (closure->file, &closure->unique);
+
+ g_file_replace_contents_async (file, closure->data, closure->size, "invalid-etag",
+ FALSE, G_FILE_CREATE_PRIVATE, closure->cancellable,
+ on_export_replace, g_object_ref (res));
+
+ g_clear_error (&error);
+ g_object_unref (file);
+
+ } else {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+ }
+
+ g_object_unref (res);
+}
+
+static void
+on_export_complete (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ FileClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GError *error = NULL;
+
+ closure->data = seahorse_exporter_export_finish (SEAHORSE_EXPORTER (source),
+ result, &closure->size, &error);
+ if (error == NULL) {
+ /*
+ * When not trying to overwrite we pass an invalid etag. This way
+ * if the file exists, it will not match the etag, and we'll be
+ * able to detect it and try another file name.
+ */
+ g_file_replace_contents_async (closure->file, closure->data,
+ closure->size, closure->overwrite ? NULL : "invalid-etag",
+ FALSE, G_FILE_CREATE_PRIVATE, closure->cancellable,
+ on_export_replace, g_object_ref (res));
+ } else {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+ }
+
+ g_object_unref (res);
+}
+
+void
+seahorse_exporter_export_to_file_async (SeahorseExporter *exporter,
+ GFile *file,
+ gboolean overwrite,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ FileClosure *closure;
+
+ g_return_if_fail (SEAHORSE_IS_EXPORTER (exporter));
+ g_return_if_fail (G_IS_FILE (file));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ res = g_simple_async_result_new (G_OBJECT (exporter), callback, user_data,
+ seahorse_exporter_export_to_file_async);
+ closure = g_new0 (FileClosure, 1);
+ closure->file = g_object_ref (file);
+ closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+ closure->overwrite = overwrite;
+ g_simple_async_result_set_op_res_gpointer (res, closure, file_closure_free);
+
+ seahorse_exporter_export_async (exporter, cancellable, on_export_complete,
+ g_object_ref (res));
+
+ g_object_unref (res);
+}
+
+gboolean
+seahorse_exporter_export_to_file_finish (SeahorseExporter *exporter,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (SEAHORSE_IS_EXPORTER (exporter), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (exporter),
+ seahorse_exporter_export_to_file_async), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/libseahorse/seahorse-exporter.h b/libseahorse/seahorse-exporter.h
new file mode 100644
index 0000000..698545d
--- /dev/null
+++ b/libseahorse/seahorse-exporter.h
@@ -0,0 +1,101 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Exporter, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef __SEAHORSE_EXPORTER_H__
+#define __SEAHORSE_EXPORTER_H__
+
+#include "seahorse-types.h"
+
+#include <gio/gio.h>
+
+#include <gtk/gtk.h>
+
+typedef enum {
+ SEAHORSE_EXPORTER_ANY,
+ SEAHORSE_EXPORTER_TEXTUAL
+} SeahorseExporterType;
+
+#define SEAHORSE_TYPE_EXPORTER (seahorse_exporter_get_type ())
+#define SEAHORSE_EXPORTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_EXPORTER, SeahorseExporter))
+#define SEAHORSE_IS_EXPORTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_EXPORTER))
+#define SEAHORSE_EXPORTER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SEAHORSE_TYPE_EXPORTER, SeahorseExporterIface))
+
+typedef struct _SeahorseExporter SeahorseExporter;
+typedef struct _SeahorseExporterIface SeahorseExporterIface;
+
+struct _SeahorseExporterIface {
+ GTypeInterface parent;
+
+ /* virtual methods ------------------------------------------------- */
+
+ GList * (* get_objects) (SeahorseExporter *exporter);
+
+ gboolean (* add_object) (SeahorseExporter *exporter,
+ GObject *object);
+
+ void (* export_async) (SeahorseExporter *exporter,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ gpointer (* export_finish) (SeahorseExporter *exporter,
+ GAsyncResult *result,
+ gsize *size,
+ GError **error);
+};
+
+GType seahorse_exporter_get_type (void) G_GNUC_CONST;
+
+gchar * seahorse_exporter_get_filename (SeahorseExporter *exporter);
+
+gchar * seahorse_exporter_get_content_type (SeahorseExporter *exporter);
+
+GtkFileFilter * seahorse_exporter_get_file_filter (SeahorseExporter *exporter);
+
+GList * seahorse_exporter_get_objects (SeahorseExporter *exporter);
+
+gboolean seahorse_exporter_add_object (SeahorseExporter *exporter,
+ GObject *object);
+
+void seahorse_exporter_export_async (SeahorseExporter *exporter,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gpointer seahorse_exporter_export_finish (SeahorseExporter *exporter,
+ GAsyncResult *result,
+ gsize *size,
+ GError **error);
+
+void seahorse_exporter_export_to_file_async (SeahorseExporter *exporter,
+ GFile *file,
+ gboolean overwrite,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean seahorse_exporter_export_to_file_finish (SeahorseExporter *exporter,
+ GAsyncResult *result,
+ GError **error);
+
+#endif /* __SEAHORSE_EXPORTER_H__ */
diff --git a/libseahorse/seahorse-key-manager-store.c b/libseahorse/seahorse-key-manager-store.c
index 1e7ccf2..670e1b1 100644
--- a/libseahorse/seahorse-key-manager-store.c
+++ b/libseahorse/seahorse-key-manager-store.c
@@ -23,6 +23,7 @@
#include "config.h"
+#include "seahorse-exportable.h"
#include "seahorse-place.h"
#include "seahorse-util.h"
@@ -348,70 +349,47 @@ typedef struct {
} export_keys_to_output_closure;
static gboolean
-export_to_text (SeahorseKeyManagerStore *skstore,
+export_to_text (SeahorseKeyManagerStore *self,
GtkSelectionData *selection_data)
{
- GOutputStream *output;
- gboolean ret = FALSE;
+ gpointer output;
+ gsize size;
+ gboolean ret;
+ guint count;
- g_return_val_if_fail (skstore->priv->drag_objects, FALSE);
+ g_return_val_if_fail (self->priv->drag_objects, FALSE);
seahorse_debug ("exporting to text");
- output = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
- g_return_val_if_fail (output, FALSE);
+ count = seahorse_exportable_export_to_text_wait (self->priv->drag_objects,
+ &output, &size, &self->priv->drag_error);
- ret = seahorse_place_export_auto_wait (skstore->priv->drag_objects, output,
- &skstore->priv->drag_error) &&
- g_output_stream_close (output, NULL, &skstore->priv->drag_error);
+ /* TODO: Need to print status if only partially exported */
- if (ret) {
+ if (count > 0) {
seahorse_debug ("setting selection text");
- gtk_selection_data_set_text (selection_data,
- g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (output)),
- g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (output)));
+ gtk_selection_data_set_text (selection_data, output, size);
+ ret = TRUE;
+ } else if (self->priv->drag_error) {
+ g_message ("error occurred on export: %s", self->priv->drag_error->message);
+ ret = FALSE;
} else {
- g_message ("error occurred on export: %s",
- skstore->priv->drag_error && skstore->priv->drag_error->message ?
- skstore->priv->drag_error->message : "");
+ g_message ("no objects exported");
+ ret = FALSE;
}
- g_object_unref (output);
+ g_free (output);
return ret;
}
static gboolean
-export_to_filename (SeahorseKeyManagerStore *skstore, const gchar *filename)
+export_to_directory (SeahorseKeyManagerStore *self,
+ const gchar *directory)
{
- GOutputStream *output;
- gboolean ret;
- gchar *uri;
- GFile *file;
- GList *keys;
-
- seahorse_debug ("exporting to %s", filename);
-
- ret = FALSE;
- g_return_val_if_fail (skstore->priv->drag_objects, FALSE);
- keys = g_list_copy (skstore->priv->drag_objects);
-
- uri = seahorse_util_uri_unique (filename);
-
- /* Create output file */
- file = g_file_new_for_uri (uri);
- g_free (uri);
- output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE,
- NULL, &skstore->priv->drag_error));
- g_object_unref (file);
+ seahorse_debug ("exporting to %s", directory);
- if (output) {
- /* This modifies and frees keys */
- ret = seahorse_place_export_auto_wait (keys, output, &skstore->priv->drag_error) &&
- g_output_stream_close (output, NULL, &skstore->priv->drag_error);
-
- g_object_unref (output);
- }
-
- return ret;
+ return seahorse_exportable_export_to_directory_wait (self->priv->drag_objects,
+ directory,
+ &self->priv->drag_error);
}
static gboolean
@@ -455,22 +433,10 @@ drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *sel
static void
drag_end (GtkWidget *widget, GdkDragContext *context, SeahorseKeyManagerStore *skstore)
{
- gchar *filename, *name;
-
seahorse_debug ("drag_end -->");
- if (skstore->priv->drag_destination && !skstore->priv->drag_error) {
- g_return_if_fail (skstore->priv->drag_objects);
-
- name = seahorse_util_filename_for_objects (skstore->priv->drag_objects);
- g_return_if_fail (name);
-
- filename = g_build_filename (skstore->priv->drag_destination, name, NULL);
- g_free (name);
-
- export_to_filename (skstore, filename);
- g_free (filename);
- }
+ if (skstore->priv->drag_destination && !skstore->priv->drag_error)
+ export_to_directory (skstore, skstore->priv->drag_destination);
if (skstore->priv->drag_error) {
seahorse_util_show_error (widget, _("Couldn't export keys"),
diff --git a/libseahorse/seahorse-place.c b/libseahorse/seahorse-place.c
index aaec3aa..1bbe98a 100644
--- a/libseahorse/seahorse-place.c
+++ b/libseahorse/seahorse-place.c
@@ -109,171 +109,3 @@ seahorse_place_import_finish (SeahorsePlace *place,
g_return_val_if_fail (SEAHORSE_PLACE_GET_INTERFACE (place)->import_finish, NULL);
return SEAHORSE_PLACE_GET_INTERFACE (place)->import_finish (place, result, error);
}
-
-void
-seahorse_place_export_async (SeahorsePlace *place,
- GList *objects,
- GOutputStream *output,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- SeahorsePlaceIface *iface;
-
- g_return_if_fail (SEAHORSE_IS_PLACE (place));
- g_return_if_fail (G_IS_OUTPUT_STREAM (output));
- g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
- iface = SEAHORSE_PLACE_GET_INTERFACE (place);
- g_return_if_fail (iface->export_async != NULL);
-
- iface->export_async (place, objects, output,
- cancellable, callback, user_data);
-}
-
-GOutputStream *
-seahorse_place_export_finish (SeahorsePlace *place,
- GAsyncResult *result,
- GError **error)
-{
- SeahorsePlaceIface *iface;
-
- g_return_val_if_fail (SEAHORSE_IS_PLACE (place), NULL);
- g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- iface = SEAHORSE_PLACE_GET_INTERFACE (place);
- g_return_val_if_fail (iface->export_async != NULL, NULL);
- g_return_val_if_fail (iface->export_finish, NULL);
- return (iface->export_finish) (place, result, error);
-}
-
-typedef struct {
- GOutputStream *output;
- guint exports;
-} export_auto_closure;
-
-static void
-export_auto_free (gpointer data)
-{
- export_auto_closure *closure = data;
- g_object_unref (closure->output);
- g_free (closure);
-}
-
-static void
-on_export_auto_complete (GObject *place,
- GAsyncResult *result,
- gpointer user_data)
-{
- GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- export_auto_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
- GError *error = NULL;
-
- if (!seahorse_place_export_finish (SEAHORSE_PLACE (place), result, &error))
- g_simple_async_result_take_error (res, error);
-
- g_assert (closure->exports > 0);
- closure->exports--;
-
- if (closure->exports == 0)
- g_simple_async_result_complete (res);
-
- g_object_unref (res);
-}
-
-void
-seahorse_place_export_auto_async (GList *objects,
- GOutputStream *output,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *res;
- export_auto_closure *closure;
- SeahorsePlace *place;
- GObject *object;
- GList *next;
-
- res = g_simple_async_result_new (NULL, callback, user_data,
- seahorse_place_export_auto_async);
- closure = g_new0 (export_auto_closure, 1);
- closure->output = g_object_ref (output);
- g_simple_async_result_set_op_res_gpointer (res, closure, export_auto_free);
-
- /* Sort by object place */
- objects = g_list_copy (objects);
- objects = seahorse_util_objects_sort_by_place (objects);
-
- while (objects) {
-
- /* Break off one set (same place) */
- next = seahorse_util_objects_splice_by_place (objects);
-
- g_assert (G_IS_OBJECT (objects->data));
- object = G_OBJECT (objects->data);
-
- /* Export from this object place */
- place = NULL;
- g_object_get (object, "place", &place, NULL);
- g_return_if_fail (place != NULL);
-
- /* We pass our own data object, to which data is appended */
- seahorse_place_export_async (place, objects, output, cancellable,
- on_export_auto_complete, g_object_ref (res));
- closure->exports++;
-
- g_list_free (objects);
- objects = next;
- }
-
- if (closure->exports == 0)
- g_simple_async_result_complete_in_idle (res);
-
- g_object_unref (res);
-}
-
-GOutputStream *
-seahorse_place_export_auto_finish (GAsyncResult *result,
- GError **error)
-{
- export_auto_closure *closure;
-
- g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
- seahorse_place_export_auto_async), NULL);
-
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
- return NULL;
-
- closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
- return closure->output;
-
-}
-
-static void
-on_export_auto_wait_complete (GObject *place,
- GAsyncResult *result,
- gpointer user_data)
-{
- GAsyncResult **ret = user_data;
- *ret = g_object_ref (result);
-}
-
-gboolean
-seahorse_place_export_auto_wait (GList *objects,
- GOutputStream *output,
- GError **error)
-{
- GAsyncResult *result = NULL;
- gboolean ret;
-
- seahorse_place_export_auto_async (objects, output, NULL,
- on_export_auto_wait_complete,
- &result);
-
- seahorse_util_wait_until (result != NULL);
-
- ret = seahorse_place_export_auto_finish (result, error) != NULL;
- g_object_unref (result);
- return ret;
-}
diff --git a/libseahorse/seahorse-place.h b/libseahorse/seahorse-place.h
index 5b05d3e..c0e72da 100644
--- a/libseahorse/seahorse-place.h
+++ b/libseahorse/seahorse-place.h
@@ -58,25 +58,12 @@ struct _SeahorsePlaceIface {
GList * (*import_finish) (SeahorsePlace *place,
GAsyncResult *result,
GError **error);
-
- void (*export_async) (SeahorsePlace *place,
- GList *objects,
- GOutputStream *output,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
- GOutputStream * (*export_finish) (SeahorsePlace *place,
- GAsyncResult *result,
- GError **error);
};
GType seahorse_place_get_type (void) G_GNUC_CONST;
GtkActionGroup * seahorse_place_get_actions (SeahorsePlace *self);
-/* Method helper functions ------------------------------------------- */
-
void seahorse_place_import_async (SeahorsePlace *place,
GInputStream *input,
GCancellable *cancellable,
@@ -87,28 +74,4 @@ GList * seahorse_place_import_finish (SeahorsePlace *place,
GAsyncResult *result,
GError **error);
-void seahorse_place_export_async (SeahorsePlace *place,
- GList *objects,
- GOutputStream *output,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
-GOutputStream * seahorse_place_export_finish (SeahorsePlace *place,
- GAsyncResult *result,
- GError **error);
-
-void seahorse_place_export_auto_async (GList *objects,
- GOutputStream *output,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
-GOutputStream * seahorse_place_export_auto_finish (GAsyncResult *result,
- GError **error);
-
-gboolean seahorse_place_export_auto_wait (GList *objects,
- GOutputStream *output,
- GError **error);
-
#endif /* __SEAHORSE_PLACE_H__ */
diff --git a/libseahorse/seahorse-util.c b/libseahorse/seahorse-util.c
index 55c99b3..ee9b3a6 100644
--- a/libseahorse/seahorse-util.c
+++ b/libseahorse/seahorse-util.c
@@ -52,8 +52,6 @@
#include <sys/types.h>
-static const gchar *bad_filename_chars = "/\\<>|";
-
/**
* seahorse_util_show_error:
* @parent: The parent widget. Can be NULL
@@ -372,41 +370,6 @@ seahorse_util_printf_fd (int fd, const char* fmt, ...)
return ret;
}
-/**
- * seahorse_util_filename_for_objects:
- * @objects: A list of objects
- *
- * If the single object has a nickname, this will be returned (with .asc attached)
- * If there are multiple objects, "Multiple Keys.asc" will be returned.
- * Single objects default to "Key Data.asc".
- * Results are internationalized
- *
- * Returns: NULL on error, the filename else. The returned string should be
- * freed with #g_free when no longer needed.
- */
-gchar*
-seahorse_util_filename_for_objects (GList *objects)
-{
- const gchar *name = NULL;
- gchar *filename;
-
- g_return_val_if_fail (g_list_length (objects) > 0, NULL);
-
- if (g_list_length (objects) == 1) {
- if (SEAHORSE_IS_OBJECT (objects->data))
- name = seahorse_object_get_nickname (SEAHORSE_OBJECT (objects->data));
- if (name == NULL)
- name = _("Key Data");
- } else {
- name = _("Multiple Keys");
- }
-
- filename = g_strconcat (name, SEAHORSE_EXT_ASC, NULL);
- g_strstrip (filename);
- g_strdelimit (filename, bad_filename_chars, '_');
- return filename;
-}
-
/**
* seahorse_util_uri_get_last:
* @uri: The uri to parse
@@ -435,86 +398,48 @@ seahorse_util_uri_get_last (const gchar* uri)
return t;
}
-/**
- * seahorse_util_uri_exists:
- * @uri: The uri to check
- *
- * Verify whether a given uri exists or not.
- *
- * Returns: FALSE if it does not exist, TRUE else
- **/
-gboolean
-seahorse_util_uri_exists (const gchar* uri)
+GFile *
+seahorse_util_file_increment_unique (GFile *file,
+ guint *state)
{
- GFile *file;
- gboolean exists;
+ GFile *result;
+ gchar *suffix;
+ gchar *prefix;
+ gchar *uri_try;
+ gchar *x;
+ guint len;
- file = g_file_new_for_uri (uri);
- g_return_val_if_fail (file, FALSE);
-
- exists = g_file_query_exists (file, NULL);
- g_object_unref (file);
-
- return exists;
-}
-
-/**
- * seahorse_util_uri_unique:
- * @uri: The uri to guarantee is unique
- *
- * Creates a URI based on @uri that does not exist.
- * A simple numbering scheme is used to create new
- * URIs. Not meant for temp file creation.
- *
- * Returns: Newly allocated unique URI.
- **/
-gchar*
-seahorse_util_uri_unique (const gchar* uri)
-{
- gchar* suffix;
- gchar* prefix;
- gchar* uri_try;
- gchar* x;
- guint len;
- int i;
-
- /* Simple when doesn't exist */
- if (!seahorse_util_uri_exists (uri))
- return g_strdup (uri);
-
- prefix = g_strdup (uri);
- len = strlen (prefix);
-
- /* Always take off a slash at end */
- g_return_val_if_fail (len > 1, g_strdup (uri));
- if (prefix[len - 1] == '/')
- prefix[len - 1] = 0;
-
- /* Split into prefix and suffix */
- suffix = strrchr (prefix, '.');
- x = strrchr(uri, '/');
- if (suffix == NULL || (x != NULL && suffix < x)) {
- suffix = g_strdup ("");
- } else {
- x = suffix;
- suffix = g_strdup (suffix);
- *x = 0;
- }
-
- for (i = 1; i < 1000; i++) {
-
- uri_try = g_strdup_printf ("%s-%d%s", prefix, i, suffix);
-
- if (!seahorse_util_uri_exists (uri_try))
- break;
-
- g_free (uri_try);
- uri_try = NULL;
- }
-
- g_free (suffix);
- g_free (prefix);
- return uri_try ? uri_try : g_strdup (uri);
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_return_val_if_fail (state != NULL, NULL);
+
+ prefix = g_file_get_uri (file);
+ len = strlen (prefix);
+
+ g_return_val_if_fail (len > 0, NULL);
+
+ /* Always take off a slash at end */
+ if (prefix[len - 1] == '/')
+ prefix[len - 1] = 0;
+
+ /* Split into prefix and suffix */
+ suffix = strrchr (prefix, '.');
+ x = strrchr (prefix, '/');
+ if (suffix == NULL || (x != NULL && suffix < x)) {
+ suffix = g_strdup ("");
+ } else {
+ x = suffix;
+ suffix = g_strdup (suffix);
+ *x = 0;
+ }
+
+ ++(*state);
+ uri_try = g_strdup_printf ("%s-%u%s", prefix, *state, suffix);
+ g_free (suffix);
+ g_free (prefix);
+
+ result = g_file_new_for_uri (uri_try);
+ g_free (uri_try);
+ return result;
}
/**
@@ -705,136 +630,6 @@ seahorse_util_chooser_show_key_files (GtkDialog *dialog)
}
/**
- * seahorse_util_chooser_show_archive_files:
- * @dialog: the dialog to add the filter for
- *
- * Adds a archive file filter and a "All files" filter. The archive filter
- * is used.
- *
- */
-void
-seahorse_util_chooser_show_archive_files (GtkDialog *dialog)
-{
- GtkFileFilter* filter;
- int i;
-
- static const char *archive_mime_type[] = {
- "application/x-ar",
- "application/x-arj",
- "application/x-bzip",
- "application/x-bzip-compressed-tar",
- "application/x-cd-image",
- "application/x-compress",
- "application/x-compressed-tar",
- "application/x-gzip",
- "application/x-java-archive",
- "application/x-jar",
- "application/x-lha",
- "application/x-lzop",
- "application/x-rar",
- "application/x-rar-compressed",
- "application/x-tar",
- "application/x-zoo",
- "application/zip",
- "application/x-7zip"
- };
-
- filter = gtk_file_filter_new ();
- gtk_file_filter_set_name (filter, _("Archive files"));
- for (i = 0; i < G_N_ELEMENTS (archive_mime_type); i++)
- gtk_file_filter_add_mime_type (filter, archive_mime_type[i]);
- gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
- gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
-
- filter = gtk_file_filter_new ();
- gtk_file_filter_set_name (filter, _("All files"));
- gtk_file_filter_add_pattern (filter, "*");
- gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
-}
-
-/**
- * seahorse_util_chooser_set_filename_full:
- * @dialog: The dialog to pre set the name
- * @objects: generate the file name from this object
- *
- *
- */
-void
-seahorse_util_chooser_set_filename_full (GtkDialog *dialog, GList *objects)
-{
- gchar *t = NULL;
-
- if (g_list_length (objects) > 0) {
- t = seahorse_util_filename_for_objects (objects);
- gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), t);
- g_free (t);
- }
-}
-
-/**
- * seahorse_util_chooser_set_filename:
- * @dialog: set the dialog for this
- * @object: The object to use for the filename. #GObject
- *
- */
-void
-seahorse_util_chooser_set_filename (GtkDialog *dialog,
- GObject *object)
-{
- GList *objects = g_list_append (NULL, object);
- seahorse_util_chooser_set_filename_full (dialog, objects);
- g_list_free (objects);
-}
-
-/**
- * seahorse_util_chooser_save_prompt:
- * @dialog: save dialog to show
- *
- * If the selected file already exists, a confirmation dialog will be displayed
- *
- * Returns: the uri of the chosen file or NULL
- */
-gchar*
-seahorse_util_chooser_save_prompt (GtkDialog *dialog)
-{
- GtkWidget* edlg;
- gchar *uri = NULL;
-
- while (gtk_dialog_run (dialog) == GTK_RESPONSE_ACCEPT) {
-
- uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER (dialog));
-
- if (uri == NULL)
- continue;
-
- if (seahorse_util_uri_exists (uri)) {
-
- edlg = gtk_message_dialog_new_with_markup (GTK_WINDOW (dialog),
- GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_NONE, _("<b>A file already exists with this name.</b>\n\nDo you want to replace it with a new file?"));
- gtk_dialog_add_buttons (GTK_DIALOG (edlg),
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- _("_Replace"), GTK_RESPONSE_ACCEPT, NULL);
-
- gtk_dialog_set_default_response (GTK_DIALOG (edlg), GTK_RESPONSE_CANCEL);
-
- if (gtk_dialog_run (GTK_DIALOG (edlg)) != GTK_RESPONSE_ACCEPT) {
- g_free (uri);
- uri = NULL;
- }
-
- gtk_widget_destroy (edlg);
- }
-
- if (uri != NULL)
- break;
- }
-
- gtk_widget_destroy (GTK_WIDGET (dialog));
- return uri;
-}
-
-/**
* seahorse_util_chooser_open_prompt:
* @dialog: open dialog to display
*
diff --git a/libseahorse/seahorse-util.h b/libseahorse/seahorse-util.h
index f6d6d79..cdcf04f 100644
--- a/libseahorse/seahorse-util.h
+++ b/libseahorse/seahorse-util.h
@@ -38,8 +38,7 @@ const AvahiPoll* seahorse_util_dns_sd_get_poll (void);
typedef guint64 SeahorseVersion;
-#define SEAHORSE_EXT_ASC ".asc"
-#define SEAHORSE_EXT_GPG ".gpg"
+#define SEAHORSE_BAD_FILENAME_CHARS "/\\<>|:?;"
gchar* seahorse_util_get_date_string (const time_t time);
gchar* seahorse_util_get_display_date_string (const time_t time);
@@ -71,12 +70,9 @@ gboolean seahorse_util_print_fd (int fd,
gboolean seahorse_util_printf_fd (int fd,
const char* data, ...);
-
-gchar* seahorse_util_filename_for_objects (GList *objects);
-
-gboolean seahorse_util_uri_exists (const gchar* uri);
-gchar* seahorse_util_uri_unique (const gchar* uri);
+GFile * seahorse_util_file_increment_unique (GFile *file,
+ guint *state);
const gchar* seahorse_util_uri_get_last (const gchar* uri);
@@ -99,18 +95,9 @@ GtkDialog* seahorse_util_chooser_save_new (const gchar *title,
void seahorse_util_chooser_show_key_files (GtkDialog *dialog);
-void seahorse_util_chooser_show_archive_files (GtkDialog *dialog);
-
-void seahorse_util_chooser_set_filename_full (GtkDialog *dialog,
- GList *objects);
-
-void seahorse_util_chooser_set_filename (GtkDialog *dialog,
- GObject *object);
gchar* seahorse_util_chooser_open_prompt (GtkDialog *dialog);
-gchar* seahorse_util_chooser_save_prompt (GtkDialog *dialog);
-
GList * seahorse_util_objects_sort_by_place (GList *objects);
GList * seahorse_util_objects_splice_by_place (GList *objects);
diff --git a/libseahorse/seahorse-viewer.c b/libseahorse/seahorse-viewer.c
index 7c5834c..bb42111 100644
--- a/libseahorse/seahorse-viewer.c
+++ b/libseahorse/seahorse-viewer.c
@@ -25,6 +25,7 @@
#include "seahorse-action.h"
#include "seahorse-actions.h"
#include "seahorse-backend.h"
+#include "seahorse-exportable.h"
#include "seahorse-object.h"
#include "seahorse-preferences.h"
#include "seahorse-progress.h"
@@ -223,158 +224,84 @@ on_properties_place (GtkAction *action,
g_list_free (objects);
}
-static const GtkActionEntry UI_ENTRIES[] = {
-
- /* Top menu items */
- { "file-menu", NULL, N_("_File") },
- { "edit-menu", NULL, N_("_Edit") },
- /*Translators: This text refers to deleting an item from its type's backing store*/
- { "edit-delete", GTK_STOCK_DELETE, N_("_Delete"), NULL,
- N_("Delete selected items"), G_CALLBACK (on_object_delete) },
- { "properties-object", GTK_STOCK_PROPERTIES, NULL, NULL,
- N_("Show the properties of this item"), G_CALLBACK (on_properties_object) },
- { "properties-place", GTK_STOCK_PROPERTIES, NULL, NULL,
- N_("Show the properties of this place"), G_CALLBACK (on_properties_place) },
- { "app-preferences", GTK_STOCK_PREFERENCES, N_("Prefere_nces"), NULL,
- N_("Change preferences for this program"), G_CALLBACK (on_app_preferences) },
- { "view-menu", NULL, N_("_View") },
- { "help-menu", NULL, N_("_Help") },
- { "app-about", GTK_STOCK_ABOUT, NULL, NULL,
- N_("About this program"), G_CALLBACK (on_app_about) },
- { "help-show", GTK_STOCK_HELP, N_("_Contents"), "F1",
- N_("Show Seahorse help"), G_CALLBACK (on_help_show) }
-};
-
-#if 0
-static void
-on_file_export_completed (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- SeahorseViewer* self = SEAHORSE_VIEWER (user_data);
- GError *error = NULL;
-
- if (!seahorse_place_export_auto_finish (result, &error))
- seahorse_util_handle_error (&error, seahorse_viewer_get_window (self),
- _("Couldn't export keys"));
-
- g_object_unref (self);
-}
-
static void
on_key_export_file (GtkAction* action, SeahorseViewer* self)
{
GError *error = NULL;
+ GtkWindow *window;
GList *objects;
- GtkDialog *dialog;
- gchar *uri, *unesc_uri;
g_return_if_fail (SEAHORSE_IS_VIEWER (self));
g_return_if_fail (GTK_IS_ACTION (action));
+ window = seahorse_viewer_get_window (self);
objects = seahorse_viewer_get_selected_objects (self);
- objects = objects_prune_non_exportable (objects);
- if (objects == NULL)
- return;
-
- dialog = seahorse_util_chooser_save_new (_("Export public key"),
- seahorse_viewer_get_window (self));
- seahorse_util_chooser_show_key_files (dialog);
- seahorse_util_chooser_set_filename_full (dialog, objects);
- uri = seahorse_util_chooser_save_prompt (dialog);
- if (uri != NULL) {
- GFile* file;
- GOutputStream* output;
- GCancellable *cancellable;
-
- file = g_file_new_for_uri (uri);
- output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, 0, NULL, &error));
- if (output == NULL) {
- unesc_uri = g_uri_unescape_string (seahorse_util_uri_get_last (uri), NULL);
- seahorse_util_handle_error (&error, NULL, _ ("Couldn't export key to \"%s\""),
- unesc_uri, NULL);
- g_free (unesc_uri);
- } else {
- cancellable = g_cancellable_new ();
- seahorse_place_export_auto_async (objects, output, cancellable,
- on_file_export_completed, g_object_ref (self));
- seahorse_progress_show (cancellable, _("Exporting keys"), TRUE);
- g_object_unref (cancellable);
- }
-
+ seahorse_exportable_export_to_prompt_wait (objects, window, &error);
+ g_list_free (objects);
- g_object_unref (file);
- g_object_unref (output);
- g_free (uri);
- }
+ /* TODO: message if only partially exported */
- g_list_free (objects);
+ if (error != NULL)
+ seahorse_util_handle_error (&error, window, _("Couldn't export keys"));
}
static void
-on_copy_export_complete (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
+on_key_export_clipboard (GtkAction* action,
+ SeahorseViewer* self)
{
- SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
- GOutputStream* output;
+ GList* objects;
+ gpointer output;
+ gsize size;
GError *error = NULL;
- const gchar* text;
- guint size;
GdkAtom atom;
GtkClipboard* board;
- output = seahorse_place_export_auto_finish (result, &error);
- if (error != NULL) {
- seahorse_util_handle_error (&error, seahorse_viewer_get_window (self),
- _("Couldn't retrieve data from key server"));
- return;
- }
-
- text = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (output));
- size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (output));
-
- atom = gdk_atom_intern ("CLIPBOARD", FALSE);
- board = gtk_clipboard_get (atom);
- gtk_clipboard_set_text (board, text, (gint)size);
-
- g_object_unref (self);
-}
-
-static void
-on_key_export_clipboard (GtkAction* action, SeahorseViewer* self)
-{
- GList* objects;
- GOutputStream* output;
- GCancellable *cancellable;
-
g_return_if_fail (SEAHORSE_IS_VIEWER (self));
g_return_if_fail (GTK_IS_ACTION (action));
objects = seahorse_viewer_get_selected_objects (self);
- objects = objects_prune_non_exportable (objects);
- if (objects == NULL)
- return;
+ seahorse_exportable_export_to_text_wait (objects, &output, &size, &error);
+ g_list_free (objects);
- output = G_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0, g_realloc, g_free));
+ /* TODO: Print message if only partially exported */
- cancellable = g_cancellable_new ();
- seahorse_place_export_auto_async (objects, output, cancellable,
- on_copy_export_complete, g_object_ref (self));
- seahorse_progress_show (cancellable, _ ("Retrieving keys"), TRUE);
- g_object_unref (cancellable);
+ if (error == NULL) {
+ atom = gdk_atom_intern ("CLIPBOARD", FALSE);
+ board = gtk_clipboard_get (atom);
+ gtk_clipboard_set_text (board, output, (gint)size);
+ } else {
+ seahorse_util_handle_error (&error, seahorse_viewer_get_window (self),
+ _("Couldn't export data"));
+ }
- g_list_free (objects);
- g_object_unref (output);
+ g_free (output);
}
-static const GtkActionEntry EXPORT_ENTRIES[] = {
+static const GtkActionEntry UI_ENTRIES[] = {
+
+ /* Top menu items */
+ { "file-menu", NULL, N_("_File") },
{ "file-export", GTK_STOCK_SAVE_AS, N_("E_xport..."), NULL,
N_("Export to a file"), G_CALLBACK (on_key_export_file) },
+ { "edit-menu", NULL, N_("_Edit") },
+ /*Translators: This text refers to deleting an item from its type's backing store*/
{ "edit-export-clipboard", GTK_STOCK_COPY, NULL, "<control>C",
- N_("Copy to the clipboard"), G_CALLBACK (on_key_export_clipboard) }
+ N_("Copy to the clipboard"), G_CALLBACK (on_key_export_clipboard) },
+ { "edit-delete", GTK_STOCK_DELETE, N_("_Delete"), NULL,
+ N_("Delete selected items"), G_CALLBACK (on_object_delete) },
+ { "properties-object", GTK_STOCK_PROPERTIES, NULL, NULL,
+ N_("Show the properties of this item"), G_CALLBACK (on_properties_object) },
+ { "properties-place", GTK_STOCK_PROPERTIES, NULL, NULL,
+ N_("Show the properties of this place"), G_CALLBACK (on_properties_place) },
+ { "app-preferences", GTK_STOCK_PREFERENCES, N_("Prefere_nces"), NULL,
+ N_("Change preferences for this program"), G_CALLBACK (on_app_preferences) },
+ { "view-menu", NULL, N_("_View") },
+ { "help-menu", NULL, N_("_Help") },
+ { "app-about", GTK_STOCK_ABOUT, NULL, NULL,
+ N_("About this program"), G_CALLBACK (on_app_about) },
+ { "help-show", GTK_STOCK_HELP, N_("_Contents"), "F1",
+ N_("Show Seahorse help"), G_CALLBACK (on_help_show) }
};
-#endif
static void
on_ui_manager_pre_activate (GtkUIManager *ui_manager,
diff --git a/pgp/Makefile.am b/pgp/Makefile.am
index 39813d0..d7c260f 100644
--- a/pgp/Makefile.am
+++ b/pgp/Makefile.am
@@ -46,6 +46,7 @@ libseahorse_pgp_la_SOURCES = \
seahorse-gpgme-dialogs.h \
seahorse-gpgme-data.c seahorse-gpgme-data.h \
seahorse-gpgme-expires.c \
+ seahorse-gpgme-exporter.c seahorse-gpgme-exporter.h \
seahorse-gpgme-generate.c \
seahorse-gpgme-key.c seahorse-gpgme-key.h \
seahorse-gpgme-key-op.c seahorse-gpgme-key-op.h \
diff --git a/pgp/seahorse-gpg-op.c b/pgp/seahorse-gpg-op.c
index ee3daee..f395df9 100644
--- a/pgp/seahorse-gpg-op.c
+++ b/pgp/seahorse-gpg-op.c
@@ -61,34 +61,33 @@ execute_gpg_command (gpgme_ctx_t ctx, const gchar *args, gchar **std_out,
return gerr;
}
-gpgme_error_t
-seahorse_gpg_op_export_secret (gpgme_ctx_t ctx, const char *pattern,
- gpgme_data_t keydata)
+gpgme_error_t
+seahorse_gpg_op_export_secret (gpgme_ctx_t ctx,
+ const gchar **patterns,
+ gpgme_data_t keydata)
{
- gchar *output = NULL;
- gpgme_error_t err;
- gchar *args;
-
- g_return_val_if_fail (pattern != NULL, GPG_E (GPG_ERR_INV_VALUE));
-
- /*
- * We have to use armor mode, because otherwise below
- * string stuff doesn't work
- */
- args = g_strdup_printf ("--armor --export-secret-key '%s'",
- pattern);
-
- err = execute_gpg_command (ctx, args, &output, NULL);
- g_free (args);
-
- if (!GPG_IS_OK (err))
- return err;
-
- if (gpgme_data_write (keydata, output, strlen (output)) == -1)
- return GPG_E (GPG_ERR_GENERAL);
-
- g_free (output);
- return GPG_OK;
+ gchar *output = NULL;
+ gpgme_error_t gerr;
+ gchar *args;
+ gsize i;
+
+ g_return_val_if_fail (patterns != NULL, GPG_E (GPG_ERR_INV_VALUE));
+
+ for (i = 0; patterns[i] != NULL; i++) {
+ args = g_strdup_printf ("--armor --export-secret-key '%s'", patterns[i]);
+ gerr = execute_gpg_command (ctx, args, &output, NULL);
+ g_free (args);
+
+ if (!GPG_IS_OK (gerr))
+ return gerr;
+
+ if (gpgme_data_write (keydata, output, strlen (output)) == -1)
+ return GPG_E (GPG_ERR_GENERAL);
+
+ g_free (output);
+ }
+
+ return GPG_OK;
}
gpgme_error_t
diff --git a/pgp/seahorse-gpg-op.h b/pgp/seahorse-gpg-op.h
index 311eb91..fb24d91 100644
--- a/pgp/seahorse-gpg-op.h
+++ b/pgp/seahorse-gpg-op.h
@@ -27,7 +27,7 @@
#include <gpgme.h>
gpgme_error_t seahorse_gpg_op_export_secret (gpgme_ctx_t ctx,
- const char *pattern,
+ const gchar **patterns,
gpgme_data_t keydata);
gpgme_error_t seahorse_gpg_op_num_uids (gpgme_ctx_t ctx,
diff --git a/pgp/seahorse-gpgme-exporter.c b/pgp/seahorse-gpgme-exporter.c
new file mode 100644
index 0000000..73328fd
--- /dev/null
+++ b/pgp/seahorse-gpgme-exporter.c
@@ -0,0 +1,445 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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 "seahorse-gpgme.h"
+#include "seahorse-gpgme-data.h"
+#include "seahorse-gpgme-exporter.h"
+#include "seahorse-gpgme-key.h"
+#include "seahorse-gpgme-keyring.h"
+#include "seahorse-gpg-op.h"
+#include "seahorse-progress.h"
+
+#include "seahorse-exporter.h"
+#include "seahorse-object.h"
+#include "seahorse-util.h"
+
+#include <glib/gi18n.h>
+
+#include <string.h>
+
+#define SEAHORSE_GPGME_EXPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_GPGME_EXPORTER, SeahorseGpgmeExporterClass))
+#define SEAHORSE_IS_GPGME_EXPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_GPGME_EXPORTER))
+#define SEAHORSE_GPGME_EXPORTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_GPGME_EXPORTER, SeahorseGpgmeExporterClass))
+
+typedef struct _SeahorseGpgmeExporterClass SeahorseGpgmeExporterClass;
+
+struct _SeahorseGpgmeExporter {
+ GObject parent;
+ GList *objects;
+ gboolean armor;
+ gboolean secret;
+};
+
+struct _SeahorseGpgmeExporterClass {
+ GObjectClass parent_class;
+};
+
+enum {
+ PROP_0,
+ PROP_FILENAME,
+ PROP_CONTENT_TYPE,
+ PROP_FILE_FILTER,
+ PROP_ARMOR,
+ PROP_SECRET
+};
+
+static void seahorse_gpgme_exporter_iface_init (SeahorseExporterIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (SeahorseGpgmeExporter, seahorse_gpgme_exporter, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_EXPORTER, seahorse_gpgme_exporter_iface_init);
+);
+
+static gchar *
+calc_filename (SeahorseGpgmeExporter *self)
+{
+ const gchar *basename = NULL;
+ gchar *filename;
+
+ g_return_val_if_fail (self->objects, NULL);
+
+ /* Multiple objects */
+ if (self->objects->next)
+ basename = _("Multiple Keys");
+ else if (self->objects->data)
+ basename = seahorse_object_get_nickname (self->objects->data);
+ if (basename == NULL)
+ basename = _("Key Data");
+
+ if (self->armor)
+ filename = g_strconcat (basename, ".asc", NULL);
+ else
+ filename = g_strconcat (basename, ".pgp", NULL);
+ g_strstrip (filename);
+ g_strdelimit (filename, SEAHORSE_BAD_FILENAME_CHARS, '_');
+ return filename;
+}
+
+static const gchar *
+calc_content_type (SeahorseGpgmeExporter *self)
+{
+ if (self->armor)
+ return "application/pgp-keys";
+ else
+ return "application/pgp-keys+armor";
+}
+
+static GtkFileFilter *
+calc_file_filter (SeahorseGpgmeExporter *self)
+{
+ GtkFileFilter *filter = gtk_file_filter_new ();
+
+ if (self->armor) {
+ gtk_file_filter_set_name (filter, _("Armored PGP keys"));
+ gtk_file_filter_add_mime_type (filter, "application/pgp-keys+armor");
+ gtk_file_filter_add_pattern (filter, "*.asc");
+ } else {
+ gtk_file_filter_set_name (filter, _("PGP keys"));
+ gtk_file_filter_add_mime_type (filter, "application/pgp-keys");
+ gtk_file_filter_add_pattern (filter, "*.pgp");
+ gtk_file_filter_add_pattern (filter, "*.gpg");
+ }
+
+ return filter;
+}
+
+static void
+seahorse_gpgme_exporter_init (SeahorseGpgmeExporter *self)
+{
+
+}
+
+static void
+seahorse_gpgme_exporter_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SeahorseGpgmeExporter *self = SEAHORSE_GPGME_EXPORTER (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ g_value_take_string (value, calc_filename (self));
+ break;
+ case PROP_CONTENT_TYPE:
+ g_value_set_string (value, calc_content_type (self));
+ break;
+ case PROP_FILE_FILTER:
+ g_value_take_object (value, calc_file_filter (self));
+ break;
+ case PROP_ARMOR:
+ g_value_set_boolean (value, self->armor);
+ break;
+ case PROP_SECRET:
+ g_value_set_boolean (value, self->secret);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+seahorse_gpgme_exporter_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SeahorseGpgmeExporter *self = SEAHORSE_GPGME_EXPORTER (object);
+
+ switch (prop_id) {
+ case PROP_ARMOR:
+ self->armor = g_value_get_boolean (value);
+ break;
+ case PROP_SECRET:
+ self->secret = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+seahorse_gpgme_exporter_finalize (GObject *obj)
+{
+ SeahorseGpgmeExporter *self = SEAHORSE_GPGME_EXPORTER (obj);
+
+ g_list_free_full (self->objects, g_object_unref);
+
+ G_OBJECT_CLASS (seahorse_gpgme_exporter_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_gpgme_exporter_class_init (SeahorseGpgmeExporterClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = seahorse_gpgme_exporter_finalize;
+ gobject_class->set_property = seahorse_gpgme_exporter_set_property;
+ gobject_class->get_property = seahorse_gpgme_exporter_get_property;
+
+ g_object_class_override_property (gobject_class, PROP_FILENAME, "filename");
+ g_object_class_override_property (gobject_class, PROP_CONTENT_TYPE, "content-type");
+ g_object_class_override_property (gobject_class, PROP_FILE_FILTER, "file-filter");
+
+ g_object_class_install_property (gobject_class, PROP_ARMOR,
+ g_param_spec_boolean ("armor", "Armor", "Armor encoding",
+ FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_SECRET,
+ g_param_spec_boolean ("secret", "Secret", "Secret key export",
+ FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static GList *
+seahorse_gpgme_exporter_get_objects (SeahorseExporter *exporter)
+{
+ SeahorseGpgmeExporter *self = SEAHORSE_GPGME_EXPORTER (exporter);
+ return self->objects;
+}
+
+static gboolean
+seahorse_gpgme_exporter_add_object (SeahorseExporter *exporter,
+ GObject *object)
+{
+ SeahorseGpgmeExporter *self = SEAHORSE_GPGME_EXPORTER (exporter);
+ SeahorseGpgmeKey *key;
+
+ if (SEAHORSE_IS_GPGME_KEY (object)) {
+ key = SEAHORSE_GPGME_KEY (object);
+ if (self->secret && seahorse_gpgme_key_get_private (key) == NULL)
+ return FALSE;
+
+ self->objects = g_list_append (self->objects, g_object_ref (key));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+typedef struct {
+ GPtrArray *keyids;
+ gint at;
+ gpgme_data_t data;
+ gpgme_ctx_t gctx;
+ GMemoryOutputStream *output;
+ GCancellable *cancellable;
+ gulong cancelled_sig;
+} GpgmeExportClosure;
+
+static void
+gpgme_export_closure_free (gpointer data)
+{
+ GpgmeExportClosure *closure = data;
+ g_cancellable_disconnect (closure->cancellable, closure->cancelled_sig);
+ g_clear_object (&closure->cancellable);
+ gpgme_data_release (closure->data);
+ if (closure->gctx)
+ gpgme_release (closure->gctx);
+ g_ptr_array_free (closure->keyids, TRUE);
+ g_object_unref (closure->output);
+ g_free (closure);
+}
+
+
+static gboolean
+on_keyring_export_complete (gpgme_error_t gerr,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GpgmeExportClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GError *error = NULL;
+
+ if (seahorse_gpgme_propagate_error (gerr, &error)) {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+ return FALSE; /* don't call again */
+ }
+
+ if (closure->at >= 0)
+ seahorse_progress_end (closure->cancellable,
+ closure->keyids->pdata[closure->at]);
+
+ g_assert (closure->at < (gint)closure->keyids->len);
+ closure->at++;
+
+ if (closure->at == closure->keyids->len) {
+ g_simple_async_result_complete (res);
+ return FALSE; /* don't run this again */
+ }
+
+ /* Do the next key in the list */
+ gerr = gpgme_op_export_start (closure->gctx, closure->keyids->pdata[closure->at],
+ 0, closure->data);
+
+ if (seahorse_gpgme_propagate_error (gerr, &error)) {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+ return FALSE; /* don't run this again */
+ }
+
+ seahorse_progress_begin (closure->cancellable,
+ closure->keyids->pdata[closure->at]);
+ return TRUE; /* call this source again */
+}
+
+static void
+seahorse_gpgme_exporter_export_async (SeahorseExporter *exporter,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SeahorseGpgmeExporter *self = SEAHORSE_GPGME_EXPORTER (exporter);
+ GSimpleAsyncResult *res;
+ GpgmeExportClosure *closure;
+ GError *error = NULL;
+ gpgme_error_t gerr = 0;
+ SeahorsePgpKey *key;
+ gchar *keyid;
+ GSource *gsource;
+ GList *l;
+
+ res = g_simple_async_result_new (G_OBJECT (exporter), callback, user_data,
+ seahorse_gpgme_exporter_export_async);
+ closure = g_new0 (GpgmeExportClosure, 1);
+ closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+ closure->gctx = seahorse_gpgme_keyring_new_context (&gerr);
+ closure->output = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0, g_realloc, g_free));
+ closure->data = seahorse_gpgme_data_output (G_OUTPUT_STREAM (closure->output));
+ closure->keyids = g_ptr_array_new_with_free_func (g_free);
+ closure->at = -1;
+ g_simple_async_result_set_op_res_gpointer (res, closure, gpgme_export_closure_free);
+
+ if (seahorse_gpgme_propagate_error (gerr, &error)) {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete_in_idle (res);
+ g_object_unref (res);
+ return;
+ }
+
+ gpgme_set_armor (closure->gctx, self->armor);
+
+ for (l = self->objects; l != NULL; l = g_list_next (l)) {
+ key = SEAHORSE_PGP_KEY (l->data);
+
+ /* Building list */
+ keyid = g_strdup (seahorse_pgp_key_get_keyid (key));
+ seahorse_progress_prep (closure->cancellable, keyid, NULL);
+ g_ptr_array_add (closure->keyids, keyid);
+ }
+
+ if (self->secret) {
+ g_return_if_fail (self->armor == TRUE);
+ g_ptr_array_add (closure->keyids, NULL);
+ gerr = seahorse_gpg_op_export_secret (closure->gctx, (const gchar **)closure->keyids->pdata,
+ closure->data);
+ if (seahorse_gpgme_propagate_error (gerr, &error))
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete_in_idle (res);
+ g_object_unref (res);
+ return;
+ }
+
+ gsource = seahorse_gpgme_gsource_new (closure->gctx, cancellable);
+ g_source_set_callback (gsource, (GSourceFunc)on_keyring_export_complete,
+ g_object_ref (res), g_object_unref);
+
+ /* Get things started */
+ if (on_keyring_export_complete (0, res))
+ g_source_attach (gsource, g_main_context_default ());
+
+ g_source_unref (gsource);
+ g_object_unref (res);
+}
+
+static gpointer
+seahorse_gpgme_exporter_export_finish (SeahorseExporter *exporter,
+ GAsyncResult *result,
+ gsize *size,
+ GError **error)
+{
+ GpgmeExportClosure *closure;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (exporter),
+ seahorse_gpgme_exporter_export_async), NULL);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return NULL;
+
+ closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ g_output_stream_close (G_OUTPUT_STREAM (closure->output), NULL, NULL);
+ *size = g_memory_output_stream_get_data_size (closure->output);
+ return g_memory_output_stream_steal_data (closure->output);
+}
+
+static void
+seahorse_gpgme_exporter_iface_init (SeahorseExporterIface *iface)
+{
+ iface->add_object = seahorse_gpgme_exporter_add_object;
+ iface->export_async = seahorse_gpgme_exporter_export_async;
+ iface->export_finish = seahorse_gpgme_exporter_export_finish;
+ iface->get_objects = seahorse_gpgme_exporter_get_objects;
+}
+
+SeahorseExporter *
+seahorse_gpgme_exporter_new (GObject *object,
+ gboolean armor,
+ gboolean secret)
+{
+ SeahorseExporter *exporter;
+
+ g_return_val_if_fail (secret == FALSE || armor == TRUE, NULL);
+
+ exporter = g_object_new (SEAHORSE_TYPE_GPGME_EXPORTER,
+ "armor", armor,
+ "secret", secret,
+ NULL);
+
+ if (!seahorse_exporter_add_object (exporter, object))
+ g_return_val_if_reached (NULL);
+
+ return exporter;
+}
+
+
+SeahorseExporter *
+seahorse_gpgme_exporter_new_multiple (GList *keys,
+ gboolean armor)
+{
+ SeahorseExporter *exporter;
+ GList *l;
+
+ exporter = g_object_new (SEAHORSE_TYPE_GPGME_EXPORTER,
+ "armor", armor,
+ "secret", FALSE,
+ NULL);
+
+ for (l = keys; l != NULL; l = g_list_next (l)) {
+ if (!seahorse_exporter_add_object (exporter, l->data))
+ g_return_val_if_reached (NULL);
+ }
+
+ return exporter;
+}
diff --git a/pgp/seahorse-gpgme-exporter.h b/pgp/seahorse-gpgme-exporter.h
new file mode 100644
index 0000000..1b3c7ba
--- /dev/null
+++ b/pgp/seahorse-gpgme-exporter.h
@@ -0,0 +1,47 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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 __SEAHORSE_GPGME_EXPORTER_H__
+#define __SEAHORSE_GPGME_EXPORTER_H__
+
+#include <glib-object.h>
+
+#include "seahorse-exporter.h"
+
+#define SEAHORSE_TYPE_GPGME_EXPORTER (seahorse_gpgme_exporter_get_type ())
+#define SEAHORSE_GPGME_EXPORTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_GPGME_EXPORTER, SeahorseGpgmeExporter))
+#define SEAHORSE_IS_GPGME_EXPORTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_GPGME_EXPORTER))
+
+typedef struct _SeahorseGpgmeExporter SeahorseGpgmeExporter;
+
+GType seahorse_gpgme_exporter_get_type (void) G_GNUC_CONST;
+
+SeahorseExporter * seahorse_gpgme_exporter_new (GObject *object,
+ gboolean armor,
+ gboolean secret);
+
+SeahorseExporter * seahorse_gpgme_exporter_new_multiple (GList *keys,
+ gboolean armor);
+
+
+#endif /* __SEAHORSE_GPGME_EXPORTER_H__ */
diff --git a/pgp/seahorse-gpgme-key.c b/pgp/seahorse-gpgme-key.c
index f2875e6..b90c0d6 100644
--- a/pgp/seahorse-gpgme-key.c
+++ b/pgp/seahorse-gpgme-key.c
@@ -21,24 +21,26 @@
*/
#include "config.h"
-#include <string.h>
-
-#include <glib/gi18n.h>
+#include "seahorse-gpgme.h"
+#include "seahorse-gpgme-exporter.h"
+#include "seahorse-gpgme-key-op.h"
+#include "seahorse-gpgme-photo.h"
+#include "seahorse-gpgme-keyring.h"
+#include "seahorse-gpgme-uid.h"
+#include "seahorse-pgp-actions.h"
+#include "seahorse-pgp-backend.h"
+#include "seahorse-pgp-key.h"
+#include "seahorse-exportable.h"
#include "seahorse-icons.h"
#include "seahorse-predicate.h"
#include "seahorse-object-list.h"
#include "seahorse-place.h"
#include "seahorse-util.h"
-#include "seahorse-pgp-actions.h"
-#include "seahorse-pgp-backend.h"
-#include "pgp/seahorse-pgp-key.h"
-#include "pgp/seahorse-gpgme.h"
-#include "pgp/seahorse-gpgme-key-op.h"
-#include "pgp/seahorse-gpgme-photo.h"
-#include "pgp/seahorse-gpgme-keyring.h"
-#include "pgp/seahorse-gpgme-uid.h"
+#include <glib/gi18n.h>
+
+#include <string.h>
enum {
PROP_0,
@@ -48,7 +50,11 @@ enum {
PROP_TRUST
};
-G_DEFINE_TYPE (SeahorseGpgmeKey, seahorse_gpgme_key, SEAHORSE_TYPE_PGP_KEY);
+static void seahorse_gpgme_key_exportable_iface (SeahorseExportableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (SeahorseGpgmeKey, seahorse_gpgme_key, SEAHORSE_TYPE_PGP_KEY,
+ G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_EXPORTABLE, seahorse_gpgme_key_exportable_iface);
+);
struct _SeahorseGpgmeKeyPrivate {
gpgme_key_t pubkey; /* The public key */
@@ -544,6 +550,24 @@ seahorse_gpgme_key_class_init (SeahorseGpgmeKeyClass *klass)
g_object_class_override_property (gobject_class, PROP_TRUST, "trust");
}
+static GList *
+seahorse_gpgme_key_create_exporters (SeahorseExportable *exportable,
+ SeahorseExporterType type)
+{
+ GList *result = NULL;
+
+ if (type != SEAHORSE_EXPORTER_TEXTUAL)
+ result = g_list_append (result, seahorse_gpgme_exporter_new (G_OBJECT (exportable), FALSE, FALSE));
+ result = g_list_append (result, seahorse_gpgme_exporter_new (G_OBJECT (exportable), TRUE, FALSE));
+
+ return result;
+}
+
+static void
+seahorse_gpgme_key_exportable_iface (SeahorseExportableIface *iface)
+{
+ iface->create_exporters = seahorse_gpgme_key_create_exporters;
+}
/* -----------------------------------------------------------------------------
* PUBLIC
diff --git a/pgp/seahorse-gpgme-keyring.c b/pgp/seahorse-gpgme-keyring.c
index ee8652d..2d0b144 100644
--- a/pgp/seahorse-gpgme-keyring.c
+++ b/pgp/seahorse-gpgme-keyring.c
@@ -729,154 +729,6 @@ seahorse_gpgme_keyring_import_finish (SeahorsePlace *place,
return results;
}
-typedef struct {
- GPtrArray *keyids;
- gint at;
- gpgme_data_t data;
- gpgme_ctx_t gctx;
- GOutputStream *output;
- GCancellable *cancellable;
- gulong cancelled_sig;
-} keyring_export_closure;
-
-static void
-keyring_export_free (gpointer data)
-{
- keyring_export_closure *closure = data;
- g_cancellable_disconnect (closure->cancellable, closure->cancelled_sig);
- g_clear_object (&closure->cancellable);
- gpgme_data_release (closure->data);
- if (closure->gctx)
- gpgme_release (closure->gctx);
- g_ptr_array_free (closure->keyids, TRUE);
- g_object_unref (closure->output);
- g_free (closure);
-}
-
-static gboolean
-on_keyring_export_complete (gpgme_error_t gerr,
- gpointer user_data)
-{
- GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- keyring_export_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
- GError *error = NULL;
-
- if (seahorse_gpgme_propagate_error (gerr, &error)) {
- g_simple_async_result_take_error (res, error);
- g_simple_async_result_complete (res);
- return FALSE; /* don't call again */
- }
-
- if (closure->at >= 0)
- seahorse_progress_end (closure->cancellable,
- closure->keyids->pdata[closure->at]);
-
- g_assert (closure->at < (gint)closure->keyids->len);
- closure->at++;
-
- if (closure->at == closure->keyids->len) {
- g_simple_async_result_complete (res);
- return FALSE; /* don't run this again */
- }
-
- /* Do the next key in the list */
- gerr = gpgme_op_export_start (closure->gctx, closure->keyids->pdata[closure->at],
- 0, closure->data);
-
- if (seahorse_gpgme_propagate_error (gerr, &error)) {
- g_simple_async_result_take_error (res, error);
- g_simple_async_result_complete (res);
- return FALSE; /* don't run this again */
- }
-
- seahorse_progress_begin (closure->cancellable,
- closure->keyids->pdata[closure->at]);
- return TRUE; /* call this source again */
-}
-
-static void
-seahorse_gpgme_keyring_export_async (SeahorsePlace *place,
- GList *objects,
- GOutputStream *output,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *res;
- keyring_export_closure *closure;
- GError *error = NULL;
- gpgme_error_t gerr = 0;
- SeahorsePgpKey *key;
- gchar *keyid;
- GSource *gsource;
- GList *l;
-
- res = g_simple_async_result_new (G_OBJECT (place), callback, user_data,
- seahorse_gpgme_keyring_export_async);
- closure = g_new0 (keyring_export_closure, 1);
- closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
- closure->gctx = seahorse_gpgme_keyring_new_context (&gerr);
- closure->data = seahorse_gpgme_data_output (output);
- closure->keyids = g_ptr_array_new_with_free_func (g_free);
- closure->output = g_object_ref (output);
- closure->at = -1;
- g_simple_async_result_set_op_res_gpointer (res, closure, keyring_export_free);
-
- if (seahorse_gpgme_propagate_error (gerr, &error)) {
- g_simple_async_result_take_error (res, error);
- g_simple_async_result_complete_in_idle (res);
- g_object_unref (res);
- return;
- }
-
- gpgme_set_armor (closure->gctx, TRUE);
- gpgme_set_textmode (closure->gctx, TRUE);
-
- for (l = objects; l != NULL; l = g_list_next (l)) {
-
- /* Ignore PGP Uids */
- if (SEAHORSE_IS_PGP_UID (l->data))
- continue;
-
- g_return_if_fail (SEAHORSE_IS_PGP_KEY (l->data));
- key = SEAHORSE_PGP_KEY (l->data);
- g_return_if_fail (seahorse_object_get_place (SEAHORSE_OBJECT (key)) == place);
-
- /* Building list */
- keyid = g_strdup (seahorse_pgp_key_get_keyid (key));
- seahorse_progress_prep (closure->cancellable, keyid, NULL);
- g_ptr_array_add (closure->keyids, keyid);
- }
-
- gsource = seahorse_gpgme_gsource_new (closure->gctx, cancellable);
- g_source_set_callback (gsource, (GSourceFunc)on_keyring_export_complete,
- g_object_ref (res), g_object_unref);
-
- /* Get things started */
- if (on_keyring_export_complete (0, res))
- g_source_attach (gsource, g_main_context_default ());
-
- g_source_unref (gsource);
- g_object_unref (res);
-}
-
-static GOutputStream *
-seahorse_gpgme_keyring_export_finish (SeahorsePlace *place,
- GAsyncResult *result,
- GError **error)
-{
- keyring_export_closure *closure;
-
- g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (place),
- seahorse_gpgme_keyring_export_async), NULL);
-
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
- return NULL;
-
- closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
- return closure->output;
-}
-
static gboolean
scheduled_refresh (gpointer user_data)
{
@@ -901,7 +753,7 @@ monitor_gpg_homedir (GFileMonitor *handle, GFile *file, GFile *other_file,
event_type == G_FILE_MONITOR_EVENT_CREATED) {
name = g_file_get_basename (file);
- if (g_str_has_suffix (name, SEAHORSE_EXT_GPG)) {
+ if (g_str_has_suffix (name, ".gpg")) {
if (self->pv->scheduled_refresh == 0) {
seahorse_debug ("scheduling refresh event due to file changes");
self->pv->scheduled_refresh = g_timeout_add (500, scheduled_refresh, self);
@@ -1048,8 +900,6 @@ seahorse_gpgme_keyring_place_iface (SeahorsePlaceIface *iface)
{
iface->import_async = seahorse_gpgme_keyring_import_async;
iface->import_finish = seahorse_gpgme_keyring_import_finish;
- iface->export_async = seahorse_gpgme_keyring_export_async;
- iface->export_finish = seahorse_gpgme_keyring_export_finish;
}
static guint
diff --git a/pgp/seahorse-hkp-source.c b/pgp/seahorse-hkp-source.c
index 2aeaf28..2004ad3 100644
--- a/pgp/seahorse-hkp-source.c
+++ b/pgp/seahorse-hkp-source.c
@@ -926,19 +926,20 @@ seahorse_hkp_source_import_finish (SeahorsePlace *place,
typedef struct {
SeahorseHKPSource *source;
- GOutputStream *output;
+ GString *data;
GCancellable *cancellable;
gulong cancelled_sig;
SoupSession *session;
gint requests;
-} source_export_closure;
+} ExportClosure;
static void
-source_export_free (gpointer data)
+export_closure_free (gpointer data)
{
- source_export_closure *closure = data;
+ ExportClosure *closure = data;
g_object_unref (closure->source);
- g_object_unref (closure->output);
+ if (closure->data)
+ g_string_free (closure->data, TRUE);
g_cancellable_disconnect (closure->cancellable, closure->cancelled_sig);
g_clear_object (&closure->cancellable);
g_object_unref (closure->session);
@@ -951,14 +952,12 @@ on_export_message_complete (SoupSession *session,
gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- source_export_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ ExportClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GError *error = NULL;
const gchar *start;
const gchar *end;
const gchar *text;
- gboolean ret;
guint len;
- gsize written;
seahorse_progress_end (closure->cancellable, message);
@@ -980,16 +979,8 @@ on_export_message_complete (SoupSession *session,
if (!detect_key (text, len, &start, &end))
break;
- ret = g_output_stream_write_all (closure->output, start, end - start, &written, NULL, &error) &&
- g_output_stream_write_all (closure->output, "\n", 1, &written, NULL, &error) &&
- g_output_stream_flush (closure->output, NULL, &error);
-
- if (!ret) {
- g_simple_async_result_take_error (res, error);
- g_simple_async_result_complete_in_idle (res);
- g_object_unref (res);
- return;
- }
+ g_string_append_len (closure->data, start, end - start);
+ g_string_append_c (closure->data, '\n');
}
g_assert (closure->requests > 0);
@@ -1011,13 +1002,12 @@ on_export_message_complete (SoupSession *session,
static void
seahorse_hkp_source_export_async (SeahorseServerSource *source,
GList *keyids,
- GOutputStream *output,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
SeahorseHKPSource *self = SEAHORSE_HKP_SOURCE (source);
- source_export_closure *closure;
+ ExportClosure *closure;
GSimpleAsyncResult *res;
SoupMessage *message;
SoupURI *uri;
@@ -1029,12 +1019,12 @@ seahorse_hkp_source_export_async (SeahorseServerSource *source,
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
seahorse_hkp_source_export_async);
- closure = g_new0 (source_export_closure, 1);
+ closure = g_new0 (ExportClosure, 1);
closure->source = g_object_ref (self);
- closure->output = g_object_ref (output);
+ closure->data = g_string_sized_new (1024);
closure->session = create_hkp_soup_session ();
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
- g_simple_async_result_set_op_res_gpointer (res, closure, source_export_free);
+ g_simple_async_result_set_op_res_gpointer (res, closure, export_closure_free);
if (g_list_length (keyids) == 0) {
g_simple_async_result_complete_in_idle (res);
@@ -1085,13 +1075,16 @@ seahorse_hkp_source_export_async (SeahorseServerSource *source,
g_object_unref (res);
}
-static GOutputStream *
+static gpointer
seahorse_hkp_source_export_finish (SeahorseServerSource *source,
GAsyncResult *result,
+ gsize *size,
GError **error)
{
- source_export_closure *closure;
+ ExportClosure *closure;
+ gpointer output;
+ g_return_val_if_fail (size != NULL, NULL);
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
seahorse_hkp_source_export_async), NULL);
@@ -1099,7 +1092,10 @@ seahorse_hkp_source_export_finish (SeahorseServerSource *source,
return NULL;
closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
- return closure->output;
+ *size = closure->data->len;
+ output = g_string_free (closure->data, FALSE);
+ closure->data = NULL;
+ return output;
}
/**
diff --git a/pgp/seahorse-ldap-source.c b/pgp/seahorse-ldap-source.c
index df30b83..38d3d0c 100644
--- a/pgp/seahorse-ldap-source.c
+++ b/pgp/seahorse-ldap-source.c
@@ -1204,17 +1204,18 @@ seahorse_ldap_source_import_finish (SeahorsePlace *place,
typedef struct {
GPtrArray *fingerprints;
gint current_index;
- GOutputStream *output;
+ GString *data;
GCancellable *cancellable;
LDAP *ldap;
-} source_export_closure;
+} ExportClosure;
static void
-source_export_free (gpointer data)
+export_closure_free (gpointer data)
{
- source_export_closure *closure = data;
+ ExportClosure *closure = data;
g_ptr_array_free (closure->fingerprints, TRUE);
- g_object_unref (closure->output);
+ if (closure->data)
+ g_string_free (closure->data, TRUE);
g_clear_object (&closure->cancellable);
if (closure->ldap)
ldap_unbind_ext (closure->ldap, NULL, NULL);
@@ -1229,14 +1230,12 @@ on_export_search_completed (LDAPMessage *result,
gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- source_export_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ ExportClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (g_async_result_get_source_object (G_ASYNC_RESULT (res)));
LDAPServerInfo *sinfo;
char *message;
GError *error = NULL;
- gboolean ret;
gchar *key;
- gsize written;
int code;
int type;
int rc;
@@ -1264,18 +1263,10 @@ on_export_search_completed (LDAPMessage *result,
return FALSE;
}
- ret = g_output_stream_write_all (closure->output, key, strlen (key), &written, NULL, &error) &&
- g_output_stream_write_all (closure->output, "\n", 1, &written, NULL, &error) &&
- g_output_stream_flush (closure->output, NULL, &error);
+ g_string_append (closure->data, key);
+ g_string_append_c (closure->data, '\n');
g_free (key);
-
- if (!ret) {
- g_simple_async_result_take_error (res, error);
- g_simple_async_result_complete (res);
- return FALSE;
- }
-
return TRUE;
/* No more entries, result */
@@ -1302,7 +1293,7 @@ static void
export_retrieve_key (SeahorseLDAPSource *self,
GSimpleAsyncResult *res)
{
- source_export_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ ExportClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
LDAPServerInfo *sinfo;
gchar *filter;
char *attrs[2];
@@ -1362,7 +1353,7 @@ on_export_connect_completed (GObject *source,
gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- source_export_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ ExportClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GError *error = NULL;
closure->ldap = seahorse_ldap_source_connect_finish (SEAHORSE_LDAP_SOURCE (source),
@@ -1380,21 +1371,20 @@ on_export_connect_completed (GObject *source,
static void
seahorse_ldap_source_export_async (SeahorseServerSource *source,
GList *keyids,
- GOutputStream *output,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (source);
- source_export_closure *closure;
+ ExportClosure *closure;
GSimpleAsyncResult *res;
gchar *fingerprint;
GList *l;
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
seahorse_ldap_source_export_async);
- closure = g_new0 (source_export_closure, 1);
- closure->output = g_object_ref (output);
+ closure = g_new0 (ExportClosure, 1);
+ closure->data = g_string_sized_new (1024);
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
closure->fingerprints = g_ptr_array_new_with_free_func (g_free);
for (l = keyids; l; l = g_list_next (l)) {
@@ -1403,7 +1393,7 @@ seahorse_ldap_source_export_async (SeahorseServerSource *source,
seahorse_progress_prep (closure->cancellable, fingerprint, NULL);
}
closure->current_index = -1;
- g_simple_async_result_set_op_res_gpointer (res, closure, source_export_free);
+ g_simple_async_result_set_op_res_gpointer (res, closure, export_closure_free);
seahorse_ldap_source_connect_async (self, cancellable,
on_export_connect_completed,
@@ -1412,21 +1402,27 @@ seahorse_ldap_source_export_async (SeahorseServerSource *source,
g_object_unref (res);
}
-static GOutputStream *
+static gpointer
seahorse_ldap_source_export_finish (SeahorseServerSource *source,
GAsyncResult *result,
+ gsize *size,
GError **error)
{
- source_export_closure *closure;
+ ExportClosure *closure;
+ gpointer output;
+ g_return_val_if_fail (size != NULL, NULL);
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
- seahorse_ldap_source_export_async), FALSE);
+ seahorse_ldap_source_export_async), NULL);
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
- return FALSE;
+ return NULL;
closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
- return closure->output;
+ *size = closure->data->len;
+ output = g_string_free (closure->data, FALSE);
+ closure->data = NULL;
+ return output;
}
static void
diff --git a/pgp/seahorse-pgp-key-properties.c b/pgp/seahorse-pgp-key-properties.c
index d29b5ef..8ee8cae 100644
--- a/pgp/seahorse-pgp-key-properties.c
+++ b/pgp/seahorse-pgp-key-properties.c
@@ -32,6 +32,8 @@
#include "seahorse-bind.h"
#include "seahorse-delete-dialog.h"
+#include "seahorse-exportable.h"
+#include "seahorse-exporter.h"
#include "seahorse-icons.h"
#include "seahorse-object.h"
#include "seahorse-object-model.h"
@@ -39,6 +41,7 @@
#include "seahorse-util.h"
#include "seahorse-gpgme-dialogs.h"
+#include "seahorse-gpgme-exporter.h"
#include "seahorse-gpgme-key.h"
#include "seahorse-gpgme-key-op.h"
#include "seahorse-pgp-backend.h"
@@ -1130,21 +1133,17 @@ on_pgp_details_trust_changed (GtkComboBox *selection,
}
static void
-export_complete (GFile *file, GAsyncResult *result, gchar *contents)
+on_export_complete (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
- GError *err = NULL;
- gchar *uri, *unesc_uri;
-
- g_free (contents);
-
- if (!g_file_replace_contents_finish (file, result, NULL, &err)) {
- uri = g_file_get_uri (file);
- unesc_uri = g_uri_unescape_string (seahorse_util_uri_get_last (uri), NULL);
- seahorse_util_handle_error (&err, NULL, _("Couldn't export key to \"%s\""),
- unesc_uri);
- g_free (uri);
- g_free (unesc_uri);
- }
+ GtkWindow *parent = GTK_WINDOW (user_data);
+ GError *error = NULL;
+
+ if (!seahorse_exporter_export_to_file_finish (SEAHORSE_EXPORTER (source), result, &error))
+ seahorse_util_handle_error (&error, parent, _("Couldn't export key"));
+
+ g_object_unref (parent);
}
G_MODULE_EXPORT void
@@ -1152,56 +1151,25 @@ on_pgp_details_export_button (GtkWidget *widget,
gpointer user_data)
{
SeahorseWidget *swidget = SEAHORSE_WIDGET (user_data);
+ SeahorseExporter *exporter;
+ GList *exporters = NULL;
+ GtkWindow *window;
GObject *object;
- GtkDialog *dialog;
- gchar* uri = NULL;
- GError *err = NULL;
GFile *file;
- gpgme_error_t gerr;
- gpgme_ctx_t ctx;
- gpgme_data_t data;
- gchar *results;
- gsize n_results;
- gpgme_key_t seckey;
object = SEAHORSE_OBJECT_WIDGET (swidget)->object;
- g_return_if_fail (SEAHORSE_IS_GPGME_KEY (object));
- seckey = seahorse_gpgme_key_get_private (SEAHORSE_GPGME_KEY (object));
- g_return_if_fail (seckey && seckey->subkeys && seckey->subkeys->keyid);
+ exporters = g_list_append (exporters, seahorse_gpgme_exporter_new (object, TRUE, TRUE));
- dialog = seahorse_util_chooser_save_new (_("Export Complete Key"),
- GTK_WINDOW (seahorse_widget_get_toplevel (swidget)));
- seahorse_util_chooser_show_key_files (dialog);
- seahorse_util_chooser_set_filename (dialog, object);
-
- uri = seahorse_util_chooser_save_prompt (dialog);
- if (!uri)
- return;
-
- ctx = seahorse_gpgme_keyring_new_context (&gerr);
- if (ctx == NULL)
- return;
-
- /* Export to a data block */
- gerr = gpgme_data_new (&data);
- g_return_if_fail (GPG_IS_OK (gerr));
-
- gerr = seahorse_gpg_op_export_secret (ctx, seckey->subkeys->keyid, data);
- gpgme_release (ctx);
- results = gpgme_data_release_and_get_mem (data, &n_results);
-
- if (GPG_IS_OK (gerr)) {
- file = g_file_new_for_uri (uri);
- g_file_replace_contents_async (file, results, n_results, NULL, FALSE,
- G_FILE_CREATE_PRIVATE, NULL,
- (GAsyncReadyCallback)export_complete, results);
- } else {
- seahorse_gpgme_propagate_error (gerr, &err);
- seahorse_util_handle_error (&err, NULL, _("Couldn't export key."));
+ window = GTK_WINDOW (seahorse_widget_get_toplevel (swidget));
+ if (seahorse_exportable_prompt (exporters, window, NULL, &file, &exporter)) {
+ seahorse_exporter_export_to_file_async (exporter, file, TRUE, NULL,
+ on_export_complete, g_object_ref (window));
+ g_object_unref (file);
+ g_object_unref (exporter);
}
-
- g_free (uri);
+
+ g_list_free_full (exporters, g_object_unref);
}
G_MODULE_EXPORT void
diff --git a/pgp/seahorse-server-source.c b/pgp/seahorse-server-source.c
index 39d881e..d146cab 100644
--- a/pgp/seahorse-server-source.c
+++ b/pgp/seahorse-server-source.c
@@ -399,7 +399,6 @@ seahorse_server_source_search_finish (SeahorseServerSource *self,
void
seahorse_server_source_export_async (SeahorseServerSource *self,
GList *keyids,
- GOutputStream *output,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -407,27 +406,28 @@ seahorse_server_source_export_async (SeahorseServerSource *self,
SeahorseServerSourceClass *klass;
g_return_if_fail (SEAHORSE_IS_SERVER_SOURCE (self));
- g_return_if_fail (output == NULL || G_IS_OUTPUT_STREAM (output));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
klass = SEAHORSE_SERVER_SOURCE_GET_CLASS (self);
g_return_if_fail (klass->export_async);
- (klass->export_async) (self, keyids, output, cancellable, callback, user_data);
+ (klass->export_async) (self, keyids, cancellable, callback, user_data);
}
-GOutputStream *
+gpointer
seahorse_server_source_export_finish (SeahorseServerSource *self,
GAsyncResult *result,
+ gsize *size,
GError **error)
{
SeahorseServerSourceClass *klass;
g_return_val_if_fail (SEAHORSE_IS_SERVER_SOURCE (self), NULL);
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+ g_return_val_if_fail (size != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
klass = SEAHORSE_SERVER_SOURCE_GET_CLASS (self);
g_return_val_if_fail (klass->export_async != NULL, NULL);
g_return_val_if_fail (klass->export_finish != NULL, NULL);
- return (klass->export_finish) (self, result, error);
+ return (klass->export_finish) (self, result, size, error);
}
diff --git a/pgp/seahorse-server-source.h b/pgp/seahorse-server-source.h
index e701d03..3aab05d 100644
--- a/pgp/seahorse-server-source.h
+++ b/pgp/seahorse-server-source.h
@@ -66,13 +66,13 @@ struct _SeahorseServerSourceClass {
void (*export_async) (SeahorseServerSource *source,
GList *ids,
- GOutputStream *output,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
- GOutputStream * (*export_finish) (SeahorseServerSource *source,
+ gpointer (*export_finish) (SeahorseServerSource *source,
GAsyncResult *result,
+ gsize *size,
GError **error);
void (*search_async) (SeahorseServerSource *source,
@@ -104,13 +104,13 @@ gboolean seahorse_server_source_search_finish (SeahorseServerSo
void seahorse_server_source_export_async (SeahorseServerSource *self,
GList *ids,
- GOutputStream *output,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-GOutputStream * seahorse_server_source_export_finish (SeahorseServerSource *self,
+gpointer seahorse_server_source_export_finish (SeahorseServerSource *self,
GAsyncResult *result,
+ gsize *size,
GError **error);
#endif /* __SEAHORSE_SERVER_SOURCE_H__ */
diff --git a/pgp/seahorse-transfer.c b/pgp/seahorse-transfer.c
index 82afbd9..31494e8 100644
--- a/pgp/seahorse-transfer.c
+++ b/pgp/seahorse-transfer.c
@@ -23,35 +23,34 @@
#include "config.h"
#include "seahorse-server-source.h"
+#include "seahorse-gpgme-exporter.h"
#include "seahorse-gpgme-keyring.h"
-#include <stdlib.h>
-#include <glib/gi18n.h>
-
+#define DEBUG_FLAG SEAHORSE_DEBUG_OPERATION
+#include "seahorse-debug.h"
+#include "seahorse-exporter.h"
#include "seahorse-object-list.h"
-#include "seahorse-transfer.h"
#include "seahorse-progress.h"
+#include "seahorse-transfer.h"
#include "seahorse-util.h"
-#define DEBUG_FLAG SEAHORSE_DEBUG_OPERATION
-#include "seahorse-debug.h"
+#include <glib/gi18n.h>
+
+#include <stdlib.h>
typedef struct {
GCancellable *cancellable;
SeahorsePlace *from;
SeahorsePlace *to;
- GOutputStream *output;
GList *keys;
-} transfer_closure;
+} TransferClosure;
static void
transfer_closure_free (gpointer user_data)
{
- transfer_closure *closure = user_data;
-
+ TransferClosure *closure = user_data;
g_clear_object (&closure->from);
g_clear_object (&closure->to);
- g_clear_object (&closure->output);
g_clear_object (&closure->cancellable);
seahorse_object_list_free (closure->keys);
g_free (closure);
@@ -63,7 +62,7 @@ on_source_import_ready (GObject *object,
gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- transfer_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ TransferClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GError *error = NULL;
seahorse_debug ("[transfer] import done");
@@ -85,9 +84,9 @@ on_source_export_ready (GObject *object,
gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- transfer_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ TransferClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GError *error = NULL;
- gpointer stream_data;
+ gpointer stream_data = NULL;
gsize stream_size;
GInputStream *input;
@@ -95,11 +94,15 @@ on_source_export_ready (GObject *object,
seahorse_progress_end (closure->cancellable, &closure->from);
if (SEAHORSE_IS_SERVER_SOURCE (closure->from)) {
- seahorse_server_source_export_finish (SEAHORSE_SERVER_SOURCE (closure->from),
- result, &error);
+ stream_data = seahorse_server_source_export_finish (SEAHORSE_SERVER_SOURCE (object),
+ result, &stream_size, &error);
+
+ } else if (SEAHORSE_IS_GPGME_KEYRING (closure->from)) {
+ stream_data = seahorse_exporter_export_finish (SEAHORSE_EXPORTER (object), result,
+ &stream_size, &error);
} else {
- seahorse_place_export_finish (closure->from, result, &error);
+ g_warning ("unsupported source for export: %s", G_OBJECT_TYPE_NAME (object));
}
if (error == NULL)
@@ -108,17 +111,15 @@ on_source_export_ready (GObject *object,
if (error == NULL) {
seahorse_progress_begin (closure->cancellable, &closure->to);
- stream_data = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (closure->output));
- stream_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (closure->output));
-
if (!stream_size) {
seahorse_debug ("[transfer] nothing to import");
seahorse_progress_end (closure->cancellable, &closure->to);
g_simple_async_result_complete (res);
} else {
- input = g_memory_input_stream_new_from_data (g_memdup (stream_data, stream_size),
- stream_size, g_free);
+ input = g_memory_input_stream_new_from_data (stream_data, stream_size, g_free);
+ stream_data = NULL;
+ stream_size = 0;
seahorse_debug ("[transfer] starting import");
seahorse_place_import_async (closure->to, input, closure->cancellable,
@@ -132,6 +133,7 @@ on_source_export_ready (GObject *object,
g_simple_async_result_complete (res);
}
+ g_free (stream_data);
g_object_unref (user_data);
}
@@ -139,7 +141,8 @@ static gboolean
on_timeout_start_transfer (gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- transfer_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ TransferClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ SeahorseExporter *exporter;
GList *keyids, *l;
g_assert (SEAHORSE_IS_PLACE (closure->from));
@@ -152,13 +155,18 @@ on_timeout_start_transfer (gpointer user_data)
keyids = g_list_prepend (keyids, (gpointer)seahorse_pgp_key_get_keyid (l->data));
keyids = g_list_reverse (keyids);
seahorse_server_source_export_async (SEAHORSE_SERVER_SOURCE (closure->from),
- keyids, closure->output, closure->cancellable,
+ keyids, closure->cancellable,
on_source_export_ready, g_object_ref (res));
g_list_free (keyids);
+
+ } else if (SEAHORSE_IS_GPGME_KEYRING (closure->from)) {
+ exporter = seahorse_gpgme_exporter_new_multiple (closure->keys, TRUE);
+ seahorse_exporter_export_async (exporter, closure->cancellable,
+ on_source_export_ready, g_object_ref (res));
+ g_object_unref (exporter);
+
} else {
- seahorse_place_export_async (closure->from, closure->keys, closure->output,
- closure->cancellable, on_source_export_ready,
- g_object_ref (res));
+ g_warning ("unsupported source for transfer: %s", G_OBJECT_TYPE_NAME (closure->from));
}
return FALSE; /* Don't run again */
@@ -173,7 +181,7 @@ seahorse_transfer_async (SeahorsePlace *from,
gpointer user_data)
{
GSimpleAsyncResult *res;
- transfer_closure *closure = NULL;
+ TransferClosure *closure;
g_return_if_fail (SEAHORSE_PLACE (from));
g_return_if_fail (SEAHORSE_PLACE (to));
@@ -187,12 +195,11 @@ seahorse_transfer_async (SeahorsePlace *from,
return;
}
- closure = g_new0 (transfer_closure, 1);
+ closure = g_new0 (TransferClosure, 1);
closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
closure->from = g_object_ref (from);
closure->to = g_object_ref (to);
closure->keys = seahorse_object_list_copy (keys);
- closure->output = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
g_simple_async_result_set_op_res_gpointer (res, closure, transfer_closure_free);
seahorse_progress_prep (cancellable, &closure->from,
diff --git a/pkcs11/Makefile.am b/pkcs11/Makefile.am
index 6406266..7cdce84 100644
--- a/pkcs11/Makefile.am
+++ b/pkcs11/Makefile.am
@@ -16,6 +16,7 @@ noinst_LTLIBRARIES = libseahorse-pkcs11.la
libseahorse_pkcs11_la_SOURCES = \
seahorse-certificate.c seahorse-certificate.h \
+ seahorse-certificate-der-exporter.c seahorse-certificate-der-exporter.h \
seahorse-interaction.c seahorse-interaction.h \
seahorse-pkcs11-actions.c seahorse-pkcs11-actions.h \
seahorse-pkcs11-backend.c seahorse-pkcs11-backend.h \
diff --git a/pkcs11/seahorse-certificate-der-exporter.c b/pkcs11/seahorse-certificate-der-exporter.c
new file mode 100644
index 0000000..3b6f7d6
--- /dev/null
+++ b/pkcs11/seahorse-certificate-der-exporter.c
@@ -0,0 +1,245 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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 "seahorse-certificate.h"
+#include "seahorse-certificate-der-exporter.h"
+
+#include "seahorse-util.h"
+
+#include <gcr/gcr.h>
+
+#include <glib/gi18n.h>
+
+#include <string.h>
+
+#define SEAHORSE_CERTIFICATE_DER_EXPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_CERTIFICATE_DER_EXPORTER, SeahorseCertificateDerExporterClass))
+#define SEAHORSE_IS_CERTIFICATE_DER_EXPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_CERTIFICATE_DER_EXPORTER))
+#define SEAHORSE_CERTIFICATE_DER_EXPORTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_CERTIFICATE_DER_EXPORTER, SeahorseCertificateDerExporterClass))
+
+typedef struct _SeahorseCertificateDerExporterClass SeahorseCertificateDerExporterClass;
+
+struct _SeahorseCertificateDerExporter {
+ GObject parent;
+ SeahorseCertificate *certificate;
+ GList *objects;
+};
+
+struct _SeahorseCertificateDerExporterClass {
+ GObjectClass parent_class;
+};
+
+enum {
+ PROP_0,
+ PROP_FILENAME,
+ PROP_CONTENT_TYPE,
+ PROP_FILE_FILTER,
+};
+
+static void seahorse_certificate_der_exporter_iface_init (SeahorseExporterIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (SeahorseCertificateDerExporter, seahorse_certificate_der_exporter, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_EXPORTER, seahorse_certificate_der_exporter_iface_init);
+);
+
+static gchar *
+calc_filename (SeahorseCertificateDerExporter *self)
+{
+ const gchar *basename = NULL;
+ gchar *label = NULL;
+ gchar *filename;
+
+ g_return_val_if_fail (self->certificate, NULL);
+
+ g_object_get (self->certificate, "label", &label, NULL);
+ if (label == NULL)
+ basename = _("Certificate");
+ else
+ basename = label;
+
+ filename = g_strconcat (basename, ".crt", NULL);
+ g_strstrip (filename);
+ g_strdelimit (filename, SEAHORSE_BAD_FILENAME_CHARS, '_');
+ g_free (label);
+ return filename;
+}
+
+static const gchar *
+calc_content_type (SeahorseCertificateDerExporter *self)
+{
+ return "application/pkix-cert";
+}
+
+static GtkFileFilter *
+calc_file_filter (SeahorseCertificateDerExporter *self)
+{
+ GtkFileFilter *filter = gtk_file_filter_new ();
+
+ gtk_file_filter_set_name (filter, _("Certificates (DER encoded)"));
+ gtk_file_filter_add_mime_type (filter, "application/pkix-cert");
+ gtk_file_filter_add_mime_type (filter, "application/x-x509-ca-cert");
+ gtk_file_filter_add_mime_type (filter, "application/x-x509-user-cert");
+ gtk_file_filter_add_pattern (filter, "*.cer");
+ gtk_file_filter_add_pattern (filter, "*.crt");
+ gtk_file_filter_add_pattern (filter, "*.cert");
+
+ return filter;
+}
+
+static void
+seahorse_certificate_der_exporter_init (SeahorseCertificateDerExporter *self)
+{
+
+}
+
+static void
+seahorse_certificate_der_exporter_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SeahorseCertificateDerExporter *self = SEAHORSE_CERTIFICATE_DER_EXPORTER (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ g_value_take_string (value, calc_filename (self));
+ break;
+ case PROP_CONTENT_TYPE:
+ g_value_set_string (value, calc_content_type (self));
+ break;
+ case PROP_FILE_FILTER:
+ g_value_take_object (value, calc_file_filter (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+seahorse_certificate_der_exporter_finalize (GObject *obj)
+{
+ SeahorseCertificateDerExporter *self = SEAHORSE_CERTIFICATE_DER_EXPORTER (obj);
+
+ g_clear_object (&self->certificate);
+ g_list_free (self->objects);
+
+ G_OBJECT_CLASS (seahorse_certificate_der_exporter_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_certificate_der_exporter_class_init (SeahorseCertificateDerExporterClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = seahorse_certificate_der_exporter_finalize;
+ gobject_class->get_property = seahorse_certificate_der_exporter_get_property;
+
+ g_object_class_override_property (gobject_class, PROP_FILENAME, "filename");
+ g_object_class_override_property (gobject_class, PROP_CONTENT_TYPE, "content-type");
+ g_object_class_override_property (gobject_class, PROP_FILE_FILTER, "file-filter");
+}
+
+static GList *
+seahorse_certificate_der_exporter_get_objects (SeahorseExporter *exporter)
+{
+ SeahorseCertificateDerExporter *self = SEAHORSE_CERTIFICATE_DER_EXPORTER (exporter);
+ return self->objects;
+}
+
+static gboolean
+seahorse_certificate_der_exporter_add_object (SeahorseExporter *exporter,
+ GObject *object)
+{
+ SeahorseCertificateDerExporter *self = SEAHORSE_CERTIFICATE_DER_EXPORTER (exporter);
+
+ if (self->certificate == NULL && SEAHORSE_IS_CERTIFICATE (object)) {
+ self->certificate = g_object_ref (object);
+ self->objects = g_list_append (self->objects, self->certificate);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+seahorse_certificate_der_exporter_export_async (SeahorseExporter *exporter,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SeahorseCertificateDerExporter *self = SEAHORSE_CERTIFICATE_DER_EXPORTER (exporter);
+ GSimpleAsyncResult *res;
+
+ g_return_if_fail (self->certificate != NULL);
+
+ res = g_simple_async_result_new (G_OBJECT (exporter), callback, user_data,
+ seahorse_certificate_der_exporter_export_async);
+
+ g_simple_async_result_complete_in_idle (res);
+ g_object_unref (res);
+}
+
+static gpointer
+seahorse_certificate_der_exporter_export_finish (SeahorseExporter *exporter,
+ GAsyncResult *result,
+ gsize *size,
+ GError **error)
+{
+ SeahorseCertificateDerExporter *self = SEAHORSE_CERTIFICATE_DER_EXPORTER (exporter);
+ gconstpointer output;
+
+ g_return_val_if_fail (self->certificate != NULL, NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (exporter),
+ seahorse_certificate_der_exporter_export_async), NULL);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return NULL;
+
+ output = gcr_certificate_get_der_data (GCR_CERTIFICATE (self->certificate), size);
+ return g_memdup (output, *size);
+}
+
+static void
+seahorse_certificate_der_exporter_iface_init (SeahorseExporterIface *iface)
+{
+ iface->add_object = seahorse_certificate_der_exporter_add_object;
+ iface->export_async = seahorse_certificate_der_exporter_export_async;
+ iface->export_finish = seahorse_certificate_der_exporter_export_finish;
+ iface->get_objects = seahorse_certificate_der_exporter_get_objects;
+}
+
+SeahorseExporter *
+seahorse_certificate_der_exporter_new (SeahorseCertificate *certificate)
+{
+ SeahorseExporter *exporter;
+
+ exporter = g_object_new (SEAHORSE_TYPE_CERTIFICATE_DER_EXPORTER,
+ NULL);
+
+ if (!seahorse_exporter_add_object (exporter, G_OBJECT (certificate)))
+ g_assert_not_reached ();
+
+ return exporter;
+}
diff --git a/pkcs11/seahorse-certificate-der-exporter.h b/pkcs11/seahorse-certificate-der-exporter.h
new file mode 100644
index 0000000..78d02b5
--- /dev/null
+++ b/pkcs11/seahorse-certificate-der-exporter.h
@@ -0,0 +1,41 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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 __SEAHORSE_CERTIFICATE_DER_EXPORTER_H__
+#define __SEAHORSE_CERTIFICATE_DER_EXPORTER_H__
+
+#include "seahorse-exporter.h"
+
+#include <glib-object.h>
+
+#define SEAHORSE_TYPE_CERTIFICATE_DER_EXPORTER (seahorse_certificate_der_exporter_get_type ())
+#define SEAHORSE_CERTIFICATE_DER_EXPORTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_CERTIFICATE_DER_EXPORTER, SeahorseCertificateDerExporter))
+#define SEAHORSE_IS_CERTIFICATE_DER_EXPORTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_CERTIFICATE_DER_EXPORTER))
+
+typedef struct _SeahorseCertificateDerExporter SeahorseCertificateDerExporter;
+
+GType seahorse_certificate_der_exporter_get_type (void) G_GNUC_CONST;
+
+SeahorseExporter * seahorse_certificate_der_exporter_new (SeahorseCertificate *certificate);
+
+#endif /* __SEAHORSE_CERTIFICATE_DER_EXPORTER_H__ */
diff --git a/pkcs11/seahorse-certificate.c b/pkcs11/seahorse-certificate.c
index e2fb500..3ae4474 100644
--- a/pkcs11/seahorse-certificate.c
+++ b/pkcs11/seahorse-certificate.c
@@ -23,6 +23,7 @@
#include "config.h"
#include "seahorse-certificate.h"
+#include "seahorse-certificate-der-exporter.h"
#include "seahorse-pkcs11.h"
#include "seahorse-pkcs11-actions.h"
#include "seahorse-pkcs11-helpers.h"
@@ -30,6 +31,7 @@
#include "seahorse-token.h"
#include "seahorse-types.h"
+#include "seahorse-exportable.h"
#include "seahorse-util.h"
#include "seahorse-validity.h"
@@ -66,13 +68,17 @@ struct _SeahorseCertificatePrivate {
GIcon *icon;
};
-static void seahorse_certificate_certificate_iface (GcrCertificateIface *iface);
-static void seahorse_certificate_object_attributes_iface (GckObjectAttributesIface *iface);
+static void seahorse_certificate_certificate_iface (GcrCertificateIface *iface);
+
+static void seahorse_certificate_object_attributes_iface (GckObjectAttributesIface *iface);
+
+static void seahorse_certificate_exportable_iface (SeahorseExportableIface *iface);
G_DEFINE_TYPE_WITH_CODE (SeahorseCertificate, seahorse_certificate, GCK_TYPE_OBJECT,
GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE ();
G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, seahorse_certificate_certificate_iface);
- G_IMPLEMENT_INTERFACE (GCK_TYPE_OBJECT_ATTRIBUTES, seahorse_certificate_object_attributes_iface)
+ G_IMPLEMENT_INTERFACE (GCK_TYPE_OBJECT_ATTRIBUTES, seahorse_certificate_object_attributes_iface);
+ G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_EXPORTABLE, seahorse_certificate_exportable_iface);
);
static void
@@ -278,6 +284,21 @@ seahorse_certificate_object_attributes_iface (GckObjectAttributesIface *iface)
iface->n_attribute_types = G_N_ELEMENTS (REQUIRED_ATTRS);
}
+static GList *
+seahorse_certificate_create_exporters (SeahorseExportable *exportable,
+ SeahorseExporterType type)
+{
+ SeahorseExporter *exporter;
+ exporter = seahorse_certificate_der_exporter_new (SEAHORSE_CERTIFICATE (exportable));
+ return g_list_append (NULL, exporter);
+}
+
+static void
+seahorse_certificate_exportable_iface (SeahorseExportableIface *iface)
+{
+ iface->create_exporters = seahorse_certificate_create_exporters;
+}
+
GIcon *
seahorse_certificate_get_icon (SeahorseCertificate *self)
{
diff --git a/pkcs11/seahorse-pkcs11-properties.c b/pkcs11/seahorse-pkcs11-properties.c
index 409baa7..fd00890 100644
--- a/pkcs11/seahorse-pkcs11-properties.c
+++ b/pkcs11/seahorse-pkcs11-properties.c
@@ -29,6 +29,7 @@
#include "seahorse-action.h"
#include "seahorse-delete-dialog.h"
+#include "seahorse-exportable.h"
#include "seahorse-progress.h"
#include "seahorse-util.h"
@@ -155,7 +156,17 @@ static void
on_export_certificate (GtkAction *action,
gpointer user_data)
{
- /* TODO: Exporter not done */
+ SeahorsePkcs11Properties *self = SEAHORSE_PKCS11_PROPERTIES (user_data);
+ GtkWindow *parent = GTK_WINDOW (self);
+ GError *error = NULL;
+ GList *objects;
+
+ objects = g_list_append (NULL, self->object);
+ seahorse_exportable_export_to_prompt_wait (objects, parent, &error);
+ g_list_free (objects);
+
+ if (error != NULL)
+ seahorse_util_handle_error (&error, parent, _("Failed to export certificate"));
}
static void
@@ -327,6 +338,7 @@ seahorse_pkcs11_properties_constructed (GObject *obj)
SeahorsePkcs11Properties *self = SEAHORSE_PKCS11_PROPERTIES (obj);
GObject *partner = NULL;
GError *error = NULL;
+ GList *exporters = NULL;
GtkAction *request;
G_OBJECT_CLASS (seahorse_pkcs11_properties_parent_class)->constructed (obj);
@@ -366,6 +378,14 @@ seahorse_pkcs11_properties_constructed (GObject *obj)
g_object_unref (partner);
}
+ if (SEAHORSE_IS_EXPORTABLE (self->object))
+ exporters = seahorse_exportable_create_exporters (SEAHORSE_EXPORTABLE (self->object),
+ SEAHORSE_EXPORTER_ANY);
+
+ request = gtk_action_group_get_action (self->actions, "export-object");
+ gtk_action_set_visible (request, exporters != NULL);
+ g_list_free_full (exporters, g_object_unref);
+
gtk_widget_grab_focus (GTK_WIDGET (self->viewer));
}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 494e867..3735718 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -16,6 +16,7 @@ gkr/seahorse-gkr-operation.c
libegg/egg-datetime.c
[type: gettext/glade]libseahorse/seahorse-add-keyserver.xml
libseahorse/seahorse-context.c
+libseahorse/seahorse-exportable.c
libseahorse/seahorse-key-manager-store.c
libseahorse/seahorse-object.c
libseahorse/seahorse-passphrase.c
@@ -52,6 +53,7 @@ pgp/seahorse-keyserver-sync.c
pgp/seahorse-ldap-source.c
pgp/seahorse-pgp-actions.c
pgp/seahorse-pgp-backend.c
+pgp/seahorse-gpgme-exporter.c
[type: gettext/glade]pgp/seahorse-pgp-generate.xml
pgp/seahorse-pgp-key.c
pgp/seahorse-pgp-key-properties.c
@@ -67,6 +69,7 @@ pgp/seahorse-transfer.c
pgp/seahorse-unknown.c
pgp/seahorse-unknown-source.c
pkcs11/seahorse-certificate.c
+pkcs11/seahorse-certificate-der-exporter.c
pkcs11/seahorse-interaction.c
pkcs11/seahorse-pkcs11-actions.c
pkcs11/seahorse-pkcs11-backend.c
@@ -88,6 +91,7 @@ src/seahorse-main.c
ssh/seahorse-ssh-actions.c
ssh/seahorse-ssh-askpass.c
ssh/seahorse-ssh-backend.c
+ssh/seahorse-ssh-exporter.c
ssh/seahorse-ssh-generate.c
[type: gettext/glade]ssh/seahorse-ssh-generate.xml
ssh/seahorse-ssh-key.c
diff --git a/src/seahorse-key-manager.ui b/src/seahorse-key-manager.ui
index ea72e35..3bbefc4 100644
--- a/src/seahorse-key-manager.ui
+++ b/src/seahorse-key-manager.ui
@@ -3,6 +3,7 @@
<menu name="File" action="file-menu">
<menuitem action="file-new"/>
<menuitem action="file-import"/>
+ <menuitem action="file-export"/>
<separator/>
<placeholder name="FileCommands">
</placeholder>
@@ -10,6 +11,7 @@
<menuitem action="app-quit"/>
</menu>
<menu name="Edit" action="edit-menu">
+ <menuitem action="edit-export-clipboard"/>
<menuitem action="edit-import-clipboard"/>
<menuitem action="edit-delete"/>
<separator/>
diff --git a/ssh/Makefile.am b/ssh/Makefile.am
index 0ff2116..af3a760 100644
--- a/ssh/Makefile.am
+++ b/ssh/Makefile.am
@@ -21,6 +21,7 @@ libseahorse_ssh_la_SOURCES = \
seahorse-ssh-actions.c seahorse-ssh-actions.h \
seahorse-ssh-backend.c seahorse-ssh-backend.h \
seahorse-ssh-dialogs.h \
+ seahorse-ssh-exporter.c seahorse-ssh-exporter.h \
seahorse-ssh-generate.c \
seahorse-ssh-key-data.c seahorse-ssh-key-data.h \
seahorse-ssh-key.c seahorse-ssh-key.h \
diff --git a/ssh/seahorse-ssh-exporter.c b/ssh/seahorse-ssh-exporter.c
new file mode 100644
index 0000000..1f76279
--- /dev/null
+++ b/ssh/seahorse-ssh-exporter.c
@@ -0,0 +1,321 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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 "seahorse-ssh.h"
+#include "seahorse-ssh-key.h"
+#include "seahorse-ssh-exporter.h"
+#include "seahorse-ssh-source.h"
+
+#include "seahorse-exporter.h"
+#include "seahorse-object.h"
+#include "seahorse-util.h"
+
+#include <glib/gi18n.h>
+
+#include <string.h>
+
+#define SEAHORSE_SSH_EXPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_SSH_EXPORTER, SeahorseSshExporterClass))
+#define SEAHORSE_IS_SSH_EXPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_SSH_EXPORTER))
+#define SEAHORSE_SSH_EXPORTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_SSH_EXPORTER, SeahorseSshExporterClass))
+
+typedef struct _SeahorseSshExporterClass SeahorseSshExporterClass;
+
+struct _SeahorseSshExporter {
+ GObject parent;
+ SeahorseSSHKey *key;
+ GList *objects;
+ gboolean secret;
+};
+
+struct _SeahorseSshExporterClass {
+ GObjectClass parent_class;
+};
+
+enum {
+ PROP_0,
+ PROP_FILENAME,
+ PROP_CONTENT_TYPE,
+ PROP_FILE_FILTER,
+ PROP_SECRET
+};
+
+static void seahorse_ssh_exporter_iface_init (SeahorseExporterIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (SeahorseSshExporter, seahorse_ssh_exporter, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_EXPORTER, seahorse_ssh_exporter_iface_init);
+);
+
+static gchar *
+calc_filename (SeahorseSshExporter *self)
+{
+ SeahorseSSHKeyData *data;
+ const gchar *location = NULL;
+ const gchar *basename = NULL;
+ gchar *filename;
+
+ g_return_val_if_fail (self->key, NULL);
+
+ data = seahorse_ssh_key_get_data (self->key);
+ if (data && !data->partial) {
+ if (self->secret && data->privfile)
+ location = data->privfile;
+ else if (!self->secret && data->pubfile)
+ location = data->pubfile;
+ if (location != NULL)
+ return g_path_get_basename (location);
+ }
+
+ basename = seahorse_object_get_nickname (SEAHORSE_OBJECT (self->key));
+ if (basename == NULL)
+ basename = _("Ssh Key");
+
+ if (self->secret) {
+ filename = g_strdup_printf ("id_%s", basename);
+ g_strstrip (filename);
+ g_strdelimit (filename, SEAHORSE_BAD_FILENAME_CHARS " ", '_');
+ return filename;
+ } else {
+ filename = g_strdup_printf ("%s.pub", basename);
+ g_strstrip (filename);
+ g_strdelimit (filename, SEAHORSE_BAD_FILENAME_CHARS, '_');
+ return filename;
+ }
+}
+
+static const gchar *
+calc_content_type (SeahorseSshExporter *self)
+{
+ if (self->secret)
+ return "application/x-pem-key";
+ else
+ return "application/x-ssh-key";
+}
+
+static GtkFileFilter *
+calc_file_filter (SeahorseSshExporter *self)
+{
+ GtkFileFilter *filter = gtk_file_filter_new ();
+
+ if (self->secret) {
+ gtk_file_filter_set_name (filter, _("Secret SSH keys"));
+ gtk_file_filter_add_mime_type (filter, "application/x-pem-key");
+ gtk_file_filter_add_pattern (filter, "id_*");
+ } else {
+ gtk_file_filter_set_name (filter, _("Public SSH keys"));
+ gtk_file_filter_add_mime_type (filter, "application/x-ssh-key");
+ gtk_file_filter_add_pattern (filter, "*.pub");
+ }
+
+ return filter;
+}
+
+static void
+seahorse_ssh_exporter_init (SeahorseSshExporter *self)
+{
+
+}
+
+static void
+seahorse_ssh_exporter_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SeahorseSshExporter *self = SEAHORSE_SSH_EXPORTER (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ g_value_take_string (value, calc_filename (self));
+ break;
+ case PROP_CONTENT_TYPE:
+ g_value_set_string (value, calc_content_type (self));
+ break;
+ case PROP_FILE_FILTER:
+ g_value_take_object (value, calc_file_filter (self));
+ break;
+ case PROP_SECRET:
+ g_value_set_boolean (value, self->secret);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+seahorse_ssh_exporter_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SeahorseSshExporter *self = SEAHORSE_SSH_EXPORTER (object);
+
+ switch (prop_id) {
+ case PROP_SECRET:
+ self->secret = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+seahorse_ssh_exporter_finalize (GObject *obj)
+{
+ SeahorseSshExporter *self = SEAHORSE_SSH_EXPORTER (obj);
+
+ g_clear_object (&self->key);
+
+ G_OBJECT_CLASS (seahorse_ssh_exporter_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_ssh_exporter_class_init (SeahorseSshExporterClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = seahorse_ssh_exporter_finalize;
+ gobject_class->set_property = seahorse_ssh_exporter_set_property;
+ gobject_class->get_property = seahorse_ssh_exporter_get_property;
+
+ g_object_class_override_property (gobject_class, PROP_FILENAME, "filename");
+ g_object_class_override_property (gobject_class, PROP_CONTENT_TYPE, "content-type");
+ g_object_class_override_property (gobject_class, PROP_FILE_FILTER, "file-filter");
+
+ g_object_class_install_property (gobject_class, PROP_SECRET,
+ g_param_spec_boolean ("secret", "Secret", "Secret key export",
+ FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static GList *
+seahorse_ssh_exporter_get_objects (SeahorseExporter *exporter)
+{
+ SeahorseSshExporter *self = SEAHORSE_SSH_EXPORTER (exporter);
+ return self->objects;
+}
+
+static gboolean
+seahorse_ssh_exporter_add_object (SeahorseExporter *exporter,
+ GObject *object)
+{
+ SeahorseSshExporter *self = SEAHORSE_SSH_EXPORTER (exporter);
+ SeahorseSSHKey *key;
+ SeahorseUsage usage;
+
+ if (SEAHORSE_IS_SSH_KEY (object) && !self->key) {
+ key = SEAHORSE_SSH_KEY (object);
+ if (self->secret) {
+ usage = seahorse_object_get_usage (SEAHORSE_OBJECT (object));
+ if (usage != SEAHORSE_USAGE_PRIVATE_KEY)
+ return FALSE;
+ }
+ self->key = g_object_ref (key);
+ self->objects = g_list_append (self->objects, self->key);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+seahorse_ssh_exporter_export_async (SeahorseExporter *exporter,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SeahorseSshExporter *self = SEAHORSE_SSH_EXPORTER (exporter);
+ GSimpleAsyncResult *res;
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ seahorse_ssh_exporter_export_async);
+
+ g_simple_async_result_complete_in_idle (res);
+ g_object_unref (res);
+ }
+
+static gpointer
+seahorse_ssh_exporter_export_finish (SeahorseExporter *exporter,
+ GAsyncResult *result,
+ gsize *size,
+ GError **error)
+{
+ SeahorseSshExporter *self = SEAHORSE_SSH_EXPORTER (exporter);
+ SeahorseSSHKeyData *keydata;
+ gpointer results = NULL;
+ SeahorsePlace *place;
+ gsize n_results;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (exporter),
+ seahorse_ssh_exporter_export_async), NULL);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return NULL;
+
+ keydata = seahorse_ssh_key_get_data (self->key);
+
+ if (self->secret) {
+ place = seahorse_object_get_place (SEAHORSE_OBJECT (self->key));
+ results = seahorse_ssh_source_export_private (SEAHORSE_SSH_SOURCE (place),
+ self->key, &n_results, error);
+ } else {
+ if (keydata->pubfile) {
+ g_assert (keydata->rawdata);
+ results = g_strdup_printf ("%s\n", keydata->rawdata);
+ n_results = strlen (results);
+ } else {
+ g_set_error (error, SEAHORSE_ERROR, 0, "%s",
+ _("No public key file is available for this key."));
+ }
+ }
+
+ *size = n_results;
+ return results;
+}
+
+static void
+seahorse_ssh_exporter_iface_init (SeahorseExporterIface *iface)
+{
+ iface->add_object = seahorse_ssh_exporter_add_object;
+ iface->export_async = seahorse_ssh_exporter_export_async;
+ iface->export_finish = seahorse_ssh_exporter_export_finish;
+ iface->get_objects = seahorse_ssh_exporter_get_objects;
+}
+
+SeahorseExporter *
+seahorse_ssh_exporter_new (GObject *object,
+ gboolean secret)
+{
+ SeahorseExporter *exporter;
+
+ exporter = g_object_new (SEAHORSE_TYPE_SSH_EXPORTER,
+ "secret", secret,
+ NULL);
+
+ if (!seahorse_exporter_add_object (exporter, object))
+ g_assert_not_reached ();
+
+ return exporter;
+}
diff --git a/ssh/seahorse-ssh-exporter.h b/ssh/seahorse-ssh-exporter.h
new file mode 100644
index 0000000..d8516b5
--- /dev/null
+++ b/ssh/seahorse-ssh-exporter.h
@@ -0,0 +1,42 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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 __SEAHORSE_SSH_EXPORTER_H__
+#define __SEAHORSE_SSH_EXPORTER_H__
+
+#include <glib-object.h>
+
+#include "seahorse-exporter.h"
+
+#define SEAHORSE_TYPE_SSH_EXPORTER (seahorse_ssh_exporter_get_type ())
+#define SEAHORSE_SSH_EXPORTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_SSH_EXPORTER, SeahorseSshExporter))
+#define SEAHORSE_IS_SSH_EXPORTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_SSH_EXPORTER))
+
+typedef struct _SeahorseSshExporter SeahorseSshExporter;
+
+GType seahorse_ssh_exporter_get_type (void) G_GNUC_CONST;
+
+SeahorseExporter * seahorse_ssh_exporter_new (GObject *object,
+ gboolean secret);
+
+#endif /* __SEAHORSE_SSH_EXPORTER_H__ */
diff --git a/ssh/seahorse-ssh-key-properties.c b/ssh/seahorse-ssh-key-properties.c
index 902702b..376282e 100644
--- a/ssh/seahorse-ssh-key-properties.c
+++ b/ssh/seahorse-ssh-key-properties.c
@@ -21,17 +21,20 @@
*/
#include "config.h"
+#include "seahorse-ssh-dialogs.h"
+#include "seahorse-ssh-exporter.h"
+#include "seahorse-ssh-key.h"
+#include "seahorse-ssh-operation.h"
+
#include "seahorse-bind.h"
+#include "seahorse-exporter.h"
+#include "seahorse-exportable.h"
#include "seahorse-icons.h"
#include "seahorse-object.h"
#include "seahorse-object-widget.h"
#include "seahorse-util.h"
#include "seahorse-validity.h"
-#include "ssh/seahorse-ssh-dialogs.h"
-#include "ssh/seahorse-ssh-key.h"
-#include "ssh/seahorse-ssh-operation.h"
-
#include <glib/gi18n.h>
#define NOTEBOOK "notebook"
@@ -188,65 +191,41 @@ on_ssh_passphrase_button_clicked (GtkWidget *widget,
}
static void
-export_complete (GFile *file, GAsyncResult *result, guchar *contents)
+on_export_complete (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
- GError *err = NULL;
- gchar *uri, *unesc_uri;
-
- g_free (contents);
-
- if (!g_file_replace_contents_finish (file, result, NULL, &err)) {
- uri = g_file_get_uri (file);
- unesc_uri = g_uri_unescape_string (seahorse_util_uri_get_last (uri), NULL);
- seahorse_util_handle_error (&err, NULL, _("Couldn't export key to \"%s\""),
- unesc_uri);
- g_free (uri);
- g_free (unesc_uri);
- }
+ GtkWindow *parent = GTK_WINDOW (user_data);
+ GError *error = NULL;
+
+ if (!seahorse_exporter_export_to_file_finish (SEAHORSE_EXPORTER (source), result, &error))
+ seahorse_util_handle_error (&error, parent, _("Couldn't export key"));
+
+ g_object_unref (parent);
}
G_MODULE_EXPORT void
on_ssh_export_button_clicked (GtkWidget *widget, SeahorseWidget *swidget)
{
- SeahorsePlace *sksrc;
+ SeahorseExporter *exporter;
+ GList *exporters = NULL;
GObject *object;
+ GtkWindow *window;
GFile *file;
- GtkDialog *dialog;
- guchar *results;
- gsize n_results;
- gchar* uri = NULL;
- GError *err = NULL;
object = SEAHORSE_OBJECT_WIDGET (swidget)->object;
- g_return_if_fail (SEAHORSE_IS_SSH_KEY (object));
- g_object_get (object, "place", &sksrc, NULL);
- g_return_if_fail (SEAHORSE_IS_SSH_SOURCE (sksrc));
- dialog = seahorse_util_chooser_save_new (_("Export Complete Key"),
- GTK_WINDOW (seahorse_widget_get_toplevel (swidget)));
- seahorse_util_chooser_show_key_files (dialog);
- seahorse_util_chooser_set_filename (dialog, object);
+ exporters = g_list_append (exporters, seahorse_ssh_exporter_new (object, TRUE));
- uri = seahorse_util_chooser_save_prompt (dialog);
- if (!uri)
- return;
-
- results = seahorse_ssh_source_export_private (SEAHORSE_SSH_SOURCE (sksrc),
- SEAHORSE_SSH_KEY (object),
- &n_results, &err);
-
- if (results) {
- g_return_if_fail (err == NULL);
- file = g_file_new_for_uri (uri);
- g_file_replace_contents_async (file, (gchar*)results, n_results, NULL, FALSE,
- G_FILE_CREATE_PRIVATE, NULL,
- (GAsyncReadyCallback)export_complete, results);
+ window = GTK_WINDOW (seahorse_widget_get_toplevel (swidget));
+ if (seahorse_exportable_prompt (exporters, window, NULL, &file, &exporter)) {
+ seahorse_exporter_export_to_file_async (exporter, file, TRUE, NULL,
+ on_export_complete, g_object_ref (window));
+ g_object_unref (file);
+ g_object_unref (exporter);
}
-
- if (err)
- seahorse_util_handle_error (&err, swidget, _("Couldn't export key."));
- g_free (uri);
+ g_list_free_full (exporters, g_object_unref);
}
static void
diff --git a/ssh/seahorse-ssh-key.c b/ssh/seahorse-ssh-key.c
index 0078dff..27913d0 100644
--- a/ssh/seahorse-ssh-key.c
+++ b/ssh/seahorse-ssh-key.c
@@ -23,10 +23,16 @@
#include "config.h"
#include "seahorse-ssh-actions.h"
+#include "seahorse-ssh-exporter.h"
#include "seahorse-ssh-key.h"
#include "seahorse-ssh-operation.h"
#include "seahorse-ssh-source.h"
+#include "seahorse-exportable.h"
+#include "seahorse-icons.h"
+#include "seahorse-place.h"
+#include "seahorse-validity.h"
+
#include <gcr/gcr.h>
#include <glib.h>
@@ -36,11 +42,6 @@
#include <errno.h>
#include <string.h>
-
-#include "seahorse-place.h"
-#include "seahorse-icons.h"
-#include "seahorse-validity.h"
-
enum {
PROP_0,
PROP_KEY_DATA,
@@ -52,7 +53,11 @@ enum {
PROP_LENGTH
};
-G_DEFINE_TYPE (SeahorseSSHKey, seahorse_ssh_key, SEAHORSE_TYPE_OBJECT);
+static void seahorse_ssh_key_exportable_iface (SeahorseExportableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (SeahorseSSHKey, seahorse_ssh_key, SEAHORSE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_EXPORTABLE, seahorse_ssh_key_exportable_iface);
+);
/* -----------------------------------------------------------------------------
* INTERNAL
@@ -295,6 +300,19 @@ seahorse_ssh_key_class_init (SeahorseSSHKeyClass *klass)
0, G_MAXUINT, 0, G_PARAM_READABLE));
}
+static GList *
+seahorse_ssh_key_create_exporters (SeahorseExportable *exportable,
+ SeahorseExporterType type)
+{
+ return g_list_append (NULL, seahorse_ssh_exporter_new (G_OBJECT (exportable), FALSE));
+}
+
+static void
+seahorse_ssh_key_exportable_iface (SeahorseExportableIface *iface)
+{
+ iface->create_exporters = seahorse_ssh_key_create_exporters;
+}
+
/* -----------------------------------------------------------------------------
* PUBLIC METHODS
*/
@@ -311,6 +329,13 @@ seahorse_ssh_key_new (SeahorsePlace *place,
return skey;
}
+SeahorseSSHKeyData *
+seahorse_ssh_key_get_data (SeahorseSSHKey *self)
+{
+ g_return_val_if_fail (SEAHORSE_IS_SSH_KEY (self), NULL);
+ return self->keydata;
+}
+
guint
seahorse_ssh_key_get_algo (SeahorseSSHKey *skey)
{
diff --git a/ssh/seahorse-ssh-key.h b/ssh/seahorse-ssh-key.h
index 46b6563..8cd9319 100644
--- a/ssh/seahorse-ssh-key.h
+++ b/ssh/seahorse-ssh-key.h
@@ -63,6 +63,8 @@ struct _SeahorseSSHKeyClass {
SeahorseSSHKey* seahorse_ssh_key_new (SeahorsePlace *sksrc,
SeahorseSSHKeyData *data);
+SeahorseSSHKeyData * seahorse_ssh_key_get_data (SeahorseSSHKey *self);
+
void seahorse_ssh_key_refresh (SeahorseSSHKey *self);
GType seahorse_ssh_key_get_type (void);
diff --git a/ssh/seahorse-ssh-operation.c b/ssh/seahorse-ssh-operation.c
index 25f762c..c320d7b 100644
--- a/ssh/seahorse-ssh-operation.c
+++ b/ssh/seahorse-ssh-operation.c
@@ -22,6 +22,13 @@
#include "config.h"
+#include "seahorse-ssh-operation.h"
+
+#define DEBUG_FLAG SEAHORSE_DEBUG_OPERATION
+#include "seahorse-debug.h"
+#include "seahorse-exporter.h"
+#include "seahorse-util.h"
+
#include <sys/wait.h>
#include <signal.h>
#include <sys/socket.h>
@@ -33,12 +40,6 @@
#include <glib/gi18n.h>
#include <glib/gstdio.h>
-#include "seahorse-ssh-operation.h"
-#include "seahorse-util.h"
-
-#define DEBUG_FLAG SEAHORSE_DEBUG_OPERATION
-#include "seahorse-debug.h"
-
#define COMMAND_PASSWORD "PASSWORD "
#define COMMAND_PASSWORD_LEN 9
@@ -473,26 +474,6 @@ seahorse_ssh_operation_finish (SeahorseSSHSource *source,
* UPLOAD KEY
*/
-typedef struct {
- GMemoryOutputStream *output;
- GCancellable *cancellable;
- gchar *username;
- gchar *hostname;
- gchar *port;
-} ssh_upload_closure;
-
-static void
-ssh_upload_free (gpointer data)
-{
- ssh_upload_closure *closure = data;
- g_object_unref (closure->output);
- g_clear_object (&closure->cancellable);
- g_free (closure->username);
- g_free (closure->hostname);
- g_free (closure->port);
- g_free (closure);
-}
-
static void
on_upload_send_complete (GObject *source,
GAsyncResult *result,
@@ -508,49 +489,6 @@ on_upload_send_complete (GObject *source,
g_object_unref (res);
}
-static void
-on_upload_export_complete (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- ssh_upload_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
- SeahorseSshPromptInfo prompt = { _("Remote Host Password"), NULL, NULL, NULL };
- GError *error = NULL;
- gchar *data;
- size_t length;
- gchar *cmd;
-
- if (!seahorse_place_export_finish (SEAHORSE_PLACE (source), result, &error)) {
- g_simple_async_result_take_error (res, error);
- g_simple_async_result_complete (res);
- g_object_unref (res);
- return;
- }
-
- /*
- * This command creates the .ssh directory if necessary (with appropriate permissions)
- * and then appends all input data onto the end of .ssh/authorized_keys
- */
- /* TODO: Important, we should handle the host checking properly */
- cmd = g_strdup_printf (SSH_PATH " '%s %s' %s %s -o StrictHostKeyChecking=no "
- "\"umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys\"",
- closure->username, closure->hostname,
- closure->port ? "-p" : "", closure->port ? closure->port : "");
-
- if (g_output_stream_write_all (G_OUTPUT_STREAM (closure->output), "\n", 1, NULL, NULL, NULL) != 1)
- g_return_if_reached ();
- data = g_memory_output_stream_get_data (closure->output);
- length = g_memory_output_stream_get_data_size (closure->output);
-
- seahorse_ssh_operation_async (SEAHORSE_SSH_SOURCE (source), cmd, data, length,
- closure->cancellable, on_upload_send_complete,
- &prompt, g_object_ref (res));
-
- g_free (cmd);
- g_object_unref (res);
-}
-
void
seahorse_ssh_op_upload_async (SeahorseSSHSource *source,
GList *keys,
@@ -561,8 +499,12 @@ seahorse_ssh_op_upload_async (SeahorseSSHSource *source,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ SeahorseSshPromptInfo prompt = { _("Remote Host Password"), NULL, NULL, NULL };
+ SeahorseSSHKeyData *keydata;
GSimpleAsyncResult *res;
- ssh_upload_closure *closure;
+ GString *data;
+ GList *l;
+ gchar *cmd;
g_return_if_fail (keys != NULL);
g_return_if_fail (username && username[0]);
@@ -573,18 +515,30 @@ seahorse_ssh_op_upload_async (SeahorseSSHSource *source,
res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
seahorse_ssh_op_upload_async);
- closure = g_new0 (ssh_upload_closure, 1);
- closure->output = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0, g_realloc, NULL));
- closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
- closure->username = g_strdup (username);
- closure->hostname = g_strdup (hostname);
- closure->port = g_strdup (port);
- g_simple_async_result_set_op_res_gpointer (res, closure, ssh_upload_free);
- /* Buffer for what we send to the server */
- seahorse_place_export_async (SEAHORSE_PLACE (source), keys, G_OUTPUT_STREAM (closure->output),
- cancellable, on_upload_export_complete, g_object_ref (res));
+ data = g_string_sized_new (1024);
+ for (l = keys; l != NULL; l = g_list_next (l)) {
+ keydata = seahorse_ssh_key_get_data (l->data);
+ if (keydata && keydata->pubfile) {
+ g_string_append (data, keydata->rawdata);
+ g_string_append_c (data, '\n');
+ }
+ }
+
+ /*
+ * This command creates the .ssh directory if necessary (with appropriate permissions)
+ * and then appends all input data onto the end of .ssh/authorized_keys
+ */
+ /* TODO: Important, we should handle the host checking properly */
+ cmd = g_strdup_printf (SSH_PATH " '%s %s' %s %s -o StrictHostKeyChecking=no "
+ "\"umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys\"",
+ username, hostname, port ? "-p" : "", port ? port : "");
+
+ seahorse_ssh_operation_async (SEAHORSE_SSH_SOURCE (source), cmd, data->str, data->len,
+ cancellable, on_upload_send_complete,
+ &prompt, g_object_ref (res));
+ g_string_free (data, TRUE);
g_object_unref (res);
}
diff --git a/ssh/seahorse-ssh-source.c b/ssh/seahorse-ssh-source.c
index 514e852..a30e84e 100644
--- a/ssh/seahorse-ssh-source.c
+++ b/ssh/seahorse-ssh-source.c
@@ -824,93 +824,11 @@ seahorse_ssh_source_import_finish (SeahorsePlace *place,
return NULL;
}
-static void
-seahorse_ssh_source_export_async (SeahorsePlace *place,
- GList *keys,
- GOutputStream *output,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *res;
- SeahorseSSHKeyData *keydata;
- gchar *results = NULL;
- gchar *raw = NULL;
- GError *error = NULL;
- SeahorseObject *object;
- GList *l;
- gsize written;
-
- res = g_simple_async_result_new (G_OBJECT (place), callback, user_data,
- seahorse_ssh_source_export_async);
-
- for (l = keys; l; l = g_list_next (l)) {
- object = SEAHORSE_OBJECT (l->data);
- g_assert (SEAHORSE_IS_SSH_KEY (object));
-
- results = NULL;
- raw = NULL;
-
- keydata = NULL;
- g_object_get (object, "key-data", &keydata, NULL);
- g_assert (keydata);
-
- /* We should already have the data loaded */
- if (keydata->pubfile) {
- g_assert (keydata->rawdata);
- results = g_strdup_printf ("%s", keydata->rawdata);
-
- } else if (!keydata->pubfile) {
-
- /*
- * TODO: We should be able to get at this data by using ssh-keygen
- * to make a public key from the private
- */
- g_warning ("private key without public, not exporting: %s", keydata->privfile);
- }
-
- /* Write the data out */
- if (results) {
- if (g_output_stream_write_all (output, results, strlen (results),
- &written, NULL, &error))
- g_output_stream_flush (output, NULL, &error);
- g_free (results);
- }
-
- g_free (raw);
-
- if (error != NULL) {
- g_simple_async_result_take_error (res, error);
- break;
- }
- }
-
- g_simple_async_result_set_op_res_gpointer (res, g_object_ref (output), g_object_unref);
- g_simple_async_result_complete_in_idle (res);
- g_object_unref (res);
-}
-
-static GOutputStream *
-seahorse_ssh_source_export_finish (SeahorsePlace *place,
- GAsyncResult *result,
- GError **error)
-{
- g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (place),
- seahorse_ssh_source_export_async), NULL);
-
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
- return NULL;
-
- return g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
-}
-
static void
seahorse_ssh_source_place_iface (SeahorsePlaceIface *iface)
{
iface->import_async = seahorse_ssh_source_import_async;
iface->import_finish = seahorse_ssh_source_import_finish;
- iface->export_async = seahorse_ssh_source_export_async;
- iface->export_finish = seahorse_ssh_source_export_finish;
}
/* -----------------------------------------------------------------------------
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]