changeset 2681:37d80035e77f

[gaim-migrate @ 2694] don't ask. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Tue, 06 Nov 2001 23:58:24 +0000
parents ab2ca2770d2e
children db2b0b733732
files ChangeLog src/buddy.c src/conversation.c src/dialogs.c src/gaim.h src/list.c src/protocols/gg/gg.c src/protocols/icq/gaim_icq.c src/protocols/irc/irc.c src/protocols/jabber/jabber.c src/protocols/msn/msn.c src/protocols/napster/napster.c src/protocols/oscar/oscar.c src/protocols/toc/toc.c src/protocols/yahoo/.cvsignore src/protocols/yahoo/AUTHORS src/protocols/yahoo/Makefile.am src/protocols/yahoo/buddy.c src/protocols/yahoo/conn.c src/protocols/yahoo/internal.h src/protocols/yahoo/login.c src/protocols/yahoo/misc.c src/protocols/yahoo/outgoing.c src/protocols/yahoo/rxhandlers.c src/protocols/yahoo/yahoo.c src/protocols/yahoo/yay.c src/protocols/yahoo/yay.h src/protocols/zephyr/zephyr.c src/prpl.h src/server.c
diffstat 30 files changed, 1136 insertions(+), 2376 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Nov 06 21:30:31 2001 +0000
+++ b/ChangeLog	Tue Nov 06 23:58:24 2001 +0000
@@ -2,6 +2,7 @@
 
 version 0.48:
 	* Right-click on links to open/copy URL
+	* Yahoo changes
 
 version 0.47 (11/01/2001):
 	* Better font loading (pays attention to charset now)
--- a/src/buddy.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/buddy.c	Tue Nov 06 23:58:24 2001 +0000
@@ -999,6 +999,7 @@
 		 * we change the group that the buddy is in */
 		struct group *old_g, *new_g = (struct group *)ptype;
 		struct buddy *s = NULL, *buddy = (struct buddy *)ctype;
+		gboolean add = FALSE;
 		int pos;
 
 		if (buddy->gc != new_g->gc) {
@@ -1015,7 +1016,7 @@
 				og->members = g_slist_remove(og->members, a);
 			} else {
 				/* we don't have this buddy yet; let's add him */
-				serv_add_buddy(new_g->gc, buddy->name);
+				add = TRUE;
 			}
 		}
 
@@ -1035,6 +1036,10 @@
 		} else
 			new_g->members = g_slist_append(new_g->members, buddy);
 
+		/* we do the add after it's added locally so that prpls can find it if necessary */
+		if (add)
+			serv_add_buddy(new_g->gc, buddy->name);
+
 		do_export(buddy->gc);
 		if (buddy->gc != new_g->gc) {
 			do_export(new_g->gc);
@@ -1245,7 +1250,7 @@
 			b = (struct buddy *)type;
 			g = find_group_by_buddy(b->gc, b->name);
 			gct = b->gc;
-			serv_remove_buddy(b->gc, b->name);
+			serv_remove_buddy(b->gc, b->name, g->name);
 			remove_buddy(b->gc, g, b);
 			gtk_ctree_remove_node(GTK_CTREE(edittree), node);
 			do_export(gct);
--- a/src/conversation.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/conversation.c	Tue Nov 06 23:58:24 2001 +0000
@@ -538,17 +538,17 @@
 
 void add_callback(GtkWidget *widget, struct conversation *c)
 {
-	if (c->gc && find_buddy(c->gc, c->name) != NULL) {
+	struct buddy *b = find_buddy(c->gc, c->name);
+	if (b) {
+		struct group *g = find_group_by_buddy(c->gc, c->name);
 		debug_printf(_("Removing '%s' from buddylist.\n"), c->name);
-		serv_remove_buddy(c->gc, c->name);
-		remove_buddy(c->gc, find_group_by_buddy(c->gc, c->name), find_buddy(c->gc, c->name));
+		serv_remove_buddy(c->gc, c->name, g->name);
+		remove_buddy(c->gc, g, b);
 		do_export(c->gc);
 		build_edit_tree();
 		update_convo_add_button(c);
-	} else {
-		if (c->gc)
-			show_add_buddy(c->gc, c->name, NULL, NULL);
-	}
+	} else if (c->gc)
+		show_add_buddy(c->gc, c->name, NULL, NULL);
 
 	gtk_widget_grab_focus(c->entry);
 }
--- a/src/dialogs.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/dialogs.c	Tue Nov 06 23:58:24 2001 +0000
@@ -3767,13 +3767,32 @@
 {
 	char *new_name;
 	struct buddy *b;
+	GSList *gr;
 
 	new_name = gtk_entry_get_text(GTK_ENTRY(entry));
 	b = gtk_object_get_user_data(obj);
 
+	if (!g_slist_find(connections, b->gc)) {
+		destroy_dialog(rename_bud_dialog, rename_bud_dialog);
+		return;
+	}
+
+	gr = b->gc->groups;
+	while (gr) {
+		if (g_slist_find(((struct group *)gr->data)->members, b))
+			break;
+		gr = gr->next;
+	}
+	if (!gr) {
+		destroy_dialog(rename_bud_dialog, rename_bud_dialog);
+		return;
+	}
+
 	if (new_name && (strlen(new_name) != 0) && strcmp(new_name, b->name)) {
+		struct group *g = find_group_by_buddy(b->gc, b->name);
 		char *prevname = g_strdup(b->name);
-		serv_remove_buddy(b->gc, b->name);
+		if (g)
+			serv_remove_buddy(b->gc, b->name, g->name);
 		if (!strcmp(b->name, b->show))
 			 g_snprintf(b->show, sizeof(b->show), "%s", new_name);
 		g_snprintf(b->name, sizeof(b->name), "%s", new_name);
--- a/src/gaim.h	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/gaim.h	Tue Nov 06 23:58:24 2001 +0000
@@ -362,8 +362,8 @@
 extern void serv_change_passwd(struct gaim_connection *, char *, char *);
 extern void serv_add_buddy(struct gaim_connection *, char *);
 extern void serv_add_buddies(struct gaim_connection *, GList *);
-extern void serv_remove_buddy(struct gaim_connection *, char *);
-extern void serv_remove_buddies(struct gaim_connection *, GList *);
+extern void serv_remove_buddy(struct gaim_connection *, char *, char *);
+extern void serv_remove_buddies(struct gaim_connection *, GList *, char *);
 extern void serv_add_permit(struct gaim_connection *, char *);
 extern void serv_add_deny(struct gaim_connection *, char *);
 extern void serv_rem_permit(struct gaim_connection *, char *);
--- a/src/list.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/list.c	Tue Nov 06 23:58:24 2001 +0000
@@ -86,7 +86,7 @@
 
 	gc->groups = g_slist_remove(gc->groups, delg);
 
-	serv_remove_buddies(gc, tmp);
+	serv_remove_buddies(gc, tmp, rem_g->name);
 	while (tmp) {
 		g_free(tmp->data);
 		tmp = g_list_remove(tmp, tmp->data);
--- a/src/protocols/gg/gg.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/gg/gg.c	Tue Nov 06 23:58:24 2001 +0000
@@ -1,6 +1,6 @@
 /*
  * gaim - Gadu-Gadu Protocol Plugin
- * $Id: gg.c 2576 2001-10-21 00:14:41Z robflynn $
+ * $Id: gg.c 2694 2001-11-06 23:58:24Z warmenhoven $
  *
  * Copyright (C) 2001, Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
  * 
@@ -616,7 +616,7 @@
 	gg_add_notify(gd->sess, strtol(who, (char **)NULL, 10));
 }
 
-static void agg_rem_buddy(struct gaim_connection *gc, char *who)
+static void agg_rem_buddy(struct gaim_connection *gc, char *who, char *group)
 {
 	struct agg_data *gd = (struct agg_data *)gc->proto_data;
 	if (invalid_uin(who))
--- a/src/protocols/icq/gaim_icq.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/icq/gaim_icq.c	Tue Nov 06 23:58:24 2001 +0000
@@ -386,7 +386,7 @@
 	}
 }
 
-static void icq_rem_buddy(struct gaim_connection *gc, char *who) {
+static void icq_rem_buddy(struct gaim_connection *gc, char *who, char *group) {
 	struct icq_data *id = (struct icq_data *)gc->proto_data;
 	icq_ContactRemove(id->link, atol(who));
 }
--- a/src/protocols/irc/irc.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/irc/irc.c	Tue Nov 06 23:58:24 2001 +0000
@@ -1338,7 +1338,8 @@
 }
 
 /* IRC doesn't have a buddy list, but we can still figure out who's online with ISON */
-static void irc_fake_buddy(struct gaim_connection *gc, char *who) {}
+static void irc_add_buddy(struct gaim_connection *gc, char *who) {}
+static void irc_remove_buddy(struct gaim_connection *gc, char *who, char *group) {}
 
 static GList *irc_chat_info(struct gaim_connection *gc)
 {
@@ -1461,8 +1462,8 @@
 	ret->login = irc_login;
 	ret->close = irc_close;
 	ret->send_im = irc_send_im;
-	ret->add_buddy = irc_fake_buddy;
-	ret->remove_buddy = irc_fake_buddy;
+	ret->add_buddy = irc_add_buddy;
+	ret->remove_buddy = irc_remove_buddy;
 	ret->chat_info = irc_chat_info;
 	ret->join_chat = irc_join_chat;
 	ret->chat_leave = irc_chat_leave;
--- a/src/protocols/jabber/jabber.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/jabber/jabber.c	Tue Nov 06 23:58:24 2001 +0000
@@ -1301,7 +1301,7 @@
 	g_free(realwho);
 }
 
-static void jabber_remove_buddy(struct gaim_connection *gc, char *name)
+static void jabber_remove_buddy(struct gaim_connection *gc, char *name, char *group)
 {
 	xmlnode x, y;
 	char *realwho;
--- a/src/protocols/msn/msn.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/msn/msn.c	Tue Nov 06 23:58:24 2001 +0000
@@ -1511,7 +1511,7 @@
 	}
 }
 
-static void msn_rem_buddy(struct gaim_connection *gc, char *who)
+static void msn_rem_buddy(struct gaim_connection *gc, char *who, char *group)
 {
 	struct msn_data *md = gc->proto_data;
 	char buf[MSN_BUF_LEN];
--- a/src/protocols/napster/napster.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/napster/napster.c	Tue Nov 06 23:58:24 2001 +0000
@@ -506,7 +506,7 @@
 	nap_write_packet(gc, 0xCF, name);
 }
 
-static void nap_remove_buddy(struct gaim_connection *gc, char *name)
+static void nap_remove_buddy(struct gaim_connection *gc, char *name, char *group)
 {
 	nap_write_packet(gc, 0x12F, name);
 }
--- a/src/protocols/oscar/oscar.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/oscar/oscar.c	Tue Nov 06 23:58:24 2001 +0000
@@ -2291,7 +2291,7 @@
 	aim_bos_setbuddylist(odata->sess, odata->conn, buf);
 }
 
-static void oscar_remove_buddy(struct gaim_connection *g, char *name) {
+static void oscar_remove_buddy(struct gaim_connection *g, char *name, char *group) {
 	struct oscar_data *odata = (struct oscar_data *)g->proto_data;
 	aim_remove_buddy(odata->sess, odata->conn, name);
 }
--- a/src/protocols/toc/toc.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/toc/toc.c	Tue Nov 06 23:58:24 2001 +0000
@@ -1037,7 +1037,7 @@
 	sflap_send(g, buf, -1, TYPE_DATA);
 }
 
-static void toc_remove_buddy(struct gaim_connection *g, char *name)
+static void toc_remove_buddy(struct gaim_connection *g, char *name, char *group)
 {
 	char buf[BUF_LEN * 2];
 	g_snprintf(buf, sizeof(buf), "toc_remove_buddy %s", normalize(name));
@@ -1045,7 +1045,7 @@
 	toc_set_config(g);
 }
 
-static void toc_remove_buddies(struct gaim_connection *g, GList *buddies)
+static void toc_remove_buddies(struct gaim_connection *g, GList *buddies, char *group)
 {
 	char buf[BUF_LEN * 2];
 	int n;
--- a/src/protocols/yahoo/.cvsignore	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/yahoo/.cvsignore	Tue Nov 06 23:58:24 2001 +0000
@@ -10,3 +10,4 @@
 outgoing.lo
 rxhandlers.lo
 yay.lo
+yahoo.lo
--- a/src/protocols/yahoo/AUTHORS	Tue Nov 06 21:30:31 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-Eric Warmenhoven <warmenhoven@yahoo.com>
-
-Most of this code is either based off of or taken from:
-libfaim by Adam Fritzler, et al., http://sourceforge.net/projects/libfaim/
-icqlib by Bill Soudan et al., http://sourceforge.net/projects/icqlib/
-libyahoo by Nathan Neulinger et al., http://sourceforge.net/projects/libyahoo/
-
-I did not reverse engineer the protocol at all. All of that work was done by
-everyone who has worked on libyahoo.
--- a/src/protocols/yahoo/Makefile.am	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/yahoo/Makefile.am	Tue Nov 06 23:58:24 2001 +0000
@@ -11,8 +11,7 @@
 pkg_LTLIBRARIES =
 noinst_LIBRARIES = libyahoo.a
 
-libyahoo_a_SOURCES = \
-	buddy.c conn.c internal.h login.c misc.c outgoing.c rxhandlers.c yay.c yay.h
+libyahoo_a_SOURCES = yahoo.c
 
 else
 
@@ -20,7 +19,6 @@
 pkg_LTLIBRARIES = libyahoo.la
 noinst_LIBRARIES =
 
-libyahoo_la_SOURCES = \
-	buddy.c conn.c internal.h login.c misc.c outgoing.c rxhandlers.c yay.c yay.h
+libyahoo_la_SOURCES = yahoo.c
 
 endif
--- a/src/protocols/yahoo/buddy.c	Tue Nov 06 21:30:31 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-/*
- * libyay
- *
- * Copyright (C) 2001 Eric Warmenhoven <warmenhoven@yahoo.com>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "internal.h"
-#include <string.h>
-
-int yahoo_add_buddy(struct yahoo_session *session, const char *active_id,
-		const char *group, const char *buddy, const char *message)
-{
-	struct yahoo_conn *conn;
-	char *send;
-	char *grp, *bdy, *id, *msg = "", *usr;
-
-	if (!session || !active_id || !group || !buddy)
-		return 0;
-
-	if (!(grp = yahoo_urlencode(group)))
-		return 0;
-	if (!(bdy = yahoo_urlencode(buddy))) {
-		g_free(grp);
-		return 0;
-	}
-	if (!(id = yahoo_urlencode(active_id))) {
-		g_free(grp);
-		g_free(bdy);
-		return 0;
-	}
-	if (!(usr = yahoo_urlencode(session->name))) {
-		g_free(grp);
-		g_free(bdy);
-		g_free(id);
-		return 0;
-	}
-	if (message && strlen(message) && !(msg = yahoo_urlencode(message))) {
-		g_free(grp);
-		g_free(bdy);
-		g_free(id);
-		g_free(usr);
-		return 0;
-	}
-
-	send = g_strconcat("GET ",
-			session->proxy_type ? "http://" : "",
-			session->proxy_type ? session->auth_host : "",
-			"/config/set_buddygrp?.bg=", grp,
-			"&.src=bl&.cmd=a&.bdl=", bdy,
-			"&.id=", id,
-			"&.l=", usr,
-			"&.amsg=", msg,
-			" HTTP/1.0\r\n",
-			"User-Agent: " YAHOO_USER_AGENT "\r\n"
-			"Host: ", session->auth_host, "\r\n"
-			"Cookie: ", session->cookie,
-			"\r\n\r\n", NULL);
-	g_free(grp);
-	g_free(bdy);
-	g_free(id);
-	g_free(usr);
-	if (message && strlen(message))
-		g_free(msg);
-
-	if (!send)
-		return 0;
-
-	if (!(conn = yahoo_new_conn(session, YAHOO_CONN_TYPE_DUMB, session->auth_host,
-					session->auth_port)))
-		return 0;
-
-	conn->txqueue = send;
-
-	return 1;
-}
-
-int yahoo_remove_buddy(struct yahoo_session *session, const char *active_id,
-		const char *group, const char *buddy, const char *message)
-{
-	struct yahoo_conn *conn;
-	char *send;
-	char *grp, *bdy, *id, *msg = "", *usr;
-
-	if (!session || !active_id || !group || !buddy)
-		return 0;
-
-	if (!(grp = yahoo_urlencode(group)))
-		return 0;
-	if (!(bdy = yahoo_urlencode(buddy))) {
-		g_free(grp);
-		return 0;
-	}
-	if (!(id = yahoo_urlencode(active_id))) {
-		g_free(grp);
-		g_free(bdy);
-		return 0;
-	}
-	if (!(usr = yahoo_urlencode(session->name))) {
-		g_free(grp);
-		g_free(bdy);
-		g_free(id);
-		return 0;
-	}
-	if (message && strlen(message) && !(msg = yahoo_urlencode(message))) {
-		g_free(grp);
-		g_free(bdy);
-		g_free(id);
-		g_free(usr);
-		return 0;
-	}
-
-	send = g_strconcat("GET ",
-			session->proxy_type ? "http://" : "",
-			session->proxy_type ? session->auth_host : "",
-			"/config/set_buddygrp?.bg=", grp,
-			"&.src=bl&.cmd=d&.bdl=", bdy,
-			"&.id=", id,
-			"&.l=", usr,
-			"&.amsg=", msg,
-			" HTTP/1.0\r\n",
-			"User-Agent: " YAHOO_USER_AGENT "\r\n"
-			"Host: ", session->auth_host, "\r\n"
-			"Cookie: ", session->cookie,
-			"\r\n\r\n", NULL);
-	g_free(grp);
-	g_free(bdy);
-	g_free(id);
-	g_free(usr);
-	if (message && strlen(message))
-		g_free(msg);
-
-	if (!send)
-		return 0;
-
-	if (!(conn = yahoo_new_conn(session, YAHOO_CONN_TYPE_DUMB, session->auth_host,
-					session->auth_port)))
-		return 0;
-
-	conn->txqueue = send;
-
-	return 1;
-}
--- a/src/protocols/yahoo/conn.c	Tue Nov 06 21:30:31 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,321 +0,0 @@
-/*
- * libyay
- *
- * Copyright (C) 2001 Eric Warmenhoven <warmenhoven@yahoo.com>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <string.h>
-#include "internal.h"
-
-void (*yahoo_socket_notify)(struct yahoo_session *, int, int, gboolean) = NULL;
-void (*yahoo_print)(struct yahoo_session *, int, const char *) = NULL;
-int (*yahoo_connector)(struct yahoo_session *, const char *, int, gpointer) = NULL;
-
-struct yahoo_session *yahoo_new()
-{
-	struct yahoo_session *sess;
-
-	if (!(sess = g_new0(struct yahoo_session, 1)))
-		return NULL;
-
-	return sess;
-}
-
-void yahoo_set_proxy(struct yahoo_session *session, int proxy_type, char *proxy_host, int proxy_port)
-{
-	if (!session || !proxy_type || !proxy_host)
-		return;
-
-	session->proxy_type = proxy_type;
-	session->proxy_host = g_strdup(proxy_host);
-	session->proxy_port = proxy_port;
-}
-
-static int yahoo_connect_host(struct yahoo_session *sess, const char *host, int port, int *statusret)
-{
-	struct sockaddr_in sa;
-	struct hostent *hp;
-	int fd;
-
-	if (!(hp = gethostbyname(host))) {
-		YAHOO_PRINT(sess, YAHOO_LOG_WARNING, "Resolve error");
-		if (statusret)
-			*statusret = (h_errno | YAHOO_CONN_STATUS_RESOLVERR);
-		return -1;
-	}
-
-	memset(&sa, 0, sizeof(struct sockaddr_in));
-	sa.sin_port = htons(port);
-	memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
-	sa.sin_family = hp->h_addrtype;
-
-	fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
-
-	fcntl(fd, F_SETFL, O_NONBLOCK);
-
-	if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) {
-		if ((errno == EINPROGRESS) || (errno == EINTR)) { 
-			YAHOO_PRINT(sess, YAHOO_LOG_NOTICE, "Connect would block");
-			if (statusret)
-				*statusret |= YAHOO_CONN_STATUS_INPROGRESS;
-			return fd;
-		}
-		close(fd);
-		fd = -1;
-	}
-
-	return fd;
-}
-
-int yahoo_connected(struct yahoo_session *session, gpointer data, int fd)
-{
-	struct yahoo_conn *conn = data;
-
-	if (fd < 0) {
-		YAHOO_PRINT(session, YAHOO_LOG_WARNING, "connect failed");
-		session->connlist = g_list_remove(session->connlist, conn);
-		g_free(conn);
-		return 0;
-	}
-
-	YAHOO_PRINT(session, YAHOO_LOG_NOTICE, "connect succeeded");
-	conn->socket = fd;
-	conn->connected = TRUE;
-	if (conn->type == YAHOO_CONN_TYPE_AUTH) {
-		if (session->callbacks[YAHOO_HANDLE_AUTHCONNECT].function)
-			if (!(*session->callbacks[YAHOO_HANDLE_AUTHCONNECT].function)(session))
-				return 0;
-	} else if (conn->type == YAHOO_CONN_TYPE_MAIN) {
-		if (session->callbacks[YAHOO_HANDLE_MAINCONNECT].function)
-			if (!(*session->callbacks[YAHOO_HANDLE_MAINCONNECT].function)(session))
-				return 0;
-	} else if (conn->type == YAHOO_CONN_TYPE_DUMB) {
-		YAHOO_PRINT(session, YAHOO_LOG_DEBUG, "sending to buddy list host");
-		yahoo_write(session, conn, conn->txqueue, strlen(conn->txqueue));
-		g_free(conn->txqueue);
-		conn->txqueue = NULL;
-	}
-
-	if (yahoo_socket_notify)
-		(*yahoo_socket_notify)(session, conn->socket, YAHOO_SOCKET_READ, TRUE);
-	else
-		YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "yahoo_socket_notify not set up");
-
-	return 1;
-}
-
-struct yahoo_conn *yahoo_new_conn(struct yahoo_session *session, int type, const char *host, int port)
-{
-	struct yahoo_conn *conn;
-	int status;
-
-	if (!session)
-		return NULL;
-
-	conn = g_new0(struct yahoo_conn, 1);
-	conn->type = type;
-
-	if (yahoo_connector) {
-		YAHOO_PRINT(session, YAHOO_LOG_DEBUG, "Connecting using user-specified connect routine");
-		if ((*yahoo_connector)(session, host, port, conn) < 0) {
-			YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "connect failed");
-			g_free(conn);
-			return NULL;
-		}
-		session->connlist = g_list_append(session->connlist, conn);
-		return conn;
-	}
-
-	if (session->proxy_type) {
-		YAHOO_PRINT(session, YAHOO_LOG_DEBUG, "connecting to proxy");
-		conn->socket = yahoo_connect_host(session, session->proxy_host,
-				session->proxy_port, &status);
-		if (type == YAHOO_CONN_TYPE_MAIN)
-			conn->type = YAHOO_CONN_TYPE_PROXY;
-	} else
-		conn->socket = yahoo_connect_host(session, host, port, &status);
-
-	if (conn->socket < 0) {
-		g_free(conn);
-		return NULL;
-	}
-
-	if (yahoo_socket_notify)
-		(*yahoo_socket_notify)(session, conn->socket, YAHOO_SOCKET_WRITE, TRUE);
-	else
-		YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "yahoo_socket_notify not set up");
-
-	session->connlist = g_list_append(session->connlist, conn);
-
-	return conn;
-}
-
-struct yahoo_conn *yahoo_getconn_type(struct yahoo_session *sess, int type)
-{
-	GList *c;
-	struct yahoo_conn *conn;
-
-	if (!sess)
-		return NULL;
-
-	c = sess->connlist;
-	while (c) {
-		conn = c->data;
-		if (conn->type == type)
-			return conn;
-		c = g_list_next(c);
-	}
-
-	return NULL;
-}
-
-struct yahoo_conn *yahoo_find_conn(struct yahoo_session *sess, int socket)
-{
-	GList *c;
-	struct yahoo_conn *conn;
-
-	c = sess->connlist;
-	while (c) {
-		conn = c->data;
-		if (conn->socket == socket)
-			return conn;
-		c = g_list_next(c);
-	}
-
-	return NULL;
-}
-
-int yahoo_connect(struct yahoo_session *session, const char *host, int port)
-{
-	if (!session)
-		return 0;
-
-	if (session->auth_host)
-		g_free(session->auth_host);
-	if (host && *host)
-		session->auth_host = g_strdup(host);
-	else
-		session->auth_host = g_strdup(YAHOO_AUTH_HOST);
-
-	if (port)
-		session->auth_port = port;
-	else
-		session->auth_port = YAHOO_AUTH_PORT;
-
-	if (!yahoo_new_conn(session, YAHOO_CONN_TYPE_AUTH, session->auth_host, session->auth_port))
-		return 0;
-
-	return 1;
-}
-
-int yahoo_major_connect(struct yahoo_session *session, const char *host, int port)
-{
-	if (!session)
-		return 0;
-
-	if (session->pager_host)
-		g_free(session->pager_host);
-	if (host && *host)
-		session->pager_host = g_strdup(host);
-	else
-		session->pager_host = g_strdup(YAHOO_PAGER_HOST);
-
-	if (port)
-		session->pager_port = port;
-	else
-		session->pager_port = YAHOO_AUTH_PORT;
-
-	if (!yahoo_new_conn(session, YAHOO_CONN_TYPE_MAIN, session->pager_host, session->pager_port))
-		return 0;
-
-	return 1;
-}
-
-void yahoo_close(struct yahoo_session *session, struct yahoo_conn *conn)
-{
-	if (!session || !conn)
-		return;
-
-	if (!g_list_find(session->connlist, conn))
-		return;
-
-	if (yahoo_socket_notify) {
-		if (conn->connected)
-			(*yahoo_socket_notify)(session, conn->socket, YAHOO_SOCKET_READ, FALSE);
-		else
-			(*yahoo_socket_notify)(session, conn->socket, YAHOO_SOCKET_WRITE, FALSE);
-	}
-	close(conn->socket);
-
-	session->connlist = g_list_remove(session->connlist, conn);
-	if (conn->txqueue)
-		g_free(conn->txqueue);
-	g_free(conn);
-}
-
-int yahoo_disconnect(struct yahoo_session *session)
-{
-	if (!session)
-		return 0;
-	yahoo_logoff(session);
-	if (session->name)
-		g_free(session->name);
-	session->name = NULL;
-	while (session->connlist)
-		yahoo_close(session, session->connlist->data);
-	if (session->cookie)
-		g_free(session->cookie);
-	session->cookie = NULL;
-	if (session->login_cookie)
-		g_free(session->login_cookie);
-	session->login_cookie = NULL;
-	while (session->ignored) {
-		g_free(session->ignored->data);
-		session->ignored = g_list_remove(session->ignored, session->ignored->data);
-	}
-	if (session->identities)
-		g_strfreev(session->identities);
-	session->identities = NULL;
-	if (session->login)
-		g_free(session->login);
-	session->login = NULL;
-	while (session->groups) {
-		struct yahoo_group *grp = session->groups->data;
-		g_strfreev(grp->buddies);
-		g_free(grp->name);
-		g_free(grp);
-		session->groups = g_list_remove(session->groups, grp);
-	}
-	if (session->auth_host)
-		g_free(session->auth_host);
-	session->auth_host = NULL;
-	if (session->pager_host)
-		g_free(session->pager_host);
-	session->pager_host = NULL;
-	return 0;
-}
-
-int yahoo_delete(struct yahoo_session *session)
-{
-	if (!session)
-		return 0;
-	if (session->proxy_host)
-		g_free(session->proxy_host);
-	g_free(session);
-	return 0;
-}
--- a/src/protocols/yahoo/internal.h	Tue Nov 06 21:30:31 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * libyay
- *
- * Copyright (C) 2001 Eric Warmenhoven <warmenhoven@yahoo.com>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef _LIBYAY_INTERNAL_H
-#define _LIBYAY_INTERNAL_H
-
-#include "yay.h"
-
-#define YAHOO_CONN_STATUS_RESOLVERR  0x0040
-#define YAHOO_CONN_STATUS_INPROGRESS 0x0100
-
-#define YAHOO_USER_AGENT "Mozilla/4.6 (libyay/1.0)"
-
-#define YAHOO_PRINT(x, y, z) if (yahoo_print) (*yahoo_print)(x, y, z)
-
-struct yahoo_conn {
-	int type;
-	int socket;
-	int magic_id;
-	gboolean connected;
-	char *txqueue;
-};
-
-#define YAHOO_CONN_TYPE_AUTH  1
-#define YAHOO_CONN_TYPE_MAIN  2
-#define YAHOO_CONN_TYPE_DUMB  3
-#define YAHOO_CONN_TYPE_PROXY 4
-
-#define HTTP_GOODSTRING1 "HTTP/1.0 200 Connection established"
-#define HTTP_GOODSTRING2 "HTTP/1.1 200 Connection established"
-
-char *yahoo_urlencode(const char *);
-struct yahoo_conn *yahoo_new_conn(struct yahoo_session *, int, const char *, int);
-struct yahoo_conn *yahoo_getconn_type(struct yahoo_session *, int);
-struct yahoo_conn *yahoo_find_conn(struct yahoo_session *, int);
-int yahoo_write(struct yahoo_session *, struct yahoo_conn *, void *, int);
-int yahoo_write_cmd(struct yahoo_session *, struct yahoo_conn *, int, const char *, void *, guint);
-void yahoo_close(struct yahoo_session *, struct yahoo_conn *);
-
-#define YAHOO_SERVICE_LOGON            1
-#define YAHOO_SERVICE_LOGOFF           2
-#define YAHOO_SERVICE_ISAWAY           3
-#define YAHOO_SERVICE_ISBACK           4
-#define YAHOO_SERVICE_IDLE             5
-#define YAHOO_SERVICE_MESSAGE          6
-#define YAHOO_SERVICE_IDACT            7
-#define YAHOO_SERVICE_IDDEACT          8
-#define YAHOO_SERVICE_NEWMAIL         11
-#define YAHOO_SERVICE_NEWPERSONALMAIL 14
-#define YAHOO_SERVICE_NEWCONTACT      15
-#define YAHOO_SERVICE_PING            18
-
-#define YAHOO_MESSAGE_NORMAL  1
-#define YAHOO_MESSAGE_BOUNCE  2
-#define YAHOO_MESSAGE_OFFLINE 5
-#define YAHOO_MESSAGE_SEND    1515563606
-
-void yahoo_storeint(guchar *, guint);
-int yahoo_makeint(guchar *);
-
-struct yahoo_packet {
-	char version[8];
-	guchar len[4];
-	guchar service[4];
-
-	guchar conn_id[4];
-	guchar magic_id[4];
-	guchar address[4];
-	guchar msgtype[4];
-
-	char nick1[36];
-	char nick2[36];
-
-	char content[1024];
-};
-
-#endif
--- a/src/protocols/yahoo/login.c	Tue Nov 06 21:30:31 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * libyay
- *
- * Copyright (C) 2001 Eric Warmenhoven <warmenhoven@yahoo.com>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "internal.h"
-#include <string.h>
-
-int yahoo_send_login(struct yahoo_session *session, const char *name, const char *password)
-{
-	char *buf = g_malloc(1024 + strlen(name) + strlen(password));
-	char *a, *b;
-	int at;
-	struct yahoo_conn *conn;
-
-	if (!buf)
-		return 0;
-
-	if (!(conn = yahoo_getconn_type(session, YAHOO_CONN_TYPE_AUTH)))
-		return 0;
-
-	if (!(a = yahoo_urlencode(name)))
-		return 0;
-	if (!(b = yahoo_urlencode(password))) {
-		g_free(a);
-		return 0;
-	}
-
-	at = g_snprintf(buf, 1024 + strlen(name) + strlen(password),
-			"GET %s%s/config/ncclogin?login=%s&passwd=%s&n=1 HTTP/1.0\r\n"
-			"User-Agent: " YAHOO_USER_AGENT "\r\n"
-			"Host: %s\r\n\r\n",
-			session->proxy_type ? "http://" : "",
-			session->proxy_type ? session->auth_host : "",
-			a, b, session->auth_host);
-
-	g_free(a);
-	g_free(b);
-
-	if (yahoo_write(session, conn, buf, at) != at) {
-		g_free(buf);
-		return 0;
-	}
-
-	g_free(buf);
-	session->name = g_strdup(name);
-	return at;
-}
-
-int yahoo_finish_logon(struct yahoo_session *session, enum yahoo_status status)
-{
-	char *buf = NULL, *tmp = NULL;
-	int ret;
-	struct yahoo_conn *conn;
-
-	if (!session || !session->login_cookie)
-		return 0;
-
-	if (!(conn = yahoo_getconn_type(session, YAHOO_CONN_TYPE_MAIN)))
-		return 0;
-
-	if (session->identities) {
-		if (!(tmp = g_strjoinv(",", session->identities)))
-			return 0;
-	} else
-		tmp = "";
-
-	if (!(buf = g_strconcat(session->login_cookie, "\001", session->name, tmp, NULL))) {
-		g_free(tmp);
-		return 0;
-	}
-
-	ret = yahoo_write_cmd(session, conn, YAHOO_SERVICE_LOGON, session->name, buf, status);
-	g_free(buf);
-	if (session->identities)
-		g_free(tmp);
-
-	return ret;
-}
--- a/src/protocols/yahoo/misc.c	Tue Nov 06 21:30:31 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * libyay
- *
- * Copyright (C) 2001 Eric Warmenhoven <warmenhoven@yahoo.com>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "internal.h"
-#include <ctype.h>
-#include <string.h>
-
-char *yahoo_urlencode(const char *str)
-{
-	int len;
-	char *ret;
-	const char *s;
-	char *r;
-
-	if ((len = strlen(str)) == 0)
-		return NULL;
-
-	ret = g_malloc(len * 3 + 1);
-	if (!ret)
-		return NULL;
-
-	for (s = str, r = ret; *s; s++) {
-		if (isdigit(*s) || isalpha(*s) || *s == '_')
-			*r++ = *s;
-		else {
-			int tmp = *s / 16;
-			*r++ = '%';
-			*r++ = (tmp < 10) ? (tmp + '0') : (tmp - 10 + 'A');
-			tmp = *s % 16;
-			*r++ = (tmp < 10) ? (tmp + '0') : (tmp - 10 + 'A');
-		}
-	}
-
-	*r = '\0';
-
-	return ret;
-}
-
-int yahoo_makeint(guchar *buf)
-{
-	return ((buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + buf[0]);
-}
-
-void yahoo_storeint(guchar *buf, guint data)
-{
-	int i;
-	for (i = 0; i < 4; i++) {
-		buf[i] = data % 256;
-		data >>= 8;
-	}
-}
--- a/src/protocols/yahoo/outgoing.c	Tue Nov 06 21:30:31 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * libyay
- *
- * Copyright (C) 2001 Eric Warmenhoven <warmenhoven@yahoo.com>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "internal.h"
-#include <string.h>
-
-int yahoo_write(struct yahoo_session *session, struct yahoo_conn *conn, void *buf, int len)
-{
-	if (!session || !conn)
-		return 0;
-
-	if (!g_list_find(session->connlist, conn))
-		return 0;
-
-	if (send(conn->socket, buf, len, 0) != len) {
-		int type = conn->type;
-		yahoo_close(session, conn);
-		YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "error sending");
-		if (type == YAHOO_CONN_TYPE_DUMB)
-			if (session->callbacks[YAHOO_HANDLE_DISCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_DISCONNECT].function)(session);
-		return 0;
-	}
-
-	return len;
-}
-
-int yahoo_write_cmd(struct yahoo_session *session, struct yahoo_conn *conn,
-		int service, const char *active_id, void *buf, guint msgtype)
-{
-	struct yahoo_packet *pkt;
-	int ret;
-
-	if (!session || !session->login || !conn || !active_id)
-		return 0;
-
-	if (!(pkt = g_new0(struct yahoo_packet, 1)))
-		return 0;
-
-	strcpy(pkt->version, "YPNS2.0");
-	yahoo_storeint(pkt->len, sizeof(struct yahoo_packet));
-	yahoo_storeint(pkt->service, service);
-
-	yahoo_storeint(pkt->magic_id, conn->magic_id);
-	yahoo_storeint(pkt->msgtype, msgtype);
-
-	strcpy(pkt->nick1, session->login);
-	strcpy(pkt->nick2, active_id);
-
-	strncpy(pkt->content, buf, 1024);
-
-	ret = yahoo_write(session, conn, pkt, sizeof(struct yahoo_packet));
-	g_free(pkt);
-	return ret;
-}
-
-int yahoo_activate_id(struct yahoo_session *session, char *id)
-{
-	struct yahoo_conn *conn;
-
-	if (!session || !id)
-		return 0;
-
-	if (!(conn = yahoo_getconn_type(session, YAHOO_CONN_TYPE_MAIN)))
-		return 0;
-
-	return yahoo_write_cmd(session, conn, YAHOO_SERVICE_IDACT, id, id, 0);
-}
-
-int yahoo_deactivate_id(struct yahoo_session *session, char *id)
-{
-	struct yahoo_conn *conn;
-
-	if (!session || !id)
-		return 0;
-
-	if (!(conn = yahoo_getconn_type(session, YAHOO_CONN_TYPE_MAIN)))
-		return 0;
-
-	return yahoo_write_cmd(session, conn, YAHOO_SERVICE_IDDEACT, id, id, 0);
-}
-
-int yahoo_send_message(struct yahoo_session *session, const char *active_id,
-		const char *user, const char *msg)
-{
-	struct yahoo_conn *conn;
-	char *buf;
-	int ret;
-
-	if (!session || !user || !msg)
-		return 0;
-
-	if (!(conn = yahoo_getconn_type(session, YAHOO_CONN_TYPE_MAIN)))
-		return 0;
-
-	if (!(buf = g_strconcat(user, ",", msg, NULL)))
-		return 0;
-
-	ret = yahoo_write_cmd(session, conn, YAHOO_SERVICE_MESSAGE,
-			active_id ? active_id : session->name, buf, 0);
-	g_free(buf);
-
-	return ret;
-}
-
-int yahoo_send_message_offline(struct yahoo_session *session, const char *active_id,
-		const char *user, const char *msg)
-{
-	struct yahoo_conn *conn;
-	char *buf;
-	int ret;
-
-	if (!session || !user || !msg)
-		return 0;
-
-	if (!(conn = yahoo_getconn_type(session, YAHOO_CONN_TYPE_MAIN)))
-		return 0;
-
-	if (!(buf = g_strconcat(user, ",", msg, NULL)))
-		return 0;
-
-	ret = yahoo_write_cmd(session, conn, YAHOO_SERVICE_MESSAGE,
-			active_id ? active_id : session->name, buf, YAHOO_MESSAGE_SEND);
-	g_free(buf);
-
-	return ret;
-}
-
-int yahoo_logoff(struct yahoo_session *session)
-{
-	struct yahoo_conn *conn;
-
-	if (!session)
-		return 0;
-
-	if (!session->login)
-		return 0;
-
-	if (!(conn = yahoo_getconn_type(session, YAHOO_CONN_TYPE_MAIN)))
-		return 0;
-
-	return yahoo_write_cmd(session, conn, YAHOO_SERVICE_LOGOFF, session->name, session->name, 0);
-}
-
-int yahoo_ping(struct yahoo_session *session)
-{
-	struct yahoo_conn *conn;
-
-	if (!session)
-		return 0;
-
-	if (!(conn = yahoo_getconn_type(session, YAHOO_CONN_TYPE_MAIN)))
-		return 0;
-
-	return yahoo_write_cmd(session, conn, YAHOO_SERVICE_PING, session->name, "", 0);
-}
-
-int yahoo_away(struct yahoo_session *session, enum yahoo_status status, char *msg)
-{
-	struct yahoo_conn *conn;
-	char buf[1024];
-
-	if (!session)
-		return 0;
-
-	if (!(conn = yahoo_getconn_type(session, YAHOO_CONN_TYPE_MAIN)))
-		return 0;
-
-	g_snprintf(buf, sizeof(buf), "%d%c%s", status, 1, msg ? msg : "---");
-
-	return yahoo_write_cmd(session, conn, YAHOO_SERVICE_ISAWAY, session->name, buf, 0);
-}
-
-int yahoo_back(struct yahoo_session *session, enum yahoo_status status, char *msg)
-{
-	struct yahoo_conn *conn;
-	char buf[1024];
-
-	if (!session)
-		return 0;
-
-	if (!(conn = yahoo_getconn_type(session, YAHOO_CONN_TYPE_MAIN)))
-		return 0;
-
-	g_snprintf(buf, sizeof(buf), "%d%c%s", status, 1, msg ? msg : "---");
-
-	return yahoo_write_cmd(session, conn, YAHOO_SERVICE_ISBACK, session->name, buf, 0);
-}
--- a/src/protocols/yahoo/rxhandlers.c	Tue Nov 06 21:30:31 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,472 +0,0 @@
-/*
- * libyay
- *
- * Copyright (C) 2001 Eric Warmenhoven <warmenhoven@yahoo.com>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "internal.h"
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-static void yahoo_parse_config(struct yahoo_session *session, struct yahoo_conn *conn, char *buf)
-{
-	char **str_array = g_strsplit(buf, "\n", 1024);
-	char **it;
-	int state = 0;
-
-	for (it = str_array; *it; it++) {
-		if (!**it) continue;
-		if (!strncmp(*it, "ERROR", strlen("ERROR"))) {
-			yahoo_close(session, conn);
-			if (session->callbacks[YAHOO_HANDLE_BADPASSWORD].function)
-				(*session->callbacks[YAHOO_HANDLE_BADPASSWORD].function)(session);
-			return;
-		} else if (!strncmp(*it, "Set-Cookie: Y=", strlen("Set-Cookie: Y="))) {
-			char **sa;
-			char **m;
-
-			char *end = strchr(*it, ';');
-			if (session->cookie)
-				g_free(session->cookie);
-			session->cookie = g_strndup(*it + strlen("Set-Cookie: "),
-					end - *it - strlen("Set-Cookie: "));
-			YAHOO_PRINT(session, YAHOO_LOG_DEBUG, session->cookie);
-			if (!session->cookie) {
-				yahoo_close(session, conn);
-				YAHOO_PRINT(session, YAHOO_LOG_ERROR, "did not get cookie");
-				if (session->callbacks[YAHOO_HANDLE_DISCONNECT].function)
-					(*session->callbacks[YAHOO_HANDLE_DISCONNECT].function)(session);
-				return;
-			}
-
-			sa = g_strsplit(session->cookie, "&", 8);
-			for (m = sa; *m; m++) {
-				if (!strncmp(*m, "n=", 2)) {
-					if (session->login_cookie)
-						g_free(session->login_cookie);
-					session->login_cookie = g_strdup(*m + 2);
-					YAHOO_PRINT(session, YAHOO_LOG_DEBUG, session->login_cookie);
-				}
-			}
-			g_strfreev(sa);
-		} else if (!strncmp(*it, "BEGIN BUDDYLIST", strlen("BEGIN BUDDYLIST"))) {
-			state = 1;
-		} else if (!strncmp(*it, "END BUDDYLIST", strlen("END BUDDYLIST"))) {
-			state = 0;
-		} else if (!strncmp(*it, "BEGIN IGNORELIST", strlen("BEGIN IGNORELIST"))) {
-			state = 2;
-		} else if (!strncmp(*it, "END IGNORELIST", strlen("END IGNORELIST"))) {
-			state = 0;
-		} else if (!strncmp(*it, "BEGIN IDENTITIES", strlen("BEGIN IDENTITIES"))) {
-			state = 3;
-		} else if (!strncmp(*it, "END IDENTITIES", strlen("END IDENTITIES"))) {
-			state = 0;
-		} else if (!strncmp(*it, "Mail=", strlen("Mail="))) {
-			session->mail = atoi(*it + strlen("Mail="));
-		} else if (!strncmp(*it, "Login=", strlen("Login="))) {
-			if (session->login)
-				g_free(session->login);
-			session->login = g_strdup(*it + strlen("Login="));
-		} else {
-			if (state == 1) {
-				struct yahoo_group *grp = g_new0(struct yahoo_group, 1);
-				char *end = strchr(*it, ':');
-				if (end) {
-					grp->name = g_strndup(*it, end - *it);
-					end++;
-					grp->buddies = g_strsplit(end, ",", 1024);
-					session->groups = g_list_append(session->groups, grp);
-				}
-			} else if (state == 2) {
-				session->ignored = g_list_append(session->ignored, g_strdup(*it));
-			} else if (state == 3) {
-				session->identities = g_strsplit(*it, ",", 6);
-			}
-		}
-	}
-
-	g_strfreev(str_array);
-	yahoo_close(session, conn);
-	if (session->callbacks[YAHOO_HANDLE_LOGINCOOKIE].function)
-		(*session->callbacks[YAHOO_HANDLE_LOGINCOOKIE].function)(session);
-}
-
-static void yahoo_parse_status(struct yahoo_session *sess, struct yahoo_packet *pkt)
-{
-	/* OK, I'm going to comment it this time. We either get:
-	 * warmenhoven(99,(test)\001,6634CD3,0,1,0,0)
-	 * or
-	 * 2,smarterchild(0,6634CD3,0,1,0,0),warmenhoven(0,6C8C0C48,0,1,0,0)
-	 *
-	 * in the first case, we only get one person, and we get a bunch of fields.
-	 * in the second case, the number is how many people we got, and then the
-	 * names followed by a bunch of fields, separated by commas.
-	 *
-	 * the fields are: (status, [optional: custom message \001,] session id, ?, pager, chat, game)
-	 *
-	 * the custom message may contain any characters (none are escaped) so we can't split on
-	 * anything in particular. this is what we fucked up with the first time
-	 */
-	char *tmp = pkt->content;
-	int count = 0;
-	int i;
-
-	if (strstr(pkt->content, "was not AWAY"))
-		return;
-
-	/* count is the first number, if we got it. */
-	while (*tmp && isdigit((int)*tmp))
-		count = count * 10 + *tmp++ - '0';
-	count = count ? count : 1;
-
-	for (i = 0; i < count && *tmp; i++) {
-		int status, in_pager, in_chat, in_game;
-		char *p, *who, *msg = NULL;
-
-		if (*tmp == ',')
-			tmp++;
-
-		/* who is the person we're getting an update for. there will always be a paren
-		 * after this so we should be OK. if we don't get a paren, we'll just break. */
-		who = tmp;
-		if ((tmp = strchr(who, '(')) == NULL)
-			break;
-		*tmp++ = '\0';
-
-		/* tmp now points to the start of the fields. we'll get the status first. it
-		 * should always be followed by a comma, and if it isn't, we'll just break. */
-		if ((p = strchr(tmp, ',')) == NULL)
-			break;
-		*p++ = '\0';
-		status = atoi(tmp);
-		tmp = p;
-
-		if (status == YAHOO_STATUS_CUSTOM) {
-			/* tmp now points to the away message. it should end with "\001,". */
-			msg = tmp;
-			if ((tmp = strstr(msg, "\001,")) == NULL)
-				break;
-			*tmp = '\0';
-			tmp += 2;
-		}
-
-		/* tmp now points to the session id. we don't need it. */
-		if ((tmp = strchr(tmp, ',')) == NULL)
-			break;
-		tmp++;
-
-		/* tmp is at the unknown value. we don't need it. */
-		if ((tmp = strchr(tmp, ',')) == NULL)
-			break;
-		tmp++;
-
-		/* tmp is at the in_pager value */
-		if ((p = strchr(tmp, ',')) == NULL)
-			break;
-		*p++ = '\0';
-		in_pager = atoi(tmp);
-		tmp = p;
-
-		/* tmp is at the in_chat value */
-		if ((p = strchr(tmp, ',')) == NULL)
-			break;
-		*p++ = '\0';
-		in_chat = atoi(tmp);
-		tmp = p;
-
-		/* tmp is at the in_game value. this is the last value, so it should end with
-		 * a parenthesis. */
-		if ((p = strchr(tmp, ')')) == NULL)
-			break;
-		*p++ = '\0';
-		in_game = atoi(tmp);
-		tmp = p;
-
-		if (sess->callbacks[YAHOO_HANDLE_STATUS].function)
-			(*sess->callbacks[YAHOO_HANDLE_STATUS].function)(sess, who, status, msg,
-									 in_pager, in_chat, in_game);
-	}
-}
-
-static void yahoo_parse_message(struct yahoo_session *sess, struct yahoo_packet *pkt)
-{
-	char buf[256];
-	int type = yahoo_makeint(pkt->msgtype);
-	char *str_array[4];
-	char *tmp;
-
-	switch(type) {
-	case YAHOO_MESSAGE_NORMAL:
-		str_array[0] = pkt->content;
-		if ((tmp = strchr(str_array[0], ',')) == NULL)
-			break;
-		*tmp++ = '\0';
-		str_array[1] = tmp;
-		if ((tmp = strchr(str_array[1], ',')) == NULL)
-			break;
-		*tmp++ = '\0';
-		str_array[2] = tmp;
-		str_array[2][strlen(str_array[2]) - 1] = 0;
-		if (sess->callbacks[YAHOO_HANDLE_MESSAGE].function)
-			(*sess->callbacks[YAHOO_HANDLE_MESSAGE].function)(sess, pkt->nick2,
-									  str_array[0],
-									  atol(str_array[1]),
-									  str_array[2]);
-		break;
-	case YAHOO_MESSAGE_BOUNCE:
-		if (sess->callbacks[YAHOO_HANDLE_BOUNCE].function)
-			(*sess->callbacks[YAHOO_HANDLE_BOUNCE].function)(sess);
-		break;
-	case YAHOO_MESSAGE_OFFLINE:
-		tmp = pkt->content;
-		if ((tmp = strchr(tmp, ',')) == NULL)
-			break;
-		++tmp;
-		if ((tmp = strchr(tmp, ',')) == NULL)
-			break;
-		str_array[0] = ++tmp;
-		if ((tmp = strchr(tmp, ',')) == NULL)
-			break;
-		*tmp++ = '\0';
-		str_array[1] = tmp;
-		if ((tmp = strchr(tmp, ',')) == NULL)
-			break;
-		*tmp++ = '\0';
-		str_array[2] = tmp;
-		if ((tmp = strchr(tmp, ',')) == NULL)
-			break;
-		*tmp++ = '\0';
-		str_array[3] = tmp;
-		if (sess->callbacks[YAHOO_HANDLE_MESSAGE].function)
-			(*sess->callbacks[YAHOO_HANDLE_MESSAGE].function)(sess, str_array[0],
-									  str_array[1],
-									  atol(str_array[2]),
-									  str_array[3]);
-		break;
-	default:
-		g_snprintf(buf, sizeof(buf), "unhandled message type %d", type);
-		YAHOO_PRINT(sess, YAHOO_LOG_WARNING, buf);
-		break;
-	}
-}
-
-static void yahoo_parse_packet(struct yahoo_session *sess,
-		struct yahoo_conn *conn, struct yahoo_packet *pkt)
-{
-	char buf[256];
-	int service = yahoo_makeint(pkt->service);
-	conn->magic_id = yahoo_makeint(pkt->magic_id);
-	g_snprintf(buf, sizeof(buf), "Service %d (msgtype %d): %s", service,
-			yahoo_makeint(pkt->msgtype), pkt->content);
-	YAHOO_PRINT(sess, YAHOO_LOG_DEBUG, buf);
-	switch(service) {
-	case YAHOO_SERVICE_LOGON:
-		if (yahoo_makeint(pkt->msgtype) == 0)
-			if (sess->callbacks[YAHOO_HANDLE_ONLINE].function)
-				(*sess->callbacks[YAHOO_HANDLE_ONLINE].function)(sess);
-	case YAHOO_SERVICE_LOGOFF:
-	case YAHOO_SERVICE_ISAWAY:
-	case YAHOO_SERVICE_ISBACK:
-		yahoo_parse_status(sess, pkt);
-		break;
-	case YAHOO_SERVICE_NEWCONTACT:
-		if (yahoo_makeint(pkt->msgtype) == 3) {
-			char **str_array = g_strsplit(pkt->content, ",", 3);
-			if (sess->callbacks[YAHOO_HANDLE_BUDDYADDED].function)
-				(*sess->callbacks[YAHOO_HANDLE_BUDDYADDED].function)(sess,
-										     pkt->nick2,
-										     str_array[0],
-										     atol(str_array[1]),
-										     str_array[2]);
-			g_strfreev(str_array);
-		} else
-			yahoo_parse_status(sess, pkt);
-		break;
-	case YAHOO_SERVICE_IDACT:
-		if (sess->callbacks[YAHOO_HANDLE_ACTIVATE].function)
-			(*sess->callbacks[YAHOO_HANDLE_ACTIVATE].function)(sess);
-		break;
-	case YAHOO_SERVICE_MESSAGE:
-		yahoo_parse_message(sess, pkt);
-		break;
-	case YAHOO_SERVICE_NEWMAIL:
-		if (sess->callbacks[YAHOO_HANDLE_NEWMAIL].function)
-			(*sess->callbacks[YAHOO_HANDLE_NEWMAIL].function)(sess, strlen(pkt->content) ?
-									  atoi(pkt->content) : 0);
-		break;
-	default:
-		g_snprintf(buf, sizeof(buf), "unhandled service type %d", service);
-		YAHOO_PRINT(sess, YAHOO_LOG_WARNING, buf);
-		break;
-	}
-}
-
-void yahoo_socket_handler(struct yahoo_session *session, int socket, int type)
-{
-	int pos = 0;
-	struct yahoo_conn *conn;
-
-	if (!session)
-		return;
-
-	if (!(conn = yahoo_find_conn(session, socket)))
-		return;
-
-	if (type == YAHOO_SOCKET_WRITE) {
-		int error = ETIMEDOUT, len = sizeof(error);
-
-		if (getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
-			error = errno;
-		if (error) {
-			yahoo_close(session, conn);
-			YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "unable to connect");
-			if (session->callbacks[YAHOO_HANDLE_DISCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_DISCONNECT].function)(session);
-			return;
-		}
-
-		fcntl(socket, F_SETFL, 0);
-
-		YAHOO_PRINT(session, YAHOO_LOG_NOTICE, "connected");
-
-		conn->connected = TRUE;
-		if (yahoo_socket_notify)
-			(*yahoo_socket_notify)(session, socket, YAHOO_SOCKET_WRITE, FALSE);
-		if (yahoo_socket_notify)
-			(*yahoo_socket_notify)(session, socket, YAHOO_SOCKET_READ, TRUE);
-
-		if (conn->type == YAHOO_CONN_TYPE_AUTH) {
-			if (session->callbacks[YAHOO_HANDLE_AUTHCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_AUTHCONNECT].function)(session);
-		} else if (conn->type == YAHOO_CONN_TYPE_MAIN) {
-			if (session->callbacks[YAHOO_HANDLE_MAINCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_MAINCONNECT].function)(session);
-		} else if (conn->type == YAHOO_CONN_TYPE_DUMB) {
-			YAHOO_PRINT(session, YAHOO_LOG_DEBUG, "sending to buddy list host");
-			yahoo_write(session, conn, conn->txqueue, strlen(conn->txqueue));
-			g_free(conn->txqueue);
-			conn->txqueue = NULL;
-		} else if (conn->type == YAHOO_CONN_TYPE_PROXY) {
-			char buf[1024];
-			g_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\n\r\n",
-					session->pager_host, session->pager_port);
-			YAHOO_PRINT(session, YAHOO_LOG_DEBUG, buf);
-			yahoo_write(session, conn, buf, strlen(buf));
-		}
-
-		return;
-	}
-
-	if (conn->type == YAHOO_CONN_TYPE_AUTH) {
-		char *buf = g_malloc0(5000);
-		while (read(socket, &buf[pos++], 1) == 1);
-		if (pos == 1) {
-			g_free(buf);
-			yahoo_close(session, conn);
-			YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "could not read auth response");
-			if (session->callbacks[YAHOO_HANDLE_DISCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_DISCONNECT].function)(session);
-			return;
-		}
-		YAHOO_PRINT(session, YAHOO_LOG_DEBUG, buf);
-		yahoo_parse_config(session, conn, buf);
-		g_free(buf);
-	} else if (conn->type == YAHOO_CONN_TYPE_MAIN) {
-		struct yahoo_packet pkt;
-		int len;
-
-		if ((read(socket, &pkt, 8) != 8) || strcmp(pkt.version, "YHOO1.0")) {
-			yahoo_close(session, conn);
-			YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "invalid version type");
-			if (session->callbacks[YAHOO_HANDLE_DISCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_DISCONNECT].function)(session);
-			return;
-		}
-
-		if (read(socket, &pkt.len, 4) != 4) {
-			yahoo_close(session, conn);
-			YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "could not read length");
-			if (session->callbacks[YAHOO_HANDLE_DISCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_DISCONNECT].function)(session);
-			return;
-		}
-		len = yahoo_makeint(pkt.len);
-
-		if (read(socket, &pkt.service, len - 12) != len - 12) {
-			yahoo_close(session, conn);
-			YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "could not read data");
-			if (session->callbacks[YAHOO_HANDLE_DISCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_DISCONNECT].function)(session);
-			return;
-		}
-		yahoo_parse_packet(session, conn, &pkt);
-	} else if (conn->type == YAHOO_CONN_TYPE_DUMB) {
-		char *buf = g_malloc0(5000);
-		while (read(socket, &buf[pos++], 1) == 1);
-		if (pos == 1) {
-			g_free(buf);
-			yahoo_close(session, conn);
-			YAHOO_PRINT(session, YAHOO_LOG_WARNING, "error reading from listserv");
-			return;
-		}
-		YAHOO_PRINT(session, YAHOO_LOG_DEBUG, buf);
-		YAHOO_PRINT(session, YAHOO_LOG_NOTICE, "closing buddy list host connnection");
-		yahoo_close(session, conn);
-		g_free(buf);
-	} else if (conn->type == YAHOO_CONN_TYPE_PROXY) {
-		char *buf = g_malloc0(5000);
-		int nlc = 0;
-		while ((nlc != 2) && (read(socket, &buf[pos++], 1) == 1)) {
-			if (buf[pos-1] == '\n')
-				nlc++;
-			else if (buf[pos-1] != '\r')
-				nlc = 0;
-		}
-		if (pos == 1) {
-			g_free(buf);
-			yahoo_close(session, conn);
-			YAHOO_PRINT(session, YAHOO_LOG_ERROR, "error reading from proxy");
-			if (session->callbacks[YAHOO_HANDLE_DISCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_DISCONNECT].function)(session);
-			return;
-		}
-		YAHOO_PRINT(session, YAHOO_LOG_DEBUG, buf);
-		if (!strncasecmp(buf, HTTP_GOODSTRING1, strlen(HTTP_GOODSTRING1)) ||
-		    !strncasecmp(buf, HTTP_GOODSTRING2, strlen(HTTP_GOODSTRING2))) {
-			conn->type = YAHOO_CONN_TYPE_MAIN;
-			YAHOO_PRINT(session, YAHOO_LOG_NOTICE, "proxy connected successfully");
-			if (session->callbacks[YAHOO_HANDLE_MAINCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_MAINCONNECT].function)(session);
-		} else {
-			yahoo_close(session, conn);
-			YAHOO_PRINT(session, YAHOO_LOG_ERROR, "proxy could not connect");
-			if (session->callbacks[YAHOO_HANDLE_DISCONNECT].function)
-				(*session->callbacks[YAHOO_HANDLE_DISCONNECT].function)(session);
-		}
-		g_free(buf);
-	}
-}
-
-void yahoo_add_handler(struct yahoo_session *session, int type, yahoo_callback function)
-{
-	if (!session)
-		return;
-
-	session->callbacks[type].function = function;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/yahoo/yahoo.c	Tue Nov 06 23:58:24 2001 +0000
@@ -0,0 +1,1074 @@
+/*
+ * gaim
+ *
+ * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
+ * libfaim code copyright 1998, 1999 Adam Fritzler <afritz@auk.cx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <crypt.h>
+#include "multi.h"
+#include "prpl.h"
+#include "gaim.h"
+#include "proxy.h"
+
+#include "pixmaps/status-away.xpm"
+#include "pixmaps/status-here.xpm"
+#include "pixmaps/status-idle.xpm"
+
+#define YAHOO_DEBUG
+
+#define USEROPT_MAIL 0
+
+#define USEROPT_PAGERHOST 3
+#define YAHOO_PAGER_HOST "scs.yahoo.com"
+#define USEROPT_PAGERPORT 4
+#define YAHOO_PAGER_PORT 5050
+
+enum yahoo_service {
+	YAHOO_SERVICE_LOGON = 1,
+	YAHOO_SERVICE_LOGOFF,
+	YAHOO_SERVICE_ISAWAY,
+	YAHOO_SERVICE_ISBACK,
+	YAHOO_SERVICE_IDLE,
+	YAHOO_SERVICE_MESSAGE,
+	YAHOO_SERVICE_IDACT,
+	YAHOO_SERVICE_IDDEACT,
+	YAHOO_SERVICE_MAILSTAT,
+	YAHOO_SERVICE_USERSTAT,
+	YAHOO_SERVICE_NEWMAIL,
+	YAHOO_SERVICE_CHATINVITE,
+	YAHOO_SERVICE_CALENDAR,
+	YAHOO_SERVICE_NEWPERSONALMAIL,
+	YAHOO_SERVICE_NEWCONTACT,
+	YAHOO_SERVICE_ADDIDENT,
+	YAHOO_SERVICE_ADDIGNORE,
+	YAHOO_SERVICE_PING,
+	YAHOO_SERVICE_GROUPRENAME,
+	YAHOO_SERVICE_SYSMESSAGE = 20,
+	YAHOO_SERVICE_PASSTHROUGH2 = 22,
+	YAHOO_SERVICE_CONFINVITE = 24,
+	YAHOO_SERVICE_CONFLOGON,
+	YAHOO_SERVICE_CONFDECLINE,
+	YAHOO_SERVICE_CONFLOGOFF,
+	YAHOO_SERVICE_CONFADDINVITE,
+	YAHOO_SERVICE_CONFMSG,
+	YAHOO_SERVICE_CHATLOGON,
+	YAHOO_SERVICE_CHATLOGOFF,
+	YAHOO_SERVICE_CHATMSG = 32,
+	YAHOO_SERVICE_GAMELOGON = 40,
+	YAHOO_SERVICE_GAMELOGOFF = 41,
+	YAHOO_SERVICE_FILETRANSFER = 70,
+	YAHOO_SERVICE_LIST = 85,
+	YAHOO_SERVICE_ADDBUDDY = 131,
+	YAHOO_SERVICE_REMBUDDY = 132
+};
+
+enum yahoo_status {
+	YAHOO_STATUS_AVAILABLE,
+	YAHOO_STATUS_BRB,
+	YAHOO_STATUS_BUSY,
+	YAHOO_STATUS_NOTATHOME,
+	YAHOO_STATUS_NOTATDESK,
+	YAHOO_STATUS_NOTINOFFICE,
+	YAHOO_STATUS_ONPHONE,
+	YAHOO_STATUS_ONVACATION,
+	YAHOO_STATUS_OUTTOLUNCH,
+	YAHOO_STATUS_STEPPEDOUT,
+	YAHOO_STATUS_INVISIBLE = 12,
+	YAHOO_STATUS_CUSTOM = 99,
+	YAHOO_STATUS_IDLE = 999,
+	YAHOO_STATUS_OFFLINE = 0x5a55aa56
+};
+
+struct yahoo_data {
+	int fd;
+	guchar *rxqueue;
+	int rxlen;
+	GHashTable *hash;
+	GSList *login;
+	int current_status;
+	gboolean logged_in;
+};
+
+struct yahoo_pair {
+	int key;
+	char *value;
+};
+
+struct yahoo_packet {
+	guint16 service;
+	guint32 status;
+	guint32 id;
+	GSList *hash;
+};
+
+struct yahoo_buddy {
+	char *name;
+	int state;
+	char *msg;
+};
+
+static char *yahoo_name() {
+	return "Yahoo";
+}
+
+#define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
+
+static struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id)
+{
+	struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1);
+
+	pkt->service = service;
+	pkt->status = status;
+	pkt->id = id;
+
+	return pkt;
+}
+
+static void yahoo_packet_hash(struct yahoo_packet *pkt, int key, char *value)
+{
+	struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1);
+	pair->key = key;
+	pair->value = g_strdup(value);
+	pkt->hash = g_slist_append(pkt->hash, pair);
+}
+
+static int yahoo_packet_length(struct yahoo_packet *pkt)
+{
+	GSList *l;
+
+	int len = 0;
+
+	l = pkt->hash;
+	while (l) {
+		struct yahoo_pair *pair = l->data;
+		int tmp = pair->key;
+		do {
+			tmp /= 10;
+			len++;
+		} while (tmp);
+		len += 2;
+		len += strlen(pair->value);
+		len += 2;
+		l = l->next;
+	}
+
+	return len;
+}
+
+/* sometimes i wish prpls could #include things from other prpls. then i could just
+ * use the routines from libfaim and not have to admit to knowing how they work. */
+#define yahoo_put16(buf, data) ( \
+		(*(buf) = (u_char)((data)>>8)&0xff), \
+		(*((buf)+1) = (u_char)(data)&0xff),  \
+		2)
+#define yahoo_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff))
+#define yahoo_put32(buf, data) ( \
+		(*((buf)) = (u_char)((data)>>24)&0xff), \
+		(*((buf)+1) = (u_char)((data)>>16)&0xff), \
+		(*((buf)+2) = (u_char)((data)>>8)&0xff), \
+		(*((buf)+3) = (u_char)(data)&0xff), \
+		4)
+#define yahoo_get32(buf) ((((*(buf))<<24)&0xff000000) + \
+		(((*((buf)+1))<<16)&0x00ff0000) + \
+		(((*((buf)+2))<< 8)&0x0000ff00) + \
+		(((*((buf)+3)    )&0x000000ff)))
+
+static void yahoo_packet_read(struct yahoo_packet *pkt, guchar *data, int len)
+{
+	int pos = 0;
+
+	while (pos + 1 < len) {
+		char key[64], *value;
+		int x;
+
+		struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1);
+		pkt->hash = g_slist_append(pkt->hash, pair);
+
+		x = 0;
+		while (pos + 1 < len) {
+			if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
+				break;
+			key[x++] = data[pos++];
+		}
+		key[x] = 0;
+		pos += 2;
+		pair->key = strtol(key, NULL, 10);
+
+		value = g_malloc(len - pos);
+		x = 0;
+		while (pos + 1 < len) {
+			if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
+				break;
+			value[x++] = data[pos++];
+		}
+		value[x] = 0;
+		pos += 2;
+		pair->value = g_strdup(value);
+		g_free(value);
+		debug_printf("Key: %d  \tValue: %s\n", pair->key, pair->value);
+	}
+}
+
+static void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data)
+{
+	GSList *l = pkt->hash;
+	int pos = 0;
+
+	while (l) {
+		struct yahoo_pair *pair = l->data;
+		guchar buf[100];
+
+		g_snprintf(buf, sizeof(buf), "%d", pair->key);
+		strcpy(data + pos, buf);
+		pos += strlen(buf);
+		data[pos++] = 0xc0;
+		data[pos++] = 0x80;
+
+		strcpy(data + pos, pair->value);
+		pos += strlen(pair->value);
+		data[pos++] = 0xc0;
+		data[pos++] = 0x80;
+
+		l = l->next;
+	}
+}
+
+static void yahoo_packet_dump(guchar *data, int len)
+{
+#ifdef YAHOO_DEBUG
+	int i;
+	for (i = 0; i + 1 < len; i += 2) {
+		if ((i % 16 == 0) && i)
+			debug_printf("\n");
+		debug_printf("%02x", data[i]);
+		debug_printf("%02x ", data[i+1]);
+	}
+	if (i < len)
+		debug_printf("%02x", data[i]);
+	debug_printf("\n");
+	for (i = 0; i < len; i++) {
+		if ((i % 16 == 0) && i)
+			debug_printf("\n");
+		if (isprint(data[i]))
+			debug_printf("%c ", data[i]);
+		else
+			debug_printf(". ");
+	}
+	debug_printf("\n");
+#endif
+}
+
+static int yahoo_send_packet(struct yahoo_data *yd, struct yahoo_packet *pkt)
+{
+	int pktlen = yahoo_packet_length(pkt);
+	int len = YAHOO_PACKET_HDRLEN + pktlen;
+	int ret;
+
+	guchar *data;
+	int pos = 0;
+
+	if (yd->fd < 0)
+		return -1;
+
+	data = g_malloc0(len + 1);
+
+	memcpy(data + pos, "YMSG", 4); pos += 4;
+	pos += yahoo_put16(data + pos, 0x0600);
+	pos += yahoo_put16(data + pos, 0x0000);
+	pos += yahoo_put16(data + pos, pktlen);
+	pos += yahoo_put16(data + pos, pkt->service);
+	pos += yahoo_put32(data + pos, pkt->status);
+	pos += yahoo_put32(data + pos, pkt->id);
+
+	yahoo_packet_write(pkt, data + pos);
+
+	yahoo_packet_dump(data, len);
+	ret = write(yd->fd, data, len);
+
+	g_free(data);
+
+	return ret;
+}
+
+static void yahoo_packet_free(struct yahoo_packet *pkt)
+{
+	while (pkt->hash) {
+		struct yahoo_pair *pair = pkt->hash->data;
+		g_free(pair->value);
+		g_free(pair);
+		pkt->hash = g_slist_remove(pkt->hash, pair);
+	}
+	g_free(pkt);
+}
+
+static void yahoo_process_logon(struct gaim_connection *gc, struct yahoo_packet *pkt)
+{
+	struct yahoo_data *yd = gc->proto_data;
+	GSList *l = pkt->hash;
+	struct yahoo_buddy *buddy = NULL;
+	struct yahoo_packet *newpkt;
+	char *name = NULL;
+	int state = 0;
+	char *msg = NULL;
+
+	while (l) {
+		struct yahoo_pair *pair = l->data;
+
+		switch (pair->key) {
+		case 0: /* we won't actually do anything with this */
+			break;
+		case 1: /* we don't get the full buddy list here. */
+			account_online(gc);
+			serv_finish_login(gc);
+			g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", pair->value);
+			do_import(gc, NULL);
+			yd->logged_in = TRUE;
+
+			/* this requests the list. i have a feeling that this is very evil */
+			newpkt = yahoo_packet_new(YAHOO_SERVICE_LIST, YAHOO_STATUS_OFFLINE, 0);
+			yahoo_send_packet(yd, newpkt);
+			yahoo_packet_free(newpkt);
+
+			break;
+		case 8: /* how many online buddies we have */
+			break;
+		case 7: /* the current buddy */
+			name = pair->value;
+			break;
+		case 10: /* state */
+			state = strtol(pair->value, NULL, 10);
+			break;
+		case 19: /* custom message */
+			msg = pair->value;
+			break;
+		case 11: /* i didn't know what this was in the old protocol either */
+			break;
+		case 17: /* in chat? */
+			break;
+		case 13: /* in pager, i think this should always be 1 */
+			/* we don't actually give notification here. we wait until after we've
+			 * gotten the list, so that they get added to the right group */
+			buddy = g_new0(struct yahoo_buddy, 1);
+			buddy->name = g_strdup(name);
+			buddy->state = state;
+			buddy->msg = msg ? g_strdup(msg) : NULL;
+			yd->login = g_slist_append(yd->login, buddy);
+			break;
+		default:
+			debug_printf("unknown login key %d\n", pair->key);
+			break;
+		}
+
+		l = l->next;
+	}
+}
+
+static void yahoo_process_list(struct gaim_connection *gc, struct yahoo_packet *pkt)
+{
+	struct yahoo_data *yd = gc->proto_data;
+	GSList *l = pkt->hash;
+	gboolean export = FALSE;
+
+	while (l) {
+		char **lines;
+		char **split;
+		char **buddies;
+		char **tmp, **bud;
+
+		struct yahoo_pair *pair = l->data;
+		l = l->next;
+
+		if (pair->key != 87)
+			continue;
+
+		lines = g_strsplit(pair->value, "\n", -1);
+		for (tmp = lines; *tmp; tmp++) {
+			split = g_strsplit(*tmp, ":", 2);
+			buddies = g_strsplit(split[1], ",", -1);
+			for (bud = buddies; *bud; bud++)
+				if (!find_buddy(gc, *bud)) {
+					add_buddy(gc, split[0], *bud, *bud);
+					export = TRUE;
+				}
+			g_strfreev(buddies);
+			g_strfreev(split);
+		}
+		g_strfreev(lines);
+	}
+
+	if (export)
+		do_export(gc);
+
+	while (yd->login) {
+		struct yahoo_buddy *buddy = yd->login->data;
+		int status = buddy->state;
+		yd->login = g_slist_remove(yd->login, buddy);
+		if (status == YAHOO_STATUS_AVAILABLE)
+			serv_got_update(gc, buddy->name, 1, 0, 0, 0, 0, 0);
+		else if (status == YAHOO_STATUS_IDLE)
+			serv_got_update(gc, buddy->name, 1, 0, 0, time(NULL) - 600, (status << 1), 0);
+		else
+			serv_got_update(gc, buddy->name, 1, 0, 0, 0, (status << 1) | UC_UNAVAILABLE, 0);
+		if (status == YAHOO_STATUS_CUSTOM) {
+			gpointer val = g_hash_table_lookup(yd->hash, buddy->name);
+			if (val) {
+				g_free(val);
+				g_hash_table_insert(yd->hash, buddy->name, g_strdup(buddy->msg));
+			} else
+				g_hash_table_insert(yd->hash, g_strdup(buddy->name), g_strdup(buddy->msg));
+		}
+		g_free(buddy->msg);
+		g_free(buddy->name);
+		g_free(buddy);
+	}
+}
+
+static void yahoo_process_message(struct gaim_connection *gc, struct yahoo_packet *pkt)
+{
+	char *msg = NULL;
+	char *from = NULL;
+	time_t tm = time(NULL);
+	GSList *l = pkt->hash;
+
+	while (l) {
+		struct yahoo_pair *pair = l->data;
+		if (pair->key == 4)
+			from = pair->value;
+		if (pair->key == 14)
+			msg = pair->value;
+		if (pair->key == 15)
+			tm = strtol(pair->value, NULL, 10);
+		l = l->next;
+	}
+
+	if (pkt->status == 1) {
+		strip_linefeed(msg);
+		serv_got_im(gc, from, msg, 0, tm);
+	} else if (pkt->status == 2) {
+		do_error_dialog(_("Your message did not get sent."), _("Gaim - Error"));
+	}
+}
+
+static void yahoo_process_status(struct gaim_connection *gc, struct yahoo_packet *pkt)
+{
+	struct yahoo_data *yd = gc->proto_data;
+	GSList *l = pkt->hash;
+	char *name = NULL;
+	int state = 0;
+	char *msg = NULL;
+
+	while (l) {
+		struct yahoo_pair *pair = l->data;
+
+		switch (pair->key) {
+		case 7:
+			name = pair->value;
+			break;
+		case 10:
+			state = strtol(pair->value, NULL, 10);
+			break;
+		case 19:
+			msg = pair->value;
+			break;
+		case 11: /* i didn't know what this was in the old protocol either */
+			break;
+		case 17: /* in chat? */
+			break;
+		case 13:
+			if (strtol(pair->value, NULL, 10) != 1) {
+				serv_got_update(gc, name, 0, 0, 0, 0, 0, 0);
+				break;
+			}
+			if (state == YAHOO_STATUS_AVAILABLE)
+				serv_got_update(gc, name, 1, 0, 0, 0, 0, 0);
+			else if (state == YAHOO_STATUS_IDLE)
+				serv_got_update(gc, name, 1, 0, 0, time(NULL) - 600, (state << 1), 0);
+			else
+				serv_got_update(gc, name, 1, 0, 0, 0, (state << 1) | UC_UNAVAILABLE, 0);
+			if (state == YAHOO_STATUS_CUSTOM) {
+				gpointer val = g_hash_table_lookup(yd->hash, name);
+				if (val) {
+					g_free(val);
+					g_hash_table_insert(yd->hash, name, g_strdup(msg));
+				} else
+					g_hash_table_insert(yd->hash, g_strdup(name), g_strdup(msg));
+			}
+			break;
+		}
+
+		l = l->next;
+	}
+}
+
+static void yahoo_process_contact(struct gaim_connection *gc, struct yahoo_packet *pkt)
+{
+	char *id = NULL;
+	char *who = NULL;
+	char *msg = NULL;
+	GSList *l = pkt->hash;
+
+	while (l) {
+		struct yahoo_pair *pair = l->data;
+		if (pair->key == 1)
+			id = pair->value;
+		else if (pair->key == 3)
+			who = pair->value;
+		else if (pair->key == 14)
+			msg = pair->value;
+		l = l->next;
+	}
+
+	show_got_added(gc, id, who, NULL, msg);
+}
+
+static void yahoo_process_mail(struct gaim_connection *gc, struct yahoo_packet *pkt)
+{
+	char *who = NULL;
+	char *email = NULL;
+	char *subj = NULL;
+	int count = 0;
+	GSList *l = pkt->hash;
+
+	while (l) {
+		struct yahoo_pair *pair = l->data;
+		if (pair->key == 9)
+			count = strtol(pair->value, NULL, 10);
+		else if (pair->key == 43)
+			who = pair->value;
+		else if (pair->key == 42)
+			email = pair->value;
+		else if (pair->key == 18)
+			subj = pair->value;
+		l = l->next;
+	}
+
+	connection_has_mail(gc, count, NULL, NULL, "http://mail.yahoo.com/");
+}
+
+static void yahoo_packet_process(struct gaim_connection *gc, struct yahoo_packet *pkt)
+{
+	switch (pkt->service)
+	{
+	case YAHOO_SERVICE_LOGON:
+		yahoo_process_logon(gc, pkt);
+		break;
+	case YAHOO_SERVICE_ISAWAY:
+		yahoo_process_status(gc, pkt);
+		break;
+	case YAHOO_SERVICE_MESSAGE:
+		yahoo_process_message(gc, pkt);
+		break;
+	case YAHOO_SERVICE_NEWMAIL:
+		yahoo_process_mail(gc, pkt);
+		break;
+	case YAHOO_SERVICE_NEWCONTACT:
+		yahoo_process_contact(gc, pkt);
+		break;
+	case YAHOO_SERVICE_LIST:
+		yahoo_process_list(gc, pkt);
+		break;
+	default:
+		debug_printf("unhandled service %d\n", pkt->service);
+		break;
+	}
+}
+
+static void yahoo_pending(gpointer data, gint source, GaimInputCondition cond)
+{
+	struct gaim_connection *gc = data;
+	struct yahoo_data *yd = gc->proto_data;
+	char buf[1024];
+	int len;
+
+	len = read(yd->fd, buf, sizeof(buf));
+
+	if (len <= 0) {
+		hide_login_progress(gc, "Unable to read");
+		signoff(gc);
+		return;
+	}
+
+	yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen);
+	memcpy(yd->rxqueue + yd->rxlen, buf, len);
+	yd->rxlen += len;
+
+	while (1) {
+		struct yahoo_packet *pkt;
+		int pos = 0;
+		int pktlen;
+
+		if (yd->rxlen < YAHOO_PACKET_HDRLEN)
+			return;
+
+		pos += 4; /* YMSG */
+		pos += 2;
+		pos += 2;
+
+		pktlen = yahoo_get16(yd->rxqueue + pos); pos += 2;
+		debug_printf("%d bytes to read, rxlen is %d\n", pktlen, yd->rxlen);
+
+		if (yd->rxlen < (YAHOO_PACKET_HDRLEN + pktlen))
+			return;
+
+		yahoo_packet_dump(yd->rxqueue, YAHOO_PACKET_HDRLEN + pktlen);
+
+		pkt = yahoo_packet_new(0, 0, 0);
+
+		pkt->service = yahoo_get16(yd->rxqueue + pos); pos += 2;
+		debug_printf("Yahoo Service: %d Status: %d\n", pkt->service, pkt->status);
+		pkt->status = yahoo_get32(yd->rxqueue + pos); pos += 4;
+		pkt->id = yahoo_get32(yd->rxqueue + pos); pos += 4;
+
+		yahoo_packet_read(pkt, yd->rxqueue + pos, pktlen);
+
+		yd->rxlen -= YAHOO_PACKET_HDRLEN + pktlen;
+		if (yd->rxlen) {
+			char *tmp = g_memdup(yd->rxqueue + YAHOO_PACKET_HDRLEN + pktlen, yd->rxlen);
+			g_free(yd->rxqueue);
+			yd->rxqueue = tmp;
+		} else {
+			g_free(yd->rxqueue);
+			yd->rxqueue = NULL;
+		}
+
+		yahoo_packet_process(gc, pkt);
+
+		yahoo_packet_free(pkt);
+	}
+}
+
+static void yahoo_got_connected(gpointer data, gint source, GaimInputCondition cond)
+{
+	struct gaim_connection *gc = data;
+	struct yahoo_data *yd;
+	struct yahoo_packet *pkt;
+
+	if (!g_slist_find(connections, gc)) {
+		close(source);
+		return;
+	}
+
+	if (source < 0) {
+		hide_login_progress(gc, "Unable to connect");
+		signoff(gc);
+		return;
+	}
+
+	yd = gc->proto_data;
+	yd->fd = source;
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_LOGON, YAHOO_STATUS_AVAILABLE, 0);
+
+	yahoo_packet_hash(pkt, 0, gc->username);
+	yahoo_packet_hash(pkt, 1, gc->username);
+	yahoo_packet_hash(pkt, 6, crypt(gc->password, "$1$_2S43d5f$"));
+
+	yahoo_send_packet(yd, pkt);
+
+	yahoo_packet_free(pkt);
+
+	gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc);
+}
+
+static void yahoo_login(struct aim_user *user) {
+	struct gaim_connection *gc = new_gaim_conn(user);
+	struct yahoo_data *yd = gc->proto_data = g_new0(struct yahoo_data, 1);
+
+	set_login_progress(gc, 1, "Connecting");
+
+	yd->fd = -1;
+	yd->hash = g_hash_table_new(g_str_hash, g_str_equal);
+
+	if (!proxy_connect(user->proto_opt[USEROPT_PAGERHOST][0] ?
+				user->proto_opt[USEROPT_PAGERHOST] : YAHOO_PAGER_HOST,
+			   user->proto_opt[USEROPT_PAGERPORT][0] ?
+				atoi(user->proto_opt[USEROPT_PAGERPORT]) : YAHOO_PAGER_PORT,
+			   yahoo_got_connected, gc)) {
+		hide_login_progress(gc, "Connection problem");
+		signoff(gc);
+		return;
+	}
+
+}
+
+static gboolean yahoo_destroy_hash(gpointer key, gpointer val, gpointer data)
+{
+	g_free(key);
+	g_free(val);
+	return TRUE;
+}
+
+static void yahoo_close(struct gaim_connection *gc) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	g_hash_table_foreach_remove(yd->hash, yahoo_destroy_hash, NULL);
+	g_hash_table_destroy(yd->hash);
+	if (yd->fd >= 0)
+		close(yd->fd);
+	if (yd->rxqueue)
+		g_free(yd->rxqueue);
+	while (yd->login) {
+		struct yahoo_buddy *buddy = yd->login->data;
+		yd->login = g_slist_remove(yd->login, buddy);
+		g_free(buddy->msg);
+		g_free(buddy->name);
+		g_free(buddy);
+	}
+	if (gc->inpa)
+		gaim_input_remove(gc->inpa);
+	g_free(yd);
+}
+
+static char **yahoo_list_icon(int uc)
+{
+	if ((uc >> 1) == YAHOO_STATUS_IDLE)
+		return status_idle_xpm;
+	else if (uc == 0)
+		return status_here_xpm;
+	return status_away_xpm;
+}
+
+static char *yahoo_get_status_string(enum yahoo_status a)
+{
+	switch (a) {
+	case YAHOO_STATUS_BRB:
+		return "Be Right Back";
+	case YAHOO_STATUS_BUSY:
+		return "Busy";
+	case YAHOO_STATUS_NOTATHOME:
+		return "Not At Home";
+	case YAHOO_STATUS_NOTATDESK:
+		return "Not At Desk";
+	case YAHOO_STATUS_NOTINOFFICE:
+		return "Not In Office";
+	case YAHOO_STATUS_ONPHONE:
+		return "On Phone";
+	case YAHOO_STATUS_ONVACATION:
+		return "On Vacation";
+	case YAHOO_STATUS_OUTTOLUNCH:
+		return "Out To Lunch";
+	case YAHOO_STATUS_STEPPEDOUT:
+		return "Stepped Out";
+	default:
+		return NULL;
+	}
+}
+
+static GList *yahoo_buddy_menu(struct gaim_connection *gc, char *who)
+{
+	GList *m = NULL;
+	struct proto_buddy_menu *pbm;
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	struct buddy *b = find_buddy(gc, who); /* this should never be null. if it is,
+						  segfault and get the bug report. */
+	static char buf[1024];
+
+	if (!(b->uc & UC_UNAVAILABLE))
+		return NULL;
+
+	pbm = g_new0(struct proto_buddy_menu, 1);
+	if ((b->uc >> 1) != YAHOO_STATUS_CUSTOM)
+		g_snprintf(buf, sizeof buf, "Status: %s", yahoo_get_status_string(b->uc >> 1));
+	else
+		g_snprintf(buf, sizeof buf, "Custom Status: %s",
+			   (char *)g_hash_table_lookup(yd->hash, b->name));
+	pbm->label = buf;
+	pbm->callback = NULL;
+	pbm->gc = gc;
+	m = g_list_append(m, pbm);
+
+	return m;
+}
+
+static GList *yahoo_user_opts()
+{
+	GList *m = NULL;
+	struct proto_user_opt *puo;
+
+	puo = g_new0(struct proto_user_opt, 1);
+	puo->label = "Pager Host:";
+	puo->def = YAHOO_PAGER_HOST;
+	puo->pos = USEROPT_PAGERHOST;
+	m = g_list_append(m, puo);
+
+	puo = g_new0(struct proto_user_opt, 1);
+	puo->label = "Pager Port:";
+	puo->def = "5050";
+	puo->pos = USEROPT_PAGERPORT;
+	m = g_list_append(m, puo);
+
+	return m;
+}
+
+static void yahoo_act_id(gpointer data, char *entry)
+{
+	struct gaim_connection *gc = data;
+	struct yahoo_data *yd = gc->proto_data;
+
+	struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_IDACT, YAHOO_STATUS_AVAILABLE, 0);
+	yahoo_packet_hash(pkt, 3, entry);
+	yahoo_send_packet(yd, pkt);
+	yahoo_packet_free(pkt);
+
+	g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", entry);
+}
+
+static void yahoo_do_action(struct gaim_connection *gc, char *act)
+{
+	if (!strcmp(act, "Activate ID")) {
+		do_prompt_dialog("Activate which ID:", gc->displayname, gc, yahoo_act_id, NULL);
+	}
+}
+
+static GList *yahoo_actions() {
+	GList *m = NULL;
+
+	m = g_list_append(m, "Activate ID");
+
+	return m;
+}
+
+static int yahoo_send_im(struct gaim_connection *gc, char *who, char *what, int flags)
+{
+	struct yahoo_data *yd = gc->proto_data;
+	struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, 0);
+
+	yahoo_packet_hash(pkt, 1, gc->displayname);
+	yahoo_packet_hash(pkt, 5, who);
+	yahoo_packet_hash(pkt, 14, what);
+
+	yahoo_send_packet(yd, pkt);
+
+	yahoo_packet_free(pkt);
+
+	return 1;
+}
+
+static void yahoo_set_away(struct gaim_connection *gc, char *state, char *msg)
+{
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	struct yahoo_packet *pkt;
+	char s[4];
+
+	gc->away = NULL;
+
+	if (msg) {
+		yd->current_status = YAHOO_STATUS_CUSTOM;
+		gc->away = "";
+	} else if (state) {
+		gc->away = "";
+		if (!strcmp(state, "Available")) {
+			yd->current_status = YAHOO_STATUS_AVAILABLE;
+			gc->away = NULL;
+		} else if (!strcmp(state, "Be Right Back")) {
+			yd->current_status = YAHOO_STATUS_BRB;
+		} else if (!strcmp(state, "Busy")) {
+			yd->current_status = YAHOO_STATUS_BUSY;
+		} else if (!strcmp(state, "Not At Home")) {
+			yd->current_status = YAHOO_STATUS_NOTATHOME;
+		} else if (!strcmp(state, "Not At Desk")) {
+			yd->current_status = YAHOO_STATUS_NOTATDESK;
+		} else if (!strcmp(state, "Not In Office")) {
+			yd->current_status = YAHOO_STATUS_NOTINOFFICE;
+		} else if (!strcmp(state, "On Phone")) {
+			yd->current_status = YAHOO_STATUS_ONPHONE;
+		} else if (!strcmp(state, "On Vacation")) {
+			yd->current_status = YAHOO_STATUS_ONVACATION;
+		} else if (!strcmp(state, "Out To Lunch")) {
+			yd->current_status = YAHOO_STATUS_OUTTOLUNCH;
+		} else if (!strcmp(state, "Stepped Out")) {
+			yd->current_status = YAHOO_STATUS_STEPPEDOUT;
+		} else if (!strcmp(state, "Invisible")) {
+			yd->current_status = YAHOO_STATUS_INVISIBLE;
+		} else if (!strcmp(state, GAIM_AWAY_CUSTOM)) {
+			if (gc->is_idle) {
+				yd->current_status = YAHOO_STATUS_IDLE;
+			} else {
+				yd->current_status = YAHOO_STATUS_AVAILABLE;
+			}
+			gc->away = NULL;
+		}
+	} else if (gc->is_idle) {
+		yd->current_status = YAHOO_STATUS_IDLE;
+	} else {
+		yd->current_status = YAHOO_STATUS_AVAILABLE;
+	}
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, yd->current_status, 0);
+	g_snprintf(s, sizeof(s), "%d", yd->current_status);
+	yahoo_packet_hash(pkt, 10, s);
+	if (yd->current_status == YAHOO_STATUS_CUSTOM)
+		yahoo_packet_hash(pkt, 19, msg);
+
+	yahoo_send_packet(yd, pkt);
+	yahoo_packet_free(pkt);
+}
+
+static void yahoo_set_idle(struct gaim_connection *gc, int idle)
+{
+	struct yahoo_data *yd = gc->proto_data;
+	struct yahoo_packet *pkt = NULL;
+
+	if (idle && yd->current_status == YAHOO_STATUS_AVAILABLE) {
+		pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_IDLE, 0);
+		yd->current_status = YAHOO_STATUS_IDLE;
+	} else if (!idle && yd->current_status == YAHOO_STATUS_IDLE) {
+		pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_AVAILABLE, 0);
+		yd->current_status = YAHOO_STATUS_AVAILABLE;
+	}
+
+	if (pkt) {
+		char buf[4];
+		g_snprintf(buf, sizeof(buf), "%d", yd->current_status);
+		yahoo_packet_hash(pkt, 10, buf);
+		yahoo_send_packet(yd, pkt);
+		yahoo_packet_free(pkt);
+	}
+}
+
+static GList *yahoo_away_states(struct gaim_connection *gc)
+{
+	GList *m = NULL;
+
+	m = g_list_append(m, "Available");
+	m = g_list_append(m, "Be Right Back");
+	m = g_list_append(m, "Busy");
+	m = g_list_append(m, "Not At Home");
+	m = g_list_append(m, "Not At Desk");
+	m = g_list_append(m, "Not In Office");
+	m = g_list_append(m, "On Phone");
+	m = g_list_append(m, "On Vacation");
+	m = g_list_append(m, "Out To Lunch");
+	m = g_list_append(m, "Stepped Out");
+	m = g_list_append(m, "Invisible");
+	m = g_list_append(m, GAIM_AWAY_CUSTOM);
+
+	return m;
+}
+
+static void yahoo_keepalive(struct gaim_connection *gc)
+{
+	struct yahoo_data *yd = gc->proto_data;
+	struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, 0);
+	yahoo_send_packet(yd, pkt);
+	yahoo_packet_free(pkt);
+}
+
+static void yahoo_add_buddy(struct gaim_connection *gc, char *who)
+{
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	struct yahoo_packet *pkt;
+	struct group *g;
+	char *group = NULL;
+
+	if (!yd->logged_in)
+		return;
+
+	g = find_group_by_buddy(gc, who);
+	if (g)
+		group = g->name;
+	else
+		group = "Buddies";
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0);
+	yahoo_packet_hash(pkt, 1, gc->displayname);
+	yahoo_packet_hash(pkt, 7, who);
+	yahoo_packet_hash(pkt, 65, group);
+	yahoo_send_packet(yd, pkt);
+	yahoo_packet_free(pkt);
+}
+
+static void yahoo_remove_buddy(struct gaim_connection *gc, char *who, char *group)
+{
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+
+	struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0);
+	yahoo_packet_hash(pkt, 1, gc->displayname);
+	yahoo_packet_hash(pkt, 7, who);
+	yahoo_packet_hash(pkt, 65, group);
+	yahoo_send_packet(yd, pkt);
+	yahoo_packet_free(pkt);
+}
+
+static struct prpl *my_protocol = NULL;
+
+void yahoo_init(struct prpl *ret) {
+	ret->protocol = PROTO_YAHOO;
+	ret->options = OPT_PROTO_MAIL_CHECK;
+	ret->name = yahoo_name;
+	ret->user_opts = yahoo_user_opts;
+	ret->login = yahoo_login;
+	ret->close = yahoo_close;
+	ret->buddy_menu = yahoo_buddy_menu;
+	ret->list_icon = yahoo_list_icon;
+	ret->actions = yahoo_actions;
+	ret->do_action = yahoo_do_action;
+	ret->send_im = yahoo_send_im;
+	ret->away_states = yahoo_away_states;
+	ret->set_away = yahoo_set_away;
+	ret->set_idle = yahoo_set_idle;
+	ret->keepalive = yahoo_keepalive;
+	ret->add_buddy = yahoo_add_buddy;
+	ret->remove_buddy = yahoo_remove_buddy;
+
+	my_protocol = ret;
+}
+
+#ifndef STATIC
+
+char *gaim_plugin_init(GModule *handle)
+{
+	load_protocol(yahoo_init, sizeof(struct prpl));
+	return NULL;
+}
+
+void gaim_plugin_remove()
+{
+	struct prpl *p = find_prpl(PROTO_YAHOO);
+	if (p == my_protocol)
+		unload_protocol(p);
+}
+
+char *name()
+{
+	return "Yahoo";
+}
+
+char *description()
+{
+	return PRPL_DESC("Yahoo");
+}
+
+#endif
--- a/src/protocols/yahoo/yay.c	Tue Nov 06 21:30:31 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,762 +0,0 @@
-/*
- * gaim
- *
- * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- * libfaim code copyright 1998, 1999 Adam Fritzler <afritz@auk.cx>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-
-#include <netdb.h>
-#include <unistd.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include "multi.h"
-#include "prpl.h"
-#include "gaim.h"
-#include "yay.h"
-#include "proxy.h"
-
-#include "pixmaps/status-away.xpm"
-#include "pixmaps/status-here.xpm"
-#include "pixmaps/status-idle.xpm"
-
-#define USEROPT_MAIL 0
-
-#define USEROPT_AUTHHOST 1
-#define USEROPT_AUTHPORT 2
-#define USEROPT_PAGERHOST 3
-#define USEROPT_PAGERPORT 4
-
-struct conn {
-	int socket;
-	int type;
-	int inpa;
-};
-
-struct connect {
-	struct yahoo_session *sess;
-	gpointer data;
-};
-
-struct yahoo_data {
-	struct yahoo_session *sess;
-	int current_status;
-	GHashTable *hash;
-	char *active_id;
-	GList *conns;
-	gboolean logged_in;
-};
-
-static char *yahoo_name() {
-	return "Yahoo";
-}
-
-static int yahoo_status(struct yahoo_session *sess, ...) {
-	struct gaim_connection *gc = sess->user_data;
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
-	time_t tmptime;
-	struct buddy *b;
-	gboolean online;
-
-	va_list ap;
-	char *who;
-	int status;
-	char *msg;
-	int in_pager, in_chat, in_game;
-
-	va_start(ap, sess);
-	who = va_arg(ap, char *);
-	status = va_arg(ap, int);
-	msg = va_arg(ap, char *);
-	in_pager = va_arg(ap, int);
-	in_chat = va_arg(ap, int);
-	in_game = va_arg(ap, int);
-	va_end(ap);
-
-	online = in_pager || in_chat || in_game;
-
-	b = find_buddy(gc, who);
-	if (!b) return 0;
-	if (!online)
-		serv_got_update(gc, b->name, 0, 0, 0, 0, 0, 0);
-	else {
-		if (status == YAHOO_STATUS_AVAILABLE)
-			serv_got_update(gc, b->name, 1, 0, 0, 0, 0, 0);
-		else if (status == YAHOO_STATUS_IDLE) {
-			time(&tmptime);
-			serv_got_update(gc, b->name, 1, 0, 0, tmptime - 600, (status << 1), 0);
-		} else
-			serv_got_update(gc, b->name, 1, 0, 0, 0, (status << 1) | UC_UNAVAILABLE, 0);
-		if (status == YAHOO_STATUS_CUSTOM) {
-			gpointer val = g_hash_table_lookup(yd->hash, b->name);
-			if (val)
-				g_free(val);
-			g_hash_table_insert(yd->hash, g_strdup(b->name), g_strdup(msg));
-		}
-	}
-
-	return 1;
-}
-
-static int yahoo_message(struct yahoo_session *sess, ...) {
-	struct gaim_connection *gc = sess->user_data;
-	char buf[BUF_LEN * 4];
-	char *tmp, *c, *e;
-	time_t tm;
-	int at = 0;
-
-	va_list ap;
-	char *id, *nick, *msg;
-
-	va_start(ap, sess);
-	id = va_arg(ap, char *);
-	nick = va_arg(ap, char *);
-	tm = va_arg(ap, time_t);
-	msg = va_arg(ap, char *);
-	va_end(ap);
-
-	if (msg)
-		e = tmp = g_strdup(msg);
-	else
-		return 1;
-
-	while ((c = strchr(e, '\033')) != NULL) {
-		*c++ = '\0';
-		at += g_snprintf(buf + at, sizeof(buf) - at, "%s", e);
-		e = ++c;
-		while (*e && (*e++ != 'm'));
-	}
-
-	if (*e)
-		g_snprintf(buf + at, sizeof(buf) - at, "%s", e);
-
-	g_free(tmp);
-
-	strip_linefeed(buf);
-	serv_got_im(gc, nick, buf, 0, tm ? tm : time((time_t)NULL));
-
-	return 1;
-}
-
-static int yahoo_bounce(struct yahoo_session *sess, ...) {
-	do_error_dialog(_("Your message did not get sent."), _("Gaim - Error"));
-	
-	return 1;
-}
-
-static int yahoo_buddyadded(struct yahoo_session *sess, ...) {
-	va_list ap;
-	char *id;
-	time_t t;
-	char *who;
-	char *msg;
-
-	va_start(ap, sess);
-	id = va_arg(ap, char *);
-	who = va_arg(ap, char *);
-	t = va_arg(ap, time_t);
-	msg = va_arg(ap, char *);
-	va_end(ap);
-
-	show_got_added(sess->user_data, id, who, NULL, msg);
-
-	return 1;
-}
-
-static int yahoo_newmail(struct yahoo_session *sess, ...) {
-	struct gaim_connection *gc = sess->user_data;
-
-	va_list ap;
-	int count;
-
-	va_start(ap, sess);
-	count = va_arg(ap, int);
-	va_end(ap);
-
-	connection_has_mail(gc, count, NULL, NULL, "http://mail.yahoo.com/");
-
-	return 1;
-}
-
-static int yahoo_disconn(struct yahoo_session *sess, ...) {
-	struct gaim_connection *gc = sess->user_data;
-	hide_login_progress(gc, "Disconnected");
-	signoff(gc);
-	return 1;
-}
-
-static int yahoo_authconnect(struct yahoo_session *sess, ...) {
-	struct gaim_connection *gc = sess->user_data;
-
-	set_login_progress(gc, 2, "Connected to Auth");
-	if (yahoo_send_login(sess, gc->username, gc->password) < 1) {
-		hide_login_progress(gc, "Authorizer error");
-		signoff(gc);
-		return 0;
-	}
-
-	return 1;
-}
-
-static int yahoo_badpassword(struct yahoo_session *sess, ...) {
-	struct gaim_connection *gc = sess->user_data;
-	hide_login_progress(gc, "Bad Password");
-	signoff(gc);
-	return 1;
-}
-
-static int yahoo_logincookie(struct yahoo_session *sess, ...) {
-	struct gaim_connection *gc = sess->user_data;
-
-	set_login_progress(gc, 3, "Got login cookie");
-	if (yahoo_major_connect(sess, gc->user->proto_opt[USEROPT_PAGERHOST],
-				atoi(gc->user->proto_opt[USEROPT_PAGERPORT])) < 1) {
-		hide_login_progress(gc, "Login error");
-		signoff(gc);
-	}
-
-	return 1;
-}
-
-static int yahoo_mainconnect(struct yahoo_session *sess, ...) {
-	struct gaim_connection *gc = sess->user_data;
-	struct yahoo_data *yd = gc->proto_data;
-	GList *grps;
-
-	set_login_progress(gc, 4, "Connected to service");
-	if (yahoo_finish_logon(sess, YAHOO_STATUS_AVAILABLE) < 1) {
-		hide_login_progress(gc, "Login error");
-		signoff(gc);
-		return 0;
-	}
-
-	if (bud_list_cache_exists(gc))
-		do_import(gc, NULL);
-
-	grps = yd->sess->groups;
-	while (grps) {
-		struct yahoo_group *grp = grps->data;
-		int i;
-		
-		for (i = 0; grp->buddies[i]; i++)
-			add_buddy(gc, grp->name, grp->buddies[i], NULL);
-
-		grps = grps->next;
-	}
-
-	return 1;
-}
-
-static int yahoo_online(struct yahoo_session *sess, ...) {
-	struct gaim_connection *gc = sess->user_data;
-	struct yahoo_data *yd = gc->proto_data;
-
-	account_online(gc);
-	serv_finish_login(gc);
-	if (yd->active_id)
-		g_free(yd->active_id);
-	yd->active_id = g_strdup(gc->username);
-	yd->logged_in = TRUE;
-
-	return 1;
-}
-
-static void yahoo_pending(gpointer data, gint source, GaimInputCondition condition) {
-	struct gaim_connection *gc = (struct gaim_connection *)data;
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
-
-	yahoo_socket_handler(yd->sess, source, condition);
-}
-
-static void yahoo_notify(struct yahoo_session *sess, int socket, int type, int cont) {
-	struct gaim_connection *gc = sess->user_data;
-	struct yahoo_data *yd;
-
-	if (!g_slist_find(connections, gc))
-		return;
-	
-	yd = gc->proto_data;
-
-	if (cont) {
-		struct conn *c = g_new0(struct conn, 1);
-		c->socket = socket;
-		c->type = type;
-		c->inpa = gaim_input_add(socket, type, yahoo_pending, gc);
-		yd->conns = g_list_append(yd->conns, c);
-	} else {
-		GList *c = yd->conns;
-		while (c) {
-			struct conn *m = c->data;
-			if ((m->socket == socket) && (m->type == type)) {
-				yd->conns = g_list_remove(yd->conns, m);
-				gaim_input_remove(m->inpa);
-				g_free(m);
-				return;
-			}
-			c = g_list_next(c);
-		}
-	}
-}
-
-static void yahoo_got_connected(gpointer data, gint source, GaimInputCondition cond) {
-	struct connect *con = data;
-	struct gaim_connection *gc = con->sess->user_data;
-
-	if (!g_slist_find(connections, gc)) {
-		close(source);
-		g_free(con);
-		return;
-	}
-
-	debug_printf("got connected (possibly)\n");
-	yahoo_connected(con->sess, con->data, source);
-
-	g_free(con);
-}
-
-static int yahoo_connect_to(struct yahoo_session *sess, const char *host, int port, gpointer data) {
-	struct connect *con = g_new0(struct connect, 1);
-	int fd;
-
-	con->sess = sess;
-	con->data = data;
-	fd = proxy_connect((char *)host, port, yahoo_got_connected, con);
-	if (fd < 0) {
-		g_free(con);
-		return -1;
-	}
-
-	return fd;
-}
-
-static void yahoo_debug(struct yahoo_session *sess, int level, const char *string) {
-	debug_printf("Level %d: %s\n", level, string);
-}
-
-static void yahoo_login(struct aim_user *user) {
-	struct gaim_connection *gc = new_gaim_conn(user);
-	struct yahoo_data *yd = gc->proto_data = g_new0(struct yahoo_data, 1);
-
-	yd->sess = yahoo_new();
-	yd->sess->user_data = gc;
-	yd->current_status = YAHOO_STATUS_AVAILABLE;
-	yd->hash = g_hash_table_new(g_str_hash, g_str_equal);
-
-	set_login_progress(gc, 1, "Connecting");
-
-	if (!yahoo_connect(yd->sess, user->proto_opt[USEROPT_AUTHHOST],
-				atoi(user->proto_opt[USEROPT_AUTHPORT]))) {
-		hide_login_progress(gc, "Connection problem");
-		signoff(gc);
-		return;
-	}
-
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_DISCONNECT, yahoo_disconn);
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_AUTHCONNECT, yahoo_authconnect);
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_BADPASSWORD, yahoo_badpassword);
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_LOGINCOOKIE, yahoo_logincookie);
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_MAINCONNECT, yahoo_mainconnect);
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_ONLINE, yahoo_online);
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_NEWMAIL, yahoo_newmail);
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_MESSAGE, yahoo_message);
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_BOUNCE, yahoo_bounce);
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_STATUS, yahoo_status);
-	yahoo_add_handler(yd->sess, YAHOO_HANDLE_BUDDYADDED, yahoo_buddyadded);
-}
-
-static gboolean yahoo_destroy_hash(gpointer key, gpointer val, gpointer data) {
-	g_free(key);
-	g_free(val);
-	return TRUE;
-}
-
-static void yahoo_close(struct gaim_connection *gc) {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
-	g_hash_table_foreach_remove(yd->hash, yahoo_destroy_hash, NULL);
-	g_hash_table_destroy(yd->hash);
-	yahoo_disconnect(yd->sess);
-	yahoo_delete(yd->sess);
-	g_free(yd->active_id);
-	g_free(yd);
-}
-
-static int yahoo_send_im(struct gaim_connection *gc, char *who, char *message, int flags) {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
-
-	if ((flags & IM_FLAG_AWAY)|| !strlen(message)) return 0;
-
-	if (flags & IM_FLAG_CHECKBOX)
-		yahoo_send_message_offline(yd->sess, yd->active_id, who, message);
-	else
-		yahoo_send_message(yd->sess, yd->active_id, who, message);
-	return 1;
-}
-
-static void yahoo_set_away(struct gaim_connection *gc, char *state, char *msg) {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
-
-	gc->away = NULL;
-
-	if (msg) {
-		yahoo_away(yd->sess, YAHOO_STATUS_CUSTOM, msg);
-		yd->current_status = YAHOO_STATUS_CUSTOM;
-		gc->away = "";
-	} else if (state) {
-		gc->away = "";
-		if (!strcmp(state, "Available")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_AVAILABLE, msg);
-			yd->current_status = YAHOO_STATUS_AVAILABLE;
-		} else if (!strcmp(state, "Be Right Back")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_BRB, msg);
-			yd->current_status = YAHOO_STATUS_BRB;
-		} else if (!strcmp(state, "Busy")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_BUSY, msg);
-			yd->current_status = YAHOO_STATUS_BUSY;
-		} else if (!strcmp(state, "Not At Home")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_NOTATHOME, msg);
-			yd->current_status = YAHOO_STATUS_NOTATHOME;
-		} else if (!strcmp(state, "Not At Desk")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_NOTATDESK, msg);
-			yd->current_status = YAHOO_STATUS_NOTATDESK;
-		} else if (!strcmp(state, "Not In Office")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_NOTINOFFICE, msg);
-			yd->current_status = YAHOO_STATUS_NOTINOFFICE;
-		} else if (!strcmp(state, "On Phone")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_ONPHONE, msg);
-			yd->current_status = YAHOO_STATUS_ONPHONE;
-		} else if (!strcmp(state, "On Vacation")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_ONVACATION, msg);
-			yd->current_status = YAHOO_STATUS_ONVACATION;
-		} else if (!strcmp(state, "Out To Lunch")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_OUTTOLUNCH, msg);
-			yd->current_status = YAHOO_STATUS_OUTTOLUNCH;
-		} else if (!strcmp(state, "Stepped Out")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_STEPPEDOUT, msg);
-			yd->current_status = YAHOO_STATUS_STEPPEDOUT;
-		} else if (!strcmp(state, "Invisible")) {
-			yahoo_away(yd->sess, YAHOO_STATUS_INVISIBLE, msg);
-			yd->current_status = YAHOO_STATUS_INVISIBLE;
-		} else if (!strcmp(state, GAIM_AWAY_CUSTOM)) {
-			if (gc->is_idle) {
-				yahoo_away(yd->sess, YAHOO_STATUS_IDLE, NULL);
-				yd->current_status = YAHOO_STATUS_IDLE;
-			} else {
-				yahoo_away(yd->sess, YAHOO_STATUS_AVAILABLE, NULL);
-				yd->current_status = YAHOO_STATUS_AVAILABLE;
-			}
-			gc->away = NULL;
-		}
-	} else if (gc->is_idle) {
-		yahoo_away(yd->sess, YAHOO_STATUS_IDLE, NULL);
-		yd->current_status = YAHOO_STATUS_IDLE;
-	} else {
-		yahoo_away(yd->sess, YAHOO_STATUS_AVAILABLE, NULL);
-		yd->current_status = YAHOO_STATUS_AVAILABLE;
-	}
-}
-
-static void yahoo_set_idle(struct gaim_connection *gc, int idle) {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
-
-	if (idle && yd->current_status == YAHOO_STATUS_AVAILABLE) {
-		yahoo_away(yd->sess, YAHOO_STATUS_IDLE, NULL);
-		yd->current_status = YAHOO_STATUS_IDLE;
-	} else if (!idle && yd->current_status == YAHOO_STATUS_IDLE) {
-		yahoo_back(yd->sess, YAHOO_STATUS_AVAILABLE, NULL);
-		yd->current_status = YAHOO_STATUS_AVAILABLE;
-	}
-}
-
-static void yahoo_keepalive(struct gaim_connection *gc) {
-	yahoo_ping(((struct yahoo_data *)gc->proto_data)->sess);
-}
-
-static void gyahoo_add_buddy(struct gaim_connection *gc, char *name) {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
-	struct yahoo_group *tmpgroup;
-	struct group *g = find_group_by_buddy(gc, name);
-	char *group = NULL;
-
-	if (!yd->logged_in)
-		return;
-
-	if (g) {
-		group = g->name;
-	} else if (yd->sess && yd->sess->groups) {
-		tmpgroup = yd->sess->groups->data;
-		group = tmpgroup->name;
-	} else {
-		group = "Buddies";
-	}
-
-	if (group)
-		yahoo_add_buddy(yd->sess, yd->active_id, group, normalize(name), "");
-}
-
-static void yahoo_add_buddies(struct gaim_connection *gc, GList *buddies) {
-	while (buddies) {
-		gyahoo_add_buddy(gc, buddies->data);
-		buddies = buddies->next;
-	}
-}
-
-static void gyahoo_remove_buddy(struct gaim_connection *gc, char *name) {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
-	struct group *g = find_group_by_buddy(gc, name);
-	char *group = NULL;
-
-	if (g) {
-		group = g->name;
-	} else if (yd->sess && yd->sess->groups) {
-		GList *x = yd->sess->groups;
-		while (x) {
-			struct yahoo_group *tmpgroup = x->data;
-			char **bds = tmpgroup->buddies;
-			while (*bds) {
-				if (!strcmp(*bds, name))
-					break;
-				bds++;
-			}
-			if (*bds) {
-				group = tmpgroup->name;
-				break;
-			}
-			x = x->next;
-		}
-	} else {
-		group = "Buddies";
-	}
-
-	if (group)
-		yahoo_remove_buddy(yd->sess, yd->active_id, group, name, "");
-}
-
-static char **yahoo_list_icon(int uc) {
-	if ((uc >> 1) == YAHOO_STATUS_IDLE)
-		return status_idle_xpm;
-	else if (uc == 0)
-		return status_here_xpm;
-	return status_away_xpm;
-}
-
-static char *yahoo_get_status_string(enum yahoo_status a) {
-	switch (a) {
-	case YAHOO_STATUS_BRB:
-		return "Be Right Back";
-	case YAHOO_STATUS_BUSY:
-		return "Busy";
-	case YAHOO_STATUS_NOTATHOME:
-		return "Not At Home";
-	case YAHOO_STATUS_NOTATDESK:
-		return "Not At Desk";
-	case YAHOO_STATUS_NOTINOFFICE:
-		return "Not In Office";
-	case YAHOO_STATUS_ONPHONE:
-		return "On Phone";
-	case YAHOO_STATUS_ONVACATION:
-		return "On Vacation";
-	case YAHOO_STATUS_OUTTOLUNCH:
-		return "Out To Lunch";
-	case YAHOO_STATUS_STEPPEDOUT:
-		return "Stepped Out";
-	default:
-		return NULL;
-	}
-}
-
-static GList *yahoo_buddy_menu(struct gaim_connection *gc, char *who) {
-	GList *m = NULL;
-	struct proto_buddy_menu *pbm;
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
-	struct buddy *b = find_buddy(gc, who); /* this should never be null. if it is,
-						  segfault and get the bug report. */
-	static char buf[1024];
-
-	if (!(b->uc & UC_UNAVAILABLE))
-		return NULL;
-
-	pbm = g_new0(struct proto_buddy_menu, 1);
-	if ((b->uc >> 1) != YAHOO_STATUS_CUSTOM)
-		g_snprintf(buf, sizeof buf, "Status: %s", yahoo_get_status_string(b->uc >> 1));
-	else
-		g_snprintf(buf, sizeof buf, "Custom Status: %s",
-			   (char *)g_hash_table_lookup(yd->hash, b->name));
-	pbm->label = buf;
-	pbm->callback = NULL;
-	pbm->gc = gc;
-	m = g_list_append(m, pbm);
-
-	return m;
-}
-
-static GList *yahoo_away_states(struct gaim_connection *gc) {
-	GList *m = NULL;
-
-	m = g_list_append(m, "Available");
-	m = g_list_append(m, "Be Right Back");
-	m = g_list_append(m, "Busy");
-	m = g_list_append(m, "Not At Home");
-	m = g_list_append(m, "Not At Desk");
-	m = g_list_append(m, "Not In Office");
-	m = g_list_append(m, "On Phone");
-	m = g_list_append(m, "On Vacation");
-	m = g_list_append(m, "Out To Lunch");
-	m = g_list_append(m, "Stepped Out");
-	m = g_list_append(m, "Invisible");
-	m = g_list_append(m, GAIM_AWAY_CUSTOM);
-
-	return m;
-}
-
-static void yahoo_act_id(gpointer data, char *entry) {
-	struct gaim_connection *gc = data;
-	struct yahoo_data *yd = gc->proto_data;
-
-	yahoo_activate_id(yd->sess, entry);
-	if (yd->active_id)
-		g_free(yd->active_id);
-	yd->active_id = g_strdup(entry);
-	g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", yd->active_id);
-}
-
-static void yahoo_do_action(struct gaim_connection *gc, char *act) {
-	if (!strcmp(act, "Activate ID")) {
-		do_prompt_dialog("Activate which ID:", gc->displayname, gc, yahoo_act_id, NULL);
-	}
-}
-
-static GList *yahoo_actions() {
-	GList *m = NULL;
-
-	m = g_list_append(m, "Activate ID");
-
-	return m;
-}
-
-static GList *yahoo_user_opts()
-{
-	GList *m = NULL;
-	struct proto_user_opt *puo;
-
-	puo = g_new0(struct proto_user_opt, 1);
-	puo->label = "Auth Host:";
-	puo->def = YAHOO_AUTH_HOST;
-	puo->pos = USEROPT_AUTHHOST;
-	m = g_list_append(m, puo);
-
-	puo = g_new0(struct proto_user_opt, 1);
-	puo->label = "Auth Port:";
-	puo->def = "80";
-	puo->pos = USEROPT_AUTHPORT;
-	m = g_list_append(m, puo);
-
-	puo = g_new0(struct proto_user_opt, 1);
-	puo->label = "Pager Host:";
-	puo->def = YAHOO_PAGER_HOST;
-	puo->pos = USEROPT_PAGERHOST;
-	m = g_list_append(m, puo);
-
-	puo = g_new0(struct proto_user_opt, 1);
-	puo->label = "Pager Port:";
-	puo->def = "5050";
-	puo->pos = USEROPT_PAGERPORT;
-	m = g_list_append(m, puo);
-
-	return m;
-}
-
-static struct prpl *my_protocol = NULL;
-
-void yahoo_init(struct prpl *ret) {
-	/* the NULL's aren't required but they're nice to have */
-	ret->protocol = PROTO_YAHOO;
-	ret->options = OPT_PROTO_MAIL_CHECK;
-	ret->checkbox = _("Send offline message");
-	ret->name = yahoo_name;
-	ret->list_icon = yahoo_list_icon;
-	ret->away_states = yahoo_away_states;
-	ret->actions = yahoo_actions;
-	ret->do_action = yahoo_do_action;
-	ret->buddy_menu = yahoo_buddy_menu;
-	ret->user_opts = yahoo_user_opts;
-	ret->login = yahoo_login;
-	ret->close = yahoo_close;
-	ret->send_im = yahoo_send_im;
-	ret->set_info = NULL;
-	ret->get_info = NULL;
-	ret->set_away = yahoo_set_away;
-	ret->set_dir = NULL;
-	ret->get_dir = NULL;
-	ret->dir_search = NULL;
-	ret->set_idle = yahoo_set_idle;
-	ret->change_passwd = NULL;
-	ret->add_buddy = gyahoo_add_buddy;
-	ret->add_buddies = yahoo_add_buddies;
-	ret->remove_buddy = gyahoo_remove_buddy;
-	ret->add_permit = NULL;
-	ret->add_deny = NULL;
-	ret->rem_permit = NULL;
-	ret->rem_deny = NULL;
-	ret->set_permit_deny = NULL;
-	ret->warn = NULL;
-	ret->keepalive = yahoo_keepalive;
-
-	my_protocol = ret;
-
-	yahoo_socket_notify = yahoo_notify;
-	yahoo_print = yahoo_debug;
-	yahoo_connector = yahoo_connect_to;
-}
-
-#ifndef STATIC
-
-char *gaim_plugin_init(GModule *handle)
-{
-	load_protocol(yahoo_init, sizeof(struct prpl));
-	return NULL;
-}
-
-void gaim_plugin_remove()
-{
-	struct prpl *p = find_prpl(PROTO_YAHOO);
-	if (p == my_protocol)
-		unload_protocol(p);
-}
-
-char *name()
-{
-	return "Yahoo";
-}
-
-char *description()
-{
-	return PRPL_DESC("Yahoo");
-}
-
-#endif
--- a/src/protocols/yahoo/yay.h	Tue Nov 06 21:30:31 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * libyay
- *
- * Copyright (C) 2001 Eric Warmenhoven <warmenhoven@yahoo.com>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef _LIBYAY_H
-#define _LIBYAY_H
-
-#include <glib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-struct yahoo_session;
-
-#define YAHOO_PROXY_NONE 0
-#define YAHOO_PROXY_HTTP 1
-
-#define YAHOO_AUTH_HOST "msg.edit.yahoo.com"
-#define YAHOO_AUTH_PORT 80
-#define YAHOO_PAGER_HOST "cs.yahoo.com"
-#define YAHOO_PAGER_PORT 5050
-
-enum yahoo_status {
-	YAHOO_STATUS_AVAILABLE,
-	YAHOO_STATUS_BRB,
-	YAHOO_STATUS_BUSY,
-	YAHOO_STATUS_NOTATHOME,
-	YAHOO_STATUS_NOTATDESK,
-	YAHOO_STATUS_NOTINOFFICE,
-	YAHOO_STATUS_ONPHONE,
-	YAHOO_STATUS_ONVACATION,
-	YAHOO_STATUS_OUTTOLUNCH,
-	YAHOO_STATUS_STEPPEDOUT,
-	YAHOO_STATUS_INVISIBLE = 12,
-	YAHOO_STATUS_CUSTOM = 99,
-	YAHOO_STATUS_IDLE = 999
-};
-
-struct yahoo_session *yahoo_new();
-void yahoo_set_proxy(struct yahoo_session *session, int proxy_type, char *proxy_host, int proxy_port);
-int yahoo_connect(struct yahoo_session *session, const char *host, int port);
-int yahoo_send_login(struct yahoo_session *session, const char *name, const char *password);
-int yahoo_major_connect(struct yahoo_session *session, const char *host, int port);
-int yahoo_finish_logon(struct yahoo_session *session, enum yahoo_status status);
-int yahoo_logoff(struct yahoo_session *session);
-int yahoo_disconnect(struct yahoo_session *session);
-int yahoo_delete(struct yahoo_session *session);
-
-int yahoo_activate_id(struct yahoo_session *session, char *id);
-int yahoo_deactivate_id(struct yahoo_session *session, char *id);
-int yahoo_send_message(struct yahoo_session *session, const char *id, const char *user, const char *msg);
-int yahoo_send_message_offline(struct yahoo_session *session, const char *id,
-		const char *user, const char *msg);
-int yahoo_away(struct yahoo_session *session, enum yahoo_status stats, char *msg);
-int yahoo_back(struct yahoo_session *session, enum yahoo_status stats, char *msg);
-int yahoo_ping(struct yahoo_session *session);
-
-int yahoo_add_buddy(struct yahoo_session *session, const char *active_id,
-		const char *group, const char *buddy, const char *message);
-int yahoo_remove_buddy(struct yahoo_session *session, const char *active_id,
-		const char *group, const char *buddy, const char *message);
-
-extern void (*yahoo_socket_notify)(struct yahoo_session *session, int socket, int type, gboolean status);
-#define YAHOO_SOCKET_READ  1
-#define YAHOO_SOCKET_WRITE 2
-void yahoo_socket_handler(struct yahoo_session *session, int socket, int type);
-
-extern void (*yahoo_print)(struct yahoo_session *session, int level, const char *log);
-#define YAHOO_LOG_DEBUG    4
-#define YAHOO_LOG_NOTICE   3
-#define YAHOO_LOG_WARNING  2
-#define YAHOO_LOG_ERROR    1
-#define YAHOO_LOG_CRITICAL 0
-
-extern int (*yahoo_connector)(struct yahoo_session *session, const char *host, int port, gpointer data);
-int yahoo_connected(struct yahoo_session *session, gpointer data, int fd);
-
-typedef int (*yahoo_callback)(struct yahoo_session *session, ...);
-void yahoo_add_handler(struct yahoo_session *session, int type, yahoo_callback function);
-#define YAHOO_HANDLE_DISCONNECT   0
-#define YAHOO_HANDLE_AUTHCONNECT  1
-#define YAHOO_HANDLE_BADPASSWORD  2
-#define YAHOO_HANDLE_LOGINCOOKIE  3
-#define YAHOO_HANDLE_MAINCONNECT  4
-#define YAHOO_HANDLE_ONLINE       5
-#define YAHOO_HANDLE_NEWMAIL      6
-#define YAHOO_HANDLE_MESSAGE      7
-#define YAHOO_HANDLE_BOUNCE       8
-#define YAHOO_HANDLE_STATUS       9
-#define YAHOO_HANDLE_ACTIVATE    10
-#define YAHOO_HANDLE_BUDDYADDED  11
-#define YAHOO_HANDLE_MAX         12
-
-struct callback {
-	yahoo_callback function;
-	void *data;
-};
-
-struct yahoo_group {
-	char *name;
-	char **buddies;
-};
-
-struct yahoo_session {
-	void *user_data;
-	struct callback callbacks[YAHOO_HANDLE_MAX];
-
-	int proxy_type;
-	char *proxy_host;
-	int proxy_port;
-
-	char *auth_host;
-	int auth_port;
-	char *pager_host;
-	int pager_port;
-
-	char *name;
-
-	char *cookie;
-	char *login_cookie;
-	GList *connlist;
-
-	GList *groups;
-	GList *ignored;
-
-	char **identities;
-	int mail;
-	char *login;
-};
-
-#endif
--- a/src/protocols/zephyr/zephyr.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/protocols/zephyr/zephyr.c	Tue Nov 06 23:58:24 2001 +0000
@@ -670,7 +670,7 @@
 }
 
 static void zephyr_add_buddy(struct gaim_connection *gc, char *buddy) { }
-static void zephyr_remove_buddy(struct gaim_connection *gc, char *buddy) { }
+static void zephyr_remove_buddy(struct gaim_connection *gc, char *buddy, char *group) { }
 
 static int zephyr_chat_send(struct gaim_connection *gc, int id, char *im)
 {
--- a/src/prpl.h	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/prpl.h	Tue Nov 06 23:58:24 2001 +0000
@@ -127,8 +127,8 @@
 	void (* change_passwd)	(struct gaim_connection *, char *old, char *new);
 	void (* add_buddy)	(struct gaim_connection *, char *name);
 	void (* add_buddies)	(struct gaim_connection *, GList *buddies);
-	void (* remove_buddy)	(struct gaim_connection *, char *name);
-	void (* remove_buddies)	(struct gaim_connection *, GList *buddies);
+	void (* remove_buddy)	(struct gaim_connection *, char *name, char *group);
+	void (* remove_buddies)	(struct gaim_connection *, GList *buddies, char *group);
 	void (* add_permit)	(struct gaim_connection *, char *name);
 	void (* add_deny)	(struct gaim_connection *, char *name);
 	void (* rem_permit)	(struct gaim_connection *, char *name);
--- a/src/server.c	Tue Nov 06 21:30:31 2001 +0000
+++ b/src/server.c	Tue Nov 06 23:58:24 2001 +0000
@@ -250,23 +250,23 @@
 }
 
 
-void serv_remove_buddy(struct gaim_connection *g, char *name)
+void serv_remove_buddy(struct gaim_connection *g, char *name, char *group)
 {
 	if (g && g_slist_find(connections, g) && g->prpl && g->prpl->remove_buddy)
-		g->prpl->remove_buddy(g, name);
+		g->prpl->remove_buddy(g, name, group);
 }
 
-void serv_remove_buddies(struct gaim_connection *gc, GList *g)
+void serv_remove_buddies(struct gaim_connection *gc, GList *g, char *group)
 {
 	if (!g_slist_find(connections, gc))
 		return;
 	if (!gc->prpl)
 		return;		/* how the hell did that happen? */
 	if (gc->prpl->remove_buddies)
-		gc->prpl->remove_buddies(gc, g);
+		gc->prpl->remove_buddies(gc, g, group);
 	else {
 		while (g) {
-			serv_remove_buddy(gc, g->data);
+			serv_remove_buddy(gc, g->data, group);
 			g = g->next;
 		}
 	}