|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* Copyright (C) 2011 Collabora Ltd.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
b00eeb |
* it under the terms of the GNU Lesser General Public License as
|
|
Packit |
b00eeb |
* published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
b00eeb |
* the License, or (at your option) any later version.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
b00eeb |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b00eeb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
b00eeb |
* Lesser General Public License for more details.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
b00eeb |
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Author: Stef Walter <stefw@collabora.co.uk>
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "config.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "gcr/gcr-certificate.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "gcr-certificate-exporter.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "egg/egg-armor.h"
|
|
Packit |
b00eeb |
#include "egg/egg-openssl.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include <glib/gi18n-lib.h>
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
enum {
|
|
Packit |
b00eeb |
PROP_0,
|
|
Packit |
b00eeb |
PROP_CERTIFICATE,
|
|
Packit |
b00eeb |
PROP_LABEL,
|
|
Packit |
b00eeb |
PROP_TRANSIENT_FOR
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
struct _GcrCertificateExporterPrivate {
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Setup stuff */
|
|
Packit |
b00eeb |
GcrCertificate *certificate;
|
|
Packit |
b00eeb |
gchar *label;
|
|
Packit |
b00eeb |
GtkWindow *transient_for;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Used during operation */
|
|
Packit |
b00eeb |
GtkFileChooser *chooser_dialog;
|
|
Packit |
b00eeb |
GFile *output_file;
|
|
Packit |
b00eeb |
GByteArray *buffer;
|
|
Packit |
b00eeb |
guint buffer_at;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Async stuff */
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback;
|
|
Packit |
b00eeb |
gpointer user_data;
|
|
Packit |
b00eeb |
GCancellable *cancellable;
|
|
Packit |
b00eeb |
GError *error;
|
|
Packit |
b00eeb |
gboolean completed;
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static const gchar *BAD_FILENAME_CHARS = "/\\<>|?*";
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Forward declarations */
|
|
Packit |
b00eeb |
static void _gcr_certificate_exporter_async_result_init (GAsyncResultIface *iface);
|
|
Packit |
b00eeb |
static void write_to_outputstream (GcrCertificateExporter *self, GOutputStream *os);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_DEFINE_TYPE_WITH_CODE (GcrCertificateExporter, _gcr_certificate_exporter, G_TYPE_OBJECT,
|
|
Packit |
b00eeb |
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, _gcr_certificate_exporter_async_result_init));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
typedef void (*PrepareDataFunc) (GcrCertificateExporter *self);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* -----------------------------------------------------------------------------
|
|
Packit |
b00eeb |
* INTERNAL
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
prepare_data_for_der (GcrCertificateExporter *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
gconstpointer data;
|
|
Packit |
b00eeb |
gsize n_data;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
data = gcr_certificate_get_der_data (self->pv->certificate, &n_data);
|
|
Packit |
b00eeb |
g_return_if_fail (data);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->pv->buffer = g_byte_array_new ();
|
|
Packit |
b00eeb |
g_byte_array_append (self->pv->buffer, data, n_data);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
prepare_data_for_pem (GcrCertificateExporter *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
gconstpointer data;
|
|
Packit |
b00eeb |
gpointer encoded;
|
|
Packit |
b00eeb |
gsize n_data, n_encoded;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
data = gcr_certificate_get_der_data (self->pv->certificate, &n_data);
|
|
Packit |
b00eeb |
g_return_if_fail (data);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->pv->buffer = g_byte_array_new ();
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
encoded = egg_armor_write (data, n_data,
|
|
Packit |
b00eeb |
g_quark_from_static_string ("CERTIFICATE"),
|
|
Packit |
b00eeb |
NULL, &n_encoded);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_byte_array_append (self->pv->buffer, encoded, n_encoded);
|
|
Packit |
b00eeb |
g_free (encoded);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
complete_async_result (GcrCertificateExporter *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_assert (self->pv->callback);
|
|
Packit |
b00eeb |
g_assert (!self->pv->completed);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->chooser_dialog)
|
|
Packit |
b00eeb |
gtk_widget_hide (GTK_WIDGET (self->pv->chooser_dialog));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->pv->completed = TRUE;
|
|
Packit |
b00eeb |
(self->pv->callback) (G_OBJECT (self), G_ASYNC_RESULT (self),
|
|
Packit |
b00eeb |
self->pv->user_data);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_outputstream_write_ready (GObject *source, GAsyncResult *res, gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateExporter *self = GCR_CERTIFICATE_EXPORTER (user_data);
|
|
Packit |
b00eeb |
GOutputStream *os = G_OUTPUT_STREAM (source);
|
|
Packit |
b00eeb |
gssize written;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
written = g_output_stream_write_finish (os, res, &self->pv->error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->error) {
|
|
Packit |
b00eeb |
complete_async_result (self);
|
|
Packit |
b00eeb |
return;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_if_fail (written >= 0);
|
|
Packit |
b00eeb |
g_return_if_fail (written <= self->pv->buffer->len - self->pv->buffer_at);
|
|
Packit |
b00eeb |
self->pv->buffer_at += written;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Write next bit, or finished */
|
|
Packit |
b00eeb |
write_to_outputstream (self, os);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_outputstream_closed (GObject *source, GAsyncResult *res, gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateExporter *self = GCR_CERTIFICATE_EXPORTER (user_data);
|
|
Packit |
b00eeb |
g_output_stream_close_finish (G_OUTPUT_STREAM (source), res, &self->pv->error);
|
|
Packit |
b00eeb |
complete_async_result (self);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
write_to_outputstream (GcrCertificateExporter *self, GOutputStream *os)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
gtk_widget_hide (GTK_WIDGET (self->pv->chooser_dialog));
|
|
Packit |
b00eeb |
g_assert (GTK_IS_WIDGET (self->pv->chooser_dialog));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Are we all done? */
|
|
Packit |
b00eeb |
g_assert (self->pv->buffer_at <= self->pv->buffer->len);
|
|
Packit |
b00eeb |
if (self->pv->buffer_at == self->pv->buffer->len) {
|
|
Packit |
b00eeb |
g_output_stream_close_async (os, G_PRIORITY_DEFAULT,
|
|
Packit |
b00eeb |
self->pv->cancellable,
|
|
Packit |
b00eeb |
on_outputstream_closed, self);
|
|
Packit |
b00eeb |
return;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_output_stream_write_async (os, self->pv->buffer->data + self->pv->buffer_at,
|
|
Packit |
b00eeb |
self->pv->buffer->len - self->pv->buffer_at,
|
|
Packit |
b00eeb |
G_PRIORITY_DEFAULT, self->pv->cancellable,
|
|
Packit |
b00eeb |
on_outputstream_write_ready, self);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_replace_file_ready (GObject *source, GAsyncResult *res, gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateExporter *self = GCR_CERTIFICATE_EXPORTER (user_data);
|
|
Packit |
b00eeb |
GFile *file = G_FILE (source);
|
|
Packit |
b00eeb |
GFileOutputStream *os;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
os = g_file_replace_finish (file, res, &self->pv->error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->error) {
|
|
Packit |
b00eeb |
complete_async_result (self);
|
|
Packit |
b00eeb |
return;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
write_to_outputstream (self, G_OUTPUT_STREAM (os));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_replace_dialog_response (GtkDialog *dialog, gint response_id, gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateExporter *self = GCR_CERTIFICATE_EXPORTER (user_data);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (response_id == GTK_RESPONSE_ACCEPT) {
|
|
Packit |
b00eeb |
g_file_replace_async (self->pv->output_file, NULL, FALSE, G_FILE_CREATE_NONE,
|
|
Packit |
b00eeb |
G_PRIORITY_DEFAULT, self->pv->cancellable,
|
|
Packit |
b00eeb |
on_replace_file_ready, self);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gtk_widget_destroy (GTK_WIDGET (dialog));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_cancel_replace_dialog (GCancellable *cancellable, gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
gtk_widget_destroy (user_data);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_create_file_ready (GObject *source, GAsyncResult *res, gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateExporter *self = GCR_CERTIFICATE_EXPORTER (user_data);
|
|
Packit |
b00eeb |
GFileOutputStream *os;
|
|
Packit |
b00eeb |
GtkWidget *dialog;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
os = g_file_create_finish (self->pv->output_file, res, &self->pv->error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Try again this time replacing the file */
|
|
Packit |
b00eeb |
if (g_error_matches (self->pv->error, G_IO_ERROR, G_IO_ERROR_EXISTS)) {
|
|
Packit |
b00eeb |
g_clear_error (&self->pv->error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (self->pv->chooser_dialog),
|
|
Packit |
b00eeb |
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
|
|
Packit |
b00eeb |
GTK_BUTTONS_NONE, "%s\n\n%s",
|
|
Packit |
b00eeb |
_("A file already exists with this name."),
|
|
Packit |
b00eeb |
_("Do you want to replace it with a new file?"));
|
|
Packit |
b00eeb |
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
|
|
Packit |
b00eeb |
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
Packit |
b00eeb |
_("_Replace"), GTK_RESPONSE_ACCEPT, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_signal_connect (dialog, "response",
|
|
Packit |
b00eeb |
G_CALLBACK (on_replace_dialog_response), self);
|
|
Packit |
b00eeb |
if (self->pv->cancellable)
|
|
Packit |
b00eeb |
g_cancellable_connect (self->pv->cancellable,
|
|
Packit |
b00eeb |
G_CALLBACK (on_cancel_replace_dialog),
|
|
Packit |
b00eeb |
g_object_ref (dialog), g_object_unref);
|
|
Packit |
b00eeb |
gtk_widget_show (dialog);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->error) {
|
|
Packit |
b00eeb |
complete_async_result (self);
|
|
Packit |
b00eeb |
return;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
write_to_outputstream (self, G_OUTPUT_STREAM (os));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_chooser_dialog_response (GtkDialog *dialog, gint response_id, gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateExporter *self = GCR_CERTIFICATE_EXPORTER (user_data);
|
|
Packit |
b00eeb |
GtkFileFilter *filter;
|
|
Packit |
b00eeb |
PrepareDataFunc prepare_data;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (response_id != GTK_RESPONSE_ACCEPT) {
|
|
Packit |
b00eeb |
g_set_error (&self->pv->error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
|
|
Packit |
b00eeb |
_("The operation was cancelled."));
|
|
Packit |
b00eeb |
complete_async_result (self);
|
|
Packit |
b00eeb |
return;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->output_file)
|
|
Packit |
b00eeb |
g_object_unref (self->pv->output_file);
|
|
Packit |
b00eeb |
self->pv->output_file = gtk_file_chooser_get_file (self->pv->chooser_dialog);
|
|
Packit |
b00eeb |
g_return_if_fail (self->pv->output_file);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
filter = gtk_file_chooser_get_filter (self->pv->chooser_dialog);
|
|
Packit |
b00eeb |
prepare_data = g_object_get_data (G_OBJECT (filter), "prepare-data-func");
|
|
Packit |
b00eeb |
g_assert (prepare_data);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->buffer)
|
|
Packit |
b00eeb |
g_byte_array_free (self->pv->buffer, TRUE);
|
|
Packit |
b00eeb |
self->pv->buffer = NULL;
|
|
Packit |
b00eeb |
self->pv->buffer_at = 0;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Prepare the for writing out */
|
|
Packit |
b00eeb |
(prepare_data) (self);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Try to open the file */
|
|
Packit |
b00eeb |
g_file_create_async (self->pv->output_file, G_FILE_CREATE_NONE, G_PRIORITY_DEFAULT,
|
|
Packit |
b00eeb |
self->pv->cancellable, on_create_file_ready,
|
|
Packit |
b00eeb |
self);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_cancel_chooser_dialog (GCancellable *cancellable, gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GtkDialog *dialog = GTK_DIALOG (user_data);
|
|
Packit |
b00eeb |
gtk_dialog_response (dialog, GTK_RESPONSE_CANCEL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
exporter_display_chooser (GcrCertificateExporter *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GtkFileFilter* filter;
|
|
Packit |
b00eeb |
GtkWidget *dialog;
|
|
Packit |
b00eeb |
gchar *filename;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (!self->pv->chooser_dialog);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
dialog = gtk_file_chooser_dialog_new (_("Export certificate"),
|
|
Packit |
b00eeb |
NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
Packit |
b00eeb |
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
Packit |
b00eeb |
_("_Save"), GTK_RESPONSE_ACCEPT,
|
|
Packit |
b00eeb |
NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->pv->chooser_dialog = g_object_ref_sink(dialog);
|
|
Packit |
b00eeb |
gtk_dialog_set_default_response (GTK_DIALOG (dialog),
|
|
Packit |
b00eeb |
GTK_RESPONSE_ACCEPT);
|
|
Packit |
b00eeb |
gtk_file_chooser_set_local_only (self->pv->chooser_dialog, FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
filter = gtk_file_filter_new ();
|
|
Packit |
b00eeb |
gtk_file_filter_set_name (filter, _("Certificate files"));
|
|
Packit |
b00eeb |
gtk_file_filter_add_mime_type (filter, "application/x-x509-ca-cert");
|
|
Packit |
b00eeb |
gtk_file_filter_add_mime_type (filter, "application/x-x509-user-cert");
|
|
Packit |
b00eeb |
gtk_file_filter_add_mime_type (filter, "application/pkix-cert");
|
|
Packit |
b00eeb |
gtk_file_filter_add_pattern (filter, "*.cer");
|
|
Packit |
b00eeb |
gtk_file_filter_add_pattern (filter, "*.crt");
|
|
Packit |
b00eeb |
g_object_set_data (G_OBJECT (filter), "prepare-data-func", prepare_data_for_der);
|
|
Packit |
b00eeb |
gtk_file_chooser_add_filter (self->pv->chooser_dialog, filter);
|
|
Packit |
b00eeb |
gtk_file_chooser_set_filter (self->pv->chooser_dialog, filter);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
filter = gtk_file_filter_new ();
|
|
Packit |
b00eeb |
gtk_file_filter_set_name (filter, _("PEM files"));
|
|
Packit |
b00eeb |
gtk_file_filter_add_mime_type (filter, "text/plain");
|
|
Packit |
b00eeb |
gtk_file_filter_add_pattern (filter, "*.pem");
|
|
Packit |
b00eeb |
g_object_set_data (G_OBJECT (filter), "prepare-data-func", prepare_data_for_pem);
|
|
Packit |
b00eeb |
gtk_file_chooser_add_filter (self->pv->chooser_dialog, filter);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
filename = g_strconcat (self->pv->label, ".crt", NULL);
|
|
Packit |
b00eeb |
g_strdelimit (filename, BAD_FILENAME_CHARS, '_');
|
|
Packit |
b00eeb |
gtk_file_chooser_set_current_name (self->pv->chooser_dialog, filename);
|
|
Packit |
b00eeb |
g_free (filename);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_signal_connect (self->pv->chooser_dialog, "response",
|
|
Packit |
b00eeb |
G_CALLBACK (on_chooser_dialog_response), self);
|
|
Packit |
b00eeb |
if (self->pv->cancellable)
|
|
Packit |
b00eeb |
g_cancellable_connect (self->pv->cancellable,
|
|
Packit |
b00eeb |
G_CALLBACK (on_cancel_chooser_dialog), self, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gtk_dialog_run (GTK_DIALOG (self->pv->chooser_dialog));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* -----------------------------------------------------------------------------
|
|
Packit |
b00eeb |
* OBJECT
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_init (GcrCertificateExporter *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_CERTIFICATE_EXPORTER,
|
|
Packit |
b00eeb |
GcrCertificateExporterPrivate));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_dispose (GObject *obj)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateExporter *self = GCR_CERTIFICATE_EXPORTER (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->certificate)
|
|
Packit |
b00eeb |
g_object_unref (self->pv->certificate);
|
|
Packit |
b00eeb |
self->pv->certificate = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->cancellable)
|
|
Packit |
b00eeb |
g_object_unref (self->pv->cancellable);
|
|
Packit |
b00eeb |
self->pv->cancellable = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_OBJECT_CLASS (_gcr_certificate_exporter_parent_class)->dispose (obj);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_finalize (GObject *obj)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateExporter *self = GCR_CERTIFICATE_EXPORTER (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_free (self->pv->label);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* Should have been freed in _export_finish, which holds a ref to self
|
|
Packit |
b00eeb |
* so this should never be reached without being finished.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
g_assert (!self->pv->chooser_dialog);
|
|
Packit |
b00eeb |
g_assert (!self->pv->output_file);
|
|
Packit |
b00eeb |
g_assert (!self->pv->buffer);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_clear_error (&self->pv->error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_OBJECT_CLASS (_gcr_certificate_exporter_parent_class)->finalize (obj);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_set_property (GObject *obj, guint prop_id, const GValue *value,
|
|
Packit |
b00eeb |
GParamSpec *pspec)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateExporter *self = GCR_CERTIFICATE_EXPORTER (obj);
|
|
Packit |
b00eeb |
GcrCertificate *cert;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
switch (prop_id) {
|
|
Packit |
b00eeb |
case PROP_CERTIFICATE:
|
|
Packit |
b00eeb |
cert = g_value_dup_object (value);
|
|
Packit |
b00eeb |
if (self->pv->certificate)
|
|
Packit |
b00eeb |
g_object_unref (self->pv->certificate);
|
|
Packit |
b00eeb |
self->pv->certificate = cert;
|
|
Packit |
b00eeb |
g_object_notify (G_OBJECT (self), "certificate");
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_LABEL:
|
|
Packit |
b00eeb |
g_free (self->pv->label);
|
|
Packit |
b00eeb |
self->pv->label = g_value_dup_string (value);
|
|
Packit |
b00eeb |
g_object_notify (obj, "label");
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_TRANSIENT_FOR:
|
|
Packit |
b00eeb |
self->pv->transient_for = g_value_get_object (value);
|
|
Packit |
b00eeb |
g_object_notify (obj, "transient-for");
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
default:
|
|
Packit |
b00eeb |
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_get_property (GObject *obj, guint prop_id, GValue *value,
|
|
Packit |
b00eeb |
GParamSpec *pspec)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateExporter *self = GCR_CERTIFICATE_EXPORTER (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
switch (prop_id) {
|
|
Packit |
b00eeb |
case PROP_CERTIFICATE:
|
|
Packit |
b00eeb |
g_value_set_object (value, self->pv->certificate);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_LABEL:
|
|
Packit |
b00eeb |
g_value_take_string (value, self->pv->label);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_TRANSIENT_FOR:
|
|
Packit |
b00eeb |
g_value_set_object (value, self->pv->transient_for);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
default:
|
|
Packit |
b00eeb |
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_class_init (GcrCertificateExporterClass *klass)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_parent_class = g_type_class_peek_parent (klass);
|
|
Packit |
b00eeb |
g_type_class_add_private (klass, sizeof (GcrCertificateExporterPrivate));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gobject_class->dispose = _gcr_certificate_exporter_dispose;
|
|
Packit |
b00eeb |
gobject_class->finalize = _gcr_certificate_exporter_finalize;
|
|
Packit |
b00eeb |
gobject_class->set_property = _gcr_certificate_exporter_set_property;
|
|
Packit |
b00eeb |
gobject_class->get_property = _gcr_certificate_exporter_get_property;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
|
|
Packit |
b00eeb |
g_param_spec_object ("certificate", "Certificate", "Certificate to display.",
|
|
Packit |
b00eeb |
GCR_TYPE_CERTIFICATE, G_PARAM_READWRITE));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_class_install_property (gobject_class, PROP_LABEL,
|
|
Packit |
b00eeb |
g_param_spec_string ("label", "Label", "Label of certificate.",
|
|
Packit |
b00eeb |
_("Certificate"), G_PARAM_READWRITE));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_class_install_property (gobject_class, PROP_TRANSIENT_FOR,
|
|
Packit |
b00eeb |
g_param_spec_object ("transient-for", "Transient For", "Transient for this Window",
|
|
Packit |
b00eeb |
GTK_TYPE_WINDOW, G_PARAM_READWRITE));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GObject*
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_get_source_object (GAsyncResult *result)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_CERTIFICATE_EXPORTER (result), NULL);
|
|
Packit |
b00eeb |
return G_OBJECT (result);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gpointer
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_get_user_data (GAsyncResult *result)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_CERTIFICATE_EXPORTER (result), NULL);
|
|
Packit |
b00eeb |
return GCR_CERTIFICATE_EXPORTER (result)->pv->user_data;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_async_result_init (GAsyncResultIface *iface)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
iface->get_source_object = _gcr_certificate_exporter_get_source_object;
|
|
Packit |
b00eeb |
iface->get_user_data = _gcr_certificate_exporter_get_user_data;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* -----------------------------------------------------------------------------
|
|
Packit |
b00eeb |
* PUBLIC
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
GcrCertificateExporter*
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_new (GcrCertificate *certificate, const gchar *label,
|
|
Packit |
b00eeb |
GtkWindow *transient_for)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
return g_object_new (GCR_TYPE_CERTIFICATE_EXPORTER,
|
|
Packit |
b00eeb |
"certificate", certificate,
|
|
Packit |
b00eeb |
"label", label,
|
|
Packit |
b00eeb |
"transient-for", transient_for,
|
|
Packit |
b00eeb |
NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_export_async (GcrCertificateExporter *self,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_if_fail (GCR_IS_CERTIFICATE_EXPORTER (self));
|
|
Packit |
b00eeb |
g_return_if_fail (callback);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Must not have already started */
|
|
Packit |
b00eeb |
g_return_if_fail (!self->pv->callback);
|
|
Packit |
b00eeb |
g_return_if_fail (!self->pv->cancellable);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->pv->callback = callback;
|
|
Packit |
b00eeb |
self->pv->user_data = user_data;
|
|
Packit |
b00eeb |
if (cancellable)
|
|
Packit |
b00eeb |
self->pv->cancellable = g_object_ref (cancellable);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Matching in export_finish */
|
|
Packit |
b00eeb |
g_object_ref (self);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
exporter_display_chooser (self);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gboolean
|
|
Packit |
b00eeb |
_gcr_certificate_exporter_export_finish (GcrCertificateExporter *self,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
gboolean ret = TRUE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (G_ASYNC_RESULT (self) == result, FALSE);
|
|
Packit |
b00eeb |
g_return_val_if_fail (!error || !*error, FALSE);
|
|
Packit |
b00eeb |
g_return_val_if_fail (self->pv->completed, FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Cleanup all the operation stuff */
|
|
Packit |
b00eeb |
self->pv->callback = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->chooser_dialog)
|
|
Packit |
b00eeb |
g_object_unref (self->pv->chooser_dialog);
|
|
Packit |
b00eeb |
self->pv->chooser_dialog = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->output_file)
|
|
Packit |
b00eeb |
g_object_unref (self->pv->output_file);
|
|
Packit |
b00eeb |
self->pv->output_file = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->buffer)
|
|
Packit |
b00eeb |
g_byte_array_free (self->pv->buffer, TRUE);
|
|
Packit |
b00eeb |
self->pv->buffer = NULL;
|
|
Packit |
b00eeb |
self->pv->buffer_at = 0;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->pv->completed = FALSE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->error) {
|
|
Packit |
b00eeb |
g_propagate_error (error, self->pv->error);
|
|
Packit |
b00eeb |
ret = FALSE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Matches in export_async */
|
|
Packit |
b00eeb |
g_object_unref (self);
|
|
Packit |
b00eeb |
return ret;
|
|
Packit |
b00eeb |
}
|