]> www.fi.muni.cz Git - evince.git/blob - shell/ev-password.c
463d1e71af71d049c5b54781b8dd14a9e3c4071f
[evince.git] / shell / ev-password.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2005 Red Hat, Inc
4  *
5  * Evince is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Evince is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <glib/gi18n.h>
25 #include <gtk/gtk.h>
26 #include <glade/glade.h>
27 #include <libgnomevfs/gnome-vfs-utils.h>
28
29 #ifdef WITH_KEYRING
30 #include <gnome-keyring.h>
31 #else
32 #define gnome_keyring_is_available()    FALSE
33 #endif
34
35 #include "ev-password.h"
36
37 enum {
38         PROP_0,
39         PROP_URI,
40 };
41
42 struct _EvPasswordDialogPrivate {
43         
44         gchar *uri;
45     
46         GtkWidget *bad_label;
47         GtkWidget *label;
48         GtkWidget *entry;
49         GtkWidget *check_default;
50         GtkWidget *check_session;
51 };
52
53 #define EV_PASSWORD_DIALOG_GET_PRIVATE(object) \
54         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_PASSWORD_DIALOG, EvPasswordDialogPrivate));
55
56 G_DEFINE_TYPE (EvPasswordDialog, ev_password_dialog, GTK_TYPE_DIALOG)
57
58
59 static void ev_password_dialog_entry_changed_cb   (GtkEditable *editable,
60                                                    EvPasswordDialog *dialog);
61 static void ev_password_dialog_entry_activated_cb (GtkEntry *entry,
62                                                    EvPasswordDialog *dialog);
63 static void ev_password_set_bad_password_label    (EvPasswordDialog *dialog,
64                                                    gchar     *message);
65 static void ev_password_search_in_keyring         (EvPasswordDialog *dialog, 
66                                                    const gchar *uri);
67
68 static void
69 ev_password_dialog_set_property (GObject      *object,
70                                  guint         prop_id,
71                                  const GValue *value,
72                                  GParamSpec   *pspec)
73 {
74         EvPasswordDialog *dialog = EV_PASSWORD_DIALOG (object);
75         char *format;
76         char *markup;
77         char *base_name;
78         char *file_name;
79
80         switch (prop_id)
81         {
82         case PROP_URI:
83                 dialog->priv->uri = g_strdup (g_value_get_string (value));
84
85                 file_name = gnome_vfs_format_uri_for_display (dialog->priv->uri);
86                 base_name = g_path_get_basename (file_name);
87                 format = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>\n\n%s",
88                                           _("Password required"),
89                                           _("The document ā€œ%sā€ is locked and requires a password before it can be opened."));
90                 markup = g_markup_printf_escaped (format, base_name);
91
92                 gtk_label_set_markup (GTK_LABEL (dialog->priv->label), markup);
93
94                 g_free (base_name);
95                 g_free (file_name);
96                 g_free (format);
97                 g_free (markup);
98
99                 ev_password_search_in_keyring (dialog, dialog->priv->uri);
100                 break;
101         default:
102                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
103                 break;
104         }
105 }
106
107 static void
108 ev_password_dialog_finalize (GObject *object)
109 {
110         EvPasswordDialog *dialog = EV_PASSWORD_DIALOG (object);
111
112         if (dialog->priv->uri) {
113                 g_free (dialog->priv->uri);
114                 dialog->priv->uri = NULL;
115         }
116
117         G_OBJECT_CLASS (ev_password_dialog_parent_class)->finalize (object);
118 }
119
120
121 static void
122 ev_password_dialog_class_init (EvPasswordDialogClass *class)
123 {
124         GObjectClass *g_object_class;
125         GtkWidgetClass *widget_class;
126
127         g_object_class = G_OBJECT_CLASS (class);
128         widget_class = GTK_WIDGET_CLASS (class);
129
130         g_type_class_add_private (g_object_class, sizeof (EvPasswordDialogPrivate));
131
132         g_object_class->set_property = ev_password_dialog_set_property;
133         g_object_class->finalize = ev_password_dialog_finalize;
134         
135         g_object_class_install_property (g_object_class,
136                                          PROP_URI,
137                                          g_param_spec_string ("uri",
138                                                               "Document URI",
139                                                               "Encrypted document URI",
140                                                               NULL,
141                                                               G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
142 }
143
144
145 static void
146 ev_password_dialog_init (EvPasswordDialog *dialog)
147 {
148         GtkWidget *hbox;
149         const char *glade_file = DATADIR "/evince-password.glade";
150         GladeXML *xml;
151
152         dialog->priv = EV_PASSWORD_DIALOG_GET_PRIVATE (dialog);
153                 
154         gtk_window_set_title (GTK_WINDOW (dialog), _("Enter password"));
155         gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
156         gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
157         gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
158         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 12);
159
160         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL,
161                                GTK_RESPONSE_CANCEL);
162         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK,
163                                GTK_RESPONSE_OK);
164
165         xml = glade_xml_new (glade_file, "hbox-contents", NULL);
166         g_assert (xml);
167         
168         hbox = glade_xml_get_widget (xml, "hbox-contents");
169         gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
170
171         dialog->priv->bad_label = glade_xml_get_widget (xml, "bad_password_label");
172         dialog->priv->check_default = glade_xml_get_widget (xml, "savesession_checkbutton");
173         dialog->priv->check_session = glade_xml_get_widget (xml, "savekeyring_checkbutton");
174         dialog->priv->entry = glade_xml_get_widget (xml, "password_entry");
175         dialog->priv->label = glade_xml_get_widget (xml, "password_label");
176
177         g_signal_connect (dialog->priv->entry, "changed", G_CALLBACK (ev_password_dialog_entry_changed_cb), dialog);
178         g_signal_connect (dialog->priv->entry, "activate", G_CALLBACK (ev_password_dialog_entry_activated_cb), dialog);
179
180         ev_password_set_bad_password_label (dialog, " ");
181
182         if (!gnome_keyring_is_available ()) {
183                 gtk_widget_hide (dialog->priv->check_default);
184                 gtk_widget_hide (dialog->priv->check_session);
185         }
186
187         g_object_unref (xml);
188 }
189
190 static void
191 ev_password_set_bad_password_label (EvPasswordDialog *dialog,
192                                     gchar     *message)
193 {
194         gchar *markup;
195
196         markup = g_strdup_printf ("<span color=\"red\" size=\"smaller\">%s</span>",
197                                   message);
198         gtk_label_set_markup (GTK_LABEL (dialog->priv->bad_label), markup);
199         g_free (markup);
200 }
201
202 static void
203 ev_password_dialog_entry_changed_cb (GtkEditable *editable,
204                                      EvPasswordDialog *dialog)
205 {
206         const char *text;
207
208         text = gtk_entry_get_text (GTK_ENTRY (editable));
209
210         if (text == NULL || *text == '\0')
211                 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 
212                                                    GTK_RESPONSE_OK, FALSE);
213         else
214                 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 
215                                                    GTK_RESPONSE_OK, TRUE);
216
217         ev_password_set_bad_password_label (dialog, " ");
218 }
219
220 static void
221 ev_password_dialog_entry_activated_cb (GtkEntry *entry,
222                                        EvPasswordDialog *dialog)
223 {
224         gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
225 }
226
227 #ifdef WITH_KEYRING
228 static void
229 ev_password_item_created_callback (GnomeKeyringResult result,
230                                    guint32            val,
231                                    gpointer           data)
232 {
233         /* Nothing yet */
234         return;
235 }
236 #endif
237
238 void
239 ev_password_dialog_save_password (EvPasswordDialog *dialog)
240 {
241 #ifdef WITH_KEYRING
242         GnomeKeyringAttributeList *attributes;
243         GnomeKeyringAttribute attribute;
244         gchar *name;
245         gchar *unescaped_uri;
246
247         attributes = gnome_keyring_attribute_list_new ();
248
249         attribute.name = g_strdup ("type");
250         attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
251         attribute.value.string = g_strdup ("document_password");
252         g_array_append_val (attributes, attribute);
253  
254         attribute.name = g_strdup ("uri");
255         attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
256         attribute.value.string = g_strdup (dialog->priv->uri);
257         g_array_append_val (attributes, attribute);
258         
259         unescaped_uri = gnome_vfs_unescape_string_for_display (dialog->priv->uri);
260         name = g_strdup_printf (_("Password for document %s"), unescaped_uri);  
261
262         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_default))) {
263                 gnome_keyring_item_create (NULL,
264                                            GNOME_KEYRING_ITEM_GENERIC_SECRET,
265                                            name,
266                                            attributes,
267                                            ev_password_dialog_get_password (dialog),
268                                            TRUE, ev_password_item_created_callback, 
269                                            NULL, NULL);
270         }
271
272         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_session))) {
273                 gnome_keyring_item_create ("session",
274                                            GNOME_KEYRING_ITEM_GENERIC_SECRET,
275                                            name,
276                                            attributes,
277                                            ev_password_dialog_get_password (dialog),
278                                            TRUE, ev_password_item_created_callback, 
279                                            NULL, NULL);
280         }
281         
282         gnome_keyring_attribute_list_free (attributes);
283         g_free (name);
284         g_free (unescaped_uri);
285
286 #endif /* WITH_KEYRING */
287         return;
288 }
289
290 #ifdef WITH_KEYRING
291 static void 
292 ev_password_keyring_found_cb (GnomeKeyringResult result,
293                               GList             *list,
294                               gpointer           data)
295
296 {
297         GnomeKeyringFound *found;
298         EvPasswordDialog *dialog = EV_PASSWORD_DIALOG (data);
299
300         if (result != GNOME_KEYRING_RESULT_OK || list == NULL) 
301                     return;
302
303         found = list->data;
304         gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), found->secret);
305 }                         
306 #endif /* WITH_KEYRING */
307
308 static void
309 ev_password_search_in_keyring (EvPasswordDialog *dialog, const gchar *uri)
310 {
311 #ifdef WITH_KEYRING
312         GnomeKeyringAttributeList *attributes;
313         GnomeKeyringAttribute attribute;
314         
315         attributes = gnome_keyring_attribute_list_new ();
316
317         attribute.name = g_strdup ("type");
318         attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
319         attribute.value.string = g_strdup ("document_password");
320         g_array_append_val (attributes, attribute);
321  
322         attribute.name = g_strdup ("uri");
323         attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
324         attribute.value.string = g_strdup (uri);
325         g_array_append_val (attributes, attribute);
326          
327         gnome_keyring_find_items  (GNOME_KEYRING_ITEM_GENERIC_SECRET,
328                                    attributes,
329                                    ev_password_keyring_found_cb,
330                                    g_object_ref (dialog),
331                                    g_object_unref);
332         gnome_keyring_attribute_list_free (attributes);
333 #endif /* WITH_KEYRING */
334         return;
335 }
336
337 char *
338 ev_password_dialog_get_password (EvPasswordDialog *dialog)
339 {
340         return g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry)));
341 }
342
343 void
344 ev_password_dialog_set_bad_pass (EvPasswordDialog *dialog)
345 {
346         gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), "");
347         ev_password_set_bad_password_label (dialog, _("Incorrect password"));
348 }
349
350