📄 family_icbm.c
字号:
aim_tlvlist_free(inner_tlvlist); aim_tlvlist_free(outer_tlvlist); flap_connection_send(conn, frame);}/** * Subtype 0x0006 - Send an "I want to send you this file" message * */voidaim_im_sendch2_sendfile_requestdirect(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 port, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles){ FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL; ByteStream hdrbs; conn = flap_connection_findbygroup(od, 0x0004); if (conn == NULL) return; frame = flap_frame_new(od, 0x02, 1024); snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ aim_im_puticbm(&frame->data, cookie, 0x0002, sn); aim_tlvlist_add_noval(&outer_tlvlist, 0x0003); byte_stream_new(&hdrbs, 512); byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE); byte_stream_putraw(&hdrbs, cookie, 8); byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE); aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip); aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip); aim_tlvlist_add_16(&inner_tlvlist, 0x0005, port); aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber); aim_tlvlist_add_noval(&inner_tlvlist, 0x000f); /* TODO: Send 0x0016 and 0x0017 */#if 0 /* TODO: If the following is ever enabled, ensure that it is * not sent with a receive redirect or stage 3 proxy * redirect for a file receive (same conditions for * sending 0x000f above) */ aim_tlvlist_add_raw(&inner_tlvlist, 0x000e, 2, "en"); aim_tlvlist_add_raw(&inner_tlvlist, 0x000d, 8, "us-ascii"); aim_tlvlist_add_raw(&inner_tlvlist, 0x000c, 24, "Please accept this file.");#endif if (filename != NULL) { ByteStream bs; /* Begin TLV t(2711) */ byte_stream_new(&bs, 2+2+4+strlen(filename)+1); byte_stream_put16(&bs, (numfiles > 1) ? 0x0002 : 0x0001); byte_stream_put16(&bs, numfiles); byte_stream_put32(&bs, size); /* Filename - NULL terminated, for some odd reason */ byte_stream_putstr(&bs, filename); byte_stream_put8(&bs, 0x00); aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, bs.len, bs.data); g_free(bs.data); /* End TLV t(2711) */ } aim_tlvlist_write(&hdrbs, &inner_tlvlist); aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data); g_free(hdrbs.data); aim_tlvlist_write(&frame->data, &outer_tlvlist); aim_tlvlist_free(inner_tlvlist); aim_tlvlist_free(outer_tlvlist); flap_connection_send(conn, frame);}/** * Subtype 0x0006 - Send a sendfile connect rendezvous ICBM asking the * remote user to connect to us via a proxy server. */voidaim_im_sendch2_sendfile_requestproxy(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 pin, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles){ FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL; ByteStream hdrbs; guint8 ip_comp[4]; conn = flap_connection_findbygroup(od, 0x0004); if (conn == NULL) return; frame = flap_frame_new(od, 0x02, 1024); snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ aim_im_puticbm(&frame->data, cookie, 0x0002, sn); aim_tlvlist_add_noval(&outer_tlvlist, 0x0003); byte_stream_new(&hdrbs, 512); byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE); byte_stream_putraw(&hdrbs, cookie, 8); byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE); aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip); aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip); aim_tlvlist_add_16(&inner_tlvlist, 0x0005, pin); aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber); aim_tlvlist_add_noval(&inner_tlvlist, 0x000f); aim_tlvlist_add_noval(&inner_tlvlist, 0x0010); /* Send the bitwise complement of the port and ip. As a check? */ ip_comp[0] = ~ip[0]; ip_comp[1] = ~ip[1]; ip_comp[2] = ~ip[2]; ip_comp[3] = ~ip[3]; aim_tlvlist_add_raw(&inner_tlvlist, 0x0016, 4, ip_comp); aim_tlvlist_add_16(&inner_tlvlist, 0x0017, ~pin);#if 0 /* TODO: If the following is ever enabled, ensure that it is * not sent with a receive redirect or stage 3 proxy * redirect for a file receive (same conditions for * sending 0x000f above) */ aim_tlvlist_add_raw(&inner_tlvlist, 0x000e, 2, "en"); aim_tlvlist_add_raw(&inner_tlvlist, 0x000d, 8, "us-ascii"); aim_tlvlist_add_raw(&inner_tlvlist, 0x000c, 24, "Please accept this file.");#endif if (filename != NULL) { ByteStream bs; /* Begin TLV t(2711) */ byte_stream_new(&bs, 2+2+4+strlen(filename)+1); byte_stream_put16(&bs, (numfiles > 1) ? 0x0002 : 0x0001); byte_stream_put16(&bs, numfiles); byte_stream_put32(&bs, size); /* Filename - NULL terminated, for some odd reason */ byte_stream_putstr(&bs, filename); byte_stream_put8(&bs, 0x00); aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, bs.len, bs.data); g_free(bs.data); /* End TLV t(2711) */ } aim_tlvlist_write(&hdrbs, &inner_tlvlist); aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data); g_free(hdrbs.data); aim_tlvlist_write(&frame->data, &outer_tlvlist); aim_tlvlist_free(inner_tlvlist); aim_tlvlist_free(outer_tlvlist); flap_connection_send(conn, frame);}/** * Subtype 0x0006 - Request the status message of the given ICQ user. * * @param od 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. */int aim_im_sendch2_geticqaway(OscarData *od, const char *sn, int type){ FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; guchar cookie[8]; if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)) || !sn) return -EINVAL; aim_icbm_makecookie(cookie); frame = flap_frame_new(od, 0x02, 10+8+2+1+strlen(sn) + 4+0x5e + 4); snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ aim_im_puticbm(&frame->data, cookie, 0x0002, sn); /* TLV t(0005) - Encompasses almost everything below. */ byte_stream_put16(&frame->data, 0x0005); /* T */ byte_stream_put16(&frame->data, 0x005e); /* L */ { /* V */ byte_stream_put16(&frame->data, 0x0000); /* Cookie */ byte_stream_putraw(&frame->data, cookie, 8); /* Put the 16 byte server relay capability */ byte_stream_putcaps(&frame->data, OSCAR_CAPABILITY_ICQSERVERRELAY); /* TLV t(000a) */ byte_stream_put16(&frame->data, 0x000a); byte_stream_put16(&frame->data, 0x0002); byte_stream_put16(&frame->data, 0x0001); /* TLV t(000f) */ byte_stream_put16(&frame->data, 0x000f); byte_stream_put16(&frame->data, 0x0000); /* TLV t(2711) */ byte_stream_put16(&frame->data, 0x2711); byte_stream_put16(&frame->data, 0x0036); { /* V */ byte_stream_putle16(&frame->data, 0x001b); /* L */ byte_stream_putle16(&frame->data, 0x0009); /* Protocol version */ byte_stream_putcaps(&frame->data, OSCAR_CAPABILITY_EMPTY); byte_stream_putle16(&frame->data, 0x0000); /* Unknown */ byte_stream_putle16(&frame->data, 0x0001); /* Client features? */ byte_stream_putle16(&frame->data, 0x0000); /* Unknown */ byte_stream_putle8(&frame->data, 0x00); /* Unkizown */ byte_stream_putle16(&frame->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ byte_stream_putle16(&frame->data, 0x000e); /* L */ byte_stream_putle16(&frame->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ byte_stream_putle32(&frame->data, 0x00000000); /* Unknown */ byte_stream_putle32(&frame->data, 0x00000000); /* Unknown */ byte_stream_putle32(&frame->data, 0x00000000); /* Unknown */ /* The type of status message being requested */ if (type & AIM_ICQ_STATE_CHAT) byte_stream_putle16(&frame->data, 0x03ec); else if(type & AIM_ICQ_STATE_DND) byte_stream_putle16(&frame->data, 0x03eb); else if(type & AIM_ICQ_STATE_OUT) byte_stream_putle16(&frame->data, 0x03ea); else if(type & AIM_ICQ_STATE_BUSY) byte_stream_putle16(&frame->data, 0x03e9); else if(type & AIM_ICQ_STATE_AWAY) byte_stream_putle16(&frame->data, 0x03e8); byte_stream_putle16(&frame->data, 0x0001); /* Status? */ byte_stream_putle16(&frame->data, 0x0001); /* Priority of this message? */ byte_stream_putle16(&frame->data, 0x0001); /* L */ byte_stream_putle8(&frame->data, 0x00); /* String of length L */ } /* End TLV t(2711) */ } /* End TLV t(0005) */ /* TLV t(0003) */ byte_stream_put16(&frame->data, 0x0003); byte_stream_put16(&frame->data, 0x0000); flap_connection_send(conn, frame); return 0;}/** * Subtype 0x0006 - Send an ICQ-esque ICBM. * * 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. * * @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. */int aim_im_sendch4(OscarData *od, const char *sn, guint16 type, const char *message){ FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; guchar cookie[8]; if (!od || !(conn = flap_connection_findbygroup(od, 0x0002))) return -EINVAL; if (!sn || !type || !message) return -EINVAL; frame = flap_frame_new(od, 0x02, 10+8+3+strlen(sn)+12+strlen(message)+1+4); snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); aim_icbm_makecookie(cookie); /* ICBM header */ aim_im_puticbm(&frame->data, cookie, 0x0004, sn); /* * TLV t(0005) * * ICQ data (the UIN and the message). */ byte_stream_put16(&frame->data, 0x0005); byte_stream_put16(&frame->data, 4 + 2+2+strlen(message)+1); /* * Your UIN */ byte_stream_putle32(&frame->data, atoi(od->sn)); /* * TLV t(type) l(strlen(message)+1) v(message+NULL) */ byte_stream_putle16(&frame->data, type); byte_stream_putle16(&frame->data, strlen(message)+1); byte_stream_putraw(&frame->data, (const guint8 *)message, strlen(message)+1); /* * TLV t(0006) l(0000) v() */ byte_stream_put16(&frame->data, 0x0006); byte_stream_put16(&frame->data, 0x0000); flap_connection_send(conn, frame); return 0;}/* * XXX - I don't see when this would ever get called... */static int outgoingim(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){ int ret = 0; aim_rxcallback_t userfunc; guchar cookie[8]; guint16 channel; GSList *tlvlist; char *sn; int snlen; guint16 icbmflags = 0; guint8 flag1 = 0, flag2 = 0; gchar *msg = NULL; aim_tlv_t *msgblock; /* ICBM Cookie. */ aim_icbm_makecookie(cookie); /* Channel ID */ channel = byte_stream_get16(bs); if (channel != 0x01) { purple_debug_misc("oscar", "icbm: ICBM recieved on unsupported channel. Ignoring. (chan = %04x)\n", channel); return 0; } snlen = byte_stream_get8(bs); sn = byte_stream_getstr(bs, snlen); tlvlist = aim_tlvlist_read(bs); if (aim_tlv_gettlv(tlvlist, 0x0003, 1)) icbmflags |= AIM_IMFLAGS_ACK; if (aim_tlv_gettlv(tlvlist, 0x0004, 1)) icbmflags |= AIM_IMFLAGS_AWAY; if ((msgblock = aim_tlv_gettlv(tlvlist, 0x0002, 1))) { ByteStream mbs; int featurelen, msglen; byte_stream_init(&mbs, msgblock->value, msgblock->length); byte_stream_get8(&mbs); byte_stream_get8(&mbs); for (featurelen = byte_stream_get16(&mbs); featurelen; featurelen--) byte_stream_get8(&mbs); byte_stream_get8(&mbs); byte_stream_get8(&mbs); msglen = byte_stream_get16(&mbs) - 4; /* final block length */ flag1 = byte_stream_get16(&mbs); flag2 = byte_stream_get16(&mbs); msg = byte_stream_getstr(&mbs, msglen); } if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) ret = userfunc(od, conn, frame, channel, sn, msg, icbmflags, flag1, flag2); g_free(sn); g_free(msg); aim_tlvlist_free(tlvlist); return ret;}/* * Ahh, the joys of nearly ridiculous over-engineering. * * Not only do AIM ICBM's support multiple channels. Not only do they * support multiple character sets. But they support multiple character * sets / encodings within the same ICBM. * * These multipart messages allow for complex space savings techniques, which * seem utterly unnecessary by today's standards. In fact, there is only * one client still in popular use that still uses this method: AOL for the * Macintosh, Version 5.0. Obscure, yes, I know. * * In modern (non-"legacy") clients, if the user tries to send a character * that is not ISO-8859-1 or ASCII, the client will send the entire message * as UNICODE, meaning that every character in the message will occupy the * full 16 bit UNICODE field, even if the high order byte would be zero. * Multipart messages prevent this wasted space by allowing the client to * only send the characters in UNICODE that need to be sent that way, and * the rest of the message can be sent in whatever the native character * set is (probably ASCII). * * An important note is that sections will be displayed in the order that * they appear in the ICBM. There is no facility for merging or rearranging
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -