summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Wasilczyk <tomkiewicz@cpw.pidgin.im>2013-05-11 15:34:47 +0200
committerTomasz Wasilczyk <tomkiewicz@cpw.pidgin.im>2013-05-11 15:34:47 +0200
commit1a05dbdb9c87bcd7ba12597344ff10f5749fba54 (patch)
treec13fc1f814cb2ba6debf90d657622db042aea86d
parent9970d5f0b734126bf5442981a35e9e88be7c34a1 (diff)
downloadpidgin-1a05dbdb9c87bcd7ba12597344ff10f5749fba54.tar.gz
Initial support for keyring settings
-rw-r--r--libpurple/keyring.c134
-rw-r--r--libpurple/keyring.h55
-rw-r--r--libpurple/plugins/keyrings/internalkeyring.c29
-rw-r--r--libpurple/request.h2
-rw-r--r--pidgin/gtkprefs.c200
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)