# HG changeset patch # User ivan.komarov@soc.pidgin.im # Date 1281043187 0 # Node ID be056399ae5f4496e088696666b548847f9ae6f2 # Parent 1f3ef11a9690c86ee2d2665d57662c592206fea7 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. diff -r 1f3ef11a9690 -r be056399ae5f libpurple/protocols/oscar/family_locate.c --- 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; } diff -r 1f3ef11a9690 -r be056399ae5f libpurple/protocols/oscar/family_oservice.c --- 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. diff -r 1f3ef11a9690 -r be056399ae5f libpurple/protocols/oscar/oscar.c --- 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", "
"); + 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); diff -r 1f3ef11a9690 -r be056399ae5f libpurple/protocols/oscar/oscar.h --- 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); diff -r 1f3ef11a9690 -r be056399ae5f libpurple/protocols/oscar/tlv.c --- 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); } /**