From e53e8a7ba14b5156d41e84d56cab85cbe195e344 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 13 Sep 2005 13:41:17 +0000 Subject: [PATCH] Support for gnome-keyring for encrypted PDF's. * configure.ac: * data/evince-password.glade: * shell/ev-password.c: (ev_password_dialog_set_property), (ev_password_dialog_finalize), (ev_password_dialog_class_init), (ev_password_dialog_init), (ev_password_set_bad_password_label), (ev_password_dialog_entry_changed_cb), (ev_password_dialog_entry_activated_cb), (ev_password_dialog_save_password), (ev_password_keyring_found_cb), (ev_password_search_in_keyring), (ev_password_dialog_get_password), (ev_password_dialog_set_bad_pass): * shell/ev-password.h: * shell/ev-window.c: (password_dialog_response), (ev_window_popup_password_dialog): Support for gnome-keyring for encrypted PDF's. --- ChangeLog | 18 ++ configure.ac | 3 +- data/evince-password.glade | 40 ++++- shell/ev-password.c | 338 ++++++++++++++++++++++++++++--------- shell/ev-password.h | 34 +++- shell/ev-window.c | 15 +- 6 files changed, 356 insertions(+), 92 deletions(-) diff --git a/ChangeLog b/ChangeLog index 28aa88c2..f037b555 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2005-09-13 Nickolay V. Shmyrev + + * configure.ac: + * data/evince-password.glade: + * shell/ev-password.c: (ev_password_dialog_set_property), + (ev_password_dialog_finalize), (ev_password_dialog_class_init), + (ev_password_dialog_init), (ev_password_set_bad_password_label), + (ev_password_dialog_entry_changed_cb), + (ev_password_dialog_entry_activated_cb), + (ev_password_dialog_save_password), (ev_password_keyring_found_cb), + (ev_password_search_in_keyring), (ev_password_dialog_get_password), + (ev_password_dialog_set_bad_pass): + * shell/ev-password.h: + * shell/ev-window.c: (password_dialog_response), + (ev_window_popup_password_dialog): + + Support for gnome-keyring for encrypted PDF's. + 2005-09-11 Nickolay V. Shmyrev * shell/ev-view.c: (handle_link_over_xy), (ev_view_realize), diff --git a/configure.ac b/configure.ac index c279f113..b280ed36 100644 --- a/configure.ac +++ b/configure.ac @@ -47,12 +47,13 @@ POPPLER_REQUIRED=0.4.1 DBUS_GLIB_REQUIRED=0.33 GTK_REQUIRED=2.6.0 LIBGNOMEUI_REQUIRED=2.6.0 +KEYRING_REQUIRED=0.4.2 PKG_CHECK_MODULES(LIB, gtk+-2.0 >= $GTK_REQUIRED libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED) PKG_CHECK_MODULES(BACKEND, gtk+-2.0 >= $GTK_REQUIRED) PKG_CHECK_MODULES(FRONTEND_CORE, gtk+-2.0 >= $GTK_REQUIRED libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED libglade-2.0 poppler-glib >= $POPPLER_REQUIRED) PKG_CHECK_MODULES(POPPLER, poppler-glib >= $POPPLER_REQUIRED) -PKG_CHECK_MODULES(SHELL_CORE, gtk+-2.0 >= $GTK_REQUIRED libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED gnome-vfs-2.0 libgnomeprint-2.2 >= 2.5.1 libgnomeprintui-2.2 libglade-2.0 gconf-2.0 poppler-glib >= $POPPLER_REQUIRED) +PKG_CHECK_MODULES(SHELL_CORE, gtk+-2.0 >= $GTK_REQUIRED libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED gnome-vfs-2.0 libgnomeprint-2.2 >= 2.5.1 libgnomeprintui-2.2 libglade-2.0 gconf-2.0 poppler-glib >= $POPPLER_REQUIRED gnome-keyring-1 >= $KEYRING_REQUIRED) GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` AC_SUBST(GLIB_GENMARSHAL) diff --git a/data/evince-password.glade b/data/evince-password.glade index 0b02ad05..9d8bc975 100644 --- a/data/evince-password.glade +++ b/data/evince-password.glade @@ -66,7 +66,7 @@ - + 6 True False @@ -190,6 +190,44 @@ False + + + + True + True + True + Remember password for this session + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + True + Save password in keyring + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + 0 diff --git a/shell/ev-password.c b/shell/ev-password.c index 7a5c819a..4dc312df 100644 --- a/shell/ev-password.c +++ b/shell/ev-password.c @@ -21,123 +21,309 @@ #include "config.h" #endif -#include "ev-password.h" #include #include #include +#include +#include + +#include "ev-password.h" + +enum { + PROP_0, + PROP_URI, +}; -#define EV_PASSWORD_DATA "ev-password-data" +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_set_bad_password_label (GtkWidget *password, - gchar *message) +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; + char *file_name; + + switch (prop_id) + { + case PROP_URI: + dialog->priv->uri = g_strdup (g_value_get_string (value)); + + file_name = gnome_vfs_format_uri_for_display (dialog->priv->uri); + base_name = g_path_get_basename (file_name); + 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 (file_name); + g_free (format); + g_free (markup); + + 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; - GtkWidget *label; - gchar *markup; - xml = g_object_get_data (G_OBJECT (password), EV_PASSWORD_DATA); + 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; - label = glade_xml_get_widget (xml, "bad_password_label"); markup = g_strdup_printf ("%s", message); - gtk_label_set_markup (GTK_LABEL (label), markup); + gtk_label_set_markup (GTK_LABEL (dialog->priv->bad_label), markup); g_free (markup); } static void -ev_window_password_entry_changed_cb (GtkEditable *editable, - GtkWidget *password) +ev_password_dialog_entry_changed_cb (GtkEditable *editable, + EvPasswordDialog *dialog) { const char *text; - GtkWidget *button; - GladeXML *xml; - - xml = g_object_get_data (G_OBJECT (password), EV_PASSWORD_DATA); - g_assert (xml); text = gtk_entry_get_text (GTK_ENTRY (editable)); - button = glade_xml_get_widget (xml, "ok_button"); if (text == NULL || *text == '\0') - gtk_widget_set_sensitive (button, FALSE); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GTK_RESPONSE_OK, FALSE); else - gtk_widget_set_sensitive (button, TRUE); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GTK_RESPONSE_OK, TRUE); - ev_password_set_bad_password_label (password, " "); + ev_password_set_bad_password_label (dialog, " "); } -GtkWidget * -ev_password_dialog_new (GtkWidget *toplevel, - const char *uri) +static void +ev_password_dialog_entry_activated_cb (GtkEntry *entry, + EvPasswordDialog *dialog) { - const char *glade_file = DATADIR "/evince-password.glade"; - GladeXML *xml; - GtkWidget *dialog, *label; - GtkWidget *entry; - char *format; - char *markup; + gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); +} - xml = glade_xml_new (glade_file, NULL, NULL); - if (xml == NULL) { - dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - _("Unable to find glade file")); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), - _("The glade file, %s, cannot be found. Please check that your installation is complete."), - glade_file); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - return NULL; - } +void +ev_password_dialog_save_password (EvPasswordDialog *dialog) +{ + GnomeKeyringAttributeList *attributes; + GnomeKeyringAttribute attribute; + guint32 item_id; + 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); - dialog = glade_xml_get_widget (xml, "password_dialog"); - label = glade_xml_get_widget (xml, "password_label"); - entry = glade_xml_get_widget (xml, "password_entry"); - - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel)); - g_signal_connect (entry, "changed", G_CALLBACK (ev_window_password_entry_changed_cb), dialog); - 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, uri); - gtk_label_set_markup (GTK_LABEL (label), markup); - g_free (format); - g_free (markup); + unescaped_uri = gnome_vfs_unescape_string_for_display (dialog->priv->uri); + name = g_strdup_printf (_("Password for document %s"), unescaped_uri); - g_object_set_data_full (G_OBJECT (dialog), EV_PASSWORD_DATA, xml, g_object_unref); - ev_password_set_bad_password_label (dialog, " "); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_default))) { + gnome_keyring_item_create_sync (NULL, + GNOME_KEYRING_ITEM_GENERIC_SECRET, + name, + attributes, + ev_password_dialog_get_password (dialog), + TRUE, + &item_id); + } - return dialog; + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_session))) { + gnome_keyring_item_create_sync ("session", + GNOME_KEYRING_ITEM_GENERIC_SECRET, + name, + attributes, + ev_password_dialog_get_password (dialog), + TRUE, + &item_id); + } + + gnome_keyring_attribute_list_free (attributes); + g_free (name); + g_free (unescaped_uri); + + return; } -char * -ev_password_dialog_get_password (GtkWidget *password) +static void +ev_password_keyring_found_cb (GnomeKeyringResult result, + GList *list, + gpointer data) + { - GladeXML *xml; - GtkWidget *entry; + GnomeKeyringFound *found; + EvPasswordDialog *dialog = EV_PASSWORD_DIALOG (data); - xml = g_object_get_data (G_OBJECT (password), EV_PASSWORD_DATA); - g_assert (xml); + if (result != GNOME_KEYRING_RESULT_OK || list == NULL) + return; - entry = glade_xml_get_widget (xml, "password_entry"); + found = list->data; + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), found->secret); +} - return g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); +static void +ev_password_search_in_keyring (EvPasswordDialog *dialog, const gchar *uri) +{ + 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); + return; +} + +char * +ev_password_dialog_get_password (EvPasswordDialog *dialog) +{ + return g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry))); } void -ev_password_dialog_set_bad_pass (GtkWidget *password) +ev_password_dialog_set_bad_pass (EvPasswordDialog *dialog) { - GladeXML *xml; - GtkWidget *entry; + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), ""); + ev_password_set_bad_password_label (dialog, _("Incorrect password")); +} - xml = g_object_get_data (G_OBJECT (password), EV_PASSWORD_DATA); - g_assert (xml); - entry = glade_xml_get_widget (xml, "password_entry"); - gtk_entry_set_text (GTK_ENTRY (entry), ""); - ev_password_set_bad_password_label (password, _("Incorrect password")); -} diff --git a/shell/ev-password.h b/shell/ev-password.h index 0c725a84..048cf473 100644 --- a/shell/ev-password.h +++ b/shell/ev-password.h @@ -20,14 +20,38 @@ #ifndef __EV_PASSWORD_H__ #define __EV_PASSWORD_H__ -#include +#include G_BEGIN_DECLS -GtkWidget *ev_password_dialog_new (GtkWidget *toplevel, - const gchar *uri); -char *ev_password_dialog_get_password (GtkWidget *password); -void ev_password_dialog_set_bad_pass (GtkWidget *password); +#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; + +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 diff --git a/shell/ev-window.c b/shell/ev-window.c index 0b4f919e..ad276796 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -710,7 +710,7 @@ password_dialog_response (GtkWidget *password_dialog, EvDocument *document; gchar *uri; - password = ev_password_dialog_get_password (password_dialog); + password = ev_password_dialog_get_password (EV_PASSWORD_DIALOG (password_dialog)); if (password) { ev_document_doc_mutex_lock (); ev_document_security_set_password (EV_DOCUMENT_SECURITY (ev_window->priv->password_document), @@ -719,6 +719,8 @@ password_dialog_response (GtkWidget *password_dialog, } g_free (password); + ev_password_dialog_save_password (EV_PASSWORD_DIALOG (password_dialog)); + document = ev_window->priv->password_document; uri = ev_window->priv->password_uri; @@ -753,14 +755,9 @@ ev_window_popup_password_dialog (EvWindow *ev_window) update_window_title (ev_window->priv->password_document, NULL, ev_window); if (ev_window->priv->password_dialog == NULL) { - gchar *base_name, *file_name; - - file_name = gnome_vfs_format_uri_for_display (ev_window->priv->password_uri); - base_name = g_path_get_basename (file_name); ev_window->priv->password_dialog = - ev_password_dialog_new (GTK_WIDGET (ev_window), base_name); - g_free (base_name); - g_free (file_name); + g_object_new (EV_TYPE_PASSWORD_DIALOG, "uri", ev_window->priv->password_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)); @@ -770,7 +767,7 @@ ev_window_popup_password_dialog (EvWindow *ev_window) ev_window); gtk_widget_show (ev_window->priv->password_dialog); } else { - ev_password_dialog_set_bad_pass (ev_window->priv->password_dialog); + ev_password_dialog_set_bad_pass (EV_PASSWORD_DIALOG (ev_window->priv->password_dialog)); } } -- 2.43.5