+2008-12-01 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * 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 <carlosgc@gnome.org>
* backend/comics/comics-document.c: (comics_document_load):
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
ev-file-monitor.c \
ev-history.c \
ev-history.h \
+ ev-keyring.h \
+ ev-keyring.c \
ev-marshal.c \
ev-marshal.h \
$(DBUS_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 \
--- /dev/null
+/* 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 */
+}
--- /dev/null
+/* 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__ */
/* 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
#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 {
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) \
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)
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
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 */
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);
}
+
#define __EV_PASSWORD_VIEW_H__
#include <gtk/gtk.h>
+#include <gio/gio.h>
G_BEGIN_DECLS
struct _EvPasswordView {
GtkViewport parent_instance;
+
EvPasswordViewPrivate *priv;
};
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
+++ /dev/null
-/* 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"));
-}
-
-
+++ /dev/null
-/* 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__ */
#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"
#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"
/* Dialogs */
GtkWidget *properties;
GtkWidget *print_dialog;
- GtkWidget *password_dialog;
/* UI Builders */
GtkActionGroup *action_group;
}
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
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;
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"));
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;
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),