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

📄 family_icbm.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	return;}static voidincomingim_ch2_buddyicon(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata){	args->info.icon.checksum = byte_stream_get32(servdata);	args->info.icon.length = byte_stream_get32(servdata);	args->info.icon.timestamp = byte_stream_get32(servdata);	args->info.icon.icon = byte_stream_getraw(servdata, args->info.icon.length);	args->destructor = (void *)incomingim_ch2_buddyicon_free;	return;}static voidincomingim_ch2_chat_free(OscarData *od, IcbmArgsCh2 *args){	/* XXX - aim_chat_roominfo_free() */	g_free(args->info.chat.roominfo.name);	return;}static voidincomingim_ch2_chat(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata){	/*	 * Chat room info.	 */	aim_chat_readroominfo(servdata, &args->info.chat.roominfo);	args->destructor = (void *)incomingim_ch2_chat_free;}static voidincomingim_ch2_icqserverrelay_free(OscarData *od, IcbmArgsCh2 *args){	g_free((char *)args->info.rtfmsg.rtfmsg);}/* * The relationship between OSCAR_CAPABILITY_ICQSERVERRELAY and OSCAR_CAPABILITY_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 voidincomingim_ch2_icqserverrelay(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata){	guint16 hdrlen, anslen, msglen;	if (byte_stream_empty(servdata) < 24)		/* Someone sent us a short server relay ICBM.  Weird.  (Maybe?) */		return;	hdrlen = byte_stream_getle16(servdata);	byte_stream_advance(servdata, hdrlen);	hdrlen = byte_stream_getle16(servdata);	byte_stream_advance(servdata, hdrlen);	args->info.rtfmsg.msgtype = byte_stream_getle16(servdata);	anslen = byte_stream_getle32(servdata);	byte_stream_advance(servdata, anslen);	msglen = byte_stream_getle16(servdata);	args->info.rtfmsg.rtfmsg = byte_stream_getstr(servdata, msglen);	args->info.rtfmsg.fgcolor = byte_stream_getle32(servdata);	args->info.rtfmsg.bgcolor = byte_stream_getle32(servdata);	hdrlen = byte_stream_getle32(servdata);	byte_stream_advance(servdata, hdrlen);	args->destructor = (void *)incomingim_ch2_icqserverrelay_free;}static voidincomingim_ch2_sendfile_free(OscarData *od, IcbmArgsCh2 *args){	g_free(args->info.sendfile.filename);}/* Someone is sending us a file */static voidincomingim_ch2_sendfile(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata){	int flen;	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)? */	/* subtype is one of AIM_OFT_SUBTYPE_* */	args->info.sendfile.subtype = byte_stream_get16(servdata);	args->info.sendfile.totfiles = byte_stream_get16(servdata);	args->info.sendfile.totsize = byte_stream_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 byte_stream_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; byte_stream_get8(servdata); flen++);	byte_stream_advance(servdata, -flen -1);	args->info.sendfile.filename = byte_stream_getstr(servdata, flen);	/* There is sometimes more after the null-terminated filename,	 * but I'm unsure of its format. */	/* I don't believe him. */	/* There is sometimes a null byte inside a unicode filename,	 * but as far as I can tell the filename is the last	 * piece of data that will be in this message. --Jonathan */}typedef void (*ch2_args_destructor_t)(OscarData *od, IcbmArgsCh2 *args);static int incomingim_ch2(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, GSList *tlvlist, guint8 *cookie){	aim_rxcallback_t userfunc;	aim_tlv_t *block1, *servdatatlv;	GSList *list2;	aim_tlv_t *tlv;	IcbmArgsCh2 args;	ByteStream bbs, sdbs, *sdbsptr = NULL;	guint8 *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);	if (block1 == NULL)	{		/* The server sent us ch2 ICBM without ch2 info?  Weird. */		return 1;	}	byte_stream_init(&bbs, block1->value, block1->length);	/*	 * First two bytes represent the status of the connection.	 * One of the AIM_RENDEZVOUS_ defines.	 *	 * 0 is a request, 1 is a cancel, 2 is an accept	 */	args.status = byte_stream_get16(&bbs);	/*	 * Next comes the cookie.  Should match the ICBM cookie.	 */	cookie2 = byte_stream_getraw(&bbs, 8);	if (memcmp(cookie, cookie2, 8) != 0)	{		purple_debug_warning("oscar",				"Cookies don't match in rendezvous ICBM, bailing out.\n");		g_free(cookie2);		return 1;	}	memcpy(args.cookie, cookie2, 8);	g_free(cookie2);	/*	 * The next 16bytes are a capability block so we can	 * identify what type of rendezvous this is.	 */	args.type = aim_locate_getcaps(od, &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.	 *	 * TODO: I don't like this.  Maybe just read in an int?  Or inet_ntoa...	 */	tlv = aim_tlv_gettlv(list2, 0x0002, 1);	if ((tlv != NULL) && (tlv->length == 4))		snprintf(proxyip, sizeof(proxyip), "%hhu.%hhu.%hhu.%hhu",				tlv->value[0], tlv->value[1],				tlv->value[2], tlv->value[3]);	/*	 * IP address from the perspective of the client.	 */	tlv = aim_tlv_gettlv(list2, 0x0003, 1);	if ((tlv != NULL) && (tlv->length == 4))		snprintf(clientip, sizeof(clientip), "%hhu.%hhu.%hhu.%hhu",				tlv->value[0], tlv->value[1],				tlv->value[2], tlv->value[3]);	/*	 * Verified IP address (from the perspective of Oscar).	 *	 * This is added by the server.	 */	tlv = aim_tlv_gettlv(list2, 0x0004, 1);	if ((tlv != NULL) && (tlv->length == 4))		snprintf(verifiedip, sizeof(verifiedip), "%hhu.%hhu.%hhu.%hhu",				tlv->value[0], tlv->value[1],				tlv->value[2], tlv->value[3]);	/*	 * Port number for something.	 */	if (aim_tlv_gettlv(list2, 0x0005, 1))		args.port = aim_tlv_get16(list2, 0x0005, 1);	/*	 * File transfer "request number":	 * 0x0001 - Initial file transfer request for no proxy or stage 1 proxy	 * 0x0002 - "Reply request" for a stage 2 proxy (receiver wants to use proxy)	 * 0x0003 - A third request has been sent; applies only to stage 3 proxied transfers	 */	if (aim_tlv_gettlv(list2, 0x000a, 1))		args.requestnumber = aim_tlv_get16(list2, 0x000a, 1);	/*	 * Terminate connection/error code.  0x0001 means the other user	 * canceled the connection.	 */	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);#if 0	/*	 * Unknown -- no value	 *	 * Maybe means we should connect directly to transfer the file?	 * Also used in ICQ Lite Beta 4.0 URLs.  Also empty.	 */	 /* I don't think this indicates a direct transfer; this flag is	  * also present in a stage 1 proxied file send request -- Jonathan */	if (aim_tlv_gettlv(list2, 0x000f, 1)) {		/* Unhandled */	}#endif	/*	 * Flag meaning we should proxy the file transfer through an AIM server	 */	if (aim_tlv_gettlv(list2, 0x0010, 1))		args.use_proxy = TRUE;	if (strlen(proxyip))		args.proxyip = (char *)proxyip;	if (strlen(clientip))		args.clientip = (char *)clientip;	if (strlen(verifiedip))		args.verifiedip = (char *)verifiedip;	/*	 * This must be present in PROPOSALs, but will probably not	 * exist in CANCELs and ACCEPTs.  Also exists in ICQ Lite	 * Beta 4.0 URLs (OSCAR_CAPABILITY_ICQSERVERRELAY).	 *	 * Service Data blocks are module-specific in format.	 */	if ((servdatatlv = aim_tlv_gettlv(list2, 0x2711 /* 10001 */, 1))) {		byte_stream_init(&sdbs, servdatatlv->value, servdatatlv->length);		sdbsptr = &sdbs;		/*		 * The rest of the handling depends on what type it is.		 *		 * Not all of them have special handling (yet).		 */		if (args.type & OSCAR_CAPABILITY_BUDDYICON)			incomingim_ch2_buddyicon(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);		else if (args.type & OSCAR_CAPABILITY_SENDBUDDYLIST)			incomingim_ch2_buddylist(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);		else if (args.type & OSCAR_CAPABILITY_CHAT)			incomingim_ch2_chat(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);		else if (args.type & OSCAR_CAPABILITY_ICQSERVERRELAY)			incomingim_ch2_icqserverrelay(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);		else if (args.type & OSCAR_CAPABILITY_SENDFILE)			incomingim_ch2_sendfile(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);	}	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))		ret = userfunc(od, conn, frame, channel, userinfo, &args);	if (args.destructor)		((ch2_args_destructor_t)args.destructor)(od, &args);	g_free((char *)args.msg);	g_free((char *)args.encoding);	g_free((char *)args.language);	aim_tlvlist_free(list2);	return ret;}static int incomingim_ch4(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, GSList *tlvlist, guint8 *cookie){	ByteStream meat;	aim_rxcallback_t userfunc;	aim_tlv_t *block;	struct aim_incomingim_ch4_args args;	int ret = 0;	/*	 * Make a bstream for the meaty part.  Yum.  Meat.	 */	if (!(block = aim_tlv_gettlv(tlvlist, 0x0005, 1)))		return -1;	byte_stream_init(&meat, block->value, block->length);	args.uin = byte_stream_getle32(&meat);	args.type = byte_stream_getle8(&meat);	args.flags = byte_stream_getle8(&meat);	args.msglen = byte_stream_getle16(&meat);	args.msg = (gchar *)byte_stream_getraw(&meat, args.msglen);	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))		ret = userfunc(od, conn, frame, channel, userinfo, &args);	g_free(args.msg);	return ret;}/* * Subtype 0x0007 * * It can easily be said that parsing ICBMs is THE single * most difficult thing to do in the in AIM protocol.  In * fact, I think I just did say that. * * Below is the best damned solution I've come up with * over the past sixteen months of battling with it. This * can parse both away and normal messages from every client * I have access to.  Its not fast, its not clean.  But it works. * */static int incomingim(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){	int ret = 0;	guchar *cookie;	guint16 channel;	aim_userinfo_t userinfo;	memset(&userinfo, 0x00, sizeof(aim_userinfo_t));	/*	 * Read ICBM Cookie.	 */	cookie = byte_stream_getraw(bs, 8);	/*	 * Channel ID.	 *	 * Channel 0x0001 is the message channel.  It is	 * used to send basic ICBMs.	 *	 * Channel 0x0002 is the Rendezvous channel, which	 * is where Chat Invitiations and various client-client	 * connection negotiations come from.	 *	 * Channel 0x0003 is used for chat messages.	 *	 * Channel 0x0004 is used for ICQ authorization, or	 * possibly any system notice.	 *	 */	channel = byte_stream_get16(bs);	/*	 * Extract the standard user info block.	 *	 * Note that although this contains TLVs that appear contiguous	 * with the TLVs read below, they are two different pieces.  The	 * userinfo block contains the number of TLVs that contain user	 * information, the rest are not even though there is no separation.	 * You can start reading the message TLVs after aim_info_extract()	 * parses out the standard userinfo block.	 *	 * That also means that TLV types can be duplicated between the	 * userinfo block and the rest of the message, however there should	 * never be two TLVs of the same type in one block.	 *	 */	aim_info_extract(od, bs, &userinfo);	/*	 * From here on, its depends on what channel we're on.	 *	 * Technically all channels have a TLV list have this, however,	 * for the common channel 1 case, in-place parsing is used for	 * performance reasons (

⌨️ 快捷键说明

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