changeset 6306:69c9b6e63a98

[gaim-migrate @ 6805] This fixes a crash sending toc messages with certain characters. I broke it in the great constification of 0.64cvs. http://sourceforge.net/tracker/?group_id=235&atid=100235&func=detail&aid=775318 committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sat, 26 Jul 2003 15:57:07 +0000
parents 1fbdca69a25e
children 55588b222901
files src/protocols/toc/toc.c
diffstat 1 files changed, 89 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/toc/toc.c	Sat Jul 26 13:14:05 2003 +0000
+++ b/src/protocols/toc/toc.c	Sat Jul 26 15:57:07 2003 +0000
@@ -288,35 +288,45 @@
 	}
 }
 
-static int escape_message(char *msg)
+char *escape_message(const char *msg)
 {
-	char *c, *cpy;
-	int cnt = 0;
-	/* Assumes you have a buffer able to cary at least BUF_LEN * 2 bytes */
-	if (strlen(msg) > BUF_LEN) {
-		debug_printf("Warning:  truncating message to 2048 bytes\n");
-		msg[2047] = '\0';
-	}
+	char *ret;
+	int i, j;
+
+	if (!msg)
+		return NULL;
 
-	cpy = g_strdup(msg);
-	c = cpy;
-	while (*c) {
-		switch (*c) {
-		case '$':
-		case '[':
-		case ']':
-		case '(':
-		case ')':
-			msg[cnt++] = '\\';
-			/* Fall through */
-		default:
-			msg[cnt++] = *c;
+	/* Calculate the length after escaping */
+	for (i=0, j=0; msg[i]; i++)
+		switch (msg[i]) {
+			case '$':
+			case '[':
+			case ']':
+			case '(':
+			case ')':
+				j++;
+			default:
+				j++;
 		}
-		c++;
-	}
-	msg[cnt] = '\0';
-	g_free(cpy);
-	return cnt;
+
+	/* Allocate a string */
+	ret = (char *)malloc((j+1) * sizeof(char));
+
+	/* Copy the string */
+	for (i=0, j=0; msg[i]; i++)
+		switch (msg[i]) {
+			case '$':
+			case '[':
+			case ']':
+			case '(':
+			case ')':
+				ret[j++] = '\\';
+			default:
+				ret[j++] = msg[i];
+			}
+	ret[j] = '\0';
+
+	return ret;
 }
 
 /*
@@ -332,100 +342,104 @@
 		return NULL;
 
 	/* Calculate the length after escaping */
-	i = 0;
-	j = 0;
-	while (msg[i++])
+	for (i=0, j=0; msg[i]; i++)
 		switch (msg[i]) {
-		case '\n':
-			j += 4;
-			break;
-		case '{':
-		case '}':
-		case '\\':
-		case '"':
-			j += 1;
-		default:
-			j += 1;
+			case '\n':
+				j += 4;
+				break;
+			case '{':
+			case '}':
+			case '\\':
+			case '"':
+				j += 1;
+			default:
+				j += 1;
 		}
 
 	/* Allocate a string */
 	ret = (char *)malloc((j+1) * sizeof(char));
 
 	/* Copy the string */
-	i = 0;
-	j = 0;
-	while (msg[i]) {
+	for (i=0, j=0; msg[i]; i++)
 		switch (msg[i]) {
-		case '\n':
-			ret[j] = '<';
-			ret[j+1] = 'B';
-			ret[j+2] = 'R';
-			ret[j+3] = '>';
-			j += 4;
-			break;
-		case '{':
-		case '}':
-		case '\\':
-		case '"':
-			ret[j] = '\\';
-			j++;
-		default:
-			ret[j] = msg[i];
-			j++;
+			case '\n':
+				ret[j++] = '<';
+				ret[j++] = 'B';
+				ret[j++] = 'R';
+				ret[j++] = '>';
+				break;
+			case '{':
+			case '}':
+			case '\\':
+			case '"':
+				ret[j++] = '\\';
+			default:
+				ret[j++] = msg[i];
 		}
-		i++;
-	}
 	ret[j] = '\0';
 
 	return ret;
 }
 
-static int sflap_send(GaimConnection *gc, char *buf, int olen, int type)
+static int sflap_send(GaimConnection *gc, const char *buf, int olen, int type)
 {
+	struct toc_data *tdt = (struct toc_data *)gc->proto_data;
 	int len;
 	int slen = 0;
+	int ret;
 	struct sflap_hdr hdr;
-	char obuf[MSG_LEN];
-	struct toc_data *tdt = (struct toc_data *)gc->proto_data;
+	char *escaped, *obuf;
 
 	if (tdt->state == STATE_PAUSE)
 		/* TOC has given us the PAUSE message; sending could cause a disconnect
 		 * so we just return here like everything went through fine */
 		return 0;
 
-	if (olen < 0)
-		len = escape_message(buf);
-	else
+	if (olen < 0) {
+		escaped = escape_message(buf);
+		len = strlen(buf);
+	} else {
+		escaped = g_memdup(buf, olen);
 		len = olen;
+	}
 
-	/* One _last_ 2048 check here!  This shouldn't ever
-	   * get hit though, hopefully.  If it gets hit on an IM
-	   * It'll lose the last " and the message won't go through,
-	   * but this'll stop a segfault. */
+	/*
+	 * One _last_ 2048 check here!  This shouldn't ever
+	 * get hit though, hopefully.  If it gets hit on an IM
+	 * It'll lose the last " and the message won't go through,
+	 * but this'll stop a segfault.
+	 */
 	if (len > MSG_LEN) {
 		debug_printf("message too long, truncating\n");
-		buf[MSG_LEN - 1] = '\0';
+		escaped[MSG_LEN - 1] = '\0';
 		len = MSG_LEN;
 	}
 
 	if (olen < 0)
-		debug_printf("TOC C: %s\n", buf);
+		debug_printf("TOC C: %s\n", escaped);
 
 	hdr.ast = '*';
 	hdr.type = type;
 	hdr.seqno = htons(tdt->seqno++ & 0xffff);
 	hdr.len = htons(len + (type == TYPE_SIGNON ? 0 : 1));
 
+	obuf = (char *)malloc((sizeof(hdr)+len+1) * sizeof(char));
 	memcpy(obuf, &hdr, sizeof(hdr));
 	slen += sizeof(hdr);
-	memcpy(&obuf[slen], buf, len);
+
+	memcpy(&obuf[slen], escaped, len);
 	slen += len;
+
 	if (type != TYPE_SIGNON) {
 		obuf[slen] = '\0';
 		slen += 1;
 	}
 
-	return toc_write(tdt->toc_fd, obuf, slen);
+	ret = toc_write(tdt->toc_fd, obuf, slen);
+	free(obuf);
+	free(escaped);
+
+	return ret;
 }
 
 static int wait_reply(GaimConnection *gc, char *buffer, size_t buflen)
@@ -1124,7 +1138,7 @@
 {
 	char buf[BUF_LEN * 2];
 	g_snprintf(buf, BUF_LONG, "toc_change_passwd %s %s", orig, new);
-	sflap_send(g, buf, strlen(buf), TYPE_DATA);
+	sflap_send(g, buf, -1, TYPE_DATA);
 }
 
 static void toc_add_buddy(GaimConnection *g, const char *name)