changeset 17449:e3fd996b7780

merge of 'd25352d4d47369224b6a555d8008b07f6a930ce4' and 'fddae6c06ad36c616e9e26413f15f4102f375fa1'
author Gabriel Schulhof <nix@go-nix.ca>
date Tue, 29 May 2007 22:21:35 +0000
parents af5f8bdc0bab (diff) ce03892c4755 (current diff)
children 5205be30c0be
files
diffstat 27 files changed, 708 insertions(+), 686 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Tue May 29 22:21:02 2007 +0000
+++ b/COPYRIGHT	Tue May 29 22:21:35 2007 +0000
@@ -149,6 +149,7 @@
 Casey Harkins
 Andy Harrison
 Andrew Hart (arhart)
+Rene Hausleitner
 G. Sumner Hayes
 Michael R. Head
 Nick Hebner
--- a/ChangeLog	Tue May 29 22:21:02 2007 +0000
+++ b/ChangeLog	Tue May 29 22:21:35 2007 +0000
@@ -1,6 +1,8 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
 version 2.0.2 (??/??/????):
+	* Moving an ICQ buddy from one group to another no longer
+	  re-requests authorization from that person (Rene Hausleitner)
 
 	Finch:
 	* Auto account reconnecting
--- a/libpurple/protocols/jabber/disco.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/jabber/disco.c	Tue May 29 22:21:35 2007 +0000
@@ -224,17 +224,17 @@
 		/* If the server supports JABBER_CAP_GOOGLE_ROSTER; we will have already requested it */
 		jabber_roster_request(js);
 	}
-	
+
 	/* Send initial presence; this will trigger receipt of presence for contacts on the roster */
 	gpresence = purple_account_get_presence(js->gc->account);
 	status = purple_presence_get_active_status(gpresence);
-	jabber_presence_send(js->gc->account, status);	
+	jabber_presence_send(js->gc->account, status);
 }
 
 static void
 jabber_disco_server_info_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
 {
-  	xmlnode *query, *child;
+	xmlnode *query, *child;
 	const char *from = xmlnode_get_attrib(packet, "from");
 	const char *type = xmlnode_get_attrib(packet, "type");
 
@@ -257,7 +257,7 @@
 		return;
 	}
 
-	for (child = xmlnode_get_child(query, "identity"); child; 
+	for (child = xmlnode_get_child(query, "identity"); child;
 	     child = xmlnode_get_next_twin(child)) {
 		const char *category, *type, *name;
 		category = xmlnode_get_attrib(child, "category");
@@ -266,7 +266,7 @@
 		type = xmlnode_get_attrib(child, "type");
 		if (!type || strcmp(type, "im"))
 			continue;
-		
+
 		name = xmlnode_get_attrib(child, "name");
 		if (!name)
 			continue;
@@ -279,7 +279,7 @@
 		}
 	}
 
-	for (child = xmlnode_get_child(query, "feature"); child; 
+	for (child = xmlnode_get_child(query, "feature"); child;
 	     child = xmlnode_get_next_twin(child)) {
 		const char *var;
 		var = xmlnode_get_attrib(child, "var");
@@ -324,11 +324,16 @@
 	for(child = xmlnode_get_child(query, "item"); child;
 			child = xmlnode_get_next_twin(child)) {
 		JabberIq *iq;
-		const char *jid;
+		const char *jid, *node;
 
 		if(!(jid = xmlnode_get_attrib(child, "jid")))
 			continue;
 
+		/* we don't actually care about the specific nodes,
+		 * so we won't query them */
+		if((node = xmlnode_get_attrib(child, "node")))
+			continue;
+
 		iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info");
 		xmlnode_set_attrib(iq->node, "to", jid);
 		jabber_iq_send(iq);
--- a/libpurple/protocols/jabber/presence.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/jabber/presence.c	Tue May 29 22:21:35 2007 +0000
@@ -106,11 +106,12 @@
 		return;
 
 	disconnected = purple_account_is_disconnected(account);
-	primitive = purple_status_type_get_primitive(purple_status_get_type(status));
 
 	if(disconnected)
 		return;
 
+	primitive = purple_status_type_get_primitive(purple_status_get_type(status));
+
 	gc = purple_account_get_connection(account);
 	js = gc->proto_data;
 
--- a/libpurple/protocols/jabber/si.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/jabber/si.c	Tue May 29 22:21:35 2007 +0000
@@ -26,6 +26,7 @@
 #include "cipher.h"
 #include "debug.h"
 #include "ft.h"
+#include "request.h"
 #include "network.h"
 #include "notify.h"
 
@@ -769,6 +770,36 @@
 	}
 }
 
+static void resource_select_cancel_cb(PurpleXfer *xfer, PurpleRequestFields *fields)
+{
+	purple_xfer_cancel_local(xfer);
+}
+
+static void do_transfer_send(PurpleXfer *xfer, const char *resource)
+{
+	JabberSIXfer *jsx = xfer->data;
+	char **who_v = g_strsplit(xfer->who, "/", 2);
+	char *who;
+
+	who = g_strdup_printf("%s/%s", who_v[0], resource);
+	g_strfreev(who_v);
+	g_free(xfer->who);
+	xfer->who = who;
+	jabber_disco_info_do(jsx->js, who,
+			jabber_si_xfer_send_disco_cb, xfer);
+}
+
+static void resource_select_ok_cb(PurpleXfer *xfer, PurpleRequestFields *fields)
+{
+	PurpleRequestField *field = purple_request_fields_get_field(fields, "resource");
+	int selected_id = purple_request_field_choice_get_value(field);
+	GList *labels = purple_request_field_choice_get_labels(field);
+
+	const char *selected_label = g_list_nth_data(labels, selected_id);
+
+	do_transfer_send(xfer, selected_label);
+}
+
 static void jabber_si_xfer_init(PurpleXfer *xfer)
 {
 	JabberSIXfer *jsx = xfer->data;
@@ -776,26 +807,65 @@
 	if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
 		JabberBuddy *jb;
 		JabberBuddyResource *jbr = NULL;
+		char *resource;
+
+		if(NULL != (resource = jabber_get_resource(xfer->who))) {
+			/* they've specified a resource, no need to ask or
+			 * default or anything, just do it */
+
+			do_transfer_send(xfer, resource);
+			g_free(resource);
+		}
 
 		jb = jabber_buddy_find(jsx->js, xfer->who, TRUE);
-		/* XXX */
-		if(!jb)
-			return;
+
+		if(!jb || !jb->resources) {
+			/* no resources online, we're trying to send to someone
+			 * whose presence we're not subscribed to, or
+			 * someone who is offline.  Let's inform the user */
+			char *msg;
 
-		/* XXX: for now, send to the first resource available */
-		if(jb->resources != NULL) {
-			char **who_v = g_strsplit(xfer->who, "/", 2);
-			char *who;
+			if(!jb) {
+				msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), xfer->who);
+			} else if(jb->subscription & JABBER_SUB_TO) {
+				msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), xfer->who);
+			} else {
+				msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), xfer->who);
+			}
+
+			purple_notify_error(jsx->js->gc, _("File Send Failed"), _("File Send Failed"), msg);
+			g_free(msg);
+		} else if(g_list_length(jb->resources) == 1) {
+			/* only 1 resource online (probably our most common case)
+			 * so no need to ask who to send to */
+			jbr = jb->resources->data;
+
+			do_transfer_send(xfer, jbr->name);
 
-			jbr = jabber_buddy_find_resource(jb, NULL);
-			who = g_strdup_printf("%s/%s", who_v[0], jbr->name);
-			g_strfreev(who_v);
-			g_free(xfer->who);
-			xfer->who = who;
-			jabber_disco_info_do(jsx->js, who,
-					jabber_si_xfer_send_disco_cb, xfer);
 		} else {
-			return; /* XXX: ick */
+			/* we've got multiple resources, we need to pick one to send to */
+			GList *l;
+			char *msg = g_strdup_printf(_("Please select which resource of %s you would like to send a file to"), xfer->who);
+			PurpleRequestFields *fields = purple_request_fields_new();
+			PurpleRequestField *field = purple_request_field_choice_new("resource", _("Resource"), 0);
+			PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL);
+
+			for(l = jb->resources; l; l = l->next)
+			{
+				jbr = l->data;
+
+				purple_request_field_choice_add(field, jbr->name);
+			}
+
+			purple_request_field_group_add_field(group, field);
+
+			purple_request_fields_add_group(fields, group);
+
+			purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, fields,
+					_("Send File"), G_CALLBACK(resource_select_ok_cb), _("Cancel"), G_CALLBACK(resource_select_cancel_cb),
+					jsx->js->gc->account, xfer->who, NULL, xfer);
+
+			g_free(msg);
 		}
 	} else {
 		xmlnode *si, *feature, *x, *field, *value;
--- a/libpurple/protocols/oscar/family_admin.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_admin.c	Tue May 29 22:21:35 2007 +0000
@@ -125,17 +125,17 @@
 {
 	FlapFrame *fr;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	fr = flap_frame_new(od, 0x02, 10+2+2+strlen(newnick));
 
 	snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0);
 	aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
 
-	aim_tlvlist_add_str(&tl, 0x0001, newnick);
+	aim_tlvlist_add_str(&tlvlist, 0x0001, newnick);
 
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&fr->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, fr);
 
@@ -151,7 +151,7 @@
 aim_admin_changepasswd(OscarData *od, FlapConnection *conn, const char *newpw, const char *curpw)
 {
 	FlapFrame *fr;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 	aim_snacid_t snacid;
 
 	fr = flap_frame_new(od, 0x02, 10+4+strlen(curpw)+4+strlen(newpw));
@@ -160,13 +160,13 @@
 	aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
 
 	/* new password TLV t(0002) */
-	aim_tlvlist_add_str(&tl, 0x0002, newpw);
+	aim_tlvlist_add_str(&tlvlist, 0x0002, newpw);
 
 	/* current password TLV t(0012) */
-	aim_tlvlist_add_str(&tl, 0x0012, curpw);
+	aim_tlvlist_add_str(&tlvlist, 0x0012, curpw);
 
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&fr->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, fr);
 
@@ -182,17 +182,17 @@
 {
 	FlapFrame *fr;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	fr = flap_frame_new(od, 0x02, 10+2+2+strlen(newemail));
 
 	snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0);
 	aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
 
-	aim_tlvlist_add_str(&tl, 0x0011, newemail);
+	aim_tlvlist_add_str(&tlvlist, 0x0011, newemail);
 
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&fr->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, fr);
 
@@ -223,17 +223,17 @@
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	guint16 status;
-	/* aim_tlvlist_t *tl; */
+	/* GSList *tlvlist; */
 
 	status = byte_stream_get16(bs);
 	/* Status is 0x0013 if unable to confirm at this time */
 
-	/* tl = aim_tlvlist_read(bs); */
+	/* tlvlist = aim_tlvlist_read(bs); */
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, status);
 
-	/* aim_tlvlist_free(&tl); */
+	/* aim_tlvlist_free(tlvlist); */
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_alert.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_alert.c	Tue May 29 22:21:35 2007 +0000
@@ -98,7 +98,7 @@
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	struct aim_emailinfo *new;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	guint8 *cookie8, *cookie16;
 	int tmp, havenewmail = 0; /* Used to tell the client we have _new_ mail */
 
@@ -152,7 +152,7 @@
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, new, havenewmail, alertitle, (alerturl ? alerturl + 2 : NULL));
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	g_free(alertitle);
 	g_free(alerturl);
--- a/libpurple/protocols/oscar/family_auth.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_auth.c	Tue May 29 22:21:35 2007 +0000
@@ -129,7 +129,7 @@
 goddamnicq2(OscarData *od, FlapConnection *conn, const char *sn, const char *password, ClientInfo *ci)
 {
 	FlapFrame *frame;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 	int passwdlen;
 	guint8 *password_encoded;
 
@@ -143,24 +143,24 @@
 	aim_encode_password(password, password_encoded);
 
 	byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
-	aim_tlvlist_add_str(&tl, 0x0001, sn);
-	aim_tlvlist_add_raw(&tl, 0x0002, passwdlen, password_encoded);
+	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
+	aim_tlvlist_add_raw(&tlvlist, 0x0002, passwdlen, password_encoded);
 
 	if (ci->clientstring)
-		aim_tlvlist_add_str(&tl, 0x0003, ci->clientstring);
-	aim_tlvlist_add_16(&tl, 0x0016, (guint16)ci->clientid);
-	aim_tlvlist_add_16(&tl, 0x0017, (guint16)ci->major);
-	aim_tlvlist_add_16(&tl, 0x0018, (guint16)ci->minor);
-	aim_tlvlist_add_16(&tl, 0x0019, (guint16)ci->point);
-	aim_tlvlist_add_16(&tl, 0x001a, (guint16)ci->build);
-	aim_tlvlist_add_32(&tl, 0x0014, (guint32)ci->distrib); /* distribution chan */
-	aim_tlvlist_add_str(&tl, 0x000f, ci->lang);
-	aim_tlvlist_add_str(&tl, 0x000e, ci->country);
+		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->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, (guint32)ci->distrib); /* distribution chan */
+	aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
+	aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);
 
-	aim_tlvlist_write(&frame->data, &tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
 
 	g_free(password_encoded);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -201,7 +201,7 @@
 aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key)
 {
 	FlapFrame *frame;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 	guint8 digest[16];
 	aim_snacid_t snacid;
 	size_t password_len;
@@ -220,7 +220,7 @@
 	snacid = aim_cachesnac(od, 0x0017, 0x0002, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x0017, 0x0002, 0x0000, snacid);
 
-	aim_tlvlist_add_str(&tl, 0x0001, sn);
+	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
 
 	/* Truncate ICQ and AOL passwords, if necessary */
 	password_len = strlen(password);
@@ -231,32 +231,32 @@
 
 	aim_encode_password_md5(password, password_len, key, digest);
 
-	aim_tlvlist_add_raw(&tl, 0x0025, 16, digest);
+	aim_tlvlist_add_raw(&tlvlist, 0x0025, 16, digest);
 
 #ifndef USE_OLD_MD5
-	aim_tlvlist_add_noval(&tl, 0x004c);
+	aim_tlvlist_add_noval(&tlvlist, 0x004c);
 #endif
 
 	if (ci->clientstring)
-		aim_tlvlist_add_str(&tl, 0x0003, ci->clientstring);
-	aim_tlvlist_add_16(&tl, 0x0016, (guint16)ci->clientid);
-	aim_tlvlist_add_16(&tl, 0x0017, (guint16)ci->major);
-	aim_tlvlist_add_16(&tl, 0x0018, (guint16)ci->minor);
-	aim_tlvlist_add_16(&tl, 0x0019, (guint16)ci->point);
-	aim_tlvlist_add_16(&tl, 0x001a, (guint16)ci->build);
-	aim_tlvlist_add_32(&tl, 0x0014, (guint32)ci->distrib);
-	aim_tlvlist_add_str(&tl, 0x000f, ci->lang);
-	aim_tlvlist_add_str(&tl, 0x000e, ci->country);
+		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->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, (guint32)ci->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(&tl, 0x004a, 0x01);
+	aim_tlvlist_add_8(&tlvlist, 0x004a, 0x01);
 
-	aim_tlvlist_write(&frame->data, &tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
 
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -274,7 +274,7 @@
 static int
 parse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_rxcallback_t userfunc;
 	struct aim_authresp_info *info;
 	int ret = 0;
@@ -402,7 +402,7 @@
 	if ((userfunc = aim_callhandler(od, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003)))
 		ret = userfunc(od, conn, frame, info);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -471,7 +471,7 @@
 {
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !conn || !sn)
 		return -EINVAL;
@@ -486,16 +486,16 @@
 	snacid = aim_cachesnac(od, 0x0017, 0x0006, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x0017, 0x0006, 0x0000, snacid);
 
-	aim_tlvlist_add_str(&tl, 0x0001, sn);
+	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
 
 	/* Tell the server we support SecurID logins. */
-	aim_tlvlist_add_noval(&tl, 0x004b);
+	aim_tlvlist_add_noval(&tlvlist, 0x004b);
 
 	/* Unknown.  Sent in recent WinAIM clients.*/
-	aim_tlvlist_add_noval(&tl, 0x005a);
+	aim_tlvlist_add_noval(&tlvlist, 0x005a);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -517,7 +517,7 @@
 	int keylen, ret = 1;
 	aim_rxcallback_t userfunc;
 	char *keystr;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	gboolean truncate_pass;
 
 	keylen = byte_stream_get16(bs);
@@ -539,7 +539,7 @@
 		ret = userfunc(od, conn, frame, keystr, (int)truncate_pass);
 
 	g_free(keystr);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_bos.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_bos.c	Tue May 29 22:21:35 2007 +0000
@@ -39,7 +39,7 @@
 static int rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	guint16 maxpermits = 0, maxdenies = 0;
 	int ret = 0;
 
@@ -63,7 +63,7 @@
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, maxpermits, maxdenies);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_buddy.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_buddy.c	Tue May 29 22:21:35 2007 +0000
@@ -47,7 +47,7 @@
 rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	guint16 maxbuddies = 0, maxwatchers = 0;
 	int ret = 0;
 
@@ -82,7 +82,7 @@
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, maxbuddies, maxwatchers);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_chat.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_chat.c	Tue May 29 22:21:35 2007 +0000
@@ -159,7 +159,7 @@
 	char *roomname;
 	struct aim_chat_roominfo roominfo;
 	guint16 tlvcount = 0;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_tlv_t *tlv;
 	char *roomdesc;
 	guint16 flags;
@@ -309,7 +309,7 @@
 	g_free(userinfo);
 	g_free(roomname);
 	g_free(roomdesc);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -357,7 +357,7 @@
 	IcbmCookie *cookie;
 	aim_snacid_t snacid;
 	guint8 ckstr[8];
-	aim_tlvlist_t *tlvlist = NULL, *inner_tlvlist = NULL;
+	GSList *tlvlist = NULL, *inner_tlvlist = NULL;
 
 	if (!od || !conn || !msg || (msglen <= 0))
 		return 0;
@@ -430,8 +430,8 @@
 
 	aim_tlvlist_write(&frame->data, &tlvlist);
 
-	aim_tlvlist_free(&inner_tlvlist);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -471,7 +471,7 @@
 	aim_userinfo_t userinfo;
 	guint8 cookie[8];
 	guint16 channel;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	char *msg = NULL;
 	int len = 0;
 	char *encoding = NULL, *language = NULL;
@@ -536,7 +536,7 @@
 	tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1);
 	if (tlv != NULL)
 	{
-		aim_tlvlist_t *inner_tlvlist;
+		GSList *inner_tlvlist;
 		aim_tlv_t *inner_tlv;
 
 		byte_stream_init(&tbs, tlv->value, tlv->length);
@@ -562,7 +562,7 @@
 		 */
 		language = aim_tlv_getstr(inner_tlvlist, 0x0003, 1);
 
-		aim_tlvlist_free(&inner_tlvlist);
+		aim_tlvlist_free(inner_tlvlist);
 	}
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
@@ -572,7 +572,7 @@
 	g_free(msg);
 	g_free(encoding);
 	g_free(language);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_chatnav.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_chatnav.c	Tue May 29 22:21:35 2007 +0000
@@ -50,7 +50,7 @@
 	static const char charset[] = {"us-ascii"};
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	frame = flap_frame_new(od, 0x02, 1152);
 
@@ -85,15 +85,15 @@
 	/* detail level */
 	byte_stream_put8(&frame->data, 0x01);
 
-	aim_tlvlist_add_str(&tl, 0x00d3, name);
-	aim_tlvlist_add_str(&tl, 0x00d6, charset);
-	aim_tlvlist_add_str(&tl, 0x00d7, lang);
+	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(&frame->data, aim_tlvlist_count(&tl));
-	aim_tlvlist_write(&frame->data, &tl);
+	byte_stream_put16(&frame->data, aim_tlvlist_count(tlvlist));
+	aim_tlvlist_write(&frame->data, &tlvlist);
 
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -109,7 +109,7 @@
 	int curexchange;
 	aim_tlv_t *exchangetlv;
 	guint8 maxrooms = 0;
-	aim_tlvlist_t *tlvlist, *innerlist;
+	GSList *tlvlist, *innerlist;
 
 	tlvlist = aim_tlvlist_read(bs);
 
@@ -290,7 +290,7 @@
 		}
 #endif
 
-		aim_tlvlist_free(&innerlist);
+		aim_tlvlist_free(innerlist);
 	}
 
 	/*
@@ -307,7 +307,7 @@
 		g_free(exchanges[curexchange].lang2);
 	}
 	g_free(exchanges);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -316,7 +316,7 @@
 parseinfo_create(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs, aim_snac_t *snac2)
 {
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist, *innerlist;
+	GSList *tlvlist, *innerlist;
 	char *ck = NULL, *fqcn = NULL, *name = NULL;
 	guint16 exchange = 0, instance = 0, unknown = 0, flags = 0, maxmsglen = 0, maxoccupancy = 0;
 	guint32 createtime = 0;
@@ -330,7 +330,7 @@
 
 	if (!(bigblock = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
 		purple_debug_misc("oscar", "no bigblock in top tlv in create room response\n");
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 		return 0;
 	}
 
@@ -344,7 +344,7 @@
 
 	if (detaillevel != 0x02) {
 		purple_debug_misc("oscar", "unknown detaillevel in create room response (0x%02x)\n", detaillevel);
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 		g_free(ck);
 		return 0;
 	}
@@ -381,8 +381,8 @@
 	g_free(ck);
 	g_free(name);
 	g_free(fqcn);
-	aim_tlvlist_free(&innerlist);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(innerlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_feedbag.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_feedbag.c	Tue May 29 22:21:35 2007 +0000
@@ -110,7 +110,7 @@
  * @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, aim_tlvlist_t *data)
+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;
@@ -214,7 +214,7 @@
 
 	/* Free the removed item */
 	g_free(del->name);
-	aim_tlvlist_free(&del->data);
+	aim_tlvlist_free(del->data);
 	g_free(del);
 
 	return 0;
@@ -610,7 +610,7 @@
 		del = cur;
 		cur = cur->next;
 		g_free(del->name);
-		aim_tlvlist_free(&del->data);
+		aim_tlvlist_free(del->data);
 		g_free(del);
 	}
 
@@ -619,7 +619,7 @@
 		del = cur;
 		cur = cur->next;
 		g_free(del->name);
-		aim_tlvlist_free(&del->data);
+		aim_tlvlist_free(del->data);
 		g_free(del);
 	}
 
@@ -670,7 +670,7 @@
 				aim_ssi_deldeny(od, NULL);
 		} else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(od->ssi.local, cur->gid, 0x0000)))) {
 			char *alias = aim_ssi_getalias(od->ssi.local, NULL, cur->name);
-			aim_ssi_addbuddy(od, cur->name, "orphans", alias, NULL, NULL, 0);
+			aim_ssi_addbuddy(od, cur->name, "orphans", NULL, alias, NULL, NULL, FALSE);
 			aim_ssi_delbuddy(od, cur->name, NULL);
 			g_free(alias);
 		}
@@ -721,15 +721,15 @@
  * @param od The oscar odion.
  * @param name The name of the item.
  * @param group The group of the item.
+ * @param data A TLV list to use as the additional data for this item.
  * @param alias The alias/nickname of the item, or NULL.
  * @param comment The buddy comment for the item, or NULL.
  * @param smsnum The locally assigned SMS number, or NULL.
  * @return Return 0 if no errors, otherwise return the error number.
  */
-int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth)
+int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, GSList *data, const char *alias, const char *comment, const char *smsnum, gboolean needauth)
 {
 	struct aim_ssi_item *parent;
-	aim_tlvlist_t *data = NULL;
 
 	if (!od || !name || !group)
 		return -EINVAL;
@@ -750,16 +750,16 @@
 	/* Create a TLV list for the new buddy */
 	if (needauth)
 		aim_tlvlist_add_noval(&data, 0x0066);
-	if (alias)
+	if (alias != NULL)
 		aim_tlvlist_add_str(&data, 0x0131, alias);
-	if (smsnum)
+	if (smsnum != NULL)
 		aim_tlvlist_add_str(&data, 0x013a, smsnum);
-	if (comment)
+	if (comment != NULL)
 		aim_tlvlist_add_str(&data, 0x013c, comment);
 
 	/* Add that bad boy */
 	aim_ssi_itemlist_add(&od->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data);
-	aim_tlvlist_free(&data);
+	aim_tlvlist_free(data);
 
 	/* Modify the parent group */
 	aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
@@ -920,16 +920,22 @@
  */
 int aim_ssi_movebuddy(OscarData *od, const char *oldgn, const char *newgn, const char *sn)
 {
-	char *alias;
-	gboolean waitingforauth;
+	struct aim_ssi_item *buddy;
+	GSList *data;
+
+	/* Find the buddy */
+	buddy = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, sn, AIM_SSI_TYPE_BUDDY);
+	if (buddy == NULL)
+		return -EINVAL;
 
-	alias = aim_ssi_getalias(od->ssi.local, oldgn, sn);
-	waitingforauth = aim_ssi_waitingforauth(od->ssi.local, oldgn, sn);
+	/* Make a copy of the buddy's TLV list */
+	data = aim_tlvlist_copy(buddy->data);
 
+	/* Delete the old item */
 	aim_ssi_delbuddy(od, sn, oldgn);
-	aim_ssi_addbuddy(od, sn, newgn, alias, NULL, NULL, waitingforauth);
 
-	g_free(alias);
+	/* Add the new item using the EXACT SAME TLV list */
+	aim_ssi_addbuddy(od, sn, newgn, data, NULL, NULL, NULL, FALSE);
 
 	return 0;
 }
@@ -1172,7 +1178,7 @@
 {
 	int ret = 0, i;
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_tlv_t *tlv;
 	ByteStream bstream;
 	guint16 *maxitems;
@@ -1182,7 +1188,7 @@
 
 	/* TLV 0x0004 contains the maximum number of each item */
 	if (!(tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 		return 0;
 	}
 
@@ -1196,7 +1202,7 @@
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, tlv->length/2, maxitems);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 	g_free(maxitems);
 
 	return ret;
@@ -1267,7 +1273,7 @@
 	guint8 fmtver; /* guess */
 	guint16 namelen, gid, bid, type;
 	char *name;
-	aim_tlvlist_t *data;
+	GSList *data;
 
 	fmtver = byte_stream_get8(bs); /* Version of ssi data.  Should be 0x00 */
 	od->ssi.numitems += byte_stream_get16(bs); /* # of items in this SSI SNAC */
@@ -1284,7 +1290,7 @@
 		data = aim_tlvlist_readlen(bs, byte_stream_get16(bs));
 		aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data);
 		g_free(name);
-		aim_tlvlist_free(&data);
+		aim_tlvlist_free(data);
 	}
 
 	/* Read in the timestamp */
@@ -1352,7 +1358,7 @@
 		if (cur->item->name)
 			snaclen += strlen(cur->item->name);
 		if (cur->item->data)
-			snaclen += aim_tlvlist_size(&cur->item->data);
+			snaclen += aim_tlvlist_size(cur->item->data);
 	}
 
 	frame = flap_frame_new(od, 0x02, snaclen);
@@ -1367,7 +1373,7 @@
 		byte_stream_put16(&frame->data, cur->item->gid);
 		byte_stream_put16(&frame->data, cur->item->bid);
 		byte_stream_put16(&frame->data, cur->item->type);
-		byte_stream_put16(&frame->data, cur->item->data ? aim_tlvlist_size(&cur->item->data) : 0);
+		byte_stream_put16(&frame->data, cur->item->data ? aim_tlvlist_size(cur->item->data) : 0);
 		if (cur->item->data)
 			aim_tlvlist_write(&frame->data, &cur->item->data);
 	}
@@ -1389,7 +1395,7 @@
 	aim_rxcallback_t userfunc;
 	char *name;
 	guint16 len, gid, bid, type;
-	aim_tlvlist_t *data;
+	GSList *data;
 
 	while (byte_stream_empty(bs)) {
 		if ((len = byte_stream_get16(bs)))
@@ -1406,7 +1412,7 @@
 
 		aim_ssi_itemlist_add(&od->ssi.local, name, gid, bid, type, data);
 		aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data);
-		aim_tlvlist_free(&data);
+		aim_tlvlist_free(data);
 
 		if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 			ret = userfunc(od, conn, frame, type, name);
@@ -1428,7 +1434,7 @@
 	aim_rxcallback_t userfunc;
 	char *name;
 	guint16 len, gid, bid, type;
-	aim_tlvlist_t *data;
+	GSList *data;
 	struct aim_ssi_item *item;
 
 	while (byte_stream_empty(bs)) {
@@ -1453,7 +1459,7 @@
 				strcpy(item->name, name);
 			} else
 				item->name = NULL;
-			aim_tlvlist_free(&item->data);
+			aim_tlvlist_free(item->data);
 			item->data = aim_tlvlist_copy(data);
 		}
 
@@ -1465,7 +1471,7 @@
 				strcpy(item->name, name);
 			} else
 				item->name = NULL;
-			aim_tlvlist_free(&item->data);
+			aim_tlvlist_free(item->data);
 			item->data = aim_tlvlist_copy(data);
 		}
 
@@ -1473,7 +1479,7 @@
 			ret = userfunc(od, conn, frame);
 
 		g_free(name);
-		aim_tlvlist_free(&data);
+		aim_tlvlist_free(data);
 	}
 
 	return ret;
@@ -1561,7 +1567,7 @@
 							strcpy(cur->item->name, cur1->name);
 						} else
 							cur->item->name = NULL;
-						aim_tlvlist_free(&cur->item->data);
+						aim_tlvlist_free(cur->item->data);
 						cur->item->data = aim_tlvlist_copy(cur1->data);
 					}
 				} else
@@ -1595,7 +1601,7 @@
 							strcpy(cur1->name, cur->item->name);
 						} else
 							cur1->name = NULL;
-						aim_tlvlist_free(&cur1->data);
+						aim_tlvlist_free(cur1->data);
 						cur1->data = aim_tlvlist_copy(cur->item->data);
 					}
 				} else
--- a/libpurple/protocols/oscar/family_icbm.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Tue May 29 22:21:35 2007 +0000
@@ -451,7 +451,7 @@
 	IcbmCookie *msgcookie;
 	struct aim_invite_priv *priv;
 	guchar cookie[8];
-	aim_tlvlist_t *otl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
@@ -498,19 +498,19 @@
 	byte_stream_putraw(&hdrbs, cookie, sizeof(cookie)); /* I think... */
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_CHAT);
 
-	aim_tlvlist_add_16(&itl, 0x000a, 0x0001);
-	aim_tlvlist_add_noval(&itl, 0x000f);
-	aim_tlvlist_add_str(&itl, 0x000c, msg);
-	aim_tlvlist_add_chatroom(&itl, 0x2711, exchange, roomname, instance);
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&otl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+	aim_tlvlist_add_str(&inner_tlvlist, 0x000c, msg);
+	aim_tlvlist_add_chatroom(&inner_tlvlist, 0x2711, exchange, roomname, instance);
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &otl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&otl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -689,7 +689,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
 	od = peer_conn->od;
@@ -705,7 +705,7 @@
 	/* ICBM header */
 	aim_im_puticbm(&frame->data, peer_conn->cookie, 0x0002, peer_conn->sn);
 
-	aim_tlvlist_add_noval(&tl, 0x0003);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
 
 	byte_stream_new(&hdrbs, 64);
 
@@ -714,16 +714,16 @@
 	byte_stream_putcaps(&hdrbs, peer_conn->type);
 
 	/* This TLV means "cancel!" */
-	aim_tlvlist_add_16(&itl, 0x000b, 0x0001);
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000b, 0x0001);
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &tl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -775,7 +775,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
 	conn = flap_connection_findbygroup(od, 0x0004);
@@ -790,7 +790,7 @@
 	/* ICBM header */
 	aim_im_puticbm(&frame->data, cookie, 0x0002, sn);
 
-	aim_tlvlist_add_noval(&tl, 0x0003);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
 
 	byte_stream_new(&hdrbs, 128);
 
@@ -798,20 +798,20 @@
 	byte_stream_putraw(&hdrbs, cookie, 8);
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM);
 
-	aim_tlvlist_add_raw(&itl, 0x0002, 4, ip);
-	aim_tlvlist_add_raw(&itl, 0x0003, 4, ip);
-	aim_tlvlist_add_16(&itl, 0x0005, port);
-	aim_tlvlist_add_16(&itl, 0x000a, requestnumber);
-	aim_tlvlist_add_noval(&itl, 0x000f);
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0005, port);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &tl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -826,7 +826,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 	guint8 ip_comp[4];
 
@@ -842,7 +842,7 @@
 	/* ICBM header */
 	aim_im_puticbm(&frame->data, cookie, 0x0002, sn);
 
-	aim_tlvlist_add_noval(&tl, 0x0003);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
 
 	byte_stream_new(&hdrbs, 128);
 
@@ -850,30 +850,30 @@
 	byte_stream_putraw(&hdrbs, cookie, 8);
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM);
 
-	aim_tlvlist_add_raw(&itl, 0x0002, 4, ip);
-	aim_tlvlist_add_raw(&itl, 0x0003, 4, ip);
-	aim_tlvlist_add_16(&itl, 0x0005, pin);
-	aim_tlvlist_add_16(&itl, 0x000a, requestnumber);
-	aim_tlvlist_add_noval(&itl, 0x000f);
-	aim_tlvlist_add_noval(&itl, 0x0010);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0005, pin);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x0010);
 
 	/* Send the bitwise complement of the port and ip.  As a check? */
 	ip_comp[0] = ~ip[0];
 	ip_comp[1] = ~ip[1];
 	ip_comp[2] = ~ip[2];
 	ip_comp[3] = ~ip[3];
-	aim_tlvlist_add_raw(&itl, 0x0016, 4, ip_comp);
-	aim_tlvlist_add_16(&itl, 0x0017, ~pin);
-
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0016, 4, ip_comp);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0017, ~pin);
+
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &tl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -888,7 +888,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
 	conn = flap_connection_findbygroup(od, 0x0004);
@@ -903,7 +903,7 @@
 	/* ICBM header */
 	aim_im_puticbm(&frame->data, cookie, 0x0002, sn);
 
-	aim_tlvlist_add_noval(&tl, 0x0003);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
 
 	byte_stream_new(&hdrbs, 512);
 
@@ -911,11 +911,11 @@
 	byte_stream_putraw(&hdrbs, cookie, 8);
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE);
 
-	aim_tlvlist_add_raw(&itl, 0x0002, 4, ip);
-	aim_tlvlist_add_raw(&itl, 0x0003, 4, ip);
-	aim_tlvlist_add_16(&itl, 0x0005, port);
-	aim_tlvlist_add_16(&itl, 0x000a, requestnumber);
-	aim_tlvlist_add_noval(&itl, 0x000f);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0005, port);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
 	/* TODO: Send 0x0016 and 0x0017 */
 
 #if 0
@@ -924,9 +924,9 @@
 	 *       redirect for a file receive (same conditions for
 	 *       sending 0x000f above)
 	 */
-	aim_tlvlist_add_raw(&itl, 0x000e, 2, "en");
-	aim_tlvlist_add_raw(&itl, 0x000d, 8, "us-ascii");
-	aim_tlvlist_add_raw(&itl, 0x000c, 24, "Please accept this file.");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000e, 2, "en");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000d, 8, "us-ascii");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000c, 24, "Please accept this file.");
 #endif
 
 	if (filename != NULL)
@@ -943,19 +943,19 @@
 		byte_stream_putstr(&bs, filename);
 		byte_stream_put8(&bs, 0x00);
 
-		aim_tlvlist_add_raw(&itl, 0x2711, bs.len, bs.data);
+		aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, bs.len, bs.data);
 		g_free(bs.data);
 		/* End TLV t(2711) */
 	}
 
-	aim_tlvlist_write(&hdrbs, &itl);
-	aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &tl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -970,7 +970,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 	guint8 ip_comp[4];
 
@@ -986,7 +986,7 @@
 	/* ICBM header */
 	aim_im_puticbm(&frame->data, cookie, 0x0002, sn);
 
-	aim_tlvlist_add_noval(&tl, 0x0003);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
 
 	byte_stream_new(&hdrbs, 512);
 
@@ -994,20 +994,20 @@
 	byte_stream_putraw(&hdrbs, cookie, 8);
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE);
 
-	aim_tlvlist_add_raw(&itl, 0x0002, 4, ip);
-	aim_tlvlist_add_raw(&itl, 0x0003, 4, ip);
-	aim_tlvlist_add_16(&itl, 0x0005, pin);
-	aim_tlvlist_add_16(&itl, 0x000a, requestnumber);
-	aim_tlvlist_add_noval(&itl, 0x000f);
-	aim_tlvlist_add_noval(&itl, 0x0010);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0005, pin);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x0010);
 
 	/* Send the bitwise complement of the port and ip.  As a check? */
 	ip_comp[0] = ~ip[0];
 	ip_comp[1] = ~ip[1];
 	ip_comp[2] = ~ip[2];
 	ip_comp[3] = ~ip[3];
-	aim_tlvlist_add_raw(&itl, 0x0016, 4, ip_comp);
-	aim_tlvlist_add_16(&itl, 0x0017, ~pin);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0016, 4, ip_comp);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0017, ~pin);
 
 #if 0
 	/* TODO: If the following is ever enabled, ensure that it is
@@ -1015,9 +1015,9 @@
 	 *       redirect for a file receive (same conditions for
 	 *       sending 0x000f above)
 	 */
-	aim_tlvlist_add_raw(&itl, 0x000e, 2, "en");
-	aim_tlvlist_add_raw(&itl, 0x000d, 8, "us-ascii");
-	aim_tlvlist_add_raw(&itl, 0x000c, 24, "Please accept this file.");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000e, 2, "en");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000d, 8, "us-ascii");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000c, 24, "Please accept this file.");
 #endif
 
 	if (filename != NULL)
@@ -1034,20 +1034,20 @@
 		byte_stream_putstr(&bs, filename);
 		byte_stream_put8(&bs, 0x00);
 
-		aim_tlvlist_add_raw(&itl, 0x2711, bs.len, bs.data);
+		aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, bs.len, bs.data);
 		g_free(bs.data);
 		/* End TLV t(2711) */
 	}
 
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &tl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -1226,7 +1226,7 @@
 	aim_rxcallback_t userfunc;
 	guchar cookie[8];
 	guint16 channel;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	char *sn;
 	int snlen;
 	guint16 icbmflags = 0;
@@ -1281,7 +1281,7 @@
 
 	g_free(sn);
 	g_free(msg);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -1874,11 +1874,11 @@
 
 typedef void (*ch2_args_destructor_t)(OscarData *od, IcbmArgsCh2 *args);
 
-static int incomingim_ch2(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie)
+static int incomingim_ch2(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, GSList *tlvlist, guint8 *cookie)
 {
 	aim_rxcallback_t userfunc;
 	aim_tlv_t *block1, *servdatatlv;
-	aim_tlvlist_t *list2;
+	GSList *list2;
 	aim_tlv_t *tlv;
 	IcbmArgsCh2 args;
 	ByteStream bbs, sdbs, *sdbsptr = NULL;
@@ -2078,12 +2078,12 @@
 	g_free((char *)args.encoding);
 	g_free((char *)args.language);
 
-	aim_tlvlist_free(&list2);
+	aim_tlvlist_free(list2);
 
 	return ret;
 }
 
-static int incomingim_ch4(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie)
+static int incomingim_ch4(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, GSList *tlvlist, guint8 *cookie)
 {
 	ByteStream meat;
 	aim_rxcallback_t userfunc;
@@ -2186,7 +2186,7 @@
 		ret = incomingim_ch1(od, conn, mod, frame, snac, channel, &userinfo, bs, cookie);
 
 	} else if (channel == 2) {
-		aim_tlvlist_t *tlvlist;
+		GSList *tlvlist;
 
 		/*
 		 * Read block of TLVs (not including the userinfo data).  All
@@ -2196,14 +2196,14 @@
 
 		ret = incomingim_ch2(od, conn, mod, frame, snac, channel, &userinfo, tlvlist, cookie);
 
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 
 	} else if (channel == 4) {
-		aim_tlvlist_t *tlvlist;
+		GSList *tlvlist;
 
 		tlvlist = aim_tlvlist_read(bs);
 		ret = incomingim_ch4(od, conn, mod, frame, snac, channel, &userinfo, tlvlist, cookie);
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 
 	} else {
 		purple_debug_misc("oscar", "icbm: ICBM received on an unsupported channel.  Ignoring.  (chan = %04x)\n", channel);
@@ -2284,7 +2284,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
 		return -EINVAL;
@@ -2300,9 +2300,9 @@
 	byte_stream_put8(&frame->data, strlen(sn));
 	byte_stream_putstr(&frame->data, sn);
 
-	aim_tlvlist_add_16(&tl, 0x0003, code);
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_add_16(&tlvlist, 0x0003, code);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
--- a/libpurple/protocols/oscar/family_icq.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_icq.c	Tue May 29 22:21:35 2007 +0000
@@ -474,14 +474,14 @@
 icqresponse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	int ret = 0;
-	aim_tlvlist_t *tl;
+	GSList *tlvlist;
 	aim_tlv_t *datatlv;
 	ByteStream qbs;
 	guint32 ouruin;
 	guint16 cmdlen, cmd, reqid;
 
-	if (!(tl = aim_tlvlist_read(bs)) || !(datatlv = aim_tlv_gettlv(tl, 0x0001, 1))) {
-		aim_tlvlist_free(&tl);
+	if (!(tlvlist = aim_tlvlist_read(bs)) || !(datatlv = aim_tlv_gettlv(tlvlist, 0x0001, 1))) {
+		aim_tlvlist_free(tlvlist);
 		purple_debug_misc("oscar", "corrupt ICQ response\n");
 		return 0;
 	}
@@ -661,7 +661,7 @@
 		}
 	}
 
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_locate.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_locate.c	Tue May 29 22:21:35 2007 +0000
@@ -930,7 +930,7 @@
 int
 aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info)
 {
-	aim_tlvlist_t *tlvlist = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!bs || !info)
 		return -EINVAL;
@@ -965,9 +965,9 @@
 	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));
+	byte_stream_put16(bs, aim_tlvlist_count(tlvlist));
 	aim_tlvlist_write(bs, &tlvlist);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return 0;
 }
@@ -1050,7 +1050,7 @@
 static int
 rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_rxcallback_t userfunc;
 	int ret = 0;
 	guint16 maxsiglen = 0;
@@ -1063,7 +1063,7 @@
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, maxsiglen);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -1096,7 +1096,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 	char *encoding;
 	static const char defencoding[] = {"text/aolrtf; charset=\"%s\""};
 
@@ -1115,8 +1115,8 @@
 		/* 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(&tl, 0x0001, encoding);
-		aim_tlvlist_add_raw(&tl, 0x0002, profile_len, (const guchar *)profile);
+		aim_tlvlist_add_str(&tlvlist, 0x0001, encoding);
+		aim_tlvlist_add_raw(&tlvlist, 0x0002, profile_len, (const guchar *)profile);
 		g_free(encoding);
 	}
 
@@ -1132,20 +1132,20 @@
 		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(&tl, 0x0003, encoding);
-			aim_tlvlist_add_raw(&tl, 0x0004, awaymsg_len, (const guchar *)awaymsg);
+			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(&tl, 0x0004);
+			aim_tlvlist_add_noval(&tlvlist, 0x0004);
 	}
 
-	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(&tl));
+	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, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -1161,20 +1161,20 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
 		return -EINVAL;
 
-	aim_tlvlist_add_caps(&tl, 0x0005, caps);
+	aim_tlvlist_add_caps(&tlvlist, 0x0005, caps);
 
-	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(&tl));
+	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, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -1221,7 +1221,7 @@
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	aim_userinfo_t *userinfo, *userinfo2;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_tlv_t *tlv = NULL;
 	int was_explicit;
 
@@ -1252,7 +1252,7 @@
 		userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length);
 		userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES;
 	}
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	aim_locate_adduserinfo(od, userinfo);
 	userinfo2 = aim_locate_finduserinfo(od, userinfo->sn);
@@ -1284,42 +1284,42 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
 		return -EINVAL;
 
-	aim_tlvlist_add_16(&tl, 0x000a, privacy);
+	aim_tlvlist_add_16(&tlvlist, 0x000a, privacy);
 
 	if (first)
-		aim_tlvlist_add_str(&tl, 0x0001, first);
+		aim_tlvlist_add_str(&tlvlist, 0x0001, first);
 	if (last)
-		aim_tlvlist_add_str(&tl, 0x0002, last);
+		aim_tlvlist_add_str(&tlvlist, 0x0002, last);
 	if (middle)
-		aim_tlvlist_add_str(&tl, 0x0003, middle);
+		aim_tlvlist_add_str(&tlvlist, 0x0003, middle);
 	if (maiden)
-		aim_tlvlist_add_str(&tl, 0x0004, maiden);
+		aim_tlvlist_add_str(&tlvlist, 0x0004, maiden);
 
 	if (state)
-		aim_tlvlist_add_str(&tl, 0x0007, state);
+		aim_tlvlist_add_str(&tlvlist, 0x0007, state);
 	if (city)
-		aim_tlvlist_add_str(&tl, 0x0008, city);
+		aim_tlvlist_add_str(&tlvlist, 0x0008, city);
 
 	if (nickname)
-		aim_tlvlist_add_str(&tl, 0x000c, nickname);
+		aim_tlvlist_add_str(&tlvlist, 0x000c, nickname);
 	if (zip)
-		aim_tlvlist_add_str(&tl, 0x000d, zip);
+		aim_tlvlist_add_str(&tlvlist, 0x000d, zip);
 
 	if (street)
-		aim_tlvlist_add_str(&tl, 0x0021, street);
+		aim_tlvlist_add_str(&tlvlist, 0x0021, street);
 
-	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));
 
 	snacid = aim_cachesnac(od, 0x0002, 0x0009, 0x0000, NULL, 0);
 
 	aim_putsnac(&frame->data, 0x0002, 0x0009, 0x0000, snacid);
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -1365,32 +1365,32 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
 		return -EINVAL;
 
 	/* ?? privacy ?? */
-	aim_tlvlist_add_16(&tl, 0x000a, privacy);
+	aim_tlvlist_add_16(&tlvlist, 0x000a, privacy);
 
 	if (interest1)
-		aim_tlvlist_add_str(&tl, 0x0000b, interest1);
+		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest1);
 	if (interest2)
-		aim_tlvlist_add_str(&tl, 0x0000b, interest2);
+		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest2);
 	if (interest3)
-		aim_tlvlist_add_str(&tl, 0x0000b, interest3);
+		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest3);
 	if (interest4)
-		aim_tlvlist_add_str(&tl, 0x0000b, interest4);
+		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest4);
 	if (interest5)
-		aim_tlvlist_add_str(&tl, 0x0000b, interest5);
+		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest5);
 
-	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl));
+	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, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
--- a/libpurple/protocols/oscar/family_odir.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_odir.c	Tue May 29 22:21:35 2007 +0000
@@ -43,22 +43,22 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region || !email)
 		return -EINVAL;
 
 	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
-	aim_tlvlist_add_str(&tl, 0x001c, region);
-	aim_tlvlist_add_16(&tl, 0x000a, 0x0001); /* Type of search */
-	aim_tlvlist_add_str(&tl, 0x0005, email);
+	aim_tlvlist_add_str(&tlvlist, 0x001c, region);
+	aim_tlvlist_add_16(&tlvlist, 0x000a, 0x0001); /* Type of search */
+	aim_tlvlist_add_str(&tlvlist, 0x0005, email);
 
-	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));
 	snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x000f, 0x0002, 0x0000, snacid);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -91,41 +91,41 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region)
 		return -EINVAL;
 
 	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
-	aim_tlvlist_add_str(&tl, 0x001c, region);
-	aim_tlvlist_add_16(&tl, 0x000a, 0x0000); /* Type of search */
+	aim_tlvlist_add_str(&tlvlist, 0x001c, region);
+	aim_tlvlist_add_16(&tlvlist, 0x000a, 0x0000); /* Type of search */
 	if (first)
-		aim_tlvlist_add_str(&tl, 0x0001, first);
+		aim_tlvlist_add_str(&tlvlist, 0x0001, first);
 	if (last)
-		aim_tlvlist_add_str(&tl, 0x0002, last);
+		aim_tlvlist_add_str(&tlvlist, 0x0002, last);
 	if (middle)
-		aim_tlvlist_add_str(&tl, 0x0003, middle);
+		aim_tlvlist_add_str(&tlvlist, 0x0003, middle);
 	if (maiden)
-		aim_tlvlist_add_str(&tl, 0x0004, maiden);
+		aim_tlvlist_add_str(&tlvlist, 0x0004, maiden);
 	if (country)
-		aim_tlvlist_add_str(&tl, 0x0006, country);
+		aim_tlvlist_add_str(&tlvlist, 0x0006, country);
 	if (state)
-		aim_tlvlist_add_str(&tl, 0x0007, state);
+		aim_tlvlist_add_str(&tlvlist, 0x0007, state);
 	if (city)
-		aim_tlvlist_add_str(&tl, 0x0008, city);
+		aim_tlvlist_add_str(&tlvlist, 0x0008, city);
 	if (nick)
-		aim_tlvlist_add_str(&tl, 0x000c, nick);
+		aim_tlvlist_add_str(&tlvlist, 0x000c, nick);
 	if (zip)
-		aim_tlvlist_add_str(&tl, 0x000d, zip);
+		aim_tlvlist_add_str(&tlvlist, 0x000d, zip);
 	if (address)
-		aim_tlvlist_add_str(&tl, 0x0021, address);
+		aim_tlvlist_add_str(&tlvlist, 0x0021, address);
 
-	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));
 	snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x000f, 0x0002, 0x0000, snacid);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -145,23 +145,23 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region)
 		return -EINVAL;
 
 	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
-	aim_tlvlist_add_str(&tl, 0x001c, region);
-	aim_tlvlist_add_16(&tl, 0x000a, 0x0001); /* Type of search */
+	aim_tlvlist_add_str(&tlvlist, 0x001c, region);
+	aim_tlvlist_add_16(&tlvlist, 0x000a, 0x0001); /* Type of search */
 	if (interest)
-		aim_tlvlist_add_str(&tl, 0x0001, interest);
+		aim_tlvlist_add_str(&tlvlist, 0x0001, interest);
 
-	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));
 	snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x000f, 0x0002, 0x0000, snacid);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -189,22 +189,22 @@
 	/* Allocate a linked list, 1 node per result */
 	while (numresults) {
 		struct aim_odir *new;
-		aim_tlvlist_t *tl = aim_tlvlist_readnum(bs, byte_stream_get16(bs));
+		GSList *tlvlist = aim_tlvlist_readnum(bs, byte_stream_get16(bs));
 		new = (struct aim_odir *)g_malloc(sizeof(struct aim_odir));
-		new->first = aim_tlv_getstr(tl, 0x0001, 1);
-		new->last = aim_tlv_getstr(tl, 0x0002, 1);
-		new->middle = aim_tlv_getstr(tl, 0x0003, 1);
-		new->maiden = aim_tlv_getstr(tl, 0x0004, 1);
-		new->email = aim_tlv_getstr(tl, 0x0005, 1);
-		new->country = aim_tlv_getstr(tl, 0x0006, 1);
-		new->state = aim_tlv_getstr(tl, 0x0007, 1);
-		new->city = aim_tlv_getstr(tl, 0x0008, 1);
-		new->sn = aim_tlv_getstr(tl, 0x0009, 1);
-		new->interest = aim_tlv_getstr(tl, 0x000b, 1);
-		new->nick = aim_tlv_getstr(tl, 0x000c, 1);
-		new->zip = aim_tlv_getstr(tl, 0x000d, 1);
-		new->region = aim_tlv_getstr(tl, 0x001c, 1);
-		new->address = aim_tlv_getstr(tl, 0x0021, 1);
+		new->first = aim_tlv_getstr(tlvlist, 0x0001, 1);
+		new->last = aim_tlv_getstr(tlvlist, 0x0002, 1);
+		new->middle = aim_tlv_getstr(tlvlist, 0x0003, 1);
+		new->maiden = aim_tlv_getstr(tlvlist, 0x0004, 1);
+		new->email = aim_tlv_getstr(tlvlist, 0x0005, 1);
+		new->country = aim_tlv_getstr(tlvlist, 0x0006, 1);
+		new->state = aim_tlv_getstr(tlvlist, 0x0007, 1);
+		new->city = aim_tlv_getstr(tlvlist, 0x0008, 1);
+		new->sn = aim_tlv_getstr(tlvlist, 0x0009, 1);
+		new->interest = aim_tlv_getstr(tlvlist, 0x000b, 1);
+		new->nick = aim_tlv_getstr(tlvlist, 0x000c, 1);
+		new->zip = aim_tlv_getstr(tlvlist, 0x000d, 1);
+		new->region = aim_tlv_getstr(tlvlist, 0x001c, 1);
+		new->address = aim_tlv_getstr(tlvlist, 0x0021, 1);
 		new->next = results;
 		results = new;
 		numresults--;
--- a/libpurple/protocols/oscar/family_oservice.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_oservice.c	Tue May 29 22:21:35 2007 +0000
@@ -123,7 +123,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 	struct chatsnacinfo csi;
 
 	conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
@@ -145,9 +145,9 @@
 	 */
 	byte_stream_put16(&frame->data, 0x000e);
 
-	aim_tlvlist_add_chatroom(&tl, 0x0001, exchange, roomname, instance);
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_add_chatroom(&tlvlist, 0x0001, exchange, roomname, instance);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -160,7 +160,7 @@
 {
 	struct aim_redirect_data redir;
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_snac_t *origsnac = NULL;
 	int ret = 0;
 
@@ -171,7 +171,7 @@
 	if (!aim_tlv_gettlv(tlvlist, 0x000d, 1) ||
 			!aim_tlv_gettlv(tlvlist, 0x0005, 1) ||
 			!aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 		return 0;
 	}
 
@@ -201,7 +201,7 @@
 		g_free(origsnac->data);
 	g_free(origsnac);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -606,7 +606,7 @@
 	aim_rxcallback_t userfunc;
 	int ret = 0;
 	guint16 groupcount, i;
-	aim_tlvlist_t *tl;
+	GSList *tlvlist;
 	char *ip = NULL;
 	aim_tlv_t *cktlv;
 
@@ -630,17 +630,17 @@
 		purple_debug_misc("oscar", "bifurcated migration unsupported -- group 0x%04x\n", group);
 	}
 
-	tl = aim_tlvlist_read(bs);
+	tlvlist = aim_tlvlist_read(bs);
 
-	if (aim_tlv_gettlv(tl, 0x0005, 1))
-		ip = aim_tlv_getstr(tl, 0x0005, 1);
+	if (aim_tlv_gettlv(tlvlist, 0x0005, 1))
+		ip = aim_tlv_getstr(tlvlist, 0x0005, 1);
 
-	cktlv = aim_tlv_gettlv(tl, 0x0006, 1);
+	cktlv = aim_tlv_gettlv(tlvlist, 0x0006, 1);
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, ip, cktlv ? cktlv->value : NULL);
 
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 	g_free(ip);
 
 	return ret;
@@ -653,7 +653,7 @@
 	aim_rxcallback_t userfunc;
 	char *msg = NULL;
 	int ret = 0;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	guint16 id;
 
 	/*
@@ -681,7 +681,7 @@
 
 	g_free(msg);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -805,24 +805,24 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
 		return -EINVAL;
 
 	if (seticqstatus)
 	{
-		aim_tlvlist_add_32(&tl, 0x0006, icqstatus |
+		aim_tlvlist_add_32(&tlvlist, 0x0006, icqstatus |
 				AIM_ICQ_STATE_HIDEIP | AIM_ICQ_STATE_DIRECTREQUIREAUTH);
 	}
 
 #if 0
 	if (other_stuff_that_isnt_implemented)
 	{
-		aim_tlvlist_add_raw(&tl, 0x000c, 0x0025,
+		aim_tlvlist_add_raw(&tlvlist, 0x000c, 0x0025,
 				chunk_of_x25_bytes_with_ip_address_etc);
-		aim_tlvlist_add_raw(&tl, 0x0011, 0x0005, unknown 0x01 61 10 f6 41);
-		aim_tlvlist_add_16(&tl, 0x0012, unknown 0x00 00);
+		aim_tlvlist_add_raw(&tlvlist, 0x0011, 0x0005, unknown 0x01 61 10 f6 41);
+		aim_tlvlist_add_16(&tlvlist, 0x0012, unknown 0x00 00);
 	}
 #endif
 
@@ -851,18 +851,18 @@
 			byte_stream_putstr(&tmpbs, itmsurl);
 		byte_stream_put16(&tmpbs, 0x0000);
 
-		aim_tlvlist_add_raw(&tl, 0x001d,
+		aim_tlvlist_add_raw(&tlvlist, 0x001d,
 				byte_stream_curpos(&tmpbs), tmpbs.data);
 		g_free(tmpbs.data);
 	}
 
-	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(tlvlist));
 
 	snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x0001, 0x001e, 0x0000, snacid);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -913,14 +913,14 @@
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	guint32 offset, len;
-	aim_tlvlist_t *list;
+	GSList *tlvlist;
 	char *modname;
 
 	offset = byte_stream_get32(bs);
 	len = byte_stream_get32(bs);
-	list = aim_tlvlist_read(bs);
+	tlvlist = aim_tlvlist_read(bs);
 
-	modname = aim_tlv_getstr(list, 0x0001, 1);
+	modname = aim_tlv_getstr(tlvlist, 0x0001, 1);
 
 	purple_debug_info("oscar", "Got memory request for data at 0x%08lx (%d bytes) of requested %s\n", offset, len, modname ? modname : "aim.exe");
 
@@ -928,7 +928,7 @@
 		ret = userfunc(od, conn, frame, offset, len, modname);
 
 	g_free(modname);
-	aim_tlvlist_free(&list);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_popup.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_popup.c	Tue May 29 22:21:35 2007 +0000
@@ -37,23 +37,23 @@
 parsepopup(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tl;
+	GSList *tlvlist;
 	int ret = 0;
 	char *msg, *url;
 	guint16 width, height, delay;
 
-	tl = aim_tlvlist_read(bs);
+	tlvlist = aim_tlvlist_read(bs);
 
-	msg = aim_tlv_getstr(tl, 0x0001, 1);
-	url = aim_tlv_getstr(tl, 0x0002, 1);
-	width = aim_tlv_get16(tl, 0x0003, 1);
-	height = aim_tlv_get16(tl, 0x0004, 1);
-	delay = aim_tlv_get16(tl, 0x0005, 1);
+	msg = aim_tlv_getstr(tlvlist, 0x0001, 1);
+	url = aim_tlv_getstr(tlvlist, 0x0002, 1);
+	width = aim_tlv_get16(tlvlist, 0x0003, 1);
+	height = aim_tlv_get16(tlvlist, 0x0004, 1);
+	delay = aim_tlv_get16(tlvlist, 0x0005, 1);
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, msg, url, width, height, delay);
 
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 	g_free(msg);
 	g_free(url);
 
--- a/libpurple/protocols/oscar/family_userlookup.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/family_userlookup.c	Tue May 29 22:21:35 2007 +0000
@@ -89,7 +89,7 @@
 static int reply(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	int j = 0, m, ret = 0;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	char *cur = NULL, *buf = NULL;
 	aim_rxcallback_t userfunc;
 	aim_snac_t *snac2;
@@ -99,7 +99,7 @@
 		searchaddr = (const char *)snac2->data;
 
 	tlvlist = aim_tlvlist_read(bs);
-	m = aim_tlvlist_count(&tlvlist);
+	m = aim_tlvlist_count(tlvlist);
 
 	/* XXX uhm.
 	 * This is the only place that uses something other than 1 for the 3rd
@@ -116,7 +116,7 @@
 	}
 	g_free(cur);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, searchaddr, j, buf);
--- a/libpurple/protocols/oscar/flap_connection.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/flap_connection.c	Tue May 29 22:21:35 2007 +0000
@@ -61,13 +61,13 @@
 flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy)
 {
 	FlapFrame *frame;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	frame = flap_frame_new(od, 0x01, 4 + 2 + 2 + length);
 	byte_stream_put32(&frame->data, 0x00000001);
-	aim_tlvlist_add_raw(&tl, 0x0006, length, chipsahoy);
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_add_raw(&tlvlist, 0x0006, length, chipsahoy);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -693,7 +693,7 @@
 static void
 parse_flap_ch4(OscarData *od, FlapConnection *conn, FlapFrame *frame)
 {
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	char *msg = NULL;
 	guint16 code = 0;
 	aim_rxcallback_t userfunc;
@@ -721,7 +721,7 @@
 	if ((userfunc = aim_callhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
 		userfunc(od, conn, frame, code, msg);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	g_free(msg);
 }
--- a/libpurple/protocols/oscar/oscar.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Tue May 29 22:21:35 2007 +0000
@@ -2202,7 +2202,7 @@
 				   buddy->name, group->name);
 		aim_ssi_sendauthrequest(od, data->name, msg ? msg : _("Please authorize me so I can add you to my buddy list."));
 		if (!aim_ssi_itemlist_finditem(od->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY))
-			aim_ssi_addbuddy(od, buddy->name, group->name, purple_buddy_get_alias_only(buddy), NULL, NULL, 1);
+			aim_ssi_addbuddy(od, buddy->name, group->name, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, TRUE);
 	}
 }
 
@@ -4592,7 +4592,7 @@
 	if ((od->ssi.received_data) && !(aim_ssi_itemlist_finditem(od->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY))) {
 		purple_debug_info("oscar",
 				   "ssi: adding buddy %s to group %s\n", buddy->name, group->name);
-		aim_ssi_addbuddy(od, buddy->name, group->name, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
+		aim_ssi_addbuddy(od, buddy->name, group->name, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
 	}
 
 	/* XXX - Should this be done from AIM accounts, as well? */
--- a/libpurple/protocols/oscar/oscar.h	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Tue May 29 22:21:35 2007 +0000
@@ -1172,7 +1172,7 @@
 	guint16 gid;
 	guint16 bid;
 	guint16 type;
-	struct aim_tlvlist_s *data;
+	GSList *data;
 	struct aim_ssi_item *next;
 };
 
@@ -1208,7 +1208,7 @@
 gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn);
 
 /* Client functions for changing SSI data */
-int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth);
+int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, GSList *tlvlist, const char *alias, const char *comment, const char *smsnum, gboolean needauth);
 int aim_ssi_addpermit(OscarData *od, const char *name);
 int aim_ssi_adddeny(OscarData *od, const char *name);
 int aim_ssi_delbuddy(OscarData *od, const char *name, const char *group);
@@ -1357,54 +1357,47 @@
 	guint8 *value;
 } aim_tlv_t;
 
-/* TLV List structure */
-typedef struct aim_tlvlist_s
-{
-	aim_tlv_t *tlv;
-	struct aim_tlvlist_s *next;
-} aim_tlvlist_t;
-
 /* TLV handling functions */
 char *aim_tlv_getvalue_as_string(aim_tlv_t *tlv);
 
-aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, guint16 type, const int nth);
-int aim_tlv_getlength(aim_tlvlist_t *list, guint16 type, const int nth);
-char *aim_tlv_getstr(aim_tlvlist_t *list, const guint16 type, const int nth);
-guint8 aim_tlv_get8(aim_tlvlist_t *list, const guint16 type, const int nth);
-guint16 aim_tlv_get16(aim_tlvlist_t *list, const guint16 type, const int nth);
-guint32 aim_tlv_get32(aim_tlvlist_t *list, const guint16 type, const int nth);
+aim_tlv_t *aim_tlv_gettlv(GSList *list, guint16 type, const int nth);
+int aim_tlv_getlength(GSList *list, guint16 type, const int nth);
+char *aim_tlv_getstr(GSList *list, const guint16 type, const int nth);
+guint8 aim_tlv_get8(GSList *list, const guint16 type, const int nth);
+guint16 aim_tlv_get16(GSList *list, const guint16 type, const int nth);
+guint32 aim_tlv_get32(GSList *list, const guint16 type, const int nth);
 
 /* TLV list handling functions */
-aim_tlvlist_t *aim_tlvlist_read(ByteStream *bs);
-aim_tlvlist_t *aim_tlvlist_readnum(ByteStream *bs, guint16 num);
-aim_tlvlist_t *aim_tlvlist_readlen(ByteStream *bs, guint16 len);
-aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig);
+GSList *aim_tlvlist_read(ByteStream *bs);
+GSList *aim_tlvlist_readnum(ByteStream *bs, guint16 num);
+GSList *aim_tlvlist_readlen(ByteStream *bs, guint16 len);
+GSList *aim_tlvlist_copy(GSList *orig);
 
-int aim_tlvlist_count(aim_tlvlist_t **list);
-int aim_tlvlist_size(aim_tlvlist_t **list);
-int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two);
-int aim_tlvlist_write(ByteStream *bs, aim_tlvlist_t **list);
-void aim_tlvlist_free(aim_tlvlist_t **list);
+int aim_tlvlist_count(GSList *list);
+int aim_tlvlist_size(GSList *list);
+int aim_tlvlist_cmp(GSList *one, GSList *two);
+int aim_tlvlist_write(ByteStream *bs, GSList **list);
+void aim_tlvlist_free(GSList *list);
 
-int aim_tlvlist_add_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value);
-int aim_tlvlist_add_noval(aim_tlvlist_t **list, const guint16 type);
-int aim_tlvlist_add_8(aim_tlvlist_t **list, const guint16 type, const guint8 value);
-int aim_tlvlist_add_16(aim_tlvlist_t **list, const guint16 type, const guint16 value);
-int aim_tlvlist_add_32(aim_tlvlist_t **list, const guint16 type, const guint32 value);
-int aim_tlvlist_add_str(aim_tlvlist_t **list, const guint16 type, const char *value);
-int aim_tlvlist_add_caps(aim_tlvlist_t **list, const guint16 type, const guint32 caps);
-int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *userinfo);
-int aim_tlvlist_add_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance);
-int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl);
+int aim_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value);
+int aim_tlvlist_add_noval(GSList **list, const guint16 type);
+int aim_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value);
+int aim_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value);
+int aim_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value);
+int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value);
+int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps);
+int aim_tlvlist_add_userinfo(GSList **list, guint16 type, aim_userinfo_t *userinfo);
+int aim_tlvlist_add_chatroom(GSList **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance);
+int aim_tlvlist_add_frozentlvlist(GSList **list, guint16 type, GSList **tl);
 
-int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const guint16 type, const guint16 lenth, const guint8 *value);
-int aim_tlvlist_replace_str(aim_tlvlist_t **list, const guint16 type, const char *str);
-int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const guint16 type);
-int aim_tlvlist_replace_8(aim_tlvlist_t **list, const guint16 type, const guint8 value);
-int aim_tlvlist_replace_16(aim_tlvlist_t **list, const guint16 type, const guint16 value);
-int aim_tlvlist_replace_32(aim_tlvlist_t **list, const guint16 type, const guint32 value);
+int aim_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 lenth, const guint8 *value);
+int aim_tlvlist_replace_str(GSList **list, const guint16 type, const char *str);
+int aim_tlvlist_replace_noval(GSList **list, const guint16 type);
+int aim_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value);
+int aim_tlvlist_replace_16(GSList **list, const guint16 type, const guint16 value);
+int aim_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value);
 
-void aim_tlvlist_remove(aim_tlvlist_t **list, const guint16 type);
+void aim_tlvlist_remove(GSList **list, const guint16 type);
 
 
 
--- a/libpurple/protocols/oscar/tlv.c	Tue May 29 22:21:02 2007 +0000
+++ b/libpurple/protocols/oscar/tlv.c	Tue May 29 22:21:35 2007 +0000
@@ -18,7 +18,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-
 #include "oscar.h"
 
 static aim_tlv_t *
@@ -35,17 +34,57 @@
 }
 
 static void
-freetlv(aim_tlv_t **oldtlv)
+freetlv(aim_tlv_t *oldtlv)
 {
+	g_free(oldtlv->value);
+	g_free(oldtlv);
+}
 
-	if (!oldtlv || !*oldtlv)
-		return;
+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);
 
-	g_free((*oldtlv)->value);
-	g_free(*oldtlv);
-	*oldtlv = NULL;
+#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;
+	}
 
-	return;
+	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);
 }
 
 /**
@@ -56,7 +95,7 @@
  * 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
+ * TODO: 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 efficient as the in-place TLV parsing used in a couple places
@@ -65,56 +104,17 @@
  * @param bs Input bstream
  * @return Return the TLV chain read
  */
-aim_tlvlist_t *aim_tlvlist_read(ByteStream *bs)
+GSList *aim_tlvlist_read(ByteStream *bs)
 {
-	aim_tlvlist_t *list = NULL, *cur;
+	GSList *list = NULL;
 
 	while (byte_stream_empty(bs) > 0) {
-		guint16 type, length;
-
-		type = byte_stream_get16(bs);
-		length = byte_stream_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
-		 * there's no special cases to this special case.
-		 *   - mid (30jun2000)
-		 */
-		if ((type == 0x0013) && (length != 0x0002))
-			length = 0x0002;
-#else
-		if (0)
-			;
-#endif
-		else {
-
-			if (length > byte_stream_empty(bs)) {
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-
-			cur = g_new0(aim_tlvlist_t, 1);
-			cur->tlv = createtlv(type, length, NULL);
-			if (cur->tlv->length > 0) {
-				cur->tlv->value = byte_stream_getraw(bs, length);
-				if (!cur->tlv->value) {
-					freetlv(&cur->tlv);
-					g_free(cur);
-					aim_tlvlist_free(&list);
-					return NULL;
-				}
-			}
-
-			cur->next = list;
-			list = cur;
-		}
+		list = aim_tlv_read(list, bs);
+		if (list == NULL)
+			return NULL;
 	}
 
-	return list;
+	return g_slist_reverse(list);
 }
 
 /**
@@ -125,7 +125,7 @@
  * 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
+ * TODO: 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 efficient as the in-place TLV parsing used in a couple places
@@ -138,40 +138,18 @@
  *        preceded by the number of TLVs.  So you can limit that with this.
  * @return Return the TLV chain read
  */
-aim_tlvlist_t *aim_tlvlist_readnum(ByteStream *bs, guint16 num)
+GSList *aim_tlvlist_readnum(ByteStream *bs, guint16 num)
 {
-	aim_tlvlist_t *list = NULL, *cur;
+	GSList *list = NULL;
 
 	while ((byte_stream_empty(bs) > 0) && (num != 0)) {
-		guint16 type, length;
-
-		type = byte_stream_get16(bs);
-		length = byte_stream_get16(bs);
-
-		if (length > byte_stream_empty(bs)) {
-			aim_tlvlist_free(&list);
+		list = aim_tlv_read(list, bs);
+		if (list == NULL)
 			return NULL;
-		}
-
-		cur = g_new0(aim_tlvlist_t, 1);
-		cur->tlv = createtlv(type, length, NULL);
-		if (cur->tlv->length > 0) {
-			cur->tlv->value = byte_stream_getraw(bs, length);
-			if (!cur->tlv->value) {
-				freetlv(&cur->tlv);
-				g_free(cur);
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-		}
-
-		if (num > 0)
-			num--;
-		cur->next = list;
-		list = cur;
+		num--;
 	}
 
-	return list;
+	return g_slist_reverse(list);
 }
 
 /**
@@ -182,7 +160,7 @@
  * 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
+ * TODO: 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 efficient as the in-place TLV parsing used in a couple places
@@ -195,39 +173,19 @@
  *        preceded by the length of the TLVs.  So you can limit that with this.
  * @return Return the TLV chain read
  */
-aim_tlvlist_t *aim_tlvlist_readlen(ByteStream *bs, guint16 len)
+GSList *aim_tlvlist_readlen(ByteStream *bs, guint16 len)
 {
-	aim_tlvlist_t *list = NULL, *cur;
+	GSList *list = NULL;
 
 	while ((byte_stream_empty(bs) > 0) && (len > 0)) {
-		guint16 type, length;
-
-		type = byte_stream_get16(bs);
-		length = byte_stream_get16(bs);
-
-		if (length > byte_stream_empty(bs)) {
-			aim_tlvlist_free(&list);
+		list = aim_tlv_read(list, bs);
+		if (list == NULL)
 			return NULL;
-		}
 
-		cur = g_new0(aim_tlvlist_t, 1);
-		cur->tlv = createtlv(type, length, NULL);
-		if (cur->tlv->length > 0) {
-			cur->tlv->value = byte_stream_getraw(bs, length);
-			if (!cur->tlv->value) {
-				freetlv(&cur->tlv);
-				g_free(cur);
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-		}
-
-		len -= aim_tlvlist_size(&cur);
-		cur->next = list;
-		list = cur;
+		len -= 2 + 2 + ((aim_tlv_t *)list->data)->length;
 	}
 
-	return list;
+	return g_slist_reverse(list);
 }
 
 /**
@@ -237,12 +195,14 @@
  * @param orig The TLV chain you want to make a copy of.
  * @return A newly allocated TLV chain.
  */
-aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig)
+GSList *aim_tlvlist_copy(GSList *orig)
 {
-	aim_tlvlist_t *new = NULL;
+	GSList *new = NULL;
+	aim_tlv_t *tlv;
 
-	while (orig) {
-		aim_tlvlist_add_raw(&new, orig->tlv->type, orig->tlv->length, orig->tlv->value);
+	while (orig != NULL) {
+		tlv = orig->data;
+		aim_tlvlist_add_raw(&new, tlv->type, tlv->length, tlv->value);
 		orig = orig->next;
 	}
 
@@ -257,15 +217,15 @@
  * @param two The other TLV chain to compare.
  * @return Return 0 if the lists are the same, return 1 if they are different.
  */
-int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two)
+int aim_tlvlist_cmp(GSList *one, GSList *two)
 {
 	ByteStream bs1, bs2;
 
-	if (aim_tlvlist_size(&one) != aim_tlvlist_size(&two))
+	if (aim_tlvlist_size(one) != aim_tlvlist_size(two))
 		return 1;
 
-	byte_stream_new(&bs1, aim_tlvlist_size(&one));
-	byte_stream_new(&bs2, aim_tlvlist_size(&two));
+	byte_stream_new(&bs1, aim_tlvlist_size(one));
+	byte_stream_new(&bs2, aim_tlvlist_size(two));
 
 	aim_tlvlist_write(&bs1, &one);
 	aim_tlvlist_write(&bs2, &two);
@@ -291,26 +251,13 @@
  *
  * @param list Chain to be freed
  */
-void aim_tlvlist_free(aim_tlvlist_t **list)
+void aim_tlvlist_free(GSList *list)
 {
-	aim_tlvlist_t *cur;
-
-	if (!list || !*list)
-		return;
-
-	for (cur = *list; cur; ) {
-		aim_tlvlist_t *tmp;
-
-		freetlv(&cur->tlv);
-
-		tmp = cur->next;
-		g_free(cur);
-		cur = tmp;
+	while (list != NULL)
+	{
+		freetlv(list->data);
+		list = g_slist_delete_link(list, list);
 	}
-
-	list = NULL;
-
-	return;
 }
 
 /**
@@ -319,15 +266,15 @@
  * @param list Chain to be counted.
  * @return The number of TLVs stored in the passed chain.
  */
-int aim_tlvlist_count(aim_tlvlist_t **list)
+int aim_tlvlist_count(GSList *list)
 {
-	aim_tlvlist_t *cur;
+	GSList *cur;
 	int count;
 
-	if (!list || !*list)
+	if (list == NULL)
 		return 0;
 
-	for (cur = *list, count = 0; cur; cur = cur->next)
+	for (cur = list, count = 0; cur; cur = cur->next)
 		count++;
 
 	return count;
@@ -340,16 +287,16 @@
  * @return The number of bytes that would be needed to
  *         write the passed TLV chain to a data buffer.
  */
-int aim_tlvlist_size(aim_tlvlist_t **list)
+int aim_tlvlist_size(GSList *list)
 {
-	aim_tlvlist_t *cur;
+	GSList *cur;
 	int size;
 
-	if (!list || !*list)
+	if (list == NULL)
 		return 0;
 
-	for (cur = *list, size = 0; cur; cur = cur->next)
-		size += (4 + cur->tlv->length);
+	for (cur = list, size = 0; cur; cur = cur->next)
+		size += (4 + ((aim_tlv_t *)cur->data)->length);
 
 	return size;
 }
@@ -364,27 +311,20 @@
  * @param value String to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value)
+int aim_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value)
 {
-	aim_tlvlist_t *newtlv, *cur;
+	aim_tlv_t *tlv;
 
 	if (list == NULL)
 		return 0;
 
-	newtlv = g_new0(aim_tlvlist_t, 1);
-	newtlv->tlv = createtlv(type, length, NULL);
-	if (newtlv->tlv->length > 0)
-		newtlv->tlv->value = g_memdup(value, length);
+	tlv = createtlv(type, length, NULL);
+	if (tlv->length > 0)
+		tlv->value = g_memdup(value, length);
 
-	if (!*list)
-		*list = newtlv;
-	else {
-		for(cur = *list; cur->next; cur = cur->next)
-			;
-		cur->next = newtlv;
-	}
+	*list = g_slist_append(*list, tlv);
 
-	return newtlv->tlv->length;
+	return tlv->length;
 }
 
 /**
@@ -395,7 +335,7 @@
  * @param value Value to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_8(aim_tlvlist_t **list, const guint16 type, const guint8 value)
+int aim_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value)
 {
 	guint8 v8[1];
 
@@ -412,7 +352,7 @@
  * @param value Value to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_16(aim_tlvlist_t **list, const guint16 type, const guint16 value)
+int aim_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value)
 {
 	guint8 v16[2];
 
@@ -429,7 +369,7 @@
  * @param value Value to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_32(aim_tlvlist_t **list, const guint16 type, const guint32 value)
+int aim_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value)
 {
 	guint8 v32[4];
 
@@ -446,7 +386,7 @@
  * @param value Value to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_str(aim_tlvlist_t **list, const guint16 type, const char *value)
+int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value)
 {
 	return aim_tlvlist_add_raw(list, type, strlen(value), (guint8 *)value);
 }
@@ -467,12 +407,12 @@
  * @param caps Bitfield of capability flags to send
  * @return The size of the value added.
  */
-int aim_tlvlist_add_caps(aim_tlvlist_t **list, const guint16 type, const guint32 caps)
+int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps)
 {
-	guint8 buf[16*16]; /* XXX icky fixed length buffer */
+	guint8 buf[256]; /* TODO: Don't use a fixed length buffer */
 	ByteStream bs;
 
-	if (!caps)
+	if (caps == 0)
 		return 0; /* nothing there anyway */
 
 	byte_stream_init(&bs, buf, sizeof(buf));
@@ -489,9 +429,9 @@
  * @param type TLV type to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *userinfo)
+int aim_tlvlist_add_userinfo(GSList **list, guint16 type, aim_userinfo_t *userinfo)
 {
-	guint8 buf[1024]; /* bleh */
+	guint8 buf[1024]; /* TODO: Don't use a fixed length buffer */
 	ByteStream bs;
 
 	byte_stream_init(&bs, buf, sizeof(buf));
@@ -510,7 +450,7 @@
  * @param instance The instance.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance)
+int aim_tlvlist_add_chatroom(GSList **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance)
 {
 	int len;
 	ByteStream bs;
@@ -536,7 +476,7 @@
  * @param type TLV type to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_noval(aim_tlvlist_t **list, const guint16 type)
+int aim_tlvlist_add_noval(GSList **list, const guint16 type)
 {
 	return aim_tlvlist_add_raw(list, type, 0, NULL);
 }
@@ -546,7 +486,7 @@
  * it is written using this.  Or rather, it can be, but updates won't be
  * made to this.
  *
- * XXX should probably support sublists for real.
+ * TODO: Should probably support sublists for real.
  *
  * This is so neat.
  *
@@ -557,19 +497,19 @@
  *         0 is returned if there was an error or if the destination
  *         TLV chain has length 0.
  */
-int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl)
+int aim_tlvlist_add_frozentlvlist(GSList **list, guint16 type, GSList **tlvlist)
 {
 	int buflen;
 	ByteStream bs;
 
-	buflen = aim_tlvlist_size(tl);
+	buflen = aim_tlvlist_size(*tlvlist);
 
 	if (buflen <= 0)
 		return 0;
 
 	byte_stream_new(&bs, buflen);
 
-	aim_tlvlist_write(&bs, tl);
+	aim_tlvlist_write(&bs, tlvlist);
 
 	aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), bs.data);
 
@@ -589,25 +529,33 @@
  * @param value String to add.
  * @return The length of the TLV.
  */
-int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value)
+int aim_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value)
 {
-	aim_tlvlist_t *cur;
+	GSList *cur;
+	aim_tlv_t *tlv;
 
 	if (list == NULL)
 		return 0;
 
-	for (cur = *list; ((cur != NULL) && (cur->tlv->type != type)); cur = cur->next);
+	for (cur = *list; cur != NULL; cur = cur->next)
+	{
+		tlv = cur->data;
+		if (tlv->type == type)
+			break;
+	}
+
 	if (cur == NULL)
+		/* TLV does not exist, so add a new one */
 		return aim_tlvlist_add_raw(list, type, length, value);
 
-	g_free(cur->tlv->value);
-	cur->tlv->length = length;
-	if (cur->tlv->length > 0) {
-		cur->tlv->value = g_memdup(value, length);
+	g_free(tlv->value);
+	tlv->length = length;
+	if (tlv->length > 0) {
+		tlv->value = g_memdup(value, length);
 	} else
-		cur->tlv->value = NULL;
+		tlv->value = NULL;
 
-	return cur->tlv->length;
+	return tlv->length;
 }
 
 /**
@@ -620,7 +568,7 @@
  * @param str String to add.
  * @return The length of the TLV.
  */
-int aim_tlvlist_replace_str(aim_tlvlist_t **list, const guint16 type, const char *str)
+int aim_tlvlist_replace_str(GSList **list, const guint16 type, const char *str)
 {
 	return aim_tlvlist_replace_raw(list, type, strlen(str), (const guchar *)str);
 }
@@ -634,7 +582,7 @@
  * @param type TLV type.
  * @return The length of the TLV.
  */
-int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const guint16 type)
+int aim_tlvlist_replace_noval(GSList **list, const guint16 type)
 {
 	return aim_tlvlist_replace_raw(list, type, 0, NULL);
 }
@@ -649,7 +597,7 @@
  * @param value 8 bit value to add.
  * @return The length of the TLV.
  */
-int aim_tlvlist_replace_8(aim_tlvlist_t **list, const guint16 type, const guint8 value)
+int aim_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value)
 {
 	guint8 v8[1];
 
@@ -668,7 +616,7 @@
  * @param value 32 bit value to add.
  * @return The length of the TLV.
  */
-int aim_tlvlist_replace_32(aim_tlvlist_t **list, const guint16 type, const guint32 value)
+int aim_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value)
 {
 	guint8 v32[4];
 
@@ -678,36 +626,36 @@
 }
 
 /**
- * Remove a TLV of a given type.  If you attempt to remove a TLV that
- * does not exist, nothing happens.
+ * Remove all TLVs of a given type.  If you attempt to remove a TLV
+ * that does not exist, nothing happens.
  *
  * @param list Desination chain (%NULL pointer if empty).
  * @param type TLV type.
  */
-void aim_tlvlist_remove(aim_tlvlist_t **list, const guint16 type)
+void aim_tlvlist_remove(GSList **list, const guint16 type)
 {
-	aim_tlvlist_t *del;
+	GSList *cur, *next;
+	aim_tlv_t *tlv;
 
-	if (!list || !(*list))
+	if (list == NULL || *list == NULL)
 		return;
 
-	/* Remove the item from the list */
-	if ((*list)->tlv->type == type) {
-		del = *list;
-		*list = (*list)->next;
-	} else {
-		aim_tlvlist_t *cur;
-		for (cur=*list; (cur->next && (cur->next->tlv->type!=type)); cur=cur->next);
-		if (!cur->next)
-			return;
-		del = cur->next;
-		cur->next = del->next;
+	cur = *list;
+	while (cur != NULL)
+	{
+		tlv = cur->data;
+		next = cur->next;
+
+		if (tlv->type == type)
+		{
+			/* Delete this TLV */
+			*list = g_slist_delete_link(*list, cur);
+			g_free(tlv->value);
+			g_free(tlv);
+		}
+
+		cur = next;
 	}
-
-	/* Free the removed item */
-	g_free(del->tlv->value);
-	g_free(del->tlv);
-	g_free(del);
 }
 
 /**
@@ -718,32 +666,34 @@
  * aim_tlvlist_free() must still be called to free up the memory used
  * by the chain structures.
  *
- * XXX clean this up, make better use of bstreams
+ * TODO: Clean this up, make better use of bstreams
  *
  * @param bs Input bstream
  * @param list Source TLV chain
  * @return Return 0 if the destination bstream is too small.
  */
-int aim_tlvlist_write(ByteStream *bs, aim_tlvlist_t **list)
+int aim_tlvlist_write(ByteStream *bs, GSList **list)
 {
 	int goodbuflen;
-	aim_tlvlist_t *cur;
+	GSList *cur;
+	aim_tlv_t *tlv;
 
 	/* do an initial run to test total length */
-	goodbuflen = aim_tlvlist_size(list);
+	goodbuflen = aim_tlvlist_size(*list);
 
 	if (goodbuflen > byte_stream_empty(bs))
 		return 0; /* not enough buffer */
 
 	/* do the real write-out */
 	for (cur = *list; cur; cur = cur->next) {
-		byte_stream_put16(bs, cur->tlv->type);
-		byte_stream_put16(bs, cur->tlv->length);
-		if (cur->tlv->length)
-			byte_stream_putraw(bs, cur->tlv->value, cur->tlv->length);
+		tlv = cur->data;
+		byte_stream_put16(bs, tlv->type);
+		byte_stream_put16(bs, tlv->length);
+		if (tlv->length > 0)
+			byte_stream_putraw(bs, tlv->value, tlv->length);
 	}
 
-	return 1; /* XXX this is a nonsensical return */
+	return 1; /* TODO: This is a nonsensical return */
 }
 
 
@@ -760,17 +710,19 @@
  * @param nth Index of TLV of type to get.
  * @return The TLV you were looking for, or NULL if one could not be found.
  */
-aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, const guint16 type, const int nth)
+aim_tlv_t *aim_tlv_gettlv(GSList *list, const guint16 type, const int nth)
 {
-	aim_tlvlist_t *cur;
+	GSList *cur;
+	aim_tlv_t *tlv;
 	int i;
 
-	for (cur = list, i = 0; cur; cur = cur->next) {
-		if (cur && cur->tlv) {
-			if (cur->tlv->type == type)
+	for (cur = list, i = 0; cur != NULL; cur = cur->next) {
+		tlv = cur->data;
+		if (tlv != NULL) { /* TODO: This NULL check shouldn't be needed */
+			if (tlv->type == type)
 				i++;
 			if (i >= nth)
-				return cur->tlv;
+				return tlv;
 		}
 	}
 
@@ -786,21 +738,15 @@
  * @return The length of the data in this TLV, or -1 if the TLV could not be
  *         found.  Unless -1 is returned, this value will be 2 bytes.
  */
-int aim_tlv_getlength(aim_tlvlist_t *list, const guint16 type, const int nth)
+int aim_tlv_getlength(GSList *list, const guint16 type, const int nth)
 {
-	aim_tlvlist_t *cur;
-	int i;
+	aim_tlv_t *tlv;
 
-	for (cur = list, i = 0; cur; cur = cur->next) {
-		if (cur && cur->tlv) {
-			if (cur->tlv->type == type)
-				i++;
-			if (i >= nth)
-				return cur->tlv->length;
-		}
-	}
+	tlv = aim_tlv_gettlv(list, type, nth);
+	if (tlv == NULL)
+		return -1;
 
-	return -1;
+	return tlv->length;
 }
 
 char *
@@ -825,11 +771,12 @@
  *         not be found.  This is a dynamic buffer and must be freed by the
  *         caller.
  */
-char *aim_tlv_getstr(aim_tlvlist_t *list, const guint16 type, const int nth)
+char *aim_tlv_getstr(GSList *list, const guint16 type, const int nth)
 {
 	aim_tlv_t *tlv;
 
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
+	tlv = aim_tlv_gettlv(list, type, nth);
+	if (tlv == NULL)
 		return NULL;
 
 	return aim_tlv_getvalue_as_string(tlv);
@@ -845,12 +792,14 @@
  * @return The value the TLV you were looking for, or 0 if one could
  *         not be found.
  */
-guint8 aim_tlv_get8(aim_tlvlist_t *list, const guint16 type, const int nth)
+guint8 aim_tlv_get8(GSList *list, const guint16 type, const int nth)
 {
 	aim_tlv_t *tlv;
 
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
+	tlv = aim_tlv_gettlv(list, type, nth);
+	if (tlv == NULL)
 		return 0; /* erm */
+
 	return aimutil_get8(tlv->value);
 }
 
@@ -864,12 +813,14 @@
  * @return The value the TLV you were looking for, or 0 if one could
  *         not be found.
  */
-guint16 aim_tlv_get16(aim_tlvlist_t *list, const guint16 type, const int nth)
+guint16 aim_tlv_get16(GSList *list, const guint16 type, const int nth)
 {
 	aim_tlv_t *tlv;
 
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
+	tlv = aim_tlv_gettlv(list, type, nth);
+	if (tlv == NULL)
 		return 0; /* erm */
+
 	return aimutil_get16(tlv->value);
 }
 
@@ -883,11 +834,13 @@
  * @return The value the TLV you were looking for, or 0 if one could
  *         not be found.
  */
-guint32 aim_tlv_get32(aim_tlvlist_t *list, const guint16 type, const int nth)
+guint32 aim_tlv_get32(GSList *list, const guint16 type, const int nth)
 {
 	aim_tlv_t *tlv;
 
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
+	tlv = aim_tlv_gettlv(list, type, nth);
+	if (tlv == NULL)
 		return 0; /* erm */
+
 	return aimutil_get32(tlv->value);
 }
--- a/pidgin/gtkaccount.c	Tue May 29 22:21:02 2007 +0000
+++ b/pidgin/gtkaccount.c	Tue May 29 22:21:35 2007 +0000
@@ -433,6 +433,7 @@
 
 	/* Screen name */
 	dialog->screenname_entry = gtk_entry_new();
+	g_object_set(G_OBJECT(dialog->screenname_entry), "truncate-multiline", TRUE, NULL);
 
 	add_pref_box(dialog, vbox, _("Screen name:"), dialog->screenname_entry);
 
--- a/pidgin/gtkblist.c	Tue May 29 22:21:02 2007 +0000
+++ b/pidgin/gtkblist.c	Tue May 29 22:21:35 2007 +0000
@@ -488,11 +488,6 @@
 	pidgin_syslog_show();
 }
 
-static void gtk_blist_show_onlinehelp_cb()
-{
-	purple_notify_uri(NULL, PURPLE_WEBSITE "documentation.php");
-}
-
 static void
 do_join_chat(PidginJoinChatData *data)
 {
@@ -2845,6 +2840,7 @@
 	{ N_("/Buddies/Add C_hat..."), NULL, pidgin_blist_add_chat_cb, 0, "<StockItem>", GTK_STOCK_ADD },
 	{ N_("/Buddies/Add _Group..."), NULL, purple_blist_request_add_group, 0, "<StockItem>", GTK_STOCK_ADD },
 	{ "/Buddies/sep3", NULL, NULL, 0, "<Separator>", NULL },
+	{ N_("/Buddies/_About Pidgin"), NULL, pidgin_dialogs_about, 0,  "<Item>", NULL },
 	{ N_("/Buddies/_Quit"), "<CTL>Q", purple_core_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
 
 	/* Accounts menu */
@@ -2861,14 +2857,9 @@
 	{ N_("/Tools/_File Transfers"), "<CTL>T", pidgin_xfer_dialog_show, 0, "<Item>", NULL },
 	{ N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL },
 	{ N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, "<Item>", NULL },
+	{ N_("/Tools/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL },
 	{ "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL },
 	{ N_("/Tools/Mute _Sounds"), "<CTL>S", pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL },
-
-	/* Help */
-	{ N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL },
-	{ N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP },
-	{ N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL },
-	{ N_("/Help/_About"), NULL, pidgin_dialogs_about, 0,  "<Item>", NULL },
 };
 
 /*********************************************************
@@ -3239,7 +3230,7 @@
 				ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_XA,
 						icon_size, "GtkTreeView");
 		else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE))
-			ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_OFFLINE_I,
+			ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_OFFLINE,
 					icon_size, "GtkTreeView");
 		else if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL)
 			ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE_I,
--- a/pidgin/pixmaps/emotes/default/22/theme	Tue May 29 22:21:02 2007 +0000
+++ b/pidgin/pixmaps/emotes/default/22/theme	Tue May 29 22:21:35 2007 +0000
@@ -90,7 +90,7 @@
 good.png            (Y)     (y)
 bad.png             (N)     (n)
 vampire.png         :[      :-[
-#goat.png           (nah)
+goat.png            (nah)
 sun.png             (#)
 rainbow.png         (R)     (r)
 quiet.png           :-#
@@ -122,7 +122,6 @@
 party.png           <:o)
 eyeroll.png         8-)
 yawn.png            |-) 
-goat.png            (nah)
 ! skywalker.png     C:-)    c:-)    C:)     c:)
 ! monkey.png        :-(|)