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

📄 family_locate.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Purple's oscar protocol plugin * This file is the legal property of its developers. * Please see the AUTHORS file distributed alongside this file. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//* * Family 0x0002 - Locate. * * The functions here are responsible for requesting and parsing information- * gathering SNACs.  Or something like that.  This family contains the SNACs * for getting and setting info, away messages, directory profile thingy, etc. */#include "oscar.h"#ifdef _WIN32#include "win32dep.h"#endif/* Define to log unknown TLVs *//* #define LOG_UNKNOWN_TLV *//* * Capability blocks. * * These are CLSIDs. They should actually be of the form: * * {0x0946134b, 0x4c7f, 0x11d1, *  {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}}, * * But, eh. */static const struct {	guint32 flag;	guint8 data[16];} aim_caps[] = {	/*	 * These are in ascending numerical order.	 */	/*	 * Perhaps better called OSCAR_CAPABILITY_SHORTCAPS	 */	{OSCAR_CAPABILITY_ICHAT,	 {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_SECUREIM,	 {0x09, 0x46, 0x00, 0x01, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_VIDEO,	 {0x09, 0x46, 0x01, 0x00, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	/* "Live Video" support in Windows AIM 5.5.3501 and newer */	{OSCAR_CAPABILITY_LIVEVIDEO,	 {0x09, 0x46, 0x01, 0x01, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	/* "Camera" support in Windows AIM 5.5.3501 and newer */	{OSCAR_CAPABILITY_CAMERA,	 {0x09, 0x46, 0x01, 0x02, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	/* In Windows AIM 5.5.3501 and newer */	{OSCAR_CAPABILITY_GENERICUNKNOWN,	 {0x09, 0x46, 0x01, 0x03, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	/* In iChatAV (version numbers...?) */	{OSCAR_CAPABILITY_ICHATAV,	 {0x09, 0x46, 0x01, 0x05, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x45, 0x53, 0x54, 0x00}},	/*	 * Not really sure about this one.  In an email from	 * 26 Sep 2003, Matthew Sachs suggested that, "this	 * is probably the capability for the SMS features."	 */	{OSCAR_CAPABILITY_SMS,	 {0x09, 0x46, 0x01, 0xff, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_HIPTOP,	 {0x09, 0x46, 0x13, 0x23, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_TALK,	 {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_SENDFILE,	 {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_ICQ_DIRECT,	 {0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_DIRECTIM,	 {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_BUDDYICON,	 {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_ADDINS,	 {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_GETFILE,	 {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_ICQSERVERRELAY,	 {0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	/*	 * Indeed, there are two of these.  The former appears to be correct,	 * but in some versions of winaim, the second one is set.  Either they	 * forgot to fix endianness, or they made a typo. It really doesn't	 * matter which.	 */	{OSCAR_CAPABILITY_GAMES,	 {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_GAMES2,	 {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,	  0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_SENDBUDDYLIST,	 {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	/*	 * Setting this lets AIM users receive messages from ICQ users, and ICQ	 * users receive messages from AIM users.  It also lets ICQ users show	 * up in buddy lists for AIM users, and AIM users show up in buddy lists	 * for ICQ users.  And ICQ privacy/invisibility acts like AIM privacy,	 * in that if you add a user to your deny list, you will not be able to	 * see them as online (previous you could still see them, but they	 * couldn't see you.	 */	{OSCAR_CAPABILITY_INTEROPERATE,	 {0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_UNICODE,	 {0x09, 0x46, 0x13, 0x4e, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_GENERICUNKNOWN,	 {0x09, 0x46, 0xf0, 0x03, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_GENERICUNKNOWN,	 {0x09, 0x46, 0xf0, 0x04, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_GENERICUNKNOWN,	 {0x09, 0x46, 0xf0, 0x05, 0x4c, 0x7f, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	{OSCAR_CAPABILITY_UNICODEOLD,	 {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8,	  0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}},	/*	{OSCAR_CAPABILITY_ICQ2GO,	 {0x56, 0x3f, 0xc8, 0x09, 0x0b, 0x6f, 0x41, 0xbd,	  0x9f, 0x79, 0x42, 0x26, 0x09, 0xdf, 0xa2, 0xf3}},	*/	/*	 * Chat is oddball.	 */	{OSCAR_CAPABILITY_CHAT,	 {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},	/* This is added by the servers and it only shows up for ourselves... */	{OSCAR_CAPABILITY_GENERICUNKNOWN,	 {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34,	  0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x09}},	{OSCAR_CAPABILITY_ICQRTF,	 {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34,	  0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92}},	{OSCAR_CAPABILITY_APINFO,	 {0xaa, 0x4a, 0x32, 0xb5, 0xf8, 0x84, 0x48, 0xc6,	  0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}},	{OSCAR_CAPABILITY_TRILLIANCRYPT,	 {0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb,	  0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00}},	{OSCAR_CAPABILITY_EMPTY,	 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},	{OSCAR_CAPABILITY_LAST,	 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},};/* * Add the userinfo to our linked list.  If we already have userinfo * for this buddy, then just overwrite parts of the old data. * * @param userinfo Contains the new information for the buddy. */static voidaim_locate_adduserinfo(OscarData *od, aim_userinfo_t *userinfo){	aim_userinfo_t *cur;	FlapConnection *conn;	aim_rxcallback_t userfunc;	cur = aim_locate_finduserinfo(od, userinfo->sn);	if (cur == NULL) {		cur = (aim_userinfo_t *)g_new0(aim_userinfo_t, 1);		cur->sn = g_strdup(userinfo->sn);		cur->next = od->locate.userinfo;		od->locate.userinfo = cur;	}	cur->warnlevel = userinfo->warnlevel;	cur->idletime = userinfo->idletime;	if (userinfo->flags != 0)		cur->flags = userinfo->flags;	if (userinfo->createtime != 0)		cur->createtime = userinfo->createtime;	if (userinfo->membersince != 0)		cur->membersince = userinfo->membersince;	if (userinfo->onlinesince != 0)		cur->onlinesince = userinfo->onlinesince;	if (userinfo->sessionlen != 0)		cur->sessionlen = userinfo->sessionlen;	if (userinfo->capabilities != 0)		cur->capabilities = userinfo->capabilities;	cur->present |= userinfo->present;	if (userinfo->iconcsumlen > 0) {		g_free(cur->iconcsum);		cur->iconcsum = (guint8 *)g_malloc(userinfo->iconcsumlen);		memcpy(cur->iconcsum, userinfo->iconcsum, userinfo->iconcsumlen);		cur->iconcsumlen = userinfo->iconcsumlen;	}	if (userinfo->info != NULL) {		g_free(cur->info);		g_free(cur->info_encoding);		if (userinfo->info_len > 0) {			cur->info = (char *)g_malloc(userinfo->info_len);			memcpy(cur->info, userinfo->info, userinfo->info_len);		} else			cur->info = NULL;		cur->info_encoding = g_strdup(userinfo->info_encoding);		cur->info_len = userinfo->info_len;	}	if (userinfo->status != NULL) {		g_free(cur->status);		g_free(cur->status_encoding);		if (userinfo->status_len > 0) {			cur->status = (char *)g_malloc(userinfo->status_len);			memcpy(cur->status, userinfo->status, userinfo->status_len);		} else			cur->status = NULL;		if (userinfo->status_encoding != NULL)			cur->status_encoding = g_strdup(userinfo->status_encoding);		else			cur->status_encoding = NULL;		cur->status_len = userinfo->status_len;	}	if (userinfo->itmsurl != NULL) {		g_free(cur->itmsurl);		g_free(cur->itmsurl_encoding);		if (userinfo->itmsurl_len > 0) {			cur->itmsurl = (char *)g_malloc(userinfo->itmsurl_len);			memcpy(cur->itmsurl, userinfo->itmsurl, userinfo->itmsurl_len);		} else			cur->itmsurl = NULL;		if (userinfo->itmsurl_encoding != NULL)			cur->itmsurl_encoding = g_strdup(userinfo->itmsurl_encoding);		else			cur->itmsurl_encoding = NULL;		cur->itmsurl_len = userinfo->itmsurl_len;	}	if (userinfo->away != NULL) {		g_free(cur->away);		g_free(cur->away_encoding);		if (userinfo->away_len > 0) {			cur->away = (char *)g_malloc(userinfo->away_len);			memcpy(cur->away, userinfo->away, userinfo->away_len);		} else			cur->away = NULL;		cur->away_encoding = g_strdup(userinfo->away_encoding);		cur->away_len = userinfo->away_len;	} else if (!(userinfo->flags & AIM_FLAG_AWAY)) {		/*		 * We don't have an away message specified in this user_info block.		 * If the user is not away, clear any cached away message now.		 */		if (cur->away) {			g_free(cur->away);			cur->away = NULL;		}		if (cur->away_encoding) {			g_free(cur->away_encoding);			cur->away_encoding = NULL;		}		cur->away_len = 0;	}	/*	 * This callback can be used by a client if they want to know whenever	 * info for a buddy is updated.  For example, if a client shows away	 * messages in its buddy list, then it would need to know if a user's	 * away message changes.	 */	conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE);	if ((userfunc = aim_callhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK)))		userfunc(od, conn, NULL, cur);}voidaim_locate_dorequest(OscarData *od){	struct userinfo_node *cur = od->locate.torequest;	if (od->locate.waiting_for_response == TRUE)		return;	od->locate.waiting_for_response = TRUE;	aim_locate_getinfoshort(od, cur->sn, 0x00000003);	/* Move this node to the "requested" queue */	od->locate.torequest = cur->next;	cur->next = od->locate.requested;	od->locate.requested = cur;}static gbooleanpurple_reqinfo_timeout_cb(void *data){	OscarData *od;	od = data;	if (od->locate.torequest == NULL)	{		od->getinfotimer = 0;		return FALSE;	}	aim_locate_dorequest(od);	return TRUE;}/** * Remove this screen name from our queue.  If this info was requested * by our info request queue, then pop the next element off of the queue. * * @param od The aim session. * @param sn Screen name of the info we just received. * @return True if the request was explicit (client requested the info), *         false if the request was implicit (libfaim request the info). */static intaim_locate_gotuserinfo(OscarData *od, FlapConnection *conn, const char *sn){	struct userinfo_node *cur, *del;	int was_explicit = TRUE;	while ((od->locate.requested != NULL) && (aim_sncmp(sn, od->locate.requested->sn) == 0)) {		del = od->locate.requested;		od->locate.requested = del->next;		was_explicit = FALSE;		g_free(del->sn);		g_free(del);	}	cur = od->locate.requested;	while ((cur != NULL) && (cur->next != NULL)) {		if (aim_sncmp(sn, cur->next->sn) == 0) {			del = cur->next;			cur->next = del->next;			was_explicit = FALSE;			g_free(del->sn);			g_free(del);		} else			cur = cur->next;	}	if (!was_explicit) {		od->locate.waiting_for_response = FALSE;		/*		 * Wait a little while then call aim_locate_dorequest(od).		 * This keeps us from hitting the rate limit due to		 * requesting away messages and info too quickly.		 */		if (od->getinfotimer == 0)			od->getinfotimer = purple_timeout_add(500,					purple_reqinfo_timeout_cb, od);	}	return was_explicit;}voidaim_locate_requestuserinfo(OscarData *od, const char *sn){	struct userinfo_node *cur;	/* Make sure we aren't already requesting info for this buddy */	cur = od->locate.torequest;	while (cur != NULL) {		if (aim_sncmp(sn, cur->sn) == 0)			return;		cur = cur->next;	}	/* Add a new node to our request queue */	cur = (struct userinfo_node *)g_malloc(sizeof(struct userinfo_node));	cur->sn = g_strdup(sn);	cur->next = od->locate.torequest;	od->locate.torequest = cur;	/* Actually request some info up in this piece */	aim_locate_dorequest(od);}aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *sn) {	aim_userinfo_t *cur = NULL;	if (sn == NULL)		return NULL;	cur = od->locate.userinfo;	while (cur != NULL) {		if (aim_sncmp(cur->sn, sn) == 0)			return cur;		cur = cur->next;	}	return NULL;}guint32aim_locate_getcaps(OscarData *od, ByteStream *bs, int len){	guint32 flags = 0;	int offset;	for (offset = 0; byte_stream_empty(bs) && (offset < len); offset += 0x10) {		guint8 *cap;		int i, identified;		cap = byte_stream_getraw(bs, 0x10);		for (i = 0, identified = 0; !(aim_caps[i].flag & OSCAR_CAPABILITY_LAST); i++) {			if (memcmp(&aim_caps[i].data, cap, 0x10) == 0) {				flags |= aim_caps[i].flag;				identified++;				break; /* should only match once... */

⌨️ 快捷键说明

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