[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