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

📄 ssi.c

📁 oscar message protocol stack
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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. * */#define FAIM_INTERNAL#include <aim.h>/** * 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 struct aim_ssi_item *aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name){	int newlen;	struct aim_ssi_item *cur, *group;	if (!list)		return NULL;	/* Find the group */	if (!(group = aim_ssi_itemlist_finditem(list, name, NULL, AIM_SSI_TYPE_GROUP)))		return NULL;	/* 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) {		fu8_t *newdata;		if (!(newdata = (fu8_t *)malloc((newlen)*sizeof(fu8_t))))			return NULL;		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);		free(newdata);	}	return group;}/** * 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, fu16_t gid, fu16_t bid, fu16_t type, aim_tlvlist_t *data){	int i;	struct aim_ssi_item *cur, *new;	if (!list)		return NULL;	if (!(new = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item))))		return NULL;	/* Set the name */	if (name) {		new->name = (char *)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;				for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next)					if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid))						i=1;			} while (i);		}	} else {		if (new->bid == 0xFFFF) {			do {				new->bid += 0x0001;				for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next)					if ((cur->bid == new->bid) && (cur->gid == new->gid))						i=1;			} while (i);		}	}	/* 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 || !(*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 */	free(del->name);	aim_tlvlist_free(&del->data);	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;}faim_export int 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 1;	return 0;}/** * 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; */faim_export struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, fu16_t gid, fu16_t 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. */faim_export struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, fu16_t 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; */faim_export 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; */faim_export 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. */faim_export 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 aim.h * * @param list A pointer to the current list of items. * @return Return the current visibility mask. */faim_export fu32_t 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! */faim_export 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) {			char *alias = (char *)malloc((tlv->length+1)*sizeof(char));			strncpy(alias, tlv->value, tlv->length);			alias[tlv->length] = 0;			return alias;		}	}	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! */faim_export 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) {			char *alias = (char *)malloc((tlv->length+1)*sizeof(char));			strncpy(alias, tlv->value, tlv->length);			alias[tlv->length] = 0;			return alias;		}	}	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 A pointer to a NULL terminated string that is the buddies  *         alias, or NULL if the buddy has no alias.  You should free *         this returned value! */faim_export int 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 1;	}	return 0;}/** * If there are changes, then create temporary items and  * call addmoddel. * * @param sess The oscar session. * @return Return 0 if no errors, otherwise return the error number. */static int aim_ssi_sync(aim_session_t *sess){	struct aim_ssi_item *cur1, *cur2;	struct aim_ssi_tmp *cur, *new;	if (!sess)		return -EINVAL;	/* If we're waiting for an ack, we shouldn't do anything else */	if (sess->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 	 * additions, then modifications.  Also, both the official and the local 	 * list should be in ascending numerical order for the group ID#s and the 	 * buddy ID#s, which makes things more efficient.  I think.	 */	/* Additions */	if (!sess->ssi.pending) {		for (cur1=sess->ssi.local; cur1; cur1=cur1->next) {			if (!aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid)) {				new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));				new->action = AIM_CB_SSI_ADD;				new->ack = 0xffff;				new->name = NULL;				new->item = cur1;				new->next = NULL;				if (sess->ssi.pending) {					for (cur=sess->ssi.pending; cur->next; cur=cur->next);					cur->next = new;

⌨️ 快捷键说明

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