changeset 17553:61005dea822b

Cleanup, fix a leak and prevent the inbound xml from being parsed twice for every message.
author Daniel Atallah <daniel.atallah@gmail.com>
date Fri, 08 Jun 2007 06:04:06 +0000
parents a8aa651f341f
children a1d05bc43d95
files libpurple/protocols/bonjour/bonjour.c libpurple/protocols/bonjour/jabber.c libpurple/protocols/bonjour/jabber.h
diffstat 3 files changed, 71 insertions(+), 89 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/bonjour/bonjour.c	Fri Jun 08 05:06:47 2007 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Fri Jun 08 06:04:06 2007 +0000
@@ -277,7 +277,7 @@
 		return;
 	}
 
-	bonjour_jabber_close_conversation(((BonjourData*)(connection->proto_data))->jabber_data, buddy);
+	bonjour_jabber_close_conversation(buddy);
 }
 
 static char *
@@ -320,6 +320,8 @@
 static gboolean
 plugin_unload(PurplePlugin *plugin)
 {
+	/* These shouldn't happen here because they are allocated in _init() */
+
 	g_free(default_firstname);
 	g_free(default_lastname);
 	g_free(default_hostname);
--- a/libpurple/protocols/bonjour/jabber.c	Fri Jun 08 05:06:47 2007 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Fri Jun 08 06:04:06 2007 +0000
@@ -28,7 +28,6 @@
 #endif
 #include <sys/types.h>
 #include <glib.h>
-#include <glib/gprintf.h>
 #include <unistd.h>
 #include <fcntl.h>
 
@@ -125,9 +124,9 @@
 }
 
 static void
-_jabber_parse_and_write_message_to_ui(char *message, PurpleConnection *connection, PurpleBuddy *gb)
+_jabber_parse_and_write_message_to_ui(xmlnode *message_node, PurpleConnection *connection, PurpleBuddy *gb)
 {
-	xmlnode *message_node, *body_node, *html_node, *events_node;
+	xmlnode *body_node, *html_node, *events_node;
 	char *body, *html_body = NULL;
 	const char *ichat_balloon_color = NULL;
 	const char *ichat_text_color = NULL;
@@ -136,16 +135,9 @@
 	const char *font_color = NULL;
 	gboolean composing_event = FALSE;
 
-	/* Parsing of the message */
-	message_node = xmlnode_from_str(message, strlen(message));
-	if (message_node == NULL)
+	body_node = xmlnode_get_child(message_node, "body");
+	if (body_node == NULL)
 		return;
-
-	body_node = xmlnode_get_child(message_node, "body");
-	if (body_node == NULL) {
-		xmlnode_free(message_node);
-		return;
-	}
 	body = xmlnode_get_data(body_node);
 
 	html_node = xmlnode_get_child(message_node, "html");
@@ -171,11 +163,8 @@
 				font_color = xmlnode_get_attrib(html_body_font_node, "color");
 				html_body = xmlnode_get_data(html_body_font_node);
 				if (html_body == NULL)
-				{
-					gint garbage = -1;
 					/* This is the kind of formated messages that Purple creates */
-					html_body = xmlnode_to_str(html_body_font_node, &garbage);
-				}
+					html_body = xmlnode_to_str(html_body_font_node, NULL);
 			}
 		}
 	}
@@ -191,7 +180,6 @@
 		{
 			/* The user is just typing */
 			/* TODO: Deal with typing notification */
-			xmlnode_free(message_node);
 			g_free(body);
 			g_free(html_body);
 			return;
@@ -207,8 +195,9 @@
 		if (font_size == NULL) font_size = "3";
 		if (ichat_text_color == NULL) ichat_text_color = "#000000";
 		if (ichat_balloon_color == NULL) ichat_balloon_color = "#FFFFFF";
-		body = g_strconcat("<font face='", font_face, "' size='", font_size, "' color='", ichat_text_color,
-							"' back='", ichat_balloon_color, "'>", html_body, "</font>", NULL);
+		body = g_strdup_printf("<font face='%s' size='%s' color='%s' back='%s'>%s</font>",
+				       font_face, font_size, ichat_text_color, ichat_balloon_color,
+				       html_body);
 	}
 
 	/* TODO: Should we do something with "composing_event" here? */
@@ -216,8 +205,6 @@
 	/* Send the message to the UI */
 	serv_got_im(connection, gb->name, body, 0, time(NULL));
 
-	/* Free all the strings and nodes (the attributes are freed with their nodes) */
-	xmlnode_free(message_node);
 	g_free(body);
 	g_free(html_body);
 }
@@ -356,7 +343,7 @@
 	 * using a magic string, but xmlnode won't play nice when just
 	 * parsing an end tag
 	 */
-	if (purple_str_has_prefix(message, STREAM_END) || (closed_conversation == TRUE)) {
+	if (closed_conversation || purple_str_has_prefix(message, STREAM_END)) {
 		char *closed_conv_message;
 
 		/* Close the socket, clear the watcher and free memory */
@@ -373,11 +360,14 @@
 		closed_conv_message = g_strdup_printf(_("%s has closed the conversation."), gb->name);
 		purple_conversation_write(conversation, NULL, closed_conv_message, PURPLE_MESSAGE_SYSTEM, time(NULL));
 		g_free(closed_conv_message);
-	} else {
+	} else if (message_node != NULL) {
 		/* Parse the message to get the data and send to the ui */
-		_jabber_parse_and_write_message_to_ui(message, account->gc, gb);
+		_jabber_parse_and_write_message_to_ui(message_node, account->gc, gb);
+	} else {
+		/* TODO: Deal with receiving only a partial message */
 	}
 
+	g_free(message);
 	if (message_node != NULL)
 		xmlnode_free(message_node);
 }
@@ -426,7 +416,6 @@
 		bb->conversation->socket = client_socket;
 		bb->conversation->stream_started = FALSE;
 		bb->conversation->buddy_name = g_strdup(gb->name);
-		bb->conversation->message_id = 1;
 
 		if (bb->conversation->stream_started == FALSE) {
 			/* Start the stream */
@@ -517,75 +506,62 @@
 int
 bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body)
 {
-	xmlnode *message_node = NULL;
-	gchar *message = NULL;
-	gint message_length = -1;
-	xmlnode *message_body_node = NULL;
-	xmlnode *message_html_node = NULL;
-	xmlnode *message_html_body_node = NULL;
-	xmlnode *message_html_body_font_node = NULL;
-	xmlnode *message_x_node = NULL;
-	PurpleBuddy *gb = NULL;
-	BonjourBuddy *bb = NULL;
-	PurpleConversation *conversation = NULL;
-	char *message_from_ui = NULL;
-	char *stripped_message = NULL;
-	gint ret;
+	xmlnode *message_node, *node, *node2;
+	gchar *message;
+	PurpleBuddy *pb;
+	BonjourBuddy *bb;
+	int ret;
 
-	gb = purple_find_buddy(data->account, to);
-	if (gb == NULL) {
+	pb = purple_find_buddy(data->account, to);
+	if (pb == NULL) {
 		purple_debug_info("bonjour", "Can't send a message to an offline buddy (%s).\n", to);
 		/* You can not send a message to an offline buddy */
 		return -10000;
 	}
 
-	bb = (BonjourBuddy *)gb->proto_data;
+	bb = pb->proto_data;
 
 	/* Check if there is a previously open conversation */
 	if (bb->conversation == NULL)
 	{
-		int socket = _connect_to_buddy(gb);
+		int socket = _connect_to_buddy(pb);
 		if (socket < 0)
 			return -10001;
 
 		bb->conversation = g_new(BonjourJabberConversation, 1);
 		bb->conversation->socket = socket;
 		bb->conversation->stream_started = FALSE;
-		bb->conversation->buddy_name = g_strdup(gb->name);
+		bb->conversation->buddy_name = g_strdup(pb->name);
 		bb->conversation->watcher_id = purple_input_add(bb->conversation->socket,
-				PURPLE_INPUT_READ, _client_socket_handler, gb);
+				PURPLE_INPUT_READ, _client_socket_handler, pb);
 	}
 
+	message_node = xmlnode_new("message");
+	xmlnode_set_attrib(message_node, "to", bb->name);
+	xmlnode_set_attrib(message_node, "from", purple_account_get_username(data->account));
+	xmlnode_set_attrib(message_node, "type", "chat");
+
 	/* Enclose the message from the UI within a "font" node */
-	message_body_node = xmlnode_new("body");
-	stripped_message = purple_markup_strip_html(body);
-	xmlnode_insert_data(message_body_node, stripped_message, strlen(stripped_message));
-	g_free(stripped_message);
+	node = xmlnode_new_child(message_node, "body");
+	message = purple_markup_strip_html(body);
+	xmlnode_insert_data(node, message, strlen(message));
+	g_free(message);
 
-	message_from_ui = g_strconcat("<font>", body, "</font>", NULL);
-	message_html_body_font_node = xmlnode_from_str(message_from_ui, strlen(message_from_ui));
-	g_free(message_from_ui);
-
-	message_html_body_node = xmlnode_new("body");
-	xmlnode_insert_child(message_html_body_node, message_html_body_font_node);
+	node = xmlnode_new_child(message_node, "html");
+	xmlnode_set_namespace(node, "http://www.w3.org/1999/xhtml");
 
-	message_html_node = xmlnode_new("html");
-	xmlnode_set_attrib(message_html_node, "xmlns", "http://www.w3.org/1999/xhtml");
-	xmlnode_insert_child(message_html_node, message_html_body_node);
-
-	message_x_node = xmlnode_new("x");
-	xmlnode_set_attrib(message_x_node, "xmlns", "jabber:x:event");
-	xmlnode_insert_child(message_x_node, xmlnode_new("composing"));
+	node = xmlnode_new_child(node, "body");
+	message = g_strdup_printf("<font>%s</font>", body);
+	node2 = xmlnode_from_str(message, strlen(message));
+	g_free(message);
+	xmlnode_insert_child(node, node2);
 
-	message_node = xmlnode_new("message");
-	xmlnode_set_attrib(message_node, "to", ((BonjourBuddy*)(gb->proto_data))->name);
-	xmlnode_set_attrib(message_node, "from", data->account->username);
-	xmlnode_set_attrib(message_node, "type", "chat");
-	xmlnode_insert_child(message_node, message_body_node);
-	xmlnode_insert_child(message_node, message_html_node);
-	xmlnode_insert_child(message_node, message_x_node);
+	node = xmlnode_new_child(message_node, "x");
+	xmlnode_set_namespace(node, "jabber:x:event");
+	xmlnode_insert_child(node, xmlnode_new("composing"));
 
-	message = xmlnode_to_str(message_node, &message_length);
+
+	message = xmlnode_to_str(message_node, NULL);
 	xmlnode_free(message_node);
 
 	/* Check if the stream for the conversation has been started */
@@ -594,10 +570,12 @@
 		/* Start the stream */
 		if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1)
 		{
+			PurpleConversation *conv;
+
 			purple_debug_error("bonjour", "Unable to start a conversation\n");
 			purple_debug_warning("bonjour", "send error: %s\n", strerror(errno));
-			conversation = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, data->account);
-			purple_conversation_write(conversation, NULL,
+			conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, data->account);
+			purple_conversation_write(conv, NULL,
 						  _("Unable to send the message, the conversation couldn't be started."),
 						  PURPLE_MESSAGE_SYSTEM, time(NULL));
 			close(bb->conversation->socket);
@@ -625,22 +603,26 @@
 }
 
 void
-bonjour_jabber_close_conversation(BonjourJabber *data, PurpleBuddy *gb)
+bonjour_jabber_close_conversation(PurpleBuddy *pb)
 {
-	BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data;
+	BonjourBuddy *bb = pb->proto_data;
+	BonjourJabberConversation *bconv = bb->conversation;
 
-	if (bb->conversation != NULL)
+	if (bconv != NULL)
 	{
-		/* Send the end of the stream to the other end of the conversation */
-		send(bb->conversation->socket, STREAM_END, strlen(STREAM_END), 0);
-
 		/* Close the socket and remove the watcher */
-		close(bb->conversation->socket);
-		purple_input_remove(bb->conversation->watcher_id);
+		if (bconv->socket >= 0) {
+			/* Send the end of the stream to the other end of the conversation */
+			if (bconv->stream_started)
+				send(bconv->socket, STREAM_END, strlen(STREAM_END), 0);
+			/* TODO: We're really supposed to wait for "</stream:stream>" before closing the socket */
+			close(bconv->socket);
+		}
+		purple_input_remove(bconv->watcher_id);
 
 		/* Free all the data related to the conversation */
-		g_free(bb->conversation->buddy_name);
-		g_free(bb->conversation);
+		g_free(bconv->buddy_name);
+		g_free(bconv);
 		bb->conversation = NULL;
 	}
 }
@@ -657,12 +639,11 @@
 	/* Close all the conversation sockets and remove all the watchers after sending end streams */
 	if (data->account->gc != NULL)
 	{
-		GSList *buddies;
-		GSList *l;
+		GSList *buddies, *l;
 
-		buddies = purple_find_buddies(data->account, data->account->username);
+		buddies = purple_find_buddies(data->account, purple_account_get_username(data->account));
 		for (l = buddies; l; l = l->next)
-			bonjour_jabber_close_conversation(data, l->data);
+			bonjour_jabber_close_conversation(l->data);
 		g_slist_free(buddies);
 	}
 }
--- a/libpurple/protocols/bonjour/jabber.h	Fri Jun 08 05:06:47 2007 +0000
+++ b/libpurple/protocols/bonjour/jabber.h	Fri Jun 08 06:04:06 2007 +0000
@@ -45,7 +45,6 @@
 	gint watcher_id;
 	gchar* buddy_name;
 	gboolean stream_started;
-	gint message_id;
 } BonjourJabberConversation;
 
 /**
@@ -58,7 +57,7 @@
 
 int bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body);
 
-void bonjour_jabber_close_conversation(BonjourJabber *data, PurpleBuddy *gb);
+void bonjour_jabber_close_conversation(PurpleBuddy *gb);
 
 void bonjour_jabber_stop(BonjourJabber *data);