diff options
Diffstat (limited to 'shell')
-rw-r--r-- | shell/Makefile.am | 4 | ||||
-rw-r--r-- | shell/ev-keyring.c | 116 | ||||
-rw-r--r-- | shell/ev-keyring.h | 37 | ||||
-rw-r--r-- | shell/ev-password-view.c | 310 | ||||
-rw-r--r-- | shell/ev-password-view.h | 14 | ||||
-rw-r--r-- | shell/ev-password.c | 350 | ||||
-rw-r--r-- | shell/ev-password.h | 58 | ||||
-rw-r--r-- | shell/ev-window.c | 119 |
8 files changed, 509 insertions, 499 deletions
diff --git a/shell/Makefile.am b/shell/Makefile.am index b1dafd7..1a15494 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 0000000..0199863 --- /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 <carlosgc@gnome.org> + * + * 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 <glib/gi18n.h> + +#include "ev-keyring.h" + +#ifdef WITH_KEYRING +#include <gnome-keyring.h> + +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 0000000..f51410e --- /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 <carlosgc@gnome.org> + * + * 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 <glib.h> +#include <gio/gio.h> + +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 b53300d..f7d0ca3 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 <carlosgc@gnome.org> * Copyright (C) 2005 Red Hat, Inc * * Evince is free software; you can redistribute it and/or modify it @@ -24,8 +25,9 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> +#include <gio/gio.h> -#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 ("<span size=\"x-large\" weight=\"bold\">%s</span>", 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 ("<span size=\"x-large\" weight=\"bold\">%s</span>", + 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 ("<span size=\"larger\" weight=\"bold\">%s</span>\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 d59d62b..7f2670b 100644 --- a/shell/ev-password-view.h +++ b/shell/ev-password-view.h @@ -21,6 +21,7 @@ #define __EV_PASSWORD_VIEW_H__ #include <gtk/gtk.h> +#include <gio/gio.h> 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 a191b9f..0000000 --- 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 <glib/gi18n.h> -#include <gio/gio.h> -#include <gtk/gtk.h> -#include <glade/glade.h> - -#ifdef WITH_KEYRING -#include <gnome-keyring.h> -#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 ("<span size=\"larger\" weight=\"bold\">%s</span>\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 ("<span color=\"red\" size=\"smaller\">%s</span>", - 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 d092cca..0000000 --- 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 <gtk/gtk.h> - -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 47ce4c7..c570de7 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), |