changeset 8518:833dd756dcc3

[gaim-migrate @ 9257] Patch by David Vermeille to add outgoing formatting support for MSN. I'd like to thank him, as a number of people have attempted this patch and ended up discouraged when told it would break core/UI split. David went ahead and stuck through it, and we now have some decent support. I also realized during this that we weren't processing certain incoming colors correctly, so that's taken care of now. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Sun, 28 Mar 2004 21:38:22 +0000
parents 5cb93726e4d5
children f8ab826e11ad
files COPYRIGHT ChangeLog src/protocols/msn/msn.c src/protocols/msn/utils.c src/protocols/msn/utils.h
diffstat 5 files changed, 212 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Sun Mar 28 19:53:43 2004 +0000
+++ b/COPYRIGHT	Sun Mar 28 21:38:22 2004 +0000
@@ -124,6 +124,7 @@
 Tom Tromey
 Chris Toshok
 Junichi Uekawa
+David Vermeille
 Bjoern Voigt
 Nathan Walp
 Eric Warmenhoven
--- a/ChangeLog	Sun Mar 28 19:53:43 2004 +0000
+++ b/ChangeLog	Sun Mar 28 21:38:22 2004 +0000
@@ -10,6 +10,7 @@
 	* Non-ascii character support in AIM chats (Uli Luckas and Marco Ziech)
 	* Vastly improved browser opening, with tab support! (Nathan Fredrickson)
 	* Added support for connecting to MSN using the port 80 method.
+	* Added outgoing MSN formatting support (David Vermeille)
 	* Support for Mozilla Firefox (Chris Friesen and Nathan Fredrickson)
 	* Added protocol-specific preferences (Gary Kramlich)
 	* Local IP address information can be changed in Preferences
@@ -51,6 +52,8 @@
 	* Removing invalid buddies in MSN with a space in their name no longer
 	  causes a disconnect (Stu Tomlinson)
 	* Multiple MSN chats should now work (Robert Mibus)
+	* Added new MSN error codes and fixed an incorrect one (Stu Tomlinson)
+	* Incoming colors are now processed correctly in MSN.
 	* Conversation placement by account now works correctly with both
 	  chats and IMs, and takes the Combine Chats and IMs option into
 	  consideration.
@@ -58,7 +61,6 @@
 	  so they work without a label and scrollbar (Pekka Riikonen)
 	* The Disconnect dialog no longer raises and gains focus each time
 	  a disconnected account is added (Ka-Hing Cheung)
-	* Added new MSN error codes and fixed an incorrect one (Stu Tomlinson)
 	* Gadu-Gadu might actually connect again (Ignacy Gawedzki)
 	* Buddy pounces for an account are removed when the account is
 	  deleted (Gary Kramlich)
--- a/src/protocols/msn/msn.c	Sun Mar 28 19:53:43 2004 +0000
+++ b/src/protocols/msn/msn.c	Sun Mar 28 21:38:22 2004 +0000
@@ -487,6 +487,7 @@
 		msn_http_session_init(session);
 
 	gc->proto_data = session;
+	gc->flags |= GAIM_CONNECTION_HTML;
 
 	gaim_connection_update_progress(gc, _("Connecting"), 0, MSN_CONNECT_STEPS);
 
@@ -532,14 +533,20 @@
 	if (g_ascii_strcasecmp(who, gaim_account_get_username(account))) {
 		MsnMessage *msg;
 		MsnUser *user;
+		char *msgformat;
+		char *msgtext;
 
 		user = msn_user_new(session, who, NULL);
 
+		msn_import_html(message, &msgformat, &msgtext);
+
 		msg = msn_message_new();
 		msn_message_set_receiver(msg, user);
-		msn_message_set_attr(msg, "X-MMS-IM-Format",
-							 "FN=MS%20Sans%20Serif; EF=; CO=0; PF=0");
-		msn_message_set_body(msg, message);
+		msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat);
+		msn_message_set_body(msg, msgtext);
+
+		g_free(msgformat);
+		g_free(msgtext);
 
 		if (swboard != NULL) {
 			if (!msn_switchboard_send_msg(swboard, msg))
--- a/src/protocols/msn/utils.c	Sun Mar 28 19:53:43 2004 +0000
+++ b/src/protocols/msn/utils.c	Sun Mar 28 21:38:22 2004 +0000
@@ -34,10 +34,12 @@
 
 	cur = strstr(mime, "FN=");
 
-	if (cur && (*(cur = cur + 3) != ';')) {
+	if (cur && (*(cur = cur + 3) != ';'))
+	{
 		pre = g_string_append(pre, "<FONT FACE=\"");
 
-		while (*cur && *cur != ';') {
+		while (*cur && *cur != ';')
+		{
 			pre = g_string_append_c(pre, *cur);
 			cur++;
 		}
@@ -48,8 +50,10 @@
 
 	cur = strstr(mime, "EF=");
 
-	if (cur && (*(cur = cur + 3) != ';')) {
-		while (*cur && *cur != ';') {
+	if (cur && (*(cur = cur + 3) != ';'))
+	{
+		while (*cur && *cur != ';')
+		{
 			pre = g_string_append_c(pre, '<');
 			pre = g_string_append_c(pre, *cur);
 			pre = g_string_append_c(pre, '>');
@@ -59,28 +63,42 @@
 
 	cur = strstr(mime, "CO=");
 
-	if (cur && (*(cur = cur + 3) != ';')) {
+	if (cur && (*(cur = cur + 3) != ';'))
+	{
 		int i;
 
 		i = sscanf(cur, "%02x%02x%02x;", &colors[0], &colors[1], &colors[2]);
 
-		if (i > 0) {
+		if (i > 0)
+		{
 			char tag[64];
 
-			if (i == 1) {
-				colors[2] = colors[0];
+			if (i == 1)
+			{
 				colors[1] = 0;
-				colors[0] = 0;
+				colors[2] = 0;
 			}
-			else if (i == 2) {
-				colors[2] = colors[1];
-				colors[1] = colors[0];
-				colors[0] = 0;
+			else if (i == 2)
+			{
+				unsigned int temp = colors[0];
+
+				colors[0] = colors[1];
+				colors[1] = temp;
+				colors[2] = 0;
+			}
+			else if (i == 3)
+			{
+				unsigned int temp = colors[2];
+
+				colors[2] = colors[0];
+				colors[0] = temp;
 			}
 
 			g_snprintf(tag, sizeof(tag),
 					   "<FONT COLOR=\"#%02hhx%02hhx%02hhx\">",
-					   colors[2], colors[1], colors[0]);
+					   colors[0], colors[1], colors[2]);
+
+			gaim_debug_misc("msn", "Got: %s\n", tag);
 
 			pre = g_string_append(pre, tag);
 			post = g_string_prepend(post, "</FONT>");
@@ -103,3 +121,158 @@
 	else
 		g_free(cur);
 }
+
+/*
+ * We need this because we're only supposed to encode spaces in the font
+ * names. gaim_url_encode() isn't acceptable.
+ */
+const char *
+encode_spaces(const char *str)
+{
+	static char buf[BUF_LEN];
+	const char *c;
+	char *d;
+
+	g_return_val_if_fail(str != NULL, NULL);
+
+	for (c = str, d = buf; *c != '\0'; c++)
+	{
+		if (*c == ' ')
+		{
+			*d++ = '%';
+			*d++ = '2';
+			*d++ = '0';
+		}
+		else
+			*d++ = *c;
+	}
+
+	return buf;
+}
+
+/*
+ * Taken from the zephyr plugin.
+ * This parses HTML formatting (put out by one of the gtkimhtml widgets
+ * and converts it to msn formatting. It doesn't deal with the tag closing,
+ * but gtkimhtml widgets give valid html.
+ * It currently deals properly with <b>, <u>, <i>, <font face=...>,
+ * <font color=...>.
+ * It ignores <font back=...> and <font size=...>
+ */
+void
+msn_import_html(const char *html, char **attributes, char **message)
+{
+	int len, retcount = 0;
+	const char *c;
+	char *msg;
+	char *fontface = NULL;
+	char fonteffect[4];
+	char fontcolor[7];
+
+	g_return_if_fail(html       != NULL);
+	g_return_if_fail(attributes != NULL);
+	g_return_if_fail(message    != NULL);
+
+	len = strlen(html);
+	msg = g_malloc0(len + 1);
+
+	memset(fontcolor, 0, sizeof(fontcolor));
+	memset(fonteffect, 0, sizeof(fontcolor));
+
+	for (c = html; *c != '\0';)
+	{
+		if (*c == '<')
+		{
+			if (!g_ascii_strncasecmp(c + 1, "i>", 2))
+			{
+				strcat(fonteffect, "I");
+				c += 3;
+			}
+			else if (!g_ascii_strncasecmp(c + 1, "b>", 2))
+			{
+				strcat(fonteffect, "B");
+				c += 3;
+			}
+			else if (!g_ascii_strncasecmp(c + 1, "u>", 2))
+			{
+				strcat(fonteffect, "U");
+				c += 3;
+			}
+			else if (!g_ascii_strncasecmp(c + 1, "a href=\"", 8))
+			{
+				c += 9;
+
+				while (g_ascii_strncasecmp(c, "\">", 2))
+					msg[retcount++] = *c++;
+
+				c += 2;
+
+				/* ignore descriptive string */
+				while (g_ascii_strncasecmp(c, "</a>", 4))
+					c++;
+
+				c += 4;
+			}
+			else if (!g_ascii_strncasecmp(c + 1, "font", 4))
+			{
+				c += 5;
+
+				while (!g_ascii_strncasecmp(c, " ", 1))
+					c++;
+
+				if (!g_ascii_strncasecmp(c, "color=\"#", 7))
+				{
+					c += 8;
+
+					fontcolor[0] = *(c + 4);
+					fontcolor[1] = *(c + 5);
+					fontcolor[2] = *(c + 2);
+					fontcolor[3] = *(c + 3);
+					fontcolor[4] = *c;
+					fontcolor[5] = *(c + 1);
+
+					c += 8;
+				}
+				else if (!g_ascii_strncasecmp(c, "face=\"", 6))
+				{
+					const char *end = NULL;
+					unsigned int namelen = 0;
+
+					c += 6;
+					end = strchr(c, '\"');
+					namelen = (unsigned int)(end - c);
+					fontface = g_strndup(c, namelen);
+					c = end + 2;
+				}
+				else
+				{
+					/* Drop all unrecognized/misparsed font tags */
+					while (g_ascii_strncasecmp(c, "\">", 2))
+						c++;
+
+					c += 2;
+				}
+			}
+			else
+			{
+				while (g_ascii_strncasecmp(c, ">", 1))
+					c++;
+
+				c++;
+			}
+		}
+		else
+			msg[retcount++] = *c++;
+	}
+
+	if (fontface == NULL)
+		fontface = g_strdup("MS Sans Serif");
+
+	*attributes = g_strdup_printf("FN=%s; EF=%s; CO=%s; PF=0",
+								  encode_spaces(fontface),
+								  fonteffect, fontcolor);
+	*message = g_strdup(msg);
+
+	g_free(fontface);
+	g_free(msg);
+}
--- a/src/protocols/msn/utils.h	Sun Mar 28 19:53:43 2004 +0000
+++ b/src/protocols/msn/utils.h	Sun Mar 28 21:38:22 2004 +0000
@@ -33,4 +33,15 @@
  */
 void msn_parse_format(const char *mime, char **pre_ret, char **post_ret);
 
+/**
+ * Parses the Gaim message formatting (html) into the MSN format.
+ *
+ * @param html			The html message to format.
+ * @param attributes	The returned attributes string.
+ * @param message		The returned message string.
+ *
+ * @return The new message.
+ */
+void msn_import_html(const char *html, char **attributes, char **message);
+
 #endif /* _MSN_UTILS_H_ */