示例#1
0
/*
 * Subtype 0x0004 - Set your client's capabilities.
 */
int
aim_locate_setcaps(OscarData *od, guint32 caps)
{
	FlapConnection *conn;
	ByteStream bs;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	aim_tlvlist_add_caps(&tlvlist, 0x0005, caps);

	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, NULL, 0);

	aim_tlvlist_write(&bs, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, snacid, &bs);

	byte_stream_destroy(&bs);

	return 0;
}
示例#2
0
/*
 * Subtype 0x0007
 *
 * Middle handler for 0017/0007 SNACs.  Contains the auth key prefixed
 * by only its length in a two byte word.
 *
 * Calls the client, which should then use the value to call aim_send_login.
 *
 */
static int
keyparse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
{
	int keylen, ret = 1;
	aim_rxcallback_t userfunc;
	char *keystr;
	GSList *tlvlist;
	gboolean truncate_pass;

	keylen = byte_stream_get16(bs);
	keystr = byte_stream_getstr(bs, keylen);
	tlvlist = aim_tlvlist_read(bs);

	/*
	 * If the truncate_pass TLV exists then we should truncate the
	 * user's password to 8 characters.  This flag is sent to us
	 * when logging in with an AOL user's username.
	 */
	truncate_pass = aim_tlv_gettlv(tlvlist, 0x0026, 1) != NULL;

	/* XXX - When GiantGrayPanda signed on AIM I got a thing asking me to register
	 * for the netscape network.  This SNAC had a type 0x0058 TLV with length 10.
	 * Data is 0x0007 0004 3e19 ae1e 0006 0004 0000 0005 */

	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
		ret = userfunc(od, conn, frame, keystr, (int)truncate_pass);

	g_free(keystr);
	aim_tlvlist_free(tlvlist);

	return ret;
}
示例#3
0
/* Subtype 0x0003 - BOS Rights. */
static int rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
{
	aim_rxcallback_t userfunc;
	GSList *tlvlist;
	guint16 maxpermits = 0, maxdenies = 0;
	int ret = 0;

	/*
	 * TLVs follow
	 */
	tlvlist = aim_tlvlist_read(bs);

	/*
	 * TLV type 0x0001: Maximum number of buddies on permit list.
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
		maxpermits = aim_tlv_get16(tlvlist, 0x0001, 1);

	/*
	 * TLV type 0x0002: Maximum number of buddies on deny list.
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
		maxdenies = aim_tlv_get16(tlvlist, 0x0002, 1);

	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
		ret = userfunc(od, conn, frame, maxpermits, maxdenies);

	aim_tlvlist_free(tlvlist);

	return ret;
}
示例#4
0
/*
 * Subtype 0x0004 - Set your client's capabilities.
 */
int
aim_locate_setcaps(OscarData *od, guint32 caps)
{
	FlapConnection *conn;
	FlapFrame *frame;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	aim_tlvlist_add_caps(&tlvlist, 0x0005, caps);

	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, 0x0002, 0x0004, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, 0x0002, 0x004, 0x0000, snacid);

	aim_tlvlist_write(&frame->data, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
示例#5
0
void
flap_connection_send_version_with_cookie_and_clientinfo(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy, ClientInfo *ci, gboolean allow_multiple_logins)
{
	FlapFrame *frame;
	GSList *tlvlist = NULL;

	frame = flap_frame_new(od, 0x01, 1152 + length);

	byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
	aim_tlvlist_add_raw(&tlvlist, 0x0006, length, chipsahoy);

	if (ci->clientstring != NULL)
		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
	else {
		gchar *clientstring = oscar_get_clientstring();
		aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
		g_free(clientstring);
	}
	aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
	aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
	aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
	aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
	aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03));

	aim_tlvlist_write(&frame->data, &tlvlist);

	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);
}
示例#6
0
static int negchan_middle(aim_session_t *sess, aim_frame_t *fr)
{
	aim_tlvlist_t *tlvlist;
	char *msg = NULL;
	fu16_t code = 0;
	aim_rxcallback_t userfunc;
	int ret = 1;

	if (aim_bstream_empty(&fr->data) == 0) {
		/* XXX should do something with this */
		return 1;
	}

	/* Used only by the older login protocol */
	/* XXX remove this special case? */
	if (fr->conn->type == AIM_CONN_TYPE_AUTH)
		return consumenonsnac(sess, fr, 0x0017, 0x0003);

	tlvlist = aim_tlvlist_read(&fr->data);

	if (aim_tlv_gettlv(tlvlist, 0x0009, 1))
		code = aim_tlv_get16(tlvlist, 0x0009, 1);

	if (aim_tlv_gettlv(tlvlist, 0x000b, 1))
		msg = aim_tlv_getstr(tlvlist, 0x000b, 1);

	if ((userfunc = aim_callhandler(sess, fr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
		ret = userfunc(sess, fr, code, msg);

	aim_tlvlist_free(&tlvlist);

	free(msg);

	return ret;
}
示例#7
0
/*
 * Subtype 0x0006
 *
 * In AIM 3.5 protocol, the first stage of login is to request login from the
 * Authorizer, passing it the username for verification.  If the name is
 * invalid, a 0017/0003 is spit back, with the standard error contents.  If
 * valid, a 0017/0007 comes back, which is the signal to send it the main
 * login command (0017/0002).
 *
 */
int
aim_request_login(OscarData *od, FlapConnection *conn, const char *sn)
{
	FlapFrame *frame;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!od || !conn || !sn)
		return -EINVAL;

#ifdef USE_XOR_FOR_ICQ
	if (aim_snvalid_icq(sn))
		return goddamnicq(od, conn, sn);
#endif

	frame = flap_frame_new(od, 0x02, 10+2+2+strlen(sn)+8);

	snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0006, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0006, 0x0000, snacid);

	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);

	/* Tell the server we support SecurID logins. */
	aim_tlvlist_add_noval(&tlvlist, 0x004b);

	/* Unknown.  Sent in recent WinAIM clients.*/
	aim_tlvlist_add_noval(&tlvlist, 0x005a);

	aim_tlvlist_write(&frame->data, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
/*
 * Subtype 0x0004 - Set your client's capabilities.
 */
int
aim_locate_setcaps(OscarData *od, guint64 caps)
{
	FlapConnection *conn;
	PurpleAccount *account = purple_connection_get_account(od->gc);
	PurplePresence *presence = purple_account_get_presence(account);
	PurpleStatus *status = purple_presence_get_status(presence, "mood");
	const char *mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
	ByteStream bs;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	aim_tlvlist_add_caps(&tlvlist, 0x0005, caps, mood);

	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, NULL, 0);

	aim_tlvlist_write(&bs, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0004, snacid, &bs);

	byte_stream_destroy(&bs);

	return 0;
}
示例#9
0
文件: tlv.c 项目: JasonGross/barnowl
/**
 * Read a TLV chain from a buffer.
 *
 * Reads and parses a series of TLV patterns from a data buffer; the
 * returned structure is manipulatable with the rest of the TLV
 * routines.  When done with a TLV chain, aim_tlvlist_free() should
 * be called to free the dynamic substructures.
 *
 * XXX There should be a flag setable here to have the tlvlist contain
 * bstream references, so that at least the ->value portion of each 
 * element doesn't need to be malloc/memcpy'd.  This could prove to be
 * just as effecient as the in-place TLV parsing used in a couple places
 * in libfaim.
 *
 * @param bs Input bstream
 * @param num The max number of TLVs that will be read, or -1 if unlimited.  
 *        There are a number of places where you want to read in a tlvchain, 
 *        but the chain is not at the end of the SNAC, and the chain is 
 *        preceeded by the number of TLVs.  So you can limit that with this.
 */
faim_internal aim_tlvlist_t *aim_tlvlist_readnum(aim_bstream_t *bs, fu16_t num)
{
	aim_tlvlist_t *list = NULL, *cur;

	while ((aim_bstream_empty(bs) > 0) && (num != 0)) {
		fu16_t type, length;

		type = aimbs_get16(bs);
		length = aimbs_get16(bs);

		if (length > aim_bstream_empty(bs)) {
			aim_tlvlist_free(&list);
			return NULL;
		}

		cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
		if (!cur) {
			aim_tlvlist_free(&list);
			return NULL;
		}

		memset(cur, 0, sizeof(aim_tlvlist_t));

		cur->tlv = createtlv(type, length, NULL);
		if (!cur->tlv) {
			free(cur);
			aim_tlvlist_free(&list);
			return NULL;
		}
		if (cur->tlv->length > 0) {
			cur->tlv->value = aimbs_getraw(bs, length);
			if (!cur->tlv->value) {
				freetlv(&cur->tlv);
				free(cur);
				aim_tlvlist_free(&list);
				return NULL;
			}
		}

		if (num > 0)
			num--;
		cur->next = list;
		list = cur;
	}

	return list;
}
示例#10
0
/* Subtype 0x0006 */
static int
userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
{
	int ret = 0;
	aim_rxcallback_t userfunc;
	aim_userinfo_t *userinfo, *userinfo2;
	GSList *tlvlist;
	aim_tlv_t *tlv = NULL;
	int was_explicit;

	userinfo = (aim_userinfo_t *)g_malloc(sizeof(aim_userinfo_t));
	aim_info_extract(od, bs, userinfo);
	tlvlist = aim_tlvlist_read(bs);

	/* Profile will be 1 and 2 */
	userinfo->info_encoding = aim_tlv_getstr(tlvlist, 0x0001, 1);
	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0002, 1))) {
		userinfo->info = (char *)g_malloc(tlv->length);
		memcpy(userinfo->info, tlv->value, tlv->length);
		userinfo->info_len = tlv->length;
	}

	/* Away message will be 3 and 4 */
	userinfo->away_encoding = aim_tlv_getstr(tlvlist, 0x0003, 1);
	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
		userinfo->away = (char *)g_malloc(tlv->length);
		memcpy(userinfo->away, tlv->value, tlv->length);
		userinfo->away_len = tlv->length;
	}

	/* Caps will be 5 */
	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) {
		ByteStream cbs;
		byte_stream_init(&cbs, tlv->value, tlv->length);
		userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length);
		userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES;
	}
	aim_tlvlist_free(tlvlist);

	aim_locate_adduserinfo(od, userinfo);
	userinfo2 = aim_locate_finduserinfo(od, userinfo->sn);
	aim_info_free(userinfo);
	g_free(userinfo);

	/*
	 * Remove this screen name from our queue.  If the client requested
	 * this buddy's info explicitly, then notify them that we have info
	 * for this buddy.
	 */
	if (userinfo2 != NULL)
	{
		was_explicit = aim_locate_gotuserinfo(od, conn, userinfo2->sn);
		if (was_explicit == TRUE)
			if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
				ret = userfunc(od, conn, frame, userinfo2);
	}

	return ret;
}
/* Subtype 0x0006 */
static int
userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
{
	int ret = 0;
	aim_userinfo_t *userinfo, *userinfo2;
	GSList *tlvlist;
	aim_tlv_t *tlv = NULL;

	userinfo = (aim_userinfo_t *)g_malloc(sizeof(aim_userinfo_t));
	aim_info_extract(od, bs, userinfo);
	tlvlist = aim_tlvlist_read(bs);

	/* Profile will be 1 and 2 */
	userinfo->info_encoding = aim_tlv_getstr(tlvlist, 0x0001, 1);
	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0002, 1))) {
		userinfo->info = (char *)g_malloc(tlv->length);
		memcpy(userinfo->info, tlv->value, tlv->length);
		userinfo->info_len = tlv->length;
	}

	/* Away message will be 3 and 4 */
	userinfo->away_encoding = aim_tlv_getstr(tlvlist, 0x0003, 1);
	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
		userinfo->away = (char *)g_malloc(tlv->length);
		memcpy(userinfo->away, tlv->value, tlv->length);
		userinfo->away_len = tlv->length;
	}

	/* Caps will be 5 */
	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) {
		ByteStream cbs;
		PurpleAccount *account = purple_connection_get_account(od->gc);
		const char *mood;

		byte_stream_init(&cbs, tlv->value, tlv->length);
		userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length);
		byte_stream_rewind(&cbs);
		userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES;

		mood = aim_receive_custom_icon(od, &cbs, tlv->length);
		if (mood)
			purple_prpl_got_user_status(account, userinfo->bn, "mood",
					PURPLE_MOOD_NAME, mood,
					NULL);
		else
			purple_prpl_got_user_status_deactive(account, userinfo->bn, "mood");
	}
	aim_tlvlist_free(tlvlist);

	aim_locate_adduserinfo(od, userinfo);
	userinfo2 = aim_locate_finduserinfo(od, userinfo->bn);
	aim_info_free(userinfo);
	g_free(userinfo);

	/* Show the info to the user */
	oscar_user_info_display_aim(od, userinfo2);

	return ret;
}
示例#12
0
文件: tlv.c 项目: Mons/libpurple-mini
static GSList *
aim_tlv_read(GSList *list, ByteStream *bs)
{
	guint16 type, length;
	aim_tlv_t *tlv;

	type = byte_stream_get16(bs);
	length = byte_stream_get16(bs);

#if 0
	/*
	 * This code hasn't been needed in years.  It's been commented
	 * out since 2003, at the latest.  It seems likely that it was
	 * just a bug in their server code that has since been fixed.
	 * In any case, here's the orignal comment, kept for historical
	 * purposes:
	 *
	 * Okay, so now AOL has decided that any TLV of
	 * type 0x0013 can only be two bytes, despite
	 * what the actual given length is.  So here
	 * we dump any invalid TLVs of that sort.  Hopefully
	 * there's no special cases to this special case.
	 *   - mid (30jun2000)
	 */
	if ((type == 0x0013) && (length != 0x0002)) {
		length = 0x0002;
		return list;
	}
#endif
	if (length > byte_stream_empty(bs)) {
		aim_tlvlist_free(list);
		return NULL;
	}

	tlv = createtlv(type, length, NULL);
	if (tlv->length > 0) {
		tlv->value = byte_stream_getraw(bs, length);
		if (!tlv->value) {
			freetlv(tlv);
			aim_tlvlist_free(list);
			return NULL;
		}
	}

	return g_slist_prepend(list, tlv);
}
/*
 * Subtype 0x0008
 */
int aim_chatnav_createroom(OscarData *od, FlapConnection *conn, const char *name, guint16 exchange)
{
	static const char ck[] = {"create"};
	static const char lang[] = {"en"};
	static const char charset[] = {"us-ascii"};
	ByteStream bs;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	byte_stream_new(&bs, 1142);

	snacid = aim_cachesnac(od, SNAC_FAMILY_CHATNAV, 0x0008, 0x0000, NULL, 0);

	/* exchange */
	byte_stream_put16(&bs, exchange);

	/*
	 * This looks to be a big hack.  You'll note that this entire
	 * SNAC is just a room info structure, but the hard room name,
	 * here, is set to "create".
	 *
	 * Either this goes on the "list of questions concerning
	 * why-the-hell-did-you-do-that", or this value is completely
	 * ignored.  Without experimental evidence, but a good knowledge of
	 * AOL style, I'm going to guess that it is the latter, and that
	 * the value of the room name in create requests is ignored.
	 */
	byte_stream_put8(&bs, strlen(ck));
	byte_stream_putstr(&bs, ck);

	/*
	 * instance
	 *
	 * Setting this to 0xffff apparently assigns the last instance.
	 *
	 */
	byte_stream_put16(&bs, 0xffff);

	/* detail level */
	byte_stream_put8(&bs, 0x01);

	aim_tlvlist_add_str(&tlvlist, 0x00d3, name);
	aim_tlvlist_add_str(&tlvlist, 0x00d6, charset);
	aim_tlvlist_add_str(&tlvlist, 0x00d7, lang);

	/* tlvcount */
	byte_stream_put16(&bs, aim_tlvlist_count(tlvlist));
	aim_tlvlist_write(&bs, &tlvlist);

	aim_tlvlist_free(tlvlist);

	flap_connection_send_snac(od, conn, SNAC_FAMILY_CHATNAV, 0x0008, snacid, &bs);

	byte_stream_destroy(&bs);

	return 0;
}
示例#14
0
/*
 * Part two of the ICQ hack.  Note the ignoring of the key.
 */
static int
goddamnicq2(OscarData *od, FlapConnection *conn, const char *sn, const char *password, ClientInfo *ci)
{
	FlapFrame *frame;
	GSList *tlvlist = NULL;
	int passwdlen;
	guint8 *password_encoded;
	guint32 distrib;

	passwdlen = strlen(password);
	password_encoded = (guint8 *)g_malloc(passwdlen+1);
	if (passwdlen > MAXICQPASSLEN)
		passwdlen = MAXICQPASSLEN;

	frame = flap_frame_new(od, 0x01, 1152);

	aim_encode_password(password, password_encoded);

	distrib = oscar_get_ui_info_int(
			od->icq ? "prpl-icq-distid" : "prpl-aim-distid",
			ci->distrib);

	byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
	aim_tlvlist_add_raw(&tlvlist, 0x0002, passwdlen, password_encoded);

	if (ci->clientstring != NULL)
		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
	else {
		gchar *clientstring = oscar_get_clientstring();
		aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
		g_free(clientstring);
	}
	aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid);
	aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
	aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
	aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
	aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
	aim_tlvlist_add_32(&tlvlist, 0x0014, distrib); /* distribution chan */
	aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
	aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);

	aim_tlvlist_write(&frame->data, &tlvlist);

	g_free(password_encoded);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
示例#15
0
/**
 * This sends a channel 1 FLAP containing the FLAP version and
 * the authentication cookie.  This is sent when connecting to
 * any FLAP server after the initial connection to the auth
 * server.  It is always the very first packet sent by both the
 * server and the client after the SYN, SYN/ACK, ACK handshake.
 */
void
flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy)
{
	FlapFrame *frame;
	GSList *tlvlist = NULL;

	frame = flap_frame_new(od, 0x01, 4 + 2 + 2 + length);
	byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
	aim_tlvlist_add_raw(&tlvlist, 0x0006, length, chipsahoy);
	aim_tlvlist_write(&frame->data, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);
}
示例#16
0
/* Subtype 0x0006 */
static int
userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
{
	int ret = 0;
	aim_rxcallback_t userfunc;
	aim_userinfo_t *userinfo, *userinfo2;
	GSList *tlvlist;
	aim_tlv_t *tlv = NULL;

	userinfo = (aim_userinfo_t *)g_malloc(sizeof(aim_userinfo_t));
	aim_info_extract(od, bs, userinfo);
	tlvlist = aim_tlvlist_read(bs);

	/* Profile will be 1 and 2 */
	userinfo->info_encoding = aim_tlv_getstr(tlvlist, 0x0001, 1);
	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0002, 1))) {
		userinfo->info = (char *)g_malloc(tlv->length);
		memcpy(userinfo->info, tlv->value, tlv->length);
		userinfo->info_len = tlv->length;
	}

	/* Away message will be 3 and 4 */
	userinfo->away_encoding = aim_tlv_getstr(tlvlist, 0x0003, 1);
	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
		userinfo->away = (char *)g_malloc(tlv->length);
		memcpy(userinfo->away, tlv->value, tlv->length);
		userinfo->away_len = tlv->length;
	}

	/* Caps will be 5 */
	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) {
		ByteStream cbs;
		byte_stream_init(&cbs, tlv->value, tlv->length);
		userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length);
		userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES;
	}
	aim_tlvlist_free(tlvlist);

	aim_locate_adduserinfo(od, userinfo);
	userinfo2 = aim_locate_finduserinfo(od, userinfo->bn);
	aim_info_free(userinfo);
	g_free(userinfo);

	/* Show the info to the user */
	if (userinfo2 != NULL && ((userfunc = aim_callhandler(od, snac->family, snac->subtype))))
		ret = userfunc(od, conn, frame, userinfo2);

	return ret;
}
示例#17
0
/*
 * Subtype 0x0009 - Set directory profile data.
 *
 * This is not the same as aim_location_setprofile!
 * privacy: 1 to allow searching, 0 to disallow.
 *
 */
int aim_locate_setdirinfo(OscarData *od, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy)
{
	FlapConnection *conn;
	ByteStream bs;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	aim_tlvlist_add_16(&tlvlist, 0x000a, privacy);

	if (first)
		aim_tlvlist_add_str(&tlvlist, 0x0001, first);
	if (last)
		aim_tlvlist_add_str(&tlvlist, 0x0002, last);
	if (middle)
		aim_tlvlist_add_str(&tlvlist, 0x0003, middle);
	if (maiden)
		aim_tlvlist_add_str(&tlvlist, 0x0004, maiden);

	if (state)
		aim_tlvlist_add_str(&tlvlist, 0x0007, state);
	if (city)
		aim_tlvlist_add_str(&tlvlist, 0x0008, city);

	if (nickname)
		aim_tlvlist_add_str(&tlvlist, 0x000c, nickname);
	if (zip)
		aim_tlvlist_add_str(&tlvlist, 0x000d, zip);

	if (street)
		aim_tlvlist_add_str(&tlvlist, 0x0021, street);

	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0009, 0x0000, NULL, 0);

	aim_tlvlist_write(&bs, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0009, 0x0000, snacid, &bs);

	byte_stream_destroy(&bs);

	return 0;
}
示例#18
0
/*
 * Subtype 0x0002 - General room information.  Lots of stuff.
 *
 * Values I know are in here but I haven't attached
 * them to any of the 'Unknown's:
 *	- Language (English)
 *
 */
static int
infoupdate(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
{
	aim_rxcallback_t userfunc;
	int ret = 0;
	guint8 detaillevel = 0;
	struct aim_chat_roominfo roominfo;
	GSList *tlvlist;
	guint16 maxmsglen, maxvisiblemsglen;

	aim_chat_readroominfo(bs, &roominfo);

	detaillevel = byte_stream_get8(bs);

	if (detaillevel != 0x02) {
		purple_debug_misc("oscar", "faim: chat_roomupdateinfo: detail level %d not supported\n", detaillevel);
		return 1;
	}

	byte_stream_get16(bs); /* skip the TLV count */

	/*
	 * Everything else are TLVs.
	 */
	tlvlist = aim_tlvlist_read(bs);

	/*
	 * Type 0x00d1: Maximum Message Length
	 */
	maxmsglen = aim_tlv_get16(tlvlist, 0x00d1, 1);

	/*
	 * Type 0x00da: Maximum visible message length
	 */
	maxvisiblemsglen = aim_tlv_get16(tlvlist, 0x00da, 1);

	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) {
		ret = userfunc(od, conn, frame, maxmsglen, maxvisiblemsglen);
	}

	g_free(roominfo.name);

	aim_tlvlist_free(tlvlist);

	return ret;
}
示例#19
0
/*
 * Inverse of aim_info_extract()
 */
int
aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info)
{
	GSList *tlvlist = NULL;

	if (!bs || !info)
		return -EINVAL;

	byte_stream_put8(bs, strlen(info->bn));
	byte_stream_putstr(bs, info->bn);

	byte_stream_put16(bs, info->warnlevel);

	if (info->present & AIM_USERINFO_PRESENT_FLAGS)
		aim_tlvlist_add_16(&tlvlist, 0x0001, info->flags);
	if (info->present & AIM_USERINFO_PRESENT_MEMBERSINCE)
		aim_tlvlist_add_32(&tlvlist, 0x0002, info->membersince);
	if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE)
		aim_tlvlist_add_32(&tlvlist, 0x0003, info->onlinesince);
	if (info->present & AIM_USERINFO_PRESENT_IDLE)
		aim_tlvlist_add_16(&tlvlist, 0x0004, info->idletime);

/* XXX - So, ICQ_OSCAR_SUPPORT is never defined anywhere... */
#ifdef ICQ_OSCAR_SUPPORT
	if (atoi(info->bn) != 0) {
		if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS)
			aim_tlvlist_add_16(&tlvlist, 0x0006, info->icqinfo.status);
		if (info->present & AIM_USERINFO_PRESENT_ICQIPADDR)
			aim_tlvlist_add_32(&tlvlist, 0x000a, info->icqinfo.ipaddr);
	}
#endif

	if (info->present & AIM_USERINFO_PRESENT_CAPABILITIES)
		aim_tlvlist_add_caps(&tlvlist, 0x000d, info->capabilities);

	if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN)
		aim_tlvlist_add_32(&tlvlist, (guint16)((info->flags & AIM_FLAG_AOL) ? 0x0010 : 0x000f), info->sessionlen);

	byte_stream_put16(bs, aim_tlvlist_count(tlvlist));
	aim_tlvlist_write(bs, &tlvlist);
	aim_tlvlist_free(tlvlist);

	return 0;
}
示例#20
0
/*
 * Subtype 0x0003 - Rights.
 *
 */
static int
rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
{
	aim_rxcallback_t userfunc;
	GSList *tlvlist;
	guint16 maxbuddies = 0, maxwatchers = 0;
	int ret = 0;

	/*
	 * TLVs follow
	 */
	tlvlist = aim_tlvlist_read(bs);

	/*
	 * TLV type 0x0001: Maximum number of buddies.
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
		maxbuddies = aim_tlv_get16(tlvlist, 0x0001, 1);

	/*
	 * TLV type 0x0002: Maximum number of watchers.
	 *
	 * Watchers are other users who have you on their buddy
	 * list.  (This is called the "reverse list" by a certain
	 * other IM protocol.)
	 *
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
		maxwatchers = aim_tlv_get16(tlvlist, 0x0002, 1);

	/*
	 * TLV type 0x0003: Unknown.
	 *
	 * ICQ only?
	 */

	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
		ret = userfunc(od, conn, frame, maxbuddies, maxwatchers);

	aim_tlvlist_free(tlvlist);

	return ret;
}
示例#21
0
文件: buddylist.c 项目: echoline/powk
/*
 * Subtype 0x0003 - Rights.
 *
 */
static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
{
	aim_rxcallback_t userfunc;
	aim_tlvlist_t *tlvlist;
	fu16_t maxbuddies = 0, maxwatchers = 0;
	int ret = 0;

	/* 
	 * TLVs follow 
	 */
	tlvlist = aim_tlvlist_read(bs);

	/*
	 * TLV type 0x0001: Maximum number of buddies.
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
		maxbuddies = aim_tlv_get16(tlvlist, 0x0001, 1);

	/*
	 * TLV type 0x0002: Maximum number of watchers.
	 *
	 * Watchers are other users who have you on their buddy
	 * list.  (This is called the "reverse list" by a certain
	 * other IM protocol.)
	 * 
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
		maxwatchers = aim_tlv_get16(tlvlist, 0x0002, 1);

	/*
	 * TLV type 0x0003: Unknown.
	 *
	 * ICQ only?
	 */

	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
		ret = userfunc(sess, rx, maxbuddies, maxwatchers);

	aim_tlvlist_free(&tlvlist);

	return ret;
}
示例#22
0
/*
 * Subtype 0x0003
 *
 * Normally contains:
 *   t(0001)  - short containing max profile length (value = 1024)
 *   t(0002)  - short - unknown (value = 16) [max MIME type length?]
 *   t(0003)  - short - unknown (value = 10)
 *   t(0004)  - short - unknown (value = 2048) [ICQ only?]
 */
static int
rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
{
	GSList *tlvlist;
	aim_rxcallback_t userfunc;
	int ret = 0;
	guint16 maxsiglen = 0;

	tlvlist = aim_tlvlist_read(bs);

	if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
		maxsiglen = aim_tlv_get16(tlvlist, 0x0001, 1);

	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
		ret = userfunc(od, conn, frame, maxsiglen);

	aim_tlvlist_free(tlvlist);

	return ret;
}
示例#23
0
/*
 * Subtype 0x000f
 *
 * XXX pass these in better
 *
 */
int
aim_locate_setinterests(OscarData *od, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy)
{
	FlapConnection *conn;
	FlapFrame *frame;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	/* ?? privacy ?? */
	aim_tlvlist_add_16(&tlvlist, 0x000a, privacy);

	if (interest1)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest1);
	if (interest2)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest2);
	if (interest3)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest3);
	if (interest4)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest4);
	if (interest5)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest5);

	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, 0x0002, 0x000f, 0x0000, NULL, 0);

	aim_putsnac(&frame->data, 0x0002, 0x000f, 0x0000, 0);
	aim_tlvlist_write(&frame->data, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
示例#24
0
static void
parse_flap_ch4(OscarData *od, FlapConnection *conn, FlapFrame *frame)
{
	GSList *tlvlist;
	char *msg = NULL;

	if (byte_stream_bytes_left(&frame->data) == 0) {
		/* XXX should do something with this */
		return;
	}

	/* An ICQ account is logging in */
	if (conn->type == SNAC_FAMILY_AUTH)
	{
		parse_fakesnac(od, conn, frame, 0x0017, 0x0003);
		return;
	}

	tlvlist = aim_tlvlist_read(&frame->data);

	if (aim_tlv_gettlv(tlvlist, 0x0009, 1))
		conn->disconnect_code = aim_tlv_get16(tlvlist, 0x0009, 1);

	if (aim_tlv_gettlv(tlvlist, 0x000b, 1))
		msg = aim_tlv_getstr(tlvlist, 0x000b, 1);

	/*
	 * The server ended this FLAP connnection, so let's be nice and
	 * close the physical TCP connection
	 */
	flap_connection_schedule_destroy(conn,
			OSCAR_DISCONNECT_REMOTE_CLOSED, msg);

	aim_tlvlist_free(tlvlist);

	g_free(msg);
}
示例#25
0
/*
 * Subtype 0x000f
 *
 * XXX pass these in better
 *
 */
int
aim_locate_setinterests(OscarData *od, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy)
{
	FlapConnection *conn;
	ByteStream bs;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	/* ?? privacy ?? */
	aim_tlvlist_add_16(&tlvlist, 0x000a, privacy);

	if (interest1)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest1);
	if (interest2)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest2);
	if (interest3)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest3);
	if (interest4)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest4);
	if (interest5)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest5);

	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x000f, 0x0000, NULL, 0);

	aim_tlvlist_write(&bs, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x000f, 0x0000, snacid, &bs);

	byte_stream_destroy(&bs);
	return 0;
}
示例#26
0
/*
 * This is sent back as a general response to the login command.
 * It can be either an error or a success, depending on the
 * presence of certain TLVs.
 *
 * The client should check the value passed as errorcode. If
 * its nonzero, there was an error.
 */
static int
parse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
{
	GSList *tlvlist;
	aim_rxcallback_t userfunc;
	struct aim_authresp_info *info;
	int ret = 0;

	info = g_new0(struct aim_authresp_info, 1);

	/*
	 * Read block of TLVs.  All further data is derived
	 * from what is parsed here.
	 */
	tlvlist = aim_tlvlist_read(bs);

	/*
	 * No matter what, we should have a username.
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0001, 1)) {
		info->bn = aim_tlv_getstr(tlvlist, 0x0001, 1);
		purple_connection_set_display_name(od->gc, info->bn);
	}

	/*
	 * Check for an error code.  If so, we should also
	 * have an error url.
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0008, 1))
		info->errorcode = aim_tlv_get16(tlvlist, 0x0008, 1);
	if (aim_tlv_gettlv(tlvlist, 0x0004, 1))
		info->errorurl = aim_tlv_getstr(tlvlist, 0x0004, 1);

	/*
	 * BOS server address.
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0005, 1))
		info->bosip = aim_tlv_getstr(tlvlist, 0x0005, 1);

	/*
	 * Authorization cookie.
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
		aim_tlv_t *tmptlv;

		tmptlv = aim_tlv_gettlv(tlvlist, 0x0006, 1);
		if (tmptlv != NULL)
		{
			info->cookielen = tmptlv->length;
			info->cookie = tmptlv->value;
		}
	}

	/*
	 * The email address attached to this account
	 *   Not available for ICQ or @mac.com logins.
	 *   If you receive this TLV, then you are allowed to use
	 *   family 0x0018 to check the status of your email.
	 * XXX - Not really true!
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0011, 1))
		info->email = aim_tlv_getstr(tlvlist, 0x0011, 1);

	/*
	 * The registration status.  (Not real sure what it means.)
	 *   Not available for ICQ or @mac.com logins.
	 *
	 *   1 = No disclosure
	 *   2 = Limited disclosure
	 *   3 = Full disclosure
	 *
	 * This has to do with whether your email address is available
	 * to other users or not.  AFAIK, this feature is no longer used.
	 *
	 * Means you can use the admin family? (0x0007)
	 *
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0013, 1))
		info->regstatus = aim_tlv_get16(tlvlist, 0x0013, 1);

	if (aim_tlv_gettlv(tlvlist, 0x0040, 1))
		info->latestbeta.build = aim_tlv_get32(tlvlist, 0x0040, 1);
	if (aim_tlv_gettlv(tlvlist, 0x0041, 1))
		info->latestbeta.url = aim_tlv_getstr(tlvlist, 0x0041, 1);
	if (aim_tlv_gettlv(tlvlist, 0x0042, 1))
		info->latestbeta.info = aim_tlv_getstr(tlvlist, 0x0042, 1);
	if (aim_tlv_gettlv(tlvlist, 0x0043, 1))
		info->latestbeta.name = aim_tlv_getstr(tlvlist, 0x0043, 1);

#if 0
	if (aim_tlv_gettlv(tlvlist, 0x0048, 1)) {
		/* beta serial */
	}
#endif

	if (aim_tlv_gettlv(tlvlist, 0x0044, 1))
		info->latestrelease.build = aim_tlv_get32(tlvlist, 0x0044, 1);
	if (aim_tlv_gettlv(tlvlist, 0x0045, 1))
		info->latestrelease.url = aim_tlv_getstr(tlvlist, 0x0045, 1);
	if (aim_tlv_gettlv(tlvlist, 0x0046, 1))
		info->latestrelease.info = aim_tlv_getstr(tlvlist, 0x0046, 1);
	if (aim_tlv_gettlv(tlvlist, 0x0047, 1))
		info->latestrelease.name = aim_tlv_getstr(tlvlist, 0x0047, 1);

#if 0
	if (aim_tlv_gettlv(tlvlist, 0x0049, 1)) {
		/* lastest release serial */
	}
#endif

	/*
	 * URL to change password.
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0054, 1))
		info->chpassurl = aim_tlv_getstr(tlvlist, 0x0054, 1);

#if 0
	/*
	 * Unknown.  Seen on an @mac.com username with value of 0x003f
	 */
	if (aim_tlv_gettlv(tlvlist, 0x0055, 1)) {
		/* Unhandled */
	}
#endif

	od->authinfo = info;

	if ((userfunc = aim_callhandler(od, snac ? snac->family : SNAC_FAMILY_AUTH, snac ? snac->subtype : 0x0003)))
		ret = userfunc(od, conn, frame, info);

	aim_tlvlist_free(tlvlist);

	return ret;
}
示例#27
0
/*
 * Subtype 0x0002
 *
 * This is the initial login request packet.
 *
 * NOTE!! If you want/need to make use of the aim_sendmemblock() function,
 * then the client information you send here must exactly match the
 * executable that you're pulling the data from.
 *
 * Java AIM 1.1.19:
 *   clientstring = "AOL Instant Messenger (TM) version 1.1.19 for Java built 03/24/98, freeMem 215871 totalMem 1048567, i686, Linus, #2 SMP Sun Feb 11 03:41:17 UTC 2001 2.4.1-ac9, IBM Corporation, 1.1.8, 45.3, Tue Mar 27 12:09:17 PST 2001"
 *   clientid = 0x0001
 *   major  = 0x0001
 *   minor  = 0x0001
 *   point = (not sent)
 *   build  = 0x0013
 *   unknown= (not sent)
 *
 * AIM for Linux 1.1.112:
 *   clientstring = "AOL Instant Messenger (SM)"
 *   clientid = 0x1d09
 *   major  = 0x0001
 *   minor  = 0x0001
 *   point = 0x0001
 *   build  = 0x0070
 *   unknown= 0x0000008b
 *   serverstore = 0x01
 *
 * @param truncate_pass Truncate the password to 8 characters.  This
 *        usually happens for AOL accounts.  We are told that we
 *        should truncate it if the 0x0017/0x0007 SNAC contains
 *        a TLV of type 0x0026 with data 0x0000.
 * @param allow_multiple_logins Allow multiple logins? If TRUE, the AIM
 *        server will prompt the user when multiple logins occur. If
 *        FALSE, existing connections (on other clients) will be
 *        disconnected automatically as we connect.
 */
int
aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key, gboolean allow_multiple_logins)
{
	FlapFrame *frame;
	GSList *tlvlist = NULL;
	guint8 digest[16];
	aim_snacid_t snacid;
	size_t password_len;
	guint32 distrib;

	if (!ci || !sn || !password)
		return -EINVAL;

#ifdef USE_XOR_FOR_ICQ
	/* If we're signing on an ICQ account then use the older, XOR login method */
	if (aim_snvalid_icq(sn))
		return goddamnicq2(od, conn, sn, password, ci);
#endif

	frame = flap_frame_new(od, 0x02, 1152);

	snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0002, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0002, 0x0000, snacid);

	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);

	/* Truncate ICQ and AOL passwords, if necessary */
	password_len = strlen(password);
	if (oscar_util_valid_name_icq(sn) && (password_len > MAXICQPASSLEN))
		password_len = MAXICQPASSLEN;
	else if (truncate_pass && password_len > 8)
		password_len = 8;

	aim_encode_password_md5(password, password_len, key, digest);

	distrib = oscar_get_ui_info_int(
			od->icq ? "prpl-icq-distid" : "prpl-aim-distid",
			ci->distrib);

	aim_tlvlist_add_raw(&tlvlist, 0x0025, 16, digest);

#ifndef USE_OLD_MD5
	aim_tlvlist_add_noval(&tlvlist, 0x004c);
#endif

	if (ci->clientstring != NULL)
		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
	else {
		gchar *clientstring = oscar_get_clientstring();
		aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
		g_free(clientstring);
	}
	aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid);
	aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
	aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
	aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
	aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
	aim_tlvlist_add_32(&tlvlist, 0x0014, distrib);
	aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
	aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);

	/*
	 * If set, old-fashioned buddy lists will not work. You will need
	 * to use SSI.
	 */
	aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03));

	aim_tlvlist_write(&frame->data, &tlvlist);

	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
示例#28
0
文件: tlv.c 项目: JasonGross/barnowl
/**
 * Read a TLV chain from a buffer.
 *
 * Reads and parses a series of TLV patterns from a data buffer; the
 * returned structure is manipulatable with the rest of the TLV
 * routines.  When done with a TLV chain, aim_tlvlist_free() should
 * be called to free the dynamic substructures.
 *
 * XXX There should be a flag setable here to have the tlvlist contain
 * bstream references, so that at least the ->value portion of each 
 * element doesn't need to be malloc/memcpy'd.  This could prove to be
 * just as effecient as the in-place TLV parsing used in a couple places
 * in libfaim.
 *
 * @param bs Input bstream
 */
faim_internal aim_tlvlist_t *aim_tlvlist_read(aim_bstream_t *bs)
{
	aim_tlvlist_t *list = NULL, *cur;
	
	while (aim_bstream_empty(bs) > 0) {
		fu16_t type, length;

		type = aimbs_get16(bs);
		length = aimbs_get16(bs);

#if 0 /* temporarily disabled until I know if they're still doing it or not */
		/*
		 * Okay, so now AOL has decided that any TLV of
		 * type 0x0013 can only be two bytes, despite
		 * what the actual given length is.  So here 
		 * we dump any invalid TLVs of that sort.  Hopefully
		 * theres no special cases to this special case.
		 *   - mid (30jun2000)
		 */
		if ((type == 0x0013) && (length != 0x0002))
			length = 0x0002;
#else
		if (0)
			;
#endif
		else {

			if (length > aim_bstream_empty(bs)) {
				aim_tlvlist_free(&list);
				return NULL;
			}

			cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
			if (!cur) {
				aim_tlvlist_free(&list);
				return NULL;
			}

			memset(cur, 0, sizeof(aim_tlvlist_t));

			cur->tlv = createtlv(type, length, NULL);
			if (!cur->tlv) {
				free(cur);
				aim_tlvlist_free(&list);
				return NULL;
			}
			if (cur->tlv->length > 0) {
				cur->tlv->value = aimbs_getraw(bs, length);	
				if (!cur->tlv->value) {
					freetlv(&cur->tlv);
					free(cur);
					aim_tlvlist_free(&list);
					return NULL;
				}
			}

			cur->next = list;
			list = cur;
		}
	}

	return list;
}
示例#29
0
/**
 * Subtype 0x0003 - Response to 0x0015/0x002, contains an ICQesque packet.
 */
static int icqresponse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
{
	int ret = 0;
	aim_tlvlist_t *tl;
	aim_tlv_t *datatlv;
	aim_bstream_t qbs;
	fu32_t ouruin;
	fu16_t cmdlen, cmd, reqid;

	if (!(tl = aim_tlvlist_read(bs)) || !(datatlv = aim_tlv_gettlv(tl, 0x0001, 1))) {
		aim_tlvlist_free(&tl);
		faimdprintf(sess, 0, "corrupt ICQ response\n");
		return 0;
	}

	aim_bstream_init(&qbs, datatlv->value, datatlv->length);

	cmdlen = aimbs_getle16(&qbs);
	ouruin = aimbs_getle32(&qbs);
	cmd = aimbs_getle16(&qbs);
	reqid = aimbs_getle16(&qbs);

	faimdprintf(sess, 1, "icq response: %d bytes, %ld, 0x%04x, 0x%04x\n", cmdlen, ouruin, cmd, reqid);

	if (cmd == 0x0041) { /* offline message */
		struct aim_icq_offlinemsg msg;
		aim_rxcallback_t userfunc;

		memset(&msg, 0, sizeof(msg));

		msg.sender = aimbs_getle32(&qbs);
		msg.year = aimbs_getle16(&qbs);
		msg.month = aimbs_getle8(&qbs);
		msg.day = aimbs_getle8(&qbs);
		msg.hour = aimbs_getle8(&qbs);
		msg.minute = aimbs_getle8(&qbs);
		msg.type = aimbs_getle8(&qbs);
		msg.flags = aimbs_getle8(&qbs);
		msg.msglen = aimbs_getle16(&qbs);
		msg.msg = aimbs_getstr(&qbs, msg.msglen);

		if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG)))
			ret = userfunc(sess, rx, &msg);

		free(msg.msg);

	} else if (cmd == 0x0042) {
		aim_rxcallback_t userfunc;

		if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE)))
			ret = userfunc(sess, rx);

	} else if (cmd == 0x07da) { /* information */
		fu16_t subtype;
		struct aim_icq_info *info;
		aim_rxcallback_t userfunc;

		subtype = aimbs_getle16(&qbs);
		aim_bstream_advance(&qbs, 1); /* 0x0a */

		/* find other data from the same request */
		for (info = sess->icq_info; info && (info->reqid != reqid); info = info->next);
		if (!info) {
			info = (struct aim_icq_info *)calloc(1, sizeof(struct aim_icq_info));
			info->reqid = reqid;
			info->next = sess->icq_info;
			sess->icq_info = info;
		}

		switch (subtype) {
		case 0x00a0: { /* hide ip status */
			/* nothing */
		} break;

		case 0x00aa: { /* password change status */
			/* nothing */
		} break;

		case 0x00c8: { /* general and "home" information */
			info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->homecity = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->homestate = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->homephone = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->homefax = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->homeaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->mobile = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->homezip = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->homecountry = aimbs_getle16(&qbs);
			/* 0x0a 00 02 00 */
			/* 1 byte timezone? */
			/* 1 byte hide email flag? */
		} break;

		case 0x00dc: { /* personal information */
			info->age = aimbs_getle8(&qbs);
			info->unknown = aimbs_getle8(&qbs);
			info->gender = aimbs_getle8(&qbs); /* Not specified=0x00, Female=0x01, Male=0x02 */
			info->personalwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->birthyear = aimbs_getle16(&qbs);
			info->birthmonth = aimbs_getle8(&qbs);
			info->birthday = aimbs_getle8(&qbs);
			info->language1 = aimbs_getle8(&qbs);
			info->language2 = aimbs_getle8(&qbs);
			info->language3 = aimbs_getle8(&qbs);
			/* 0x00 00 01 00 00 01 00 00 00 00 00 */
		} break;

		case 0x00d2: { /* work information */
			info->workcity = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->workstate = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->workphone = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->workfax = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->workaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->workzip = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->workcountry = aimbs_getle16(&qbs);
			info->workcompany = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->workdivision = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->workposition = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			aim_bstream_advance(&qbs, 2); /* 0x01 00 */
			info->workwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
		} break;

		case 0x00e6: { /* additional personal information */
			info->info = aimbs_getstr(&qbs, aimbs_getle16(&qbs)-1);
		} break;

		case 0x00eb: { /* email address(es) */
			int i;
			info->numaddresses = aimbs_getle16(&qbs);
			info->email2 = (char **)calloc(info->numaddresses, sizeof(char *));
			for (i = 0; i < info->numaddresses; i++) {
				info->email2[i] = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
				if (i+1 != info->numaddresses)
					aim_bstream_advance(&qbs, 1); /* 0x00 */
			}
		} break;

		case 0x00f0: { /* personal interests */
		} break;

		case 0x00fa: { /* past background and current organizations */
		} break;

		case 0x0104: { /* alias info */
			info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); /* email address? */
			/* Then 0x00 02 00 */
		} break;

		case 0x010e: { /* unknown */
			/* 0x00 00 */
		} break;

		case 0x019a: { /* simple info */
			aim_bstream_advance(&qbs, 2);
			info->uin = aimbs_getle32(&qbs);
			info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
			/* Then 0x00 02 00 00 00 00 00 */
		} break;
		} /* End switch statement */

		if (!(snac->flags & 0x0001)) {
			if (subtype != 0x0104)
				if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_INFO)))
					ret = userfunc(sess, rx, info);

			if (info->uin && info->nick)
				if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_ALIAS)))
					ret = userfunc(sess, rx, info);

			if (sess->icq_info == info) {
				sess->icq_info = info->next;
			} else {
				struct aim_icq_info *cur;
				for (cur=sess->icq_info; (cur->next && (cur->next!=info)); cur=cur->next);
				if (cur->next)
					cur->next = cur->next->next;
			}
			aim_icq_freeinfo(info);
		}
	}

	aim_tlvlist_free(&tl);

	return ret;
}
示例#30
0
/*
 * Subtype 0x0004
 *
 * Gives BOS your profile.
 *
 * profile_encoding and awaymsg_encoding MUST be set if profile or
 * away are set, respectively, and their value may or may not be
 * restricted to a few choices.  I am currently aware of:
 *
 * us-ascii		Just that
 * unicode-2-0		UTF-16BE
 *
 * profile_len and awaymsg_len MUST be set similarly, and they MUST
 * be the length of their respective strings in bytes.
 *
 * To get the previous behavior of awaymsg == "" un-setting the away
 * message, set awaymsg non-NULL and awaymsg_len to 0 (this is the
 * obvious equivalent).
 *
 */
int
aim_locate_setprofile(OscarData *od,
				  const char *profile_encoding, const gchar *profile, const int profile_len,
				  const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len)
{
	FlapConnection *conn;
	ByteStream bs;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;
	char *encoding;
	static const char defencoding[] = {"text/aolrtf; charset=\"%s\""};

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	if (!profile && !awaymsg)
		return -EINVAL;

	if ((profile && profile_encoding == NULL) || (awaymsg && awaymsg_len && awaymsg_encoding == NULL)) {
		return -EINVAL;
	}

	/* Build the packet first to get real length */
	if (profile) {
		/* no + 1 here because of %s */
		encoding = g_malloc(strlen(defencoding) + strlen(profile_encoding));
		snprintf(encoding, strlen(defencoding) + strlen(profile_encoding), defencoding, profile_encoding);
		aim_tlvlist_add_str(&tlvlist, 0x0001, encoding);
		aim_tlvlist_add_raw(&tlvlist, 0x0002, profile_len, (const guchar *)profile);
		g_free(encoding);
	}

	/*
	 * So here's how this works:
	 *   - You are away when you have a non-zero-length type 4 TLV stored.
	 *   - You become unaway when you clear the TLV with a zero-length
	 *       type 4 TLV.
	 *   - If you do not send the type 4 TLV, your status does not change
	 *       (that is, if you were away, you'll remain away).
	 */
	if (awaymsg) {
		if (awaymsg_len) {
			encoding = g_malloc(strlen(defencoding) + strlen(awaymsg_encoding));
			snprintf(encoding, strlen(defencoding) + strlen(awaymsg_encoding), defencoding, awaymsg_encoding);
			aim_tlvlist_add_str(&tlvlist, 0x0003, encoding);
			aim_tlvlist_add_raw(&tlvlist, 0x0004, awaymsg_len, (const guchar *)awaymsg);
			g_free(encoding);
		} else
			aim_tlvlist_add_noval(&tlvlist, 0x0004);
	}

	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, NULL, 0);

	aim_tlvlist_write(&bs, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, snacid, &bs);

	byte_stream_destroy(&bs);

	return 0;
}