changeset 31081:e023b0378887

Prevent sending ISON messages larger than 512 bytes. Fixes #9692. committer: John Bailey <rekkanoryo@rekkanoryo.org>
author jch@honig.net
date Thu, 30 Dec 2010 01:06:03 +0000
parents 40e5d8c3acca
children 86598f5d7ebd
files COPYRIGHT ChangeLog libpurple/protocols/irc/irc.c libpurple/protocols/irc/irc.h libpurple/protocols/irc/msgs.c
diffstat 5 files changed, 59 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Thu Dec 30 00:58:17 2010 +0000
+++ b/COPYRIGHT	Thu Dec 30 01:06:03 2010 +0000
@@ -223,6 +223,7 @@
 Andrew Hoffman
 Iain Holmes
 Joshua Honeycutt
+Jeffrey Honig
 Nigel Horne
 Jensen Hornick
 Juanjo Molinero Horno
--- a/ChangeLog	Thu Dec 30 00:58:17 2010 +0000
+++ b/ChangeLog	Thu Dec 30 01:06:03 2010 +0000
@@ -1,6 +1,9 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
 version 2.7.10 (??/??/????):
+	IRC:
+	* Don't send ISON messages longer than 512 bytes. (Jeffrey Honig) (#9692)
+
 	libpurple:
 	* Stop sending audio when placing a call on hold. (Jakub Adam) (#13032)
 	* Stop translating gpointers to ints in the dbus API.  This removes
--- a/libpurple/protocols/irc/irc.c	Thu Dec 30 00:58:17 2010 +0000
+++ b/libpurple/protocols/irc/irc.c	Thu Dec 30 01:06:03 2010 +0000
@@ -39,7 +39,7 @@
 
 #define PING_TIMEOUT 60
 
-static void irc_buddy_append(char *name, struct irc_buddy *ib, GString *string);
+static void irc_ison_buddy_init(char *name, struct irc_buddy *ib, GList **list);
 
 static const char *irc_blist_icon(PurpleAccount *a, PurpleBuddy *b);
 static GList *irc_status_types(PurpleAccount *account);
@@ -186,43 +186,62 @@
 /* XXX I don't like messing directly with these buddies */
 gboolean irc_blist_timeout(struct irc_conn *irc)
 {
-	GString *string;
-	char *list, *buf;
-
-	if (irc->ison_outstanding)
-		return TRUE;
-
-	string = g_string_sized_new(512);
-
-	g_hash_table_foreach(irc->buddies, (GHFunc)irc_buddy_append, (gpointer)string);
-
-	list = g_string_free(string, FALSE);
-	if (!list || !strlen(list)) {
-		g_free(list);
+	if (irc->ison_outstanding) {
 		return TRUE;
 	}
 
-	buf = irc_format(irc, "vn", "ISON", list);
-	g_free(list);
-	irc_send(irc, buf);
-	g_free(buf);
+	g_hash_table_foreach(irc->buddies, (GHFunc)irc_ison_buddy_init,
+	                     (gpointer *)&irc->buddies_outstanding);
 
-	irc->ison_outstanding = TRUE;
+	irc_buddy_query(irc);
 
 	return TRUE;
 }
 
-static void irc_buddy_append(char *name, struct irc_buddy *ib, GString *string)
+void irc_buddy_query(struct irc_conn *irc)
 {
-	ib->flag = FALSE;
-	g_string_append_printf(string, "%s ", name);
+	GList *lp;
+	GString *string;
+	struct irc_buddy *ib;
+	char *buf;
+
+	string = g_string_sized_new(512);
+
+	while ((lp = g_list_first(irc->buddies_outstanding))) {
+		ib = (struct irc_buddy *)lp->data;
+		if (string->len + strlen(ib->name) + 1 > 450)
+			break;
+		g_string_append_printf(string, "%s ", ib->name);
+		ib->new_online_status = FALSE;
+		irc->buddies_outstanding = g_list_remove_link(irc->buddies_outstanding, lp);
+	}
+
+	if (string->len) {
+		buf = irc_format(irc, "vn", "ISON", string->str);
+		irc_send(irc, buf);
+		g_free(buf);
+		irc->ison_outstanding = TRUE;
+	} else
+		irc->ison_outstanding = FALSE;
+
+	g_string_free(string, TRUE);
+}
+
+static void irc_ison_buddy_init(char *name, struct irc_buddy *ib, GList **list)
+{
+	*list = g_list_append(*list, ib);
 }
 
 static void irc_ison_one(struct irc_conn *irc, struct irc_buddy *ib)
 {
 	char *buf;
 
-	ib->flag = FALSE;
+	if (irc->buddies_outstanding != NULL) {
+		irc->buddies_outstanding = g_list_append(irc->buddies_outstanding, ib);
+		return;
+	}
+
+	ib->new_online_status = FALSE;
 	buf = irc_format(irc, "vn", "ISON", ib->name);
 	irc_send(irc, buf);
 	g_free(buf);
--- a/libpurple/protocols/irc/irc.h	Thu Dec 30 00:58:17 2010 +0000
+++ b/libpurple/protocols/irc/irc.h	Thu Dec 30 01:06:03 2010 +0000
@@ -58,6 +58,7 @@
 	GHashTable *buddies;
 
 	gboolean ison_outstanding;
+	GList *buddies_outstanding;
 
 	char *inbuf;
 	int inbuflen;
@@ -97,6 +98,7 @@
 	char *name;
 	gboolean online;
 	gboolean flag;
+ 	gboolean new_online_status;
 	int ref;
 };
 
@@ -104,6 +106,7 @@
 
 int irc_send(struct irc_conn *irc, const char *buf);
 gboolean irc_blist_timeout(struct irc_conn *irc);
+void irc_buddy_query(struct irc_conn *irc);
 
 char *irc_escape_privmsg(const char *text, gssize length);
 
--- a/libpurple/protocols/irc/msgs.c	Thu Dec 30 00:58:17 2010 +0000
+++ b/libpurple/protocols/irc/msgs.c	Thu Dec 30 01:06:03 2010 +0000
@@ -761,18 +761,19 @@
 		return;
 
 	nicks = g_strsplit(args[1], " ", -1);
-
 	for (i = 0; nicks[i]; i++) {
 		if ((ib = g_hash_table_lookup(irc->buddies, (gconstpointer)nicks[i])) == NULL) {
 			continue;
 		}
-		ib->flag = TRUE;
+		ib->new_online_status = TRUE;
 	}
-
 	g_strfreev(nicks);
 
-	g_hash_table_foreach(irc->buddies, (GHFunc)irc_buddy_status, (gpointer)irc);
-	irc->ison_outstanding = FALSE;
+	if (irc->ison_outstanding)
+		irc_buddy_query(irc);
+
+	if (!irc->ison_outstanding)
+		g_hash_table_foreach(irc->buddies, (GHFunc)irc_buddy_status, (gpointer)irc);
 }
 
 static void irc_buddy_status(char *name, struct irc_buddy *ib, struct irc_conn *irc)
@@ -783,10 +784,10 @@
 	if (!gc || !buddy)
 		return;
 
-	if (ib->online && !ib->flag) {
+	if (ib->online && !ib->new_online_status) {
 		purple_prpl_got_user_status(irc->account, name, "offline", NULL);
 		ib->online = FALSE;
-	} else if (!ib->online && ib->flag) {
+	} else if (!ib->online && ib->new_online_status) {
 		purple_prpl_got_user_status(irc->account, name, "available", NULL);
 		ib->online = TRUE;
 	}
@@ -837,7 +838,7 @@
 	purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), nick, userhost, PURPLE_CBFLAGS_NONE, TRUE);
 
 	if ((ib = g_hash_table_lookup(irc->buddies, nick)) != NULL) {
-		ib->flag = TRUE;
+		ib->new_online_status = TRUE;
 		irc_buddy_status(nick, ib, irc);
 	}
 
@@ -1233,7 +1234,7 @@
 	g_slist_foreach(gc->buddy_chats, (GFunc)irc_chat_remove_buddy, data);
 
 	if ((ib = g_hash_table_lookup(irc->buddies, data[0])) != NULL) {
-		ib->flag = FALSE;
+		ib->new_online_status = FALSE;
 		irc_buddy_status(data[0], ib, irc);
 	}
 	g_free(data[0]);