Mercurial > pidgin.yaz
diff src/protocols/oscar/im.c @ 2866:6d62d4520460
[gaim-migrate @ 2879]
try that
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Mon, 10 Dec 2001 00:48:27 +0000 |
parents | e79f30457998 |
children | 9b029055cfba |
line wrap: on
line diff
--- a/src/protocols/oscar/im.c Mon Dec 10 00:14:07 2001 +0000 +++ b/src/protocols/oscar/im.c Mon Dec 10 00:48:27 2001 +0000 @@ -448,6 +448,122 @@ return 0; } +/* + * This only works for ICQ 2001b (thats 2001 not 2000). Better, only + * send it to clients advertising the RTF capability. In fact, if you send + * it to a client that doesn't support that capability, the server will gladly + * bounce it back to you. + * + * You'd think this would be in icq.c, but, well, I'm trying to stick with + * the one-group-per-file scheme as much as possible. This could easily + * be an exception, since Rendezvous IMs are external of the Oscar core, + * and therefore are undefined. Really I just need to think of a good way to + * make an interface similar to what AOL actually uses. But I'm not using COM. + * + */ +faim_export int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args) +{ + const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */ + aim_conn_t *conn; + int i; + fu8_t ck[8]; + aim_frame_t *fr; + aim_snacid_t snacid; + int servdatalen; + + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + return -EINVAL; + + if (!args || !args->destsn || !args->rtfmsg) + return -EINVAL; + + servdatalen = 2+2+16+2+4+1+2 + 2+2+4+4+4 + 2+4+2+strlen(args->rtfmsg)+1 + 4+4+4+strlen(rtfcap)+1; + + for (i = 0; i < 8; i++) + aimutil_put8(ck+i, (fu8_t) rand()); + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+128+servdatalen))) + return -ENOMEM; + + snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); + + /* + * Cookie + */ + aimbs_putraw(&fr->data, ck, 8); + + /* + * Channel (2) + */ + aimbs_put16(&fr->data, 0x0002); + + /* + * Dest sn + */ + aimbs_put8(&fr->data, strlen(args->destsn)); + aimbs_putraw(&fr->data, args->destsn, strlen(args->destsn)); + + /* + * TLV t(0005) + * + * Encompasses everything below. + */ + aimbs_put16(&fr->data, 0x0005); + aimbs_put16(&fr->data, 2+8+16 + 2+2+2 + 2+2 + 2+2+servdatalen); + + aimbs_put16(&fr->data, 0x0000); + aimbs_putraw(&fr->data, ck, 8); + aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY); + + /* + * t(000a) l(0002) v(0001) + */ + aimbs_put16(&fr->data, 0x000a); + aimbs_put16(&fr->data, 0x0002); + aimbs_put16(&fr->data, 0x0001); + + /* + * t(000f) l(0000) v() + */ + aimbs_put16(&fr->data, 0x000f); + aimbs_put16(&fr->data, 0x0000); + + /* + * Service Data TLV + */ + aimbs_put16(&fr->data, 0x2711); + aimbs_put16(&fr->data, servdatalen); + + aimbs_putle16(&fr->data, 11 + 16 /* 11 + (sizeof CLSID) */); + aimbs_putle16(&fr->data, 9); + aim_putcap(&fr->data, AIM_CAPS_EMPTY); + aimbs_putle16(&fr->data, 0); + aimbs_putle32(&fr->data, 0); + aimbs_putle8(&fr->data, 0); + aimbs_putle16(&fr->data, 0x03ea); /* trid1 */ + + aimbs_putle16(&fr->data, 14); + aimbs_putle16(&fr->data, 0x03eb); /* trid2 */ + aimbs_putle32(&fr->data, 0); + aimbs_putle32(&fr->data, 0); + aimbs_putle32(&fr->data, 0); + + aimbs_putle16(&fr->data, 0x0001); + aimbs_putle32(&fr->data, 0); + aimbs_putle16(&fr->data, strlen(args->rtfmsg)+1); + aimbs_putraw(&fr->data, args->rtfmsg, strlen(args->rtfmsg)+1); + + aimbs_putle32(&fr->data, args->fgcolor); + aimbs_putle32(&fr->data, args->bgcolor); + aimbs_putle32(&fr->data, strlen(rtfcap)+1); + aimbs_putraw(&fr->data, rtfcap, strlen(rtfcap)+1); + + aim_tx_enqueue(sess, fr); + + return 0; +} + faim_internal int aim_request_directim(aim_session_t *sess, const char *destsn, fu8_t *ip, fu16_t port, fu8_t *ckret) { aim_conn_t *conn; @@ -1368,6 +1484,54 @@ return ret; } +/* + * The relationship between AIM_CAPS_ICQSERVERRELAY and AIM_CAPS_ICQRTF is + * kind of odd. This sends the client ICQRTF since that is all that I've seen + * SERVERRELAY used for. + */ +static int incomingim_ch2_icqserverrelay(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_tlvlist_t *list2) +{ + aim_rxcallback_t userfunc; + int ret = 0; + aim_tlv_t *miscinfo; + aim_bstream_t tbs; + fu16_t hdrlen, anslen, msglen; + fu16_t msgtype; + + if (!(miscinfo = aim_gettlv(list2, 0x2711, 1))) + return 0; + aim_bstream_init(&tbs, miscinfo->value, miscinfo->length); + + hdrlen = aimbs_getle16(&tbs); + aim_bstream_advance(&tbs, hdrlen); + + hdrlen = aimbs_getle16(&tbs); + aim_bstream_advance(&tbs, hdrlen); + + msgtype = aimbs_getle16(&tbs); + + anslen = aimbs_getle32(&tbs); + aim_bstream_advance(&tbs, anslen); + + msglen = aimbs_getle16(&tbs); + args->info.rtfmsg.rtfmsg = aimbs_getstr(&tbs, msglen); + + args->info.rtfmsg.fgcolor = aimbs_getle32(&tbs); + args->info.rtfmsg.bgcolor = aimbs_getle32(&tbs); + + hdrlen = aimbs_getle32(&tbs); + aim_bstream_advance(&tbs, hdrlen); + + args->reqclass = AIM_CAPS_ICQRTF; + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, 0x0002, userinfo, args); + + free(args->info.icon.icon); + + return ret; +} + /* XXX Ugh. I think its obvious. */ static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, fu8_t *cookie) { @@ -1498,6 +1662,8 @@ ret = incomingim_ch2_getfile(sess, mod, rx, snac, userinfo, &args, list2); else if (args.reqclass & AIM_CAPS_SENDFILE) ret = incomingim_ch2_sendfile(sess, mod, rx, snac, userinfo, &args, list2); + else if (args.reqclass & AIM_CAPS_ICQSERVERRELAY) + ret = incomingim_ch2_icqserverrelay(sess, mod, rx, snac, userinfo, &args, list2); else faimdprintf(sess, 0, "rend: unknown rendezvous 0x%04x\n", args.reqclass);