[Telepathy-commits] [telepathy-idle/master] Rewrite idle_text_encode_and_split to be more obviously correct.

Will Thompson will.thompson at collabora.co.uk
Wed Sep 24 02:47:08 PDT 2008


Fixes an infinite loop for ACTIONs containing newlines.
---
 src/idle-text.c |   93 ++++++++++++++++++++++++++++++-------------------------
 1 files changed, 51 insertions(+), 42 deletions(-)

diff --git a/src/idle-text.c b/src/idle-text.c
index 9bfd0ae..ba1a3d5 100644
--- a/src/idle-text.c
+++ b/src/idle-text.c
@@ -53,58 +53,67 @@ gboolean idle_text_decode(const gchar *text, TpChannelTextMessageType *type, gch
 
 GStrv idle_text_encode_and_split(TpChannelTextMessageType type, const gchar *recipient, const gchar *text, GError **error) {
 	GPtrArray *messages;
-	gchar msg[IRC_MSG_MAXLEN + 1];
-	gsize len;
-	gchar *part;
-	gsize headerlen;
-	const gchar *final_text;
-
-	final_text = text;
-	len = strlen(final_text);
-	part = (gchar*)final_text;
-
-	if (type == TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL)
-		g_snprintf(msg, IRC_MSG_MAXLEN + 1, "PRIVMSG %s :", recipient);
-	else if (type == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION)
-		g_snprintf(msg, IRC_MSG_MAXLEN + 1, "PRIVMSG %s :\001ACTION ", recipient);
-	else if (type == TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE)
-		g_snprintf(msg, IRC_MSG_MAXLEN + 1, "NOTICE %s :", recipient);
-	else {
-		IDLE_DEBUG("invalid message type %u", type);
-		g_set_error(error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "invalid message type %u", type);
-
-		return NULL;
+	const gchar *remaining_text = text;
+	gsize remaining_text_len = strlen(text);
+	gchar *header;
+	const gchar *footer = "";
+	gsize max_bytes;
+
+	switch (type) {
+		case TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL:
+			header = g_strdup_printf("PRIVMSG %s :", recipient);
+			break;
+		case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION:
+			header = g_strdup_printf("PRIVMSG %s :\001ACTION ", recipient);
+			footer = "\001";
+			break;
+		case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE:
+			header = g_strdup_printf("NOTICE %s :", recipient);
+			break;
+		default:
+			IDLE_DEBUG("invalid message type %u", type);
+			g_set_error(error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "invalid message type %u", type);
+			return NULL;
 	}
 
-	messages = g_ptr_array_new ();
-	headerlen = strlen(msg);
-
-	while (part < final_text + len) {
-		char *br = strchr (part, '\n');
-		size_t len = IRC_MSG_MAXLEN - headerlen;
-		if (br) {
-			/* If br is non-NULL, (br - part) will always be positive. */
-			size_t len_to_br = br - part;
-			len = (len < len_to_br) ? len : len_to_br;
-		}
-
-		if (type == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION) {
-			g_snprintf(msg + headerlen, len + 1, "%s\001", part);
-			len -= 1;
+	messages = g_ptr_array_new();
+	max_bytes = IRC_MSG_MAXLEN - (strlen(header) + strlen(footer));
+
+	while (remaining_text_len > 0) {
+		char *newline = strchr(remaining_text, '\n');
+		gsize bytes_to_copy;
+		gsize advance;
+		char *message;
+
+		if (newline != NULL && ((unsigned) (newline - remaining_text)) < max_bytes) {
+			/* String up to the next newline is short enough. */
+			bytes_to_copy = (newline - remaining_text);
+
+			/* Advance over the newline */
+			advance = bytes_to_copy + 1;
+		} else if (remaining_text_len > max_bytes) {
+			/* Remaining string is too long; take as many bytes as possible */
+			/* FIXME: check we're not breaking a UTF-8 code point in half */
+			bytes_to_copy = max_bytes;
+			advance = max_bytes;
 		} else {
-			g_strlcpy(msg + headerlen, part, len + 1);
+			/* Just take it all. */
+			bytes_to_copy = remaining_text_len;
+			advance = remaining_text_len;
 		}
 
-		part += len;
+		message = g_strdup_printf("%s%.*s%s", header, bytes_to_copy, remaining_text, footer);
+		g_ptr_array_add(messages, message);
 
-		if (br)
-			part++;
-
-		g_ptr_array_add(messages, g_strdup(msg));
+		remaining_text += advance;
+		remaining_text_len -= advance;
 	}
 
+	g_assert (remaining_text_len == 0);
+
 	g_ptr_array_add(messages, NULL);
 
+	g_free(header);
 	return (GStrv) g_ptr_array_free(messages, FALSE);
 }
 
-- 
1.5.6.5



More information about the Telepathy-commits mailing list