pidgin: 737941c5: Move the status note parsing into a sepa...

markdoliner at pidgin.im markdoliner at pidgin.im
Tue Mar 4 04:45:48 EST 2008


-----------------------------------------------------------------
Revision: 737941c554250344668ddf2ad67d340390521557
Ancestor: 541f6529c3dbec16782707ce37eb8206f95fc92e
Author: markdoliner at pidgin.im
Date: 2008-03-04T09:41:44
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/737941c554250344668ddf2ad67d340390521557

Modified files:
        libpurple/protocols/oscar/family_icbm.c

ChangeLog: 

Move the status note parsing into a separate function, which I think
is much cleaner.  Also fix a crash when dereferencing a null pointer.
Fixes #5023.

-------------- next part --------------
============================================================
--- libpurple/protocols/oscar/family_icbm.c	28f68371090128f88aa0851dd5e57bf91ce5ea09
+++ libpurple/protocols/oscar/family_icbm.c	8fdd7bd0305cdda828beb1281eab65a19d22acf1
@@ -2332,181 +2332,207 @@ int aim_im_denytransfer(OscarData *od, c
 	return 0;
 }
 
-/*
- * Subtype 0x000b - Receive the response from an ICQ status message
- * request (in which case this contains the ICQ status message) or
- * a file transfer or direct IM request was declined.
- */
-static int clientautoresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+static void parse_status_note_text(OscarData *od, guchar *cookie, char *sn, ByteStream *bs)
 {
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	guint16 channel, reason;
-	char *sn;
-	guchar *cookie;
-	guint8 snlen;
+	struct aim_icq_info *info;
+	struct aim_icq_info *prev_info;
+	char *response;
+	char *encoding;
+	char *stripped_encoding;
+	char *status_note_title;
+	char *status_note_text;
+	char *stripped_status_note_text;
+	char *status_note;
+	guint32 length;
+	guint16 version;
+	guint32 capability;
+	guint8 message_type;
+	guint16 status_code;
+	guint16 text_length;
+	guint32 request_length;
+	guint32 response_length;
+	guint32 encoding_length;
+	PurpleAccount *account;
+	PurpleBuddy *buddy;
+	PurplePresence *presence;
+	PurpleStatus *status;
 
-	cookie = byte_stream_getraw(bs, 8);
-	channel = byte_stream_get16(bs);
-	snlen = byte_stream_get8(bs);
-	sn = byte_stream_getstr(bs, snlen);
-	reason = byte_stream_get16(bs);
-
-	if (channel == 0x0002)
+	for (prev_info = NULL, info = od->icq_info; info != NULL; prev_info = info, info = info->next)
 	{
-		/* parse status note text */
+		if (memcmp(&info->icbm_cookie, cookie, 8) == 0)
+		{
+			if (prev_info == NULL)
+				od->icq_info = info->next;
+			else
+				prev_info->next = info->next;
 
-		struct aim_icq_info *info = NULL;
-		struct aim_icq_info *prev_info = NULL;
-		char *response = NULL;
-		char *encoding = NULL;
-		char *stripped_encoding = NULL;
-		char *status_note_text = NULL;
-		char *stripped_status_note_text = NULL;
-		char *status_note = NULL;
+			break;
+		}
+	}
 
-		/*
-		 * TODO: Using a while statement here is kind of an ugly hack
-		 *       to be able to use 'break'.  We might as well be using
-		 *       'goto'.  Should probably get rid of this.
-		 */
-		while (reason == 0x0003) /* channel-specific */
-		{
-			guint32 length;
-			guint16 version;
-			guint32 capability;
-			guint8 message_type;
-			guint16 status_code;
-			guint16 text_length;
-			guint32 request_length;
-			guint32 response_length;
-			guint32 encoding_length;
-			PurpleAccount *account;
-			PurpleBuddy *buddy;
-			PurplePresence *presence;
-			PurpleStatus *status;
+	if (info == NULL)
+		return;
 
-			for (info = od->icq_info; info != NULL; info = info->next)
-			{
-				if (memcmp(&info->icbm_cookie, cookie, 8) == 0)
-				{
-					if (prev_info == NULL)
-						od->icq_info = info->next;
-					else
-						prev_info->next = info->next;
+	status_note_title = info->status_note_title;
+	g_free(info);
 
-					break;
-				}
+	length = byte_stream_getle16(bs);
+	if (length != 27) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect header "
+				"size; expected 27, received %u.\n", length);
+		g_free(status_note_title);
+		return;
+	}
 
-				prev_info = info;
-			}
+	version = byte_stream_getle16(bs);
+	if (version != 9) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect version; "
+				"expected 9, received %u.\n", version);
+		g_free(status_note_title);
+		return;
+	}
 
-			if (info == NULL)
-				break;
+	capability = aim_locate_getcaps(od, bs, 0x10);
+	if (capability != OSCAR_CAPABILITY_EMPTY) {
+		purple_debug_misc("oscar", "clientautoresp: plugin ID is not null.\n");
+		g_free(status_note_title);
+		return;
+	}
 
-			if ((length = byte_stream_getle16(bs)) != 27)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect header size; expected 27, received %u.\n", length);
-				break;
-			}
-			if ((version = byte_stream_getle16(bs)) != 9)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect version; expected 9, received %u.\n", version);
-				break;
-			}
-			capability = aim_locate_getcaps(od, bs, 0x10);
-			if (capability != OSCAR_CAPABILITY_EMPTY)
-			{
-				purple_debug_misc("oscar", "clientautoresp: plugin ID is not null.\n");
-				break;
-			}
-			byte_stream_advance(bs, 2); /* unknown */
-			byte_stream_advance(bs, 4); /* client capabilities flags */
-			byte_stream_advance(bs, 1); /* unknown */
-			byte_stream_advance(bs, 2); /* downcouner? */
+	byte_stream_advance(bs, 2); /* unknown */
+	byte_stream_advance(bs, 4); /* client capabilities flags */
+	byte_stream_advance(bs, 1); /* unknown */
+	byte_stream_advance(bs, 2); /* downcouner? */
 
-			if ((length = byte_stream_getle16(bs)) != 14)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect header size; expected 14, received %u.\n", length);
-				break;
-			}
-			byte_stream_advance(bs, 2); /* downcounter? */
-			byte_stream_advance(bs, 12); /* unknown */
+	length = byte_stream_getle16(bs);
+	if (length != 14) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect header "
+				"size; expected 14, received %u.\n", length);
+		g_free(status_note_title);
+		return;
+	}
 
-			if ((message_type = byte_stream_get8(bs)) != 0x1a)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect message type; expected 0x1a, received 0x%x.\n", message_type);
-				break;
-			}
-			byte_stream_advance(bs, 1); /* message flags */
-			if ((status_code = byte_stream_getle16(bs)) != 0)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect status code; expected 0, received %u.\n", status_code);
-				break;
-			}
-			byte_stream_advance(bs, 2); /* priority code */
+	byte_stream_advance(bs, 2); /* downcounter? */
+	byte_stream_advance(bs, 12); /* unknown */
 
-			text_length = byte_stream_getle16(bs);
-			byte_stream_advance(bs, text_length); /* text */
+	message_type = byte_stream_get8(bs);
+	if (message_type != 0x1a) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect message "
+				"type; expected 0x1a, received 0x%x.\n", message_type);
+		g_free(status_note_title);
+		return;
+	}
 
-			length = byte_stream_getle16(bs);
-			byte_stream_advance(bs, 18); /* unknown */
-			if (length != 18 + 4 + (request_length = byte_stream_getle32(bs)) + 17)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect block; expected length is %u, got %u.\n", 18 + 4 + request_length + 17, length);
-				break;
-			}
-			byte_stream_advance(bs, request_length); /* x request */
-			byte_stream_advance(bs, 17); /* unknown */
+	byte_stream_advance(bs, 1); /* message flags */
 
-			length = byte_stream_getle32(bs);
-			response_length = byte_stream_getle32(bs);
-			response = byte_stream_getstr(bs, response_length);
-			if (length != 4 + response_length + 4 + (encoding_length = byte_stream_getle32(bs)))
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect block; expected length is %u, got %u.\n", 4 + response_length + 4 + encoding_length, length);
-				break;
-			}
-			encoding = byte_stream_getstr(bs, encoding_length);
+	status_code = byte_stream_getle16(bs);
+	if (status_code != 0) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect status "
+				"code; expected 0, received %u.\n", status_code);
+		g_free(status_note_title);
+		return;
+	}
 
-			account = purple_connection_get_account(od->gc);
-			stripped_encoding = oscar_encoding_extract(encoding);
-			status_note_text = oscar_encoding_to_utf8(account, stripped_encoding, response, response_length);
-			stripped_status_note_text = purple_markup_strip_html(status_note_text);
+	byte_stream_advance(bs, 2); /* priority code */
 
-			if (stripped_status_note_text != NULL && stripped_status_note_text[0] != 0)
-				status_note = g_strdup_printf("%s: %s", info->status_note_title, stripped_status_note_text);
-			else
-				status_note = g_strdup(info->status_note_title);
+	text_length = byte_stream_getle16(bs);
+	byte_stream_advance(bs, text_length); /* text */
 
-			buddy = purple_find_buddy(account, sn);
-			if (buddy == NULL)
-			{
-				purple_debug_misc("oscar", "clientautoresp: buddy %s was not found.\n", sn);
-				break;
-			}
+	length = byte_stream_getle16(bs);
+	byte_stream_advance(bs, 18); /* unknown */
 
-			purple_debug_misc("oscar", "clientautoresp: setting status message to \"%s\".\n", status_note);
+	request_length = byte_stream_getle32(bs);
+	if (length != 18 + 4 + request_length + 17) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect block; "
+				"expected length is %u, got %u.\n",
+				18 + 4 + request_length + 17, length);
+		g_free(status_note_title);
+		return;
+	}
 
-			presence = purple_buddy_get_presence(buddy);
-			status = purple_presence_get_active_status(presence);
+	byte_stream_advance(bs, request_length); /* x request */
+	byte_stream_advance(bs, 17); /* unknown */
 
-			purple_prpl_got_user_status(account, sn,
-					purple_status_get_id(status),
-					"message", status_note, NULL);
+	length = byte_stream_getle32(bs);
+	response_length = byte_stream_getle32(bs);
+	response = byte_stream_getstr(bs, response_length);
+	encoding_length = byte_stream_getle32(bs);
+	if (length != 4 + response_length + 4 + encoding_length) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect block; "
+				"expected length is %u, got %u.\n",
+				4 + response_length + 4 + encoding_length, length);
+		g_free(status_note_title);
+		g_free(response);
+		return;
+	}
 
-			break;
-		}
+	encoding = byte_stream_getstr(bs, encoding_length);
 
+	account = purple_connection_get_account(od->gc);
+
+	stripped_encoding = oscar_encoding_extract(encoding);
+	status_note_text = oscar_encoding_to_utf8(account, stripped_encoding, response, response_length);
+	stripped_status_note_text = purple_markup_strip_html(status_note_text);
+
+	if (stripped_status_note_text != NULL && stripped_status_note_text[0] != 0)
+		status_note = g_strdup_printf("%s: %s", status_note_title, stripped_status_note_text);
+	else
+		status_note = g_strdup(status_note_title);
+
+	g_free(status_note_title);
+	g_free(response);
+	g_free(encoding);
+	g_free(stripped_encoding);
+	g_free(status_note_text);
+	g_free(stripped_status_note_text);
+
+	buddy = purple_find_buddy(account, sn);
+	if (buddy == NULL)
+	{
+		purple_debug_misc("oscar", "clientautoresp: buddy %s was not found.\n", sn);
 		g_free(status_note);
-		g_free(stripped_status_note_text);
-		g_free(status_note_text);
-		g_free(stripped_encoding);
-		g_free(encoding);
-		g_free(response);
-		g_free(info->status_note_title);
-		g_free(info);
+		return;
+	}
 
+	purple_debug_misc("oscar", "clientautoresp: setting status "
+			"message to \"%s\".\n", status_note);
+
+	presence = purple_buddy_get_presence(buddy);
+	status = purple_presence_get_active_status(presence);
+
+	purple_prpl_got_user_status(account, sn,
+			purple_status_get_id(status),
+			"message", status_note, NULL);
+
+	g_free(status_note);
+}
+
+/*
+ * Subtype 0x000b - Receive the response from an ICQ status message
+ * request (in which case this contains the ICQ status message) or
+ * a file transfer or direct IM request was declined.
+ */
+static int clientautoresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+{
+	int ret = 0;
+	aim_rxcallback_t userfunc;
+	guint16 channel, reason;
+	char *sn;
+	guchar *cookie;
+	guint8 snlen;
+
+	cookie = byte_stream_getraw(bs, 8);
+	channel = byte_stream_get16(bs);
+	snlen = byte_stream_get8(bs);
+	sn = byte_stream_getstr(bs, snlen);
+	reason = byte_stream_get16(bs);
+
+	if (channel == 0x0002)
+	{
+		if (reason == 0x0003) /* channel-specific */
+			/* parse status note text */
+			parse_status_note_text(od, cookie, sn, bs);
+
 		byte_stream_get16(bs); /* Unknown */
 		byte_stream_get16(bs); /* Unknown */
 		if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))


More information about the Commits mailing list