Mercurial > pidgin.yaz
diff src/protocols/oscar/im.c @ 3212:56746b0868db
[gaim-migrate @ 3229]
More OSCAR stuff from KingAnt!
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sun, 05 May 2002 19:02:08 +0000 |
parents | fce1883cc608 |
children | bea080f7f5c7 |
line wrap: on
line diff
--- a/src/protocols/oscar/im.c Sun May 05 18:43:20 2002 +0000 +++ b/src/protocols/oscar/im.c Sun May 05 19:02:08 2002 +0000 @@ -732,16 +732,127 @@ return 0; } -/* +/** + * Request the status message of the given ICQ user. + * + * @param sess The oscar session. + * @param sn The UIN of the user of whom you wish to request info. + * @param type The type of info you wish to request. This should be the current + * state of the user, as one of the AIM_ICQ_STATE_* defines. + * @return Return 0 if no errors, otherwise return the error number. + */ +faim_export int aim_send_im_ch2_geticqmessage(aim_session_t *sess, const char *sn, int type) +{ + aim_conn_t *conn; + int i; + fu8_t ck[8]; + aim_frame_t *fr; + aim_snacid_t snacid; + + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !sn) + return -EINVAL; + + 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+8+2+1+strlen(sn) + 4+0x5e + 4))) + 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(sn)); + aimbs_putraw(&fr->data, sn, strlen(sn)); + + /* TLV t(0005) - Encompasses almost everything below. */ + aimbs_put16(&fr->data, 0x0005); /* T */ + aimbs_put16(&fr->data, 0x005e); /* L */ + { /* V */ + aimbs_put16(&fr->data, 0x0000); + + /* Cookie */ + aimbs_putraw(&fr->data, ck, 8); + + /* Put the 16 byte server relay capability */ + aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY); + + /* TLV t(000a) */ + aimbs_put16(&fr->data, 0x000a); + aimbs_put16(&fr->data, 0x0002); + aimbs_put16(&fr->data, 0x0001); + + /* TLV t(000f) */ + aimbs_put16(&fr->data, 0x000f); + aimbs_put16(&fr->data, 0x0000); + + /* TLV t(2711) */ + aimbs_put16(&fr->data, 0x2711); + aimbs_put16(&fr->data, 0x0036); + { /* V */ + aimbs_putle16(&fr->data, 0x001b); /* L */ + aimbs_putle16(&fr->data, 0x0008); /* AAA - Protocol version */ + aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + aimbs_putle16(&fr->data, 0x0000); /* Unknown */ + aimbs_putle16(&fr->data, 0x0003); /* Client features? */ + aimbs_putle16(&fr->data, 0x0000); /* Unknown */ + aimbs_putle8(&fr->data, 0x00); /* Unkizown */ + aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ + + aimbs_putle16(&fr->data, 0x000e); /* L */ + aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ + aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + + /* The type of status message being requested */ + if (type & AIM_ICQ_STATE_CHAT) + aimbs_putle16(&fr->data, 0x03ec); + else if(type & AIM_ICQ_STATE_DND) + aimbs_putle16(&fr->data, 0x03eb); + else if(type & AIM_ICQ_STATE_OUT) + aimbs_putle16(&fr->data, 0x03ea); + else if(type & AIM_ICQ_STATE_BUSY) + aimbs_putle16(&fr->data, 0x03e9); + else if(type & AIM_ICQ_STATE_AWAY) + aimbs_putle16(&fr->data, 0x03e8); + + aimbs_putle16(&fr->data, 0x0000); /* Status? */ + aimbs_putle16(&fr->data, 0x0001); /* Priority of this message? */ + aimbs_putle16(&fr->data, 0x0001); /* L? */ + aimbs_putle8(&fr->data, 0x00); /* Null termination? */ + } /* End TLV t(2711) */ + } /* End TLV t(0005) */ + + /* TLV t(0003) */ + aimbs_put16(&fr->data, 0x0003); + aimbs_put16(&fr->data, 0x0000); + + aim_tx_enqueue(sess, fr); + + return 0; +} + +/** * This can be used to send an ICQ authorization reply (deny or grant). It is the "old way." * The new way is to use SSI. I like the new way a lot better. This seems like such a hack, * mostly because it's in network byte order. Figuring this stuff out sometimes takes a while, * but thats ok, because it gives me time to try to figure out what kind of drugs the AOL people * were taking when they merged the two protocols. * - * sn is the destination screen name - * type is the type of message. 0x0007 for authorization denied. 0x0008 for authorization granted - * message is the message you want to send, it should be null terminated + * @param sn The destination screen name. + * @param type The type of message. 0x0007 for authorization denied. 0x0008 for authorization granted. + * @param message The message you want to send, it should be null terminated. + * @return Return 0 if no errors, otherwise return the error number. */ faim_export int aim_send_im_ch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message) { @@ -1859,7 +1970,11 @@ return ret; } -static int clienterr(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) +/* + * Receive the response from an ICQ status message request. This contains the + * ICQ status message. Go figure. + */ +static int clientautoresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1873,8 +1988,58 @@ sn = aimbs_getstr(bs, snlen); reason = aimbs_get16(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, sn, reason); + switch (reason) { + case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */ + fu8_t statusmsgtype, *msg; + fu16_t len; + fu32_t state; + + len = aimbs_getle16(bs); /* Should be 0x001b */ + free(aimbs_getraw(bs, len)); /* Unknown */ + + len = aimbs_getle16(bs); /* Should be 0x000e */ + free(aimbs_getraw(bs, len)); /* Unknown */ + + statusmsgtype = aimbs_getle8(bs); + switch (statusmsgtype) { + case 0xe8: + state = AIM_ICQ_STATE_AWAY; + break; + case 0xe9: + state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY; + break; + case 0xea: + state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT; + break; + case 0xeb: + state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY; + break; + case 0xec: + state = AIM_ICQ_STATE_CHAT; + break; + default: + state = 0; + break; + } + + aimbs_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */ + aimbs_getle16(bs); /* Unknown - 0x0000 */ + aimbs_getle16(bs); /* Unknown - 0x0000 */ + + len = aimbs_getle16(bs); + msg = aimbs_getraw(bs, len); + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, sn, reason, state, msg); + + free(msg); + } break; + + default: { + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, sn, reason); + } break; + } /* end switch */ free(ck); free(sn); @@ -1916,7 +2081,7 @@ else if (snac->subtype == 0x000a) return missedcall(sess, mod, rx, snac, bs); else if (snac->subtype == 0x000b) - return clienterr(sess, mod, rx, snac, bs); + return clientautoresp(sess, mod, rx, snac, bs); else if (snac->subtype == 0x000c) return msgack(sess, mod, rx, snac, bs);