* Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA /* TODO: This should use PurpleValues? */ /* 'generic' is kind of ugly. We use it as an elegant way to refer to the value of this pref when calling callback functions. We could use 'boolean' or 'integer' or any other field... but it feels mildly cleaner to use a gpointer. Maybe it would be best to use a struct purple_pref *parent; struct purple_pref *sibling; struct purple_pref *first_child; static struct purple_pref prefs = { static GHashTable *prefs_hash = NULL; static guint save_timer = 0; static gboolean prefs_loaded = FALSE; /********************************************************************* * Private utility functions * *********************************************************************/ purple_pref *find_pref(const char *name) g_return_val_if_fail(name != NULL && name[0] == '/', NULL); /* When we're initializing, the debug system is * initialized before the prefs system, but debug * calls will end up calling prefs functions, so we * need to deal cleanly here. */ return g_hash_table_lookup(prefs_hash, name); /********************************************************************* *********************************************************************/ * This function recursively creates the PurpleXmlNode tree from the prefs * tree structure. Yay recursion! pref_to_xmlnode(PurpleXmlNode *parent, struct purple_pref *pref) PurpleXmlNode *node, *childnode; struct purple_pref *child; node = purple_xmlnode_new_child(parent, "pref"); purple_xmlnode_set_attrib(node, "name", pref->name); /* Set the type of this node (if type == PURPLE_PREF_NONE then do nothing) */ if (pref->type == PURPLE_PREF_INT) { purple_xmlnode_set_attrib(node, "type", "int"); g_snprintf(buf, sizeof(buf), "%d", pref->value.integer); purple_xmlnode_set_attrib(node, "value", buf); else if (pref->type == PURPLE_PREF_STRING) { purple_xmlnode_set_attrib(node, "type", "string"); purple_xmlnode_set_attrib(node, "value", pref->value.string ? pref->value.string : ""); else if (pref->type == PURPLE_PREF_STRING_LIST) { purple_xmlnode_set_attrib(node, "type", "stringlist"); for (cur = pref->value.stringlist; cur != NULL; cur = cur->next) childnode = purple_xmlnode_new_child(node, "item"); purple_xmlnode_set_attrib(childnode, "value", cur->data ? cur->data : ""); else if (pref->type == PURPLE_PREF_PATH) { char *encoded = g_filename_to_utf8(pref->value.string ? pref->value.string : "", -1, NULL, NULL, NULL); purple_xmlnode_set_attrib(node, "type", "path"); purple_xmlnode_set_attrib(node, "value", encoded); else if (pref->type == PURPLE_PREF_PATH_LIST) { purple_xmlnode_set_attrib(node, "type", "pathlist"); for (cur = pref->value.stringlist; cur != NULL; cur = cur->next) char *encoded = g_filename_to_utf8(cur->data ? cur->data : "", -1, NULL, NULL, NULL); childnode = purple_xmlnode_new_child(node, "item"); purple_xmlnode_set_attrib(childnode, "value", encoded); else if (pref->type == PURPLE_PREF_BOOLEAN) { purple_xmlnode_set_attrib(node, "type", "bool"); g_snprintf(buf, sizeof(buf), "%d", pref->value.boolean); purple_xmlnode_set_attrib(node, "value", buf); for (child = pref->first_child; child != NULL; child = child->sibling) pref_to_xmlnode(node, child); struct purple_pref *pref, *child; /* Create the root preference node */ node = purple_xmlnode_new("pref"); purple_xmlnode_set_attrib(node, "version", "1"); purple_xmlnode_set_attrib(node, "name", "/"); for (child = pref->first_child; child != NULL; child = child->sibling) pref_to_xmlnode(node, child); * TODO: Call schedule_prefs_save()? Ideally we wouldn't need to. * (prefs.xml should be loaded when purple_prefs_init is called) purple_debug_error("prefs", "Attempted to save prefs before " node = prefs_to_xmlnode(); data = purple_xmlnode_to_formatted_str(node, NULL); purple_util_write_data_to_file("prefs.xml", data, -1); purple_xmlnode_free(node); schedule_prefs_save(void) save_timer = purple_timeout_add_seconds(5, save_cb, NULL); /********************************************************************* *********************************************************************/ static GList *prefs_stack = NULL; prefs_start_element_handler (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, PurplePrefType pref_type = PURPLE_PREF_NONE; const char *pref_name = NULL, *pref_value = NULL; if(!purple_strequal(element_name, "pref") && !purple_strequal(element_name, "item")) for(i = 0; attribute_names[i]; i++) { if(purple_strequal(attribute_names[i], "name")) { pref_name = attribute_values[i]; } else if(purple_strequal(attribute_names[i], "type")) { if(purple_strequal(attribute_values[i], "bool")) pref_type = PURPLE_PREF_BOOLEAN; else if(purple_strequal(attribute_values[i], "int")) pref_type = PURPLE_PREF_INT; else if(purple_strequal(attribute_values[i], "string")) pref_type = PURPLE_PREF_STRING; else if(purple_strequal(attribute_values[i], "stringlist")) pref_type = PURPLE_PREF_STRING_LIST; else if(purple_strequal(attribute_values[i], "path")) pref_type = PURPLE_PREF_PATH; else if(purple_strequal(attribute_values[i], "pathlist")) pref_type = PURPLE_PREF_PATH_LIST; } else if(purple_strequal(attribute_names[i], "value")) { pref_value = attribute_values[i]; if ((pref_type == PURPLE_PREF_BOOLEAN || pref_type == PURPLE_PREF_INT) && /* Missing a value attribute */ if(purple_strequal(element_name, "item")) { struct purple_pref *pref; pref_name_full = g_string_new(""); for(tmp = prefs_stack; tmp; tmp = tmp->next) { pref_name_full = g_string_prepend(pref_name_full, tmp->data); pref_name_full = g_string_prepend_c(pref_name_full, '/'); pref = find_pref(pref_name_full->str); if(pref->type == PURPLE_PREF_STRING_LIST) { pref->value.stringlist = g_list_append(pref->value.stringlist, } else if(pref->type == PURPLE_PREF_PATH_LIST) { pref->value.stringlist = g_list_append(pref->value.stringlist, g_filename_from_utf8(pref_value, -1, NULL, NULL, NULL)); g_string_free(pref_name_full, TRUE); if(!pref_name || purple_strequal(pref_name, "/")) pref_name_full = g_string_new(pref_name); for(tmp = prefs_stack; tmp; tmp = tmp->next) { pref_name_full = g_string_prepend_c(pref_name_full, '/'); pref_name_full = g_string_prepend(pref_name_full, tmp->data); pref_name_full = g_string_prepend_c(pref_name_full, '/'); purple_prefs_add_none(pref_name_full->str); case PURPLE_PREF_BOOLEAN: purple_prefs_set_bool(pref_name_full->str, atoi(pref_value)); purple_prefs_set_int(pref_name_full->str, atoi(pref_value)); purple_prefs_set_string(pref_name_full->str, pref_value); case PURPLE_PREF_STRING_LIST: purple_prefs_set_string_list(pref_name_full->str, NULL); decoded = g_filename_from_utf8(pref_value, -1, NULL, NULL, NULL); purple_prefs_set_path(pref_name_full->str, decoded); purple_prefs_set_path(pref_name_full->str, NULL); case PURPLE_PREF_PATH_LIST: purple_prefs_set_path_list(pref_name_full->str, NULL); prefs_stack = g_list_prepend(prefs_stack, g_strdup(pref_name)); g_string_free(pref_name_full, TRUE); prefs_end_element_handler(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error) if(prefs_stack && purple_strequal(element_name, "pref")) { g_free(prefs_stack->data); prefs_stack = g_list_delete_link(prefs_stack, prefs_stack); static GMarkupParser prefs_parser = { prefs_start_element_handler, prefs_end_element_handler, gchar *filename = g_build_filename(purple_user_dir(), "prefs.xml", NULL); GMarkupParseContext *context; purple_debug_misc("prefs", "Reading %s", filename); if(!g_file_get_contents(filename, &contents, &length, &error)) { gchar *common_appdata = wpurple_get_special_folder(CSIDL_COMMON_APPDATA); filename = g_build_filename(common_appdata ? common_appdata : "", "purple", "prefs.xml", NULL); filename = g_build_filename(SYSCONFDIR, "purple", "prefs.xml", NULL); purple_debug_info("prefs", "Reading %s\n", filename); if (!g_file_get_contents(filename, &contents, &length, &error)) { purple_debug_error("prefs", "Error reading prefs: %s\n", context = g_markup_parse_context_new(&prefs_parser, 0, NULL, NULL); if(!g_markup_parse_context_parse(context, contents, length, NULL)) { g_markup_parse_context_free(context); if(!g_markup_parse_context_end_parse(context, NULL)) { purple_debug_error("prefs", "Error parsing %s\n", filename); g_markup_parse_context_free(context); if (purple_debug_is_verbose()) purple_debug_misc("prefs", "Finished reading %s", filename); g_markup_parse_context_free(context); prefs_save_cb(const char *name, PurplePrefType type, gconstpointer val, purple_debug_misc("prefs", "%s changed, scheduling save.\n", name); get_path_dirname(const char *name) if ((c = strrchr(str, '/')) != NULL) { get_path_basename(const char *name) if ((c = strrchr(name, '/')) != NULL) pref_full_name(struct purple_pref *pref) struct purple_pref *parent; name = g_string_new(pref->name); for(parent = pref->parent; parent && parent->name; parent = parent->parent) { name = g_string_prepend_c(name, '/'); name = g_string_prepend(name, parent->name); name = g_string_prepend_c(name, '/'); return g_string_free(name, FALSE); static struct purple_pref * find_pref_parent(const char *name) char *parent_name = get_path_dirname(name); struct purple_pref *ret = &prefs; if(!purple_strequal(parent_name, "/")) { ret = find_pref(parent_name); free_pref_value(struct purple_pref *pref) case PURPLE_PREF_BOOLEAN: pref->value.boolean = FALSE; g_free(pref->value.string); pref->value.string = NULL; case PURPLE_PREF_STRING_LIST: case PURPLE_PREF_PATH_LIST: g_list_foreach(pref->value.stringlist, (GFunc)g_free, NULL); g_list_free(pref->value.stringlist); static struct purple_pref * add_pref(PurplePrefType type, const char *name) struct purple_pref *parent; struct purple_pref *sibling; parent = find_pref_parent(name); my_name = get_path_basename(name); for(sibling = parent->first_child; sibling; sibling = sibling->sibling) { if(purple_strequal(sibling->name, my_name)) { me = g_new0(struct purple_pref, 1); if(parent->first_child) { /* blatant abuse of a for loop */ for(sibling = parent->first_child; sibling->sibling; sibling = sibling->sibling); parent->first_child = me; g_hash_table_insert(prefs_hash, g_strdup(name), (gpointer)me); purple_prefs_add_none(const char *name) add_pref(PURPLE_PREF_NONE, name); purple_prefs_add_bool(const char *name, gboolean value) struct purple_pref *pref = add_pref(PURPLE_PREF_BOOLEAN, name); pref->value.boolean = value; purple_prefs_add_int(const char *name, int value) struct purple_pref *pref = add_pref(PURPLE_PREF_INT, name); pref->value.integer = value; purple_prefs_add_string(const char *name, const char *value) struct purple_pref *pref; if(value != NULL && !g_utf8_validate(value, -1, NULL)) { purple_debug_error("prefs", "purple_prefs_add_string: Cannot store invalid UTF8 for string pref %s\n", name); pref = add_pref(PURPLE_PREF_STRING, name); pref->value.string = g_strdup(value); purple_prefs_add_string_list(const char *name, GList *value) struct purple_pref *pref = add_pref(PURPLE_PREF_STRING_LIST, name); for(tmp = value; tmp; tmp = tmp->next) { if(tmp->data != NULL && !g_utf8_validate(tmp->data, -1, NULL)) { purple_debug_error("prefs", "purple_prefs_add_string_list: Skipping invalid UTF8 for string list pref %s\n", name); pref->value.stringlist = g_list_append(pref->value.stringlist, purple_prefs_add_path(const char *name, const char *value) struct purple_pref *pref = add_pref(PURPLE_PREF_PATH, name); pref->value.string = g_strdup(value); purple_prefs_add_path_list(const char *name, GList *value) struct purple_pref *pref = add_pref(PURPLE_PREF_PATH_LIST, name); for(tmp = value; tmp; tmp = tmp->next) pref->value.stringlist = g_list_append(pref->value.stringlist, remove_pref(struct purple_pref *pref) remove_pref(pref->first_child); if(pref->parent->first_child == pref) { pref->parent->first_child = pref->sibling; struct purple_pref *sib = pref->parent->first_child; while(sib && sib->sibling != pref) sib->sibling = pref->sibling; name = pref_full_name(pref); purple_debug_info("prefs", "removing pref %s\n", name); g_hash_table_remove(prefs_hash, name); while((l = pref->callbacks) != NULL) { pref->callbacks = pref->callbacks->next; purple_prefs_remove(const char *name) struct purple_pref *pref = find_pref(name); purple_prefs_remove("/"); do_callbacks(const char* name, struct purple_pref *pref) struct purple_pref *cb_pref; for(cb_pref = pref; cb_pref; cb_pref = cb_pref->parent) { for(cbs = cb_pref->callbacks; cbs; cbs = cbs->next) { struct pref_cb *cb = cbs->data; cb->func(name, pref->type, pref->value.generic, cb->data); purple_prefs_trigger_callback(const char *name) struct purple_pref *pref = find_pref(name); purple_debug_error("prefs", "purple_prefs_trigger_callback: Unknown pref %s\n", name); do_callbacks(name, pref); purple_prefs_set_bool(const char *name, gboolean value) struct purple_pref *pref = find_pref(name); if(pref->type != PURPLE_PREF_BOOLEAN) { purple_debug_error("prefs", "purple_prefs_set_bool: %s not a boolean pref\n", name); if(pref->value.boolean != value) { pref->value.boolean = value; do_callbacks(name, pref); purple_prefs_add_bool(name, value); purple_prefs_set_int(const char *name, int value) struct purple_pref *pref = find_pref(name); if(pref->type != PURPLE_PREF_INT) { purple_debug_error("prefs", "purple_prefs_set_int: %s not an integer pref\n", name); if(pref->value.integer != value) { pref->value.integer = value; do_callbacks(name, pref); purple_prefs_add_int(name, value); purple_prefs_set_string(const char *name, const char *value) struct purple_pref *pref = find_pref(name); if(value != NULL && !g_utf8_validate(value, -1, NULL)) { purple_debug_error("prefs", "purple_prefs_set_string: Cannot store invalid UTF8 for string pref %s\n", name); if(pref->type != PURPLE_PREF_STRING && pref->type != PURPLE_PREF_PATH) { purple_debug_error("prefs", "purple_prefs_set_string: %s not a string pref\n", name); if (!purple_strequal(pref->value.string, value)) { g_free(pref->value.string); pref->value.string = g_strdup(value); do_callbacks(name, pref); purple_prefs_add_string(name, value); purple_prefs_set_string_list(const char *name, GList *value) struct purple_pref *pref = find_pref(name); if(pref->type != PURPLE_PREF_STRING_LIST) { purple_debug_error("prefs", "purple_prefs_set_string_list: %s not a string list pref\n", g_list_foreach(pref->value.stringlist, (GFunc)g_free, NULL); g_list_free(pref->value.stringlist); pref->value.stringlist = NULL; for(tmp = value; tmp; tmp = tmp->next) { if(tmp->data != NULL && !g_utf8_validate(tmp->data, -1, NULL)) { purple_debug_error("prefs", "purple_prefs_set_string_list: Skipping invalid UTF8 for string list pref %s\n", name); pref->value.stringlist = g_list_prepend(pref->value.stringlist, pref->value.stringlist = g_list_reverse(pref->value.stringlist); do_callbacks(name, pref); purple_prefs_add_string_list(name, value); purple_prefs_set_path(const char *name, const char *value) struct purple_pref *pref = find_pref(name); if(pref->type != PURPLE_PREF_PATH) { purple_debug_error("prefs", "purple_prefs_set_path: %s not a path pref\n", name); if (!purple_strequal(pref->value.string, value)) { g_free(pref->value.string); pref->value.string = g_strdup(value); do_callbacks(name, pref); purple_prefs_add_path(name, value); purple_prefs_set_path_list(const char *name, GList *value) struct purple_pref *pref = find_pref(name); if(pref->type != PURPLE_PREF_PATH_LIST) { purple_debug_error("prefs", "purple_prefs_set_path_list: %s not a path list pref\n", g_list_foreach(pref->value.stringlist, (GFunc)g_free, NULL); g_list_free(pref->value.stringlist); pref->value.stringlist = NULL; for(tmp = value; tmp; tmp = tmp->next) pref->value.stringlist = g_list_prepend(pref->value.stringlist, pref->value.stringlist = g_list_reverse(pref->value.stringlist); do_callbacks(name, pref); purple_prefs_add_path_list(name, value); purple_prefs_exists(const char *name) struct purple_pref *pref = find_pref(name); purple_prefs_get_type(const char *name) struct purple_pref *pref = find_pref(name); purple_prefs_get_bool(const char *name) struct purple_pref *pref = find_pref(name); purple_debug_error("prefs", "purple_prefs_get_bool: Unknown pref %s\n", name); } else if(pref->type != PURPLE_PREF_BOOLEAN) { purple_debug_error("prefs", "purple_prefs_get_bool: %s not a boolean pref\n", name); return pref->value.boolean; purple_prefs_get_int(const char *name) struct purple_pref *pref = find_pref(name); purple_debug_error("prefs", "purple_prefs_get_int: Unknown pref %s\n", name); } else if(pref->type != PURPLE_PREF_INT) { purple_debug_error("prefs", "purple_prefs_get_int: %s not an integer pref\n", name); return pref->value.integer; purple_prefs_get_string(const char *name) struct purple_pref *pref = find_pref(name); purple_debug_error("prefs", "purple_prefs_get_string: Unknown pref %s\n", name); } else if(pref->type != PURPLE_PREF_STRING) { purple_debug_error("prefs", "purple_prefs_get_string: %s not a string pref\n", name); return pref->value.string; purple_prefs_get_string_list(const char *name) struct purple_pref *pref = find_pref(name); purple_debug_error("prefs", "purple_prefs_get_string_list: Unknown pref %s\n", name); } else if(pref->type != PURPLE_PREF_STRING_LIST) { purple_debug_error("prefs", "purple_prefs_get_string_list: %s not a string list pref\n", name); for(tmp = pref->value.stringlist; tmp; tmp = tmp->next) ret = g_list_prepend(ret, g_strdup(tmp->data)); ret = g_list_reverse(ret); purple_prefs_get_path(const char *name) struct purple_pref *pref = find_pref(name); purple_debug_error("prefs", "purple_prefs_get_path: Unknown pref %s\n", name); } else if(pref->type != PURPLE_PREF_PATH) { purple_debug_error("prefs", "purple_prefs_get_path: %s not a path pref\n", name); return pref->value.string; purple_prefs_get_path_list(const char *name) struct purple_pref *pref = find_pref(name); purple_debug_error("prefs", "purple_prefs_get_path_list: Unknown pref %s\n", name); } else if(pref->type != PURPLE_PREF_PATH_LIST) { purple_debug_error("prefs", "purple_prefs_get_path_list: %s not a path list pref\n", name); for(tmp = pref->value.stringlist; tmp; tmp = tmp->next) ret = g_list_prepend(ret, g_strdup(tmp->data)); ret = g_list_reverse(ret); purple_prefs_rename_node(struct purple_pref *oldpref, struct purple_pref *newpref) struct purple_pref *child, *next; /* if we're a parent, rename the kids first */ for(child = oldpref->first_child; child != NULL; child = next) struct purple_pref *newchild; for(newchild = newpref->first_child; newchild != NULL; newchild = newchild->sibling) if(purple_strequal(child->name, newchild->name)) purple_prefs_rename_node(child, newchild); /* no rename happened, we weren't able to find the new pref */ char *tmpname = pref_full_name(child); purple_debug_error("prefs", "Unable to find rename pref for %s\n", tmpname); oldname = pref_full_name(oldpref); newname = pref_full_name(newpref); if (oldpref->type != newpref->type) purple_debug_error("prefs", "Unable to rename %s to %s: differing types\n", oldname, newname); purple_debug_info("prefs", "Renaming %s to %s\n", oldname, newname); case PURPLE_PREF_BOOLEAN: purple_prefs_set_bool(newname, oldpref->value.boolean); purple_prefs_set_int(newname, oldpref->value.integer); purple_prefs_set_string(newname, oldpref->value.string); case PURPLE_PREF_STRING_LIST: purple_prefs_set_string_list(newname, oldpref->value.stringlist); purple_prefs_set_path(newname, oldpref->value.string); case PURPLE_PREF_PATH_LIST: purple_prefs_set_path_list(newname, oldpref->value.stringlist); purple_prefs_rename(const char *oldname, const char *newname) struct purple_pref *oldpref, *newpref; oldpref = find_pref(oldname); /* it's already been renamed, call off the dogs */ newpref = find_pref(newname); purple_debug_error("prefs", "Unable to rename %s to %s: new pref not created\n", oldname, newname); purple_prefs_rename_node(oldpref, newpref); purple_prefs_rename_boolean_toggle(const char *oldname, const char *newname) struct purple_pref *oldpref, *newpref; oldpref = find_pref(oldname); /* it's already been renamed, call off the cats */ if (oldpref->type != PURPLE_PREF_BOOLEAN) purple_debug_error("prefs", "Unable to rename %s to %s: old pref not a boolean\n", oldname, newname); if (oldpref->first_child != NULL) /* can't rename parents */ purple_debug_error("prefs", "Unable to rename %s to %s: can't rename parents\n", oldname, newname); newpref = find_pref(newname); purple_debug_error("prefs", "Unable to rename %s to %s: new pref not created\n", oldname, newname); if (oldpref->type != newpref->type) purple_debug_error("prefs", "Unable to rename %s to %s: differing types\n", oldname, newname); purple_debug_info("prefs", "Renaming and toggling %s to %s\n", oldname, newname); purple_prefs_set_bool(newname, !(oldpref->value.boolean)); purple_prefs_connect_callback(void *handle, const char *name, PurplePrefCallback func, gpointer data) struct purple_pref *pref; g_return_val_if_fail(name != NULL, 0); g_return_val_if_fail(func != NULL, 0); purple_debug_error("prefs", "purple_prefs_connect_callback: Unknown pref %s\n", name); cb = g_new0(struct pref_cb, 1); pref->callbacks = g_slist_append(pref->callbacks, cb); disco_callback_helper(struct purple_pref *pref, guint callback_id) struct purple_pref *child; for(cbs = pref->callbacks; cbs; cbs = cbs->next) { struct pref_cb *cb = cbs->data; if(cb->id == callback_id) { pref->callbacks = g_slist_delete_link(pref->callbacks, cbs); for(child = pref->first_child; child; child = child->sibling) { if(disco_callback_helper(child, callback_id)) purple_prefs_disconnect_callback(guint callback_id) disco_callback_helper(&prefs, callback_id); disco_callback_helper_handle(struct purple_pref *pref, void *handle) struct purple_pref *child; struct pref_cb *cb = cbs->data; if(cb->handle == handle) { pref->callbacks = g_slist_delete_link(pref->callbacks, cbs); for(child = pref->first_child; child; child = child->sibling) disco_callback_helper_handle(child, handle); purple_prefs_disconnect_by_handle(void *handle) g_return_if_fail(handle != NULL); disco_callback_helper_handle(&prefs, handle); purple_prefs_get_children_names(const char *name) struct purple_pref *pref = find_pref(name), *child; if (name[strlen(name) - 1] != '/') for (child = pref->first_child; child; child = child->sibling) { list = g_list_append(list, g_strdup_printf("%s%s%s", name, sep, child->name)); purple_prefs_rename("/core", "/purple"); /* Remove some no-longer-used prefs */ purple_prefs_remove("/purple/away/auto_response/enabled"); purple_prefs_remove("/purple/away/auto_response/idle_only"); purple_prefs_remove("/purple/away/auto_response/in_active_conv"); purple_prefs_remove("/purple/away/auto_response/sec_before_resend"); purple_prefs_remove("/purple/away/auto_response"); purple_prefs_remove("/purple/away/default_message"); purple_prefs_remove("/purple/buddies/use_server_alias"); purple_prefs_remove("/purple/conversations/away_back_on_send"); purple_prefs_remove("/purple/conversations/send_urls_as_links"); purple_prefs_remove("/purple/conversations/im/show_login"); purple_prefs_remove("/purple/conversations/chat/show_join"); purple_prefs_remove("/purple/conversations/chat/show_leave"); purple_prefs_remove("/purple/conversations/combine_chat_im"); purple_prefs_remove("/purple/conversations/use_alias_for_title"); purple_prefs_remove("/purple/debug/timestamps"); purple_prefs_remove("/purple/logging/log_signon_signoff"); purple_prefs_remove("/purple/logging/log_idle_state"); purple_prefs_remove("/purple/logging/log_away_state"); purple_prefs_remove("/purple/logging/log_own_states"); purple_prefs_remove("/purple/status/scores/hidden"); purple_prefs_remove("/plugins/core/autorecon/hide_connected_error"); purple_prefs_remove("/plugins/core/autorecon/hide_connecting_error"); purple_prefs_remove("/plugins/core/autorecon/hide_reconnecting_dialog"); purple_prefs_remove("/plugins/core/autorecon/restore_state"); purple_prefs_remove("/plugins/core/autorecon"); /* Convert old sounds while_away pref to new 3-way pref. */ if (purple_prefs_exists("/purple/sound/while_away") && purple_prefs_get_bool("/purple/sound/while_away")) purple_prefs_set_int("/purple/sound/while_status", 3); purple_prefs_remove("/purple/sound/while_away"); purple_prefs_get_handle(void) void *handle = purple_prefs_get_handle(); prefs_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); purple_prefs_connect_callback(handle, "/", prefs_save_cb, NULL); purple_prefs_add_none("/purple"); purple_prefs_add_none("/plugins"); purple_prefs_add_none("/plugins/core"); purple_prefs_add_none("/plugins/lopl"); purple_prefs_add_none("/plugins/prpl"); purple_prefs_add_none("/purple/away"); purple_prefs_add_string("/purple/away/idle_reporting", "system"); purple_prefs_add_bool("/purple/away/away_when_idle", TRUE); purple_prefs_add_int("/purple/away/mins_before_away", 5); if (!purple_prefs_exists("/purple/away/auto_response/enabled") || !purple_prefs_exists("/purple/away/auto_response/idle_only")) purple_prefs_add_string("/purple/away/auto_reply", "awayidle"); if (!purple_prefs_get_bool("/purple/away/auto_response/enabled")) purple_prefs_add_string("/purple/away/auto_reply", "never"); if (purple_prefs_get_bool("/purple/away/auto_response/idle_only")) purple_prefs_add_string("/purple/away/auto_reply", "awayidle"); purple_prefs_add_string("/purple/away/auto_reply", "away"); purple_prefs_add_none("/purple/buddies"); /* Contact Priority Settings */ purple_prefs_add_none("/purple/contact"); purple_prefs_add_bool("/purple/contact/last_match", FALSE); purple_prefs_remove("/purple/contact/offline_score"); purple_prefs_remove("/purple/contact/away_score"); purple_prefs_remove("/purple/contact/idle_score"); purple_timeout_remove(save_timer); purple_prefs_disconnect_by_handle(purple_prefs_get_handle()); g_hash_table_destroy(prefs_hash);