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

📄 ssi.c

📁 oscar message protocol stack
💻 C
📖 第 1 页 / 共 4 页
字号:
	free(group->name);	group->name = (char *)malloc((strlen(newgn)+1)*sizeof(char));	strcpy(group->name, newgn);	/* Sync our local list with the server list */	aim_ssi_sync(sess);	return 0;}/** * Stores your permit/deny setting on the server, and starts using it. * * @param sess The oscar session. * @param permdeny Your permit/deny setting.  Can be one of the following: *        1 - Allow all users *        2 - Block all users *        3 - Allow only the users below *        4 - Block only the users below *        5 - Allow only users on my buddy list * @param vismask A bitmask of the class of users to whom you want to be  *        visible.  See the AIM_FLAG_BLEH #defines in aim.h * @return Return 0 if no errors, otherwise return the error number. */faim_export int aim_ssi_setpermdeny(aim_session_t *sess, fu8_t permdeny, fu32_t vismask){	struct aim_ssi_item *tmp;	if (!sess)		return -EINVAL;	/* Find the PDINFO item, or add it if it does not exist */	if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO)))		tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL);	/* Need to add the 0x00ca TLV to the TLV chain */	aim_tlvlist_replace_8(&tmp->data, 0x00ca, permdeny);	/* Need to add the 0x00cb TLV to the TLV chain */	aim_tlvlist_replace_32(&tmp->data, 0x00cb, vismask);	/* Sync our local list with the server list */	aim_ssi_sync(sess);	return 0;}/** * Set buddy icon information * * @param sess The oscar session. * @param iconcsum The MD5 checksum of the icon you are using. * @param iconcsumlen Length of the MD5 checksum given above.  Should be 0x10 bytes. * @return Return 0 if no errors, otherwise return the error number. */faim_export int aim_ssi_seticon(aim_session_t *sess, fu8_t *iconsum, fu16_t iconsumlen){	struct aim_ssi_item *tmp;	fu8_t *csumdata;	if (!sess || !iconsum || !iconsumlen)		return -EINVAL;	/* Find the ICONINFO item, or add it if it does not exist */	if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {		tmp = aim_ssi_itemlist_add(&sess->ssi.local, "1", 0x0000, 0x51F4, AIM_SSI_TYPE_ICONINFO, NULL);	}	/* Need to add the 0x00d5 TLV to the TLV chain */	if (!(csumdata = (fu8_t *)malloc((iconsumlen+2)*sizeof(fu8_t))))		return -ENOMEM;	csumdata[0] = 0x00;	csumdata[1] = 0x10;	memcpy(&csumdata[2], iconsum, iconsumlen);	aim_tlvlist_replace_raw(&tmp->data, 0x00d5, (iconsumlen+2) * sizeof(fu8_t), csumdata);	free(csumdata);	/* Need to add the 0x0131 TLV to the TLV chain, used to cache the icon */	aim_tlvlist_replace_noval(&tmp->data, 0x0131);	/* Sync our local list with the server list */	aim_ssi_sync(sess);	return 0;}/** * Remove a reference to a server stored buddy icon.  This will make your  * icon stop showing up to other people. * * @param sess The oscar session. * @return Return 0 if no errors, otherwise return the error number. */faim_export int aim_ssi_delicon(aim_session_t *sess){	struct aim_ssi_item *tmp;	if (!sess)		return -EINVAL;	/* Find the ICONINFO item and delete it if it exists*/	if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO)))		aim_ssi_itemlist_del(&sess->ssi.local, tmp);	/* Sync our local list with the server list */	aim_ssi_sync(sess);	return 0;}/** * Stores your setting for various SSI settings.  Whether you  * should show up as idle or not, etc. * * @param sess The oscar session. * @param presence I think it's a bitmask, but I only know what one of the bits is: *        0x00000002 - Hide wireless? *        0x00000400 - Allow others to see your idle time * @return Return 0 if no errors, otherwise return the error number. */faim_export int aim_ssi_setpresence(aim_session_t *sess, fu32_t presence) {	struct aim_ssi_item *tmp;	if (!sess)		return -EINVAL;	/* Find the PRESENCEPREFS item, or add it if it does not exist */	if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS)))		tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL);	/* Need to add the x00c9 TLV to the TLV chain */	aim_tlvlist_replace_32(&tmp->data, 0x00c9, presence);	/* Sync our local list with the server list */	aim_ssi_sync(sess);	return 0;}/* * Subtype 0x0002 - Request SSI Rights. */faim_export int aim_ssi_reqrights(aim_session_t *sess){	aim_conn_t *conn;	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))		return -EINVAL;	return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQRIGHTS);}/* * Subtype 0x0003 - SSI Rights Information. */static int parserights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	int ret = 0, i;	aim_rxcallback_t userfunc;	aim_tlvlist_t *tlvlist;	aim_tlv_t *tlv;	aim_bstream_t bstream;	fu16_t *maxitems;	/* This SNAC is made up of a bunch of TLVs */	tlvlist = aim_tlvlist_read(bs);	/* TLV 0x0004 contains the maximum number of each item */	if (!(tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {		aim_tlvlist_free(&tlvlist);		return 0;	}	aim_bstream_init(&bstream, tlv->value, tlv->length);	if (!(maxitems = (fu16_t *)malloc((tlv->length/2)*sizeof(fu16_t)))) {		aim_tlvlist_free(&tlvlist);		return 0;	}	for (i=0; i<(tlv->length/2); i++)		maxitems[i] = aimbs_get16(&bstream);	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))		ret = userfunc(sess, rx, tlv->length/2, maxitems);	aim_tlvlist_free(&tlvlist);	free(maxitems);	return ret;}/* * Subtype 0x0004 - Request SSI Data when you don't have a timestamp and  * revision number. *  */faim_export int aim_ssi_reqdata(aim_session_t *sess){	aim_conn_t *conn;	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))		return -EINVAL;	/* Free any current data, just in case */	aim_ssi_freelist(sess);	return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQDATA);}/* * Subtype 0x0005 - Request SSI Data when you have a timestamp and revision  * number. * * The data will only be sent if it is newer than the posted local * timestamp and revision. *  * Note that the client should never increment the revision, only the server. *  */faim_export int aim_ssi_reqifchanged(aim_session_t *sess, time_t timestamp, fu16_t numitems){	aim_conn_t *conn;	aim_frame_t *fr;	aim_snacid_t snacid;	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))		return -EINVAL;	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2)))		return -ENOMEM;	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, NULL, 0);	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, snacid);	aimbs_put32(&fr->data, timestamp);	aimbs_put16(&fr->data, numitems);	aim_tx_enqueue(sess, fr);	/* Free any current data, just in case */	aim_ssi_freelist(sess);	return 0;}/* * Subtype 0x0006 - SSI Data. */static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	int ret = 0;	aim_rxcallback_t userfunc;	fu8_t fmtver; /* guess */	fu16_t namelen, gid, bid, type;	char *name;	aim_tlvlist_t *data;	fmtver = aimbs_get8(bs); /* Version of ssi data.  Should be 0x00 */	sess->ssi.numitems += aimbs_get16(bs); /* # of items in this SSI SNAC */	/* Read in the list */	while (aim_bstream_empty(bs) > 4) { /* last four bytes are timestamp */		if ((namelen = aimbs_get16(bs)))			name = aimbs_getstr(bs, namelen);		else			name = NULL;		gid = aimbs_get16(bs);		bid = aimbs_get16(bs);		type = aimbs_get16(bs);		data = aim_tlvlist_readlen(bs, aimbs_get16(bs));		aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);		free(name);		aim_tlvlist_free(&data);	}	/* Read in the timestamp */	sess->ssi.timestamp = aimbs_get32(bs);	if (!(snac->flags & 0x0001)) {		/* Make a copy of the list */		struct aim_ssi_item *cur;		for (cur=sess->ssi.official; cur; cur=cur->next)			aim_ssi_itemlist_add(&sess->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);		sess->ssi.received_data = 1;		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))			ret = userfunc(sess, rx, fmtver, sess->ssi.numitems, sess->ssi.official, sess->ssi.timestamp);	}	return ret;}/* * Subtype 0x0007 - SSI Activate Data. * * Should be sent after receiving 13/6 or 13/f to tell the server you * are ready to begin using the list.  It will promptly give you the * presence information for everyone in your list and put your permit/deny * settings into effect. *  */faim_export int aim_ssi_enable(aim_session_t *sess){	aim_conn_t *conn;	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))		return -EINVAL;	return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, 0x0007);}/* * Subtype 0x0008/0x0009/0x000a - SSI Add/Mod/Del Item(s). * * Sends the SNAC to add, modify, or delete an item from the server-stored * information.  These 3 SNACs all have an identical structure.  The only * difference is the subtype that is set for the SNAC. *  */faim_export int aim_ssi_addmoddel(aim_session_t *sess){	aim_conn_t *conn;	aim_frame_t *fr;	aim_snacid_t snacid;	int snaclen;	struct aim_ssi_tmp *cur;	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sess->ssi.pending || !sess->ssi.pending->item)		return -EINVAL;	/* Calculate total SNAC size */	snaclen = 10; /* For family, subtype, flags, and SNAC ID */	for (cur=sess->ssi.pending; cur; cur=cur->next) {		snaclen += 10; /* For length, GID, BID, type, and length */		if (cur->item->name)			snaclen += strlen(cur->item->name);		if (cur->item->data)			snaclen += aim_tlvlist_size(&cur->item->data);	}	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen)))		return -ENOMEM;	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, NULL, 0);	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, snacid);	for (cur=sess->ssi.pending; cur; cur=cur->next) {		aimbs_put16(&fr->data, cur->item->name ? strlen(cur->item->name) : 0);		if (cur->item->name)			aimbs_putraw(&fr->data, cur->item->name, strlen(cur->item->name));		aimbs_put16(&fr->data, cur->item->gid);		aimbs_put16(&fr->data, cur->item->bid);		aimbs_put16(&fr->data, cur->item->type);		aimbs_put16(&fr->data, cur->item->data ? aim_tlvlist_size(&cur->item->data) : 0);		if (cur->item->data)			aim_tlvlist_write(&fr->data, &cur->item->data);	}	aim_tx_enqueue(sess, fr);	return 0;}/* * Subtype 0x0008 - Incoming SSI add. * * Sent by the server, for example, when someone is added to  * your "Recent Buddies" group. */static int parseadd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	int ret = 0;	aim_rxcallback_t userfunc;	char *name;	fu16_t len, gid, bid, type;	aim_tlvlist_t *data;	while (aim_bstream_empty(bs)) {		if ((len = aimbs_get16(bs)))			name = aimbs_getstr(bs, len);		else			name = NULL;		gid = aimbs_get16(bs);		bid = aimbs_get16(bs);		type = aimbs_get16(bs);		if ((len = aimbs_get16(bs)))			data = aim_tlvlist_readlen(bs, len);		else			data = NULL;		aim_ssi_itemlist_add(&sess->ssi.local, name, gid, bid, type, data);		aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);		aim_tlvlist_free(&data);		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))			ret = userfunc(sess, rx, type, name);		free(name);	}	return ret;}/* * Subtype 0x0009 - Incoming SSI mod. * * XXX - It would probably be good for the client to actually do something when it gets this. */static int parsemod(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	int ret = 0;	aim_rxcallback_t userfunc;	char *name;	fu16_t len, gid, bid, type;	aim_tlvlist_t *data;	struct aim_ssi_item *item;	while (aim_bstream_empty(bs)) {		if ((len = aimbs_get16(bs)))			name = aimbs_getstr(bs, len);		else			name = NULL;		gid = aimbs_get16(bs);		bid = aimbs_get16(bs);		type = aimbs_get16(bs);		if ((len = aimbs_get16(bs)))			data = aim_tlvlist_readlen(bs, len);		else			data = NULL;		/* Replace the 2 local items with the given one */		if ((item = aim_ssi_itemlist_find(sess->ssi.local, gid, bid))) {			item->type = type;			free(item->name);			if (name) {				item->name = (char *)malloc((strlen(name)+1)*sizeof(char));				strcpy(item->name, name);			} else				item->name = NULL;			aim_tlvlist_free(&item->data);			item->data = aim_tlvlist_copy(data);		}		if ((item = aim_ssi_itemlist_find(sess->ssi.official, gid, bid))) {			item->type = type;			free(item->name);			if (name) {				item->name = (char *)malloc((strlen(name)+1)*sizeof(char));				strcpy(item->name, name);			} else				item->name = NULL;			aim_tlvlist_free(&item->data);			item->data = aim_tlvlist_copy(data);		}		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))			ret = userfunc(sess, rx);		free(name);		aim_tlvlist_free(&data);	}	return ret;}/* * Subtype 0x000a - Incoming SSI del. * * XXX - It would probably be good for the client to actually do something when it gets this. */static int parsedel(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	int ret = 0;	aim_rxcallback_t userfunc;	fu16_t gid, bid;	struct aim_ssi_item *del;	while (aim_bstream_empty(bs)) {		aim_bstream_advance(bs, aimbs_get16(bs));		gid = aimbs_get16(bs);		bid = aimbs_get16(bs);		aimbs_get16(bs);		aim_bstream_advance(bs, aimbs_get16(bs));		if ((del = aim_ssi_itemlist_find(sess->ssi.local, gid, bid)))			aim_ssi_itemlist_del(&sess->ssi.local, del);		if ((del = aim_ssi_itemlist_find(sess->ssi.official, gid, bid)))			aim_ssi_itemlist_del(&sess->ssi.official, del);		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))			ret = userfunc(sess, rx);	}

⌨️ 快捷键说明

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