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

📄 family_feedbag.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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 0x0013 - Server-Side/Stored Information. * * Relatively new facility that allows certain types of information, such as * a user's buddy list, permit/deny list, and permit/deny preferences, to be * stored on the server, so that they can be accessed from any client. * * We keep 2 copies of SSI data: * 1) An exact copy of what is stored on the AIM servers. * 2) A local copy that we make changes to, and then send diffs *    between this and the exact copy to keep them in sync. * * All the "aim_ssi_itemlist_bleh" functions near the top just modify the list * that is given to them (i.e. they don't send SNACs). * * The SNAC sending and receiving functions are lower down in the file, and * they're simpler.  They are in the order of the subtypes they deal with, * starting with the request rights function (subtype 0x0002), then parse * rights (subtype 0x0003), then--well, you get the idea. * * This is entirely too complicated. * You don't know the half of it. * */#include "oscar.h"static int aim_ssi_addmoddel(OscarData *od);/** * Locally rebuild the 0x00c8 TLV in the additional data of the given group. * * @param list A pointer to a pointer to the current list of items. * @param name A null terminated string containing the group name, or NULL *        if you want to modify the master group. * @return Return a pointer to the modified item. */static voidaim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name){	int newlen;	struct aim_ssi_item *cur, *group;	/* Find the group */	if (!(group = aim_ssi_itemlist_finditem(list, name, NULL, AIM_SSI_TYPE_GROUP)))		return;	/* Find the length for the new additional data */	newlen = 0;	if (group->gid == 0x0000) {		for (cur=list; cur; cur=cur->next)			if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))				newlen += 2;	} else {		for (cur=list; cur; cur=cur->next)			if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))				newlen += 2;	}	/* Build the new TLV list */	if (newlen > 0) {		guint8 *newdata;		newdata = (guint8 *)g_malloc((newlen)*sizeof(guint8));		newlen = 0;		if (group->gid == 0x0000) {			for (cur=list; cur; cur=cur->next)				if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))						newlen += aimutil_put16(newdata+newlen, cur->gid);		} else {			for (cur=list; cur; cur=cur->next)				if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))						newlen += aimutil_put16(newdata+newlen, cur->bid);		}		aim_tlvlist_replace_raw(&group->data, 0x00c8, newlen, newdata);		g_free(newdata);	}}/** * Locally add a new item to the given item list. * * @param list A pointer to a pointer to the current list of items. * @param name A null terminated string of the name of the new item, or NULL if the *        item should have no name. * @param gid The group ID# you want the new item to have, or 0xFFFF if we should pick something. * @param bid The buddy ID# you want the new item to have, or 0xFFFF if we should pick something. * @param type The type of the item, 0x0000 for a contact, 0x0001 for a group, etc. * @param data The additional data for the new item. * @return A pointer to the newly created item. */static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, const char *name, guint16 gid, guint16 bid, guint16 type, GSList *data){	gboolean exists;	struct aim_ssi_item *cur, *new;	new = (struct aim_ssi_item *)g_malloc(sizeof(struct aim_ssi_item));	/* Set the name */	if (name) {		new->name = (char *)g_malloc((strlen(name)+1)*sizeof(char));		strcpy(new->name, name);	} else		new->name = NULL;	/* Set the group ID# and buddy ID# */	new->gid = gid;	new->bid = bid;	if (type == AIM_SSI_TYPE_GROUP) {		if ((new->gid == 0xFFFF) && name) {			do {				new->gid += 0x0001;				exists = FALSE;				for (cur = *list; cur != NULL; cur = cur->next)					if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid)) {						exists = TRUE;						break;					}			} while (exists);		}	} else if (type == AIM_SSI_TYPE_ICONINFO) {		if (new->bid == 0xFFFF) {			do {				new->bid += 0x0001;				exists = FALSE;				for (cur = *list; cur != NULL; cur = cur->next)					if ((cur->bid >= new->bid) || (cur->gid >= new->bid)) {						exists = TRUE;						break;					}			} while (exists);		}	} else {		if (new->bid == 0xFFFF) {			do {				new->bid += 0x0001;				exists = FALSE;				for (cur = *list; cur != NULL; cur = cur->next)					if ((cur->bid == new->bid) && (cur->gid == new->gid)) {						exists = TRUE;						break;					}			} while (exists);		}	}	/* Set the type */	new->type = type;	/* Set the TLV list */	new->data = aim_tlvlist_copy(data);	/* Add the item to the list in the correct numerical position.  Fancy, eh? */	if (*list) {		if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) {			new->next = *list;			*list = new;		} else {			struct aim_ssi_item *prev;			for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next);			new->next = prev->next;			prev->next = new;		}	} else {		new->next = *list;		*list = new;	}	return new;}/** * Locally delete an item from the given item list. * * @param list A pointer to a pointer to the current list of items. * @param del A pointer to the item you want to remove from the list. * @return Return 0 if no errors, otherwise return the error number. */static int aim_ssi_itemlist_del(struct aim_ssi_item **list, struct aim_ssi_item *del){	if (!(*list) || !del)		return -EINVAL;	/* Remove the item from the list */	if (*list == del) {		*list = (*list)->next;	} else {		struct aim_ssi_item *cur;		for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next);		if (cur->next)			cur->next = del->next;	}	/* Free the removed item */	g_free(del->name);	aim_tlvlist_free(del->data);	g_free(del);	return 0;}/** * Compare two items to see if they have the same data. * * @param cur1 A pointer to a pointer to the first item. * @param cur2 A pointer to a pointer to the second item. * @return Return 0 if no differences, or a number if there are differences. */static int aim_ssi_itemlist_cmp(struct aim_ssi_item *cur1, struct aim_ssi_item *cur2){	if (!cur1 || !cur2)		return 1;	if (cur1->data && !cur2->data)		return 2;	if (!cur1->data && cur2->data)		return 3;	if ((cur1->data && cur2->data) && (aim_tlvlist_cmp(cur1->data, cur2->data)))		return 4;	if (cur1->name && !cur2->name)		return 5;	if (!cur1->name && cur2->name)		return 6;	if (cur1->name && cur2->name && aim_sncmp(cur1->name, cur2->name))		return 7;	if (cur1->gid != cur2->gid)		return 8;	if (cur1->bid != cur2->bid)		return 9;	if (cur1->type != cur2->type)		return 10;	return 0;}static gboolean aim_ssi_itemlist_valid(struct aim_ssi_item *list, struct aim_ssi_item *item){	struct aim_ssi_item *cur;	for (cur=list; cur; cur=cur->next)		if (cur == item)			return TRUE;	return FALSE;}/** * Locally find an item given a group ID# and a buddy ID#. * * @param list A pointer to the current list of items. * @param gid The group ID# of the desired item. * @param bid The buddy ID# of the desired item. * @return Return a pointer to the item if found, else return NULL; */struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid){	struct aim_ssi_item *cur;	for (cur=list; cur; cur=cur->next)		if ((cur->gid == gid) && (cur->bid == bid))			return cur;	return NULL;}/** * Locally find an item given a group name, screen name, and type.  If group name * and screen name are null, then just return the first item of the given type. * * @param list A pointer to the current list of items. * @param gn The group name of the desired item. * @param bn The buddy name of the desired item. * @param type The type of the desired item. * @return Return a pointer to the item if found, else return NULL. */struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, guint16 type){	struct aim_ssi_item *cur;	if (!list)		return NULL;	if (gn && sn) { /* For finding buddies in groups */		for (cur=list; cur; cur=cur->next)			if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {				struct aim_ssi_item *curg;				for (curg=list; curg; curg=curg->next)					if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(aim_sncmp(curg->name, gn)))						return cur;			}	} else if (gn) { /* For finding groups */		for (cur=list; cur; cur=cur->next) {			if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(aim_sncmp(cur->name, gn))) {				return cur;			}		}	} else if (sn) { /* For finding permits, denies, and ignores */		for (cur=list; cur; cur=cur->next) {			if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {				return cur;			}		}	/* For stuff without names--permit deny setting, visibility mask, etc. */	} else for (cur=list; cur; cur=cur->next) {		if ((cur->type == type) && (!cur->name))			return cur;	}	return NULL;}/** * Check if the given buddy exists in any group in the buddy list. * * @param list A pointer to the current list of items. * @param sn The group name of the desired item. * @return Return a pointer to the name of the item if found, else return NULL; */struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn){	struct aim_ssi_item *cur;	if (!list || !sn)		return NULL;	for (cur=list; cur; cur=cur->next)		if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->name) && (!aim_sncmp(cur->name, sn)))			return cur;	return NULL;}/** * Locally find the parent item of the given buddy name. * * @param list A pointer to the current list of items. * @param bn The buddy name of the desired item. * @return Return a pointer to the name of the item if found, else return NULL; */char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn){	struct aim_ssi_item *cur, *curg;	if (!list || !sn)		return NULL;	if (!(cur = aim_ssi_itemlist_exists(list, sn)))		return NULL;	if (!(curg = aim_ssi_itemlist_find(list, cur->gid, 0x0000)))		return NULL;	return curg->name;}/** * Locally find the permit/deny setting item, and return the setting. * * @param list A pointer to the current list of items. * @return Return the current SSI permit deny setting, or 0 if no setting was found. */int aim_ssi_getpermdeny(struct aim_ssi_item *list){	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO);	if (cur) {		aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00ca, 1);		if (tlv && tlv->value)			return aimutil_get8(tlv->value);	}	return 0;}/** * Locally find the presence flag item, and return the setting.  The returned setting is a * bitmask of the user flags that you are visible to.  See the AIM_FLAG_* #defines * in oscar.h * * @param list A pointer to the current list of items. * @return Return the current visibility mask. */guint32 aim_ssi_getpresence(struct aim_ssi_item *list){	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS);	if (cur) {		aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c9, 1);		if (tlv && tlv->length)			return aimutil_get32(tlv->value);	}	return 0xFFFFFFFF;}/** * Locally find the alias of the given buddy. * * @param list A pointer to the current list of items. * @param gn The group of the buddy. * @param sn The name of the buddy. * @return A pointer to a NULL terminated string that is the buddy's *         alias, or NULL if the buddy has no alias.  You should free *         this returned value! */char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn){	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);	if (cur) {		aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x0131, 1);		if (tlv && tlv->length)			return g_strndup((const gchar *)tlv->value, tlv->length);	}	return NULL;}/** * Locally find the comment of the given buddy. * * @param list A pointer to the current list of items. * @param gn The group of the buddy. * @param sn The name of the buddy. * @return A pointer to a NULL terminated string that is the buddy's *         comment, or NULL if the buddy has no comment.  You should free *         this returned value! */char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *sn){	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);	if (cur) {		aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x013c, 1);		if (tlv && tlv->length) {			return g_strndup((const gchar *)tlv->value, tlv->length);		}	}	return NULL;}/** * Locally find if you are waiting for authorization for a buddy. * * @param list A pointer to the current list of items. * @param gn The group of the buddy. * @param sn The name of the buddy. * @return 1 if you are waiting for authorization; 0 if you are not */gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn){	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);	if (cur) {		if (aim_tlv_gettlv(cur->data, 0x0066, 1))			return TRUE;	}	return FALSE;}/** * If there are changes, then create temporary items and * call addmoddel. * * @param od The oscar session. * @return Return 0 if no errors, otherwise return the error number. */static int aim_ssi_sync(OscarData *od){	struct aim_ssi_item *cur1, *cur2;	struct aim_ssi_tmp *cur, *new;	int n = 0;	/*	 * The variable "n" is used to limit the number of addmoddel's that	 * are performed in a single SNAC.  It will hopefully keep the size	 * of the SNAC below the maximum SNAC size.	 */	if (!od)		return -EINVAL;	/* If we're waiting for an ack, we shouldn't do anything else */	if (od->ssi.waiting_for_ack)		return 0;	/*	 * Compare the 2 lists and create an aim_ssi_tmp for each difference.	 * We should only send either additions, modifications, or deletions	 * before waiting for an acknowledgement.  So first do deletions, then

⌨️ 快捷键说明

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