From dc3a49f93a0798b5c0c8d2fd6283f39294945045 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Mon, 1 Dec 2008 11:16:43 +0000 Subject: [PATCH] Removed 2008-12-01 Carlos Garcia Campos * configure.ac: * shell/Makefile.am: * shell/ev-keyring.[ch]: * shell/ev-password.[ch]: Removed * shell/ev-password-view.[ch]: (ev_password_view_finalize), (ev_password_view_class_init), (ev_password_view_clicked_cb), (ev_password_view_init), (ev_password_view_set_uri), (ev_password_dialog_got_response), (ev_password_dialog_remember_button_toggled), (ev_password_dialog_entry_changed_cb), (ev_password_dialog_entry_activated_cb), (ev_password_view_ask_password), (ev_password_view_get_password), (ev_password_view_get_password_save_flags), (ev_password_view_new): * shell/ev-window.c: (ev_window_password_view_unlock), (ev_window_load_job_cb), (ev_window_close_dialogs), (ev_window_init): Rework the password view. When the password is in the keyring it's used automatically without showing the password dialog and it's only stored in the keyring when we are sure it's correct. The password dialog has been reworked too, in order to make it more hig compliant and consistent with the GTK+ dialog used in gtkmountoperation. Fixes bug #562496. svn path=/trunk/; revision=3281 --- ChangeLog | 27 +++ configure.ac | 2 +- shell/Makefile.am | 4 +- shell/ev-keyring.c | 116 +++++++++++++ shell/ev-keyring.h | 37 +++++ shell/ev-password-view.c | 310 ++++++++++++++++++++++++++++++++-- shell/ev-password-view.h | 14 +- shell/ev-password.c | 350 --------------------------------------- shell/ev-password.h | 58 ------- shell/ev-window.c | 119 ++++++------- 10 files changed, 537 insertions(+), 500 deletions(-) create mode 100644 shell/ev-keyring.c create mode 100644 shell/ev-keyring.h delete mode 100644 shell/ev-password.c delete mode 100644 shell/ev-password.h diff --git a/ChangeLog b/ChangeLog index 5e38e604..413f1dcf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2008-12-01 Carlos Garcia Campos + + * configure.ac: + * shell/Makefile.am: + * shell/ev-keyring.[ch]: + * shell/ev-password.[ch]: Removed + * shell/ev-password-view.[ch]: (ev_password_view_finalize), + (ev_password_view_class_init), (ev_password_view_clicked_cb), + (ev_password_view_init), (ev_password_view_set_uri), + (ev_password_dialog_got_response), + (ev_password_dialog_remember_button_toggled), + (ev_password_dialog_entry_changed_cb), + (ev_password_dialog_entry_activated_cb), + (ev_password_view_ask_password), (ev_password_view_get_password), + (ev_password_view_get_password_save_flags), + (ev_password_view_new): + * shell/ev-window.c: (ev_window_password_view_unlock), + (ev_window_load_job_cb), (ev_window_close_dialogs), + (ev_window_init): + + Rework the password view. When the password is in the keyring it's + used automatically without showing the password dialog and it's + only stored in the keyring when we are sure it's correct. The + password dialog has been reworked too, in order to make it + more hig compliant and consistent with the GTK+ dialog used in + gtkmountoperation. Fixes bug #562496. + 2008-11-29 Carlos Garcia Campos * backend/comics/comics-document.c: (comics_document_load): diff --git a/configure.ac b/configure.ac index 3ddbdfe1..a86f92fc 100644 --- a/configure.ac +++ b/configure.ac @@ -47,7 +47,7 @@ dnl Check dependencies DBUS_GLIB_REQUIRED=0.70 GTK_REQUIRED=2.12.0 GLIB_REQUIRED=2.15.6 -KEYRING_REQUIRED=0.4.0 +KEYRING_REQUIRED=2.22.0 GNOME_ICON_THEME_REQUIRED=2.17.1 LIBXML_REQUIRED=2.5.0 diff --git a/shell/Makefile.am b/shell/Makefile.am index b1dafd7a..1a154942 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -38,6 +38,8 @@ evince_SOURCES= \ ev-file-monitor.c \ ev-history.c \ ev-history.h \ + ev-keyring.h \ + ev-keyring.c \ ev-marshal.c \ ev-marshal.h \ $(DBUS_SOURCES) \ @@ -55,8 +57,6 @@ evince_SOURCES= \ ev-page-action-widget.h \ ev-page-cache.h \ ev-page-cache.c \ - ev-password.h \ - ev-password.c \ ev-password-view.h \ ev-password-view.c \ ev-pixbuf-cache.c \ diff --git a/shell/ev-keyring.c b/shell/ev-keyring.c new file mode 100644 index 00000000..0199863a --- /dev/null +++ b/shell/ev-keyring.c @@ -0,0 +1,116 @@ +/* ev-keyring.c + * this file is part of evince, a gnome document viewer + * + * Copyright (C) 2008 Carlos Garcia Campos + * + * Evince 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. + * + * Evince 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 + +#include "ev-keyring.h" + +#ifdef WITH_KEYRING +#include + +static const GnomeKeyringPasswordSchema doc_password_schema = { + GNOME_KEYRING_ITEM_GENERIC_SECRET, + { + { "type", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { "uri", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { NULL, 0 } + } +}; +const GnomeKeyringPasswordSchema *EV_DOCUMENT_PASSWORD_SCHEMA = &doc_password_schema; +#endif /* WITH_KEYRING */ + +gboolean +ev_keyring_is_available (void) +{ +#ifdef WITH_KEYRING + return gnome_keyring_is_available (); +#else + return FALSE; +#endif +} + +gchar * +ev_keyring_lookup_password (const gchar *uri) +{ + gchar *retval = NULL; +#ifdef WITH_KEYRING + GnomeKeyringResult result; + gchar *password = NULL; + + g_return_val_if_fail (uri != NULL, NULL); + + if (!gnome_keyring_is_available ()) + return NULL; + + result = gnome_keyring_find_password_sync (EV_DOCUMENT_PASSWORD_SCHEMA, + &password, + "type", "document_password", + "uri", uri, + NULL); + if (result != GNOME_KEYRING_RESULT_OK || !password) { + if (password) + gnome_keyring_free_password (password); + return NULL; + } + + retval = g_strdup (password); + gnome_keyring_free_password (password); +#endif /* WITH_KEYRING */ + return retval; +} + +gboolean +ev_keyring_save_password (const gchar *uri, + const gchar *password, + GPasswordSave flags) +{ +#ifdef WITH_KEYRING + GnomeKeyringResult result; + const gchar *keyring; + gchar *name; + gchar *unescaped_uri; + + g_return_val_if_fail (uri != NULL, FALSE); + + if (!gnome_keyring_is_available ()) + return FALSE; + + if (flags == G_PASSWORD_SAVE_NEVER) + return FALSE; + + keyring = (flags == G_PASSWORD_SAVE_FOR_SESSION) ? "session" : NULL; + unescaped_uri = g_uri_unescape_string (uri, NULL); + name = g_strdup_printf (_("Password for document %s"), unescaped_uri); + g_free (unescaped_uri); + + result = gnome_keyring_store_password_sync (EV_DOCUMENT_PASSWORD_SCHEMA, + keyring, name, password, + "type", "document_password", + "uri", uri, + NULL); + g_free (name); + + return (result == GNOME_KEYRING_RESULT_OK); +#else + return FALSE; +#endif /* WITH_KEYRING */ +} diff --git a/shell/ev-keyring.h b/shell/ev-keyring.h new file mode 100644 index 00000000..f51410ef --- /dev/null +++ b/shell/ev-keyring.h @@ -0,0 +1,37 @@ +/* ev-keyring.h + * this file is part of evince, a gnome document viewer + * + * Copyright (C) 2008 Carlos Garcia Campos + * + * Evince 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. + * + * Evince 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. + */ + +#ifndef __EV_KEYRING_H__ +#define __EV_KEYRING_H__ + +#include +#include + +G_BEGIN_DECLS + +gboolean ev_keyring_is_available (void); +gchar *ev_keyring_lookup_password (const gchar *uri); +gboolean ev_keyring_save_password (const gchar *uri, + const gchar *password, + GPasswordSave flags); + +G_END_DECLS + +#endif /* __EV_KEYRING_H__ */ diff --git a/shell/ev-password-view.c b/shell/ev-password-view.c index b53300d4..f7d0ca35 100644 --- a/shell/ev-password-view.c +++ b/shell/ev-password-view.c @@ -1,5 +1,6 @@ /* this file is part of evince, a gnome document viewer * + * Copyright (C) 2008 Carlos Garcia Campos * Copyright (C) 2005 Red Hat, Inc * * Evince is free software; you can redistribute it and/or modify it @@ -24,8 +25,9 @@ #include #include +#include -#include "ev-marshal.h" +#include "ev-keyring.h" #include "ev-password-view.h" enum { @@ -33,7 +35,14 @@ enum { LAST_SIGNAL }; struct _EvPasswordViewPrivate { - GtkWidget *label; + GtkWindow *parent_window; + GtkWidget *label; + GtkWidget *password_entry; + + gchar *password; + GPasswordSave password_save; + + GFile *uri_file; }; #define EV_PASSWORD_VIEW_GET_PRIVATE(object) \ @@ -44,6 +53,25 @@ static guint password_view_signals [LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (EvPasswordView, ev_password_view, GTK_TYPE_VIEWPORT) +static void +ev_password_view_finalize (GObject *object) +{ + EvPasswordView *password_view = EV_PASSWORD_VIEW (object); + + if (password_view->priv->password) { + g_free (password_view->priv->password); + password_view->priv->password = NULL; + } + + password_view->priv->parent_window = NULL; + + if (password_view->priv->uri_file) { + g_object_unref (password_view->priv->uri_file); + password_view->priv->uri_file = NULL; + } + + G_OBJECT_CLASS (ev_password_view_parent_class)->finalize (object); +} static void ev_password_view_class_init (EvPasswordViewClass *class) @@ -54,23 +82,25 @@ ev_password_view_class_init (EvPasswordViewClass *class) g_object_class = G_OBJECT_CLASS (class); widget_class = GTK_WIDGET_CLASS (class); - password_view_signals [UNLOCK] = + password_view_signals[UNLOCK] = g_signal_new ("unlock", G_TYPE_FROM_CLASS (g_object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (EvPasswordViewClass, unlock), NULL, NULL, - ev_marshal_VOID__VOID, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_type_class_add_private (g_object_class, sizeof (EvPasswordViewPrivate)); + + g_object_class->finalize = ev_password_view_finalize; } static void ev_password_view_clicked_cb (GtkWidget *button, EvPasswordView *password_view) { - g_signal_emit (password_view, password_view_signals [UNLOCK], 0); + ev_password_view_ask_password (password_view); } static void @@ -82,10 +112,12 @@ ev_password_view_init (EvPasswordView *password_view) GtkWidget *image; GtkWidget *button; GtkWidget *label; - gchar *markup; + gchar *markup; password_view->priv = EV_PASSWORD_VIEW_GET_PRIVATE (password_view); + password_view->priv->password_save = G_PASSWORD_SAVE_NEVER; + gtk_widget_push_composite_child (); /* set ourselves up */ @@ -126,30 +158,274 @@ ev_password_view_init (EvPasswordView *password_view) gtk_widget_pop_composite_child (); } - /* Public functions */ void -ev_password_view_set_file_name (EvPasswordView *password_view, - const char *file_name) +ev_password_view_set_uri (EvPasswordView *password_view, + const char *uri) { - gchar *markup; + gchar *markup, *file_name; + GFile *file; g_return_if_fail (EV_IS_PASSWORD_VIEW (password_view)); - g_return_if_fail (file_name != NULL); - - markup = g_markup_printf_escaped ("%s", file_name); + g_return_if_fail (uri != NULL); + + file = g_file_new_for_uri (uri); + if (password_view->priv->uri_file && + g_file_equal (file, password_view->priv->uri_file)) { + g_object_unref (file); + return; + } + if (password_view->priv->uri_file) + g_object_unref (password_view->priv->uri_file); + password_view->priv->uri_file = file; + + file_name = g_file_get_basename (password_view->priv->uri_file); + markup = g_markup_printf_escaped ("%s", + file_name); + g_free (file_name); gtk_label_set_markup (GTK_LABEL (password_view->priv->label), markup); + g_free (markup); +} + +static void +ev_password_dialog_got_response (GtkDialog *dialog, + gint response_id, + EvPasswordView *password_view) +{ + gtk_widget_set_sensitive (GTK_WIDGET (password_view), TRUE); + + if (response_id == GTK_RESPONSE_OK) { + g_free (password_view->priv->password); + password_view->priv->password = + g_strdup (gtk_entry_get_text (GTK_ENTRY (password_view->priv->password_entry))); + + g_signal_emit (password_view, password_view_signals[UNLOCK], 0); + } + + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + +static void +ev_password_dialog_remember_button_toggled (GtkToggleButton *button, + EvPasswordView *password_view) +{ + if (gtk_toggle_button_get_active (button)) { + gpointer data; + + data = g_object_get_data (G_OBJECT (button), "password-save"); + password_view->priv->password_save = GPOINTER_TO_INT (data); + } +} + +static void +ev_password_dialog_entry_changed_cb (GtkEditable *editable, + GtkDialog *dialog) +{ + const char *text; + + text = gtk_entry_get_text (GTK_ENTRY (editable)); + + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, + (text != NULL && *text != '\0')); +} + +static void +ev_password_dialog_entry_activated_cb (GtkEntry *entry, + GtkDialog *dialog) +{ + gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); +} + +void +ev_password_view_ask_password (EvPasswordView *password_view) +{ + GtkDialog *dialog; + GtkWidget *entry_container; + GtkWidget *hbox, *main_vbox, *vbox, *icon; + GtkWidget *table; + GtkWidget *label; + gchar *format, *markup, *file_name; + + gtk_widget_set_sensitive (GTK_WIDGET (password_view), FALSE); + + dialog = GTK_DIALOG (gtk_dialog_new ()); + + /* Set the dialog up with HIG properties */ + gtk_dialog_set_has_separator (dialog, FALSE); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */ + gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5); + gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6); + + gtk_window_set_title (GTK_WINDOW (dialog), _("Enter password")); + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_DIALOG_AUTHENTICATION); + gtk_window_set_transient_for (GTK_WINDOW (dialog), password_view->priv->parent_window); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + gtk_dialog_add_buttons (dialog, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + _("_Unlock Document"), GTK_RESPONSE_OK, + NULL); + gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GTK_RESPONSE_OK, FALSE); + gtk_dialog_set_alternative_button_order (dialog, + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + /* Build contents */ + hbox = gtk_hbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + gtk_box_pack_start (GTK_BOX (dialog->vbox), hbox, TRUE, TRUE, 0); + gtk_widget_show (hbox); + + icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, + GTK_ICON_SIZE_DIALOG); + + gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0); + gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0); + gtk_widget_show (icon); + + main_vbox = gtk_vbox_new (FALSE, 18); + gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0); + gtk_widget_show (main_vbox); + label = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + file_name = g_file_get_basename (password_view->priv->uri_file); + format = g_strdup_printf ("%s\n\n%s", + _("Password required"), + _("The document “%s” is locked and requires a password before it can be opened.")); + markup = g_markup_printf_escaped (format, file_name); + gtk_label_set_markup (GTK_LABEL (label), markup); + g_free (format); g_free (markup); + g_free (file_name); + gtk_box_pack_start (GTK_BOX (main_vbox), label, + FALSE, FALSE, 0); + gtk_widget_show (label); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); + gtk_widget_show (vbox); + + /* The table that holds the entries */ + entry_container = gtk_alignment_new (0.0, 0.0, 1.0, 1.0); + + gtk_alignment_set_padding (GTK_ALIGNMENT (entry_container), + 0, 0, 0, 0); + + gtk_box_pack_start (GTK_BOX (vbox), entry_container, + FALSE, FALSE, 0); + gtk_widget_show (entry_container); + + table = gtk_table_new (1, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 12); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (entry_container), table); + gtk_widget_show (table); + + label = gtk_label_new_with_mnemonic (_("_Password:")); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + + password_view->priv->password_entry = gtk_entry_new (); + gtk_entry_set_visibility (GTK_ENTRY (password_view->priv->password_entry), FALSE); + g_signal_connect (password_view->priv->password_entry, "changed", + G_CALLBACK (ev_password_dialog_entry_changed_cb), + dialog); + g_signal_connect (password_view->priv->password_entry, "activate", + G_CALLBACK (ev_password_dialog_entry_activated_cb), + dialog); + gtk_table_attach (GTK_TABLE (table), label, + 0, 1, 0, 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_show (label); + + gtk_table_attach_defaults (GTK_TABLE (table), password_view->priv->password_entry, + 1, 2, 0, 1); + gtk_widget_show (password_view->priv->password_entry); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), + password_view->priv->password_entry); + + if (ev_keyring_is_available ()) { + GtkWidget *choice; + GtkWidget *remember_box; + GSList *group; + + remember_box = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (vbox), remember_box, + FALSE, FALSE, 0); + gtk_widget_show (remember_box); + + choice = gtk_radio_button_new_with_mnemonic (NULL, _("Forget password _immediately")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice), + password_view->priv->password_save == G_PASSWORD_SAVE_NEVER); + g_object_set_data (G_OBJECT (choice), "password-save", + GINT_TO_POINTER (G_PASSWORD_SAVE_NEVER)); + g_signal_connect (choice, "toggled", + G_CALLBACK (ev_password_dialog_remember_button_toggled), + password_view); + gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0); + gtk_widget_show (choice); + + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice)); + choice = gtk_radio_button_new_with_mnemonic (group, _("Remember password until you _logout")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice), + password_view->priv->password_save == G_PASSWORD_SAVE_FOR_SESSION); + g_object_set_data (G_OBJECT (choice), "password-save", + GINT_TO_POINTER (G_PASSWORD_SAVE_FOR_SESSION)); + g_signal_connect (choice, "toggled", + G_CALLBACK (ev_password_dialog_remember_button_toggled), + password_view); + gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0); + gtk_widget_show (choice); + + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice)); + choice = gtk_radio_button_new_with_mnemonic (group, _("Remember _forever")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice), + password_view->priv->password_save == G_PASSWORD_SAVE_PERMANENTLY); + g_object_set_data (G_OBJECT (choice), "password-save", + GINT_TO_POINTER (G_PASSWORD_SAVE_PERMANENTLY)); + g_signal_connect (choice, "toggled", + G_CALLBACK (ev_password_dialog_remember_button_toggled), + password_view); + gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0); + gtk_widget_show (choice); + } + + g_signal_connect (G_OBJECT (dialog), "response", + G_CALLBACK (ev_password_dialog_got_response), + password_view); + + gtk_widget_show (GTK_WIDGET (dialog)); +} + +const gchar * +ev_password_view_get_password (EvPasswordView *password_view) +{ + return password_view->priv->password; +} + +GPasswordSave +ev_password_view_get_password_save_flags (EvPasswordView *password_view) +{ + return password_view->priv->password_save; } GtkWidget * -ev_password_view_new (void) +ev_password_view_new (GtkWindow *parent) { - GtkWidget *retval; + EvPasswordView *retval; + + retval = EV_PASSWORD_VIEW (g_object_new (EV_TYPE_PASSWORD_VIEW, NULL)); - retval = (GtkWidget *) g_object_new (EV_TYPE_PASSWORD_VIEW, NULL); + retval->priv->parent_window = parent; - return retval; + return GTK_WIDGET (retval); } + diff --git a/shell/ev-password-view.h b/shell/ev-password-view.h index d59d62b4..7f2670b2 100644 --- a/shell/ev-password-view.h +++ b/shell/ev-password-view.h @@ -21,6 +21,7 @@ #define __EV_PASSWORD_VIEW_H__ #include +#include G_BEGIN_DECLS @@ -34,6 +35,7 @@ typedef struct _EvPasswordViewPrivate EvPasswordViewPrivate; struct _EvPasswordView { GtkViewport parent_instance; + EvPasswordViewPrivate *priv; }; @@ -44,11 +46,13 @@ struct _EvPasswordViewClass { void (*unlock) (EvPasswordView *self); }; -GType ev_password_view_get_type (void) G_GNUC_CONST; -GtkWidget *ev_password_view_new (void); -void ev_password_view_set_file_name (EvPasswordView *password_view, - const char *file_name); - +GType ev_password_view_get_type (void) G_GNUC_CONST; +GtkWidget *ev_password_view_new (GtkWindow *parent); +void ev_password_view_set_uri (EvPasswordView *password_view, + const char *uri); +void ev_password_view_ask_password (EvPasswordView *password_view); +const gchar *ev_password_view_get_password (EvPasswordView *password_view); +GPasswordSave ev_password_view_get_password_save_flags (EvPasswordView *password_view); G_END_DECLS diff --git a/shell/ev-password.c b/shell/ev-password.c deleted file mode 100644 index a191b9f1..00000000 --- a/shell/ev-password.c +++ /dev/null @@ -1,350 +0,0 @@ -/* this file is part of evince, a gnome document viewer - * - * Copyright (C) 2005 Red Hat, Inc - * - * Evince 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. - * - * Evince 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include - -#ifdef WITH_KEYRING -#include -#else -#define gnome_keyring_is_available() FALSE -#endif - -#include "ev-password.h" - -enum { - PROP_0, - PROP_URI, -}; - -struct _EvPasswordDialogPrivate { - - gchar *uri; - - GtkWidget *bad_label; - GtkWidget *label; - GtkWidget *entry; - GtkWidget *check_default; - GtkWidget *check_session; -}; - -#define EV_PASSWORD_DIALOG_GET_PRIVATE(object) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_PASSWORD_DIALOG, EvPasswordDialogPrivate)); - -G_DEFINE_TYPE (EvPasswordDialog, ev_password_dialog, GTK_TYPE_DIALOG) - - -static void ev_password_dialog_entry_changed_cb (GtkEditable *editable, - EvPasswordDialog *dialog); -static void ev_password_dialog_entry_activated_cb (GtkEntry *entry, - EvPasswordDialog *dialog); -static void ev_password_set_bad_password_label (EvPasswordDialog *dialog, - gchar *message); -static void ev_password_search_in_keyring (EvPasswordDialog *dialog, - const gchar *uri); - -static void -ev_password_dialog_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - EvPasswordDialog *dialog = EV_PASSWORD_DIALOG (object); - char *format; - char *markup; - char *base_name; - GFile *file; - - switch (prop_id) { - case PROP_URI: - dialog->priv->uri = g_strdup (g_value_get_string (value)); - - file = g_file_new_for_uri (dialog->priv->uri); - - base_name = g_file_get_basename (file); - format = g_strdup_printf ("%s\n\n%s", - _("Password required"), - _("The document “%s” is locked and requires a password before it can be opened.")); - markup = g_markup_printf_escaped (format, base_name); - - gtk_label_set_markup (GTK_LABEL (dialog->priv->label), markup); - - g_free (base_name); - g_free (format); - g_free (markup); - g_object_unref (file); - - ev_password_search_in_keyring (dialog, dialog->priv->uri); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -ev_password_dialog_finalize (GObject *object) -{ - EvPasswordDialog *dialog = EV_PASSWORD_DIALOG (object); - - if (dialog->priv->uri) { - g_free (dialog->priv->uri); - dialog->priv->uri = NULL; - } - - G_OBJECT_CLASS (ev_password_dialog_parent_class)->finalize (object); -} - - -static void -ev_password_dialog_class_init (EvPasswordDialogClass *class) -{ - GObjectClass *g_object_class; - GtkWidgetClass *widget_class; - - g_object_class = G_OBJECT_CLASS (class); - widget_class = GTK_WIDGET_CLASS (class); - - g_type_class_add_private (g_object_class, sizeof (EvPasswordDialogPrivate)); - - g_object_class->set_property = ev_password_dialog_set_property; - g_object_class->finalize = ev_password_dialog_finalize; - - g_object_class_install_property (g_object_class, - PROP_URI, - g_param_spec_string ("uri", - "Document URI", - "Encrypted document URI", - NULL, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); -} - - -static void -ev_password_dialog_init (EvPasswordDialog *dialog) -{ - GtkWidget *hbox; - const char *glade_file = DATADIR "/evince-password.glade"; - GladeXML *xml; - - dialog->priv = EV_PASSWORD_DIALOG_GET_PRIVATE (dialog); - - gtk_window_set_title (GTK_WINDOW (dialog), _("Enter password")); - gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); - gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); - gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 12); - - gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL); - gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, - GTK_RESPONSE_OK); - - xml = glade_xml_new (glade_file, "hbox-contents", NULL); - g_assert (xml); - - hbox = glade_xml_get_widget (xml, "hbox-contents"); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); - - dialog->priv->bad_label = glade_xml_get_widget (xml, "bad_password_label"); - dialog->priv->check_default = glade_xml_get_widget (xml, "savesession_checkbutton"); - dialog->priv->check_session = glade_xml_get_widget (xml, "savekeyring_checkbutton"); - dialog->priv->entry = glade_xml_get_widget (xml, "password_entry"); - dialog->priv->label = glade_xml_get_widget (xml, "password_label"); - - g_signal_connect (dialog->priv->entry, "changed", G_CALLBACK (ev_password_dialog_entry_changed_cb), dialog); - g_signal_connect (dialog->priv->entry, "activate", G_CALLBACK (ev_password_dialog_entry_activated_cb), dialog); - - ev_password_set_bad_password_label (dialog, " "); - - if (!gnome_keyring_is_available ()) { - gtk_widget_hide (dialog->priv->check_default); - gtk_widget_hide (dialog->priv->check_session); - } - - g_object_unref (xml); -} - -static void -ev_password_set_bad_password_label (EvPasswordDialog *dialog, - gchar *message) -{ - gchar *markup; - - markup = g_strdup_printf ("%s", - message); - gtk_label_set_markup (GTK_LABEL (dialog->priv->bad_label), markup); - g_free (markup); -} - -static void -ev_password_dialog_entry_changed_cb (GtkEditable *editable, - EvPasswordDialog *dialog) -{ - const char *text; - - text = gtk_entry_get_text (GTK_ENTRY (editable)); - - if (text == NULL || *text == '\0') - gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), - GTK_RESPONSE_OK, FALSE); - else - gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), - GTK_RESPONSE_OK, TRUE); - - ev_password_set_bad_password_label (dialog, " "); -} - -static void -ev_password_dialog_entry_activated_cb (GtkEntry *entry, - EvPasswordDialog *dialog) -{ - gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); -} - -#ifdef WITH_KEYRING -static void -ev_password_item_created_callback (GnomeKeyringResult result, - guint32 val, - gpointer data) -{ - /* Nothing yet */ - return; -} -#endif - -void -ev_password_dialog_save_password (EvPasswordDialog *dialog) -{ -#ifdef WITH_KEYRING - GnomeKeyringAttributeList *attributes; - GnomeKeyringAttribute attribute; - gchar *name; - gchar *unescaped_uri; - - attributes = gnome_keyring_attribute_list_new (); - - attribute.name = g_strdup ("type"); - attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING; - attribute.value.string = g_strdup ("document_password"); - g_array_append_val (attributes, attribute); - - attribute.name = g_strdup ("uri"); - attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING; - attribute.value.string = g_strdup (dialog->priv->uri); - g_array_append_val (attributes, attribute); - - unescaped_uri = g_uri_unescape_string (dialog->priv->uri, NULL); - name = g_strdup_printf (_("Password for document %s"), unescaped_uri); - - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_default))) { - gnome_keyring_item_create (NULL, - GNOME_KEYRING_ITEM_GENERIC_SECRET, - name, - attributes, - ev_password_dialog_get_password (dialog), - TRUE, ev_password_item_created_callback, - NULL, NULL); - } - - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_session))) { - gnome_keyring_item_create ("session", - GNOME_KEYRING_ITEM_GENERIC_SECRET, - name, - attributes, - ev_password_dialog_get_password (dialog), - TRUE, ev_password_item_created_callback, - NULL, NULL); - } - - gnome_keyring_attribute_list_free (attributes); - g_free (name); - g_free (unescaped_uri); - -#endif /* WITH_KEYRING */ - return; -} - -#ifdef WITH_KEYRING -static void -ev_password_keyring_found_cb (GnomeKeyringResult result, - GList *list, - gpointer data) - -{ - GnomeKeyringFound *found; - EvPasswordDialog *dialog = EV_PASSWORD_DIALOG (data); - - if (result != GNOME_KEYRING_RESULT_OK || list == NULL) - return; - - found = list->data; - gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), found->secret); -} -#endif /* WITH_KEYRING */ - -static void -ev_password_search_in_keyring (EvPasswordDialog *dialog, const gchar *uri) -{ -#ifdef WITH_KEYRING - GnomeKeyringAttributeList *attributes; - GnomeKeyringAttribute attribute; - - attributes = gnome_keyring_attribute_list_new (); - - attribute.name = g_strdup ("type"); - attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING; - attribute.value.string = g_strdup ("document_password"); - g_array_append_val (attributes, attribute); - - attribute.name = g_strdup ("uri"); - attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING; - attribute.value.string = g_strdup (uri); - g_array_append_val (attributes, attribute); - - gnome_keyring_find_items (GNOME_KEYRING_ITEM_GENERIC_SECRET, - attributes, - ev_password_keyring_found_cb, - g_object_ref (dialog), - g_object_unref); - gnome_keyring_attribute_list_free (attributes); -#endif /* WITH_KEYRING */ - return; -} - -const char * -ev_password_dialog_get_password (EvPasswordDialog *dialog) -{ - return gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry)); -} - -void -ev_password_dialog_set_bad_pass (EvPasswordDialog *dialog) -{ - gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), ""); - ev_password_set_bad_password_label (dialog, _("Incorrect password")); -} - - diff --git a/shell/ev-password.h b/shell/ev-password.h deleted file mode 100644 index d092ccab..00000000 --- a/shell/ev-password.h +++ /dev/null @@ -1,58 +0,0 @@ -/* this file is part of evince, a gnome document viewer - * - * Copyright (C) 2005 Red Hat, Inc - * - * Evince 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. - * - * Evince 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. - */ - -#ifndef __EV_PASSWORD_H__ -#define __EV_PASSWORD_H__ - -#include - -G_BEGIN_DECLS - -#define EV_TYPE_PASSWORD_DIALOG (ev_password_dialog_get_type ()) -#define EV_PASSWORD_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EV_TYPE_PASSWORD_DIALOG, EvPasswordDialog)) -#define EV_PASSWORD_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_PASSWORD_DIALOG, EvPasswordDialogClass)) -#define EV_IS_PASSWORD_DIALOG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), EV_TYPE_PASSWORD_DIALOG)) -#define EV_IS_PASSWORD_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_PASSWORD_DIALOG)) -#define EV_PASSWORD_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_PASSWORD_DIALOG, EvPasswordDialogClass)) - -typedef struct _EvPasswordDialog EvPasswordDialog; -typedef struct _EvPasswordDialogClass EvPasswordDialogClass; -typedef struct _EvPasswordDialogPrivate EvPasswordDialogPrivate; - -struct _EvPasswordDialog -{ - GtkDialog parent_instance; - - EvPasswordDialogPrivate* priv; -}; - -struct _EvPasswordDialogClass -{ - GtkDialogClass parent_class; -}; - -GType ev_password_dialog_get_type (void) G_GNUC_CONST; - -const char *ev_password_dialog_get_password (EvPasswordDialog *dialog); -void ev_password_dialog_set_bad_pass (EvPasswordDialog *dialog); -void ev_password_dialog_save_password (EvPasswordDialog *dialog); - -G_END_DECLS - -#endif /* __EV_PASSWORD_H__ */ diff --git a/shell/ev-window.c b/shell/ev-window.c index 47ce4c77..c570de7f 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -73,7 +73,6 @@ #include "ev-navigation-action.h" #include "ev-open-recent-action.h" #include "ev-page-action.h" -#include "ev-password.h" #include "ev-password-view.h" #include "ev-properties-dialog.h" #include "ev-sidebar-attachments.h" @@ -84,6 +83,7 @@ #include "ev-sidebar-layers.h" #include "ev-stock-icons.h" #include "ev-utils.h" +#include "ev-keyring.h" #include "ev-view.h" #include "ev-window.h" #include "ev-window-title.h" @@ -135,7 +135,6 @@ struct _EvWindowPrivate { /* Dialogs */ GtkWidget *properties; GtkWidget *print_dialog; - GtkWidget *password_dialog; /* UI Builders */ GtkActionGroup *action_group; @@ -1256,57 +1255,15 @@ ev_window_document_changed (EvWindow *ev_window, } static void -password_dialog_response (GtkWidget *password_dialog, - gint response_id, - EvWindow *ev_window) -{ - if (response_id == GTK_RESPONSE_OK) { - ev_job_load_set_password (EV_JOB_LOAD (ev_window->priv->load_job), - ev_password_dialog_get_password (EV_PASSWORD_DIALOG (password_dialog))); - - ev_password_dialog_save_password (EV_PASSWORD_DIALOG (password_dialog)); - - ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_DOCUMENT); - ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE); - - gtk_widget_destroy (password_dialog); - - return; - } - - gtk_widget_set_sensitive (ev_window->priv->password_view, TRUE); - gtk_widget_destroy (password_dialog); -} - -/* Called either by ev_window_load_job_cb or by the "unlock" callback on the - * password_view page. It assumes that ev_window->priv->password_* has been set - * correctly. These are cleared by password_dialog_response() */ - -static void -ev_window_popup_password_dialog (EvWindow *ev_window) +ev_window_password_view_unlock (EvWindow *ev_window) { + const gchar *password; + g_assert (ev_window->priv->load_job); - gtk_widget_set_sensitive (ev_window->priv->password_view, FALSE); - - ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri); - ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_PASSWORD); - - if (ev_window->priv->password_dialog == NULL) { - ev_window->priv->password_dialog = - g_object_new (EV_TYPE_PASSWORD_DIALOG, "uri", ev_window->priv->uri, NULL); - gtk_window_set_transient_for (GTK_WINDOW (ev_window->priv->password_dialog), GTK_WINDOW (ev_window)); - - g_object_add_weak_pointer (G_OBJECT (ev_window->priv->password_dialog), - (gpointer) &(ev_window->priv->password_dialog)); - g_signal_connect (ev_window->priv->password_dialog, - "response", - G_CALLBACK (password_dialog_response), - ev_window); - gtk_widget_show (ev_window->priv->password_dialog); - } else { - ev_password_dialog_set_bad_pass (EV_PASSWORD_DIALOG (ev_window->priv->password_dialog)); - } + password = ev_password_view_get_password (EV_PASSWORD_VIEW (ev_window->priv->password_view)); + ev_job_load_set_password (EV_JOB_LOAD (ev_window->priv->load_job), password); + ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE); } static void @@ -1406,6 +1363,18 @@ ev_window_load_job_cb (EvJob *job, ev_window_add_recent (ev_window, ev_window->priv->uri); } + ev_window_title_set_type (ev_window->priv->title, + EV_WINDOW_TITLE_DOCUMENT); + if (job_load->password) { + GPasswordSave flags; + + flags = ev_password_view_get_password_save_flags ( + EV_PASSWORD_VIEW (ev_window->priv->password_view)); + ev_keyring_save_password (ev_window->priv->uri, + job_load->password, + flags); + } + if (job_load->dest) { EvLink *link; EvLinkAction *link_action; @@ -1448,20 +1417,40 @@ ev_window_load_job_cb (EvJob *job, if (job->error->domain == EV_DOCUMENT_ERROR && job->error->code == EV_DOCUMENT_ERROR_ENCRYPTED) { - GFile *file; - gchar *base_name; - + gchar *password; + setup_view_from_metadata (ev_window); + + /* First look whether password is in keyring */ + password = ev_keyring_lookup_password (ev_window->priv->uri); + if (password) { + if (job_load->password && strcmp (password, job_load->password) == 0) { + /* Password in kering is wrong */ + ev_job_load_set_password (job_load, NULL); + /* FIXME: delete password from keyring? */ + } else { + ev_job_load_set_password (job_load, password); + ev_job_scheduler_push_job (job, EV_JOB_PRIORITY_NONE); + g_free (password); + return; + } + + g_free (password); + } + + /* We need to ask the user for a password */ + ev_window_title_set_uri (ev_window->priv->title, + ev_window->priv->uri); + ev_window_title_set_type (ev_window->priv->title, + EV_WINDOW_TITLE_PASSWORD); + + ev_password_view_set_uri (EV_PASSWORD_VIEW (ev_window->priv->password_view), + job_load->uri); - file = g_file_new_for_uri (job_load->uri); - base_name = g_file_get_basename (file); - ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view), - base_name); - g_object_unref (file); - g_free (base_name); ev_window_set_page_mode (ev_window, PAGE_MODE_PASSWORD); - - ev_window_popup_password_dialog (ev_window); + + ev_job_load_set_password (job_load, NULL); + ev_password_view_ask_password (EV_PASSWORD_VIEW (ev_window->priv->password_view)); } else { ev_window_error_message (ev_window, job->error, "%s", _("Unable to open document")); @@ -1518,10 +1507,6 @@ ev_window_get_uri (EvWindow *ev_window) static void ev_window_close_dialogs (EvWindow *ev_window) { - if (ev_window->priv->password_dialog) - gtk_widget_destroy (ev_window->priv->password_dialog); - ev_window->priv->password_dialog = NULL; - if (ev_window->priv->print_dialog) gtk_widget_destroy (ev_window->priv->print_dialog); ev_window->priv->print_dialog = NULL; @@ -5650,10 +5635,10 @@ ev_window_init (EvWindow *ev_window) ev_window->priv->view = ev_view_new (); ev_view_set_screen_dpi (EV_VIEW (ev_window->priv->view), get_screen_dpi (GTK_WINDOW (ev_window))); - ev_window->priv->password_view = ev_password_view_new (); + ev_window->priv->password_view = ev_password_view_new (GTK_WINDOW (ev_window)); g_signal_connect_swapped (ev_window->priv->password_view, "unlock", - G_CALLBACK (ev_window_popup_password_dialog), + G_CALLBACK (ev_window_password_view_unlock), ev_window); g_signal_connect_object (ev_window->priv->view, "focus_in_event", G_CALLBACK (view_actions_focus_in_cb), -- 2.43.5