changeset 10425:9903182f2aac

[gaim-migrate @ 11677] Added a util function to read an xml file and parse it into an xmlnode tree Changed accounts.xml reading to use xmlnode's committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sun, 26 Dec 2004 22:52:52 +0000
parents 108151be77a3
children 30d9ec7d001b
files src/account.c src/gtkmain.c src/gtkprivacy.c src/savedstatuses.c src/util.c src/util.h src/xmlnode.c src/xmlnode.h
diffstat 8 files changed, 345 insertions(+), 405 deletions(-) [+]
line wrap: on
line diff
--- a/src/account.c	Sun Dec 26 18:58:36 2004 +0000
+++ b/src/account.c	Sun Dec 26 22:52:52 2004 +0000
@@ -36,22 +36,6 @@
 #include "util.h"
 #include "xmlnode.h"
 
-typedef enum
-{
-	TAG_NONE = 0,
-	TAG_PROTOCOL,
-	TAG_NAME,
-	TAG_PASSWORD,
-	TAG_ALIAS,
-	TAG_USERINFO,
-	TAG_BUDDYICON,
-	TAG_SETTING,
-	TAG_TYPE,
-	TAG_HOST,
-	TAG_PORT
-
-} AccountParserTag;
-
 typedef struct
 {
 	GaimPrefType type;
@@ -68,24 +52,6 @@
 
 } GaimAccountSetting;
 
-typedef struct
-{
-	AccountParserTag tag;
-
-	GaimAccount *account;
-	GaimProxyInfo *proxy_info;
-	char *protocol_id;
-
-	GString *buffer;
-
-	GaimPrefType setting_type;
-	char *setting_ui;
-	char *setting_name;
-
-	gboolean in_proxy;
-
-} AccountParserData;
-
 
 static GaimAccountUiOps *account_ui_ops = NULL;
 
@@ -1052,305 +1018,252 @@
 	}
 }
 
-/* XML Stuff */
 static void
-free_parser_data(gpointer user_data)
+parse_settings(xmlnode *node, GaimAccount *account)
 {
-	AccountParserData *data = user_data;
+	const char *ui;
+	xmlnode *child;
 
-	if (data->buffer != NULL)
-		g_string_free(data->buffer, TRUE);
-
-	if (data->setting_name != NULL)
-		g_free(data->setting_name);
-
-	g_free(data);
-}
+	/* Get the UI string, if these are UI settings */
+	ui = xmlnode_get_attrib(node, "ui");
 
-static void
-start_element_handler(GMarkupParseContext *context,
-					  const gchar *element_name,
-					  const gchar **attribute_names,
-					  const gchar **attribute_values,
-					  gpointer user_data, GError **error)
-{
-	const char *value;
-	AccountParserData *data = user_data;
-	GHashTable *atts;
-	int i;
+	/* Read settings, one by one */
+	for (child = xmlnode_get_child(node, "setting"); child != NULL;
+			child = xmlnode_get_next_twin(child))
+	{
+		const char *name, *str_type;
+		GaimPrefType type;
+		char *data;
 
-	atts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-
-	for (i = 0; attribute_names[i] != NULL; i++) {
-		g_hash_table_insert(atts, g_strdup(attribute_names[i]),
-							g_strdup(attribute_values[i]));
-	}
-
-	if (data->buffer != NULL) {
-		g_string_free(data->buffer, TRUE);
-		data->buffer = NULL;
-	}
+		name = xmlnode_get_attrib(child, "name");
+		if (name == NULL)
+			/* Ignore this setting */
+			continue;
 
-	if (!strcmp(element_name, "protocol"))
-		data->tag = TAG_PROTOCOL;
-	else if (!strcmp(element_name, "name") || !strcmp(element_name, "username"))
-		data->tag = TAG_NAME;
-	else if (!strcmp(element_name, "password"))
-		data->tag = TAG_PASSWORD;
-	else if (!strcmp(element_name, "alias"))
-		data->tag = TAG_ALIAS;
-	else if (!strcmp(element_name, "userinfo"))
-		data->tag = TAG_USERINFO;
-	else if (!strcmp(element_name, "buddyicon"))
-		data->tag = TAG_BUDDYICON;
-	else if (!strcmp(element_name, "proxy")) {
-		data->in_proxy = TRUE;
+		str_type = xmlnode_get_attrib(child, "type");
+		if (!strcmp(str_type, "string"))
+			type = GAIM_PREF_STRING;
+		else if (!strcmp(str_type, "int"))
+			type = GAIM_PREF_INT;
+		else if (!strcmp(str_type, "bool"))
+			type = GAIM_PREF_BOOLEAN;
+		else
+			/* Ignore this setting */
+			continue;
+
+		data = xmlnode_get_data(child);
+		if (data == NULL)
+			/* Ignore this setting */
+			continue;
 
-		data->proxy_info = gaim_proxy_info_new();
+		if (ui == NULL)
+		{
+			if (type == GAIM_PREF_STRING)
+				gaim_account_set_string(account, name, data);
+			else if (type == GAIM_PREF_INT)
+				gaim_account_set_int(account, name, atoi(data));
+			else if (type == GAIM_PREF_BOOLEAN)
+				gaim_account_set_bool(account, name,
+									  (*data == '0' ? FALSE : TRUE));
+		} else {
+			if (type == GAIM_PREF_STRING)
+				gaim_account_set_ui_string(account, ui, name, data);
+			else if (type == GAIM_PREF_INT)
+				gaim_account_set_ui_int(account, ui, name, atoi(data));
+			else if (type == GAIM_PREF_BOOLEAN)
+				gaim_account_set_ui_bool(account, ui, name,
+										 (*data == '0' ? FALSE : TRUE));
+		}
+
+		g_free(data);
 	}
-	else if (!strcmp(element_name, "type"))
-		data->tag = TAG_TYPE;
-	else if (!strcmp(element_name, "host"))
-		data->tag = TAG_HOST;
-	else if (!strcmp(element_name, "port"))
-		data->tag = TAG_PORT;
-	else if (!strcmp(element_name, "settings")) {
-		if ((value = g_hash_table_lookup(atts, "ui")) != NULL) {
-			data->setting_ui = g_strdup(value);
-		}
-	}
-	else if (!strcmp(element_name, "setting")) {
-		data->tag = TAG_SETTING;
-
-		if ((value = g_hash_table_lookup(atts, "name")) != NULL)
-			data->setting_name = g_strdup(value);
-
-		if ((value = g_hash_table_lookup(atts, "type")) != NULL) {
-			if (!strcmp(value, "string"))
-				data->setting_type = GAIM_PREF_STRING;
-			else if (!strcmp(value, "int"))
-				data->setting_type = GAIM_PREF_INT;
-			else if (!strcmp(value, "bool"))
-				data->setting_type = GAIM_PREF_BOOLEAN;
-		}
-	}
-
-	g_hash_table_destroy(atts);
 }
 
 static void
-end_element_handler(GMarkupParseContext *context, const gchar *element_name,
-					gpointer user_data,  GError **error)
+parse_proxy_info(xmlnode *node, GaimAccount *account)
 {
-	AccountParserData *data = user_data;
-	gchar *buffer;
-
-	if (data->buffer == NULL)
-		return;
-
-	buffer = g_string_free(data->buffer, FALSE);
-	data->buffer = NULL;
+	GaimProxyInfo *proxy_info;
+	xmlnode *child;
+	char *data;
 
-	if (data->tag == TAG_PROTOCOL) {
-		data->protocol_id = g_strdup(buffer);
-	}
-	else if (data->tag == TAG_NAME) {
-		if (data->in_proxy) {
-			gaim_proxy_info_set_username(data->proxy_info, buffer);
-		}
-		else {
-			data->account = gaim_account_new(buffer, data->protocol_id);
+	proxy_info = gaim_proxy_info_new();
 
-			gaim_accounts_add(data->account);
-
-			g_free(data->protocol_id);
+	/* Use the global proxy settings, by default */
+	gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_USE_GLOBAL);
 
-			data->protocol_id = NULL;
-		}
-	}
-	else if (data->tag == TAG_PASSWORD) {
-		if (*buffer != '\0') {
-			if (data->in_proxy) {
-				gaim_proxy_info_set_password(data->proxy_info, buffer);
-			}
-			else {
-				gaim_account_set_password(data->account, buffer);
-				gaim_account_set_remember_password(data->account, TRUE);
-			}
+	/* Read proxy type */
+	child = xmlnode_get_child(node, "type");
+	if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
+	{
+		if (!strcmp(data, "global"))
+			gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_USE_GLOBAL);
+		else if (!strcmp(data, "none"))
+			gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_NONE);
+		else if (!strcmp(data, "http"))
+			gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_HTTP);
+		else if (!strcmp(data, "socks4"))
+			gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_SOCKS4);
+		else if (!strcmp(data, "socks5"))
+			gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_SOCKS5);
+		else if (!strcmp(data, "envvar"))
+			gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_USE_ENVVAR);
+		else
+		{
+			gaim_debug_error("account", "Invalid proxy type found when "
+							 "loading account information for %s\n",
+							 gaim_account_get_username(account));
 		}
-	}
-	else if (data->tag == TAG_ALIAS) {
-		if (*buffer != '\0')
-			gaim_account_set_alias(data->account, buffer);
-	}
-	else if (data->tag == TAG_USERINFO) {
-		if (*buffer != '\0')
-			gaim_account_set_user_info(data->account, buffer);
-	}
-	else if (data->tag == TAG_BUDDYICON) {
-		if (*buffer != '\0')
-			gaim_account_set_buddy_icon(data->account, buffer);
+		g_free(data);
 	}
-	else if (data->tag == TAG_TYPE) {
-		if (data->in_proxy) {
-			if (!strcmp(buffer, "global"))
-				gaim_proxy_info_set_type(data->proxy_info,
-										 GAIM_PROXY_USE_GLOBAL);
-			else if (!strcmp(buffer, "none"))
-				gaim_proxy_info_set_type(data->proxy_info, GAIM_PROXY_NONE);
-			else if (!strcmp(buffer, "http"))
-				gaim_proxy_info_set_type(data->proxy_info, GAIM_PROXY_HTTP);
-			else if (!strcmp(buffer, "socks4"))
-				gaim_proxy_info_set_type(data->proxy_info, GAIM_PROXY_SOCKS4);
-			else if (!strcmp(buffer, "socks5"))
-				gaim_proxy_info_set_type(data->proxy_info, GAIM_PROXY_SOCKS5);
-			else if (!strcmp(buffer, "envvar"))
-				gaim_proxy_info_set_type(data->proxy_info, GAIM_PROXY_USE_ENVVAR);
-			else
-				gaim_debug_error("account",
-						   "Invalid proxy type found when loading account "
-						   "information for %s\n",
-						   gaim_account_get_username(data->account));
-		}
+
+	/* Read proxy host */
+	child = xmlnode_get_child(node, "host");
+	if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
+	{
+		gaim_proxy_info_set_host(proxy_info, data);
+		g_free(data);
 	}
-	else if (data->tag == TAG_HOST) {
-		if (data->in_proxy && *buffer != '\0')
-			gaim_proxy_info_set_host(data->proxy_info, buffer);
-	}
-	else if (data->tag == TAG_PORT) {
-		if (data->in_proxy && *buffer != '\0')
-			gaim_proxy_info_set_port(data->proxy_info, atoi(buffer));
+
+	/* Read proxy port */
+	child = xmlnode_get_child(node, "port");
+	if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
+	{
+		gaim_proxy_info_set_port(proxy_info, atoi(data));
+		g_free(data);
 	}
-	else if (data->tag == TAG_SETTING) {
-		if (*buffer != '\0') {
-			if (data->setting_ui != NULL) {
-				if (data->setting_type == GAIM_PREF_STRING)
-					gaim_account_set_ui_string(data->account, data->setting_ui,
-											   data->setting_name, buffer);
-				else if (data->setting_type == GAIM_PREF_INT)
-					gaim_account_set_ui_int(data->account, data->setting_ui,
-											data->setting_name, atoi(buffer));
-				else if (data->setting_type == GAIM_PREF_BOOLEAN)
-					gaim_account_set_ui_bool(data->account, data->setting_ui,
-											 data->setting_name,
-											 (*buffer == '0' ? FALSE : TRUE));
-			}
-			else {
-				if (data->setting_type == GAIM_PREF_STRING)
-					gaim_account_set_string(data->account, data->setting_name,
-											buffer);
-				else if (data->setting_type == GAIM_PREF_INT)
-					gaim_account_set_int(data->account, data->setting_name,
-										 atoi(buffer));
-				else if (data->setting_type == GAIM_PREF_BOOLEAN)
-					gaim_account_set_bool(data->account, data->setting_name,
-										  (*buffer == '0' ? FALSE : TRUE));
-			}
-		}
+
+	/* Read proxy username */
+	child = xmlnode_get_child(node, "username");
+	if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
+	{
+		gaim_proxy_info_set_username(proxy_info, data);
+		g_free(data);
+	}
 
-		g_free(data->setting_name);
-		data->setting_name = NULL;
+	/* Read proxy password */
+	child = xmlnode_get_child(node, "password");
+	if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
+	{
+		gaim_proxy_info_set_password(proxy_info, data);
+		g_free(data);
 	}
-	else if (!strcmp(element_name, "proxy")) {
-		data->in_proxy = FALSE;
 
-		if (gaim_proxy_info_get_type(data->proxy_info) == GAIM_PROXY_USE_GLOBAL) {
-			gaim_proxy_info_destroy(data->proxy_info);
-			data->proxy_info = NULL;
-		}
-		else if (*buffer != '\0') {
-			gaim_account_set_proxy_info(data->account, data->proxy_info);
-		}
-	}
-	else if (!strcmp(element_name, "settings")) {
-		if (data->setting_ui != NULL) {
-			g_free(data->setting_ui);
-			data->setting_ui = NULL;
-		}
+	/* If there are no values set then proxy_infourn NULL */
+	if ((gaim_proxy_info_get_type(proxy_info) == GAIM_PROXY_USE_GLOBAL) &&
+		(gaim_proxy_info_get_host(proxy_info) == NULL) &&
+		(gaim_proxy_info_get_port(proxy_info) == 0) &&
+		(gaim_proxy_info_get_username(proxy_info) == NULL) &&
+		(gaim_proxy_info_get_password(proxy_info) == NULL))
+	{
+		gaim_proxy_info_destroy(proxy_info);
+		return;
 	}
 
-	data->tag = TAG_NONE;
+	gaim_account_set_proxy_info(account, proxy_info);
+}
+
+static GaimAccount *
+parse_account(xmlnode *node)
+{
+	GaimAccount *ret;
+	xmlnode *child;
+	char *protocol_id = NULL;
+	char *name = NULL;
+	char *data;
+
+	child = xmlnode_get_child(node, "protocol");
+	if (child != NULL)
+		protocol_id = xmlnode_get_data(child);
+
+	child = xmlnode_get_child(node, "name");
+	if (child != NULL)
+		name = xmlnode_get_data(child);
+	if (name == NULL)
+	{
+		/* Do we really need to do this? */
+		child = xmlnode_get_child(node, "username");
+		if (child != NULL)
+			name = xmlnode_get_data(child);
+	}
+
+	if ((protocol_id == NULL) || (name == NULL))
+	{
+		free(protocol_id);
+		free(name);
+		return NULL;
+	}
+
+	ret = gaim_account_new(name, protocol_id);
+	free(name);
+	free(protocol_id);
 
-	g_free(buffer);
+	/* Read the password */
+	child = xmlnode_get_child(node, "password");
+	if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
+	{
+		gaim_account_set_password(ret, data);
+		gaim_account_set_remember_password(ret, TRUE);
+		g_free(data);
+	}
+
+	/* Read the alias */
+	child = xmlnode_get_child(node, "alias");
+	if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
+	{
+		gaim_account_set_alias(ret, data);
+		g_free(data);
+	}
+
+	/* Read the userinfo */
+	child = xmlnode_get_child(node, "userinfo");
+	if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
+	{
+		gaim_account_set_user_info(ret, data);
+		g_free(data);
+	}
+
+	/* Read the buddyicon */
+	child = xmlnode_get_child(node, "buddyicon");
+	if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
+	{
+		gaim_account_set_buddy_icon(ret, data);
+		g_free(data);
+	}
+
+	/* Read settings (both core and UI) */
+	for (child = xmlnode_get_child(node, "settings"); child != NULL;
+			child = xmlnode_get_next_twin(child))
+	{
+		parse_settings(child, ret);
+	}
+
+	/* Read proxy */
+	child = xmlnode_get_child(node, "proxy");
+	if (child != NULL)
+	{
+		parse_proxy_info(child, ret);
+	}
+
+	return ret;
 }
 
 static void
-text_handler(GMarkupParseContext *context, const gchar *text,
-			 gsize text_len, gpointer user_data, GError **error)
-{
-	AccountParserData *data = user_data;
-
-	if (data->buffer == NULL)
-		data->buffer = g_string_new_len(text, text_len);
-	else
-		g_string_append_len(data->buffer, text, text_len);
-}
-
-static GMarkupParser accounts_parser =
+load_accounts(void)
 {
-	start_element_handler,
-	end_element_handler,
-	text_handler,
-	NULL,
-	NULL
-};
+	xmlnode *node, *child;
 
-gboolean
-gaim_accounts_load()
-{
-	gchar *filename = g_build_filename(gaim_user_dir(), "accounts.xml", NULL);
-	gchar *contents = NULL;
-	gsize length;
-	GMarkupParseContext *context;
-	GError *error = NULL;
-	AccountParserData *parser_data;
-
-	if (filename == NULL) {
-		accounts_loaded = TRUE;
-		return FALSE;
-	}
+	node = gaim_util_read_xml_from_file("accounts.xml", _("accounts"));
 
-	if (!g_file_get_contents(filename, &contents, &length, &error)) {
-		gaim_debug_error("accounts",
-				   "Error reading accounts: %s\n", error->message);
-		g_error_free(error);
-		g_free(filename);
-		accounts_loaded = TRUE;
-
-		return FALSE;
-	}
-
-	parser_data = g_new0(AccountParserData, 1);
-
-	context = g_markup_parse_context_new(&accounts_parser, 0,
-										 parser_data, free_parser_data);
-
-	if (!g_markup_parse_context_parse(context, contents, length, NULL)) {
-		g_markup_parse_context_free(context);
-		g_free(contents);
-		g_free(filename);
-		accounts_loaded = TRUE;
+	if (node == NULL)
+		return;
 
-		return TRUE;
+	for (child = xmlnode_get_child(node, "account"); child != NULL;
+			child = xmlnode_get_next_twin(child))
+	{
+		GaimAccount *new;
+		new = parse_account(child);
+		gaim_accounts_add(new);
 	}
-
-	if (!g_markup_parse_context_end_parse(context, NULL)) {
-		gaim_debug_error("accounts", "Error parsing %s\n",
-				   filename);
-		g_markup_parse_context_free(context);
-		g_free(contents);
-		g_free(filename);
-		accounts_loaded = TRUE;
-
-		return TRUE;
-	}
-
-	g_markup_parse_context_free(context);
-	g_free(contents);
-	g_free(filename);
-	accounts_loaded = TRUE;
-
-	return TRUE;
 }
 
 static void
@@ -1395,9 +1308,12 @@
 	table = (GHashTable *)value;
 	node  = (xmlnode *)user_data;
 
-	child = xmlnode_new_child(node, "settings");
-	xmlnode_set_attrib(child, "ui", ui);
-	g_hash_table_foreach(table, setting_to_xmlnode, child);
+	if (g_hash_table_size(table) > 0)
+	{
+		child = xmlnode_new_child(node, "settings");
+		xmlnode_set_attrib(child, "ui", ui);
+		g_hash_table_foreach(table, setting_to_xmlnode, child);
+	}
 }
 
 static xmlnode *
@@ -1496,10 +1412,16 @@
 		xmlnode_insert_data(child, tmp, -1);
 	}
 
-	child = xmlnode_new_child(node, "settings");
-	g_hash_table_foreach(account->settings, setting_to_xmlnode, child);
+	if (g_hash_table_size(account->settings) > 0)
+	{
+		child = xmlnode_new_child(node, "settings");
+		g_hash_table_foreach(account->settings, setting_to_xmlnode, child);
+	}
 
-	g_hash_table_foreach(account->ui_settings, ui_setting_to_xmlnode, node);
+	if (g_hash_table_size(account->ui_settings) > 0)
+	{
+		g_hash_table_foreach(account->ui_settings, ui_setting_to_xmlnode, node);
+	}
 
 	if ((proxy_info = gaim_account_get_proxy_info(account)) != NULL)
 	{
@@ -1728,6 +1650,8 @@
 {
 	void *handle = gaim_accounts_get_handle();
 
+	load_accounts();
+
 	gaim_signal_register(handle, "account-connecting",
 						 gaim_marshal_VOID__POINTER, NULL, 1,
 						 gaim_value_new(GAIM_TYPE_SUBTYPE,
--- a/src/gtkmain.c	Sun Dec 26 18:58:36 2004 +0000
+++ b/src/gtkmain.c	Sun Dec 26 22:52:52 2004 +0000
@@ -627,8 +627,6 @@
 	g_free(gaimrc);
 	g_free(accountsxml);
 
-	gaim_accounts_load();
-
 	gaim_set_blist(gaim_blist_new());
 	gaim_blist_load();
 
--- a/src/gtkprivacy.c	Sun Dec 26 18:58:36 2004 +0000
+++ b/src/gtkprivacy.c	Sun Dec 26 22:52:52 2004 +0000
@@ -123,6 +123,7 @@
 	for (l = list; l != NULL; l = l->next) {
 		temp_name = (const char *)l->data;
 
+		/* Should this use gaim_normalize()? */
 		if (!gaim_utf8_strcasecmp(name, temp_name))
 			return temp_name;
 	}
--- a/src/savedstatuses.c	Sun Dec 26 18:58:36 2004 +0000
+++ b/src/savedstatuses.c	Sun Dec 26 22:52:52 2004 +0000
@@ -101,7 +101,7 @@
 
 
 /**************************************************************************
-* Saved status writting to disk
+* Writting to disk
 **************************************************************************/
 
 static xmlnode *
@@ -206,14 +206,14 @@
 
 
 /**************************************************************************
-* Saved status reading from disk
+* Reading from disk
 **************************************************************************/
 static GaimSavedStatusSub *
 parse_substatus(xmlnode *substatus)
 {
 	GaimSavedStatusSub *ret;
 	xmlnode *node;
-	char *data = NULL;
+	char *data;
 
 	ret = g_new0(GaimSavedStatusSub, 1);
 
@@ -238,21 +238,19 @@
 
 	/* Read the state */
 	node = xmlnode_get_child(substatus, "state");
-	if (node != NULL)
-		data = xmlnode_get_data(node);
-	if (data != NULL) {
+	if ((node != NULL) && ((data = xmlnode_get_data(node)) == NULL))
+	{
 		ret->type = gaim_status_type_find_with_id(
-									ret->account->status_types, data);
+							ret->account->status_types, data);
 		g_free(data);
-		data = NULL;
 	}
 
 	/* Read the message */
 	node = xmlnode_get_child(substatus, "message");
-	if (node != NULL)
-		data = xmlnode_get_data(node);
-	if (data != NULL)
+	if ((node != NULL) && ((data = xmlnode_get_data(node)) == NULL))
+	{
 		ret->message = data;
+	}
 
 	return ret;
 }
@@ -287,7 +285,7 @@
 	GaimSavedStatus *ret;
 	xmlnode *node;
 	const char *attrib;
-	char *data = NULL;
+	char *data;
 	int i;
 
 	ret = g_new0(GaimSavedStatus, 1);
@@ -308,20 +306,18 @@
 
 	/* Read the primitive status type */
 	node = xmlnode_get_child(status, "state");
-	if (node != NULL)
-		data = xmlnode_get_data(node);
-	if (data != NULL) {
+	if ((node != NULL) && ((data = xmlnode_get_data(node)) == NULL))
+	{
 		ret->type = gaim_primitive_get_type_from_id(data);
 		g_free(data);
-		data = NULL;
 	}
 
 	/* Read the message */
 	node = xmlnode_get_child(status, "message");
-	if (node != NULL)
-		data = xmlnode_get_data(node);
-	if (data != NULL)
+	if ((node != NULL) && ((data = xmlnode_get_data(node)) == NULL))
+	{
 		ret->message = data;
+	}
 
 	/* Read substatuses */
 	for (node = xmlnode_get_child(status, "status"); node != NULL;
@@ -342,48 +338,15 @@
  * @return TRUE on success, FALSE on failure (if the file can not
  *         be opened, or if it contains invalid XML).
  */
-static gboolean
-read_statuses(const char *filename)
+static void
+load_statuses(void)
 {
-	GError *error;
-	gchar *contents = NULL;
-	gsize length;
 	xmlnode *statuses, *status;
 
-	gaim_debug_info("status", "Reading %s\n", filename);
-
-	if (!g_file_get_contents(filename, &contents, &length, &error))
-	{
-		gaim_debug_error("status", "Error reading statuses: %s\n",
-						 error->message);
-		g_error_free(error);
-		return FALSE;
-	}
-
-	statuses = xmlnode_from_str(contents, length);
+	statuses = gaim_util_read_xml_from_file("status.xml", _("saved statuses"));
 
 	if (statuses == NULL)
-	{
-		FILE *backup;
-		gchar *name;
-		gaim_debug_error("status", "Error parsing statuses\n");
-		name = g_strdup_printf("%s~", filename);
-		if ((backup = fopen(name, "w")))
-		{
-			fwrite(contents, length, 1, backup);
-			fclose(backup);
-			chmod(name, S_IRUSR | S_IWUSR);
-		}
-		else
-		{
-			gaim_debug_error("status", "Unable to write backup %s\n", name);
-		}
-		g_free(name);
-		g_free(contents);
-		return FALSE;
-	}
-
-	g_free(contents);
+		return;
 
 	for (status = xmlnode_get_child(statuses, "status"); status != NULL;
 			status = xmlnode_get_next_twin(status))
@@ -393,40 +356,7 @@
 		saved_statuses = g_list_append(saved_statuses, new);
 	}
 
-	gaim_debug_info("status", "Finished reading statuses\n");
-
 	xmlnode_free(statuses);
-
-	return TRUE;
-}
-
-static void
-load_statuses(void)
-{
-	const char *user_dir = gaim_user_dir();
-	gchar *filename;
-	gchar *msg;
-
-	g_return_if_fail(user_dir != NULL);
-
-	statuses_loaded = TRUE;
-
-	filename = g_build_filename(user_dir, "status.xml", NULL);
-
-	if (g_file_test(filename, G_FILE_TEST_EXISTS))
-	{
-		if (!read_statuses(filename))
-		{
-			msg = g_strdup_printf(_("An error was encountered parsing the "
-						"file containing your saved statuses (%s).  They "
-						"have not been loaded, and the old file has been "
-						"renamed to status.xml~."), filename);
-			gaim_notify_error(NULL, NULL, _("Saved Statuses Error"), msg);
-			g_free(msg);
-		}
-	}
-
-	g_free(filename);
 }
 
 
--- a/src/util.c	Sun Dec 26 18:58:36 2004 +0000
+++ b/src/util.c	Sun Dec 26 22:52:52 2004 +0000
@@ -24,6 +24,7 @@
 
 #include "conversation.h"
 #include "debug.h"
+#include "notify.h"
 #include "prpl.h"
 #include "prefs.h"
 #include "util.h"
@@ -2048,6 +2049,75 @@
 	return TRUE;
 }
 
+xmlnode *
+gaim_util_read_xml_from_file(const char *filename, const char *description)
+{
+	const char *user_dir = gaim_user_dir();
+	gchar *filename_full;
+	GError *error;
+	gchar *contents = NULL;
+	gsize length;
+	xmlnode *node = NULL;
+
+	g_return_val_if_fail(user_dir != NULL, NULL);
+
+	gaim_debug_info("util", "Reading file %s from directory %s\n",
+					filename, user_dir);
+
+	filename_full = g_build_filename(user_dir, filename, NULL);
+
+	if (!g_file_test(filename_full, G_FILE_TEST_EXISTS))
+	{
+		gaim_debug_info("util", "File %s does not exist (this is not "
+						"necessarily an error)\n", filename_full);
+		g_free(filename_full);
+		return NULL;
+	}
+
+	if (!g_file_get_contents(filename_full, &contents, &length, &error))
+	{
+		gaim_debug_error("util", "Error reading file %s: %s\n",
+						 filename_full, error->message);
+		g_error_free(error);
+	}
+
+	if ((contents != NULL) && (length > 0))
+	{
+		node = xmlnode_from_str(contents, length);
+
+		/* If we were unable to parse the file then save its contents to a backup file */
+		if (node == NULL)
+		{
+			gchar *filename_temp;
+
+			filename_temp = g_strdup_printf("%s~", filename);
+			gaim_debug_error("util", "Error parsing file %s.  Rrenaming old "
+							 "file to %s\n", filename_full, filename_temp);
+			gaim_util_write_data_to_file(filename_temp, contents, length);
+			g_free(filename_temp);
+		}
+
+		g_free(contents);
+	}
+
+	/* If we could not parse the file then show the user an error message */
+	if (node == NULL)
+	{
+		gchar *title, *msg;
+		title = g_strdup_printf(_("Error Reading %s"), filename);
+		msg = g_strdup_printf(_("An error was encountered reading your "
+					"%s.  They have not been loaded, and the old file "
+					"been renamed to %s~."), description, filename_full);
+		gaim_notify_error(NULL, NULL, title, msg);
+		g_free(title);
+		g_free(msg);
+	}
+
+	g_free(filename_full);
+
+	return node;
+}
+
 /*
  * Like mkstemp() but returns a file pointer, uses a pre-set template,
  * uses the semantics of tempnam() for the directory to use and allocates
--- a/src/util.h	Sun Dec 26 18:58:36 2004 +0000
+++ b/src/util.h	Sun Dec 26 22:52:52 2004 +0000
@@ -31,6 +31,7 @@
 #include <stdio.h>
 
 #include "account.h"
+#include "xmlnode.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -395,6 +396,23 @@
 									  size_t size);
 
 /**
+ * Read the contents of a given file and parse the results into an
+ * xmlnode tree structure.  This is intended to be used to read
+ * Gaim's configuration xml files (prefs.xml, pounces.xml, etc.)
+ *
+ * @param filename    The basename of the file to open in the gaim_user_dir.
+ * @param description A very short description of the contents of this
+ *                    file.  This is used in error messages shown to the
+ *                    user when the file can not be opened.  For example,
+ *                    "preferences," or "buddy pounces."
+ *
+ * @return An xmlnode tree of the contents of the given file.  Or NULL, if
+ *         the file does not exist or there was an error reading the file.
+ */
+xmlnode *gaim_util_read_xml_from_file(const char *filename,
+									  const char *description);
+
+/**
  * Creates a temporary file and returns a file pointer to it.
  *
  * This is like mkstemp(), but returns a file pointer and uses a
--- a/src/xmlnode.c	Sun Dec 26 18:58:36 2004 +0000
+++ b/src/xmlnode.c	Sun Dec 26 22:52:52 2004 +0000
@@ -148,7 +148,7 @@
 	xmlnode_insert_child(node, attrib_node);
 }
 
-const char*
+const char *
 xmlnode_get_attrib(xmlnode *node, const char *attr)
 {
 	xmlnode *x;
@@ -231,7 +231,6 @@
 
 	g_return_val_if_fail(node != NULL, NULL);
 
-
 	for(c = node->child; c; c = c->next) {
 		if(c->type == XMLNODE_TYPE_DATA) {
 			if(!str)
@@ -246,7 +245,7 @@
 	return g_string_free(str, FALSE);
 }
 
-static gchar *
+static char *
 xmlnode_to_str_helper(xmlnode *node, int *len, gboolean formatting, int depth)
 {
 	GString *text = g_string_new("");
@@ -317,16 +316,16 @@
 	return g_string_free(text, FALSE);
 }
 
-gchar *
+char *
 xmlnode_to_str(xmlnode *node, int *len)
 {
 	return xmlnode_to_str_helper(node, len, FALSE, 0);
 }
 
-gchar *
+char *
 xmlnode_to_formatted_str(xmlnode *node, int *len)
 {
-	gchar *xml, *xml_with_declaration;
+	char *xml, *xml_with_declaration;
 
 	xml = xmlnode_to_str_helper(node, len, TRUE, 0);
 	xml_with_declaration =
--- a/src/xmlnode.h	Sun Dec 26 18:58:36 2004 +0000
+++ b/src/xmlnode.h	Sun Dec 26 22:52:52 2004 +0000
@@ -161,7 +161,7 @@
  * @return The node repersented as a string.  You must
  *         g_free this string when finished using it.
  */
-gchar *xmlnode_to_str(xmlnode *node, int *len);
+char *xmlnode_to_str(xmlnode *node, int *len);
 
 /**
  * Returns the node in a string of human readable xml.
@@ -173,7 +173,7 @@
  *         tab and new line characters.  You must
  *         g_free this string when finished using it.
  */
-gchar *xmlnode_to_formatted_str(xmlnode *node, int *len);
+char *xmlnode_to_formatted_str(xmlnode *node, int *len);
 
 /**
  * Creates a node from a string of XML.  Calling this on the