/*
* gnome-keyring
*
* Copyright (C) 2008 Stefan Walter
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see .
*/
#include "config.h"
#include "gcr/gcr-icons.h"
#include "gcr-dialog-util.h"
#include "gcr-secure-entry-buffer.h"
#include "gcr-pkcs11-import-dialog.h"
#include "egg/egg-secure-memory.h"
#include
#include
EGG_SECURE_DECLARE (import_dialog);
#define GCR_PKCS11_IMPORT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_PKCS11_IMPORT_DIALOG, GcrPkcs11ImportDialogClass))
#define GCR_IS_PKCS11_IMPORT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_PKCS11_IMPORT_DIALOG))
#define GCR_PKCS11_IMPORT_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_PKCS11_IMPORT_DIALOG, GcrPkcs11ImportDialogClass))
enum {
PROP_0,
PROP_IMPORTER
};
struct _GcrPkcs11ImportDialog {
GtkDialog parent;
GtkBuilder *builder;
GtkWidget *password_area;
GtkLabel *token_label;
GtkImage *token_image;
GtkEntry *password_entry;
GtkEntry *label_entry;
gboolean label_changed;
};
typedef struct _GcrPkcs11ImportDialogClass GcrPkcs11ImportDialogClass;
struct _GcrPkcs11ImportDialogClass {
GtkDialogClass parent;
};
G_DEFINE_TYPE (GcrPkcs11ImportDialog, _gcr_pkcs11_import_dialog, GTK_TYPE_DIALOG);
static void
on_label_changed (GtkEditable *editable,
gpointer user_data)
{
GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (user_data);
self->label_changed = TRUE;
}
static void
_gcr_pkcs11_import_dialog_constructed (GObject *obj)
{
GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
GError *error = NULL;
GtkEntryBuffer *buffer;
GtkWidget *widget;
GtkBox *contents;
GtkWidget *button;
G_OBJECT_CLASS (_gcr_pkcs11_import_dialog_parent_class)->constructed (obj);
if (!gtk_builder_add_from_resource (self->builder, "/org/gnome/gcr/ui/gcr-pkcs11-import-dialog.ui", &error)) {
g_warning ("couldn't load ui builder file: %s", error->message);
return;
}
/* Fill in the dialog from builder */
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "pkcs11-import-dialog"));
contents = GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self)));
gtk_box_pack_start (contents, widget, TRUE, TRUE, 0);
/* The password area */
self->password_area = GTK_WIDGET (gtk_builder_get_object (self->builder, "unlock-area"));
gtk_widget_hide (self->password_area);
/* Add a secure entry */
buffer = gcr_secure_entry_buffer_new ();
self->password_entry = GTK_ENTRY (gtk_builder_get_object (self->builder, "password-entry"));
gtk_entry_set_buffer (self->password_entry, buffer);
gtk_entry_set_activates_default (self->password_entry, TRUE);
g_object_unref (buffer);
self->token_label = GTK_LABEL (gtk_builder_get_object (self->builder, "token-description"));
self->token_image = GTK_IMAGE (gtk_builder_get_object (self->builder, "token-image"));
/* Setup the label */
self->label_entry = GTK_ENTRY (gtk_builder_get_object (self->builder, "label-entry"));
g_signal_connect (self->label_entry, "changed", G_CALLBACK (on_label_changed), self);
gtk_entry_set_activates_default (self->label_entry, TRUE);
/* Add our various buttons */
button = gtk_dialog_add_button (GTK_DIALOG (self), _("_Cancel"), GTK_RESPONSE_CANCEL);
gtk_button_set_use_underline (GTK_BUTTON (button), TRUE);
button = gtk_dialog_add_button (GTK_DIALOG (self), _("_OK"), GTK_RESPONSE_OK);
gtk_button_set_use_underline (GTK_BUTTON (button), TRUE);
gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
gtk_window_set_modal (GTK_WINDOW (self), TRUE);
}
static void
_gcr_pkcs11_import_dialog_init (GcrPkcs11ImportDialog *self)
{
self->builder = gtk_builder_new ();
}
static void
_gcr_pkcs11_import_dialog_finalize (GObject *obj)
{
GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
g_object_unref (self->builder);
G_OBJECT_CLASS (_gcr_pkcs11_import_dialog_parent_class)->finalize (obj);
}
static void
_gcr_pkcs11_import_dialog_class_init (GcrPkcs11ImportDialogClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructed = _gcr_pkcs11_import_dialog_constructed;
gobject_class->finalize = _gcr_pkcs11_import_dialog_finalize;
}
GcrPkcs11ImportDialog *
_gcr_pkcs11_import_dialog_new (GtkWindow *parent)
{
GcrPkcs11ImportDialog *dialog;
g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
dialog = g_object_new (GCR_TYPE_PKCS11_IMPORT_DIALOG,
"transient-for", parent,
NULL);
return g_object_ref_sink (dialog);
}
void
_gcr_pkcs11_import_dialog_get_supplements (GcrPkcs11ImportDialog *self,
GckBuilder *builder)
{
const gchar *label;
g_return_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self));
g_return_if_fail (builder != NULL);
label = gtk_entry_get_text (self->label_entry);
if (self->label_changed && label != NULL && label[0])
gck_builder_set_string (builder, CKA_LABEL, label);
}
void
_gcr_pkcs11_import_dialog_set_supplements (GcrPkcs11ImportDialog *self,
GckBuilder *builder)
{
gchar *label;
g_return_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self));
g_return_if_fail (builder != NULL);
if (!gck_builder_find_string (builder, CKA_LABEL, &label))
label = NULL;
if (label == NULL)
gtk_entry_set_placeholder_text (self->label_entry, _("Automatically chosen"));
gtk_entry_set_text (self->label_entry, label == NULL ? "" : label);
g_free (label);
self->label_changed = FALSE;
}
gboolean
_gcr_pkcs11_import_dialog_run (GcrPkcs11ImportDialog *self)
{
gboolean ret = FALSE;
g_return_val_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self), FALSE);
if (gtk_dialog_run (GTK_DIALOG (self)) == GTK_RESPONSE_OK) {
ret = TRUE;
}
gtk_widget_hide (GTK_WIDGET (self));
return ret;
}
void
_gcr_pkcs11_import_dialog_run_async (GcrPkcs11ImportDialog *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_return_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self));
_gcr_dialog_util_run_async (GTK_DIALOG (self), cancellable, callback, user_data);
}
gboolean
_gcr_pkcs11_import_dialog_run_finish (GcrPkcs11ImportDialog *self,
GAsyncResult *result)
{
gint response;
g_return_val_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self), FALSE);
response = _gcr_dialog_util_run_finish (GTK_DIALOG (self), result);
gtk_widget_hide (GTK_WIDGET (self));
return (response == GTK_RESPONSE_OK) ? TRUE : FALSE;
}
GTlsInteractionResult
_gcr_pkcs11_import_dialog_run_ask_password (GcrPkcs11ImportDialog *self,
GTlsPassword *password,
GCancellable *cancellable,
GError **error)
{
GckTokenInfo *token_info;
const gchar *value;
GckSlot *slot;
GIcon *icon;
gboolean ret;
g_return_val_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self), G_TLS_INTERACTION_UNHANDLED);
g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
g_return_val_if_fail (error == NULL || *error == NULL, G_TLS_INTERACTION_UNHANDLED);
if (GCK_IS_PASSWORD (password)) {
slot = gck_password_get_token (GCK_PASSWORD (password));
token_info = gck_slot_get_token_info (slot);
icon = gcr_icon_for_token (token_info);
gtk_image_set_from_gicon (self->token_image, icon, GTK_ICON_SIZE_BUTTON);
gck_token_info_free (token_info);
g_object_unref (icon);
}
gtk_label_set_text (self->token_label, g_tls_password_get_description (password));
gtk_widget_show (self->password_area);
ret = _gcr_pkcs11_import_dialog_run (self);
gtk_widget_hide (self->password_area);
if (!ret) {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
_("The user cancelled the operation"));
return G_TLS_INTERACTION_FAILED;
}
value = gtk_entry_get_text (self->password_entry);
g_tls_password_set_value_full (password, egg_secure_strdup (value),
-1, egg_secure_free);
return G_TLS_INTERACTION_HANDLED;
}