⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 im.c

📁 oscar message protocol stack
💻 C
📖 第 1 页 / 共 5 页
字号:
			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);			/*			 * This looks to be a client bug.  MacAIM 4.3 will			 * send this tag, but with all zero values, in the			 * first message of a conversation. This makes no			 * sense whatsoever, so I'm going to say its a bug.			 *			 * You really shouldn't advertise a zero-length icon			 * anyway.			 * 			 */			if (args.iconlen)				args.icbmflags |= AIM_IMFLAGS_HASICON;		} else if (type == 0x0009) {			args.icbmflags |= AIM_IMFLAGS_BUDDYREQ;		} else if (type == 0x000b) { /* Non-direct connect typing notification */			args.icbmflags |= AIM_IMFLAGS_TYPINGNOT;		} 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 completely 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 void 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_bstream_t *servdata){	/*	 * 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 (servdata && aim_bstream_empty(servdata)) {		fu16_t gnlen, numb;		int i;		char *gn;		gnlen = aimbs_get16(servdata);		gn = aimbs_getstr(servdata, gnlen);		numb = aimbs_get16(servdata);		for (i = 0; i < numb; i++) {			fu16_t bnlen;			char *bn;			bnlen = aimbs_get16(servdata);			bn = aimbs_getstr(servdata, bnlen);			faimdprintf(sess, 0, "got a buddy list from %s: group %s, buddy %s\n", userinfo->sn, gn, bn);			free(bn);		}		free(gn);	}	return;}static void incomingim_ch2_buddyicon_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args){	free(args->info.icon.icon);	return;}static void 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_bstream_t *servdata){	if (servdata) {		args->info.icon.checksum = aimbs_get32(servdata);		args->info.icon.length = aimbs_get32(servdata);		args->info.icon.timestamp = aimbs_get32(servdata);		args->info.icon.icon = aimbs_getraw(servdata, args->info.icon.length);	}	args->destructor = (void *)incomingim_ch2_buddyicon_free;	return;}static void incomingim_ch2_chat_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args){	/* XXX - aim_chat_roominfo_free() */	free(args->info.chat.roominfo.name);	return;}static void 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_bstream_t *servdata){	/*	 * Chat room info.	 */	if (servdata)		aim_chat_readroominfo(servdata, &args->info.chat.roominfo);	args->destructor = (void *)incomingim_ch2_chat_free;	return;}static void incomingim_ch2_icqserverrelay_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args){	free((char *)args->info.rtfmsg.rtfmsg);	return;}/* * The relationship between AIM_CAPS_ICQSERVERRELAY and AIM_CAPS_ICQRTF is  * kind of odd. This sends the client ICQRTF since that is all that I've seen * SERVERRELAY used for. * * Note that this is all little-endian.  Cringe. * */static void incomingim_ch2_icqserverrelay(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_bstream_t *servdata){	fu16_t hdrlen, anslen, msglen;	hdrlen = aimbs_getle16(servdata);	aim_bstream_advance(servdata, hdrlen);	hdrlen = aimbs_getle16(servdata);	aim_bstream_advance(servdata, hdrlen);	args->info.rtfmsg.msgtype = aimbs_getle16(servdata);	anslen = aimbs_getle32(servdata);	aim_bstream_advance(servdata, anslen);	msglen = aimbs_getle16(servdata);	args->info.rtfmsg.rtfmsg = aimbs_getstr(servdata, msglen);	args->info.rtfmsg.fgcolor = aimbs_getle32(servdata);	args->info.rtfmsg.bgcolor = aimbs_getle32(servdata);	hdrlen = aimbs_getle32(servdata);	aim_bstream_advance(servdata, hdrlen);	args->destructor = (void *)incomingim_ch2_icqserverrelay_free;	return;}static void incomingim_ch2_sendfile_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args){	free(args->info.sendfile.filename);}static void 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_bstream_t *servdata){	args->destructor = (void *)incomingim_ch2_sendfile_free;	/* Maybe there is a better way to tell what kind of sendfile 	 * this is?  Maybe TLV t(000a)? */	if (servdata) { /* Someone is sending us a file */		int flen;		/* subtype is one of AIM_OFT_SUBTYPE_* */		args->info.sendfile.subtype = aimbs_get16(servdata);		args->info.sendfile.totfiles = aimbs_get16(servdata);		args->info.sendfile.totsize = aimbs_get32(servdata);		/*		 * I hope to God I'm right when I guess that there is a 		 * 32 char max filename length for single files.  I think 		 * OFT tends to do that.  Gotta love inconsistency.  I saw 		 * a 26 byte filename?		 */		/* AAA - create an aimbs_getnullstr function (don't anymore)(maybe) */		/* Use an inelegant way of getting the null-terminated filename, 		 * since there's no easy bstream routine. */		for (flen = 0; aimbs_get8(servdata); flen++);		aim_bstream_advance(servdata, -flen -1);		args->info.sendfile.filename = aimbs_getstr(servdata, flen);		/* There is sometimes more after the null-terminated filename, 		 * but I'm unsure of its format. */		/* I don't believe him. */	}	return;}typedef void (*ch2_args_destructor_t)(aim_session_t *sess, struct aim_incomingim_ch2_args *args);static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, fu8_t *cookie){	aim_rxcallback_t userfunc;	aim_tlv_t *block1, *servdatatlv;	aim_tlvlist_t *list2;	struct aim_incomingim_ch2_args args;	aim_bstream_t bbs, sdbs, *sdbsptr = NULL;	fu8_t *cookie2;	int ret = 0;	char proxyip[30] = {""};	char clientip[30] = {""};	char verifiedip[30] = {""};	memset(&args, 0, sizeof(args));	/*	 * There's another block of TLVs embedded in the type 5 here.	 */	block1 = aim_tlv_gettlv(tlvlist, 0x0005, 1);	aim_bstream_init(&bbs, block1->value, block1->length);	/*	 * First two bytes represent the status of the connection.	 *	 * 0 is a request, 1 is a cancel, 2 is an accept	 */	args.status = aimbs_get16(&bbs);	/*	 * Next comes the cookie.  Should match the ICBM cookie.	 */	cookie2 = aimbs_getraw(&bbs, 8);	if (memcmp(cookie, cookie2, 8) != 0)		faimdprintf(sess, 0, "rend: warning cookies don't match!\n");	memcpy(args.cookie, cookie2, 8);	free(cookie2);	/*	 * The next 16bytes are a capability block so we can	 * identify what type of rendezvous this is.	 */	args.reqclass = aim_locate_getcaps(sess, &bbs, 0x10);	/* 	 * What follows may be TLVs or nothing, depending on the	 * purpose of the message.	 *	 * Ack packets for instance have nothing more to them.	 */	list2 = aim_tlvlist_read(&bbs);	/*	 * IP address to proxy the file transfer through.	 *	 * XXX - I don't like this.  Maybe just read in an int?  Or inet_ntoa...	 */	if (aim_tlv_gettlv(list2, 0x0002, 1)) {		aim_tlv_t *iptlv;		iptlv = aim_tlv_gettlv(list2, 0x0002, 1);		if (iptlv->length == 4)			snprintf(proxyip, sizeof(proxyip), "%hhu.%hhu.%hhu.%hhu",				iptlv->value[0], iptlv->value[1],				iptlv->value[2], iptlv->value[3]);	}	/*	 * IP address from the perspective of the client.	 */	if (aim_tlv_gettlv(list2, 0x0003, 1)) {		aim_tlv_t *iptlv;		iptlv = aim_tlv_gettlv(list2, 0x0003, 1);		if (iptlv->length == 4)			snprintf(clientip, sizeof(clientip), "%hhu.%hhu.%hhu.%hhu",				iptlv->value[0], iptlv->value[1],				iptlv->value[2], iptlv->value[3]);	}	/*	 * Verified IP address (from the perspective of Oscar).	 *	 * This is added by the server.	 */	if (aim_tlv_gettlv(list2, 0x0004, 1)) {		aim_tlv_t *iptlv;		iptlv = aim_tlv_gettlv(list2, 0x0004, 1);		if (iptlv->length == 4)			snprintf(verifiedip, sizeof(verifiedip), "%hhu.%hhu.%hhu.%hhu",				iptlv->value[0], iptlv->value[1],				iptlv->value[2], iptlv->value[3]);	}	/*	 * Port number for something.	 */	if (aim_tlv_gettlv(list2, 0x0005, 1))		args.port = aim_tlv_get16(list2, 0x0005, 1);	/*	 * Something to do with ft? -- two bytes	 * 0x0001 - "I want to send you this file"	 * 0x0002 - "I will accept this file from you"	 * 0x0002 - Also used in ICQ Lite Beta 4.0 URLs	 */	if (aim_tlv_gettlv(list2, 0x000a, 1))		;	/*	 * Error code.	 */	if (aim_tlv_gettlv(list2, 0x000b, 1))		args.errorcode = aim_tlv_get16(list2, 0x000b, 1);	/*	 * Invitation message / chat description.	 */	if (aim_tlv_gettlv(list2, 0x000c, 1)) {		args.msg = aim_tlv_getstr(list2, 0x000c, 1);		args.msglen = aim_tlv_getlength(list2, 0x000c, 1);	}	/*	 * Character set.	 */	if (aim_tlv_gettlv(list2, 0x000d, 1))		args.encoding = aim_tlv_getstr(list2, 0x000d, 1);		/*	 * Language.	 */	if (aim_tlv_gettlv(list2, 0x000e, 1))		args.language = aim_tlv_getstr(list2, 0x000e, 1);	/*	 * Unknown -- no value	 *	 * Maybe means we should connect directly to transfer the file?	 * Also used in ICQ Lite Beta 4.0 URLs.  Also empty.	 */	if (aim_tlv_gettlv(list2, 0x000f, 1))		;	/*	 * Unknown -- no value	 *	 * Maybe means we should proxy the file transfer through an AIM server?

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -