📄 im.c
字号:
/* Great. We found one. Fill it in. */ args->charset = sec->charset; args->charsubset = sec->charsubset; args->icbmflags |= AIM_IMFLAGS_CUSTOMCHARSET; /* Set up the simple flags */ if (args->charset == 0x0000) ; /* ASCII */ else if (args->charset == 0x0002) args->icbmflags |= AIM_IMFLAGS_UNICODE; else if (args->charset == 0x0003) args->icbmflags |= AIM_IMFLAGS_ISO_8859_1; else if (args->charset == 0xffff) ; /* no encoding (yeep!) */ if (args->charsubset == 0x0000) ; /* standard subencoding? */ else if (args->charsubset == 0x000b) args->icbmflags |= AIM_IMFLAGS_SUBENC_MACINTOSH; else if (args->charsubset == 0xffff) ; /* no subencoding */#if 0 /* XXX this isn't really necesary... */ if ( ((args.flag1 != 0x0000) && (args.flag1 != 0x0002) && (args.flag1 != 0x0003) && (args.flag1 != 0xffff)) || ((args.flag2 != 0x0000) && (args.flag2 != 0x000b) && (args.flag2 != 0xffff))) { faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", args.flag1, args.flag2); }#endif args->msg = sec->data; args->msglen = sec->datalen; return 0; } } /* No human-readable sections found. Oh well. */ args->charset = args->charsubset = 0xffff; args->msg = NULL; args->msglen = 0; return 0;}static int incomingim_ch1(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_bstream_t *bs, fu8_t *cookie){ fu16_t type, length; aim_rxcallback_t userfunc; int ret = 0; struct aim_incomingim_ch1_args args; int endpos; memset(&args, 0, sizeof(args)); aim_mpmsg_init(sess, &args.mpmsg); /* * This used to be done using tlvchains. For performance reasons, * I've changed it to process the TLVs in-place. This avoids lots * of per-IM memory allocations. */ while (aim_bstream_empty(bs)) { type = aimbs_get16(bs); length = aimbs_get16(bs); endpos = aim_bstream_curpos(bs) + length; if (type == 0x0002) { /* Message Block */ /* * This TLV consists of the following: * - 0501 -- Unknown * - Features: Don't know how to interpret these * - 0101 -- Unknown * - Message * */ aimbs_get8(bs); /* 05 */ aimbs_get8(bs); /* 01 */ args.featureslen = aimbs_get16(bs); /* XXX XXX this is all evil! */ args.features = bs->data + bs->offset; aim_bstream_advance(bs, args.featureslen); args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES; /* * The rest of the TLV contains one or more message * blocks... */ incomingim_ch1_parsemsgs(sess, bs->data + bs->offset /* XXX evil!!! */, length - 2 - 2 - args.featureslen, &args); } else if (type == 0x0003) { /* Server Ack Requested */ args.icbmflags |= AIM_IMFLAGS_ACK; } else if (type == 0x0004) { /* Message is Auto Response */ args.icbmflags |= AIM_IMFLAGS_AWAY; } else if (type == 0x0006) { /* Message was received offline. */ /* XXX not sure if this actually gets sent. */ args.icbmflags |= AIM_IMFLAGS_OFFLINE; } else if (type == 0x0008) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */ args.iconlen = aimbs_get32(bs); aimbs_get16(bs); /* 0x0001 */ args.iconsum = aimbs_get16(bs); args.iconstamp = aimbs_get32(bs); args.icbmflags |= AIM_IMFLAGS_HASICON; } else if (type == 0x0009) { args.icbmflags |= AIM_IMFLAGS_BUDDYREQ; } else if (type == 0x0017) { args.extdatalen = length; args.extdata = aimbs_getraw(bs, args.extdatalen); } else { faimdprintf(sess, 0, "incomingim_ch1: unknown TLV 0x%04x (len %d)\n", type, length); } /* * This is here to protect ourselves from ourselves. That * is, if something above doesn't completly parse its value * section, or, worse, overparses it, this will set the * stream where it needs to be in order to land on the next * TLV when the loop continues. * */ aim_bstream_setpos(bs, endpos); } if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, channel, userinfo, &args); aim_mpmsg_free(sess, &args.mpmsg); free(args.extdata); return ret;}static int incomingim_ch2_buddylist(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 *tse; aim_bstream_t tbs; if (args->status != 0x0000) return 1; /* ignore it -- not sure what it means */ tse = aim_gettlv(list2, 0x2711, 1); aim_bstream_init(&tbs, tse->value, tse->length); /* * This goes like this... * * group name length * group name * num of buddies in group * buddy name length * buddy name * buddy name length * buddy name * ... * group name length * group name * num of buddies in group * buddy name length * buddy name * ... * ... */ while (aim_bstream_empty(&tbs)) { fu16_t gnlen, numb; int i; char *gn; gnlen = aimbs_get16(&tbs); gn = aimbs_getstr(&tbs, gnlen); numb = aimbs_get16(&tbs); for (i = 0; i < numb; i++) { fu16_t bnlen; char *bn; bnlen = aimbs_get16(&tbs); bn = aimbs_getstr(&tbs, bnlen); faimdprintf(sess, 0, "got a buddy list from %s: group %s, buddy %s\n", userinfo->sn, gn, bn); free(bn); } free(gn); } if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, 0x0002, userinfo, args); return ret;}static int incomingim_ch2_buddyicon(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; if (!(miscinfo = aim_gettlv(list2, 0x2711, 1))) return 0; aim_bstream_init(&tbs, miscinfo->value, miscinfo->length); args->info.icon.checksum = aimbs_get32(&tbs); args->info.icon.length = aimbs_get32(&tbs); args->info.icon.timestamp = aimbs_get32(&tbs); args->info.icon.icon = aimbs_getraw(&tbs, args->info.icon.length); 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;}static int incomingim_ch2_voice(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_msgcookie_t *cachedcook; int ret = 0; aim_rxcallback_t userfunc; faimdprintf(sess, 1, "rend: voice!\n"); if (!(cachedcook = (aim_msgcookie_t*)calloc(1, sizeof(aim_msgcookie_t)))) return 0; memcpy(cachedcook->cookie, args->cookie, 8); cachedcook->type = AIM_COOKIETYPE_OFTVOICE; cachedcook->data = NULL; if (aim_cachecookie(sess, cachedcook) == -1) faimdprintf(sess, 0, "ERROR caching message cookie\n"); /* XXX: implement all this */ if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, 0x0002, userinfo, args); return ret;}static int incomingim_ch2_chat(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_tlv_t *miscinfo; aim_bstream_t tbs; aim_rxcallback_t userfunc; int ret = 0; miscinfo = aim_gettlv(list2, 0x2711, 1); aim_bstream_init(&tbs, miscinfo->value, miscinfo->length); aim_chat_readroominfo(&tbs, &args->info.chat.roominfo); if (aim_gettlv(list2, 0x000c, 1)) args->info.chat.msg = aim_gettlv_str(list2, 0x000c, 1); if (aim_gettlv(list2, 0x000d, 1)) args->info.chat.encoding = aim_gettlv_str(list2, 0x000d, 1); if (aim_gettlv(list2, 0x000e, 1)) args->info.chat.lang = aim_gettlv_str(list2, 0x000e, 1); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, 0x0002, userinfo, args); /* XXX free_roominfo */ free(args->info.chat.roominfo.name); free(args->info.chat.msg); free(args->info.chat.encoding); free(args->info.chat.lang); return ret;}static int incomingim_ch2_getfile(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){ char ip[30]; aim_msgcookie_t *cachedcook; aim_tlv_t *miscinfo; aim_tlv_t *iptlv, *porttlv; int ret = 0; aim_rxcallback_t userfunc; memset(ip, 0, 30); if (!(cachedcook = calloc(1, sizeof(aim_msgcookie_t)))) { aim_freetlvchain(&list2); return 0; } if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)) || !(iptlv = aim_gettlv(list2, 0x0003, 1)) || !(porttlv = aim_gettlv(list2, 0x0005, 1))) { faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn); aim_cookie_free(sess, cachedcook); aim_freetlvchain(&list2); return 0; } snprintf(ip, 30, "%d.%d.%d.%d:%d", aimutil_get8(iptlv->value+0), aimutil_get8(iptlv->value+1), aimutil_get8(iptlv->value+2), aimutil_get8(iptlv->value+3), aimutil_get16(porttlv->value)); faimdprintf(sess, 0, "rend: file get request from %s (%s)\n", userinfo->sn, ip); args->info.getfile.ip = ip; memcpy(args->info.getfile.cookie, args->cookie, 8); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, 0x0002, userinfo, args); return ret;}static int incomingim_ch2_sendfile(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){#if 0 char ip[30]; aim_msgcookie_t *cachedcook; aim_tlv_t *miscinfo; aim_tlv_t *iptlv, *porttlv; int ret =0; aim_rxcallback_t userfunc; char *desc = NULL; memset(ip, 0, 30); if (!(cachedcook = calloc(1, sizeof(aim_msgcookie_t)))) return 0; if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)) || !(iptlv = aim_gettlv(list2, 0x0003, 1)) || !(porttlv = aim_gettlv(list2, 0x0005, 1))) { faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn); aim_cookie_free(sess, cachedcook); return 0; } snprintf(ip, 30, "%d.%d.%d.%d:%d", aimutil_get8(iptlv->value+0), aimutil_get8(iptlv->value+1), aimutil_get8(iptlv->value+2), aimutil_get8(iptlv->value+3), aimutil_get16(porttlv->value)); if (aim_gettlv(list2, 0x000c, 1)) desc = aim_gettlv_str(list2, 0x000c, 1); faimdprintf(sess, 0, "rend: file transfer request from %s: %s (%s)\n", userinfo->sn, desc, ip); memcpy(cachedcook->cookie, args->cookie, 8); ft = malloc(sizeof(struct aim_filetransfer_priv)); /* XXX */ strncpy(ft->sn, userinfo.sn, sizeof(ft->sn)); strncpy(ft->ip, ip, sizeof(ft->ip)); strncpy(ft->fh.name, miscinfo->value+8, sizeof(ft->fh.name)); cachedcook->type = AIM_COOKIETYPE_OFTSEND; cachedcook->data = ft; if (aim_cachecookie(sess, cachedcook) == -1) faimdprintf(sess, 0, "ERROR caching message cookie\n"); aim_accepttransfer(sess, rx->conn, ft->sn, cookie, AIM_CAPS_SENDFILE); if (desc) free(desc); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, 0x0002, userinfo, &args);#endif return 0;}static int incomingim_ch2_imimage(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; /* Primary IP address */ if (aim_gettlv(list2, 0x0003, 1)) { aim_tlv_t *tlv; tlv = aim_gettlv(list2, 0x0003, 1); snprintf(args->info.imimage.ip, sizeof(args->info.imimage.ip), "%d.%d.%d.%d:4443", tlv->value[0], tlv->value[1], tlv->value[2], tlv->value[3]); } /* * Alternate IP address * * Sort of. The peer doesn't send this -- the OSCAR * server does. So it will be the IP address that the * peer is directly connected to the internet with, which * may not be the same as the IP above. If these two * values differ, it's rather unlikely that this * rendezvous is going to happen... * */ if (aim_gettlv(list2, 0x0004, 1)) ; /* Port number (not correct -- ignore) */ if (aim_gettlv(list2, 0x0005, 1)) ; /* Unknown -- two bytes = 0x0001 */ if (aim_gettlv(list2, 0x000a, 1)) ; /* Unknown -- no value */ if (aim_gettlv(list2, 0x000f, 1)) ; faimdprintf(sess, 1, "rend: directIM request from %s (%s)\n", userinfo->sn, args->info.imimage.ip);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -