4
* Copyright (C) 2006 Stefan Walter
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
* See the GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the
17
* Free Software Foundation, Inc.,
18
* 59 Temple Place, Suite 330,
19
* Boston, MA 02111-1307, USA.
24
#include "seahorse-key-widget.h"
25
#include "seahorse-util.h"
26
#include "seahorse-key.h"
27
#include "seahorse-gkeyring-item.h"
28
#include "seahorse-gkeyring-source.h"
29
#include "seahorse-gkeyring-operation.h"
30
#include "seahorse-gtkstock.h"
31
#include "seahorse-secure-memory.h"
32
#include "seahorse-secure-entry.h"
34
/* -----------------------------------------------------------------------------
39
load_password (SeahorseWidget *swidget, SeahorseGKeyringItem *git)
41
SeahorseSecureEntry *entry;
44
entry = SEAHORSE_SECURE_ENTRY (g_object_get_data (G_OBJECT (swidget),
45
"secure-password-entry"));
48
/* Retrieve initial password. Try to keep it safe */
49
WITH_SECURE_MEM ((secret = gnome_keyring_item_info_get_secret (git->info)));
50
seahorse_secure_entry_set_text (entry, secret ? secret : "");
53
seahorse_secure_entry_reset_changed (entry);
58
do_main (SeahorseWidget *swidget)
61
SeahorseGKeyringItem *git;
65
gboolean network = FALSE;
67
key = SEAHORSE_KEY_WIDGET (swidget)->skey;
68
git = SEAHORSE_GKEYRING_ITEM (key);
71
widget = seahorse_widget_get_widget (swidget, "key-image");
73
gtk_image_set_from_stock (GTK_IMAGE (widget), seahorse_key_get_stock_id (key),
74
GTK_ICON_SIZE_DIALOG);
77
widget = seahorse_widget_get_widget (swidget, "description-field");
79
text = seahorse_gkeyring_item_get_description (git);
80
gtk_entry_set_text (GTK_ENTRY (widget), text ? text : "");
85
text = seahorse_key_get_display_name (key);
86
widget = seahorse_widget_get_top (swidget);
87
gtk_window_set_title (GTK_WINDOW (widget), text);
91
switch (seahorse_gkeyring_item_get_use (git)) {
92
case SEAHORSE_GKEYRING_USE_NETWORK:
93
label = _("Access a network share or resource");
96
case SEAHORSE_GKEYRING_USE_WEB:
97
label = _("Access a website");
100
case SEAHORSE_GKEYRING_USE_PGP:
101
label = _("Unlocks a PGP key");
103
case SEAHORSE_GKEYRING_USE_SSH:
104
label = _("Unlocks a Secure Shell key");
106
case SEAHORSE_GKEYRING_USE_OTHER:
107
label = _("Saved password or login");
111
widget = seahorse_widget_get_widget (swidget, "use-field");
113
gtk_label_set_text (GTK_LABEL (widget), label);
116
widget = seahorse_widget_get_widget (swidget, "type-field");
118
gtk_label_set_text (GTK_LABEL (widget),
119
network ? _("Network Credentials") : _("Password"));
122
seahorse_widget_set_visible (swidget, "server-label", network);
123
seahorse_widget_set_visible (swidget, "server-field", network);
124
seahorse_widget_set_visible (swidget, "login-label", network);
125
seahorse_widget_set_visible (swidget, "login-field", network);
128
label = seahorse_gkeyring_item_get_attribute (git, "server");
129
widget = seahorse_widget_get_widget (swidget, "server-field");
131
gtk_label_set_text (GTK_LABEL (widget), label);
133
label = seahorse_gkeyring_item_get_attribute (git, "user");
134
widget = seahorse_widget_get_widget (swidget, "login-field");
136
gtk_label_set_text (GTK_LABEL (widget), label);
139
load_password (swidget, git);
143
password_activate (SeahorseSecureEntry *entry, SeahorseWidget *swidget)
146
SeahorseGKeyringItem *git;
147
SeahorseOperation *op;
148
GnomeKeyringItemInfo *info;
152
key = SEAHORSE_KEY_WIDGET (swidget)->skey;
153
git = SEAHORSE_GKEYRING_ITEM (key);
155
widget = seahorse_widget_get_widget (swidget, "password-expander");
156
g_return_if_fail (widget);
157
if (!gtk_expander_get_expanded (GTK_EXPANDER (widget)))
160
entry = SEAHORSE_SECURE_ENTRY (g_object_get_data (G_OBJECT (swidget),
161
"secure-password-entry"));
162
if (!entry || !seahorse_secure_entry_get_changed (entry))
165
/* Setup for saving */
166
WITH_SECURE_MEM (info = gnome_keyring_item_info_copy (git->info));
167
WITH_SECURE_MEM (gnome_keyring_item_info_set_secret (info,
168
seahorse_secure_entry_get_text (entry)));
170
gtk_widget_set_sensitive (GTK_WIDGET (entry), FALSE);
172
op = seahorse_gkeyring_operation_update_info (git, info);
173
gnome_keyring_item_info_free (info);
175
/* This is usually a quick operation */
176
seahorse_operation_wait (op);
178
if (!seahorse_operation_is_successful (op)) {
179
seahorse_operation_copy_error (op, &err);
180
seahorse_util_handle_error (err, _("Couldn't change password."));
181
load_password (swidget, git);
184
gtk_widget_set_sensitive (GTK_WIDGET (entry), TRUE);
188
password_focus_out (SeahorseSecureEntry* entry, GdkEventFocus *event, SeahorseWidget *swidget)
190
password_activate (entry, swidget);
195
show_password_toggled (GtkToggleButton *button, SeahorseWidget *swidget)
199
widget = GTK_WIDGET (g_object_get_data (G_OBJECT (swidget), "secure-password-entry"));
203
seahorse_secure_entry_set_visibility (SEAHORSE_SECURE_ENTRY (widget),
204
gtk_toggle_button_get_active (button));
208
password_expander_activate (GtkExpander *expander, SeahorseWidget *swidget)
211
SeahorseGKeyringItem *git;
215
key = SEAHORSE_KEY_WIDGET (swidget)->skey;
216
git = SEAHORSE_GKEYRING_ITEM (key);
218
if (!gtk_expander_get_expanded (expander))
222
* TODO: Once gnome-keyring-daemon has support for not reading
223
* the secret, then we'd retrieve the secret when the password
227
widget = GTK_WIDGET (g_object_get_data (G_OBJECT (swidget), "secure-password-entry"));
229
widget = seahorse_secure_entry_new ();
231
box = seahorse_widget_get_widget (swidget, "password-box-area");
232
g_return_if_fail (box != NULL);
233
gtk_container_add (GTK_CONTAINER (box), widget);
234
g_object_set_data (G_OBJECT (swidget), "secure-password-entry", widget);
235
gtk_widget_show (widget);
237
/* Retrieve initial password */
238
load_password (swidget, git);
240
/* Now watch for changes in the password */
241
g_signal_connect (widget, "activate", G_CALLBACK (password_activate), swidget);
242
g_signal_connect (widget, "focus-out-event", G_CALLBACK (password_focus_out), swidget);
245
/* Always have a hidden password when opening box */
246
widget = seahorse_widget_get_widget (swidget, "show-password-check");
247
g_return_if_fail (widget != NULL);
248
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
252
description_activate (GtkWidget *entry, SeahorseWidget *swidget)
255
SeahorseGKeyringItem *git;
256
SeahorseOperation *op;
257
GnomeKeyringItemInfo *info;
262
key = SEAHORSE_KEY_WIDGET (swidget)->skey;
263
git = SEAHORSE_GKEYRING_ITEM (key);
265
text = gtk_entry_get_text (GTK_ENTRY (entry));
266
original = seahorse_gkeyring_item_get_description (git);
268
/* Make sure not the same */
269
if (text == original || g_utf8_collate (text, original ? original : "") == 0) {
274
gtk_widget_set_sensitive (entry, FALSE);
276
WITH_SECURE_MEM (info = gnome_keyring_item_info_copy (git->info));
277
gnome_keyring_item_info_set_display_name (info, text);
279
op = seahorse_gkeyring_operation_update_info (git, info);
280
gnome_keyring_item_info_free (info);
282
/* This is usually a quick operation */
283
seahorse_operation_wait (op);
285
if (!seahorse_operation_is_successful (op)) {
286
seahorse_operation_copy_error (op, &err);
287
seahorse_util_handle_error (err, _("Couldn't set description."));
288
gtk_entry_set_text (GTK_ENTRY (entry), original);
291
gtk_widget_set_sensitive (entry, TRUE);
297
description_focus_out (GtkWidget* widget, GdkEventFocus *event, SeahorseWidget *swidget)
299
description_activate (widget, swidget);
303
/* -----------------------------------------------------------------------------
308
do_details (SeahorseWidget *swidget)
311
SeahorseGKeyringItem *git;
316
key = SEAHORSE_KEY_WIDGET (swidget)->skey;
317
git = SEAHORSE_GKEYRING_ITEM (key);
319
details = g_string_new (NULL);
321
g_string_append_printf (details, "<b>identifier</b>: %u\n", git->item_id);
323
/* Build up the display string */
324
if (git->attributes) {
325
for(i = 0; i < git->attributes->len; ++i) {
326
GnomeKeyringAttribute *attr = &(gnome_keyring_attribute_list_index (git->attributes, i));
327
g_string_append_printf (details, "<b>%s</b>: ", attr->name);
328
switch (attr->type) {
329
case GNOME_KEYRING_ATTRIBUTE_TYPE_STRING:
330
g_string_append_printf (details, "%s\n", attr->value.string);
332
case GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32:
333
g_string_append_printf (details, "%u\n", attr->value.integer);
336
g_string_append (details, "<i>[invalid]</i>\n");
342
widget = seahorse_widget_get_widget (swidget, "details-box");
343
g_return_if_fail (widget != NULL);
344
gtk_label_set_markup (GTK_LABEL (widget), details->str);
346
g_string_free (details, TRUE);
349
/* -----------------------------------------------------------------------------
354
selected_application_index (SeahorseWidget *swidget)
359
GtkTreeSelection *selection;
364
tree = GTK_TREE_VIEW (seahorse_widget_get_widget (swidget, "application-list"));
365
g_return_val_if_fail (GTK_IS_TREE_VIEW (tree), -1);
367
selection = gtk_tree_view_get_selection (tree);
368
if (!gtk_tree_selection_get_selected (selection, &model, &iter))
371
path = gtk_tree_model_get_path (model, &iter);
372
g_return_val_if_fail (path, -1);
374
indices = gtk_tree_path_get_indices (path);
375
g_return_val_if_fail (indices, -1);
378
gtk_tree_path_free (path);
384
update_application_details (SeahorseWidget *swidget)
387
SeahorseGKeyringItem *git;
388
GnomeKeyringAccessControl *ac;
390
GtkToggleButton *toggle;
391
GnomeKeyringAccessType access;
395
key = SEAHORSE_KEY_WIDGET (swidget)->skey;
396
git = SEAHORSE_GKEYRING_ITEM (key);
398
index = selected_application_index (swidget);
402
ac = (GnomeKeyringAccessControl*)g_list_nth_data (git->acl, index);
403
g_return_if_fail (ac);
406
seahorse_widget_set_sensitive (swidget, "application-details", ac != NULL);
408
label = GTK_LABEL (seahorse_widget_get_widget (swidget, "application-path"));
409
g_return_if_fail (GTK_IS_LABEL (label));
410
path = ac ? gnome_keyring_item_ac_get_path_name (ac) : NULL;
411
gtk_label_set_text (label, path ? path : "");
414
g_object_set_data (G_OBJECT (swidget), "updating", "updating");
415
access = ac ? gnome_keyring_item_ac_get_access_type (ac) : 0;
417
toggle = GTK_TOGGLE_BUTTON (seahorse_widget_get_widget (swidget, "application-read"));
418
g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle));
419
gtk_toggle_button_set_active (toggle, access & GNOME_KEYRING_ACCESS_READ);
421
toggle = GTK_TOGGLE_BUTTON (seahorse_widget_get_widget (swidget, "application-write"));
422
g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle));
423
gtk_toggle_button_set_active (toggle, access & GNOME_KEYRING_ACCESS_WRITE);
425
toggle = GTK_TOGGLE_BUTTON (seahorse_widget_get_widget (swidget, "application-delete"));
426
g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle));
427
gtk_toggle_button_set_active (toggle, access & GNOME_KEYRING_ACCESS_REMOVE);
429
g_object_set_data (G_OBJECT (swidget), "updating", NULL);
433
application_selection_changed (GtkTreeSelection *selection, SeahorseWidget *swidget)
435
update_application_details (swidget);
439
merge_toggle_button_access (SeahorseWidget *swidget, const gchar *identifier,
440
GnomeKeyringAccessType *access, GnomeKeyringAccessType type)
442
GtkToggleButton *toggle;
444
toggle = GTK_TOGGLE_BUTTON (seahorse_widget_get_widget (swidget, identifier));
445
g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle));
446
if (gtk_toggle_button_get_active (toggle))
453
application_access_toggled (GtkCheckButton *check, SeahorseWidget *swidget)
456
SeahorseGKeyringItem *git;
457
SeahorseOperation *op;
458
GnomeKeyringAccessType access;
459
GnomeKeyringAccessControl *ac;
464
/* Just us setting up the controls, not the user */
465
if (g_object_get_data (G_OBJECT (swidget), "updating"))
468
key = SEAHORSE_KEY_WIDGET (swidget)->skey;
469
git = SEAHORSE_GKEYRING_ITEM (key);
471
index = selected_application_index (swidget);
472
g_return_if_fail (index >= 0);
474
acl = gnome_keyring_acl_copy (git->acl);
475
ac = (GnomeKeyringAccessControl*)g_list_nth_data (acl, index);
476
g_return_if_fail (ac);
478
access = gnome_keyring_item_ac_get_access_type (ac);
480
merge_toggle_button_access (swidget, "application-read", &access, GNOME_KEYRING_ACCESS_READ);
481
merge_toggle_button_access (swidget, "application-write", &access, GNOME_KEYRING_ACCESS_WRITE);
482
merge_toggle_button_access (swidget, "application-delete", &access, GNOME_KEYRING_ACCESS_REMOVE);
484
if (access != gnome_keyring_item_ac_get_access_type (ac)) {
486
gnome_keyring_item_ac_set_access_type (ac, access);
488
seahorse_widget_set_sensitive (swidget, "application-details", FALSE);
490
op = seahorse_gkeyring_operation_update_acl (git, acl);
491
g_return_if_fail (op);
493
seahorse_operation_wait (op);
494
if (!seahorse_operation_is_successful (op)) {
495
seahorse_operation_copy_error (op, &err);
496
seahorse_util_handle_error (err, _("Couldn't set application access."));
497
update_application_details (swidget);
500
seahorse_widget_set_sensitive (swidget, "application-details", TRUE);
503
gnome_keyring_acl_free (acl);
507
do_application (SeahorseWidget *swidget)
510
SeahorseGKeyringItem *git;
515
GtkCellRenderer *renderer;
516
GnomeKeyringAccessControl *ac;
517
GtkTreeViewColumn *column;
522
key = SEAHORSE_KEY_WIDGET (swidget)->skey;
523
git = SEAHORSE_GKEYRING_ITEM (key);
525
tree = GTK_TREE_VIEW (seahorse_widget_get_widget (swidget, "application-list"));
526
g_return_if_fail (tree);
528
model = gtk_tree_view_get_model (tree);
530
store = gtk_list_store_new (1, GTK_TYPE_STRING);
531
model = GTK_TREE_MODEL (store);
532
gtk_tree_view_set_model (tree, model);
534
renderer = gtk_cell_renderer_text_new ();
535
column = gtk_tree_view_column_new_with_attributes ("name", renderer, "text", 0, NULL);
536
gtk_tree_view_append_column (tree, column);
538
store = GTK_LIST_STORE (model);
543
/* Fill in the tree store, replacing any rows already present */
544
valid = gtk_tree_model_get_iter_first (model, &iter);
545
for ( ; acl; acl = g_list_next (acl)) {
547
ac = (GnomeKeyringAccessControl*)acl->data;
548
g_return_if_fail (ac);
551
gtk_list_store_append (store, &iter);
553
display = gnome_keyring_item_ac_get_display_name (ac);
554
gtk_list_store_set (store, &iter, 0, display ? display : "", -1);
558
valid = gtk_tree_model_iter_next (model, &iter);
561
/* Remove all the remaining rows */
563
valid = gtk_list_store_remove (store, &iter);
565
update_application_details (swidget);
568
/* -----------------------------------------------------------------------------
573
key_changed (SeahorseKey *skey, SeahorseKeyChange change, SeahorseWidget *swidget)
576
do_details (swidget);
577
do_application (swidget);
581
key_destroyed (GtkObject *object, SeahorseWidget *swidget)
583
seahorse_widget_destroy (swidget);
587
properties_destroyed (GtkObject *object, SeahorseWidget *swidget)
589
g_signal_handlers_disconnect_by_func (SEAHORSE_KEY_WIDGET (swidget)->skey,
590
key_changed, swidget);
591
g_signal_handlers_disconnect_by_func (SEAHORSE_KEY_WIDGET (swidget)->skey,
592
key_destroyed, swidget);
596
properties_response (GtkDialog *dialog, int response, SeahorseWidget *swidget)
598
if (response == GTK_RESPONSE_HELP) {
599
seahorse_widget_show_help(swidget);
603
seahorse_widget_destroy (swidget);
607
seahorse_gkeyring_item_properties_new (SeahorseGKeyringItem *git, GtkWindow *parent)
609
SeahorseKey *key = SEAHORSE_KEY (git);
610
SeahorseKeySource *sksrc;
611
SeahorseWidget *swidget = NULL;
614
swidget = seahorse_key_widget_new ("gkeyring-item-properties",
618
/* This happens if the window is already open */
622
/* This causes the key source to get any specific info about the key */
623
if (seahorse_key_get_loaded (key) < SKEY_INFO_COMPLETE) {
624
sksrc = seahorse_key_get_source (key);
625
seahorse_key_source_load_async (sksrc, seahorse_key_get_keyid (key));
628
widget = glade_xml_get_widget (swidget->xml, swidget->name);
629
g_signal_connect (widget, "response", G_CALLBACK (properties_response), swidget);
630
g_signal_connect (GTK_OBJECT (widget), "destroy", G_CALLBACK (properties_destroyed), swidget);
631
g_signal_connect_after (git, "changed", G_CALLBACK (key_changed), swidget);
632
g_signal_connect_after (git, "destroy", G_CALLBACK (key_destroyed), swidget);
635
* The signals don't need to keep getting connected. Everytime a key changes the
636
* do_* functions get called. Therefore, seperate functions connect the signals
641
do_details (swidget);
642
do_application (swidget);
644
widget = seahorse_widget_get_widget (swidget, "password-expander");
645
g_return_if_fail (widget);
646
g_signal_connect_after (widget, "activate", G_CALLBACK (password_expander_activate), swidget);
648
glade_xml_signal_connect_data (swidget->xml, "show_password_toggled",
649
G_CALLBACK (show_password_toggled), swidget);
651
widget = seahorse_widget_get_widget (swidget, "description-field");
652
g_return_if_fail (widget != NULL);
653
g_signal_connect (widget, "activate", G_CALLBACK (description_activate), swidget);
654
g_signal_connect (widget, "focus-out-event", G_CALLBACK (description_focus_out), swidget);
656
glade_xml_signal_connect_data (swidget->xml, "application_access_toggled",
657
G_CALLBACK (application_access_toggled), swidget);
659
widget = seahorse_widget_get_widget (swidget, "application-list");
660
g_return_if_fail (GTK_IS_TREE_VIEW (widget));
662
g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)), "changed",
663
G_CALLBACK (application_selection_changed), swidget);