summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Komarov <ivan.komarov@pidgin.im>2010-08-05 21:19:47 +0000
committerIvan Komarov <ivan.komarov@pidgin.im>2010-08-05 21:19:47 +0000
commite4871408779e25cb7ad6386940364c278e4b59d0 (patch)
tree72ca36af1dab61906a55b72ff8b28379d925eb16
parentc9a61d417881856022bd025766430da586b736db (diff)
downloadpidgin-e4871408779e25cb7ad6386940364c278e4b59d0.tar.gz
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.
-rw-r--r--libpurple/protocols/oscar/family_locate.c7
-rw-r--r--libpurple/protocols/oscar/family_oservice.c44
-rw-r--r--libpurple/protocols/oscar/oscar.c16
-rw-r--r--libpurple/protocols/oscar/oscar.h4
-rw-r--r--libpurple/protocols/oscar/tlv.c22
5 files changed, 82 insertions, 11 deletions
diff --git a/libpurple/protocols/oscar/family_locate.c b/libpurple/protocols/oscar/family_locate.c
index f8d0ac2823..a81d57fc52 100644
--- a/libpurple/protocols/oscar/family_locate.c
+++ b/libpurple/protocols/oscar/family_locate.c
@@ -245,6 +245,10 @@ static const struct {
{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 @@ byte_stream_putcaps(ByteStream *bs, guint64 caps)
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 --git a/libpurple/protocols/oscar/family_oservice.c b/libpurple/protocols/oscar/family_oservice.c
index e7aeeb2972..e4770703c9 100644
--- a/libpurple/protocols/oscar/family_oservice.c
+++ b/libpurple/protocols/oscar/family_oservice.c
@@ -842,6 +842,50 @@ aim_srv_setextrainfo(OscarData *od,
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 --git a/libpurple/protocols/oscar/oscar.c b/libpurple/protocols/oscar/oscar.c
index dd31ce597e..1b832a98fe 100644
--- a/libpurple/protocols/oscar/oscar.c
+++ b/libpurple/protocols/oscar/oscar.c
@@ -68,7 +68,8 @@ static guint64 purple_caps =
| 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 @@ incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo,
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 @@ static int purple_bosrights(OscarData *od, FlapConnection *conn, FlapFrame *fr,
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 --git a/libpurple/protocols/oscar/oscar.h b/libpurple/protocols/oscar/oscar.h
index aa7cd58814..16b01370cb 100644
--- a/libpurple/protocols/oscar/oscar.h
+++ b/libpurple/protocols/oscar/oscar.h
@@ -202,7 +202,8 @@ typedef enum
#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 @@ aim_rxcallback_t aim_callhandler(OscarData *od, guint16 family, guint16 subtype)
/* 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 --git a/libpurple/protocols/oscar/tlv.c b/libpurple/protocols/oscar/tlv.c
index fd495346c9..67f18080c3 100644
--- a/libpurple/protocols/oscar/tlv.c
+++ b/libpurple/protocols/oscar/tlv.c
@@ -371,6 +371,17 @@ int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value)
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_str(GSList **list, const guint16 type, const char *value)
*/
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);
}
/**