changeset 30398:be056399ae5f

Fixes #12044. We send a dummy packet with DC version = 8 to make Miranda and QIP think we come from a respectable family and deserve being sent channel 2 messages (which we now treat as plain text). Also, we now send HTML_MSGS capability to convince Trillian to not strip HTML before sending us messages.
author ivan.komarov@soc.pidgin.im
date Thu, 05 Aug 2010 21:19:47 +0000
parents 1f3ef11a9690
children 3eb2dd8a1cc7
files libpurple/protocols/oscar/family_locate.c libpurple/protocols/oscar/family_oservice.c libpurple/protocols/oscar/oscar.c libpurple/protocols/oscar/oscar.h libpurple/protocols/oscar/tlv.c
diffstat 5 files changed, 82 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/oscar/family_locate.c	Sat Jul 31 20:08:52 2010 +0000
+++ b/libpurple/protocols/oscar/family_locate.c	Thu Aug 05 21:19:47 2010 +0000
@@ -245,6 +245,10 @@
 	 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
 
+	{OSCAR_CAPABILITY_HTML_MSGS,
+	 {0x01, 0x38, 0xca, 0x7b, 0x76, 0x9a, 0x49, 0x15,
+	  0x88, 0xf2, 0x13, 0xfc, 0x00, 0x97, 0x9e, 0xa8}},
+
 	{OSCAR_CAPABILITY_LAST,
 	 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
@@ -675,15 +679,12 @@
 		return -EINVAL;
 
 	for (i = 0; byte_stream_bytes_left(bs); i++) {
-
 		if (aim_caps[i].flag == OSCAR_CAPABILITY_LAST)
 			break;
 
 		if (caps & aim_caps[i].flag)
 			byte_stream_putraw(bs, aim_caps[i].data, 0x10);
-
 	}
-
 	return 0;
 }
 
--- a/libpurple/protocols/oscar/family_oservice.c	Sat Jul 31 20:08:52 2010 +0000
+++ b/libpurple/protocols/oscar/family_oservice.c	Thu Aug 05 21:19:47 2010 +0000
@@ -842,6 +842,50 @@
 	return 0;
 }
 
+/* Send dummy DC (direct connect) information to the server.
+ * Direct connect is ICQ's counterpart for AIM's DirectIM,
+ * as far as I can tell. Anyway, we don't support it;
+ * the reason to send this packet is that some clients
+ * (Miranda, QIP) won't send us channel 2 ICBM messages
+ * unless we specify DC version >= 8.
+ *
+ * See #12044 for more information.
+ */
+void
+aim_srv_set_dc_info(OscarData *od)
+{
+	ByteStream bs, tlv0c;
+	aim_snacid_t snacid;
+	GSList *tlvlist = NULL;
+
+	/* http://iserverd.khstu.ru/oscar/snac_01_1e.html has a nice analysis of what goes in 0xc tlv.
+	 * Kopete sends a dummy DC info, too, so I just copied the values from them.
+	 */
+	byte_stream_new(&tlv0c, 4*2 + 1 + 2 + 4*6 + 2);
+	byte_stream_put32(&tlv0c, 0x0);
+	byte_stream_put32(&tlv0c, 0x0);
+	byte_stream_put8(&tlv0c, 0x0); /* We don't support DC */
+	byte_stream_put16(&tlv0c, 8); /* DC version */
+	byte_stream_put32(&tlv0c, 0x0);
+	byte_stream_put32(&tlv0c, 0x50);
+	byte_stream_put32(&tlv0c, 0x3);
+	byte_stream_put32(&tlv0c, 0x0);
+	byte_stream_put32(&tlv0c, 0x0);
+	byte_stream_put32(&tlv0c, 0x0);
+	byte_stream_put16(&tlv0c, 0x0);
+	aim_tlvlist_add_raw(&tlvlist, 0x000c, byte_stream_curpos(&tlv0c), tlv0c.data);
+	byte_stream_destroy(&tlv0c);
+
+	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
+	aim_tlvlist_write(&bs, &tlvlist);
+	aim_tlvlist_free(tlvlist);
+
+	snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x001e, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, flap_connection_findbygroup(od, SNAC_FAMILY_ICBM), SNAC_FAMILY_OSERVICE, 0x001e, 0x0000, snacid, &bs);
+
+	byte_stream_destroy(&bs);
+}
+
 /**
  * Starting this past week (26 Mar 2001, say), AOL has started sending
  * this nice little extra SNAC.  AFAIK, it has never been used until now.
--- a/libpurple/protocols/oscar/oscar.c	Sat Jul 31 20:08:52 2010 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Thu Aug 05 21:19:47 2010 +0000
@@ -68,7 +68,8 @@
 		| OSCAR_CAPABILITY_TYPING
 		| OSCAR_CAPABILITY_ICQSERVERRELAY
 		| OSCAR_CAPABILITY_NEWCAPS
-		| OSCAR_CAPABILITY_XTRAZ;
+		| OSCAR_CAPABILITY_XTRAZ
+		| OSCAR_CAPABILITY_HTML_MSGS;
 
 static guint8 features_aim[] = {0x01, 0x01, 0x01, 0x02};
 static guint8 features_icq[] = {0x01};
@@ -1746,8 +1747,18 @@
 		if (args->info.rtfmsg.msgtype == 1) {
 			if (args->info.rtfmsg.msg != NULL) {
 				char *rtfmsg = oscar_encoding_to_utf8(args->encoding, args->info.rtfmsg.msg, strlen(args->info.rtfmsg.msg));
-				serv_got_im(gc, userinfo->bn, rtfmsg, flags, time(NULL));
+				char *tmp, *tmp2;
+
+				/* Channel 2 messages are supposed to be plain-text (never mind the name "rtfmsg", even
+				 * the official client doesn't parse them as RTF). Therefore, we should escape them before
+				 * showing to the user. */
+				tmp = g_markup_escape_text(rtfmsg, -1);
 				g_free(rtfmsg);
+				tmp2 = purple_strreplace(tmp, "\r\n", "<br>");
+				g_free(tmp);
+
+				serv_got_im(gc, userinfo->bn, tmp2, flags, time(NULL));
+				g_free(tmp2);
 			}
 		} else if (args->info.rtfmsg.msgtype == 26) {
 			purple_debug_info("oscar", "Sending X-Status Reply\n");
@@ -2783,6 +2794,7 @@
 	tmp = purple_markup_strip_html(message);
 	itmsurl = purple_status_get_attr_string(status, "itmsurl");
 	aim_srv_setextrainfo(od, FALSE, 0, is_available, tmp, itmsurl);
+	aim_srv_set_dc_info(od);
 	g_free(tmp);
 
 	presence = purple_status_get_presence(status);
--- a/libpurple/protocols/oscar/oscar.h	Sat Jul 31 20:08:52 2010 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Thu Aug 05 21:19:47 2010 +0000
@@ -202,7 +202,8 @@
 #define OSCAR_CAPABILITY_NEWCAPS               0x0000000020000000LL
 #define OSCAR_CAPABILITY_XTRAZ                 0x0000000040000000LL
 #define OSCAR_CAPABILITY_GENERICUNKNOWN        0x0000000080000000LL
-#define OSCAR_CAPABILITY_LAST                  0x0000000100000000LL
+#define OSCAR_CAPABILITY_HTML_MSGS             0x0000000100000000LL
+#define OSCAR_CAPABILITY_LAST                  0x0000000200000000LL
 
 #define OSCAR_STATUS_ID_INVISIBLE   "invisible"
 #define OSCAR_STATUS_ID_OFFLINE     "offline"
@@ -531,6 +532,7 @@
 /* 0x0011 */ void aim_srv_setidle(OscarData *od, guint32 idletime);
 /* 0x0017 */ void aim_srv_setversions(OscarData *od, FlapConnection *conn);
 /* 0x001e */ int aim_srv_setextrainfo(OscarData *od, gboolean seticqstatus, guint32 icqstatus, gboolean setstatusmsg, const char *statusmsg, const char *itmsurl);
+void aim_srv_set_dc_info(OscarData *od);
 
 
 void aim_bos_reqrights(OscarData *od, FlapConnection *conn);
--- a/libpurple/protocols/oscar/tlv.c	Sat Jul 31 20:08:52 2010 +0000
+++ b/libpurple/protocols/oscar/tlv.c	Thu Aug 05 21:19:47 2010 +0000
@@ -371,6 +371,17 @@
 	return aim_tlvlist_add_raw(list, type, strlen(value), (guint8 *)value);
 }
 
+static int
+count_caps(guint64 caps)
+{
+	int set_bits = 0;
+	while (caps) {
+		set_bits += caps & 1;
+		caps >>= 1;
+	}
+	return set_bits;
+}
+
 /**
  * Adds a block of capability blocks to a TLV chain. The bitfield
  * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
@@ -389,23 +400,24 @@
  */
 int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint64 caps, const char *mood)
 {
-	guint8 buf[256]; /* TODO: Don't use a fixed length buffer */
 	ByteStream bs;
+	guint32 bs_size;
 	guint8 *data;
 
 	if (caps == 0)
 		return 0; /* nothing there anyway */
 
-	byte_stream_init(&bs, buf, sizeof(buf));
+	data = icq_get_custom_icon_data(mood);
+	bs_size = 16*(count_caps(caps) + (data != NULL ? 1 : 0));
 
+	byte_stream_new(&bs, bs_size);
 	byte_stream_putcaps(&bs, caps);
-	
+
 	/* adding of custom icon GUID */
-	data = icq_get_custom_icon_data(mood);
 	if (data != NULL)
 		byte_stream_putraw(&bs, data, 16);
 
-	return aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), buf);
+	return aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), bs.data);
 }
 
 /**