📄 family_icbm.c
字号:
args.flags &= ~(AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_HASICON | AIM_IMFLAGS_MULTIPART); return aim_im_sendch1_ext(od, &args);}/* * Subtype 0x0006 - Send a chat invitation. */int aim_im_sendch2_chatinvite(OscarData *od, const char *sn, const char *msg, guint16 exchange, const char *roomname, guint16 instance){ FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; IcbmCookie *msgcookie; struct aim_invite_priv *priv; guchar cookie[8]; GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL; ByteStream hdrbs; if (!od || !(conn = flap_connection_findbygroup(od, 0x0004))) return -EINVAL; if (!sn || !msg || !roomname) return -EINVAL; aim_icbm_makecookie(cookie); frame = flap_frame_new(od, 0x02, 1152+strlen(sn)+strlen(roomname)+strlen(msg)); snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1); aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* XXX should be uncached by an unwritten 'invite accept' handler */ priv = g_malloc(sizeof(struct aim_invite_priv)); priv->sn = g_strdup(sn); priv->roomname = g_strdup(roomname); priv->exchange = exchange; priv->instance = instance; if ((msgcookie = aim_mkcookie(cookie, AIM_COOKIETYPE_INVITE, priv))) aim_cachecookie(od, msgcookie); else g_free(priv); /* ICBM Header */ aim_im_puticbm(&frame->data, cookie, 0x0002, sn); /* * TLV t(0005) * * Everything else is inside this TLV. * * Sigh. AOL was rather inconsistent right here. So we have * to play some minor tricks. Right inside the type 5 is some * raw data, followed by a series of TLVs. * */ byte_stream_new(&hdrbs, 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2); byte_stream_put16(&hdrbs, 0x0000); /* Unknown! */ byte_stream_putraw(&hdrbs, cookie, sizeof(cookie)); /* I think... */ byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_CHAT); aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001); aim_tlvlist_add_noval(&inner_tlvlist, 0x000f); aim_tlvlist_add_str(&inner_tlvlist, 0x000c, msg); aim_tlvlist_add_chatroom(&inner_tlvlist, 0x2711, exchange, roomname, instance); 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); return 0;}/** * Subtype 0x0006 - Send your icon to a given user. * * This is also performance sensitive. (If you can believe it...) * */int aim_im_sendch2_icon(OscarData *od, const char *sn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum){ FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; guchar cookie[8]; if (!od || !(conn = flap_connection_findbygroup(od, 0x0004))) return -EINVAL; if (!sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN)) return -EINVAL; aim_icbm_makecookie(cookie); frame = flap_frame_new(od, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2); 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 everything below. */ byte_stream_put16(&frame->data, 0x0005); byte_stream_put16(&frame->data, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT)); byte_stream_put16(&frame->data, 0x0000); byte_stream_putraw(&frame->data, cookie, 8); byte_stream_putcaps(&frame->data, OSCAR_CAPABILITY_BUDDYICON); /* 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, 4+4+4+iconlen+strlen(AIM_ICONIDENT)); byte_stream_put16(&frame->data, 0x0000); byte_stream_put16(&frame->data, iconsum); byte_stream_put32(&frame->data, iconlen); byte_stream_put32(&frame->data, stamp); byte_stream_putraw(&frame->data, icon, iconlen); byte_stream_putstr(&frame->data, AIM_ICONIDENT); /* 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 a rich text message. * * 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. * */int aim_im_sendch2_rtfmsg(OscarData *od, struct aim_sendrtfmsg_args *args){ FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; guchar cookie[8]; const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* OSCAR_CAPABILITY_ICQRTF capability in string form */ int servdatalen; if (!od || !(conn = flap_connection_findbygroup(od, 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; aim_icbm_makecookie(cookie); frame = flap_frame_new(od, 0x02, 10+128+servdatalen); 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, args->destsn); /* TLV t(0005) - Encompasses everything below. */ byte_stream_put16(&frame->data, 0x0005); byte_stream_put16(&frame->data, 2+8+16 + 2+2+2 + 2+2 + 2+2+servdatalen); byte_stream_put16(&frame->data, 0x0000); byte_stream_putraw(&frame->data, cookie, 8); byte_stream_putcaps(&frame->data, OSCAR_CAPABILITY_ICQSERVERRELAY); /* t(000a) l(0002) v(0001) */ byte_stream_put16(&frame->data, 0x000a); byte_stream_put16(&frame->data, 0x0002); byte_stream_put16(&frame->data, 0x0001); /* t(000f) l(0000) v() */ byte_stream_put16(&frame->data, 0x000f); byte_stream_put16(&frame->data, 0x0000); /* Service Data TLV */ byte_stream_put16(&frame->data, 0x2711); byte_stream_put16(&frame->data, servdatalen); byte_stream_putle16(&frame->data, 11 + 16 /* 11 + (sizeof CLSID) */); byte_stream_putle16(&frame->data, 9); byte_stream_putcaps(&frame->data, OSCAR_CAPABILITY_EMPTY); byte_stream_putle16(&frame->data, 0); byte_stream_putle32(&frame->data, 0); byte_stream_putle8(&frame->data, 0); byte_stream_putle16(&frame->data, 0x03ea); /* trid1 */ byte_stream_putle16(&frame->data, 14); byte_stream_putle16(&frame->data, 0x03eb); /* trid2 */ byte_stream_putle32(&frame->data, 0); byte_stream_putle32(&frame->data, 0); byte_stream_putle32(&frame->data, 0); byte_stream_putle16(&frame->data, 0x0001); byte_stream_putle32(&frame->data, 0); byte_stream_putle16(&frame->data, strlen(args->rtfmsg)+1); byte_stream_putraw(&frame->data, (const guint8 *)args->rtfmsg, strlen(args->rtfmsg)+1); byte_stream_putle32(&frame->data, args->fgcolor); byte_stream_putle32(&frame->data, args->bgcolor); byte_stream_putle32(&frame->data, strlen(rtfcap)+1); byte_stream_putraw(&frame->data, (const guint8 *)rtfcap, strlen(rtfcap)+1); flap_connection_send(conn, frame); return 0;}/** * Cancel a rendezvous invitation. It could be an invitation to * establish a direct connection, or a file-send, or a chat invite. */voidaim_im_sendch2_cancel(PeerConnection *peer_conn){ OscarData *od; FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL; ByteStream hdrbs; od = peer_conn->od; conn = flap_connection_findbygroup(od, 0x0004); if (conn == NULL) return; frame = flap_frame_new(od, 0x02, 128+strlen(peer_conn->sn)); snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ aim_im_puticbm(&frame->data, peer_conn->cookie, 0x0002, peer_conn->sn); aim_tlvlist_add_noval(&outer_tlvlist, 0x0003); byte_stream_new(&hdrbs, 64); byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_CANCEL); byte_stream_putraw(&hdrbs, peer_conn->cookie, 8); byte_stream_putcaps(&hdrbs, peer_conn->type); /* This TLV means "cancel!" */ aim_tlvlist_add_16(&inner_tlvlist, 0x000b, 0x0001); 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 an "I accept and I've connected to * you" message. */voidaim_im_sendch2_connected(PeerConnection *peer_conn){ OscarData *od; FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; od = peer_conn->od; conn = flap_connection_findbygroup(od, 0x0004); if (conn == NULL) return; frame = flap_frame_new(od, 0x02, 10 + 11+strlen(peer_conn->sn) + 4+2+8+16); snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ aim_im_puticbm(&frame->data, peer_conn->cookie, 0x0002, peer_conn->sn); byte_stream_put16(&frame->data, 0x0005); byte_stream_put16(&frame->data, 0x001a); byte_stream_put16(&frame->data, AIM_RENDEZVOUS_CONNECTED); byte_stream_putraw(&frame->data, peer_conn->cookie, 8); byte_stream_putcaps(&frame->data, peer_conn->type); flap_connection_send(conn, frame);}/** * Subtype 0x0006 - Send a direct connect rendezvous ICBM. This * could have a number of meanings, depending on the content: * "I want you to connect to me" * "I want to connect to you" * "I want to connect through a proxy server" */voidaim_im_sendch2_odc_requestdirect(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 port, guint16 requestnumber){ 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, 256+strlen(sn)); 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, 128); byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE); byte_stream_putraw(&hdrbs, cookie, 8); byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM); 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); 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 direct connect rendezvous ICBM asking the * remote user to connect to us via a proxy server. */voidaim_im_sendch2_odc_requestproxy(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 pin, guint16 requestnumber){ 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, 256+strlen(sn)); 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, 128); byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE); byte_stream_putraw(&hdrbs, cookie, 8); byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM); 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); 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -