diff options
author | Tomasz Wasilczyk <tomkiewicz@cpw.pidgin.im> | 2013-05-11 15:34:47 +0200 |
---|---|---|
committer | Tomasz Wasilczyk <tomkiewicz@cpw.pidgin.im> | 2013-05-11 15:34:47 +0200 |
commit | 1a05dbdb9c87bcd7ba12597344ff10f5749fba54 (patch) | |
tree | c13fc1f814cb2ba6debf90d657622db042aea86d | |
parent | 9970d5f0b734126bf5442981a35e9e88be7c34a1 (diff) | |
download | pidgin-1a05dbdb9c87bcd7ba12597344ff10f5749fba54.tar.gz |
Initial support for keyring settings
-rw-r--r-- | libpurple/keyring.c | 134 | ||||
-rw-r--r-- | libpurple/keyring.h | 55 | ||||
-rw-r--r-- | libpurple/plugins/keyrings/internalkeyring.c | 29 | ||||
-rw-r--r-- | libpurple/request.h | 2 | ||||
-rw-r--r-- | pidgin/gtkprefs.c | 200 |
5 files changed, 287 insertions, 133 deletions
diff --git a/libpurple/keyring.c b/libpurple/keyring.c index ebf6c48b0c..c78eeff64d 100644 --- a/libpurple/keyring.c +++ b/libpurple/keyring.c @@ -42,9 +42,10 @@ struct _PurpleKeyring PurpleKeyringSave save_password; PurpleKeyringCancelRequests cancel_requests; PurpleKeyringClose close_keyring; - PurpleKeyringChangeMaster change_master; PurpleKeyringImportPassword import_password; PurpleKeyringExportPassword export_password; + PurpleKeyringReadSettings read_settings; + PurpleKeyringApplySettings apply_settings; }; typedef struct @@ -896,60 +897,58 @@ purple_keyring_set_password(PurpleAccount *account, const gchar *password, save_cb(account, password, purple_keyring_set_password_save_cb, set_data); } -/* TODO: is it usable at all? */ -void -purple_keyring_change_master(PurpleKeyringChangeMasterCallback cb, - gpointer data) +PurpleRequestFields * +purple_keyring_read_settings(void) { - GError *error; PurpleKeyring *inuse; - PurpleKeyringChangeMaster change; + PurpleKeyringReadSettings read_settings; if (purple_keyring_is_quitting || current_change_tracker != NULL) { - purple_debug_error("keyring", "Cannot change a master password " - "at the moment.\n"); - if (cb == NULL) - return; - error = g_error_new(PURPLE_KEYRING_ERROR, - PURPLE_KEYRING_ERROR_INTERNAL, - "Cannot change a master password at the moment."); - cb(error, data); - g_error_free(error); - return; + purple_debug_error("keyring", "Cannot read settngs at the " + "moment.\n"); + return NULL; } inuse = purple_keyring_get_inuse(); if (inuse == NULL) { - purple_debug_error("keyring", "No keyring configured, cannot " - "change master password.\n"); - if (cb == NULL) - return; - error = g_error_new(PURPLE_KEYRING_ERROR, - PURPLE_KEYRING_ERROR_NOKEYRING, - "No keyring configured, cannot change master " - "password."); - cb(error, data); - g_error_free(error); - return; + purple_debug_error("keyring", "No keyring in use.\n"); + return NULL; } - change = purple_keyring_get_change_master(inuse); - if (change == NULL) { - purple_debug_error("keyring", "Keyring doesn't support master " - "passwords.\n"); - if (cb == NULL) - return; - error = g_error_new(PURPLE_KEYRING_ERROR, - PURPLE_KEYRING_ERROR_BACKENDFAIL, - "Keyring doesn't support master passwords."); - cb(error, data); - g_error_free(error); - return; + read_settings = purple_keyring_get_read_settings(inuse); + if (read_settings == NULL) + return NULL; + return read_settings(); +} + +gboolean +purple_keyring_apply_settings(PurpleRequestFields *fields) +{ + PurpleKeyring *inuse; + PurpleKeyringApplySettings apply_settings; + + g_return_val_if_fail(fields != NULL, FALSE); + + if (purple_keyring_is_quitting || current_change_tracker != NULL) { + purple_debug_error("keyring", "Cannot apply settngs at the " + "moment.\n"); + return FALSE; } - change(cb, data); -} + inuse = purple_keyring_get_inuse(); + if (inuse == NULL) { + purple_debug_error("keyring", "No keyring in use.\n"); + return FALSE; + } + apply_settings = purple_keyring_get_apply_settings(inuse); + if (apply_settings == NULL) { + purple_debug_warning("keyring", "Applying settings not " + "supported.\n"); + return FALSE; + } + return apply_settings(fields); +} /**************************************************************************/ /* PurpleKeyring accessors */ @@ -1019,14 +1018,6 @@ purple_keyring_get_close_keyring(const PurpleKeyring *keyring) return keyring->close_keyring; } -PurpleKeyringChangeMaster -purple_keyring_get_change_master(const PurpleKeyring *keyring) -{ - g_return_val_if_fail(keyring != NULL, NULL); - - return keyring->change_master; -} - PurpleKeyringImportPassword purple_keyring_get_import_password(const PurpleKeyring *keyring) { @@ -1043,6 +1034,22 @@ purple_keyring_get_export_password(const PurpleKeyring *keyring) return keyring->export_password; } +PurpleKeyringReadSettings +purple_keyring_get_read_settings(const PurpleKeyring *keyring) +{ + g_return_val_if_fail(keyring != NULL, NULL); + + return keyring->read_settings; +} + +PurpleKeyringApplySettings +purple_keyring_get_apply_settings(const PurpleKeyring *keyring) +{ + g_return_val_if_fail(keyring != NULL, NULL); + + return keyring->apply_settings; +} + void purple_keyring_set_name(PurpleKeyring *keyring, const gchar *name) { @@ -1102,15 +1109,6 @@ purple_keyring_set_close_keyring(PurpleKeyring *keyring, } void -purple_keyring_set_change_master(PurpleKeyring *keyring, - PurpleKeyringChangeMaster change_master) -{ - g_return_if_fail(keyring != NULL); - - keyring->change_master = change_master; -} - -void purple_keyring_set_import_password(PurpleKeyring *keyring, PurpleKeyringImportPassword import_password) { @@ -1128,6 +1126,24 @@ purple_keyring_set_export_password(PurpleKeyring *keyring, keyring->export_password = export_password; } +void +purple_keyring_set_read_settings(PurpleKeyring *keyring, +PurpleKeyringReadSettings read_settings) +{ + g_return_if_fail(keyring != NULL); + + keyring->read_settings = read_settings; +} + +void +purple_keyring_set_apply_settings(PurpleKeyring *keyring, +PurpleKeyringApplySettings apply_settings) +{ + g_return_if_fail(keyring != NULL); + + keyring->apply_settings = apply_settings; +} + /**************************************************************************/ /* Error Codes */ diff --git a/libpurple/keyring.h b/libpurple/keyring.h index ea1d8aed4d..1663345c3f 100644 --- a/libpurple/keyring.h +++ b/libpurple/keyring.h @@ -28,6 +28,7 @@ #define _PURPLE_KEYRING_H_ #include "account.h" +#include "request.h" /** * Default keyring ID. @@ -139,15 +140,6 @@ typedef void (*PurpleKeyringCancelRequests)(void); typedef void (*PurpleKeyringClose)(void); /** - * Change the master password for the keyring. - * - * @param cb A callback for once the master password has been changed. - * @param data Data to be passed to the callback. - */ -typedef void (*PurpleKeyringChangeMaster)(PurpleKeyringChangeMasterCallback cb, - gpointer data); - -/** * Import serialized (and maybe encrypted) password. * * This is not async because it is not meant to prompt for a master password and @@ -179,6 +171,12 @@ typedef gboolean (*PurpleKeyringExportPassword)(PurpleAccount *account, const gchar **mode, gchar **data, GError **error, GDestroyNotify *destroy); +/* TODO: documentation */ +typedef PurpleRequestFields * (*PurpleKeyringReadSettings)(void); + +/* TODO: documentation */ +typedef gboolean (*PurpleKeyringApplySettings)(PurpleRequestFields *fields); + /*@}*/ G_BEGIN_DECLS @@ -319,17 +317,13 @@ void purple_keyring_set_password(PurpleAccount *account, const gchar *password, PurpleKeyringSaveCallback cb, gpointer data); -/** - * Change the master password for a safe (if the safe supports it). - * - * @param cb A callback for once the master password has been changed. - * @param data Data to be passed to the callback. - * - * @todo Where is the master password string, that is being changed? - */ -void -purple_keyring_change_master(PurpleKeyringChangeMasterCallback cb, - gpointer data); +/* TODO: documentation */ +PurpleRequestFields * +purple_keyring_read_settings(void); + +/* TODO: documentation */ +gboolean +purple_keyring_apply_settings(PurpleRequestFields *fields); /*@}*/ @@ -382,15 +376,18 @@ purple_keyring_get_cancel_requests(const PurpleKeyring *keyring); PurpleKeyringClose purple_keyring_get_close_keyring(const PurpleKeyring *keyring); -PurpleKeyringChangeMaster -purple_keyring_get_change_master(const PurpleKeyring *keyring); - PurpleKeyringImportPassword purple_keyring_get_import_password(const PurpleKeyring *keyring); PurpleKeyringExportPassword purple_keyring_get_export_password(const PurpleKeyring *keyring); +PurpleKeyringReadSettings +purple_keyring_get_read_settings(const PurpleKeyring *keyring); + +PurpleKeyringApplySettings +purple_keyring_get_apply_settings(const PurpleKeyring *keyring); + /** * Sets friendly user name. * @@ -446,10 +443,6 @@ purple_keyring_set_close_keyring(PurpleKeyring *keyring, PurpleKeyringClose close_cb); void -purple_keyring_set_change_master(PurpleKeyring *keyring, - PurpleKeyringChangeMaster change_master); - -void purple_keyring_set_import_password(PurpleKeyring *keyring, PurpleKeyringImportPassword import_password); @@ -457,6 +450,14 @@ void purple_keyring_set_export_password(PurpleKeyring *keyring, PurpleKeyringExportPassword export_password); +void +purple_keyring_set_read_settings(PurpleKeyring *keyring, +PurpleKeyringReadSettings read_settings); + +void +purple_keyring_set_apply_settings(PurpleKeyring *keyring, +PurpleKeyringApplySettings apply_settings); + /*@}*/ /**************************************************************************/ diff --git a/libpurple/plugins/keyrings/internalkeyring.c b/libpurple/plugins/keyrings/internalkeyring.c index 24910d88c3..9bad7703a9 100644 --- a/libpurple/plugins/keyrings/internalkeyring.c +++ b/libpurple/plugins/keyrings/internalkeyring.c @@ -181,6 +181,31 @@ internal_keyring_export_password(PurpleAccount *account, const char **mode, } } +static PurpleRequestFields * +internal_keyring_read_settings(void) +{ + PurpleRequestFields *fields; + PurpleRequestFieldGroup *group; + PurpleRequestField *field; + + fields = purple_request_fields_new(); + group = purple_request_field_group_new(NULL); + purple_request_fields_add_group(fields, group); + + field = purple_request_field_bool_new("encrypt", "Use encryption", FALSE); + purple_request_field_group_add_field(group, field); + + /* TODO: master password setting */ + + return fields; +} + +static gboolean +internal_keyring_apply_settings(PurpleRequestFields *fields) +{ + return TRUE; +} + /***********************************************/ /* Plugin interface */ /***********************************************/ @@ -202,6 +227,10 @@ internal_keyring_load(PurplePlugin *plugin) internal_keyring_import_password); purple_keyring_set_export_password(keyring_handler, internal_keyring_export_password); + purple_keyring_set_read_settings(keyring_handler, + internal_keyring_read_settings); + purple_keyring_set_apply_settings(keyring_handler, + internal_keyring_apply_settings); purple_keyring_register(keyring_handler); diff --git a/libpurple/request.h b/libpurple/request.h index c9106b06ce..50685aa525 100644 --- a/libpurple/request.h +++ b/libpurple/request.h @@ -30,6 +30,8 @@ #include <glib-object.h> #include <glib.h> +#include "certificate.h" + /** * A request field. */ diff --git a/pidgin/gtkprefs.c b/pidgin/gtkprefs.c index 65dc931067..503734883e 100644 --- a/pidgin/gtkprefs.c +++ b/pidgin/gtkprefs.c @@ -112,7 +112,12 @@ static GtkWidget *prefs_status_themes_combo_box; static GtkWidget *prefs_smiley_themes_combo_box; /* Keyrings page */ -static gpointer keyring_page_pref_set_instance = NULL; +static GtkWidget *keyring_page_instance = NULL; +static GtkComboBox *keyring_combo = NULL; +static GtkBox *keyring_vbox = NULL; +static PurpleRequestFields *keyring_settings = NULL; +static GList *keyring_settings_fields = NULL; +static GtkWidget *keyring_apply = NULL; /* Sound theme specific */ static GtkWidget *sound_entry = NULL; @@ -520,6 +525,8 @@ pidgin_prefs_dropdown(GtkWidget *box, const gchar *title, PurplePrefType type, return dropdown; } +static void keyring_page_cleanup(void); + static void delete_prefs(GtkWidget *asdf, void *gdsa) { @@ -541,7 +548,7 @@ delete_prefs(GtkWidget *asdf, void *gdsa) prefs_status_themes_combo_box = NULL; prefs_smiley_themes_combo_box = NULL; - keyring_page_pref_set_instance = NULL; + keyring_page_cleanup(); sample_webview = NULL; @@ -2634,28 +2641,119 @@ logging_page(void) return ret; } +/*** keyring page *******************************************************/ + +static void +keyring_page_settings_toggled(GtkToggleButton *togglebutton, gpointer _unused) +{ + PurpleRequestField *setting; + + gtk_widget_set_sensitive(keyring_apply, TRUE); + + setting = g_object_get_data(G_OBJECT(togglebutton), "setting"); + purple_request_field_bool_set_value(setting, + gtk_toggle_button_get_active(togglebutton)); +} + +static GtkWidget * +keyring_page_add_settings_field(PurpleRequestField *setting) +{ + GtkWidget *widget, *hbox; + PurpleRequestFieldType field_type; + const gchar *label; + + label = purple_request_field_get_label(setting); + + field_type = purple_request_field_get_type(setting); + if (field_type == PURPLE_REQUEST_FIELD_BOOLEAN) { + widget = gtk_check_button_new_with_label(label); + label = NULL; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), + purple_request_field_bool_get_default_value(setting)); + g_signal_connect(G_OBJECT(widget), "toggled", + G_CALLBACK(keyring_page_settings_toggled), NULL); + } else { + purple_debug_error("gtkprefs", "Unsupported field type\n"); + return NULL; + } + + g_object_set_data(G_OBJECT(widget), "setting", setting); + hbox = pidgin_add_widget_to_vbox(keyring_vbox, label, NULL, widget, + FALSE, NULL); + return ((void*)hbox == (void*)keyring_vbox) ? widget : hbox; +} + +/* XXX: it could be available for all plugins, not keyrings only */ +static GList * +keyring_page_add_settings(PurpleRequestFields *settings) +{ + GList *it, *groups, *added_fields; + + added_fields = NULL; + + groups = purple_request_fields_get_groups(settings); + for (it = g_list_first(groups); it != NULL; it = g_list_next(it)) { + GList *it2, *fields; + + fields = purple_request_field_group_get_fields(it->data); + for (it2 = g_list_first(fields); it2 != NULL; + it2 = g_list_next(it2)) { + GtkWidget *added = keyring_page_add_settings_field( + it2->data); + if (added == NULL) + continue; + added_fields = g_list_prepend(added_fields, added); + } + } + + return added_fields; +} + +static void +keyring_page_settings_apply(GtkButton *button, gpointer _unused) +{ + if (!purple_keyring_apply_settings(keyring_settings)) + return; + + gtk_widget_set_sensitive(keyring_apply, FALSE); +} + static void -change_master_password_cb(GtkWidget *button, gpointer ptr) +keyring_page_update_settings() { - purple_keyring_change_master(NULL, NULL); + if (keyring_settings != NULL) + purple_request_fields_destroy(keyring_settings); + keyring_settings = purple_keyring_read_settings(); + if (!keyring_settings) + return; + + keyring_settings_fields = keyring_page_add_settings(keyring_settings); + + keyring_apply = gtk_button_new_with_mnemonic(_("_Apply")); + gtk_box_pack_start(keyring_vbox, keyring_apply, FALSE, FALSE, 1); + gtk_widget_set_sensitive(keyring_apply, FALSE); + keyring_settings_fields = g_list_prepend(keyring_settings_fields, + keyring_apply); + g_signal_connect(G_OBJECT(keyring_apply), "clicked", + G_CALLBACK(keyring_page_settings_apply), NULL); + + gtk_widget_show_all(keyring_page_instance); } static void -keyring_page_pref_set_inuse(GError *error, gpointer _combo_box) +keyring_page_pref_set_inuse(GError *error, gpointer _keyring_page_instance) { - GtkComboBox *combo_box = _combo_box; PurpleKeyring *in_use = purple_keyring_get_inuse(); - if (keyring_page_pref_set_instance != combo_box) { + if (_keyring_page_instance != keyring_page_instance) { purple_debug_info("gtkprefs", "pref window already closed\n"); return; } - keyring_page_pref_set_instance = NULL; - gtk_widget_set_sensitive(GTK_WIDGET(combo_box), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(keyring_combo), TRUE); if (error != NULL) { - pidgin_prefs_dropdown_revert_active(combo_box); + pidgin_prefs_dropdown_revert_active(keyring_combo); purple_notify_error(NULL, _("Keyring"), _("Failed to set new keyring"), error->message); return; @@ -2664,6 +2762,8 @@ keyring_page_pref_set_inuse(GError *error, gpointer _combo_box) g_return_if_fail(in_use != NULL); purple_prefs_set_string("/purple/keyring/active", purple_keyring_get_id(in_use)); + + keyring_page_update_settings(); } static void @@ -2671,18 +2771,15 @@ keyring_page_pref_changed(GtkComboBox *combo_box, PidginPrefValue value) { const char *keyring_id; PurpleKeyring *keyring; - GtkWidget *change_master_button; + GList *it; g_return_if_fail(combo_box != NULL); g_return_if_fail(value.type == PURPLE_PREF_STRING); - change_master_button = g_object_get_data(G_OBJECT(combo_box), - "change_master_button"); - keyring_id = value.value.string; keyring = purple_keyring_find_keyring_by_id(keyring_id); if (keyring == NULL) { - pidgin_prefs_dropdown_revert_active(combo_box); + pidgin_prefs_dropdown_revert_active(keyring_combo); purple_notify_error(NULL, _("Keyring"), _("Selected keyring is disabled"), NULL); return; @@ -2690,60 +2787,69 @@ keyring_page_pref_changed(GtkComboBox *combo_box, PidginPrefValue value) gtk_widget_set_sensitive(GTK_WIDGET(combo_box), FALSE); - keyring_page_pref_set_instance = combo_box; + for (it = keyring_settings_fields; it != NULL; it = g_list_next(it)) + { + GtkWidget *widget = it->data; + gtk_container_remove( + GTK_CONTAINER(gtk_widget_get_parent(widget)), widget); + } + g_list_free(keyring_settings_fields); + keyring_settings_fields = NULL; + if (keyring_settings) + purple_request_fields_destroy(keyring_settings); + keyring_settings = NULL; + purple_keyring_set_inuse(keyring, FALSE, keyring_page_pref_set_inuse, - combo_box); + keyring_page_instance); +} - if (purple_keyring_get_change_master(keyring)) - gtk_widget_set_sensitive(change_master_button, TRUE); - else - gtk_widget_set_sensitive(change_master_button, FALSE); +static void +keyring_page_cleanup(void) +{ + keyring_page_instance = NULL; + keyring_combo = NULL; + keyring_vbox = NULL; + g_list_free(keyring_settings_fields); + keyring_settings_fields = NULL; + if (keyring_settings) + purple_request_fields_destroy(keyring_settings); + keyring_settings = NULL; + keyring_apply = NULL; } static GtkWidget * keyring_page(void) { - GtkWidget *ret; - GtkWidget *vbox; - GtkWidget *button; GList *names; - const char *keyring_id; - PurpleKeyring *keyring; PidginPrefValue initial; - GtkComboBox *dropdown = NULL; - keyring_id = purple_prefs_get_string("/purple/keyring/active"); - keyring = purple_keyring_find_keyring_by_id(keyring_id); + g_return_val_if_fail(keyring_page_instance == NULL, + keyring_page_instance); - ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE); - gtk_container_set_border_width(GTK_CONTAINER (ret), PIDGIN_HIG_BORDER); - - /* Change master password */ - button = gtk_button_new_with_mnemonic(_("_Change master password.")); + keyring_page_instance = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE); + gtk_container_set_border_width(GTK_CONTAINER(keyring_page_instance), + PIDGIN_HIG_BORDER); /* Keyring selection */ - vbox = pidgin_make_frame(ret, _("Keyring")); + keyring_vbox = GTK_BOX(pidgin_make_frame(keyring_page_instance, + _("Keyring"))); names = purple_keyring_get_options(); initial.type = PURPLE_PREF_STRING; initial.value.string = purple_prefs_get_string("/purple/keyring/active"); - pidgin_prefs_dropdown_from_list_with_cb(vbox, _("Keyring:"), &dropdown, - names, initial, keyring_page_pref_changed); - g_object_set_data(G_OBJECT(dropdown), "change_master_button", button); + pidgin_prefs_dropdown_from_list_with_cb(GTK_WIDGET(keyring_vbox), + _("Keyring:"), &keyring_combo, names, initial, + keyring_page_pref_changed); g_list_free(names); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(change_master_password_cb), NULL); + keyring_page_update_settings(); - if (keyring && purple_keyring_get_change_master(keyring)) - gtk_widget_set_sensitive(button, TRUE); - else - gtk_widget_set_sensitive(button, FALSE); + gtk_widget_show_all(keyring_page_instance); - gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 1); - gtk_widget_show_all(ret); - - return ret; + return keyring_page_instance; } +/*** keyring page - end *************************************************/ + #ifndef _WIN32 static gint sound_cmd_yeah(GtkEntry *entry, gpointer d) |