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

📄 family_icbm.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * sections at run time.  So if you have, say, ASCII then UNICODE then ASCII, * you must supply two ASCII sections with a UNICODE in the middle, and incur * the associated overhead. * * Normally I would have laughed and given a firm 'no' to supporting this * seldom-used feature, but something is attracting me to it.  In the future, * it may be possible to abuse this to send mixed-media messages to other * open source clients (like encryption or something) -- see faimtest for * examples of how to do this. * * I would definitely recommend avoiding this feature unless you really * know what you are doing, and/or you have something neat to do with it. * */int aim_mpmsg_init(OscarData *od, aim_mpmsg_t *mpm){	memset(mpm, 0, sizeof(aim_mpmsg_t));	return 0;}static int mpmsg_addsection(OscarData *od, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, gchar *data, guint16 datalen){	aim_mpmsg_section_t *sec;	sec = g_malloc(sizeof(aim_mpmsg_section_t));	sec->charset = charset;	sec->charsubset = charsubset;	sec->data = data;	sec->datalen = datalen;	sec->next = NULL;	if (!mpm->parts)		mpm->parts = sec;	else {		aim_mpmsg_section_t *cur;		for (cur = mpm->parts; cur->next; cur = cur->next)			;		cur->next = sec;	}	mpm->numparts++;	return 0;}int aim_mpmsg_addraw(OscarData *od, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const gchar *data, guint16 datalen){	gchar *dup;	dup = g_malloc(datalen);	memcpy(dup, data, datalen);	if (mpmsg_addsection(od, mpm, charset, charsubset, dup, datalen) == -1) {		g_free(dup);		return -1;	}	return 0;}/* XXX - should provide a way of saying ISO-8859-1 specifically */int aim_mpmsg_addascii(OscarData *od, aim_mpmsg_t *mpm, const char *ascii){	gchar *dup;	if (!(dup = g_strdup(ascii)))		return -1;	if (mpmsg_addsection(od, mpm, 0x0000, 0x0000, dup, strlen(ascii)) == -1) {		g_free(dup);		return -1;	}	return 0;}int aim_mpmsg_addunicode(OscarData *od, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen){	gchar *buf;	ByteStream bs;	int i;	buf = g_malloc(unicodelen * 2);	byte_stream_init(&bs, (guchar *)buf, unicodelen * 2);	/* We assume unicode is in /host/ byte order -- convert to network */	for (i = 0; i < unicodelen; i++)		byte_stream_put16(&bs, unicode[i]);	if (mpmsg_addsection(od, mpm, 0x0002, 0x0000, buf, byte_stream_curpos(&bs)) == -1) {		g_free(buf);		return -1;	}	return 0;}void aim_mpmsg_free(OscarData *od, aim_mpmsg_t *mpm){	aim_mpmsg_section_t *cur;	for (cur = mpm->parts; cur; ) {		aim_mpmsg_section_t *tmp;		tmp = cur->next;		g_free(cur->data);		g_free(cur);		cur = tmp;	}	mpm->numparts = 0;	mpm->parts = NULL;	return;}/* * Start by building the multipart structures, then pick the first * human-readable section and stuff it into args->msg so no one gets * suspicious. */static int incomingim_ch1_parsemsgs(OscarData *od, aim_userinfo_t *userinfo, guint8 *data, int len, struct aim_incomingim_ch1_args *args){	/* Should this be ASCII -> UNICODE -> Custom */	static const guint16 charsetpri[] = {		AIM_CHARSET_ASCII, /* ASCII first */		AIM_CHARSET_CUSTOM, /* then ISO-8859-1 */		AIM_CHARSET_UNICODE, /* UNICODE as last resort */	};	static const int charsetpricount = 3;	int i;	ByteStream mbs;	aim_mpmsg_section_t *sec;	byte_stream_init(&mbs, data, len);	while (byte_stream_empty(&mbs)) {		guint16 msglen, flag1, flag2;		gchar *msgbuf;		byte_stream_get8(&mbs); /* 01 */		byte_stream_get8(&mbs); /* 01 */		/* Message string length, including character set info. */		msglen = byte_stream_get16(&mbs);		if (msglen > byte_stream_empty(&mbs))		{			purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s.  They are probably trying to do something malicious.", userinfo->sn);			break;		}		/* Character set info */		flag1 = byte_stream_get16(&mbs);		flag2 = byte_stream_get16(&mbs);		/* Message. */		msglen -= 4;		/*		 * For now, we don't care what the encoding is.  Just copy		 * it into a multipart struct and deal with it later. However,		 * always pad the ending with a NULL.  This makes it easier		 * to treat ASCII sections as strings.  It won't matter for		 * UNICODE or binary data, as you should never read past		 * the specified data length, which will not include the pad.		 *		 * XXX - There's an API bug here.  For sending, the UNICODE is		 * given in host byte order (aim_mpmsg_addunicode), but here		 * the received messages are given in network byte order.		 *		 */		msgbuf = (gchar *)byte_stream_getraw(&mbs, msglen);		mpmsg_addsection(od, &args->mpmsg, flag1, flag2, msgbuf, msglen);	} /* while */	args->icbmflags |= AIM_IMFLAGS_MULTIPART; /* always set */	/*	 * Clients that support multiparts should never use args->msg, as it	 * will point to an arbitrary section.	 *	 * Here, we attempt to provide clients that do not support multipart	 * messages with something to look at -- hopefully a human-readable	 * string.  But, failing that, a UNICODE message, or nothing at all.	 *	 * Which means that even if args->msg is NULL, it does not mean the	 * message was blank.	 *	 */	for (i = 0; i < charsetpricount; i++) {		for (sec = args->mpmsg.parts; sec; sec = sec->next) {			if (sec->charset != charsetpri[i])				continue;			/* Great. We found one.  Fill it in. */			args->charset = sec->charset;			args->charsubset = sec->charsubset;			/* Set up the simple flags */			switch (args->charsubset)			{				case 0x0000:					/* standard subencoding? */					break;				case 0x000b:					args->icbmflags |= AIM_IMFLAGS_SUBENC_MACINTOSH;					break;				case 0xffff:					/* no subencoding */					break;				default:					break;			}			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(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, ByteStream *bs, guint8 *cookie){	guint16 type, length;	aim_rxcallback_t userfunc;	int ret = 0;	struct aim_incomingim_ch1_args args;	unsigned int endpos;	memset(&args, 0, sizeof(args));	aim_mpmsg_init(od, &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 (byte_stream_empty(bs) >= 4)	{		type = byte_stream_get16(bs);		length = byte_stream_get16(bs);		if (length > byte_stream_empty(bs))		{			purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s.  They are probably trying to do something malicious.\n", userinfo->sn);			break;		}		endpos = byte_stream_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			 *			 */			byte_stream_get8(bs); /* 05 */			byte_stream_get8(bs); /* 01 */			args.featureslen = byte_stream_get16(bs);			if (args.featureslen > byte_stream_empty(bs))			{				purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s.  They are probably trying to do something malicious.\n", userinfo->sn);				break;			}			if (args.featureslen == 0)			{				args.features = NULL;			}			else			{				args.features = byte_stream_getraw(bs, args.featureslen);				args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES;			}			/*			 * The rest of the TLV contains one or more message			 * blocks...			 */			incomingim_ch1_parsemsgs(od, userinfo, 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 = byte_stream_get32(bs);			byte_stream_get16(bs); /* 0x0001 */			args.iconsum = byte_stream_get16(bs);			args.iconstamp = byte_stream_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) {			if (length > byte_stream_empty(bs))			{				purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s.  They are probably trying to do something malicious.\n", userinfo->sn);				break;			}			g_free(args.extdata);			args.extdatalen = length;			if (args.extdatalen == 0)				args.extdata = NULL;			else				args.extdata = byte_stream_getraw(bs, args.extdatalen);		} else {			purple_debug_misc("oscar", "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.		 *		 */		byte_stream_setpos(bs, endpos);	}	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))		ret = userfunc(od, conn, frame, channel, userinfo, &args);	aim_mpmsg_free(od, &args.mpmsg);	g_free(args.features);	g_free(args.extdata);	return ret;}static voidincomingim_ch2_buddylist(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *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 (byte_stream_empty(servdata))	{		guint16 gnlen, numb;		int i;		char *gn;		gnlen = byte_stream_get16(servdata);		gn = byte_stream_getstr(servdata, gnlen);		numb = byte_stream_get16(servdata);		for (i = 0; i < numb; i++) {			guint16 bnlen;			char *bn;			bnlen = byte_stream_get16(servdata);			bn = byte_stream_getstr(servdata, bnlen);			purple_debug_misc("oscar", "got a buddy list from %s: group %s, buddy %s\n", userinfo->sn, gn, bn);			g_free(bn);		}		g_free(gn);	}	return;}static voidincomingim_ch2_buddyicon_free(OscarData *od, IcbmArgsCh2 *args){	g_free(args->info.icon.icon);

⌨️ 快捷键说明

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