Index: libfaim/oscar.c
===================================================================
--- libfaim/oscar.c	(revision 07ab1cb58191016aa991b7765fc82ce89bd078c3)
+++ libfaim/oscar.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
@@ -31,4 +31,5 @@
 #include "buddyicon.h"
 #include "conversation.h"
+#include "core.h"
 #include "debug.h"
 #include "ft.h"
@@ -41,13 +42,7 @@
 #include "request.h"
 #include "util.h"
-#include "html.h"
 
 #include "aim.h"
 #include "md5.h"
-
-/* XXX CORE/UI */
-#include "gtkinternal.h"
-#include "gaim.h"
-
 
 #define UC_AOL		0x02
@@ -61,13 +56,16 @@
 #define AIMHASHDATA "http://gaim.sourceforge.net/aim_data.php3"
 
+#define OSCAR_CONNECT_STEPS 6
+
 static GaimPlugin *my_protocol = NULL;
 
-static int caps_aim = AIM_CAPS_CHAT | AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_INTEROPERATE;
-static int caps_icq = AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_ICQUTF8 | AIM_CAPS_INTEROPERATE;
+static int caps_aim = AIM_CAPS_CHAT | AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_INTEROPERATE | AIM_CAPS_ICHAT;
+static int caps_icq = AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_ICQUTF8 | AIM_CAPS_INTEROPERATE | AIM_CAPS_ICHAT;
 
 static fu8_t features_aim[] = {0x01, 0x01, 0x01, 0x02};
 static fu8_t features_icq[] = {0x01, 0x06};
 
-struct oscar_data {
+typedef struct _OscarData OscarData;
+struct _OscarData {
 	aim_session_t *sess;
 	aim_conn_t *conn;
@@ -101,5 +99,4 @@
 	gboolean killme;
 	gboolean icq;
-	GSList *evilhack;
 	guint icontimer;
 	guint getblisttimer;
@@ -151,8 +148,10 @@
 };
 
-/* Various PRPL-specific buddy info that we want to keep track of */
+/*
+ * Various PRPL-specific buddy info that we want to keep track of
+ * Some other info is maintained by locate.c, and I'd like to move 
+ * the rest of this to libfaim, mostly im.c
+ */
 struct buddyinfo {
-	time_t signon;
-	int caps;
 	gboolean typingnot;
 	gchar *availmsg;
@@ -168,7 +167,5 @@
 	time_t ico_time;
 	gboolean ico_need;
-
-	fu16_t iconcsumlen;
-	fu8_t *iconcsum;
+	gboolean ico_sent;
 };
 
@@ -219,11 +216,11 @@
 static int gaim_parse_misses     (aim_session_t *, aim_frame_t *, ...);
 static int gaim_parse_clientauto (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_user_info  (aim_session_t *, aim_frame_t *, ...);
+static int gaim_parse_userinfo   (aim_session_t *, aim_frame_t *, ...);
 static int gaim_parse_motd       (aim_session_t *, aim_frame_t *, ...);
 static int gaim_chatnav_info     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_chat_join        (aim_session_t *, aim_frame_t *, ...);
-static int gaim_chat_leave       (aim_session_t *, aim_frame_t *, ...);
-static int gaim_chat_info_update (aim_session_t *, aim_frame_t *, ...);
-static int gaim_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...);
+static int gaim_conv_chat_join        (aim_session_t *, aim_frame_t *, ...);
+static int gaim_conv_chat_leave       (aim_session_t *, aim_frame_t *, ...);
+static int gaim_conv_chat_info_update (aim_session_t *, aim_frame_t *, ...);
+static int gaim_conv_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...);
 static int gaim_email_parseupdate(aim_session_t *, aim_frame_t *, ...);
 static int gaim_icon_error       (aim_session_t *, aim_frame_t *, ...);
@@ -284,4 +281,5 @@
 
 /* prpl actions - remove this at some point */
+/* Because I don't like forward declarations?  I think that was why... */
 static void oscar_set_info(GaimConnection *gc, const char *text);
 
@@ -295,5 +293,4 @@
 	struct buddyinfo *bi = data;
 	g_free(bi->availmsg);
-	g_free(bi->iconcsum);
 	g_free(bi);
 }
@@ -384,5 +381,5 @@
 }
 
-static struct direct_im *find_direct_im(struct oscar_data *od, const char *who) {
+static struct direct_im *find_direct_im(OscarData *od, const char *who) {
 	GSList *d = od->direct_ims;
 	struct direct_im *m = NULL;
@@ -428,5 +425,5 @@
 
 static struct chat_connection *find_oscar_chat(GaimConnection *gc, int id) {
-	GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats;
+	GSList *g = ((OscarData *)gc->proto_data)->oscar_chats;
 	struct chat_connection *c = NULL;
 
@@ -444,5 +441,5 @@
 static struct chat_connection *find_oscar_chat_by_conn(GaimConnection *gc,
 							aim_conn_t *conn) {
-	GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats;
+	GSList *g = ((OscarData *)gc->proto_data)->oscar_chats;
 	struct chat_connection *c = NULL;
 
@@ -460,5 +457,5 @@
 static void gaim_odc_disconnect(aim_session_t *sess, aim_conn_t *conn) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	GaimConversation *cnv;
 	struct direct_im *dim;
@@ -496,8 +493,7 @@
 	aim_session_t *sess = aim_conn_getsess(conn);
 	GaimConnection *gc = sess ? sess->aux_data : NULL;
-	struct oscar_data *od;
+	OscarData *od;
 
 	if (!gc) {
-		/* gc is null. we return, else we seg SIGSEG on next line. */
 		gaim_debug(GAIM_DEBUG_INFO, "oscar",
 				   "oscar callback for closed connection (1).\n");
@@ -505,5 +501,5 @@
 	}
       
-	od = (struct oscar_data *)gc->proto_data;
+	od = (OscarData *)gc->proto_data;
 
 	if (!g_list_find(gaim_connections_get_all(), gc)) {
@@ -606,15 +602,13 @@
 
 static void oscar_debug(aim_session_t *sess, int level, const char *format, va_list va) {
-	char *s = g_strdup_vprintf(format, va);
-	char buf[256];
-	char *t;
 	GaimConnection *gc = sess->aux_data;
-
-	g_snprintf(buf, sizeof(buf), "%s %d: ", gaim_account_get_username(gaim_connection_get_account(gc)), level);
-	t = g_strconcat(buf, s, NULL);
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", t);
-	if (t[strlen(t)-1] != '\n')
+	gchar *s = g_strdup_vprintf(format, va);
+	gchar *buf;
+
+	buf = g_strdup_printf("%s %d: %s", gaim_account_get_username(gaim_connection_get_account(gc)), level, s);
+	gaim_debug(GAIM_DEBUG_INFO, "oscar", buf);
+	if (buf[strlen(buf)-1] != '\n')
 		gaim_debug(GAIM_DEBUG_INFO, NULL, "\n");
-	g_free(t);
+	g_free(buf);
 	g_free(s);
 }
@@ -623,5 +617,5 @@
 {
 	GaimConnection *gc = data;
-	struct oscar_data *od;
+	OscarData *od;
 	aim_session_t *sess;
 	aim_conn_t *conn;
@@ -635,5 +629,4 @@
 	sess = od->sess;
 	conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH);
-	
 	conn->fd = source;
 
@@ -645,6 +638,9 @@
 	aim_conn_completeconnect(sess, conn);
 	gc->inpa = gaim_input_add(conn->fd, GAIM_INPUT_READ, oscar_callback, conn);
+	aim_request_login(sess, conn, gaim_account_get_username(gaim_connection_get_account(gc)));
+
 	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "Password sent, waiting for response\n");
+			   "Screen name sent, waiting for response\n");
+	gaim_connection_update_progress(gc, _("Screen name sent"), 1, OSCAR_CONNECT_STEPS);
 }
 
@@ -652,7 +648,6 @@
 	aim_session_t *sess;
 	aim_conn_t *conn;
-	char buf[256];
 	GaimConnection *gc = gaim_account_get_connection(account);
-	struct oscar_data *od = gc->proto_data = g_new0(struct oscar_data, 1);
+	OscarData *od = gc->proto_data = g_new0(OscarData, 1);
 
 	gaim_debug(GAIM_DEBUG_MISC, "oscar", "oscar_login: gc = %p\n", gc);
@@ -667,10 +662,10 @@
 
 	sess = g_new0(aim_session_t, 1);
-
-	aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0);
+	aim_session_init(sess, TRUE, 0);
 	aim_setdebuggingcb(sess, oscar_debug);
-
-	/* we need an immediate queue because we don't use a while-loop to
-	 * see if things need to be sent. */
+	/*
+	 * We need an immediate queue because we don't use a while-loop 
+	 * to see if things need to be sent.
+	 */
 	aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);
 	od->sess = sess;
@@ -685,7 +680,4 @@
 	}
 
-	g_snprintf(buf, sizeof(buf), _("Signon: %s"), gaim_account_get_username(account));
-	gaim_connection_update_progress(gc, buf, 2, 5);
-
 	aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);
 	aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0);
@@ -699,9 +691,10 @@
 		return;
 	}
-	aim_request_login(sess, conn, gaim_account_get_username(account));
+
+	gaim_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS);
 }
 
 static void oscar_close(GaimConnection *gc) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 
 	while (od->oscar_chats) {
@@ -733,8 +726,4 @@
 	}
 	g_hash_table_destroy(od->buddyinfo);
-	while (od->evilhack) {
-		g_free(od->evilhack->data);
-		od->evilhack = g_slist_remove(od->evilhack, od->evilhack->data);
-	}
 	while (od->create_rooms) {
 		struct create_room *cr = od->create_rooms->data;
@@ -773,5 +762,5 @@
 static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition cond) {
 	GaimConnection *gc = data;
-	struct oscar_data *od;
+	OscarData *od;
 	aim_session_t *sess;
 	aim_conn_t *bosconn;
@@ -794,6 +783,7 @@
 	aim_conn_completeconnect(sess, bosconn);
 	gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn);
+
 	gaim_connection_update_progress(gc,
-			_("Connection established, cookie sent"), 4, 5);
+			_("Connection established, cookie sent"), 4, OSCAR_CONNECT_STEPS);
 }
 
@@ -834,5 +824,5 @@
 	struct aim_oft_info *oft_info = xfer->data;
 	GaimConnection *gc = oft_info->sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 
 	if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) {
@@ -900,5 +890,5 @@
 	struct aim_oft_info *oft_info = xfer->data;
 	GaimConnection *gc = oft_info->sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 
 	gaim_debug(GAIM_DEBUG_INFO, "oscar", "AAA - in oscar_xfer_end\n");
@@ -919,5 +909,5 @@
 	struct aim_oft_info *oft_info = xfer->data;
 	GaimConnection *gc = oft_info->sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 
 	gaim_debug(GAIM_DEBUG_INFO, "oscar",
@@ -936,5 +926,5 @@
 	struct aim_oft_info *oft_info = xfer->data;
 	GaimConnection *gc = oft_info->sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 
 	gaim_debug(GAIM_DEBUG_INFO, "oscar",
@@ -1007,5 +997,5 @@
 
 static void oscar_ask_sendfile(GaimConnection *gc, const char *destsn) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	GaimXfer *xfer;
 	struct aim_oft_info *oft_info;
@@ -1038,5 +1028,5 @@
 static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	GaimAccount *account = gc->account;
 	aim_conn_t *bosconn;
@@ -1136,5 +1126,5 @@
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, gaim_parse_msgerr, 0);
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MTN, gaim_parse_mtn, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_user_info, 0);
+	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_userinfo, 0);
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, gaim_parse_msgack, 0);
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, gaim_parse_motd, 0);
@@ -1163,5 +1153,5 @@
 #endif
 
-	((struct oscar_data *)gc->proto_data)->conn = bosconn;
+	od->conn = bosconn;
 	for (i = 0; i < (int)strlen(info->bosip); i++) {
 		if (info->bosip[i] == ':') {
@@ -1182,7 +1172,10 @@
 	gaim_input_remove(gc->inpa);
 
+	gaim_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS);
+
 	return 1;
 }
 
+/* XXX - Should use gaim_url_fetch for the below stuff */
 struct pieceofcrap {
 	GaimConnection *gc;
@@ -1198,5 +1191,5 @@
 {
 	struct pieceofcrap *pos = data;
-	struct oscar_data *od = pos->gc->proto_data;
+	OscarData *od = pos->gc->proto_data;
 	char in = '\0';
 	int x = 0;
@@ -1217,5 +1210,5 @@
 			"this is fixed.  Check %s for updates."), GAIM_WEBSITE);
 		gaim_notify_warning(pos->gc, NULL,
-							_("Gaim was Unable to get a valid AIM login hash."),
+							_("Gaim was unable to get a valid AIM login hash."),
 							buf);
 		gaim_input_remove(pos->inpa);
@@ -1247,5 +1240,5 @@
 			"this is fixed.  Check %s for updates."), GAIM_WEBSITE);
 		gaim_notify_warning(pos->gc, NULL,
-							_("Gaim was Unable to get a valid AIM login hash."),
+							_("Gaim was unable to get a valid AIM login hash."),
 							buf);
 		g_free(buf);
@@ -1335,5 +1328,5 @@
 			"this is fixed.  Check %s for updates."), GAIM_WEBSITE);
 		gaim_notify_warning(pos->gc, NULL,
-							_("Gaim was Unable to get a valid login hash."),
+							_("Gaim was unable to get a valid login hash."),
 							buf);
 	}
@@ -1343,10 +1336,13 @@
 
 static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...) {
-	char *key;
-	va_list ap;
 	GaimConnection *gc = sess->aux_data;
+	OscarData *od = gc->proto_data;
 	GaimAccount *account = gaim_connection_get_account(gc);
 	GaimAccount *ac = gaim_connection_get_account(gc);
-	struct oscar_data *od = gc->proto_data;
+#if 0
+	struct client_info_s info = {"gaim", 7, 3, 2003, "us", "en", 0x0004, 0x0000, 0x04b};
+#endif
+	va_list ap;
+	char *key;
 
 	va_start(ap, fr);
@@ -1359,11 +1355,10 @@
 					   gaim_account_get_password(account), &info, key);
 	} else {
-#if 0
-		struct client_info_s info = {"gaim", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x04b};
-#endif
 		struct client_info_s info = CLIENTINFO_AIM_KNOWNGOOD;
 		aim_send_login(sess, fr->conn, gaim_account_get_username(ac),
 					   gaim_account_get_password(account), &info, key);
 	}
+
+	gaim_connection_update_progress(gc, _("Password sent"), 2, OSCAR_CONNECT_STEPS);
 
 	return 1;
@@ -1376,8 +1371,8 @@
 
 	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, 0x0001, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_chat_join, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_chat_leave, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_chat_info_update, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_chat_incoming_msg, 0);
+	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_conv_chat_join, 0);
+	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_conv_chat_leave, 0);
+	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_conv_chat_info_update, 0);
+	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_conv_chat_incoming_msg, 0);
 
 	aim_clientready(sess, fr->conn);
@@ -1407,6 +1402,6 @@
 	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_EML, AIM_CB_EML_MAILSTATUS, gaim_email_parseupdate, 0);
 
-	aim_email_sendcookies(sess, fr->conn);
-	aim_email_activate(sess, fr->conn);
+	aim_email_sendcookies(sess);
+	aim_email_activate(sess);
 	aim_clientready(sess, fr->conn);
 
@@ -1416,5 +1411,5 @@
 static int conninitdone_icon(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 
 	aim_conn_addhandler(sess, fr->conn, 0x0018, 0x0001, gaim_parse_genericerr, 0);
@@ -1435,5 +1430,5 @@
 static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition cond) {
 	GaimConnection *gc = data;
-	struct oscar_data *od;
+	OscarData *od;
 	aim_session_t *sess;
 	aim_conn_t *tstconn;
@@ -1464,5 +1459,5 @@
 {
 	GaimConnection *gc = data;
-	struct oscar_data *od;
+	OscarData *od;
 	aim_session_t *sess;
 	aim_conn_t *tstconn;
@@ -1494,5 +1489,5 @@
 	struct chat_connection *ccon = data;
 	GaimConnection *gc = ccon->gc;
-	struct oscar_data *od;
+	OscarData *od;
 	aim_session_t *sess;
 	aim_conn_t *tstconn;
@@ -1526,5 +1521,5 @@
 static void oscar_email_connect(gpointer data, gint source, GaimInputCondition cond) {
 	GaimConnection *gc = data;
-	struct oscar_data *od;
+	OscarData *od;
 	aim_session_t *sess;
 	aim_conn_t *tstconn;
@@ -1555,5 +1550,5 @@
 static void oscar_icon_connect(gpointer data, gint source, GaimInputCondition cond) {
 	GaimConnection *gc = data;
-	struct oscar_data *od;
+	OscarData *od;
 	aim_session_t *sess;
 	aim_conn_t *tstconn;
@@ -1748,5 +1743,5 @@
 static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	struct buddyinfo *bi;
 	time_t time_idle = 0, signon = 0;
@@ -1789,6 +1784,6 @@
 	}
 
-	if (caps & AIM_CAPS_ICQ)
-		caps ^= AIM_CAPS_ICQ;
+	if (caps & AIM_CAPS_ICQ_DIRECT)
+		caps ^= AIM_CAPS_ICQ_DIRECT;
 
 	if (info->present & AIM_USERINFO_PRESENT_IDLE) {
@@ -1805,12 +1800,9 @@
 		gaim_connection_set_display_name(gc, info->sn);
 
-	bi = g_hash_table_lookup(od->buddyinfo, normalize(info->sn));
+	bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, info->sn));
 	if (!bi) {
 		bi = g_new0(struct buddyinfo, 1);
-		g_hash_table_insert(od->buddyinfo, g_strdup(normalize(info->sn)), bi);
-	}
-	bi->signon = info->onlinesince ? info->onlinesince : (info->sessionlen + time(NULL));
-	if (caps)
-		bi->caps = caps;
+		g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(gc->account, info->sn)), bi);
+	}
 	bi->typingnot = FALSE;
 	bi->ico_informed = FALSE;
@@ -1819,12 +1811,12 @@
 	/* Available message stuff */
 	free(bi->availmsg);
-	if (info->availmsg)
-		if (info->availmsg_encoding) {
-			gchar *enc = g_strdup_printf("charset=\"%s\"", info->availmsg_encoding);
-			bi->availmsg = oscar_encoding_to_utf8(enc, info->availmsg, info->availmsg_len);
+	if (info->avail != NULL)
+		if (info->avail_encoding) {
+			gchar *enc = g_strdup_printf("charset=\"%s\"", info->avail_encoding);
+			bi->availmsg = oscar_encoding_to_utf8(enc, info->avail, info->avail_len);
 			g_free(enc);
 		} else {
 			/* No explicit encoding means utf8.  Yay. */
-			bi->availmsg = g_strdup(info->availmsg);
+			bi->availmsg = g_strdup(info->avail);
 		}
 	else
@@ -1833,14 +1825,21 @@
 	/* Server stored icon stuff */
 	if (info->iconcsumlen) {
-		char *b16, *saved_b16;
-		GaimBuddy *b;
-
-		free(bi->iconcsum);
-		bi->iconcsum = malloc(info->iconcsumlen);
-		memcpy(bi->iconcsum, info->iconcsum, info->iconcsumlen);
-		bi->iconcsumlen = info->iconcsumlen;
-		b16 = tobase16(bi->iconcsum, bi->iconcsumlen);
+		const char *filename = NULL, *saved_b16 = NULL;
+		char *b16 = NULL;
+		GaimBuddy *b = NULL;
+
+		b16 = gaim_base16_encode(info->iconcsum, info->iconcsumlen);
 		b = gaim_find_buddy(gc->account, info->sn);
-		saved_b16 = gaim_buddy_get_setting(b, "icon_checksum");
+		/*
+		 * If for some reason the checksum is valid, but cached file is not..
+		 * we want to know.
+		 */
+		filename = gaim_buddy_get_setting(b, "buddy_icon");
+		if (filename != NULL) {
+			if (g_file_test(filename, G_FILE_TEST_EXISTS))
+				saved_b16 = gaim_buddy_get_setting(b, "icon_checksum");
+		} else
+			saved_b16 = NULL;
+
 		if (!b16 || !saved_b16 || strcmp(b16, saved_b16)) {
 			GSList *cur = od->requesticon;
@@ -1848,5 +1847,5 @@
 				cur = cur->next;
 			if (!cur) {
-				od->requesticon = g_slist_append(od->requesticon, strdup(normalize(info->sn)));
+				od->requesticon = g_slist_append(od->requesticon, g_strdup(gaim_normalize(gc->account, info->sn)));
 				if (od->icontimer)
 					g_source_remove(od->icontimer);
@@ -1854,5 +1853,4 @@
 			}
 		}
-		g_free(saved_b16);
 		g_free(b16);
 	}
@@ -1865,5 +1863,5 @@
 static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	va_list ap;
 	aim_userinfo_t *info;
@@ -1875,5 +1873,5 @@
 	serv_got_update(gc, info->sn, 0, 0, 0, 0, 0);
 
-	g_hash_table_remove(od->buddyinfo, normalize(info->sn));
+	g_hash_table_remove(od->buddyinfo, gaim_normalize(gc->account, info->sn));
 
 	return 1;
@@ -1890,5 +1888,5 @@
 	struct direct_im *dim = data;
 	GaimConnection *gc = dim->gc;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	GaimConversation *cnv;
 	char buf[256];
@@ -1929,5 +1927,5 @@
 static int oscar_sendfile_estblsh(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	GaimXfer *xfer;
 	struct aim_oft_info *oft_info;
@@ -2002,5 +2000,5 @@
 static int oscar_sendfile_prompt(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	GaimXfer *xfer;
 	struct aim_oft_info *oft_info;
@@ -2047,5 +2045,5 @@
 static int oscar_sendfile_ack(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	GaimXfer *xfer;
 	va_list ap;
@@ -2079,5 +2077,5 @@
 static int oscar_sendfile_done(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	GaimXfer *xfer;
 	va_list ap;
@@ -2104,5 +2102,5 @@
 static void accept_direct_im(struct ask_direct *d) {
 	GaimConnection *gc = d->gc;
-	struct oscar_data *od;
+	OscarData *od;
 	struct direct_im *dim;
 	char *host; int port = 4443;
@@ -2114,5 +2112,5 @@
 	}
 
-	od = (struct oscar_data *)gc->proto_data;
+	od = (OscarData *)gc->proto_data;
 	gaim_debug(GAIM_DEBUG_INFO, "oscar", "Accepted DirectIM.\n");
 
@@ -2163,7 +2161,7 @@
 static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
-	char *tmp;
-	GaimImFlags flags = 0;
+	OscarData *od = gc->proto_data;
+	gchar *tmp;
+	GaimConvImFlags flags = 0;
 	gsize convlen;
 	GError *err = NULL;
@@ -2171,12 +2169,12 @@
 	const char *iconfile;
 
-	bi = g_hash_table_lookup(od->buddyinfo, normalize(userinfo->sn));
+	bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, userinfo->sn));
 	if (!bi) {
 		bi = g_new0(struct buddyinfo, 1);
-		g_hash_table_insert(od->buddyinfo, g_strdup(normalize(userinfo->sn)), bi);
+		g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(gc->account, userinfo->sn)), bi);
 	}
 
 	if (args->icbmflags & AIM_IMFLAGS_AWAY)
-		flags |= GAIM_IM_AUTO_RESP;
+		flags |= GAIM_CONV_IM_AUTO_RESP;
 
 	if (args->icbmflags & AIM_IMFLAGS_TYPINGNOT)
@@ -2197,5 +2195,5 @@
 
 	if ((iconfile = gaim_account_get_buddy_icon(gaim_connection_get_account(gc))) && 
-	    (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)) {
+	    (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) && !bi->ico_sent && bi->ico_informed) {
 		FILE *file;
 		struct stat st;
@@ -2241,5 +2239,5 @@
 			gaim_debug(GAIM_DEBUG_INFO, "oscar",
 					   "Unicode IM conversion: %s\n", err->message);
-			tmp = strdup(_("(There was an error receiving this message)"));
+			tmp = g_strdup(_("(There was an error receiving this message)"));
 			g_error_free(err);
 		}
@@ -2263,10 +2261,10 @@
 			gaim_debug(GAIM_DEBUG_INFO, "oscar",
 					   "ISO-8859-1 IM conversion: %s\n", err->message);
-			tmp = strdup(_("(There was an error receiving this message)"));
+			tmp = g_strdup(_("(There was an error receiving this message)"));
 			g_error_free(err);
 		}
 	}
 
-	/* strip_linefeed(tmp); */
+	/* gaim_str_strip_cr(tmp); */
 	serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL));
 	g_free(tmp);
@@ -2277,5 +2275,5 @@
 static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	const char *username = gaim_account_get_username(gaim_connection_get_account(gc));
 
@@ -2438,5 +2436,5 @@
 
 	if (g_list_find(gaim_connections_get_all(), gc)) {
-		struct oscar_data *od = gc->proto_data;
+		OscarData *od = gc->proto_data;
 		GaimBuddy *buddy = gaim_find_buddy(gc->account, data->name);
 		GaimGroup *group = gaim_find_buddys_group(buddy);
@@ -2464,5 +2462,5 @@
 
 	if (g_list_find(gaim_connections_get_all(), gc)) {
-		/* struct oscar_data *od = gc->proto_data; */
+		/* OscarData *od = gc->proto_data; */
 		/* XXX - Take the buddy out of our buddy list */
 	}
@@ -2502,5 +2500,5 @@
 
 	if (g_list_find(gaim_connections_get_all(), gc)) {
-		struct oscar_data *od = gc->proto_data;
+		OscarData *od = gc->proto_data;
 #ifdef NOSSI
 		GaimBuddy *buddy;
@@ -2509,5 +2507,5 @@
 		buddy = gaim_find_buddy(gc->account, data->name);
 		aim_im_sendch4(od->sess, data->name, AIM_ICQMSG_AUTHGRANTED, &message);
-		show_got_added(gc, NULL, data->name, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
+		gaim_account_notify_added(gc->account, NULL, data->name, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
 #else
 		aim_ssi_sendauthreply(od->sess, data->name, 0x01, NULL);
@@ -2523,5 +2521,5 @@
 
 	if (g_list_find(gaim_connections_get_all(), gc)) {
-		struct oscar_data *od = gc->proto_data;
+		OscarData *od = gc->proto_data;
 #ifdef NOSSI
 		aim_im_sendch4(od->sess, data->name, AIM_ICQMSG_AUTHDENIED, msg ? msg : _("No reason given."));
@@ -2540,10 +2538,10 @@
 }
 
-/* When someone sends you contacts  */
-static void gaim_icq_contactadd(struct name_data *data) {
+/* When someone sends you buddies */
+static void gaim_icq_buddyadd(struct name_data *data) {
 	GaimConnection *gc = data->gc;
 
 	if (g_list_find(gaim_connections_get_all(), gc)) {
-		show_add_buddy(gc, data->name, NULL, data->nick);
+		gaim_blist_request_add_buddy(gaim_connection_get_account(gc), data->name, NULL, data->nick);
 	}
 
@@ -2568,5 +2566,5 @@
 	msg2 = (gchar **)g_malloc((numtoks+1)*sizeof(gchar *));
 	for (i=0; msg1[i]; i++) {
-		strip_linefeed(msg1[i]);
+		gaim_str_strip_cr(msg1[i]);
 		msg2[i] = g_convert(msg1[i], strlen(msg1[i]), "UTF-8", "ISO-8859-1", NULL, NULL, &err);
 		if (err) {
@@ -2595,9 +2593,13 @@
 		case 0x04: { /* Someone sent you a URL */
 			if (i >= 2) {
-				gchar *uin = g_strdup_printf("%u", args->uin);
-				gchar *message = g_strdup_printf("<A HREF=\"%s\">%s</A>", msg2[1], msg2[0]);
-				serv_got_im(gc, uin, message, 0, time(NULL));
-				g_free(uin);
-				g_free(message);
+				if (msg2[1] != NULL) {
+					gchar *uin = g_strdup_printf("%u", args->uin);
+					gchar *message = g_strdup_printf("<A HREF=\"%s\">%s</A>",
+													 msg2[1],
+													 (msg2[0] && msg2[0][0]) ? msg2[0] : msg2[1]);
+					serv_got_im(gc, uin, message, 0, time(NULL));
+					g_free(uin);
+					g_free(message);
+				}
 			}
 		} break;
@@ -2626,5 +2628,5 @@
 		case 0x07: { /* Someone has denied you authorization */
 			if (i >= 1) {
-				gchar *dialog_msg = g_strdup_printf(_("The user %u has denied your request to add them to your contact list for the following reason:\n%s"), args->uin, msg2[0] ? msg2[0] : _("No reason given."));
+				gchar *dialog_msg = g_strdup_printf(_("The user %u has denied your request to add them to your buddy list for the following reason:\n%s"), args->uin, msg2[0] ? msg2[0] : _("No reason given."));
 				gaim_notify_info(gc, NULL, _("ICQ authorization denied."),
 								 dialog_msg);
@@ -2634,5 +2636,5 @@
 
 		case 0x08: { /* Someone has granted you authorization */
-			gchar *dialog_msg = g_strdup_printf(_("The user %u has granted your request to add them to your contact list."), args->uin);
+			gchar *dialog_msg = g_strdup_printf(_("The user %u has granted your request to add them to your buddy list."), args->uin);
 			gaim_notify_info(gc, NULL, "ICQ authorization accepted.",
 							 dialog_msg);
@@ -2666,8 +2668,8 @@
 		case 0x12: {
 			/* Ack for authorizing/denying someone.  Or possibly an ack for sending any system notice */
-			/* Someone added you to their contact list? */
+			/* Someone added you to their buddy list? */
 		} break;
 
-		case 0x13: { /* Someone has sent you some ICQ contacts */
+		case 0x13: { /* Someone has sent you some ICQ buddies */
 			int i, num;
 			gchar **text;
@@ -2679,5 +2681,5 @@
 				for (i=0; i<num; i++) {
 					struct name_data *data = g_new(struct name_data, 1);
-					gchar *message = g_strdup_printf(_("ICQ user %u has sent you a contact: %s (%s)"), args->uin, text[i*2+2], text[i*2+1]);
+					gchar *message = g_strdup_printf(_("ICQ user %u has sent you a buddy: %s (%s)"), args->uin, text[i*2+2], text[i*2+1]);
 					data->gc = gc;
 					data->name = g_strdup(text[i*2+1]);
@@ -2685,8 +2687,8 @@
 
 					gaim_request_action(gc, NULL, message,
-										_("Do you want to add this contact "
-										  "to your Buddy List?"),
+										_("Do you want to add this buddy "
+										  "to your buddy list?"),
 										0, data, 2,
-										_("Add"), G_CALLBACK(gaim_icq_contactadd),
+										_("Add"), G_CALLBACK(gaim_icq_buddyadd),
 										_("Decline"), G_CALLBACK(oscar_free_name_data));
 					g_free(message);
@@ -2696,5 +2698,5 @@
 		} break;
 
-		case 0x1a: { /* Someone has sent you a greeting card or requested contacts? */
+		case 0x1a: { /* Someone has sent you a greeting card or requested buddies? */
 			/* This is boring and silly. */
 		} break;
@@ -2851,5 +2853,5 @@
 static int gaim_parse_clientauto_ch2(aim_session_t *sess, const char *who, fu16_t reason, const char *cookie) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 
 /* BBB */
@@ -2881,29 +2883,10 @@
 			char *status_msg = gaim_icq_status(state);
 			char *dialog_msg, **splitmsg;
-			struct oscar_data *od = gc->proto_data;
-			GSList *l = od->evilhack;
-			gboolean evilhack = FALSE;
 
 			/* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
 			splitmsg = g_strsplit(msg, "\r\n", 0);
 
-			/* If who is in od->evilhack, then we're just getting the away message, otherwise this 
-			 * will just get appended to the info box (which is already showing). */
-			while (l) {
-				char *x = l->data;
-				if (!strcmp(x, normalize(who))) {
-					evilhack = TRUE;
-					g_free(x);
-					od->evilhack = g_slist_remove(od->evilhack, x);
-					break;
-				}
-				l = l->next;
-			}
-
-			if (evilhack)
-				dialog_msg = g_strdup_printf(_("<B>UIN:</B> %s<BR><B>Status:</B> %s<HR>%s"), who, status_msg, g_strjoinv("<BR>", splitmsg));
-			else
-				dialog_msg = g_strdup_printf(_("<B>Status:</B> %s<HR>%s"), status_msg, g_strjoinv("<BR>", splitmsg));
-			g_show_info_text(gc, who, 2, dialog_msg, NULL);
+			dialog_msg = g_strdup_printf(_("<B>UIN:</B> %s<BR><B>Status:</B> %s<HR>%s"), who, status_msg, g_strjoinv("<BR>", splitmsg));
+			gaim_notify_formatted(gc, NULL, _("Buddy Information"), NULL, dialog_msg, NULL, NULL);
 
 			g_free(status_msg);
@@ -2974,5 +2957,5 @@
 #if 0
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	GaimXfer *xfer;
 #endif
@@ -3040,6 +3023,10 @@
 }
 
+/*
+ * We get this error when there was an error in the locate family.  This 
+ * happens when you request info of someone who is offline.
+ */
 static int gaim_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...) {
-	char *buf;
+	gchar *buf;
 	va_list ap;
 	fu16_t reason;
@@ -3051,8 +3038,10 @@
 	va_end(ap);
 
-	buf = g_strdup_printf(_("User information for %s unavailable:"), destn);
-	gaim_notify_error(sess->aux_data, NULL, buf,
-					  (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("No reason given."));
-	g_free(buf);
+	if (destn != NULL) {
+		buf = g_strdup_printf(_("User information for %s unavailable:"), destn);
+		gaim_notify_error(sess->aux_data, NULL, buf,
+						  (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("No reason given."));
+		g_free(buf);
+	}
 
 	return 1;
@@ -3092,5 +3081,5 @@
 				break;
 			case AIM_CAPS_DIRECTIM:
-				tmp = _("Direct IM");
+				tmp = _("AIM Direct IM");
 				break;
 			case AIM_CAPS_CHAT:
@@ -3113,6 +3102,6 @@
 				tmp = _("Send Buddy List");
 				break;
-			case AIM_CAPS_ICQ:
-				tmp = _("EveryBuddy Bug");
+			case AIM_CAPS_ICQ_DIRECT:
+				tmp = _("ICQ Direct Connect");
 				break;
 			case AIM_CAPS_APINFO:
@@ -3141,5 +3130,8 @@
 				break;
 			case AIM_CAPS_SECUREIM:
-				tmp = _("Secure IM");
+				tmp = _("Security Enabled");
+				break;
+			case AIM_CAPS_VIDEO:
+				tmp = _("Video Chat");
 				break;
 			default:
@@ -3157,108 +3149,54 @@
 }
 
-static int gaim_parse_user_info(aim_session_t *sess, aim_frame_t *fr, ...) {
+static int gaim_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
-	gchar *header;
-	GSList *l = od->evilhack;
-	gboolean evilhack = FALSE;
-	gchar *membersince = NULL, *onlinesince = NULL, *idle = NULL;
+	GString *text;
+	gchar *info_utf8 = NULL, *away_utf8 = NULL;
+	const char *final = NULL;
 	va_list ap;
-	aim_userinfo_t *info;
-	fu16_t infotype;
-	char *text_enc = NULL, *text = NULL, *utf8 = NULL;
-	int text_len;
-	const char *username = gaim_account_get_username(gaim_connection_get_account(gc));
+	aim_userinfo_t *userinfo;
 
 	va_start(ap, fr);
-	info = va_arg(ap, aim_userinfo_t *);
-	infotype = (fu16_t) va_arg(ap, unsigned int);
-	text_enc = va_arg(ap, char *);
-	text = va_arg(ap, char *);
-	text_len = va_arg(ap, int);
+	userinfo = va_arg(ap, aim_userinfo_t *);
 	va_end(ap);
 
-	if (text_len > 0) {
-		if (!(utf8 = oscar_encoding_to_utf8(text_enc, text, text_len))) {
-			utf8 = g_strdup(_("<i>Unable to display information because it was sent in an unknown encoding.</i>"));
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "Encountered an unknown encoding while parsing userinfo\n");
-		}
-	}
-
-	if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE) {
-		onlinesince = g_strdup_printf(_("Online Since : <b>%s</b><br>\n"),
-					asctime(localtime((time_t *)&info->onlinesince)));
-	}
-
-	if (info->present & AIM_USERINFO_PRESENT_MEMBERSINCE) {
-		membersince = g_strdup_printf(_("Member Since : <b>%s</b><br>\n"),
-					asctime(localtime((time_t *)&info->membersince)));
-	}
-
-	if (info->present & AIM_USERINFO_PRESENT_IDLE) {
-		gchar *itime = sec_to_text(info->idletime*60);
-		idle = g_strdup_printf(_("Idle : <b>%s</b>"), itime);
+	text = g_string_new("");
+	g_string_append_printf(text, _("Username: <b>%s</b><br>\n"), userinfo->sn);
+	g_string_append_printf(text, _("Warning Level: <b>%d%%</b><br>\n"), (int)((userinfo->warnlevel/10.0) + 0.5));
+
+	if (userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE)
+		g_string_append_printf(text, _("Online Since: <b>%s</b><br>\n"),
+					asctime(localtime((time_t *)&userinfo->onlinesince)));
+
+	if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE)
+		g_string_append_printf(text, _("Member Since: <b>%s</b><br>\n"),
+					asctime(localtime((time_t *)&userinfo->membersince)));
+
+	if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
+		gchar *itime = gaim_str_seconds_to_string(userinfo->idletime*60);
+		g_string_append_printf(text, _("Idle: <b>%s</b>"), itime);
 		g_free(itime);
 	} else
-		idle = g_strdup(_("Idle: <b>Active</b>"));
-
-	header = g_strdup_printf(_("Username : <b>%s</b>  %s <br>\n"
-			"Warning Level : <b>%d %%</b><br>\n"
-			"%s"
-			"%s"
-			"%s\n"
-			"<hr>\n"),
-			info->sn,
-			/* images(info->flags), */
-			"",
-			(int)((info->warnlevel/10.0) + 0.5),
-			onlinesince ? onlinesince : "",
-			membersince ? membersince : "",
-			idle ? idle : "");
-
-	g_free(onlinesince);
-	g_free(membersince);
-	g_free(idle);
-
-	while (l) {
-		char *x = l->data;
-		if (!strcmp(x, normalize(info->sn))) {
-			evilhack = TRUE;
-			g_free(x);
-			od->evilhack = g_slist_remove(od->evilhack, x);
-			break;
-		}
-		l = l->next;
-	}
-
-	if (infotype == AIM_GETINFO_AWAYMESSAGE) {
-		if (evilhack) {
-			g_show_info_text(gc, info->sn, 2,
-					 header,
-					 (utf8 && *utf8) ? away_subs(utf8, username) :
-					 _("<i>User has no away message</i>"), NULL);
-		} else {
-			g_show_info_text(gc, info->sn, 0,
-					 header,
-					 (utf8 && *utf8) ? away_subs(utf8, username) : NULL,
-					 (utf8 && *utf8) ? "<hr>" : NULL,
-					 NULL);
-		}
-	} else if (infotype == AIM_GETINFO_CAPABILITIES) {
-		g_show_info_text(gc, info->sn, 2,
-				header,
-				"<i>", _("Client Capabilities: "),
-				caps_string(info->capabilities),
-				"</i>",
-				NULL);
-	} else {
-		g_show_info_text(gc, info->sn, 1,
-				 (utf8 && *utf8) ? away_subs(utf8, username) : _("<i>No Information Provided</i>"),
-				 NULL);
-	}
-
-	g_free(header);
-	g_free(utf8);
+		g_string_append_printf(text, _("Idle: <b>Active</b>"));
+
+	if ((userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) {
+		away_utf8 = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
+		if (away_utf8 != NULL) {
+			g_string_append_printf(text, "<hr>%s", away_utf8);
+			g_free(away_utf8);
+		}
+	}
+
+	if ((userinfo->info_len > 0) && (userinfo->info != NULL) && (userinfo->info_encoding != NULL)) {
+		info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len);
+		if (info_utf8 != NULL) {
+			g_string_append_printf(text, "<hr>%s", info_utf8);
+			g_free(info_utf8);
+		}
+	}
+
+	final = gaim_str_sub_away_formatters(text->str, gaim_account_get_username(gaim_connection_get_account(gc)));
+	g_string_free(text, TRUE);
+	gaim_notify_formatted(gc, NULL, _("Buddy Information"), NULL, final, NULL, NULL);
 
 	return 1;
@@ -3288,5 +3226,5 @@
 	fu16_t type;
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 
 	va_start(ap, fr);
@@ -3363,5 +3301,5 @@
 }
 
-static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) {
+static int gaim_conv_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) {
 	va_list ap;
 	int count, i;
@@ -3381,10 +3319,10 @@
 
 	for (i = 0; i < count; i++)
-		gaim_chat_add_user(GAIM_CHAT(c->cnv), info[i].sn, NULL);
+		gaim_conv_chat_add_user(GAIM_CONV_CHAT(c->cnv), info[i].sn, NULL);
 
 	return 1;
 }
 
-static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) {
+static int gaim_conv_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) {
 	va_list ap;
 	int count, i;
@@ -3404,10 +3342,10 @@
 
 	for (i = 0; i < count; i++)
-		gaim_chat_remove_user(GAIM_CHAT(c->cnv), info[i].sn, NULL);
+		gaim_conv_chat_remove_user(GAIM_CONV_CHAT(c->cnv), info[i].sn, NULL);
 
 	return 1;
 }
 
-static int gaim_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) {
+static int gaim_conv_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) {
 	va_list ap;
 	aim_userinfo_t *userinfo;
@@ -3445,5 +3383,5 @@
 }
 
-static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) {
+static int gaim_conv_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
 	va_list ap;
@@ -3467,8 +3405,11 @@
 	struct aim_emailinfo *emailinfo;
 	int havenewmail;
+	char *alertitle, *alerturl;
 
 	va_start(ap, fr);
 	emailinfo = va_arg(ap, struct aim_emailinfo *);
 	havenewmail = va_arg(ap, int);
+	alertitle = va_arg(ap, char *);
+	alerturl  = va_arg(ap, char *);
 	va_end(ap);
 
@@ -3479,4 +3420,7 @@
 		g_free(to);
 	}
+	
+	if (alertitle)
+		gaim_debug(GAIM_DEBUG_MISC, "oscar", "Got an alert '%s' %s\n", alertitle, alerturl ? alerturl : "");
 
 	return 1;
@@ -3485,5 +3429,5 @@
 static int gaim_icon_error(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	char *sn;
 
@@ -3503,5 +3447,5 @@
 static int gaim_icon_parseicon(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	GSList *cur;
 	va_list ap;
@@ -3523,9 +3467,9 @@
 		gaim_buddy_icons_set_for_user(gaim_connection_get_account(gc),
 									  sn, icon, iconlen);
-		b16 = tobase16(iconcsum, iconcsumlen);
+		b16 = gaim_base16_encode(iconcsum, iconcsumlen);
 		if (b16) {
 			gaim_buddy_set_setting(b, "icon_checksum", b16);
 			gaim_blist_save();
-			free(b16);
+			g_free(b16);
 		}
 	}
@@ -3551,6 +3495,6 @@
 static gboolean gaim_icon_timerfunc(gpointer data) {
 	GaimConnection *gc = data;
-	struct oscar_data *od = gc->proto_data;
-	struct buddyinfo *bi;
+	OscarData *od = gc->proto_data;
+	aim_userinfo_t *userinfo;
 	aim_conn_t *conn;
 
@@ -3595,7 +3539,7 @@
 	}
 
-	bi = g_hash_table_lookup(od->buddyinfo, (char *)od->requesticon->data);
-	if (bi && (bi->iconcsumlen > 0)) {
-		aim_bart_request(od->sess, od->requesticon->data, bi->iconcsum, bi->iconcsumlen);
+	userinfo = aim_locate_finduserinfo(od->sess, (char *)od->requesticon->data);
+	if ((userinfo != NULL) && (userinfo->iconcsumlen > 0)) {
+		aim_bart_request(od->sess, od->requesticon->data, userinfo->iconcsum, userinfo->iconcsumlen);
 		return FALSE;
 	} else {
@@ -3690,5 +3634,5 @@
 	va_end(ap);
 
-	serv_got_eviled(gc, (userinfo && userinfo->sn[0]) ? userinfo->sn : NULL, (newevil/10.0) + 0.5);
+	serv_got_eviled(gc, (userinfo && userinfo->sn) ? userinfo->sn : NULL, (newevil/10.0) + 0.5);
 
 	return 1;
@@ -3714,5 +3658,5 @@
 static int gaim_connerr(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	va_list ap;
 	fu16_t code;
@@ -3740,23 +3684,28 @@
 
 static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...) {
+	GaimConnection *gc = sess->aux_data;
 
 	aim_reqpersonalinfo(sess, fr->conn);
 
 #ifndef NOSSI
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: requesting ssi list\n");
+	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: requesting rights and list\n");
 	aim_ssi_reqrights(sess);
 	aim_ssi_reqdata(sess);
 #endif
 
-	aim_bos_reqlocaterights(sess, fr->conn);
-	aim_bos_reqbuddyrights(sess, fr->conn);
+	aim_locate_reqrights(sess);
+	aim_buddylist_reqrights(sess, fr->conn);
 	aim_im_reqparams(sess);
-	aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi? */
+	aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi */
 
 #ifdef NOSSI
+	gaim_debug(GAIM_DEBUG_INFO, "oscar", "bos: requesting rights\n");
+	aim_bos_reqrights(sess, fr->conn);
 	aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
 	aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE | AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
 #endif
 
+	gaim_connection_update_progress(gc, _("Finalizing connection"), 5, OSCAR_CONNECT_STEPS);
+
 	return 1;
 }
@@ -3764,5 +3713,5 @@
 static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 
 	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_ADM, 0x0003, gaim_info_change, 0);
@@ -3839,5 +3788,5 @@
 {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	va_list ap;
 	fu16_t maxsiglen;
@@ -3853,7 +3802,8 @@
 
 	if (od->icq)
-		aim_bos_setprofile(sess, fr->conn, NULL, NULL, 0, NULL, NULL, 0, caps_icq);
+		aim_locate_setcaps(od->sess, caps_icq);
 	else
-		oscar_set_info(gc, gc->account->user_info);
+		aim_locate_setcaps(od->sess, caps_aim);
+	oscar_set_info(gc, gc->account->user_info);
 
 	return 1;
@@ -3864,5 +3814,5 @@
 	fu16_t maxbuddies, maxwatchers;
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 
 	va_start(ap, fr);
@@ -3881,8 +3831,8 @@
 
 static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) {
+	GaimConnection *gc = sess->aux_data;
+	OscarData *od = (OscarData *)gc->proto_data;
+	va_list ap;
 	fu16_t maxpermits, maxdenies;
-	va_list ap;
-	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
 
 	va_start(ap, fr);
@@ -3904,5 +3854,5 @@
 	aim_clientready(sess, fr->conn);
 	aim_srv_setavailmsg(sess, NULL);
-	aim_bos_setidle(sess, fr->conn, 0);
+	aim_srv_setidle(sess, 0);
 
 	if (od->icq) {
@@ -3935,5 +3885,5 @@
 	args.msglen = msg->msglen;
 	args.msg = msg->msg;
-	t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0);
+	t = gaim_time_build(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0);
 	incomingim_chan4(sess, fr->conn, NULL, &args, t);
 
@@ -3946,4 +3896,44 @@
 	return 1;
 }
+
+#if 0
+/*
+ * Update, 2003-11-09:
+ * Joseph S. Myers, a gcc dude, fixed this for gcc 3.4!  Rock on!
+ *
+ * It may not be my place to do this, but...
+ * I feel pretty strongly that the "last 2 digits" warning is ridiculously 
+ * stupid, and should not exist for % switches (%x in our case) that request 
+ * a year in the preferred representation for the current locale.  For that 
+ * reason I've chosen to not use this workaround (n., see kluge).
+ *
+ * I have a date.  I want to show it to the user in the "preferred" way.  
+ * Whether that displays a 2 digit year is perfectly fine--after all, it's 
+ * what the locale wanted.
+ * 
+ * If I have a necessity for a full representation of the year in the current 
+ * locale, then I'll use a switch that returns a full representation of the 
+ * year.
+ *
+ * If you think the preferred locale should show 4 digits instead of 2 digits 
+ * (because you're anal, or whatever), then change the f***ing locale.
+ *
+ * I guess the bottom line is--I'm trying to show a date to the user how they 
+ * prefer to see it, why the hell does gcc want me to change that?
+ *
+ * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3190
+ * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8714
+ */
+
+/*
+ * This function was recommended by the STRFTIME(3) man page to remove the
+ * "last 2 digits" warning.
+ */
+static size_t my_strftime(char *s, size_t max, const char  *fmt,  
+			const struct tm *tm)
+{
+	return strftime(s, max, fmt, tm);
+}
+#endif
 
 static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...)
@@ -3966,14 +3956,14 @@
 	g_snprintf(who, sizeof(who), "%u", info->uin);
 	buf = g_strdup_printf("<b>%s:</b> %s", _("UIN"), who);
-	if (info->nick && info->nick[0] && (utf8 = gaim_try_conv_to_utf8(info->nick))) {
+	if (info->nick && info->nick[0] && (utf8 = gaim_utf8_try_convert(info->nick))) {
 		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Nick"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 	}
-	if (info->first && info->first[0] && (utf8 = gaim_try_conv_to_utf8(info->first))) {
+	if (info->first && info->first[0] && (utf8 = gaim_utf8_try_convert(info->first))) {
 		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("First Name"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 	}
-	if (info->last && info->last[0] && (utf8 = gaim_try_conv_to_utf8(info->last))) {
+	if (info->last && info->last[0] && (utf8 = gaim_utf8_try_convert(info->last))) {
 		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Last Name"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 	}
-	if (info->email && info->email[0] && (utf8 = gaim_try_conv_to_utf8(info->email))) {
+	if (info->email && info->email[0] && (utf8 = gaim_utf8_try_convert(info->email))) {
 		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Email Address"), ":</b> <a href=\"mailto:", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
 	}
@@ -3981,10 +3971,10 @@
 		int i;
 		for (i = 0; i < info->numaddresses; i++) {
-			if (info->email2[i] && info->email2[i][0] && (utf8 = gaim_try_conv_to_utf8(info->email2[i]))) {
+			if (info->email2[i] && info->email2[i][0] && (utf8 = gaim_utf8_try_convert(info->email2[i]))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Email Address"), ":</b> <a href=\"mailto:", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
 			}
 		}
 	}
-	if (info->mobile && info->mobile[0] && (utf8 = gaim_try_conv_to_utf8(info->mobile))) {
+	if (info->mobile && info->mobile[0] && (utf8 = gaim_utf8_try_convert(info->mobile))) {
 		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Mobile Phone"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 	}
@@ -4006,8 +3996,8 @@
 		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Age"), ":</b> ", age, NULL);  g_free(tmp);
 	}
-	if (info->personalwebpage && info->personalwebpage[0] && (utf8 = gaim_try_conv_to_utf8(info->personalwebpage))) {
+	if (info->personalwebpage && info->personalwebpage[0] && (utf8 = gaim_utf8_try_convert(info->personalwebpage))) {
 		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Personal Web Page"), ":</b> <a href=\"", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
 	}
-	if (info->info && info->info[0] && (utf8 = gaim_try_conv_to_utf8(info->info))) {
+	if (info->info && info->info[0] && (utf8 = gaim_utf8_try_convert(info->info))) {
 		tmp = buf;  buf = g_strconcat(tmp, "<hr><b>", _("Additional Information"), ":</b><br>", utf8, NULL);  g_free(tmp); g_free(utf8);
 	}
@@ -4015,14 +4005,14 @@
 	if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) {
 		tmp = buf;  buf = g_strconcat(tmp, "<b>", _("Home Address"), ":</b>", NULL);  g_free(tmp);
-		if (info->homeaddr && info->homeaddr[0] && (utf8 = gaim_try_conv_to_utf8(info->homeaddr))) {
+		if (info->homeaddr && info->homeaddr[0] && (utf8 = gaim_utf8_try_convert(info->homeaddr))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Address"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 		}
-		if (info->homecity && info->homecity[0] && (utf8 = gaim_try_conv_to_utf8(info->homecity))) {
+		if (info->homecity && info->homecity[0] && (utf8 = gaim_utf8_try_convert(info->homecity))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("City"), ":</b> ", utf8,  NULL);  g_free(tmp); g_free(utf8);
 		}
-		if (info->homestate && info->homestate[0] && (utf8 = gaim_try_conv_to_utf8(info->homestate))) {
+		if (info->homestate && info->homestate[0] && (utf8 = gaim_utf8_try_convert(info->homestate))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("State"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 		}
-		if (info->homezip && info->homezip[0] && (utf8 = gaim_try_conv_to_utf8(info->homezip))) {
+		if (info->homezip && info->homezip[0] && (utf8 = gaim_utf8_try_convert(info->homezip))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Zip Code"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 		}
@@ -4031,14 +4021,14 @@
 	if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) {
 		tmp = buf;  buf = g_strconcat(tmp, "<b>", _("Work Address"), ":</b>", NULL);  g_free(tmp);
-		if (info->workaddr && info->workaddr[0] && (utf8 = gaim_try_conv_to_utf8(info->workaddr))) {
+		if (info->workaddr && info->workaddr[0] && (utf8 = gaim_utf8_try_convert(info->workaddr))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Address"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 		}
-		if (info->workcity && info->workcity[0] && (utf8 = gaim_try_conv_to_utf8(info->workcity))) {
+		if (info->workcity && info->workcity[0] && (utf8 = gaim_utf8_try_convert(info->workcity))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("City"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 		}
-		if (info->workstate && info->workstate[0] && (utf8 = gaim_try_conv_to_utf8(info->workstate))) {
+		if (info->workstate && info->workstate[0] && (utf8 = gaim_utf8_try_convert(info->workstate))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("State"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 		}
-		if (info->workzip && info->workzip[0] && (utf8 = gaim_try_conv_to_utf8(info->workzip))) {
+		if (info->workzip && info->workzip[0] && (utf8 = gaim_utf8_try_convert(info->workzip))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Zip Code"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 		}
@@ -4047,14 +4037,14 @@
 	if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) {
 		tmp = buf;  buf = g_strconcat(tmp, "<b>", _("Work Information"), ":</b>", NULL);  g_free(tmp);
-		if (info->workcompany && info->workcompany[0] && (utf8 = gaim_try_conv_to_utf8(info->workcompany))) {
+		if (info->workcompany && info->workcompany[0] && (utf8 = gaim_utf8_try_convert(info->workcompany))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Company"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 		}
-		if (info->workdivision && info->workdivision[0] && (utf8 = gaim_try_conv_to_utf8(info->workdivision))) {
+		if (info->workdivision && info->workdivision[0] && (utf8 = gaim_utf8_try_convert(info->workdivision))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Division"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 		}
-		if (info->workposition && info->workposition[0] && (utf8 = gaim_try_conv_to_utf8(info->workposition))) {
+		if (info->workposition && info->workposition[0] && (utf8 = gaim_utf8_try_convert(info->workposition))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Position"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
 		}
-		if (info->workwebpage && info->workwebpage[0] && (utf8 = gaim_try_conv_to_utf8(info->workwebpage))) {
+		if (info->workwebpage && info->workwebpage[0] && (utf8 = gaim_utf8_try_convert(info->workwebpage))) {
 			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Web Page"), ":</b> <a href=\"", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
 		}
@@ -4083,5 +4073,5 @@
 	va_end(ap);
 
-	if (info->uin && info->nick && info->nick[0] && (utf8 = gaim_try_conv_to_utf8(info->nick))) {
+	if (info->uin && info->nick && info->nick[0] && (utf8 = gaim_utf8_try_convert(info->nick))) {
 		g_snprintf(who, sizeof(who), "%u", info->uin);
 		serv_got_alias(gc, who, utf8);
@@ -4098,7 +4088,9 @@
 static int gaim_popup(aim_session_t *sess, aim_frame_t *fr, ...)
 {
+	GaimConnection *gc = sess->aux_data;
+	gchar *text;
+	va_list ap;
 	char *msg, *url;
 	fu16_t wid, hei, delay;
-	va_list ap;
 
 	va_start(ap, fr);
@@ -4110,10 +4102,13 @@
 	va_end(ap);
 
-	serv_got_popup(msg, url, wid, hei);
+	text = g_strdup_printf("%s<br><a href=\"%s\">%s</a>", msg, url, url);
+	gaim_notify_formatted(gc, NULL, _("Pop-Up Message"), NULL, text, NULL, NULL);
+	g_free(text);
 
 	return 1;
 }
 
-static int gaim_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...) {
+static int gaim_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
+{
 	GaimConnection *gc = sess->aux_data;
 	gchar *secondary;
@@ -4248,10 +4243,10 @@
 
 static void oscar_keepalive(GaimConnection *gc) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	aim_flap_nop(od->sess, od->conn);
 }
 
 static int oscar_send_typing(GaimConnection *gc, const char *name, int typing) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	struct direct_im *dim = find_direct_im(od, name);
 	if (dim)
@@ -4267,5 +4262,5 @@
 		for (list=gc->account->deny; (list && aim_sncmp(name, list->data)); list=list->next);
 		if (!list) {
-			struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(name));
+			struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, name));
 			if (bi && bi->typingnot) {
 				if (typing == GAIM_TYPING)
@@ -4281,8 +4276,8 @@
 }
 static void oscar_ask_direct_im(GaimConnection *gc, const char *name);
-static int gaim_odc_send_im(aim_session_t *, aim_conn_t *, const char *, GaimImFlags);
-
-static int oscar_send_im(GaimConnection *gc, const char *name, const char *message, GaimImFlags imflags) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+static int gaim_odc_send_im(aim_session_t *, aim_conn_t *, const char *, GaimConvImFlags);
+
+static int oscar_send_im(GaimConnection *gc, const char *name, const char *message, GaimConvImFlags imflags) {
+	OscarData *od = (OscarData *)gc->proto_data;
 	struct direct_im *dim = find_direct_im(od, name);
 	int ret = 0;
@@ -4294,5 +4289,5 @@
 		/* If we're directly connected, send a direct IM */
 		ret = gaim_odc_send_im(od->sess, dim->conn, message, imflags);
-	} else if (imflags & GAIM_IM_IMAGES) {
+	} else if (imflags & GAIM_CONV_IM_IMAGES) {
 		/* Trying to send an IM image outside of a direct connection. */
 		oscar_ask_direct_im(gc, name);
@@ -4304,8 +4299,8 @@
 		gsize len;
 
-		bi = g_hash_table_lookup(od->buddyinfo, normalize(name));
+		bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, name));
 		if (!bi) {
 			bi = g_new0(struct buddyinfo, 1);
-			g_hash_table_insert(od->buddyinfo, g_strdup(normalize(name)), bi);
+			g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(gc->account, name)), bi);
 		}
 
@@ -4319,5 +4314,5 @@
 			args.featureslen = sizeof(features_aim);
 
-			if (imflags & GAIM_IM_AUTO_RESP)
+			if (imflags & GAIM_CONV_IM_AUTO_RESP)
 				args.flags |= AIM_IMFLAGS_AWAY;
 		}
@@ -4341,6 +4336,8 @@
 				args.iconstamp = st.st_mtime;
 
-				if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time))
+				if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time)) {
 					bi->ico_informed = FALSE;
+					bi->ico_sent     = FALSE;
+				}
 
 				if (!bi->ico_informed) {
@@ -4362,7 +4359,7 @@
 		/* For ICQ send newlines as CR/LF, for AIM send newlines as <BR> */
 		if (isdigit(name[0]))
-			tmpmsg = add_cr(message);
+			tmpmsg = gaim_str_add_cr(message);
 		else
-			tmpmsg = strdup_withhtml(message);
+			tmpmsg = gaim_strdup_withhtml(message);
 		len = strlen(tmpmsg);
 
@@ -4421,19 +4418,17 @@
 }
 
-static void oscar_get_info(GaimConnection *g, const char *name) {
-	struct oscar_data *od = (struct oscar_data *)g->proto_data;
-	if (od->icq)
+static void oscar_get_info(GaimConnection *gc, const char *name) {
+	OscarData *od = (OscarData *)gc->proto_data;
+
+	if (od->icq && isdigit(name[0]))
 		aim_icq_getallinfo(od->sess, name);
 	else
-		/* people want the away message on the top, so we get the away message
-		 * first and then get the regular info, since it's too difficult to
-		 * insert in the middle. i hate people. */
-		aim_getinfo(od->sess, od->conn, name, AIM_GETINFO_AWAYMESSAGE);
-}
-
-static void oscar_get_away(GaimConnection *g, const char *who) {
-	struct oscar_data *od = (struct oscar_data *)g->proto_data;
+		aim_locate_getinfoshort(od->sess, name, 0x00000003);
+}
+
+static void oscar_get_away(GaimConnection *gc, const char *who) {
+	OscarData *od = (OscarData *)gc->proto_data;
 	if (od->icq) {
-		GaimBuddy *budlight = gaim_find_buddy(g->account, who);
+		GaimBuddy *budlight = gaim_find_buddy(gc->account, who);
 		if (budlight)
 			if ((budlight->uc & 0xffff0000) >> 16)
@@ -4444,24 +4439,24 @@
 		else
 			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "Error: Could not find %s in local contact list, therefore unable to request status message.\n", who);
+					   "Error: Could not find %s in local buddy list, therefore unable to request status message.\n", who);
 	} else
-		aim_getinfo(od->sess, od->conn, who, AIM_GETINFO_GENERALINFO);
-}
-
-static void oscar_set_dir(GaimConnection *g, const char *first, const char *middle, const char *last,
+		aim_locate_getinfoshort(od->sess, who, 0x00000002);
+}
+
+static void oscar_set_dir(GaimConnection *gc, const char *first, const char *middle, const char *last,
 			  const char *maiden, const char *city, const char *state, const char *country, int web) {
 	/* XXX - some of these things are wrong, but i'm lazy */
-	struct oscar_data *od = (struct oscar_data *)g->proto_data;
-	aim_setdirectoryinfo(od->sess, od->conn, first, middle, last,
+	OscarData *od = (OscarData *)gc->proto_data;
+	aim_locate_setdirinfo(od->sess, first, middle, last,
 				maiden, NULL, NULL, city, state, NULL, 0, web);
 }
 
 static void oscar_set_idle(GaimConnection *gc, int time) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
-	aim_bos_setidle(od->sess, od->conn, time);
+	OscarData *od = (OscarData *)gc->proto_data;
+	aim_srv_setidle(od->sess, time);
 }
 
 static void oscar_set_info(GaimConnection *gc, const char *text) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	fu32_t flags = 0;
 	char *text_html = NULL;
@@ -4476,46 +4471,41 @@
 							  "again when you are fully connected."));
 
-	if (od->icq)
-		aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, NULL, 0, caps_icq);
-	else {
-		if (!text) {
-			aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, NULL, 0, caps_aim);
-			return;
-		}
+	if (!text) {
+		aim_locate_setprofile(od->sess, NULL, "", 0, NULL, NULL, 0);
+		return;
+	}
 		
-		text_html = strdup_withhtml(text);
-		flags = oscar_encoding_check(text_html);
-		if (flags & AIM_IMFLAGS_UNICODE) {
-			msg = g_convert(text_html, strlen(text_html), "UCS-2BE", "UTF-8", NULL, &msglen, NULL);
-			aim_bos_setprofile(od->sess, od->conn, "unicode-2-0", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim);
-			g_free(msg);
-		} else if (flags & AIM_IMFLAGS_ISO_8859_1) {
-			msg = g_convert(text_html, strlen(text_html), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL);
-			aim_bos_setprofile(od->sess, od->conn, "iso-8859-1", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim);
-			g_free(msg);
-		} else {
-			msglen = strlen(text_html);
-			aim_bos_setprofile(od->sess, od->conn, "us-ascii", text_html, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim);
-		}
-
-		if (msglen > od->rights.maxsiglen) {
-			gchar *errstr;
-			errstr = g_strdup_printf(ngettext("The maximum profile length of %d byte "
-									 "has been exceeded.  Gaim has truncated it for you.",
-									 "The maximum profile length of %d bytes "
-									 "has been exceeded.  Gaim has truncated it for you.",
-									 od->rights.maxsiglen), od->rights.maxsiglen);
-			gaim_notify_warning(gc, NULL, _("Profile too long."), errstr);
-			g_free(errstr);
-		}
-
-		g_free(text_html);
-
-	}
+	text_html = gaim_strdup_withhtml(text);
+	flags = oscar_encoding_check(text_html);
+	if (flags & AIM_IMFLAGS_UNICODE) {
+		msg = g_convert(text_html, strlen(text_html), "UCS-2BE", "UTF-8", NULL, &msglen, NULL);
+		aim_locate_setprofile(od->sess, "unicode-2-0", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0);
+		g_free(msg);
+	} else if (flags & AIM_IMFLAGS_ISO_8859_1) {
+		msg = g_convert(text_html, strlen(text_html), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL);
+		aim_locate_setprofile(od->sess, "iso-8859-1", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0);
+		g_free(msg);
+	} else {
+		msglen = strlen(text_html);
+		aim_locate_setprofile(od->sess, "us-ascii", text_html, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0);
+	}
+
+	if (msglen > od->rights.maxsiglen) {
+		gchar *errstr;
+		errstr = g_strdup_printf(ngettext("The maximum profile length of %d byte "
+								 "has been exceeded.  Gaim has truncated it for you.",
+								 "The maximum profile length of %d bytes "
+								 "has been exceeded.  Gaim has truncated it for you.",
+								 od->rights.maxsiglen), od->rights.maxsiglen);
+		gaim_notify_warning(gc, NULL, _("Profile too long."), errstr);
+		g_free(errstr);
+	}
+
+	g_free(text_html);
 
 	return;
 }
 
-static void oscar_set_away_aim(GaimConnection *gc, struct oscar_data *od, const char *text)
+static void oscar_set_away_aim(GaimConnection *gc, OscarData *od, const char *text)
 {
 	fu32_t flags = 0;
@@ -4538,26 +4528,26 @@
 
 	if (!text) {
-		aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, "", 0, caps_aim);
+		aim_locate_setprofile(od->sess, NULL, NULL, 0, NULL, "", 0);
 		return;
 	}
 
-	text_html = strdup_withhtml(text);
+	text_html = gaim_strdup_withhtml(text);
 	flags = oscar_encoding_check(text_html);
 	if (flags & AIM_IMFLAGS_UNICODE) {
 		msg = g_convert(text_html, strlen(text_html), "UCS-2BE", "UTF-8", NULL, &msglen, NULL);
-		aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "unicode-2-0", msg, 
-			(msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim);
+		aim_locate_setprofile(od->sess, NULL, NULL, 0, "unicode-2-0", msg, 
+			(msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen));
 		g_free(msg);
 		gc->away = g_strndup(text, od->rights.maxawaymsglen/2);
 	} else if (flags & AIM_IMFLAGS_ISO_8859_1) {
 		msg = g_convert(text_html, strlen(text_html), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL);
-		aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "iso-8859-1", msg, 
-			(msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim);
+		aim_locate_setprofile(od->sess, NULL, NULL, 0, "iso-8859-1", msg, 
+			(msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen));
 		g_free(msg);
 		gc->away = g_strndup(text_html, od->rights.maxawaymsglen);
 	} else {
 		msglen = strlen(text_html);
-		aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "us-ascii", text_html, 
-			(msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim);
+		aim_locate_setprofile(od->sess, NULL, NULL, 0, "us-ascii", text_html, 
+			(msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen));
 		gc->away = g_strndup(text_html, od->rights.maxawaymsglen);
 	}
@@ -4579,5 +4569,5 @@
 }
 
-static void oscar_set_away_icq(GaimConnection *gc, struct oscar_data *od, const char *state, const char *message)
+static void oscar_set_away_icq(GaimConnection *gc, OscarData *od, const char *state, const char *message)
 {
 	GaimAccount *account = gaim_connection_get_account(gc);
@@ -4631,5 +4621,5 @@
 static void oscar_set_away(GaimConnection *gc, const char *state, const char *message)
 {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 
 	if (od->icq)
@@ -4642,5 +4632,5 @@
 
 static void oscar_warn(GaimConnection *gc, const char *name, int anon) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	aim_im_warn(od->sess, od->conn, name, anon ? AIM_WARN_ANON : 0);
 }
@@ -4648,5 +4638,5 @@
 static void oscar_dir_search(GaimConnection *gc, const char *first, const char *middle, const char *last,
 			     const char *maiden, const char *city, const char *state, const char *country, const char *email) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	if (strlen(email))
 		aim_search_address(od->sess, od->conn, email);
@@ -4654,5 +4644,5 @@
 
 static void oscar_add_buddy(GaimConnection *gc, const char *name, GaimGroup *g) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 #ifdef NOSSI
 	aim_add_buddy(od->sess, od->conn, name);
@@ -4673,5 +4663,5 @@
 
 static void oscar_add_buddies(GaimConnection *gc, GList *buddies) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 #ifdef NOSSI
 	char buf[MSG_LEN];
@@ -4679,5 +4669,5 @@
 	while (buddies) {
 		if (n > MSG_LEN - 18) {
-			aim_bos_setbuddylist(od->sess, od->conn, buf);
+			aim_buddylist_set(od->sess, od->conn, buf);
 			n = 0;
 		}
@@ -4685,15 +4675,9 @@
 		buddies = buddies->next;
 	}
-	aim_bos_setbuddylist(od->sess, od->conn, buf);
+	aim_buddylist_set(od->sess, od->conn, buf);
 #else
 	if (od->sess->ssi.received_data) {
 		while (buddies) {
-			GaimBuddy *buddy = gaim_find_buddy(gc->account, (const char *)buddies->data);
-			GaimGroup *group = gaim_find_buddys_group(buddy);
-			if (buddy && group) {
-				gaim_debug(GAIM_DEBUG_INFO, "oscar",
-						   "ssi: adding buddy %s to group %s\n", (const char *)buddies->data, group->name);
-				aim_ssi_addbuddy(od->sess, buddy->name, group->name, gaim_get_buddy_alias_only(buddy), NULL, NULL, 0);
-			}
+			oscar_add_buddy(gc, (const char *)buddies->data, NULL);
 			buddies = buddies->next;
 		}
@@ -4703,5 +4687,5 @@
 
 static void oscar_remove_buddy(GaimConnection *gc, const char *name, const char *group) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 #ifdef NOSSI
 	aim_remove_buddy(od->sess, od->conn, name);
@@ -4716,5 +4700,5 @@
 
 static void oscar_remove_buddies(GaimConnection *gc, GList *buddies, const char *group) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 #ifdef NOSSI
 	GList *cur;
@@ -4735,5 +4719,5 @@
 #ifndef NOSSI
 static void oscar_move_buddy(GaimConnection *gc, const char *name, const char *old_group, const char *new_group) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	if (od->sess->ssi.received_data && strcmp(old_group, new_group)) {
 		gaim_debug(GAIM_DEBUG_INFO, "oscar",
@@ -4744,5 +4728,5 @@
 
 static void oscar_alias_buddy(GaimConnection *gc, const char *name, const char *alias) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	if (od->sess->ssi.received_data) {
 		char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, name);
@@ -4756,5 +4740,5 @@
 
 static void oscar_rename_group(GaimConnection *g, const char *old_group, const char *new_group, GList *members) {
-	struct oscar_data *od = (struct oscar_data *)g->proto_data;
+	OscarData *od = (OscarData *)g->proto_data;
 
 	if (od->sess->ssi.received_data) {
@@ -4780,5 +4764,5 @@
 static int gaim_ssi_parseerr(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	va_list ap;
 	fu16_t reason;
@@ -4807,5 +4791,5 @@
 static int gaim_ssi_parserights(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	int numtypes, i;
 	fu16_t *maxitems;
@@ -4840,5 +4824,5 @@
 	GaimConnection *gc = sess->aux_data;
 	GaimAccount *account = gaim_connection_get_account(gc);
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	struct aim_ssi_item *curitem;
 	int tmp;
@@ -4862,11 +4846,12 @@
 	/* Add from server list to local list */
 	for (curitem=sess->ssi.local; curitem; curitem=curitem->next) {
+		if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL)))
 		switch (curitem->type) {
 			case 0x0000: { /* Buddy */
 				if (curitem->name) {
 					char *gname = aim_ssi_itemlist_findparentname(sess->ssi.local, curitem->name);
-					char *gname_utf8 = gaim_try_conv_to_utf8(gname);
+					char *gname_utf8 = gname ? gaim_utf8_try_convert(gname) : NULL;
 					char *alias = aim_ssi_getalias(sess->ssi.local, gname, curitem->name);
-					char *alias_utf8 = gaim_try_conv_to_utf8(alias);
+					char *alias_utf8 = alias ? gaim_utf8_try_convert(alias) : NULL;
 					GaimBuddy *buddy = gaim_find_buddy(gc->account, curitem->name);
 					/* Should gname be freed here? -- elb */
@@ -4893,6 +4878,6 @@
 						export = TRUE;
 					}
-					free(gname_utf8);
-					free(alias_utf8);
+					g_free(gname_utf8);
+					g_free(alias_utf8);
 				}
 			} break;
@@ -4958,5 +4943,5 @@
 		GaimGroup *group;
 		GaimBuddy *buddy;
-		struct gaim_buddy_list *blist;
+		GaimBuddyList *blist;
 		GSList *cur;
 
@@ -4975,9 +4960,8 @@
 						buddy = (GaimBuddy *)bnode;
 						if (buddy->account == gc->account) {
-							gchar *servernick = gaim_buddy_get_setting(buddy, "servernick");
-							if (servernick) {
+							const char *servernick = gaim_buddy_get_setting(buddy, "servernick");
+							if (servernick)
 								serv_got_alias(gc, buddy->name, servernick);
-								g_free(servernick);
-							}
+
 							if (aim_ssi_itemlist_exists(sess->ssi.local, buddy->name)) {
 								/* Store local alias on server */
@@ -5061,5 +5045,5 @@
 			}
 
-			case 0x000e: { /* contact requires authorization */
+			case 0x000e: { /* buddy requires authorization */
 				if ((retval->action == AIM_CB_SSI_ADD) && (retval->name))
 					gaim_auth_sendrequest(gc, retval->name);
@@ -5112,5 +5096,5 @@
 	gaim_request_yes_no(gc, NULL, _("Authorization Given"), dialog_msg,
 						0, data,
-						G_CALLBACK(gaim_icq_contactadd),
+						G_CALLBACK(gaim_icq_buddyadd),
 						G_CALLBACK(oscar_free_name_data));
 
@@ -5185,9 +5169,9 @@
 	if (reply) {
 		/* Granted */
-		dialog_msg = g_strdup_printf(_("The user %s has granted your request to add them to your contact list."), nombre);
+		dialog_msg = g_strdup_printf(_("The user %s has granted your request to add them to your buddy list."), nombre);
 		gaim_notify_info(gc, NULL, _("Authorization Granted"), dialog_msg);
 	} else {
 		/* Denied */
-		dialog_msg = g_strdup_printf(_("The user %s has denied your request to add them to your contact list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
+		dialog_msg = g_strdup_printf(_("The user %s has denied your request to add them to your buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
 		gaim_notify_info(gc, NULL, _("Authorization Denied"), dialog_msg);
 	}
@@ -5211,5 +5195,5 @@
 	gaim_debug(GAIM_DEBUG_INFO, "oscar",
 			   "ssi: %s added you to their buddy list\n", sn);
-	show_got_added(gc, NULL, sn, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
+	gaim_account_notify_added(gc->account, NULL, sn, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
 
 	return 1;
@@ -5238,5 +5222,5 @@
 
 static void oscar_join_chat(GaimConnection *g, GHashTable *data) {
-	struct oscar_data *od = (struct oscar_data *)g->proto_data;
+	OscarData *od = (OscarData *)g->proto_data;
 	aim_conn_t *cur;
 	char *name, *exchange;
@@ -5264,5 +5248,5 @@
 
 static void oscar_chat_invite(GaimConnection *g, int id, const char *message, const char *name) {
-	struct oscar_data *od = (struct oscar_data *)g->proto_data;
+	OscarData *od = (OscarData *)g->proto_data;
 	struct chat_connection *ccon = find_oscar_chat(g, id);
 	
@@ -5275,5 +5259,5 @@
 
 static void oscar_chat_leave(GaimConnection *g, int id) {
-	struct oscar_data *od = g ? (struct oscar_data *)g->proto_data : NULL;
+	OscarData *od = g ? (OscarData *)g->proto_data : NULL;
 	GSList *bcs = g->buddy_chats;
 	GaimConversation *b = NULL;
@@ -5284,5 +5268,5 @@
 		count++;
 		b = (GaimConversation *)bcs->data;
-		if (id == gaim_chat_get_id(GAIM_CHAT(b)))
+		if (id == gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)))
 			break;
 		bcs = bcs->next;
@@ -5296,5 +5280,5 @@
 			   "Attempting to leave room %s (currently in %d rooms)\n", b->name, count);
 	
-	c = find_oscar_chat(g, gaim_chat_get_id(GAIM_CHAT(b)));
+	c = find_oscar_chat(g, gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)));
 	if (c != NULL) {
 		if (od)
@@ -5309,9 +5293,9 @@
 	}
 	/* we do this because with Oscar it doesn't tell us we left */
-	serv_got_chat_left(g, gaim_chat_get_id(GAIM_CHAT(b)));
+	serv_got_chat_left(g, gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)));
 }
 
 static int oscar_chat_send(GaimConnection *g, int id, const char *message) {
-	struct oscar_data *od = (struct oscar_data *)g->proto_data;
+	OscarData *od = (OscarData *)g->proto_data;
 	GSList *bcs = g->buddy_chats;
 	GaimConversation *b = NULL;
@@ -5322,5 +5306,5 @@
 	while (bcs) {
 		b = (GaimConversation *)bcs->data;
-		if (id == gaim_chat_get_id(GAIM_CHAT(b)))
+		if (id == gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)))
 			break;
 		bcs = bcs->next;
@@ -5357,5 +5341,5 @@
 		return -E2BIG;
 
-	buf2 = strip_html(buf);
+	buf2 = gaim_markup_strip_html(buf);
 	if (strlen(buf2) > c->maxvis) {
 		g_free(buf2);
@@ -5384,14 +5368,21 @@
 static void oscar_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne)
 {
+	GaimAccount *account = NULL;
+	GaimConnection *gc = NULL;
+	OscarData *od = NULL;
 	char *emblems[4] = {NULL,NULL,NULL,NULL};
 	int i = 0;
+	aim_userinfo_t *userinfo = NULL;
+
+	if (b != NULL)
+		account = b->account;
+	if (account != NULL)
+		gc = account->gc;
+	if (gc != NULL)
+		od = gc->proto_data;
 
 	if (!GAIM_BUDDY_IS_ONLINE(b)) {
-		GaimAccount *account;
-		GaimConnection *gc;
-		struct oscar_data *od;
 		char *gname;
-		if ((b->name) && (account = b->account) && (gc = account->gc) && 
-			(od = gc->proto_data) && (od->sess->ssi.received_data) && 
+		if ((b->name) && (od) && (od->sess->ssi.received_data) && 
 			(gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name)) && 
 			(aim_ssi_waitingforauth(od->sess->ssi.local, gname, b->name))) {
@@ -5432,4 +5423,11 @@
 /*	if (b->uc & UC_UNCONFIRMED && i < 4)
 		emblems[i++] = "unconfirmed"; */
+
+	if ((i < 4) && (od != NULL)) {
+		userinfo = aim_locate_finduserinfo(od->sess, b->name);
+		if ((userinfo != NULL) && (userinfo->capabilities & AIM_CAPS_SECUREIM))
+			emblems[i++] = "secure";
+	}
+
 	*se = emblems[0];
 	*sw = emblems[1];
@@ -5440,51 +5438,71 @@
 static char *oscar_tooltip_text(GaimBuddy *b) {
 	GaimConnection *gc = b->account->gc;
-	struct oscar_data *od = gc->proto_data;
-	struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(b->name));
-	gchar *tmp, *yay = g_strdup("");
+	OscarData *od = gc->proto_data;
+	struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(b->account, b->name));
+	aim_userinfo_t *userinfo = aim_locate_finduserinfo(od->sess, b->name);
+	gchar *tmp = NULL, *ret = g_strdup("");
 
 	if (GAIM_BUDDY_IS_ONLINE(b)) {
 		if (isdigit(b->name[0])) {
-			char *tmp, *status;
+			char *status;
 			status = gaim_icq_status((b->uc & 0xffff0000) >> 16);
-			tmp = yay;
-			yay = g_strconcat(tmp, _("<b>Status:</b> "), status, "\n", NULL);
+			tmp = ret;
+			ret = g_strconcat(tmp, _("<b>Status:</b> "), status, "\n", NULL);
 			g_free(tmp);
 			g_free(status);
 		}
 
-		if (bi) {
-			char *tstr = sec_to_text(time(NULL) - bi->signon + 
+		if (userinfo != NULL) {
+			char *tstr = gaim_str_seconds_to_string(time(NULL) - userinfo->onlinesince +
 				(gc->login_time_official ? gc->login_time_official - gc->login_time : 0));
-			tmp = yay;
-			yay = g_strconcat(tmp, _("<b>Logged In:</b> "), tstr, "\n", NULL);
-			free(tmp);
-			free(tstr);
-
-			if (bi->ipaddr) {
-				char *tstr =  g_strdup_printf("%hhd.%hhd.%hhd.%hhd",
-								(bi->ipaddr & 0xff000000) >> 24,
-								(bi->ipaddr & 0x00ff0000) >> 16,
-								(bi->ipaddr & 0x0000ff00) >> 8,
-								(bi->ipaddr & 0x000000ff));
-				tmp = yay;
-				yay = g_strconcat(tmp, _("<b>IP Address:</b> "), tstr, "\n", NULL);
-				free(tmp);
-				free(tstr);
-			}
-
-			if (bi->caps) {
-				char *caps = caps_string(bi->caps);
-				tmp = yay;
-				yay = g_strconcat(tmp, _("<b>Capabilities:</b> "), caps, "\n", NULL);
-				free(tmp);
-			}
-
-			if (bi->availmsg && !(b->uc & UC_UNAVAILABLE)) {
-				gchar *escaped = g_markup_escape_text(bi->availmsg, strlen(bi->availmsg));
-				tmp = yay;
-				yay = g_strconcat(tmp, _("<b>Available:</b> "), escaped, "\n", NULL);
-				free(tmp);
-				g_free(escaped);
+			tmp = ret;
+			ret = g_strconcat(tmp, _("<b>Logged In:</b> "), tstr, "\n", NULL);
+			g_free(tmp);
+			g_free(tstr);
+		}
+
+		if ((bi != NULL) && (bi->ipaddr)) {
+			char *tstr =  g_strdup_printf("%hhu.%hhu.%hhu.%hhu",
+							(bi->ipaddr & 0xff000000) >> 24,
+							(bi->ipaddr & 0x00ff0000) >> 16,
+							(bi->ipaddr & 0x0000ff00) >> 8,
+							(bi->ipaddr & 0x000000ff));
+			tmp = ret;
+			ret = g_strconcat(tmp, _("<b>IP Address:</b> "), tstr, "\n", NULL);
+			g_free(tmp);
+			g_free(tstr);
+		}
+
+		if ((userinfo != NULL) && (userinfo->capabilities)) {
+			char *caps = caps_string(userinfo->capabilities);
+			tmp = ret;
+			ret = g_strconcat(tmp, _("<b>Capabilities:</b> "), caps, "\n", NULL);
+			g_free(tmp);
+		}
+
+		if ((bi != NULL) && (bi->availmsg != NULL) && !(b->uc & UC_UNAVAILABLE)) {
+			gchar *escaped = g_markup_escape_text(bi->availmsg, strlen(bi->availmsg));
+			tmp = ret;
+			ret = g_strconcat(tmp, _("<b>Available:</b> "), escaped, "\n", NULL);
+			g_free(tmp);
+			g_free(escaped);
+		}
+
+		if ((userinfo != NULL) && (userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) {
+			gchar *away_utf8 = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
+			if (away_utf8 != NULL) {
+				gchar *tmp1, *tmp2;
+				const char *tmp3;
+				tmp1 = gaim_strreplace(away_utf8, "<BR>", "\n");
+				tmp2 = gaim_markup_strip_html(tmp1);
+				g_free(tmp1);
+				tmp1 = g_markup_escape_text(tmp2, strlen(tmp2));
+				g_free(tmp2);
+				tmp3 = gaim_str_sub_away_formatters(tmp1, gaim_account_get_username(gaim_connection_get_account(gc)));
+				g_free(tmp1);
+				tmp = ret;
+				ret = g_strconcat(tmp, _("<b>Away Message:</b> "), tmp3, "\n", NULL);
+				g_free(tmp);
+				g_free(away_utf8);
 			}
 		}
@@ -5492,10 +5510,10 @@
 		char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name);
 		if (aim_ssi_waitingforauth(od->sess->ssi.local, gname, b->name)) {
-			tmp = yay;
-			yay = g_strconcat(tmp, _("<b>Status:</b> Not Authorized"), "\n", NULL);
+			tmp = ret;
+			ret = g_strconcat(tmp, _("<b>Status:</b> Not Authorized"), "\n", NULL);
 			g_free(tmp);
 		} else {
-			tmp = yay;
-			yay = g_strconcat(tmp, _("<b>Status:</b> Offline"), "\n", NULL);
+			tmp = ret;
+			ret = g_strconcat(tmp, _("<b>Status:</b> Offline"), "\n", NULL);
 			g_free(tmp);
 		}
@@ -5503,12 +5521,12 @@
 
 	/* remove the trailing newline character */
-	if (yay)
-		yay[strlen(yay)-1] = '\0';
-	return yay;
+	if (ret)
+		ret[strlen(ret)-1] = '\0';
+	return ret;
 }
 
 static char *oscar_status_text(GaimBuddy *b) {
 	GaimConnection *gc = b->account->gc;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	gchar *ret = NULL;
 
@@ -5519,5 +5537,5 @@
 			ret = g_strdup(_("Away"));
 	} else if (GAIM_BUDDY_IS_ONLINE(b)) {
-		struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(b->name));
+		struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(b->account, b->name));
 		if (bi->availmsg)
 			ret = g_markup_escape_text(bi->availmsg, strlen(bi->availmsg));
@@ -5536,9 +5554,10 @@
 static int oscar_icon_req(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	va_list ap;
 	fu16_t type;
 	fu8_t flags = 0, length = 0;
 	char *md5 = NULL;
+
 
 	va_start(ap, fr);
@@ -5598,5 +5617,5 @@
 static int gaim_odc_initiate(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	GaimConversation *cnv;
 	struct direct_im *dim;
@@ -5646,5 +5665,5 @@
 	double percent;
 	GaimConnection *gc = sess->aux_data;
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	GaimConversation *c;
 	struct direct_im *dim;
@@ -5662,6 +5681,5 @@
 	}
 	/* XXX is this really necessary? */
-	while (gtk_events_pending())
-		gtk_main_iteration();
+	gaim_core_mainloop_finish_events();
 
 	c = gaim_find_conversation_with_account(sn, gaim_connection_get_account(gc));
@@ -5705,5 +5723,5 @@
 static int gaim_odc_incoming(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
-	GaimImFlags imflags = 0;
+	GaimConvImFlags imflags = 0;
 	GString *newmsg = g_string_new("");
 	GSList *images = NULL;
@@ -5726,5 +5744,5 @@
 
 	if (isawaymsg)
-		imflags |= GAIM_IM_AUTO_RESP;
+		imflags |= GAIM_CONV_IM_AUTO_RESP;
 
 	/* message has a binary trailer */
@@ -5790,5 +5808,5 @@
 		/* set the flag if we caught any images */
 		if (images)
-			imflags |= GAIM_IM_IMAGES;
+			imflags |= GAIM_CONV_IM_IMAGES;
 	} else {
 		g_string_append_len(newmsg, msg, len);
@@ -5840,10 +5858,10 @@
 }
 
-static int gaim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *message, GaimImFlags imflags) {
+static int gaim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *message, GaimConvImFlags imflags) {
 	char *buf;
 	size_t len;
 	int ret;
 
-	if (imflags & GAIM_IM_IMAGES) {
+	if (imflags & GAIM_CONV_IM_IMAGES) {
 		GString *msg = g_string_new("");
 		GString *data = g_string_new("<BINARY>");
@@ -5872,13 +5890,13 @@
 					g_string_append_printf(msg,
 						"<IMG SRC=\"file://%s\" ID=\"%d\" DATASIZE=\"%d\">",
-						image->filename, oscar_id, image->size);
+						image->filename, oscar_id, (int)image->size);
 				else
 					g_string_append_printf(msg,
 						"<IMG ID=\"%d\" DATASIZE=\"%d\">",
-						oscar_id, image->size);
+						oscar_id, (int)image->size);
 
 				/* ... and append the data to the binary section ... */
 				g_string_append_printf(data, "<DATA ID=\"%d\" SIZE=\"%d\">",
-					oscar_id, image->size);
+					oscar_id, (int)image->size);
 				data = g_string_append_len(data, image->data, image->size);
 				data = g_string_append(data, "</DATA>");
@@ -5915,5 +5933,5 @@
 
 	/* XXX - The last parameter below is the encoding.  Let Paco-Paco do something with it. */
-	if (imflags & GAIM_IM_AUTO_RESP)
+	if (imflags & GAIM_CONV_IM_AUTO_RESP)
 		ret =  aim_odc_send_im(sess, conn, buf, len, 0, 1);
 	else
@@ -5937,5 +5955,5 @@
 static void oscar_direct_im(struct ask_do_dir_im *data) {
 	GaimConnection *gc = data->gc;
-	struct oscar_data *od;
+	OscarData *od;
 	struct direct_im *dim;
 
@@ -5946,5 +5964,5 @@
 	}
 
-	od = (struct oscar_data *)gc->proto_data;
+	od = (OscarData *)gc->proto_data;
 
 	dim = find_direct_im(od, data->who);
@@ -6002,5 +6020,5 @@
 static void oscar_set_permit_deny(GaimConnection *gc) {
 	GaimAccount *account = gaim_connection_get_account(gc);
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 #ifdef NOSSI
 	GSList *list, *g = gaim_blist_groups(), *g1;
@@ -6066,5 +6084,5 @@
 		oscar_set_permit_deny(gc);
 #else
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to add a permit\n");
 	if (od->sess->ssi.received_data)
@@ -6078,5 +6096,5 @@
 		oscar_set_permit_deny(gc);
 #else
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to add a deny\n");
 	if (od->sess->ssi.received_data)
@@ -6090,5 +6108,5 @@
 		oscar_set_permit_deny(gc);
 #else
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to delete a permit\n");
 	if (od->sess->ssi.received_data)
@@ -6102,5 +6120,5 @@
 		oscar_set_permit_deny(gc);
 #else
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
+	OscarData *od = (OscarData *)gc->proto_data;
 	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to delete a deny\n");
 	if (od->sess->ssi.received_data)
@@ -6111,5 +6129,5 @@
 static GList *oscar_away_states(GaimConnection *gc)
 {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	GList *m = NULL;
 
@@ -6128,8 +6146,62 @@
 }
 
+static void oscar_ssi_editcomment(struct name_data *data, const char *text) {
+	OscarData *od = data->gc->proto_data;
+	GaimBuddy *b;
+	GaimGroup *g;
+
+	if (!(b = gaim_find_buddy(gaim_connection_get_account(data->gc), data->name))) {
+		oscar_free_name_data(data);
+		return;
+	}
+
+	if (!(g = gaim_find_buddys_group(b))) {
+		oscar_free_name_data(data);
+		return;
+	}
+
+	aim_ssi_editcomment(od->sess, g->name, data->name, text);
+	oscar_free_name_data(data);
+}
+
+static void oscar_buddycb_edit_comment(GaimConnection *gc, const char *name) {
+	OscarData *od = gc->proto_data;
+	struct name_data *data = g_new(struct name_data, 1);
+	GaimBuddy *b;
+	GaimGroup *g;
+	char *comment;
+	gchar *comment_utf8;
+
+	if (!(b = gaim_find_buddy(gaim_connection_get_account(gc), name)))
+		return;
+	if (!(g = gaim_find_buddys_group(b)))
+		return;
+	comment = aim_ssi_getcomment(od->sess->ssi.local, g->name, name);
+	comment_utf8 = comment ? gaim_utf8_try_convert(comment) : NULL;
+
+	data->gc = gc;
+	data->name = g_strdup(name);
+	data->nick = NULL;
+
+	gaim_request_input(gc, NULL, _("Buddy Comment:"), NULL,
+					   comment_utf8, TRUE, FALSE,
+					   _("OK"), G_CALLBACK(oscar_ssi_editcomment),
+					   _("Cancel"), G_CALLBACK(oscar_free_name_data),
+					   data);
+
+	free(comment);
+	g_free(comment_utf8);
+}
+
 static GList *oscar_buddy_menu(GaimConnection *gc, const char *who) {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	GList *m = NULL;
 	struct proto_buddy_menu *pbm;
+
+	pbm = g_new0(struct proto_buddy_menu, 1);
+	pbm->label = _("Edit Buddy Comment");
+	pbm->callback = oscar_buddycb_edit_comment;
+	pbm->gc = gc;
+	m = g_list_append(m, pbm);
 
 	if (od->icq) {
@@ -6143,11 +6215,11 @@
 	} else {
 		GaimBuddy *b = gaim_find_buddy(gc->account, who);
-		struct buddyinfo *bi;
+		aim_userinfo_t *userinfo;
 
 		if (b)
-			bi = g_hash_table_lookup(od->buddyinfo, normalize(b->name));
-
-		if (b && bi && aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), who) && GAIM_BUDDY_IS_ONLINE(b)) {
-			if (bi->caps & AIM_CAPS_DIRECTIM) {
+			userinfo = aim_locate_finduserinfo(od->sess, b->name);
+
+		if (b && userinfo && aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), who) && GAIM_BUDDY_IS_ONLINE(b)) {
+			if (userinfo->capabilities & AIM_CAPS_DIRECTIM) {
 				pbm = g_new0(struct proto_buddy_menu, 1);
 				pbm->label = _("Direct IM");
@@ -6157,5 +6229,5 @@
 			}
 
-			if (bi->caps & AIM_CAPS_SENDFILE) {
+			if (userinfo->capabilities & AIM_CAPS_SENDFILE) {
 				pbm = g_new0(struct proto_buddy_menu, 1);
 				pbm->label = _("Send File");
@@ -6165,5 +6237,5 @@
 			}
 #if 0
-			if (bi->caps & AIM_CAPS_GETFILE) {
+			if (userinfo->capabilities & AIM_CAPS_GETFILE) {
 				pbm = g_new0(struct proto_buddy_menu, 1);
 				pbm->label = _("Get File");
@@ -6191,5 +6263,5 @@
 
 static void oscar_format_screenname(GaimConnection *gc, const char *nick) {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	if (!aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), nick)) {
 		if (!aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH)) {
@@ -6217,5 +6289,5 @@
 static void oscar_confirm_account(GaimConnection *gc)
 {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
 
@@ -6230,5 +6302,5 @@
 static void oscar_show_email(GaimConnection *gc)
 {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
 
@@ -6243,5 +6315,5 @@
 static void oscar_change_email(GaimConnection *gc, const char *email)
 {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
 
@@ -6266,5 +6338,5 @@
 static void oscar_show_awaitingauth(GaimConnection *gc)
 {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	gchar *nombre, *text, *tmp;
 	GaimBlistNode *gnode, *cnode, *bnode;
@@ -6312,8 +6384,25 @@
 }
 
+static void search_by_email_cb(GaimConnection *gc, const char *email)
+{
+	serv_dir_search(gc, "", "", "", "", "", "", "", email);
+}
+
+static void oscar_show_find_email(GaimConnection *gc)
+{
+	gaim_request_input(gc, _("Find Buddy by E-mail"),
+					   _("Search for a buddy by e-mail address"),
+					   _("Type the e-mail address of the buddy you are "
+						 "searching for."),
+					   NULL, FALSE, FALSE,
+					   _("Search"), G_CALLBACK(search_by_email_cb),
+					   _("Cancel"), NULL, gc);
+}
+
 #if 0
 static void oscar_setavailmsg(GaimConnection *gc, char *text) {
-	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
-
+	OscarData *od = (OscarData *)gc->proto_data;
+
+	aim_locate_setprofile(od->sess, NULL, NULL, 0, NULL, "", 0);
 	aim_srv_setavailmsg(od->sess, text);
 }
@@ -6321,6 +6410,7 @@
 static void oscar_show_setavailmsg(GaimConnection *gc)
 {
-	gaim_request_input(gc, NULL, _("Available Message:"),
-					   NULL, _("Please talk to me, I'm lonely! (and single)"), TRUE, FALSE,
+	gaim_request_input(gc, NULL, _("Available Message:"), NULL,
+					   _("I'm doing work and hoping for a distraction--IM me!"), 
+					   TRUE, FALSE,
 					   _("OK"), G_CALLBACK(oscar_setavailmsg),
 					   _("Cancel"), NULL,
@@ -6329,7 +6419,17 @@
 #endif
 
+static void oscar_show_set_info(GaimConnection *gc)
+{
+	gaim_account_request_change_user_info(gaim_connection_get_account(gc));
+}
+
+static void oscar_change_pass(GaimConnection *gc)
+{
+	gaim_account_request_change_password(gaim_connection_get_account(gc));
+}
+
 static void oscar_show_chpassurl(GaimConnection *gc)
 {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	gchar *substituted = gaim_strreplace(od->sess->authinfo->chpassurl, "%s", gaim_account_get_username(gaim_connection_get_account(gc)));
 	gaim_notify_uri(gc, substituted);
@@ -6337,7 +6437,12 @@
 }
 
+static void oscar_show_imforwardingurl(GaimConnection *gc)
+{
+	gaim_notify_uri(gc, "http://mymobile.aol.com/dbreg/register?action=imf&clientID=1");
+}
+
 static void oscar_set_icon(GaimConnection *gc, const char *iconfile)
 {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	aim_session_t *sess = od->sess;
 	FILE *file;
@@ -6372,5 +6477,5 @@
 static GList *oscar_actions(GaimConnection *gc)
 {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	struct proto_actions_menu *pam;
 	GList *m = NULL;
@@ -6378,5 +6483,5 @@
 	pam = g_new0(struct proto_actions_menu, 1);
 	pam->label = _("Set User Info");
-	pam->callback = show_set_info;
+	pam->callback = oscar_show_set_info;
 	pam->gc = gc;
 	m = g_list_append(m, pam);
@@ -6392,5 +6497,5 @@
 	pam = g_new0(struct proto_actions_menu, 1);
 	pam->label = _("Change Password");
-	pam->callback = show_change_passwd;
+	pam->callback = oscar_change_pass;
 	pam->gc = gc;
 	m = g_list_append(m, pam);
@@ -6404,4 +6509,12 @@
 	}
 
+	if (od->sess->authinfo->chpassurl) {
+		pam = g_new0(struct proto_actions_menu, 1);
+		pam->label = _("Configure IM Forwarding (URL)");
+		pam->callback = oscar_show_imforwardingurl;
+		pam->gc = gc;
+		m = g_list_append(m, pam);
+	}
+
 	if (!od->icq) {
 		/* AIM actions */
@@ -6445,5 +6558,5 @@
 	pam = g_new0(struct proto_actions_menu, 1);
 	pam->label = _("Search for Buddy by Email");
-	pam->callback = show_find_email;
+	pam->callback = oscar_show_find_email;
 	pam->gc = gc;
 	m = g_list_append(m, pam);
@@ -6460,5 +6573,5 @@
 static void oscar_change_passwd(GaimConnection *gc, const char *old, const char *new)
 {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 
 	if (od->icq) {
@@ -6479,5 +6592,5 @@
 static void oscar_convo_closed(GaimConnection *gc, const char *who)
 {
-	struct oscar_data *od = gc->proto_data;
+	OscarData *od = gc->proto_data;
 	struct direct_im *dim = find_direct_im(od, who);
 
