📄 im.c
字号:
aimbs_put16(&fr->data, 0x0002); /* Channel */ aimbs_put8(&fr->data, strlen(sn)); /* Screename length */ aimbs_putraw(&fr->data, sn, strlen(sn)); /* Screenname */ /* * 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. * */ hdrlen = 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2; hdr = malloc(hdrlen); aim_bstream_init(&hdrbs, hdr, hdrlen); aimbs_put16(&hdrbs, 0x0000); /* Unknown! */ aimbs_putraw(&hdrbs, ck, sizeof(ck)); /* I think... */ aim_putcap(&hdrbs, AIM_CAPS_CHAT); aim_tlvlist_add_16(&itl, 0x000a, 0x0001); aim_tlvlist_add_noval(&itl, 0x000f); aim_tlvlist_add_raw(&itl, 0x000c, strlen(msg), msg); aim_tlvlist_add_chatroom(&itl, 0x2711, exchange, roomname, instance); aim_tlvlist_write(&hdrbs, &itl); aim_tlvlist_add_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr); aim_tlvlist_write(&fr->data, &otl); free(hdr); aim_tlvlist_free(&itl); aim_tlvlist_free(&otl); aim_tx_enqueue(sess, fr); return 0;}/** * Subtype 0x0006 - Send your icon to a given user. * * This is also performance sensitive. (If you can believe it...) * */faim_export int aim_im_sendch2_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum){ aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; fu8_t ck[8]; int i; if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) return -EINVAL; if (!sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN)) return -EINVAL; for (i = 0; i < 8; i++) ck[i] = (fu8_t)rand(); if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 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))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ aim_im_puticbm(&fr->data, ck, 0x0002, sn); /* * TLV t(0005) * * Encompasses everything below. */ aimbs_put16(&fr->data, 0x0005); aimbs_put16(&fr->data, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT)); aimbs_put16(&fr->data, 0x0000); aimbs_putraw(&fr->data, ck, 8); aim_putcap(&fr->data, AIM_CAPS_BUDDYICON); /* 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, 4+4+4+iconlen+strlen(AIM_ICONIDENT)); aimbs_put16(&fr->data, 0x0000); aimbs_put16(&fr->data, iconsum); aimbs_put32(&fr->data, iconlen); aimbs_put32(&fr->data, stamp); aimbs_putraw(&fr->data, icon, iconlen); aimbs_putraw(&fr->data, AIM_ICONIDENT, strlen(AIM_ICONIDENT)); /* TLV t(0003) */ aimbs_put16(&fr->data, 0x0003); aimbs_put16(&fr->data, 0x0000); aim_tx_enqueue(sess, fr); 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. * */faim_export int aim_im_sendch2_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args){ aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; fu8_t ck[8]; const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */ int i, 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++) 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); /* ICBM header */ aim_im_puticbm(&fr->data, ck, 0x0002, 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;}/** * Subtype 0x0006 - Send an "I want to directly connect to you" message * */faim_export int aim_im_sendch2_odcrequest(aim_session_t *sess, fu8_t *cookie, bool usecookie, const char *sn, const fu8_t *ip, fu16_t port){ aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; fu8_t ck[8]; aim_tlvlist_t *tl = NULL, *itl = NULL; int hdrlen, i; fu8_t *hdr; aim_bstream_t hdrbs; if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) return -EINVAL; if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen(sn)))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); /* * Generate a random message cookie * * This cookie needs to be alphanumeric and NULL-terminated to be * TOC-compatible. * * XXX - have I mentioned these should be generated in msgcookie.c? * */ if (cookie && usecookie) /* allow user-specified cookie */ memcpy(ck, cookie, 8); else for (i = 0; i < 7; i++) ck[i] = 0x30 + ((fu8_t) rand() % 10); ck[7] = '\0'; if (cookie && !usecookie) memcpy(cookie, ck, 8); /* ICBM header */ aim_im_puticbm(&fr->data, ck, 0x0002, sn); aim_tlvlist_add_noval(&tl, 0x0003); hdrlen = 2+8+16+6+8+6+4; hdr = malloc(hdrlen); aim_bstream_init(&hdrbs, hdr, hdrlen); aimbs_put16(&hdrbs, 0x0000); aimbs_putraw(&hdrbs, ck, 8); aim_putcap(&hdrbs, AIM_CAPS_DIRECTIM); aim_tlvlist_add_16(&itl, 0x000a, 0x0001); aim_tlvlist_add_raw(&itl, 0x0003, 4, ip); aim_tlvlist_add_16(&itl, 0x0005, port); aim_tlvlist_add_noval(&itl, 0x000f); aim_tlvlist_write(&hdrbs, &itl); aim_tlvlist_add_raw(&tl, 0x0005, aim_bstream_curpos(&hdrbs), hdr); aim_tlvlist_write(&fr->data, &tl); free(hdr); aim_tlvlist_free(&itl); aim_tlvlist_free(&tl); aim_tx_enqueue(sess, fr); return 0;}/** * Subtype 0x0006 - Send an "I want to send you this file" message * */faim_export int aim_im_sendch2_sendfile_ask(aim_session_t *sess, struct aim_oft_info *oft_info){ aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; aim_tlvlist_t *tl=NULL, *subtl=NULL; int i; if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info) return -EINVAL; /* XXX - Should be like "21CBF95" and null terminated */ for (i = 0; i < 7; i++) oft_info->cookie[i] = 0x30 + ((fu8_t)rand() % 10); oft_info->cookie[7] = '\0'; { /* Create the subTLV chain */ fu8_t *buf; int buflen; aim_bstream_t bs; aim_tlvlist_add_16(&subtl, 0x000a, 0x0001); aim_tlvlist_add_noval(&subtl, 0x000f);/* aim_tlvlist_add_raw(&subtl, 0x000e, 2, "en"); aim_tlvlist_add_raw(&subtl, 0x000d, 8, "us-ascii"); aim_tlvlist_add_raw(&subtl, 0x000c, 24, "Please accept this file."); */ /* XXX - Change oft_info->clientip to an array of 4 bytes */ if (oft_info->clientip) { fu8_t ip[4]; char *nexttoken; int i = 0; nexttoken = strtok(oft_info->clientip, "."); while (nexttoken && i<4) { ip[i] = atoi(nexttoken); nexttoken = strtok(NULL, "."); i++; } aim_tlvlist_add_raw(&subtl, 0x0003, 4, ip); } aim_tlvlist_add_16(&subtl, 0x0005, oft_info->port); /* TLV t(2711) */ buflen = 2+2+4+strlen(oft_info->fh.name)+1; buf = malloc(buflen); aim_bstream_init(&bs, buf, buflen); aimbs_put16(&bs, (oft_info->fh.totfiles > 1) ? 0x0002 : 0x0001); aimbs_put16(&bs, oft_info->fh.totfiles); aimbs_put32(&bs, oft_info->fh.totsize); /* Filename - NULL terminated, for some odd reason */ aimbs_putraw(&bs, oft_info->fh.name, strlen(oft_info->fh.name)); aimbs_put8(&bs, 0x00); aim_tlvlist_add_raw(&subtl, 0x2711, bs.len, bs.data); free(buf); } { /* Create the main TLV chain */ fu8_t *buf; int buflen; aim_bstream_t bs; /* TLV t(0005) - Encompasses everything from above. Gee. */ buflen = 2+8+16+aim_tlvlist_size(&subtl); buf = malloc(buflen); aim_bstream_init(&bs, buf, buflen); aimbs_put16(&bs, AIM_RENDEZVOUS_PROPOSE); aimbs_putraw(&bs, oft_info->cookie, 8); aim_putcap(&bs, AIM_CAPS_SENDFILE); aim_tlvlist_write(&bs, &subtl); aim_tlvlist_free(&subtl); aim_tlvlist_add_raw(&tl, 0x0005, bs.len, bs.data); free(buf); /* TLV t(0003) - Request an ack */ aim_tlvlist_add_noval(&tl, 0x0003); } if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + aim_tlvlist_size(&tl)))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0004, 0x0006, AIM_SNACFLAGS_DESTRUCTOR, oft_info->cookie, sizeof(oft_info->cookie)); aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn); /* All that crap from above (the 0x0005 TLV and the 0x0003 TLV) */ aim_tlvlist_write(&fr->data, &tl); aim_tlvlist_free(&tl); aim_tx_enqueue(sess, fr); return 0;}/** * Subtype 0x0006 - Send an "I will accept this file" message? * * @param rendid Capability type (AIM_CAPS_GETFILE or AIM_CAPS_SENDFILE) */faim_export int aim_im_sendch2_sendfile_accept(aim_session_t *sess, struct aim_oft_info *oft_info){ aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info) return -EINVAL; if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + 4+2+8+16))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn); aimbs_put16(&fr->data, 0x0005); aimbs_put16(&fr->data, 0x001a); aimbs_put16(&fr->data, AIM_RENDEZVOUS_ACCEPT); aimbs_putraw(&fr->data, oft_info->cookie, 8); aim_putcap(&fr->data, AIM_CAPS_SENDFILE); aim_tx_enqueue(sess, fr); return 0;}/** * Subtype 0x0006 - Send a "cancel this file transfer" message? * */faim_export int aim_im_sendch2_sendfile_cancel(aim_session_t *sess, struct aim_oft_info *oft_info){ aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info) return -EINVAL; if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + 4+2+8+16))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn); aimbs_put16(&fr->data, 0x0005); aimbs_put16(&fr->data, 0x001a); aimbs_put16(&fr->data, AIM_RENDEZVOUS_CANCEL); aimbs_putraw(&fr->data, oft_info->cookie, 8); aim_putcap(&fr->data, AIM_CAPS_SENDFILE); aim_tx_enqueue(sess, fr); return 0;}/** * Subtype 0x0006 - 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_im_sendch2_geticqaway(aim_session_t *sess, const char *sn, int type){ aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -