changeset 8401:c13a4913a071

[gaim-migrate @ 9130] better error processing for jabber committer: Tailor Script <tailor@pidgin.im>
author Nathan Walp <nwalp@pidgin.im>
date Fri, 05 Mar 2004 23:42:34 +0000
parents 0383e55cd658
children fcfb1c08d402
files src/protocols/jabber/auth.c src/protocols/jabber/buddy.c src/protocols/jabber/chat.c src/protocols/jabber/jabber.c src/protocols/jabber/jabber.h src/protocols/jabber/jutil.c src/protocols/jabber/jutil.h src/protocols/jabber/presence.c
diffstat 8 files changed, 186 insertions(+), 243 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/jabber/auth.c	Fri Mar 05 19:09:59 2004 +0000
+++ b/src/protocols/jabber/auth.c	Fri Mar 05 23:42:34 2004 +0000
@@ -178,30 +178,18 @@
 	if(type && !strcmp(type, "result")) {
 		jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
 	} else {
-		xmlnode *error = xmlnode_get_child(packet, "error");
-		const char *err_code = NULL;
-		char *err_text = NULL;
-		char *buf;
+		char *msg = jabber_parse_error(js, packet);
+		xmlnode *error;
+		const char *err_code;
 
-		if(error) {
-			err_code = xmlnode_get_attrib(error, "code");
-			err_text = xmlnode_get_data(error);
+		if((error = xmlnode_get_child(packet, "error")) &&
+					(err_code = xmlnode_get_attrib(error, "code")) &&
+					!strcmp(err_code, "401")) {
+			js->gc->wants_to_die = TRUE;
 		}
 
-		if(!err_code)
-			err_code = "";
-		if(!err_text)
-			err_text = g_strdup(_("Unknown"));
-
-		if(!strcmp(err_code, "401"))
-			js->gc->wants_to_die = TRUE;
-
-		buf = g_strdup_printf("Error %s: %s",
-				err_code, err_text);
-
-		gaim_connection_error(js->gc, buf);
-		g_free(err_text);
-		g_free(buf);
+		gaim_connection_error(js->gc, msg);
+		g_free(msg);
 	}
 }
 
@@ -216,20 +204,9 @@
 		gaim_connection_error(js->gc, _("Invalid response from server."));
 		return;
 	} else if(!strcmp(type, "error")) {
-		/* XXX: still need to handle XMPP-style errors */
-		xmlnode *error;
-		char *buf, *err_txt = NULL;
-		const char *code = NULL;
-		if((error = xmlnode_get_child(packet, "error"))) {
-			code = xmlnode_get_attrib(error, "code");
-			err_txt = xmlnode_get_data(error);
-		}
-		buf = g_strdup_printf("%s%s%s", code ? code : "", code ? ": " : "",
-				err_txt ? err_txt : _("Unknown Error"));
-		gaim_connection_error(js->gc, buf);
-		if(err_txt)
-			g_free(err_txt);
-		g_free(buf);
+		char *msg = jabber_parse_error(js, packet);
+		gaim_connection_error(js->gc, msg);
+		g_free(msg);
 	} else if(!strcmp(type, "result")) {
 		query = xmlnode_get_child(packet, "query");
 		if(js->stream_id && xmlnode_get_child(query, "digest")) {
@@ -481,35 +458,12 @@
 
 void jabber_auth_handle_failure(JabberStream *js, xmlnode *packet)
 {
-	const char *ns = xmlnode_get_attrib(packet, "xmlns");
+	char *msg = jabber_parse_error(js, packet);
 
-	if(!ns)
+	if(!msg) {
 		gaim_connection_error(js->gc, _("Invalid response from server."));
-	else if(!strcmp(ns, "urn:ietf:params:xml:ns:xmpp-sasl")) {
-		if(xmlnode_get_child(packet, "bad-protocol")) {
-			gaim_connection_error(js->gc, _("Bad Protocol"));
-		} else if(xmlnode_get_child(packet, "encryption-required")) {
-			js->gc->wants_to_die = TRUE;
-			gaim_connection_error(js->gc, _("Encryption Required"));
-		} else if(xmlnode_get_child(packet, "invalid-authzid")) {
-			js->gc->wants_to_die = TRUE;
-			gaim_connection_error(js->gc, _("Invalid authzid"));
-		} else if(xmlnode_get_child(packet, "invalid-mechanism")) {
-			js->gc->wants_to_die = TRUE;
-			gaim_connection_error(js->gc, _("Invalid Mechanism"));
-		} else if(xmlnode_get_child(packet, "invalid-realm")) {
-			gaim_connection_error(js->gc, _("Invalid Realm"));
-		} else if(xmlnode_get_child(packet, "mechanism-too-weak")) {
-			js->gc->wants_to_die = TRUE;
-			gaim_connection_error(js->gc, _("Mechanism Too Weak"));
-		} else if(xmlnode_get_child(packet, "not-authorized")) {
-			js->gc->wants_to_die = TRUE;
-			gaim_connection_error(js->gc, _("Not Authorized"));
-		} else if(xmlnode_get_child(packet, "temporary-auth-failure")) {
-			gaim_connection_error(js->gc,
-					_("Temporary Authentication Failure"));
-		} else {
-			gaim_connection_error(js->gc, _("Authentication Failure"));
-		}
+	} else {
+		gaim_connection_error(js->gc, msg);
+		g_free(msg);
 	}
 }
--- a/src/protocols/jabber/buddy.c	Fri Mar 05 19:09:59 2004 +0000
+++ b/src/protocols/jabber/buddy.c	Fri Mar 05 23:42:34 2004 +0000
@@ -541,8 +541,6 @@
 	if(!from)
 		return;
 
-	/* XXX: make this handle handle errors */
-
 	resource_name = jabber_get_resource(from);
 	bare_jid = jabber_get_bare_jid(from);
 
--- a/src/protocols/jabber/chat.c	Fri Mar 05 19:09:59 2004 +0000
+++ b/src/protocols/jabber/chat.c	Fri Mar 05 23:42:34 2004 +0000
@@ -327,27 +327,12 @@
 			}
 		}
 	} else if(!strcmp(type, "error")) {
-		xmlnode *errnode = xmlnode_get_child(packet, "error");
-		const char *code = NULL;
-		char *code_txt = NULL;
-		char *msg;
-		char *text = NULL;
+		char *msg = jabber_parse_error(js, packet);
 
-		if(errnode) {
-			code = xmlnode_get_attrib(errnode, "code");
-			text = xmlnode_get_data(errnode);
-		}
-
-		if(code)
-			code_txt = g_strdup_printf(_(" (Code %s)"), code);
-
-		msg = g_strdup_printf("%s%s", text ? text : "", code_txt ? code_txt : "");
 		gaim_notify_error(js->gc, _("Configuration error"), _("Configuration error"), msg);
 
-		g_free(msg);
-		if(code_txt)
-			g_free(code_txt);
-
+		if(msg)
+			g_free(msg);
 		return;
 	}
 
@@ -418,7 +403,13 @@
 	const char *type = xmlnode_get_attrib(packet, "type");
 
 	if(type && !strcmp(type, "error")) {
-		/* XXX: handle an error (you'll get a 409 if the nick is already registered) */
+		char *msg = jabber_parse_error(js, packet);
+
+		gaim_notify_error(js->gc, _("Registration error"), _("Registration error"), msg);
+
+		if(msg)
+			g_free(msg);
+		return;
 	}
 }
 
@@ -481,28 +472,12 @@
 			}
 		}
 	} else if(!strcmp(type, "error")) {
-		/* XXX: how many places is this code duplicated?  Fix it, immediately */
-		xmlnode *errnode = xmlnode_get_child(packet, "error");
-		const char *code = NULL;
-		char *code_txt = NULL;
-		char *msg;
-		char *text = NULL;
+		char *msg = jabber_parse_error(js, packet);
 
-		if(errnode) {
-			code = xmlnode_get_attrib(errnode, "code");
-			text = xmlnode_get_data(errnode);
-		}
-
-		if(code)
-			code_txt = g_strdup_printf(_(" (Code %s)"), code);
-
-		msg = g_strdup_printf("%s%s", text ? text : "", code_txt ? code_txt : "");
 		gaim_notify_error(js->gc, _("Registration error"), _("Registration error"), msg);
 
-		g_free(msg);
-		if(code_txt)
-			g_free(code_txt);
-
+		if(msg)
+			g_free(msg);
 		return;
 	}
 
@@ -620,18 +595,24 @@
 		return;
 
 	if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) {
-		/* XXX: error msg */
+		char *err = jabber_parse_error(js,packet);
+		gaim_notify_error(js->gc, _("Roomlist Error"),
+				_("Error retreiving roomlist"), err);
 		gaim_roomlist_set_in_progress(js->roomlist, FALSE);
 		gaim_roomlist_unref(js->roomlist);
 		js->roomlist = NULL;
+		g_free(err);
 		return;
 	}
 
 	if(!(query = xmlnode_get_child(packet, "query"))) {
-		/* XXX: error msg */
+		char *err = jabber_parse_error(js, packet);
+		gaim_notify_error(js->gc, _("Roomlist Error"),
+				_("Error retreiving roomlist"), err);
 		gaim_roomlist_set_in_progress(js->roomlist, FALSE);
 		gaim_roomlist_unref(js->roomlist);
 		js->roomlist = NULL;
+		g_free(err);
 		return;
 	}
 
--- a/src/protocols/jabber/jabber.c	Fri Mar 05 19:09:59 2004 +0000
+++ b/src/protocols/jabber/jabber.c	Fri Mar 05 23:42:34 2004 +0000
@@ -90,7 +90,24 @@
 static void jabber_bind_result_cb(JabberStream *js, xmlnode *packet,
 		gpointer data)
 {
-	/* XXX: check for errors, re-set our own js->user JID */
+	const char *type = xmlnode_get_attrib(packet, "type");
+	xmlnode *bind;
+
+	if(type && !strcmp(type, "result") &&
+			(bind = xmlnode_get_child_with_namespace(packet, "bind", "urn:ietf:params:xml:ns:xmpp-bind"))) {
+		xmlnode *jid;
+		char *full_jid;
+		if((jid = xmlnode_get_child(bind, "jid")) && (full_jid = xmlnode_get_data(jid))) {
+			jabber_id_free(js->user);
+			if(!(js->user = jabber_id_new(full_jid))) {
+				gaim_connection_error(js->gc, _("Invalid response from server."));
+			}
+		}
+	} else {
+		char *msg = jabber_parse_error(js, packet);
+		gaim_connection_error(js->gc, msg);
+		g_free(msg);
+	}
 
 	jabber_session_init(js);
 }
@@ -127,74 +144,10 @@
 
 static void jabber_stream_handle_error(JabberStream *js, xmlnode *packet)
 {
-	xmlnode *textnode;
-	char *error_text = NULL;
-	const char *text;
-	char *buf;
+	char *msg = jabber_parse_error(js, packet);
 
-	if(xmlnode_get_child(packet, "bad-format")) {
-		text = _("Bad Format");
-	} else if(xmlnode_get_child(packet, "bad-namespace-prefix")) {
-		text = _("Bad Namespace Prefix");
-	} else if(xmlnode_get_child(packet, "conflict")) {
-		js->gc->wants_to_die = TRUE;
-		text = _("Resource Conflict");
-	} else if(xmlnode_get_child(packet, "connection-timeout")) {
-		text = _("Connection Timeout");
-	} else if(xmlnode_get_child(packet, "host-gone")) {
-		text = _("Host Gone");
-	} else if(xmlnode_get_child(packet, "host-unknown")) {
-		text = _("Host Unknown");
-	} else if(xmlnode_get_child(packet, "improper-addressing")) {
-		text = _("Improper Addressing");
-	} else if(xmlnode_get_child(packet, "internal-server-error")) {
-		text = _("Internal Server Error");
-	} else if(xmlnode_get_child(packet, "invalid-id")) {
-		text = _("Invalid ID");
-	} else if(xmlnode_get_child(packet, "invalid-namespace")) {
-		text = _("Invalid Namespace");
-	} else if(xmlnode_get_child(packet, "invalid-xml")) {
-		text = _("Invalid XML");
-	} else if(xmlnode_get_child(packet, "nonmatching-hosts")) {
-		text = _("Non-matching Hosts");
-	} else if(xmlnode_get_child(packet, "not-authorized")) {
-		text = _("Not Authorized");
-	} else if(xmlnode_get_child(packet, "policy-violation")) {
-		text = _("Policy Violation");
-	} else if(xmlnode_get_child(packet, "remote-connection-failed")) {
-		text = _("Remote Connection Failed");
-	} else if(xmlnode_get_child(packet, "resource-constraint")) {
-		text = _("Resource Constraint");
-	} else if(xmlnode_get_child(packet, "restricted-xml")) {
-		text = _("Restricted XML");
-	} else if(xmlnode_get_child(packet, "see-other-host")) {
-		text = _("See Other Host");
-	} else if(xmlnode_get_child(packet, "system-shutdown")) {
-		text = _("System Shutdown");
-	} else if(xmlnode_get_child(packet, "undefined-condition")) {
-		text = _("Undefined Condition");
-	} else if(xmlnode_get_child(packet, "unsupported-encoding")) {
-		text = _("Unsupported Encoding");
-	} else if(xmlnode_get_child(packet, "unsupported-stanza-type")) {
-		text = _("Unsupported Stanza Type");
-	} else if(xmlnode_get_child(packet, "unsupported-version")) {
-		text = _("Unsupported Version");
-	} else if(xmlnode_get_child(packet, "xml-not-well-formed")) {
-		text = _("XML Not Well Formed");
-	} else {
-		text = _("Stream Error");
-	}
-
-	if((textnode = xmlnode_get_child(packet, "text")))
-		error_text = xmlnode_get_data(textnode);
-
-	buf = g_strdup_printf("%s%s%s", text,
-			error_text ? ": " : "",
-			error_text ? error_text : "");
-	gaim_connection_error(js->gc, buf);
-	g_free(buf);
-	if(error_text)
-		g_free(error_text);
+	gaim_connection_error(js->gc, msg);
+	g_free(msg);
 }
 
 static void tls_init(JabberStream *js);
@@ -235,7 +188,7 @@
 
 	/* because printing a tab to debug every minute gets old */
 	if(strcmp(data, "\t"))
-		gaim_debug(GAIM_DEBUG_MISC, "jabber", "Sending%s: %s\n", 
+		gaim_debug(GAIM_DEBUG_MISC, "jabber", "Sending%s: %s\n",
 				js->gsc ? " (ssl)" : "", data);
 
 	if(js->gsc) {
@@ -475,21 +428,14 @@
 				_("Registration Successful"), buf);
 		g_free(buf);
 	} else {
-		char *error;
-		xmlnode *y;
+		char *msg = jabber_parse_error(js, packet);
 
-		if((y = xmlnode_get_child(packet, "error"))) {
-			error = xmlnode_get_data(y);
-		} else {
-			error = g_strdup(_("Unknown Error"));
-		}
+		if(!msg)
+			msg = g_strdup(_("Unknown Error"));
 
-		buf = g_strdup_printf(_("Registration of %s@%s failed: %s"),
-				js->user->node, js->user->domain, error);
 		gaim_notify_error(NULL, _("Registration Failed"),
-				_("Registration Failed"), buf);
-		g_free(buf);
-		g_free(error);
+				_("Registration Failed"), msg);
+		g_free(msg);
 	}
 	jabber_connection_schedule_close(js);
 }
@@ -1033,23 +979,11 @@
 		gaim_notify_info(js->gc, _("Password Changed"), _("Password Changed"),
 				_("Your password has been changed."));
 	} else {
-		xmlnode *error;
-		char *buf, *error_txt = NULL;
-
-
-		if((error = xmlnode_get_child(packet, "error")))
-			error_txt = xmlnode_get_data(error);
+		char *msg = jabber_parse_error(js, packet);
 
-		if(error_txt) {
-			buf = g_strdup_printf(_("Error changing password: %s"),
-					error_txt);
-			g_free(error_txt);
-		} else {
-			buf = g_strdup(_("Unknown error occurred changing password"));
-		}
-
-		gaim_notify_error(js->gc, _("Error"), _("Error"), buf);
-		g_free(buf);
+		gaim_notify_error(js->gc, _("Error changing password"),
+				_("Error changing password"), msg);
+		g_free(msg);
 	}
 }
 
@@ -1190,6 +1124,99 @@
 	jabber_id_free(jid);
 }
 
+
+char *jabber_parse_error(JabberStream *js, xmlnode *packet)
+{
+	xmlnode *error;
+	const char *code = NULL, *text = NULL;
+	const char *xmlns = xmlnode_get_attrib(packet, "xmlns");
+	char *cdata = NULL;
+
+	if((error = xmlnode_get_child(packet, "error"))) {
+		cdata = xmlnode_get_data(error);
+		code = xmlnode_get_attrib(error, "code");
+
+		/* Stanza errors */
+		if(xmlnode_get_child(error, "bad-request")) {
+			text = _("Bad Request");
+		} else if(xmlnode_get_child(error, "conflict")) {
+			text = _("Conflict");
+		} else if(xmlnode_get_child(error, "feature-not-implemented")) {
+			text = _("Feature Not Implemented");
+		} else if(xmlnode_get_child(error, "forbidden")) {
+			text = _("Forbidden");
+		} else if(xmlnode_get_child(error, "gone")) {
+			text = _("Gone");
+		} else if(xmlnode_get_child(error, "internal-server-error")) {
+			text = _("Internal Server Error");
+		} else if(xmlnode_get_child(error, "item-not-found")) {
+			text = _("Item Not Found");
+		} else if(xmlnode_get_child(error, "jid-malformed")) {
+			text = _("Malformed Jabber ID");
+		} else if(xmlnode_get_child(error, "not-acceptable")) {
+			text = _("Not Acceptable");
+		} else if(xmlnode_get_child(error, "not-allowed")) {
+			text = _("Not Allowed");
+		} else if(xmlnode_get_child(error, "not-authorized")) {
+			text = _("Not Authorized");
+		} else if(xmlnode_get_child(error, "payment-required")) {
+			text = _("Payment Required");
+		} else if(xmlnode_get_child(error, "recipient-unavailable")) {
+			text = _("Recipient Unavailable");
+		} else if(xmlnode_get_child(error, "redirect")) {
+			/* XXX */
+		} else if(xmlnode_get_child(error, "registration-required")) {
+			text = _("Registration Required");
+		} else if(xmlnode_get_child(error, "remote-server-not-found")) {
+			text = _("Remote Server Not Found");
+		} else if(xmlnode_get_child(error, "remote-server-timeout")) {
+			text = _("Remote Server Timeout");
+		} else if(xmlnode_get_child(error, "resource-constraint")) {
+			text = _("Server Overloaded");
+		} else if(xmlnode_get_child(error, "service-unavailable")) {
+			text = _("Service Unavailable");
+		} else if(xmlnode_get_child(error, "subscription-required")) {
+			text = _("Subscription Required");
+		} else if(xmlnode_get_child(error, "unexpected-request")) {
+			text = _("Unexpected Request");
+		} else if(xmlnode_get_child(error, "undefined-condition")) {
+			text = _("Unknown Error");
+		}
+	} else if(xmlns && !strcmp(xmlns, "urn:ietf:params:xml:ns:xmpp-sasl")) {
+		if(xmlnode_get_child(packet, "aborted")) {
+			js->gc->wants_to_die = TRUE;
+			text = _("Authorization Aborted");
+		} else if(xmlnode_get_child(error, "incorrect-encoding")) {
+			text = _("Incorrect encoding in authorization");
+		} else if(xmlnode_get_child(error, "invalid-authzid")) {
+			js->gc->wants_to_die = TRUE;
+			text = _("Invalid authzid");
+		} else if(xmlnode_get_child(error, "invalid-mechanism")) {
+			js->gc->wants_to_die = TRUE;
+			text = _("Invalid Authorization Mechanism");
+		} else if(xmlnode_get_child(error, "mechanism-too-weak")) {
+			js->gc->wants_to_die = TRUE;
+			text = _("Authorization mechanism too weak");
+		} else if(xmlnode_get_child(error, "not-authorized")) {
+			js->gc->wants_to_die = TRUE;
+			text = _("Not Authorized");
+		} else if(xmlnode_get_child(error, "temporary-auth-failure")) {
+			text = _("Temporary Authentication Failure");
+		} else {
+			text = _("Authentication Failure");
+		}
+	}
+
+	if(text || cdata) {
+		char *ret = g_strdup_printf("%s%s%s", code ? code : "",
+				code ? ": " : "", text ? text : cdata);
+		g_free(cdata);
+		return ret;
+	} else {
+		return NULL;
+	}
+}
+
 static GaimPluginProtocolInfo prpl_info =
 {
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME,
@@ -1328,7 +1355,7 @@
 
 	ppref = g_new0(struct proto_pref, 1);
 	ppref->key = "/plugins/prpl/jabber/hide_os";
-	ppref->label = _("Hide Operating System"); /* XXX: come up with a better name for this */
+	ppref->label = _("Hide Operating System");
 	prpl_info.protocol_prefs = g_list_append(prpl_info.protocol_prefs, ppref);
 }
 
--- a/src/protocols/jabber/jabber.h	Fri Mar 05 19:09:59 2004 +0000
+++ b/src/protocols/jabber/jabber.h	Fri Mar 05 23:42:34 2004 +0000
@@ -108,4 +108,6 @@
 
 char *jabber_get_next_id(JabberStream *js);
 
+char *jabber_parse_error(JabberStream *js, xmlnode *packet);
+
 #endif /* _GAIM_JABBER_H_ */
--- a/src/protocols/jabber/jutil.c	Fri Mar 05 19:09:59 2004 +0000
+++ b/src/protocols/jabber/jutil.c	Fri Mar 05 23:42:34 2004 +0000
@@ -30,7 +30,7 @@
 {
 	struct tm t;
 	time_t retval = 0;
-	char buf[32]; 
+	char buf[32];
 	char *c;
 	int tzoff = 0;
 
@@ -319,3 +319,4 @@
 
 	return NULL;
 }
+
--- a/src/protocols/jabber/jutil.h	Fri Mar 05 19:09:59 2004 +0000
+++ b/src/protocols/jabber/jutil.h	Fri Mar 05 23:42:34 2004 +0000
@@ -24,6 +24,7 @@
 
 #include "account.h"
 #include "conversation.h"
+#include "xmlnode.h"
 
 
 typedef struct _JabberID {
--- a/src/protocols/jabber/presence.c	Fri Mar 05 19:09:59 2004 +0000
+++ b/src/protocols/jabber/presence.c	Fri Mar 05 23:42:34 2004 +0000
@@ -39,11 +39,12 @@
 {
 	JabberChat *chat = val;
 	xmlnode *presence = user_data;
-	const char *chat_bare_jid = key;
+	char *chat_full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server,
+			chat->handle);
 
-	/* XXX: FIXME! */
-	xmlnode_set_attrib(presence, "to", chat_bare_jid);
+	xmlnode_set_attrib(presence, "to", chat_full_jid);
 	jabber_send(chat->js, presence);
+	g_free(chat_full_jid);
 }
 
 void jabber_presence_fake_to_self(JabberStream *js, const char *away_state, const char *msg) {
@@ -209,20 +210,10 @@
 	}
 
 	if(type && !strcmp(type, "error")) {
-		const char *code = NULL;
-		char *err_txt = NULL;
+		char *msg = jabber_parse_error(js, packet);
 
 		state = JABBER_STATE_ERROR;
-		if((y = xmlnode_get_child(packet, "error")) != NULL) {
-			/* XXX: need to handle new XMPP-style errors */
-			code = xmlnode_get_attrib(y, "code");
-			err_txt = xmlnode_get_data(y);
-		}
-		jb->error_msg = g_strdup_printf("%s%s%s", code ? code : "",
-				code ? ": " : "", err_txt ? err_txt :
-				_("Unknown Error in presence"));
-		if(err_txt)
-			g_free(err_txt);
+		jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence"));
 	} else if(type && !strcmp(type, "subscribe")) {
 		struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1);
 		char *msg = g_strdup_printf(_("The user %s wants to add you to their buddy list."), from);
@@ -301,35 +292,17 @@
 		char *room_jid = g_strdup_printf("%s@%s", jid->node, jid->domain);
 
 		if(state == JABBER_STATE_ERROR) {
-			const char *code = NULL;
-			char *text = NULL;
-			char *buf;
-			xmlnode *error = xmlnode_get_child(packet, "error");
-			if(error) {
-				/* I should make my own messages so they can be
-				 * translated, but i'm tired */
-				code = xmlnode_get_attrib(error, "code");
-				text = xmlnode_get_data(error);
-			}
-
-			if(!code)
-				code = "";
+			char *title, *msg = jabber_parse_error(js, packet);
 
 			if(chat->conv) {
-				if(!text)
-					text = g_strdup(_("Unknown error"));
-				buf = g_strdup_printf("Error %s in chat %s: %s",
-						code, from, text);
+				title = g_strdup_printf(_("Error in chat %s"), from);
 				serv_got_chat_left(js->gc, chat->id);
 			} else {
-				if(!text)
-					text = g_strdup(_("Unable to join chat"));
-				buf = g_strdup_printf("Error %s joining chat %s: %s",
-						code, from, text);
+				title = g_strdup_printf(_("Error joining chat %s"), from);
 			}
-			gaim_notify_error(js->gc, _("Error"), _("Error"), buf);
-			g_free(text);
-			g_free(buf);
+			gaim_notify_error(js->gc, title, title, msg);
+			g_free(title);
+			g_free(msg);
 
 			jabber_chat_destroy(chat);
 			jabber_id_free(jid);
@@ -368,6 +341,10 @@
 					if(!(nick = xmlnode_get_attrib(item, "nick")))
 						continue;
 					nick_change = TRUE;
+					if(!strcmp(jid->resource, chat->handle)) {
+						g_free(chat->handle);
+						chat->handle = g_strdup(nick);
+					}
 					gaim_conv_chat_rename_user(GAIM_CONV_CHAT(chat->conv), jid->resource, nick);
 					break;
 				}
@@ -386,6 +363,8 @@
 				chat->id = i++;
 				chat->muc = muc;
 				chat->conv = serv_got_joined_chat(js->gc, chat->id, room_jid);
+				g_free(chat->handle);
+				chat->handle = g_strdup(jid->resource);
 				gaim_conv_chat_set_nick(GAIM_CONV_CHAT(chat->conv), jid->resource);
 			}