Index: protocols/yahoo/libyahoo2.c
===================================================================
--- protocols/yahoo/libyahoo2.c	(revision c36f73bd317dd55d7e70275a6425faa4be7bfd8c)
+++ protocols/yahoo/libyahoo2.c	(revision 9034ba002b8945aee0f905b928bb0f60da9afe9f)
@@ -108,5 +108,7 @@
 #endif
 
-static int yahoo_send_data(int fd, void *data, int len);
+static int yahoo_send_data(void *fd, void *data, int len);
+static void _yahoo_http_connected(int id, void *fd, int error, void *data);
+static void yahoo_connected(void *fd, int error, void *data);
 
 int yahoo_log_message(char *fmt, ...)
@@ -140,7 +142,13 @@
 
 /* default values for servers */
-static char pager_host[] = "scs.msg.yahoo.com"; 
+static char *default_pager_hosts[] = {	"scs.msg.yahoo.com",
+					"scsa.msg.yahoo.com",
+					"scsb.msg.yahoo.com",
+					"scsc.msg.yahoo.com",
+					NULL};
+
 static int pager_port = 5050;
 static int fallback_ports[] = { 23, 25, 80, 20, 119, 8001, 8002, 5050, 0 };
+
 static char filetransfer_host[] = "filetransfer.msg.yahoo.com";
 static int filetransfer_port = 80;
@@ -153,82 +161,9 @@
 static char profile_url[] = "http://profiles.yahoo.com/";
 
-enum yahoo_service { /* these are easier to see in hex */
-	YAHOO_SERVICE_LOGON = 1,
-	YAHOO_SERVICE_LOGOFF,
-	YAHOO_SERVICE_ISAWAY,
-	YAHOO_SERVICE_ISBACK,
-	YAHOO_SERVICE_IDLE, /* 5 (placemarker) */
-	YAHOO_SERVICE_MESSAGE,
-	YAHOO_SERVICE_IDACT,
-	YAHOO_SERVICE_IDDEACT,
-	YAHOO_SERVICE_MAILSTAT,
-	YAHOO_SERVICE_USERSTAT, /* 0xa */
-	YAHOO_SERVICE_NEWMAIL,
-	YAHOO_SERVICE_CHATINVITE,
-	YAHOO_SERVICE_CALENDAR,
-	YAHOO_SERVICE_NEWPERSONALMAIL,
-	YAHOO_SERVICE_NEWCONTACT,
-	YAHOO_SERVICE_ADDIDENT, /* 0x10 */
-	YAHOO_SERVICE_ADDIGNORE,
-	YAHOO_SERVICE_PING,
-	YAHOO_SERVICE_GOTGROUPRENAME, /* < 1, 36(old), 37(new) */
-	YAHOO_SERVICE_SYSMESSAGE = 0x14,
-	YAHOO_SERVICE_SKINNAME = 0x15,
-	YAHOO_SERVICE_PASSTHROUGH2 = 0x16,
-	YAHOO_SERVICE_CONFINVITE = 0x18,
-	YAHOO_SERVICE_CONFLOGON,
-	YAHOO_SERVICE_CONFDECLINE,
-	YAHOO_SERVICE_CONFLOGOFF,
-	YAHOO_SERVICE_CONFADDINVITE,
-	YAHOO_SERVICE_CONFMSG,
-	YAHOO_SERVICE_CHATLOGON,
-	YAHOO_SERVICE_CHATLOGOFF,
-	YAHOO_SERVICE_CHATMSG = 0x20,
-	YAHOO_SERVICE_GAMELOGON = 0x28,
-	YAHOO_SERVICE_GAMELOGOFF,
-	YAHOO_SERVICE_GAMEMSG = 0x2a,
-	YAHOO_SERVICE_FILETRANSFER = 0x46,
-	YAHOO_SERVICE_VOICECHAT = 0x4A,
-	YAHOO_SERVICE_NOTIFY,
-	YAHOO_SERVICE_VERIFY,
-	YAHOO_SERVICE_P2PFILEXFER,
-	YAHOO_SERVICE_PEERTOPEER = 0x4F,	/* Checks if P2P possible */
-	YAHOO_SERVICE_WEBCAM,
-	YAHOO_SERVICE_AUTHRESP = 0x54,
-	YAHOO_SERVICE_LIST,
-	YAHOO_SERVICE_AUTH = 0x57,
-	YAHOO_SERVICE_AUTHBUDDY = 0x6d,
-	YAHOO_SERVICE_ADDBUDDY = 0x83,
-	YAHOO_SERVICE_REMBUDDY,
-	YAHOO_SERVICE_IGNORECONTACT,	/* > 1, 7, 13 < 1, 66, 13, 0*/
-	YAHOO_SERVICE_REJECTCONTACT,
-	YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */
-	YAHOO_SERVICE_Y7_PING = 0x8A, /* 0 - id and that's it?? */
-	YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/
-	YAHOO_SERVICE_CHATGOTO,
-	YAHOO_SERVICE_CHATJOIN,	/* > 1 104-room 129-1600326591 62-2 */
-	YAHOO_SERVICE_CHATLEAVE,
-	YAHOO_SERVICE_CHATEXIT = 0x9b,
-	YAHOO_SERVICE_CHATADDINVITE = 0x9d,
-	YAHOO_SERVICE_CHATLOGOUT = 0xa0,
-	YAHOO_SERVICE_CHATPING,
-	YAHOO_SERVICE_COMMENT = 0xa8,
-	YAHOO_SERVICE_STEALTH = 0xb9,
-	YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd,
-	YAHOO_SERVICE_PICTURE = 0xbe,
-	YAHOO_SERVICE_PICTURE_UPDATE = 0xc1,
-	YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2,
-	YAHOO_SERVICE_Y6_VISIBILITY = 0xc5,
-	YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6,
-	YAHOO_PHOTOSHARE_INIT = 0xd2,	
-	YAHOO_SERVICE_CONTACT_YMSG13 = 0xd6,
-	YAHOO_PHOTOSHARE_PREV = 0xd7,
-	YAHOO_PHOTOSHARE_KEY = 0xd8,
-	YAHOO_PHOTOSHARE_TRANS = 0xda,
-	YAHOO_FILE_TRANSFER_INIT_YMSG13 = 0xdc,
-	YAHOO_FILE_TRANSFER_GET_YMSG13 = 0xdd,
-	YAHOO_FILE_TRANSFER_PUT_YMSG13 = 0xde,
-	YAHOO_SERVICE_YMSG15_STATUS = 0xf0,
-	YAHOO_SERVICE_YMSG15_BUDDY_LIST = 0xf1,
+struct connect_callback_data {
+	struct yahoo_data *yd;
+	int tag;
+	int i;
+	int server_i;
 };
 
@@ -268,7 +203,7 @@
 	struct yahoo_search_state *ys;
 
-	int fd;
+	void *fd;
 	enum yahoo_connection_type type;
-	
+
 	unsigned char *rxqueue;
 	int rxlen;
@@ -289,11 +224,29 @@
 	char *local_host;
 	int conn_type;
+	char **pager_host_list;
 };
 
+static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over);
+
+static void yahoo_process_filetransfer(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt);
+static void yahoo_process_filetransferinfo(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt);
+static void yahoo_process_filetransferaccept(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt);
+
+static void yahoo_https_auth(struct yahoo_input_data *yid, const char *seed, const char *sn);
+
 static void *_yahoo_default_server_settings()
 {
-	struct yahoo_server_settings *yss = y_new0(struct yahoo_server_settings, 1);
-
-	yss->pager_host = strdup(pager_host);
+	struct yahoo_server_settings *yss =
+		y_new0(struct yahoo_server_settings, 1);
+
+	/* Give preference to the default host list
+	 * Make sure that only one of the two is set at any time 
+	 */
+	yss->pager_host = NULL;
+	yss->pager_host_list = default_pager_hosts;
+
 	yss->pager_port = pager_port;
 	yss->filetransfer_host = strdup(filetransfer_host);
@@ -314,4 +267,5 @@
 	char *svalue;
 	int nvalue;
+	char **pvalue;
 
 	while (1) {
@@ -324,4 +278,10 @@
 			free(yss->pager_host);
 			yss->pager_host = strdup(svalue);
+			yss->pager_host_list = NULL;
+		} else if (!strcmp(key, "pager_host_list")) {
+			pvalue = va_arg(ap, char **);
+			yss->pager_host_list = pvalue;
+			free(yss->pager_host);
+			yss->pager_host = NULL;
 		} else if (!strcmp(key, "pager_port")) {
 			nvalue = va_arg(ap, int);
@@ -384,4 +344,5 @@
 	conns = y_list_prepend(conns, yd);
 }
+
 static struct yahoo_data *find_conn_by_id(int id)
 {
@@ -394,4 +355,5 @@
 	return NULL;
 }
+
 static void del_from_list(struct yahoo_data *yd)
 {
@@ -400,5 +362,6 @@
 
 /* call repeatedly to get the next one */
-static struct yahoo_input_data *find_input_by_id(int id)
+/*
+static struct yahoo_input_data * find_input_by_id(int id)
 {
 	YList *l;
@@ -410,6 +373,8 @@
 	return NULL;
 }
-
-static struct yahoo_input_data *find_input_by_id_and_webcam_user(int id, const char *who)
+*/
+
+static struct yahoo_input_data *find_input_by_id_and_webcam_user(int id,
+	const char *who)
 {
 	YList *l;
@@ -417,8 +382,9 @@
 	for (l = inputs; l; l = y_list_next(l)) {
 		struct yahoo_input_data *yid = l->data;
-		if (yid->type == YAHOO_CONNECTION_WEBCAM && yid->yd->client_id == id 
-				&& yid->wcm && 
-				((who && yid->wcm->user && !strcmp(who, yid->wcm->user)) ||
-				 !(yid->wcm->user && !who)))
+		if (yid->type == YAHOO_CONNECTION_WEBCAM
+			&& yid->yd->client_id == id && yid->wcm && ((who
+					&& yid->wcm->user
+					&& !strcmp(who, yid->wcm->user))
+				|| !(yid->wcm->user && !who)))
 			return yid;
 	}
@@ -426,5 +392,6 @@
 }
 
-static struct yahoo_input_data *find_input_by_id_and_type(int id, enum yahoo_connection_type type)
+static struct yahoo_input_data *find_input_by_id_and_type(int id,
+	enum yahoo_connection_type type)
 {
 	YList *l;
@@ -438,5 +405,5 @@
 }
 
-static struct yahoo_input_data *find_input_by_id_and_fd(int id, int fd)
+static struct yahoo_input_data *find_input_by_id_and_fd(int id, void *fd)
 {
 	YList *l;
@@ -463,5 +430,4 @@
 	return c;
 }
-
 
 extern char *yahoo_crypt(char *, char *);
@@ -528,4 +494,5 @@
 	FREE(yd->cookie_y);
 	FREE(yd->cookie_t);
+	FREE(yd->cookie_b);
 	FREE(yd->cookie_c);
 	FREE(yd->login_cookie);
@@ -543,6 +510,6 @@
 #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)
+static struct yahoo_packet *yahoo_packet_new(enum yahoo_service service,
+	enum ypacket_status status, int id)
 {
 	struct yahoo_packet *pkt = y_new0(struct yahoo_packet, 1);
@@ -555,5 +522,6 @@
 }
 
-static void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value)
+static void yahoo_packet_hash(struct yahoo_packet *pkt, int key,
+	const char *value)
 {
 	struct yahoo_pair *pair = y_new0(struct yahoo_pair, 1);
@@ -600,5 +568,6 @@
 			 (((*((buf)+3))&0xff)))
 
-static void yahoo_packet_read(struct yahoo_packet *pkt, unsigned char *data, int len)
+static void yahoo_packet_read(struct yahoo_packet *pkt, unsigned char *data,
+	int len)
 {
 	int pos = 0;
@@ -653,5 +622,6 @@
 			FREE(value);
 			pkt->hash = y_list_append(pkt->hash, pair);
-			DEBUG_MSG(("Key: %d  \tValue: %s", pair->key, pair->value));
+			DEBUG_MSG(("Key: %d  \tValue: %s", pair->key,
+					pair->value));
 		} else {
 			FREE(pair);
@@ -788,10 +758,10 @@
 }
 
-static int yahoo_send_data(int fd, void *data, int len)
+static int yahoo_send_data(void *fd, void *data, int len)
 {
 	int ret;
 	int e;
 
-	if (fd < 0)
+	if (fd == NULL)
 		return -1;
 
@@ -799,5 +769,5 @@
 
 	do {
-		ret = write(fd, data, len);
+		ret = YAHOO_CALLBACK(ext_yahoo_write) (fd, data, len);
 	} while (ret == -1 && errno == EINTR);
 	e = errno;
@@ -838,5 +808,5 @@
 	yid->read_tag = yid->write_tag = 0;
 	if (yid->fd)
-		close(yid->fd);
+		YAHOO_CALLBACK(ext_yahoo_close) (yid->fd);
 	yid->fd = 0;
 	FREE(yid->rxqueue);
@@ -942,5 +912,5 @@
 	else if (!strncasecmp(msg, "GAME", strlen("GAME")))
 		YAHOO_CALLBACK(ext_yahoo_game_notify) (yd->client_id, to, from,
-			stat);
+			stat, ind);
 	else if (!strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) {
 		if (!strcmp(ind, " ")) {
@@ -959,61 +929,6 @@
 }
 
-static void yahoo_process_filetransfer(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
-{
-	struct yahoo_data *yd = yid->yd;
-	char *from = NULL;
-	char *to = NULL;
-	char *msg = NULL;
-	char *url = NULL;
-	long expires = 0;
-
-	char *service = NULL;
-
-	char *filename = NULL;
-	unsigned long filesize = 0L;
-
-	YList *l;
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-		if (pair->key == 4)
-			from = pair->value;
-		if (pair->key == 5)
-			to = pair->value;
-		if (pair->key == 14)
-			msg = pair->value;
-		if (pair->key == 20)
-			url = pair->value;
-		if (pair->key == 38)
-			expires = atol(pair->value);
-
-		if (pair->key == 27)
-			filename = pair->value;
-		if (pair->key == 28)
-			filesize = atol(pair->value);
-
-		if (pair->key == 49)
-			service = pair->value;
-	}
-
-	if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) {
-		if (strcmp("FILEXFER", service) != 0) {
-			WARNING(("unhandled service 0x%02x", pkt->service));
-			yahoo_dump_unhandled(pkt);
-			return;
-		}
-	}
-
-	if (msg) {
-		char *tmp;
-		tmp = strchr(msg, '\006');
-		if (tmp)
-			*tmp = '\0';
-	}
-	if (url && from)
-		YAHOO_CALLBACK(ext_yahoo_got_file) (yd->client_id, to, from, url, expires, msg, filename, filesize);
-
-}
-
-static void yahoo_process_conference(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
+static void yahoo_process_conference(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
 {
 	struct yahoo_data *yd = yid->yd;
@@ -1090,8 +1005,7 @@
 		break;
 	case YAHOO_SERVICE_CONFADDINVITE:
-		if (pkt->status == 2)
-			;
-		else
-			YAHOO_CALLBACK(ext_yahoo_got_conf_invite) (yd->client_id, id, host, room, msg, members);
+		if (pkt->status == 1)
+			YAHOO_CALLBACK(ext_yahoo_got_conf_invite) (yd->
+				client_id, id, host, room, msg, members);
 		break;
 	case YAHOO_SERVICE_CONFDECLINE:
@@ -1134,5 +1048,5 @@
 	int chaterr = 0;
 	YList *l;
-	
+
 	yahoo_dump_unhandled(pkt);
 	for (l = pkt->hash; l; l = l->next) {
@@ -1285,4 +1199,5 @@
 		char *msg;
 		int utf8;
+		char *gunk;
 	} *message = y_new0(struct m, 1);
 
@@ -1298,5 +1213,8 @@
 		else if (pair->key == 97)
 			message->utf8 = atoi(pair->value);
-			/* user message */  /* sys message */
+		/* This comes when the official client sends us a message */
+		else if (pair->key == 429)
+			message->gunk = pair->value;
+		/* user message *//* sys message */
 		else if (pair->key == 14 || pair->key == 16)
 			message->msg = pair->value;
@@ -1318,11 +1236,36 @@
 		message = l->data;
 		if (pkt->service == YAHOO_SERVICE_SYSMESSAGE) {
-			YAHOO_CALLBACK(ext_yahoo_system_message) (yd->client_id, message->msg);
+			YAHOO_CALLBACK(ext_yahoo_system_message) (yd->client_id,
+				message->to, message->from, message->msg);
 		} else if (pkt->status <= 2 || pkt->status == 5) {
-			YAHOO_CALLBACK(ext_yahoo_got_im) (yd->client_id, message->to, message->from, message->msg, message->tm, pkt->status, message->utf8);
+			/* Confirm message receipt if we got the gunk */
+			if(message->gunk) {
+				struct yahoo_packet *outpkt;
+                        
+				outpkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE_CONFIRM,
+					YPACKET_STATUS_DEFAULT, 0);
+				yahoo_packet_hash(outpkt, 1, yd->user);
+				yahoo_packet_hash(outpkt, 5, message->from);
+				yahoo_packet_hash(outpkt, 302, "430");
+				yahoo_packet_hash(outpkt, 430, message->gunk);
+				yahoo_packet_hash(outpkt, 303, "430");
+				yahoo_packet_hash(outpkt, 450, "0");
+				yahoo_send_packet(yid, outpkt, 0);
+                        
+				yahoo_packet_free(outpkt);
+			}
+
+			if (!strcmp(message->msg, "<ding>"))
+				YAHOO_CALLBACK(ext_yahoo_got_buzz) (yd->client_id,
+					message->to, message->from, message->tm);
+			else
+				YAHOO_CALLBACK(ext_yahoo_got_im) (yd->client_id,
+					message->to, message->from, message->msg,
+					message->tm, pkt->status, message->utf8);
 		} else if (pkt->status == 0xffffffff) {
-			YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id, message->msg, 0, E_SYSTEM);
-		}
-		free(message);
+			YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id,
+				message->msg, 0, E_SYSTEM);
+		}
+		FREE(message);
 	}
 
@@ -1330,4 +1273,27 @@
 }
 
+/*
+ * Here's what multi-level packets look like. Data in brackets is the value.
+ *
+ * 3 level:
+ * =======
+ * 
+ * 302 (318) - Beginning level 1
+ * 	300 (318) - Begin level 2
+ * 	302 (319) - End level 2 header
+ * 		300 (319) - Begin level 3
+ * 		301 (319) - End level 3
+ * 	303 (319) - End level 2
+ * 303 (318) - End level 1
+ *
+ * 2 level:
+ * =======
+ *
+ * 302 (315) - Beginning level 1
+ * 	300 (315) - Begin level 2
+ * 	301 (315) - End level 2
+ * 303 (315) - End level 1
+ *
+ */
 static void yahoo_process_status(struct yahoo_input_data *yid,
 	struct yahoo_packet *pkt)
@@ -1721,22 +1687,20 @@
 	char *url = NULL;
 
-	if ( pkt->status != 1 )
+	if (pkt->status != 1)
 		return;		/* something went wrong */
-	
-	for (l = pkt->hash; l; l = l->next)
-	{
+
+	for (l = pkt->hash; l; l = l->next) {
 		struct yahoo_pair *pair = l->data;
 
-		switch(pair->key)
-		{
-			case 5:		/* we */
-				break;
-			case 20:		/* url */
-				url = pair->value;
-				break;
-			case 27:		/* local filename */
-				break;
-			case 38:		/* time */
-				break;
+		switch (pair->key) {
+		case 5:	/* we */
+			break;
+		case 20:	/* url */
+			url = pair->value;
+			break;
+		case 27:	/* local filename */
+			break;
+		case 38:	/* time */
+			break;
 		}
 	}
@@ -1745,538 +1709,41 @@
 }
 
-static void yahoo_process_auth_pre_0x0b(struct yahoo_input_data *yid, 
-		const char *seed, const char *sn)
-{
-	struct yahoo_data *yd = yid->yd;
-	
-	/* So, Yahoo has stopped supporting its older clients in India, and 
-	 * undoubtedly will soon do so in the rest of the world.
-	 * 
-	 * The new clients use this authentication method.  I warn you in 
-	 * advance, it's bizzare, convoluted, inordinately complicated.  
-	 * It's also no more secure than crypt() was.  The only purpose this 
-	 * scheme could serve is to prevent third part clients from connecting 
-	 * to their servers.
-	 *
-	 * Sorry, Yahoo.
+void yahoo_login(int id, int initial)
+{
+	struct yahoo_data *yd = find_conn_by_id(id);
+	struct connect_callback_data *ccd;
+	struct yahoo_server_settings *yss;
+	int tag;
+
+	char *host;
+
+	struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1);
+	yid->yd = yd;
+	yid->type = YAHOO_CONNECTION_PAGER;
+	inputs = y_list_prepend(inputs, yid);
+
+	yd->initial_status = initial;
+	yss = yd->server_settings;
+
+	ccd = y_new0(struct connect_callback_data, 1);
+	ccd->yd = yd;
+
+	host = yss->pager_host;
+
+	if (!host)
+		host = yss->pager_host_list[0];
+
+	tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd->client_id,
+		host, yss->pager_port, yahoo_connected, ccd, 0);
+
+	/*
+	 * if tag <= 0, then callback has already been called
+	 * so ccd will have been freed
 	 */
-
-	struct yahoo_packet *pack;
-	
-	md5_byte_t result[16];
-	md5_state_t ctx;
-	char *crypt_result;
-	unsigned char *password_hash = malloc(25);
-	unsigned char *crypt_hash = malloc(25);
-	unsigned char *hash_string_p = malloc(50 + strlen(sn));
-	unsigned char *hash_string_c = malloc(50 + strlen(sn));
-	
-	char checksum;
-	
-	int sv;
-	
-	unsigned char *result6 = malloc(25);
-	unsigned char *result96 = malloc(25);
-
-	sv = seed[15];
-	sv = (sv % 8) % 5;
-
-	md5_init(&ctx);
-	md5_append(&ctx, (md5_byte_t *)yd->password, strlen(yd->password));
-	md5_finish(&ctx, result);
-	to_y64(password_hash, result, 16);
-	
-	md5_init(&ctx);
-	crypt_result = yahoo_crypt(yd->password, "$1$_2S43d5f$");  
-	md5_append(&ctx, (md5_byte_t *)crypt_result, strlen(crypt_result));
-	md5_finish(&ctx, result);
-	to_y64(crypt_hash, result, 16);
-	free(crypt_result);
-
-	switch (sv) {
-	case 0:
-		checksum = seed[seed[7] % 16];
-		snprintf((char *)hash_string_p, strlen(sn) + 50,
-			"%c%s%s%s", checksum, password_hash, yd->user, seed);
-		snprintf((char *)hash_string_c, strlen(sn) + 50,
-			"%c%s%s%s", checksum, crypt_hash, yd->user, seed);
-		break;
-	case 1:
-		checksum = seed[seed[9] % 16];
-		snprintf((char *)hash_string_p, strlen(sn) + 50,
-			"%c%s%s%s", checksum, yd->user, seed, password_hash);
-		snprintf((char *)hash_string_c, strlen(sn) + 50,
-			"%c%s%s%s", checksum, yd->user, seed, crypt_hash);
-		break;
-	case 2:
-		checksum = seed[seed[15] % 16];
-		snprintf((char *)hash_string_p, strlen(sn) + 50,
-			"%c%s%s%s", checksum, seed, password_hash, yd->user);
-		snprintf((char *)hash_string_c, strlen(sn) + 50,
-			"%c%s%s%s", checksum, seed, crypt_hash, yd->user);
-		break;
-	case 3:
-		checksum = seed[seed[1] % 16];
-		snprintf((char *)hash_string_p, strlen(sn) + 50,
-			"%c%s%s%s", checksum, yd->user, password_hash, seed);
-		snprintf((char *)hash_string_c, strlen(sn) + 50,
-			"%c%s%s%s", checksum, yd->user, crypt_hash, seed);
-		break;
-	case 4:
-		checksum = seed[seed[3] % 16];
-		snprintf((char *)hash_string_p, strlen(sn) + 50,
-			"%c%s%s%s", checksum, password_hash, seed, yd->user);
-		snprintf((char *)hash_string_c, strlen(sn) + 50,
-			"%c%s%s%s", checksum, crypt_hash, seed, yd->user);
-		break;
-	}
-		
-	md5_init(&ctx);  
-	md5_append(&ctx, (md5_byte_t *)hash_string_p, strlen((char *)hash_string_p));
-	md5_finish(&ctx, result);
-	to_y64(result6, result, 16);
-
-	md5_init(&ctx);  
-	md5_append(&ctx, (md5_byte_t *)hash_string_c, strlen((char *)hash_string_c));
-	md5_finish(&ctx, result);
-	to_y64(result96, result, 16);
-
-	pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->initial_status, yd->session_id);
-	yahoo_packet_hash(pack, 0, yd->user);
-	yahoo_packet_hash(pack, 6, (char *)result6);
-	yahoo_packet_hash(pack, 96, (char *)result96);
-	yahoo_packet_hash(pack, 1, yd->user);
-		
-	yahoo_send_packet(yid, pack, 0);
-		
-	FREE(result6);
-	FREE(result96);
-	FREE(password_hash);
-	FREE(crypt_hash);
-	FREE(hash_string_p);
-	FREE(hash_string_c);
-
-	yahoo_packet_free(pack);
-
-}
-
-/*
- * New auth protocol cracked by Cerulean Studios and sent in to Gaim
- */
-static void yahoo_process_auth_0x0b(struct yahoo_input_data *yid, const char *seed, const char *sn)
-{
-	struct yahoo_packet *pack = NULL;
-	struct yahoo_data *yd = yid->yd;
-
-	md5_byte_t         result[16];
-	md5_state_t        ctx;
-
-	sha1_state_t       ctx1;
-	sha1_state_t       ctx2;
-
-	char *alphabet1 = "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ";
-	char *alphabet2 = "F0E1D2C3B4A59687abcdefghijklmnop";
-
-	char *challenge_lookup = "qzec2tb3um1olpar8whx4dfgijknsvy5";
-	char *operand_lookup = "+|&%/*^-";
-	char *delimit_lookup = ",;";
-
-	unsigned char *password_hash = malloc(25);
-	unsigned char *crypt_hash = malloc(25);
-	char *crypt_result = NULL;
-	unsigned char pass_hash_xor1[64];
-	unsigned char pass_hash_xor2[64];
-	unsigned char crypt_hash_xor1[64];
-	unsigned char crypt_hash_xor2[64];
-	unsigned char chal[7];
-	char resp_6[100];
-	char resp_96[100];
-
-	unsigned char digest1[20];
-	unsigned char digest2[20];
-	unsigned char magic_key_char[4];
-	const unsigned char *magic_ptr;
-
-	unsigned int magic[64];
-	unsigned int magic_work = 0;
-
-	char comparison_src[20];
-
-	int x, j, i;
-	int cnt = 0;
-	int magic_cnt = 0;
-	int magic_len;
-	int depth =0, table =0;
-
-	memset(&pass_hash_xor1, 0, 64);
-	memset(&pass_hash_xor2, 0, 64);
-	memset(&crypt_hash_xor1, 0, 64);
-	memset(&crypt_hash_xor2, 0, 64);
-	memset(&digest1, 0, 20);
-	memset(&digest2, 0, 20);
-	memset(&magic, 0, 64);
-	memset(&resp_6, 0, 100);
-	memset(&resp_96, 0, 100);
-	memset(&magic_key_char, 0, 4);
-
-	/* 
-	 * Magic: Phase 1.  Generate what seems to be a 30 
-	 * byte value (could change if base64
-	 * ends up differently?  I don't remember and I'm 
-	 * tired, so use a 64 byte buffer.
-	 */
-
-	magic_ptr = (unsigned char *)seed;
-
-	while (*magic_ptr != 0) {
-		char *loc;
-
-		/* Ignore parentheses.  */
-
-		if (*magic_ptr == '(' || *magic_ptr == ')') {
-			magic_ptr++;
-			continue;
-		}
-
-		/* Characters and digits verify against 
-		   the challenge lookup.
-		*/
-
-		if (isalpha(*magic_ptr) || isdigit(*magic_ptr)) {
-			loc = strchr(challenge_lookup, *magic_ptr);
-			if (!loc) {
-				/* This isn't good */
-				continue;
-			}
-
-			/* Get offset into lookup table and lsh 3. */
-
-			magic_work = loc - challenge_lookup;
-			magic_work <<= 3;
-
-			magic_ptr++;
-			continue;
-		} else {
-			unsigned int local_store;
-
-			loc = strchr(operand_lookup, *magic_ptr);
-			if (!loc) {
-				/* Also not good. */
-				continue;
-			}
-
-			local_store = loc - operand_lookup;
-
-			/* Oops; how did this happen? */
-			if (magic_cnt >= 64) 
-				break;
-
-			magic[magic_cnt++] = magic_work | local_store;
-			magic_ptr++;
-			continue;
-		}
-	}
-
-	magic_len = magic_cnt;
-	magic_cnt = 0;
-
-	/* Magic: Phase 2.  Take generated magic value and 
-	 * sprinkle fairy dust on the values. */
-
-	for (magic_cnt = magic_len-2; magic_cnt >= 0; magic_cnt--) {
-		unsigned char byte1;
-		unsigned char byte2;
-
-		/* Bad.  Abort.
-		 */
-		if (magic_cnt >= magic_len) {
-			WARNING(("magic_cnt(%d)  magic_len(%d)", magic_cnt, magic_len))
-			break;
-		}
-
-		byte1 = magic[magic_cnt];
-		byte2 = magic[magic_cnt+1];
-
-		byte1 *= 0xcd;
-		byte1 ^= byte2;
-
-		magic[magic_cnt+1] = byte1;
-	}
-
-	/* Magic: Phase 3.  This computes 20 bytes.  The first 4 bytes are used as our magic 
-	 * key (and may be changed later); the next 16 bytes are an MD5 sum of the magic key 
-	 * plus 3 bytes.  The 3 bytes are found by looping, and they represent the offsets 
-	 * into particular functions we'll later call to potentially alter the magic key. 
-	 * 
-	 * %-) 
-	 */ 
-	
-	magic_cnt = 1; 
-	x = 0; 
-	
-	do { 
-		unsigned int bl = 0;  
-		unsigned int cl = magic[magic_cnt++]; 
-		
-		if (magic_cnt >= magic_len) 
-			break; 
-		
-		if (cl > 0x7F) { 
-			if (cl < 0xe0)  
-				bl = cl = (cl & 0x1f) << 6;  
-			else { 
-				bl = magic[magic_cnt++];  
-                              cl = (cl & 0x0f) << 6;  
-                              bl = ((bl & 0x3f) + cl) << 6;  
-			}  
-			
-			cl = magic[magic_cnt++];  
-			bl = (cl & 0x3f) + bl;  
-		} else 
-			bl = cl;  
-		
-		comparison_src[x++] = (bl & 0xff00) >> 8;  
-		comparison_src[x++] = bl & 0xff;  
-	} while (x < 20); 
-
-	/* Dump magic key into a char for SHA1 action. */
-	
-		
-	for (x = 0; x < 4; x++) 
-		magic_key_char[x] = comparison_src[x];
-
-	/* Compute values for recursive function table! */
-	memcpy( chal, magic_key_char, 4 );
-        x = 1;
-	for ( i = 0; i < 0xFFFF && x; i++ )
-	{
-		for ( j = 0; j < 5 && x; j++ )
-		{
-			chal[4] = i;
-			chal[5] = i >> 8;
-			chal[6] = j;
-			md5_init( &ctx );
-			md5_append( &ctx, chal, 7 );
-			md5_finish( &ctx, result );
-			if ( memcmp( comparison_src + 4, result, 16 ) == 0 )
-			{
-				depth = i;
-				table = j;
-				x = 0;
-			}
-		}
-	}
-
-	/* Transform magic_key_char using transform table */
-	x = magic_key_char[3] << 24  | magic_key_char[2] << 16 
-		| magic_key_char[1] << 8 | magic_key_char[0];
-	x = yahoo_xfrm( table, depth, x );
-	x = yahoo_xfrm( table, depth, x );
-	magic_key_char[0] = x & 0xFF;
-	magic_key_char[1] = x >> 8 & 0xFF;
-	magic_key_char[2] = x >> 16 & 0xFF;
-	magic_key_char[3] = x >> 24 & 0xFF;
-
-	/* Get password and crypt hashes as per usual. */
-	md5_init(&ctx);
-	md5_append(&ctx, (md5_byte_t *)yd->password,  strlen(yd->password));
-	md5_finish(&ctx, result);
-	to_y64(password_hash, result, 16);
-
-	md5_init(&ctx);
-	crypt_result = yahoo_crypt(yd->password, "$1$_2S43d5f$");  
-	md5_append(&ctx, (md5_byte_t *)crypt_result, strlen(crypt_result));
-	md5_finish(&ctx, result);
-	to_y64(crypt_hash, result, 16);
-	free(crypt_result);
-
-	/* Our first authentication response is based off 
-	 * of the password hash. */
-
-	for (x = 0; x < (int)strlen((char *)password_hash); x++) 
-		pass_hash_xor1[cnt++] = password_hash[x] ^ 0x36;
-
-	if (cnt < 64) 
-		memset(&(pass_hash_xor1[cnt]), 0x36, 64-cnt);
-
-	cnt = 0;
-
-	for (x = 0; x < (int)strlen((char *)password_hash); x++) 
-		pass_hash_xor2[cnt++] = password_hash[x] ^ 0x5c;
-
-	if (cnt < 64) 
-		memset(&(pass_hash_xor2[cnt]), 0x5c, 64-cnt);
-
-	sha1_init(&ctx1);
-	sha1_init(&ctx2);
-
-	/* The first context gets the password hash XORed 
-	 * with 0x36 plus a magic value
-	 * which we previously extrapolated from our 
-	 * challenge. */
-
-	sha1_append(&ctx1, pass_hash_xor1, 64);
-	if (j >= 3 )
-		ctx1.Length_Low = 0x1ff;
-	sha1_append(&ctx1, magic_key_char, 4);
-	sha1_finish(&ctx1, digest1);
-
-	 /* The second context gets the password hash XORed 
-	  * with 0x5c plus the SHA-1 digest
-	  * of the first context. */
-
-	sha1_append(&ctx2, pass_hash_xor2, 64);
-	sha1_append(&ctx2, digest1, 20);
-	sha1_finish(&ctx2, digest2);
-
-	/* Now that we have digest2, use it to fetch 
-	 * characters from an alphabet to construct
-	 * our first authentication response. */
-
-	for (x = 0; x < 20; x += 2) {
-		unsigned int val = 0;
-		unsigned int lookup = 0;
-		char byte[6];
-
-		memset(&byte, 0, 6);
-
-		/* First two bytes of digest stuffed 
-		 *  together.
-		 */
-
-		val = digest2[x];
-		val <<= 8;
-		val += digest2[x+1];
-
-		lookup = (val >> 0x0b);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet1))
-			break;
-		sprintf(byte, "%c", alphabet1[lookup]);
-		strcat(resp_6, byte);
-		strcat(resp_6, "=");
-
-		lookup = (val >> 0x06);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet2))
-			break;
-		sprintf(byte, "%c", alphabet2[lookup]);
-		strcat(resp_6, byte);
-
-		lookup = (val >> 0x01);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet2))
-			break;
-		sprintf(byte, "%c", alphabet2[lookup]);
-		strcat(resp_6, byte);
-
-		lookup = (val & 0x01);
-		if (lookup >= strlen(delimit_lookup))
-			break;
-		sprintf(byte, "%c", delimit_lookup[lookup]);
-		strcat(resp_6, byte);
-	}
-
-	/* Our second authentication response is based off 
-	 * of the crypto hash. */
-
-	cnt = 0;
-	memset(&digest1, 0, 20);
-	memset(&digest2, 0, 20);
-
-	for (x = 0; x < (int)strlen((char *)crypt_hash); x++) 
-		crypt_hash_xor1[cnt++] = crypt_hash[x] ^ 0x36;
-
-	if (cnt < 64) 
-		memset(&(crypt_hash_xor1[cnt]), 0x36, 64-cnt);
-
-	cnt = 0;
-
-	for (x = 0; x < (int)strlen((char *)crypt_hash); x++) 
-		crypt_hash_xor2[cnt++] = crypt_hash[x] ^ 0x5c;
-
-	if (cnt < 64) 
-		memset(&(crypt_hash_xor2[cnt]), 0x5c, 64-cnt);
-
-	sha1_init(&ctx1);
-	sha1_init(&ctx2);
-
-	/* The first context gets the password hash XORed 
-	 * with 0x36 plus a magic value
-	 * which we previously extrapolated from our 
-	 * challenge. */
-
-	sha1_append(&ctx1, crypt_hash_xor1, 64);
-	if (j >= 3 )
-		ctx1.Length_Low = 0x1ff;
-	sha1_append(&ctx1, magic_key_char, 4);
-	sha1_finish(&ctx1, digest1);
-
-	/* The second context gets the password hash XORed 
-	 * with 0x5c plus the SHA-1 digest
-	 * of the first context. */
-
-	sha1_append(&ctx2, crypt_hash_xor2, 64);
-	sha1_append(&ctx2, digest1, 20);
-	sha1_finish(&ctx2, digest2);
-
-	/* Now that we have digest2, use it to fetch 
-	 * characters from an alphabet to construct
-	 * our first authentication response.  */
-
-	for (x = 0; x < 20; x += 2) {
-		unsigned int val = 0;
-		unsigned int lookup = 0;
-
-		char byte[6];
-
-		memset(&byte, 0, 6);
-
-		/* First two bytes of digest stuffed 
-		 *  together. */
-
-		val = digest2[x];
-		val <<= 8;
-		val += digest2[x+1];
-
-		lookup = (val >> 0x0b);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet1))
-			break;
-		sprintf(byte, "%c", alphabet1[lookup]);
-		strcat(resp_96, byte);
-		strcat(resp_96, "=");
-
-		lookup = (val >> 0x06);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet2))
-			break;
-		sprintf(byte, "%c", alphabet2[lookup]);
-		strcat(resp_96, byte);
-
-		lookup = (val >> 0x01);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet2))
-			break;
-		sprintf(byte, "%c", alphabet2[lookup]);
-		strcat(resp_96, byte);
-
-		lookup = (val & 0x01);
-		if (lookup >= strlen(delimit_lookup))
-			break;
-		sprintf(byte, "%c", delimit_lookup[lookup]);
-		strcat(resp_96, byte);
-	}
-
-	pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->initial_status, yd->session_id);
-	yahoo_packet_hash(pack, 0, sn);
-	yahoo_packet_hash(pack, 6, resp_6);
-	yahoo_packet_hash(pack, 96, resp_96);
-	yahoo_packet_hash(pack, 1, sn);
-	yahoo_send_packet(yid, pack, 0);
-	yahoo_packet_free(pack);
-
-	free(password_hash);
-	free(crypt_hash);
+	if (tag > 0)
+		ccd->tag = tag;
+	else if (tag < 0)
+		YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id,
+			YAHOO_LOGIN_SOCK, NULL);
 }
 
@@ -2328,5 +1795,5 @@
 }
 
-static void yahoo_process_auth_0x10(struct yahoo_input_data *yid, const char *seed, const char *sn)
+static void yahoo_https_auth(struct yahoo_input_data *yid, const char *seed, const char *sn)
 {
 	struct yahoo_https_auth_data *had = g_new0(struct yahoo_https_auth_data, 1);
@@ -2479,44 +1946,45 @@
 }
 
-static void yahoo_process_auth(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
+static void yahoo_process_auth(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
 {
 	char *seed = NULL;
-	char *sn   = NULL;
+	char *sn = NULL;
 	YList *l = pkt->hash;
 	int m = 0;
+	struct yahoo_data *yd = yid->yd;
 
 	while (l) {
 		struct yahoo_pair *pair = l->data;
-		if (pair->key == 94)
+
+		switch (pair->key) {
+		case 94:
 			seed = pair->value;
-		if (pair->key == 1)
+			break;
+		case 1:
 			sn = pair->value;
-		if (pair->key == 13)
+			break;
+		case 13:
 			m = atoi(pair->value);
+			break;
+		}
 		l = l->next;
 	}
 
-	if (!seed) 
-		return;
-
-	switch (m) {
-		case 0:
-			yahoo_process_auth_pre_0x0b(yid, seed, sn);
-			break;
-		case 1:
-			yahoo_process_auth_0x0b(yid, seed, sn);
-			break;
-		case 2:
-			yahoo_process_auth_0x10(yid, seed, sn);
-			break;
-		default:
-			/* call error */
-			WARNING(("unknown auth type %d", m));
-			yahoo_process_auth_0x0b(yid, seed, sn);
-			break;
-	}
-}
-
-static void yahoo_process_auth_resp(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
+	if (!seed)
+		return;
+
+	if (m==2)
+		yahoo_https_auth(yid, seed, sn);
+	else {
+		/* call error */
+		WARNING(("unknown auth type %d", m));
+		YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id,
+			YAHOO_LOGIN_UNKNOWN, NULL);
+	}
+}
+
+static void yahoo_process_auth_resp(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
 {
 	struct yahoo_data *yd = yid->yd;
@@ -2524,5 +1992,5 @@
 	char *handle;
 	char *url = NULL;
-	int login_status = 0;
+	int login_status = -1;
 
 	YList *l;
@@ -2540,7 +2008,8 @@
 	}
 
-	if (pkt->status == 0xffffffff) {
-		YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, login_status, url);
-	/*	yahoo_logoff(yd->client_id);*/
+	if (pkt->status == YPACKET_STATUS_DISCONNECTED) {
+		YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id,
+			login_status, url);
+		/*      yahoo_logoff(yd->client_id); */
 	}
 }
@@ -2580,4 +2049,35 @@
 }
 
+static void yahoo_process_new_contact(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
+{
+	struct yahoo_data *yd = yid->yd;
+	char *me = NULL;
+	char *who = NULL;
+	char *msg = NULL;
+	int online = -1;
+
+	YList *l;
+
+	for (l = pkt->hash; l; l = l->next) {
+		struct yahoo_pair *pair = l->data;
+		if (pair->key == 4)
+			who = pair->value;
+		else if (pair->key == 5)
+			me = pair->value;
+		else if (pair->key == 14)
+			msg = pair->value;
+		else if (pair->key == 13)
+			online = strtol(pair->value, NULL, 10);
+	}
+
+	if (who && online < 0)
+		YAHOO_CALLBACK(ext_yahoo_contact_added) (yd->client_id, me, who,
+			msg);
+	else if (online == 2)
+		YAHOO_CALLBACK(ext_yahoo_rejected) (yd->client_id, who, msg);
+}
+
+/* UNUSED? */
 static void yahoo_process_contact(struct yahoo_input_data *yid,
 	struct yahoo_packet *pkt)
@@ -2661,39 +2161,19 @@
 		where = "Unknown";
 
-	/* status: 0 == Successful, 1 == Error (does not exist), 2 == Already in list */
-	if ( status == 0 ) {
-		bud = y_new0(struct yahoo_buddy, 1);
-		bud->id = strdup(who);
-		bud->group = strdup(where);
-		bud->real_name = NULL;
-		
-		yd->buddies = y_list_append(yd->buddies, bud);
-	
-		/* Possibly called already, but at least the call above doesn't
-		   seem to happen every time (not anytime I tried). */
-		YAHOO_CALLBACK(ext_yahoo_contact_added) (yd->client_id, me, who, NULL);
-	}
-
-/*	YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->client_id, who, status, NULL, (status==YAHOO_STATUS_AVAILABLE?0:1)); */
-}
-
-static void yahoo_process_contact_ymsg13(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
-{
-	char* who = NULL;
-	char* me = NULL;	
-	char* msg = NULL;
-	YList *l;
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-		if (pair->key == 4)
-			who = pair->value;
-		else if (pair->key == 5)
-			me = pair->value;
-		else
-			DEBUG_MSG(("unknown key: %d = %s", pair->key, pair->value));
-	}
-
-	if (pkt->status==3)
-		YAHOO_CALLBACK(ext_yahoo_contact_auth_request) (yid->yd->client_id, me, who, msg);
+	bud = y_new0(struct yahoo_buddy, 1);
+	bud->id = strdup(who);
+	bud->group = strdup(where);
+	bud->real_name = NULL;
+
+	yd->buddies = y_list_append(yd->buddies, bud);
+
+	/* A non-zero status (i've seen 2) seems to mean the buddy is already 
+	 * added and is online */
+	if (status) {
+		LOG(("Setting online see packet for info"));
+		yahoo_dump_unhandled(pkt);
+		YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->client_id, who,
+			YAHOO_STATUS_AVAILABLE, NULL, 0, 0, 0);
+	}
 }
 
@@ -2783,5 +2263,5 @@
 
 /*	if(status)
-		YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id, who, 0, status);
+		YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status);
 */
 }
@@ -2837,5 +2317,30 @@
 }
 
-static void _yahoo_webcam_get_server_connected(int fd, int error, void *d)
+static void yahoo_process_buddy_change_group(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
+{
+	YList *l;
+	char *me = NULL;
+	char *who = NULL;
+	char *old_group = NULL;
+	char *new_group = NULL;
+
+	for (l = pkt->hash; l; l = l->next) {
+		struct yahoo_pair *pair = l->data;
+		if (pair->key == 1)
+			me = pair->value;
+		if (pair->key == 7)
+			who = pair->value;
+		if (pair->key == 224)
+			old_group = pair->value;
+		if (pair->key == 264)
+			new_group = pair->value;
+	}
+
+	YAHOO_CALLBACK(ext_yahoo_got_buddy_change_group) (yid->yd->client_id,
+		me, who, old_group, new_group);
+}
+
+static void _yahoo_webcam_get_server_connected(void *fd, int error, void *d)
 {
 	struct yahoo_input_data *yid = d;
@@ -2848,5 +2353,5 @@
 	unsigned int pos = 0;
 
-	if (error || fd <= 0) {
+	if (error || !fd) {
 		FREE(who);
 		FREE(yid);
@@ -2905,5 +2410,5 @@
 	YAHOO_CALLBACK(ext_yahoo_connect_async) (yid->yd->client_id,
 		yss->webcam_host, yss->webcam_port,
-		_yahoo_webcam_get_server_connected, yid);
+		_yahoo_webcam_get_server_connected, yid, 0);
 
 }
@@ -2952,5 +2457,5 @@
 	case YAHOO_SERVICE_IDDEACT:
 	case YAHOO_SERVICE_Y6_STATUS_UPDATE:
-	case YAHOO_SERVICE_YMSG15_STATUS:
+	case YAHOO_SERVICE_Y8_STATUS:
 		yahoo_process_status(yid, pkt);
 		break;
@@ -2966,5 +2471,7 @@
 		yahoo_process_mail(yid, pkt);
 		break;
-	case YAHOO_SERVICE_REJECTCONTACT:
+	case YAHOO_SERVICE_Y7_AUTHORIZATION:
+		yahoo_process_new_contact(yid, pkt);
+		break;
 	case YAHOO_SERVICE_NEWCONTACT:
 		yahoo_process_contact(yid, pkt);
@@ -3001,12 +2508,15 @@
 		break;
 	case YAHOO_SERVICE_P2PFILEXFER:
-	case YAHOO_SERVICE_FILETRANSFER:
+	case YAHOO_SERVICE_Y7_FILETRANSFER:
 		yahoo_process_filetransfer(yid, pkt);
+		break;
+	case YAHOO_SERVICE_Y7_FILETRANSFERINFO:
+		yahoo_process_filetransferinfo(yid, pkt);
+		break;
+	case YAHOO_SERVICE_Y7_FILETRANSFERACCEPT:
+		yahoo_process_filetransferaccept(yid, pkt);
 		break;
 	case YAHOO_SERVICE_ADDBUDDY:
 		yahoo_process_buddyadd(yid, pkt);
-		break;
-	case YAHOO_SERVICE_CONTACT_YMSG13:
-		yahoo_process_contact_ymsg13(yid,pkt);
 		break;
 	case YAHOO_SERVICE_REMBUDDY:
@@ -3025,4 +2535,7 @@
 		yahoo_process_ping(yid, pkt);
 		break;
+	case YAHOO_SERVICE_Y7_CHANGE_GROUP:
+		yahoo_process_buddy_change_group(yid, pkt);
+		break;
 	case YAHOO_SERVICE_IDLE:
 	case YAHOO_SERVICE_MAILSTAT:
@@ -3038,4 +2551,5 @@
 	case YAHOO_SERVICE_CHATLOGOFF:
 	case YAHOO_SERVICE_CHATMSG:
+	case YAHOO_SERVICE_REJECTCONTACT:
 	case YAHOO_SERVICE_PEERTOPEER:
 		WARNING(("unhandled service 0x%02x", pkt->service));
@@ -3050,7 +2564,8 @@
 	case YAHOO_SERVICE_PICTURE_UPLOAD:
 		yahoo_process_picture_upload(yid, pkt);
-		break;	
-	case YAHOO_SERVICE_YMSG15_BUDDY_LIST:	/* Buddy List */
+		break;
+	case YAHOO_SERVICE_Y8_LIST:	/* Buddy List */
 		yahoo_process_buddy_list(yid, pkt);
+		break;
 	default:
 		WARNING(("unknown service 0x%02x", pkt->service));
@@ -3387,78 +2902,79 @@
 
 	/* find out what kind of packet we got */
-	switch (yid->wcd->packet_type)
-	{
-		case 0x00:
-			/* user requests to view webcam (uploading) */
-			if (yid->wcd->data_size &&
-				yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) {
-				end = begin;
-				while (end <= yid->rxlen &&
-					yid->rxqueue[end++] != 13);
-				if (end > begin)
-				{
-					who = y_memdup(yid->rxqueue + begin, end - begin);
-					who[end - begin - 1] = 0;
-					YAHOO_CALLBACK(ext_yahoo_webcam_viewer) (yd->client_id, who + 2, 2);
-					FREE(who);
-				}
-			}
-
-			if (yid->wcm->direction == YAHOO_WEBCAM_DOWNLOAD) {
-				/* timestamp/status field */
-				/* 0 = declined viewing permission */
-				/* 1 = accepted viewing permission */
-				if (yid->wcd->timestamp == 0) {
-					YAHOO_CALLBACK(ext_yahoo_webcam_closed) (yd->client_id, yid->wcm->user, 3);
-				}
-			}
-			break;
-		case 0x01: /* status packets?? */
-			/* timestamp contains status info */
-			/* 00 00 00 01 = we have data?? */
-			break;
-		case 0x02: /* image data */
-			YAHOO_CALLBACK(ext_yahoo_got_webcam_image) (yd->client_id, 
-					yid->wcm->user, yid->rxqueue + begin,
-					yid->wcd->data_size, pos - begin,
-					yid->wcd->timestamp);
-			break;
-		case 0x05: /* response packets when uploading */
-			if (!yid->wcd->data_size) {
-				YAHOO_CALLBACK(ext_yahoo_webcam_data_request) (yd->client_id, yid->wcd->timestamp);
-			}
-			break;
-		case 0x07: /* connection is closing */
-			switch(reason)
-			{
-				case 0x01: /* user closed connection */
-					closed = 1;
-					break;
-				case 0x0F: /* user cancelled permission */
-					closed = 2;
-					break;
-			}
-			YAHOO_CALLBACK(ext_yahoo_webcam_closed) (yd->client_id, yid->wcm->user, closed);
-			break;
-		case 0x0C: /* user connected */
-		case 0x0D: /* user disconnected */
-			if (yid->wcd->data_size) {
-				who = y_memdup(yid->rxqueue + begin, pos - begin + 1);
-				who[pos - begin] = 0;
-				if (yid->wcd->packet_type == 0x0C)
-					connect = 1;
-				else
-					connect = 0;
-				YAHOO_CALLBACK(ext_yahoo_webcam_viewer) (yd->client_id, who, connect);
+	switch (yid->wcd->packet_type) {
+	case 0x00:
+		/* user requests to view webcam (uploading) */
+		if (yid->wcd->data_size &&
+			yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) {
+			end = begin;
+			while (end <= yid->rxlen && yid->rxqueue[end++] != 13) ;
+			if (end > begin) {
+				who = y_memdup(yid->rxqueue + begin,
+					end - begin);
+				who[end - begin - 1] = 0;
+				YAHOO_CALLBACK(ext_yahoo_webcam_viewer) (yd->
+					client_id, who + 2, 2);
 				FREE(who);
 			}
-			break;
-		case 0x13: /* user data */
-			/* i = user_ip (ip of the user we are viewing) */
-			/* j = user_ext_ip (external ip of the user we */
- 			/*                are viewing) */
-			break;
-		case 0x17: /* ?? */
-			break;
+		}
+
+		if (yid->wcm->direction == YAHOO_WEBCAM_DOWNLOAD) {
+			/* timestamp/status field */
+			/* 0 = declined viewing permission */
+			/* 1 = accepted viewing permission */
+			if (yid->wcd->timestamp == 0) {
+				YAHOO_CALLBACK(ext_yahoo_webcam_closed) (yd->
+					client_id, yid->wcm->user, 3);
+			}
+		}
+		break;
+	case 0x01:		/* status packets?? */
+		/* timestamp contains status info */
+		/* 00 00 00 01 = we have data?? */
+		break;
+	case 0x02:		/* image data */
+		YAHOO_CALLBACK(ext_yahoo_got_webcam_image) (yd->client_id,
+			yid->wcm->user, yid->rxqueue + begin,
+			yid->wcd->data_size, pos - begin, yid->wcd->timestamp);
+		break;
+	case 0x05:		/* response packets when uploading */
+		if (!yid->wcd->data_size) {
+			YAHOO_CALLBACK(ext_yahoo_webcam_data_request) (yd->
+				client_id, yid->wcd->timestamp);
+		}
+		break;
+	case 0x07:		/* connection is closing */
+		switch (reason) {
+		case 0x01:	/* user closed connection */
+			closed = 1;
+			break;
+		case 0x0F:	/* user cancelled permission */
+			closed = 2;
+			break;
+		}
+		YAHOO_CALLBACK(ext_yahoo_webcam_closed) (yd->client_id,
+			yid->wcm->user, closed);
+		break;
+	case 0x0C:		/* user connected */
+	case 0x0D:		/* user disconnected */
+		if (yid->wcd->data_size) {
+			who = y_memdup(yid->rxqueue + begin, pos - begin + 1);
+			who[pos - begin] = 0;
+			if (yid->wcd->packet_type == 0x0C)
+				connect = 1;
+			else
+				connect = 0;
+			YAHOO_CALLBACK(ext_yahoo_webcam_viewer) (yd->client_id,
+				who, connect);
+			FREE(who);
+		}
+		break;
+	case 0x13:		/* user data */
+		/* i=user_ip (ip of the user we are viewing) */
+		/* j=user_ext_ip (external ip of the user we */
+		/*                are viewing) */
+		break;
+	case 0x17:		/* ?? */
+		break;
 	}
 	yid->wcd->to_read -= pos - begin;
@@ -3466,9 +2982,10 @@
 	yid->rxlen -= pos;
 	DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue));
-	if (yid->rxlen>0) {
+	if (yid->rxlen > 0) {
 		unsigned char *tmp = y_memdup(yid->rxqueue + pos, yid->rxlen);
 		FREE(yid->rxqueue);
 		yid->rxqueue = tmp;
-		DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue));
+		DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen,
+				yid->rxqueue));
 	} else {
 		DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue));
@@ -3483,5 +3000,5 @@
 }
 
-int yahoo_write_ready(int id, int fd, void *data)
+int yahoo_write_ready(int id, void *fd, void *data)
 {
 	struct yahoo_input_data *yid = data;
@@ -3489,8 +3006,8 @@
 	struct data_queue *tx;
 
-	LOG(("write callback: id=%d fd=%d data=%p", id, fd, data));
-	if (!yid || !yid->txqueues || !find_conn_by_id(id))
+	LOG(("write callback: id=%d fd=%p data=%p", id, fd, data));
+	if (!yid || !yid->txqueues)
 		return -2;
-	
+
 	tx = yid->txqueues->data;
 	LOG(("writing %d bytes", tx->len));
@@ -3508,8 +3025,10 @@
 			free(tx->queue);
 			free(tx);
-			yid->txqueues = y_list_remove_link(yid->txqueues, yid->txqueues);
+			yid->txqueues =
+				y_list_remove_link(yid->txqueues,
+				yid->txqueues);
 			y_list_free_1(l);
 		}
-		LOG(("yahoo_write_ready(%d, %d) len < 0", id, fd));
+		LOG(("yahoo_write_ready(%d, %p) len < 0", id, fd));
 		YAHOO_CALLBACK(ext_yahoo_remove_handler) (id, yid->write_tag);
 		yid->write_tag = 0;
@@ -3528,13 +3047,15 @@
 		free(tx->queue);
 		free(tx);
-		yid->txqueues = y_list_remove_link(yid->txqueues, yid->txqueues);
+		yid->txqueues =
+			y_list_remove_link(yid->txqueues, yid->txqueues);
 		y_list_free_1(l);
 		/*
-		if (!yid->txqueues) 
-			LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd));
-		*/
+		   if(!yid->txqueues) 
+		   LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd));
+		 */
 		if (!yid->txqueues) {
-			LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd));
-			YAHOO_CALLBACK(ext_yahoo_remove_handler) (id, yid->write_tag);
+			LOG(("yahoo_write_ready(%d, %p) !txqueues", id, fd));
+			YAHOO_CALLBACK(ext_yahoo_remove_handler) (id,
+				yid->write_tag);
 			yid->write_tag = 0;
 		}
@@ -3544,5 +3065,6 @@
 }
 
-static void yahoo_process_pager_connection(struct yahoo_input_data *yid, int over)
+static void yahoo_process_pager_connection(struct yahoo_input_data *yid,
+	int over)
 {
 	struct yahoo_packet *pkt;
@@ -3553,6 +3075,6 @@
 		return;
 
-	while (find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER) 
-			&& (pkt = yahoo_getdata(yid)) != NULL) {
+	while (find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER)
+		&& (pkt = yahoo_getdata(yid)) != NULL) {
 
 		yahoo_packet_process(yid, pkt);
@@ -3562,15 +3084,13 @@
 }
 
-static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over)
-{
-}
-
-static void yahoo_process_chatcat_connection(struct yahoo_input_data *yid, int over)
+static void yahoo_process_chatcat_connection(struct yahoo_input_data *yid,
+	int over)
 {
 	if (over)
 		return;
 
-	if (strstr((char*)yid->rxqueue+(yid->rxlen-20), "</content>")) {
-		YAHOO_CALLBACK(ext_yahoo_chat_cat_xml) (yid->yd->client_id, (char*)yid->rxqueue);
+	if (strstr((char *)yid->rxqueue + (yid->rxlen - 20), "</content>")) {
+		YAHOO_CALLBACK(ext_yahoo_chat_cat_xml) (yid->yd->client_id,
+			(char *)yid->rxqueue);
 	}
 }
@@ -3583,46 +3103,68 @@
 	int changed = 0;
 	int id = yd->client_id;
+	int yab_used = 0;
+
+	LOG(("Got data for YAB"));
 
 	if (over)
 		return;
 
-	while (find_input_by_id_and_type(id, YAHOO_CONNECTION_YAB) 
-			&& (yab = yahoo_getyab(yid)) != NULL) {
+	while (find_input_by_id_and_type(id, YAHOO_CONNECTION_YAB)
+		&& (yab = yahoo_getyab(yid)) != NULL) {
 		if (!yab->id)
 			continue;
+
 		changed = 1;
+		yab_used = 0;
 		for (buds = yd->buddies; buds; buds = buds->next) {
 			struct yahoo_buddy *bud = buds->data;
 			if (!strcmp(bud->id, yab->id)) {
+				yab_used = 1;
 				bud->yab_entry = yab;
 				if (yab->nname) {
 					bud->real_name = strdup(yab->nname);
 				} else if (yab->fname && yab->lname) {
-					bud->real_name = y_new0(char, 
-							strlen(yab->fname)+
-							strlen(yab->lname)+2
-							);
+					bud->real_name = y_new0(char,
+						strlen(yab->fname) +
+						strlen(yab->lname) + 2);
 					sprintf(bud->real_name, "%s %s",
-							yab->fname, yab->lname);
+						yab->fname, yab->lname);
 				} else if (yab->fname) {
 					bud->real_name = strdup(yab->fname);
 				}
-				break; /* for */
+				break;	/* for */
 			}
 		}
+
+		if (!yab_used) {
+			FREE(yab->fname);
+			FREE(yab->lname);
+			FREE(yab->nname);
+			FREE(yab->id);
+			FREE(yab->email);
+			FREE(yab->hphone);
+			FREE(yab->wphone);
+			FREE(yab->mphone);
+			FREE(yab);
+		}
+
 	}
 
 	if (changed)
-		YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, yd->buddies);
-}
-
-static void yahoo_process_search_connection(struct yahoo_input_data *yid, int over)
+		YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id,
+			yd->buddies);
+}
+
+static void yahoo_process_search_connection(struct yahoo_input_data *yid,
+	int over)
 {
 	struct yahoo_found_contact *yct = NULL;
 	char *p = (char *)yid->rxqueue, *np, *cp;
 	int k, n;
-	int start = 0, found=0, total=0;
+	int start = 0, found = 0, total = 0;
 	YList *contacts = NULL;
-	struct yahoo_input_data *pyid = find_input_by_id_and_type(yid->yd->client_id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *pyid =
+		find_input_by_id_and_type(yid->yd->client_id,
+		YAHOO_CONNECTION_PAGER);
 
 	if (!over || !pyid)
@@ -3635,8 +3177,14 @@
 			p++;
 			n = atoi(p);
-			switch(k) {
-				case 0: found = pyid->ys->lsearch_nfound = n; break;
-				case 2: start = pyid->ys->lsearch_nstart = n; break;
-				case 3: total = pyid->ys->lsearch_ntotal = n; break;
+			switch (k) {
+			case 0:
+				found = pyid->ys->lsearch_nfound = n;
+				break;
+			case 2:
+				start = pyid->ys->lsearch_nstart = n;
+				break;
+			case 3:
+				total = pyid->ys->lsearch_ntotal = n;
+				break;
 			}
 		}
@@ -3653,35 +3201,39 @@
 				break;
 			*np = 0;
-			p = np+1;
-
-			switch(k++) {
-				case 1:
-					if (strlen(cp) > 2 && y_list_length(contacts) < total) {
-						yct = y_new0(struct yahoo_found_contact, 1);
-						contacts = y_list_append(contacts, yct);
-						yct->id = cp+2;
-					} else {
-						*p = 0;
-					}
-					break;
-				case 2: 
-					yct->online = !strcmp(cp, "2") ? 1 : 0;
-					break;
-				case 3: 
-					yct->gender = cp;
-					break;
-				case 4: 
-					yct->age = atoi(cp);
-					break;
-				case 5: 
-					if (strcmp(cp, "5") != 0)
-						yct->location = cp;
-					k = 0;
-					break;
+			p = np + 1;
+
+			switch (k++) {
+			case 1:
+				if (strlen(cp) > 2
+					&& y_list_length(contacts) < total) {
+					yct = y_new0(struct yahoo_found_contact,
+						1);
+					contacts = y_list_append(contacts, yct);
+					yct->id = cp + 2;
+				} else {
+					*p = 0;
+				}
+				break;
+			case 2:
+				yct->online = !strcmp(cp, "2") ? 1 : 0;
+				break;
+			case 3:
+				yct->gender = cp;
+				break;
+			case 4:
+				yct->age = atoi(cp);
+				break;
+			case 5:
+				/* not worth the context switch for strcmp */
+				if (cp[0] != '\005' || cp[1] != '\000')
+					yct->location = cp;
+				k = 0;
+				break;
 			}
 		}
 	}
 
-	YAHOO_CALLBACK(ext_yahoo_got_search_result) (yid->yd->client_id, found, start, total, contacts);
+	YAHOO_CALLBACK(ext_yahoo_got_search_result) (yid->yd->client_id, found,
+		start, total, contacts);
 
 	while (contacts) {
@@ -3693,5 +3245,5 @@
 }
 
-static void _yahoo_webcam_connected(int fd, int error, void *d)
+static void _yahoo_webcam_connected(void *fd, int error, void *d)
 {
 	struct yahoo_input_data *yid = d;
@@ -3701,10 +3253,10 @@
 	char *data = NULL;
 	char *packet = NULL;
-	unsigned char magic_nr[] = {1, 0, 0, 0, 1};
+	unsigned char magic_nr[] = { 1, 0, 0, 0, 1 };
 	unsigned header_len = 0;
 	unsigned int len = 0;
 	unsigned int pos = 0;
 
-	if (error || fd <= 0) {
+	if (error || !fd) {
 		FREE(yid);
 		return;
@@ -3716,14 +3268,13 @@
 	LOG(("Connected"));
 	/* send initial packet */
-	switch (wcm->direction)
-	{
-		case YAHOO_WEBCAM_DOWNLOAD:
-			data = strdup("<REQIMG>");
-			break;
-		case YAHOO_WEBCAM_UPLOAD:	
-			data = strdup("<SNDIMG>");
-			break;
-		default:
-			return;
+	switch (wcm->direction) {
+	case YAHOO_WEBCAM_DOWNLOAD:
+		data = strdup("<REQIMG>");
+		break;
+	case YAHOO_WEBCAM_UPLOAD:
+		data = strdup("<SNDIMG>");
+		break;
+	default:
+		return;
 	}
 	yahoo_add_to_send_queue(yid, data, strlen(data));
@@ -3731,36 +3282,35 @@
 
 	/* send data */
-	switch (wcm->direction)
-	{
-		case YAHOO_WEBCAM_DOWNLOAD:
-			header_len = 8;
-			data = strdup("a=2\r\nc=us\r\ne=21\r\nu=");
-			data = y_string_append(data, yd->user);
-			data = y_string_append(data, "\r\nt=");
-			data = y_string_append(data, wcm->key);
-			data = y_string_append(data, "\r\ni=");
-			data = y_string_append(data, wcm->my_ip);
-			data = y_string_append(data, "\r\ng=");
-			data = y_string_append(data, wcm->user);
-			data = y_string_append(data, "\r\no=w-2-5-1\r\np=");
-			snprintf(conn_type, sizeof(conn_type), "%d", wcm->conn_type);
-			data = y_string_append(data, conn_type);
-			data = y_string_append(data, "\r\n");
-			break;
-		case YAHOO_WEBCAM_UPLOAD:
-			header_len = 13;
-			data = strdup("a=2\r\nc=us\r\nu=");
-			data = y_string_append(data, yd->user);
-			data = y_string_append(data, "\r\nt=");
-			data = y_string_append(data, wcm->key);
-			data = y_string_append(data, "\r\ni=");
-			data = y_string_append(data, wcm->my_ip);
-			data = y_string_append(data, "\r\no=w-2-5-1\r\np=");
-			snprintf(conn_type, sizeof(conn_type), "%d", wcm->conn_type);
-			data = y_string_append(data, conn_type);
-			data = y_string_append(data, "\r\nb=");
-			data = y_string_append(data, wcm->description);
-			data = y_string_append(data, "\r\n");
-			break;
+	switch (wcm->direction) {
+	case YAHOO_WEBCAM_DOWNLOAD:
+		header_len = 8;
+		data = strdup("a=2\r\nc=us\r\ne=21\r\nu=");
+		data = y_string_append(data, yd->user);
+		data = y_string_append(data, "\r\nt=");
+		data = y_string_append(data, wcm->key);
+		data = y_string_append(data, "\r\ni=");
+		data = y_string_append(data, wcm->my_ip);
+		data = y_string_append(data, "\r\ng=");
+		data = y_string_append(data, wcm->user);
+		data = y_string_append(data, "\r\no=w-2-5-1\r\np=");
+		snprintf(conn_type, sizeof(conn_type), "%d", wcm->conn_type);
+		data = y_string_append(data, conn_type);
+		data = y_string_append(data, "\r\n");
+		break;
+	case YAHOO_WEBCAM_UPLOAD:
+		header_len = 13;
+		data = strdup("a=2\r\nc=us\r\nu=");
+		data = y_string_append(data, yd->user);
+		data = y_string_append(data, "\r\nt=");
+		data = y_string_append(data, wcm->key);
+		data = y_string_append(data, "\r\ni=");
+		data = y_string_append(data, wcm->my_ip);
+		data = y_string_append(data, "\r\no=w-2-5-1\r\np=");
+		snprintf(conn_type, sizeof(conn_type), "%d", wcm->conn_type);
+		data = y_string_append(data, conn_type);
+		data = y_string_append(data, "\r\nb=");
+		data = y_string_append(data, wcm->description);
+		data = y_string_append(data, "\r\n");
+		break;
 	}
 
@@ -3769,19 +3319,17 @@
 	packet[pos++] = header_len;
 	packet[pos++] = 0;
-	switch (wcm->direction)
-	{
-		case YAHOO_WEBCAM_DOWNLOAD:
-			packet[pos++] = 1;
-			packet[pos++] = 0;
-			break;
-		case YAHOO_WEBCAM_UPLOAD:
-			packet[pos++] = 5;
-			packet[pos++] = 0;
-			break;
+	switch (wcm->direction) {
+	case YAHOO_WEBCAM_DOWNLOAD:
+		packet[pos++] = 1;
+		packet[pos++] = 0;
+		break;
+	case YAHOO_WEBCAM_UPLOAD:
+		packet[pos++] = 5;
+		packet[pos++] = 0;
+		break;
 	}
 
 	pos += yahoo_put32(packet + pos, len);
-	if (wcm->direction == YAHOO_WEBCAM_UPLOAD)
-	{
+	if (wcm->direction == YAHOO_WEBCAM_UPLOAD) {
 		memcpy(packet + pos, magic_nr, sizeof(magic_nr));
 		pos += sizeof(magic_nr);
@@ -3792,5 +3340,7 @@
 	FREE(data);
 
-	yid->read_tag = YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, yid->fd, YAHOO_INPUT_READ, yid);
+	yid->read_tag =
+		YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id,
+		yid->fd, YAHOO_INPUT_READ, yid);
 }
 
@@ -3817,12 +3367,13 @@
 
 	LOG(("Connecting to: %s:%d", wcm->server, wcm->port));
-	YAHOO_CALLBACK(ext_yahoo_connect_async) (y->yd->client_id, wcm->server, wcm->port,
-			_yahoo_webcam_connected, yid);
-
-}
-
-static void yahoo_process_webcam_master_connection(struct yahoo_input_data *yid, int over)
-{
-	char* server;
+	YAHOO_CALLBACK(ext_yahoo_connect_async) (y->yd->client_id, wcm->server,
+		wcm->port, _yahoo_webcam_connected, yid, 0);
+
+}
+
+static void yahoo_process_webcam_master_connection(struct yahoo_input_data *yid,
+	int over)
+{
+	char *server;
 	struct yahoo_server_settings *yss;
 
@@ -3832,6 +3383,5 @@
 	server = yahoo_getwebcam_master(yid);
 
-	if (server)
-	{
+	if (server) {
 		yss = yid->yd->server_settings;
 		yid->wcm->server = strdup(server);
@@ -3846,8 +3396,9 @@
 }
 
-static void yahoo_process_webcam_connection(struct yahoo_input_data *yid, int over)
+static void yahoo_process_webcam_connection(struct yahoo_input_data *yid,
+	int over)
 {
 	int id = yid->yd->client_id;
-	int fd = yid->fd;
+	void *fd = yid->fd;
 
 	if (over)
@@ -3855,19 +3406,18 @@
 
 	/* as long as we still have packets available keep processing them */
-	while (find_input_by_id_and_fd(id, fd) 
-			&& yahoo_get_webcam_data(yid) == 1);
-}
-
-static void (*yahoo_process_connection[])(struct yahoo_input_data *, int over) = {
-	yahoo_process_pager_connection,
-	yahoo_process_ft_connection,
-	yahoo_process_yab_connection,
-	yahoo_process_webcam_master_connection,
-	yahoo_process_webcam_connection,
-	yahoo_process_chatcat_connection,
-	yahoo_process_search_connection,
-};
-
-int yahoo_read_ready(int id, int fd, void *data)
+	while (find_input_by_id_and_fd(id, fd)
+		&& yahoo_get_webcam_data(yid) == 1) ;
+}
+
+static void (*yahoo_process_connection[]) (struct yahoo_input_data *,
+	int over) = {
+yahoo_process_pager_connection, yahoo_process_ft_connection,
+		yahoo_process_yab_connection,
+		yahoo_process_webcam_master_connection,
+		yahoo_process_webcam_connection,
+		yahoo_process_chatcat_connection,
+		yahoo_process_search_connection};
+
+int yahoo_read_ready(int id, void *fd, void *data)
 {
 	struct yahoo_input_data *yid = data;
@@ -3875,14 +3425,13 @@
 	int len;
 
-	LOG(("read callback: id=%d fd=%d data=%p", id, fd, data));
+	LOG(("read callback: id=%d fd=%p data=%p", id, fd, data));
 	if (!yid)
 		return -2;
 
-	
 	do {
-		len = read(fd, buf, sizeof(buf));
+		len = YAHOO_CALLBACK(ext_yahoo_read) (fd, buf, sizeof(buf));
 	} while (len == -1 && errno == EINTR);
 
-	if (len == -1 && (errno == EAGAIN||errno == EINTR))	/* we'll try again later */
+	if (len == -1 && (errno == EAGAIN || errno == EINTR))	/* we'll try again later */
 		return 1;
 
@@ -3892,8 +3441,9 @@
 
 		if (yid->type == YAHOO_CONNECTION_PAGER) {
-			YAHOO_CALLBACK(ext_yahoo_error) (yid->yd->client_id, "Connection closed by server", 1, E_CONNECTION);
-		}
-
-		yahoo_process_connection[yid->type](yid, 1);
+			YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd->
+				client_id, YAHOO_LOGIN_SOCK, NULL);
+		}
+
+		yahoo_process_connection[yid->type] (yid, 1);
 		yahoo_input_close(yid);
 
@@ -3907,9 +3457,11 @@
 	}
 
-	yid->rxqueue = y_renew(unsigned char, yid->rxqueue, len + yid->rxlen);
+	yid->rxqueue =
+		y_renew(unsigned char, yid->rxqueue, len + yid->rxlen + 1);
 	memcpy(yid->rxqueue + yid->rxlen, buf, len);
 	yid->rxlen += len;
-
-	yahoo_process_connection[yid->type](yid, 0);
+	yid->rxqueue[yid->rxlen] = 0;
+
+	yahoo_process_connection[yid->type] (yid, 0);
 
 	return len;
@@ -3948,11 +3500,5 @@
 }
 
-struct connect_callback_data {
-	struct yahoo_data *yd;
-	int tag;
-	int i;
-};
-
-static void yahoo_connected(int fd, int error, void *data)
+static void yahoo_connected(void *fd, int error, void *data)
 {
 	struct connect_callback_data *ccd = data;
@@ -3963,15 +3509,34 @@
 
 	if (error) {
+		int tag;
 		if (fallback_ports[ccd->i]) {
-			int tag;
+			char *host = yss->pager_host;
+
+			if (!host)
+				host = yss->pager_host_list[ccd->server_i];
+
 			yss->pager_port = fallback_ports[ccd->i++];
-			tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd->client_id, yss->pager_host,
-					yss->pager_port, yahoo_connected, ccd);
+			tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd->
+				client_id, host, yss->pager_port,
+				yahoo_connected, ccd, 0);
 
 			if (tag > 0)
 				ccd->tag = tag;
+		} else if (yss->pager_host_list
+				&& yss->pager_host_list[ccd->server_i]) {
+
+			/* Get back to the default port */
+			yss->pager_port = pager_port;
+			ccd->server_i++;
+			LOG(("Fallback: Connecting to %s:%d", yss->pager_host_list[ccd->server_i], yss->pager_port));
+
+			ccd->i = 0;
+			tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd->client_id,
+				yss->pager_host_list[ccd->server_i], yss->pager_port,
+				yahoo_connected, ccd, 0);
 		} else {
 			FREE(ccd);
-			YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, YAHOO_LOGIN_SOCK, NULL);
+			YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id,
+				YAHOO_LOGIN_SOCK, NULL);
 		}
 		return;
@@ -3980,17 +3545,16 @@
 	FREE(ccd);
 
-	/* fd < 0 && error == 0 means connect was cancelled */
-	if (fd < 0)
-		return;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YAHOO_STATUS_AVAILABLE, yd->session_id);
+	/* fd == NULL && error == 0 means connect was cancelled */
+	if (!fd)
+		return;
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
 	NOTICE(("Sending initial packet"));
 
 	yahoo_packet_hash(pkt, 1, yd->user);
 
-	yid = y_new0(struct yahoo_input_data, 1);
-	yid->yd = yd;
+	yid = find_input_by_id_and_type(yd->client_id, YAHOO_CONNECTION_PAGER);
 	yid->fd = fd;
-	inputs = y_list_prepend(inputs, yid);
 
 	yahoo_send_packet(yid, pkt, 0);
@@ -3998,40 +3562,13 @@
 	yahoo_packet_free(pkt);
 
-	yid->read_tag = YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, yid->fd, YAHOO_INPUT_READ, yid);
-}
-
-void yahoo_login(int id, int initial)
-{
-	struct yahoo_data *yd = find_conn_by_id(id);
-	struct connect_callback_data *ccd;
-	struct yahoo_server_settings *yss;
-	int tag;
-
-	if (!yd)
-		return;
-
-	yss = yd->server_settings;
-
-	yd->initial_status = initial;
-
-	ccd = y_new0(struct connect_callback_data, 1);
-	ccd->yd = yd;
-	tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd->client_id, yss->pager_host, yss->pager_port, 
-			yahoo_connected, ccd);
-
-	/*
-	 * if tag <= 0, then callback has already been called
-	 * so ccd will have been freed
-	 */
-	if (tag > 0)
-		ccd->tag = tag;
-	else if (tag < 0)
-		YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, YAHOO_LOGIN_SOCK, NULL);
-}
-
-
-int yahoo_get_fd(int id)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	yid->read_tag =
+		YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id,
+		yid->fd, YAHOO_INPUT_READ, yid);
+}
+
+void *yahoo_get_fd(int id)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	if (!yid)
 		return 0;
@@ -4040,7 +3577,14 @@
 }
 
-void yahoo_send_im(int id, const char *from, const char *who, const char *what, int utf8, int picture)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_send_buzz(int id, const char *from, const char *who)
+{
+	yahoo_send_im(id, from, who, "<ding>", 1, 0);
+}
+
+void yahoo_send_im(int id, const char *from, const char *who, const char *what,
+	int utf8, int picture)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_packet *pkt = NULL;
 	struct yahoo_data *yd;
@@ -4052,11 +3596,12 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE,
+		yd->session_id);
 
 	snprintf(pic_str, sizeof(pic_str), "%d", picture);
-	
+
 	if (from && strcmp(from, yd->user))
 		yahoo_packet_hash(pkt, 0, yd->user);
-	yahoo_packet_hash(pkt, 1, from?from:yd->user);
+	yahoo_packet_hash(pkt, 1, from ? from : yd->user);
 	yahoo_packet_hash(pkt, 5, who);
 	yahoo_packet_hash(pkt, 14, what);
@@ -4069,5 +3614,4 @@
 	yahoo_packet_hash(pkt, 206, pic_str);
 
-
 	yahoo_send_packet(yid, pkt, 0);
 
@@ -4077,5 +3621,6 @@
 void yahoo_send_typing(int id, const char *from, const char *who, int typ)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
@@ -4084,8 +3629,9 @@
 
 	yd = yid->yd;
-	pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_NOTIFY, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YPACKET_STATUS_NOTIFY,
+		yd->session_id);
 
 	yahoo_packet_hash(pkt, 5, who);
-	yahoo_packet_hash(pkt, 1, from?from:yd->user);
+	yahoo_packet_hash(pkt, 1, from ? from : yd->user);
 	yahoo_packet_hash(pkt, 14, " ");
 	yahoo_packet_hash(pkt, 13, typ ? "1" : "0");
@@ -4099,5 +3645,6 @@
 void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
@@ -4109,4 +3656,5 @@
 
 	yd = yid->yd;
+
 	old_status = yd->current_status;
 	yd->current_status = state;
@@ -4114,5 +3662,6 @@
 	/* Thank you libpurple :) */
 	if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
-		pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBILITY, YAHOO_STATUS_AVAILABLE, 0);
+		pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE,
+			YAHOO_STATUS_AVAILABLE, 0);
 		yahoo_packet_hash(pkt, 13, "2");
 		yahoo_send_packet(yid, pkt, 0);
@@ -4122,5 +3671,6 @@
 	}
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, yd->current_status, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE,
+		yd->current_status, yd->session_id);
 	snprintf(s, sizeof(s), "%d", yd->current_status);
 	yahoo_packet_hash(pkt, 10, s);
@@ -4131,5 +3681,6 @@
 
 	if (old_status == YAHOO_STATUS_INVISIBLE) {
-		pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBILITY, YAHOO_STATUS_AVAILABLE, 0);
+		pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE,
+			YAHOO_STATUS_AVAILABLE, 0);
 		yahoo_packet_hash(pkt, 13, "1");
 		yahoo_send_packet(yid, pkt, 0);
@@ -4140,5 +3691,6 @@
 void yahoo_logoff(int id)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
@@ -4154,5 +3706,6 @@
 		   get to do this so it'll just leak memory. And the TCP
 		   connection reset will hopefully be clear enough. */
-		pkt = yahoo_packet_new(YAHOO_SERVICE_LOGOFF, YAHOO_STATUS_AVAILABLE, yd->session_id);
+		pkt = yahoo_packet_new(YAHOO_SERVICE_LOGOFF,
+			YPACKET_STATUS_DEFAULT, yd->session_id);
 		yd->current_status = -1;
 
@@ -4163,12 +3716,14 @@
 	}
 
-	do {
+/*	do {
 		yahoo_input_close(yid);
-	} while ((yid = find_input_by_id(id)));
+	} while((yid = find_input_by_id(id)));*/
+
 }
 
 void yahoo_get_list(int id)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
@@ -4178,5 +3733,6 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_LIST, YAHOO_STATUS_AVAILABLE, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_LIST, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
 	yahoo_packet_hash(pkt, 1, yd->user);
 	if (pkt) {
@@ -4186,8 +3742,8 @@
 }
 
-static void _yahoo_http_connected(int id, int fd, int error, void *data)
+static void _yahoo_http_connected(int id, void *fd, int error, void *data)
 {
 	struct yahoo_input_data *yid = data;
-	if (fd <= 0) {
+	if (fd == NULL || error) {
 		inputs = y_list_remove(inputs, yid);
 		FREE(yid);
@@ -4196,40 +3752,76 @@
 
 	yid->fd = fd;
-	yid->read_tag = YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd, YAHOO_INPUT_READ, yid);
-}
-
+	yid->read_tag =
+		YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd,
+		YAHOO_INPUT_READ, yid);
+}
+
+/* FIXME Get address book from address.yahoo.com instead */
 void yahoo_get_yab(int id)
 {
+	struct yahoo_data *yd = find_conn_by_id(id);
+	struct yahoo_input_data *yid;
+	char url[1024];
+	char buff[2048];
+
+	if (!yd)
+		return;
+
+	yid = y_new0(struct yahoo_input_data, 1);
+	yid->yd = yd;
+	yid->type = YAHOO_CONNECTION_YAB;
+
+	LOG(("Sending request for Address Book"));
+
+	snprintf(url, 1024,
+		"http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us"
+		"&diffs=1&t=0&tags=short&rt=0&prog-ver=8.1.0.249&useutf8=1&legenc=codepage-1252");
+
+	snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
+
+	inputs = y_list_prepend(inputs, yid);
+
+	yahoo_http_get(yid->yd->client_id, url, buff, 0, 0,
+		_yahoo_http_connected, yid);
+}
+
+struct yahoo_post_data {
+	struct yahoo_input_data *yid;
+	char *data;
+};
+
+static void _yahoo_http_post_connected(int id, void *fd, int error, void *data)
+{
+	struct yahoo_post_data *yad = data;
+	struct yahoo_input_data *yid = yad->yid;
+	char *buff = yad->data;
+
+	if (!fd) {
+		inputs = y_list_remove(inputs, yid);
+		FREE(yid);
+		return;
+	}
+
+	YAHOO_CALLBACK(ext_yahoo_write) (fd, buff, strlen(buff));
+
+	yid->fd = fd;
+	yid->read_tag =
+		YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd,
+		YAHOO_INPUT_READ, yid);
+
+	FREE(buff);
+	FREE(yad);
+}
+
+/* FIXME This is also likely affected */
+void yahoo_set_yab(int id, struct yab *yab)
+{
+	struct yahoo_post_data *yad = y_new0(struct yahoo_post_data, 1);
 	struct yahoo_data *yd = find_conn_by_id(id);
 	struct yahoo_input_data *yid;
 	char url[1024];
 	char buff[1024];
-
-	if (!yd)
-		return;
-
-	yid = y_new0(struct yahoo_input_data, 1);
-	yid->yd = yd;
-	yid->type = YAHOO_CONNECTION_YAB;
-
-	snprintf(url, 1024, "http://insider.msg.yahoo.com/ycontent/?ab2=0");
-
-	snprintf(buff, sizeof(buff), "Y=%s; T=%s",
-			yd->cookie_y, yd->cookie_t);
-
-	inputs = y_list_prepend(inputs, yid);
-
-	yahoo_http_get(yid->yd->client_id, url, buff, 
-			_yahoo_http_connected, yid);
-}
-
-void yahoo_set_yab(int id, struct yab *yab)
-{
-	struct yahoo_data *yd = find_conn_by_id(id);
-	struct yahoo_input_data *yid;
-	char url[1024];
-	char buff[1024];
-	char *temp;
-	int size = sizeof(url)-1;
+	char post[1024];
+	int size = 0;
 
 	if (!yd)
@@ -4240,74 +3832,35 @@
 	yid->yd = yd;
 
-	strncpy(url, "http://insider.msg.yahoo.com/ycontent/?addab2=0", size);
-
-	if (yab->dbid) {
-		/* change existing yab */
-		char tmp[32];
-		strncat(url, "&ee=1&ow=1&id=", size - strlen(url));
-		snprintf(tmp, sizeof(tmp), "%d", yab->dbid);
-		strncat(url, tmp, size - strlen(url));
-	}
-
-	if (yab->fname) {
-		strncat(url, "&fn=", size - strlen(url));
-		temp = yahoo_urlencode(yab->fname);
-		strncat(url, temp, size - strlen(url));
-		free(temp);
-	}
-	if (yab->lname) {
-		strncat(url, "&ln=", size - strlen(url));
-		temp = yahoo_urlencode(yab->lname);
-		strncat(url, temp, size - strlen(url));
-		free(temp);
-	}
-	strncat(url, "&yid=", size - strlen(url));
-	temp = yahoo_urlencode(yab->id);
-	strncat(url, temp, size - strlen(url));
-	free(temp);
-	if (yab->nname) {
-		strncat(url, "&nn=", size - strlen(url));
-		temp = yahoo_urlencode(yab->nname);
-		strncat(url, temp, size - strlen(url));
-		free(temp);
-	}
-	if (yab->email) {
-		strncat(url, "&e=", size - strlen(url));
-		temp = yahoo_urlencode(yab->email);
-		strncat(url, temp, size - strlen(url));
-		free(temp);
-	}
-	if (yab->hphone) {
-		strncat(url, "&hp=", size - strlen(url));
-		temp = yahoo_urlencode(yab->hphone);
-		strncat(url, temp, size - strlen(url));
-		free(temp);
-	}
-	if (yab->wphone) {
-		strncat(url, "&wp=", size - strlen(url));
-		temp = yahoo_urlencode(yab->wphone);
-		strncat(url, temp, size - strlen(url));
-		free(temp);
-	}
-	if (yab->mphone) {
-		strncat(url, "&mp=", size - strlen(url));
-		temp = yahoo_urlencode(yab->mphone);
-		strncat(url, temp, size - strlen(url));
-		free(temp);
-	}
-	strncat(url, "&pp=0", size - strlen(url));
-
-	snprintf(buff, sizeof(buff), "Y=%s; T=%s",
-			yd->cookie_y, yd->cookie_t);
+	if(yab->yid)
+		size = snprintf(post, sizeof(post), "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+			"<ab k=\"%s\" cc=\"%d\">"
+			"<ct id=\"%d\" e=\"1\" yi=\"%s\" nn=\"%s\" />"
+			"</ab>", yd->user, 9, yab->yid,	/* Don't know why */
+			yab->id, yab->nname?yab->nname:"");
+	else
+		size = snprintf(post, sizeof(post), "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+			"<ab k=\"%s\" cc=\"%d\">"
+			"<ct a=\"1\" yi=\"%s\" nn=\"%s\" />"
+			"</ab>", yd->user, 1,	/* Don't know why */
+			yab->id, yab->nname?yab->nname:"");
+
+	yad->yid = yid;
+	yad->data = strdup(post);
+
+	strcpy(url, "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us"
+		"&sync=1&tags=short&noclear=1&useutf8=1&legenc=codepage-1252");
+
+	snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
 
 	inputs = y_list_prepend(inputs, yid);
 
-	yahoo_http_get(yid->yd->client_id, url, buff, 
-			_yahoo_http_connected, yid);
+	yahoo_http_post(yid->yd->client_id, url, buff, size,
+		_yahoo_http_post_connected, yad);
 }
 
 void yahoo_set_identity_status(int id, const char *identity, int active)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
@@ -4317,6 +3870,6 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(active?YAHOO_SERVICE_IDACT:YAHOO_SERVICE_IDDEACT,
-			YAHOO_STATUS_AVAILABLE, yd->session_id);
+	pkt = yahoo_packet_new(active ? YAHOO_SERVICE_IDACT :
+		YAHOO_SERVICE_IDDEACT, YPACKET_STATUS_DEFAULT, yd->session_id);
 	yahoo_packet_hash(pkt, 3, identity);
 	if (pkt) {
@@ -4328,5 +3881,6 @@
 void yahoo_refresh(int id)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
@@ -4336,5 +3890,6 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_USERSTAT, YAHOO_STATUS_AVAILABLE, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_USERSTAT, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
 	if (pkt) {
 		yahoo_send_packet(yid, pkt, 0);
@@ -4345,5 +3900,6 @@
 void yahoo_keepalive(int id)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
@@ -4352,28 +3908,33 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
 	yahoo_send_packet(yid, pkt, 0);
 	yahoo_packet_free(pkt);
 }
 
-void yahoo_chat_keepalive (int id)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type (id, YAHOO_CONNECTION_PAGER);
+void yahoo_chat_keepalive(int id)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
 
 	if (!yid)
-	    return;
+		return;
 
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new (YAHOO_SERVICE_CHATPING, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_send_packet (yid, pkt, 0);
-	yahoo_packet_free (pkt);
-}
-
-void yahoo_add_buddy(int id, const char *who, const char *group, const char *msg)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
+	yahoo_send_packet(yid, pkt, 0);
+	yahoo_packet_free(pkt);
+}
+
+void yahoo_add_buddy(int id, const char *who, const char *group,
+	const char *msg)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
@@ -4386,11 +3947,10 @@
 		return;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YPACKET_STATUS_DEFAULT, yd->session_id);
-
-	if (msg != NULL) /* add message/request "it's me add me" */
+	pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
+	if (msg != NULL)	/* add message/request "it's me add me" */
 		yahoo_packet_hash(pkt, 14, msg);
 	else
-		yahoo_packet_hash(pkt,14,"");
-
+		yahoo_packet_hash(pkt, 14, "");
 	yahoo_packet_hash(pkt, 65, group);
 	yahoo_packet_hash(pkt, 97, "1");
@@ -4402,6 +3962,4 @@
 	yahoo_packet_hash(pkt, 301, "319");
 	yahoo_packet_hash(pkt, 303, "319");
-
-
 	yahoo_send_packet(yid, pkt, 0);
 	yahoo_packet_free(pkt);
@@ -4410,5 +3968,6 @@
 void yahoo_remove_buddy(int id, const char *who, const char *group)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
@@ -4418,5 +3977,6 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
 
 	yahoo_packet_hash(pkt, 1, yd->user);
@@ -4427,7 +3987,10 @@
 }
 
-void yahoo_accept_buddy_ymsg13(int id,const char* me,const char* who){
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_confirm_buddy(int id, const char *who, int reject, const char *msg)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
+	struct yahoo_packet *pkt;
 
 	if (!yid)
@@ -4435,18 +3998,35 @@
 	yd = yid->yd;
 
-	struct yahoo_packet* pkt = NULL;
-	pkt= yahoo_packet_new(YAHOO_SERVICE_CONTACT_YMSG13,YAHOO_STATUS_AVAILABLE,0);
-
-	yahoo_packet_hash(pkt,1,me ?: yd->user);	
-	yahoo_packet_hash(pkt,5,who);
-	yahoo_packet_hash(pkt,13,"1");
-	yahoo_packet_hash(pkt,334,"0");
+	if (!yd->logged_in)
+		return;
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_AUTHORIZATION,
+		YPACKET_STATUS_DEFAULT, yd->session_id);
+	yahoo_packet_hash(pkt, 1, yd->user);
+	yahoo_packet_hash(pkt, 5, who);
+	if (reject)
+		yahoo_packet_hash(pkt, 13, "2");
+	else {
+		yahoo_packet_hash(pkt, 241, "0");
+		yahoo_packet_hash(pkt, 13, "1");
+	}
+
+	yahoo_packet_hash(pkt, 334, "0");
+
+	if (reject) {
+		yahoo_packet_hash(pkt, 14, msg ? msg : "");
+		yahoo_packet_hash(pkt, 97, "1");
+	}
+
 	yahoo_send_packet(yid, pkt, 0);
 	yahoo_packet_free(pkt);
 }
 
-void yahoo_reject_buddy_ymsg13(int id,const char* me,const char* who,const char* msg){
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_ignore_buddy(int id, const char *who, int unignore)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
+	struct yahoo_packet *pkt;
 
 	if (!yid)
@@ -4454,23 +4034,20 @@
 	yd = yid->yd;
 
-	struct yahoo_packet* pkt = NULL;
-	pkt= yahoo_packet_new(YAHOO_SERVICE_CONTACT_YMSG13,YAHOO_STATUS_AVAILABLE,0);
-
-	yahoo_packet_hash(pkt,1,me ?: yd->user);	
-	yahoo_packet_hash(pkt,5,who);
-//	yahoo_packet_hash(pkt,241,YAHOO_PROTO_VER);
-	yahoo_packet_hash(pkt,13,"2");
-	yahoo_packet_hash(pkt,334,"0");
-	yahoo_packet_hash(pkt,97,"1");
-	yahoo_packet_hash(pkt,14,msg?:"");
-
+	if (!yd->logged_in)
+		return;
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT,
+		YPACKET_STATUS_DEFAULT, yd->session_id);
+	yahoo_packet_hash(pkt, 1, yd->user);
+	yahoo_packet_hash(pkt, 7, who);
+	yahoo_packet_hash(pkt, 13, unignore ? "2" : "1");
 	yahoo_send_packet(yid, pkt, 0);
 	yahoo_packet_free(pkt);
-
-}
-
-void yahoo_reject_buddy(int id, const char *who, const char *msg)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+}
+
+void yahoo_stealth_buddy(int id, const char *who, int unstealth)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
@@ -4483,50 +4060,9 @@
 		return;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_REJECTCONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_STEALTH_PERM,
+		YPACKET_STATUS_DEFAULT, yd->session_id);
 	yahoo_packet_hash(pkt, 1, yd->user);
 	yahoo_packet_hash(pkt, 7, who);
-	yahoo_packet_hash(pkt, 14, msg);
-	yahoo_send_packet(yid, pkt, 0);
-	yahoo_packet_free(pkt);
-}
-
-void yahoo_ignore_buddy(int id, const char *who, int unignore)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
-	struct yahoo_data *yd;
-	struct yahoo_packet *pkt;
-
-	if (!yid)
-		return;
-	yd = yid->yd;
-
-	if (!yd->logged_in)
-		return;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, 1, yd->user);
-	yahoo_packet_hash(pkt, 7, who);
-	yahoo_packet_hash(pkt, 13, unignore?"2":"1");
-	yahoo_send_packet(yid, pkt, 0);
-	yahoo_packet_free(pkt);
-}
-
-void yahoo_stealth_buddy(int id, const char *who, int unstealth)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
-	struct yahoo_data *yd;
-	struct yahoo_packet *pkt;
-
-	if (!yid)
-		return;
-	yd = yid->yd;
-
-	if (!yd->logged_in)
-		return;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_STEALTH, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, 1, yd->user);
-	yahoo_packet_hash(pkt, 7, who);
-	yahoo_packet_hash(pkt, 31, unstealth?"2":"1");
+	yahoo_packet_hash(pkt, 31, unstealth ? "2" : "1");
 	yahoo_packet_hash(pkt, 13, "2");
 	yahoo_send_packet(yid, pkt, 0);
@@ -4534,7 +4070,9 @@
 }
 
-void yahoo_change_buddy_group(int id, const char *who, const char *old_group, const char *new_group)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_change_buddy_group(int id, const char *who, const char *old_group,
+	const char *new_group)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
@@ -4544,24 +4082,23 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_CHANGE_GROUP,
+		YPACKET_STATUS_DEFAULT, yd->session_id);
 	yahoo_packet_hash(pkt, 1, yd->user);
+	yahoo_packet_hash(pkt, 302, "240");
+	yahoo_packet_hash(pkt, 300, "240");
 	yahoo_packet_hash(pkt, 7, who);
-	yahoo_packet_hash(pkt, 65, new_group);
-	yahoo_packet_hash(pkt, 14, " ");
+	yahoo_packet_hash(pkt, 224, old_group);
+	yahoo_packet_hash(pkt, 264, new_group);
+	yahoo_packet_hash(pkt, 301, "240");
+	yahoo_packet_hash(pkt, 303, "240");
 
 	yahoo_send_packet(yid, pkt, 0);
 	yahoo_packet_free(pkt);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, 1, yd->user);
-	yahoo_packet_hash(pkt, 7, who);
-	yahoo_packet_hash(pkt, 65, old_group);
-	yahoo_send_packet(yid, pkt, 0);
-	yahoo_packet_free(pkt);
 }
 
 void yahoo_group_rename(int id, const char *old_group, const char *new_group)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt = NULL;
@@ -4571,5 +4108,6 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME, YAHOO_STATUS_AVAILABLE, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME,
+		YPACKET_STATUS_DEFAULT, yd->session_id);
 	yahoo_packet_hash(pkt, 1, yd->user);
 	yahoo_packet_hash(pkt, 65, old_group);
@@ -4580,17 +4118,20 @@
 }
 
-void yahoo_conference_addinvite(int id, const char *from, const char *who, const char *room, const YList *members, const char *msg)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_conference_addinvite(int id, const char *from, const char *who,
+	const char *room, const YList *members, const char *msg)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
-		
+
 	if (!yid)
 		return;
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, 1, (from?from:yd->user));
+	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE,
+		YPACKET_STATUS_DEFAULT, yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, (from ? from : yd->user));
 	yahoo_packet_hash(pkt, 51, who);
 	yahoo_packet_hash(pkt, 57, room);
@@ -4608,17 +4149,20 @@
 }
 
-void yahoo_conference_invite(int id, const char *from, YList *who, const char *room, const char *msg)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_conference_invite(int id, const char *from, YList *who,
+	const char *room, const char *msg)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
-		
+
 	if (!yid)
 		return;
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, 1, (from?from:yd->user));
+	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFINVITE, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, (from ? from : yd->user));
 	yahoo_packet_hash(pkt, 50, yd->user);
 	for (; who; who = who->next) {
@@ -4634,21 +4178,24 @@
 }
 
-void yahoo_conference_logon(int id, const char *from, YList *who, const char *room)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_conference_logon(int id, const char *from, YList *who,
+	const char *room)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
-		
+
 	if (!yid)
 		return;
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGON, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, 1, (from?from:yd->user));
-	for (; who; who = who->next) {
+	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGON, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, (from ? from : yd->user));
+	yahoo_packet_hash(pkt, 3, (from ? from : yd->user));
+	yahoo_packet_hash(pkt, 57, room);
+	for (; who; who = who->next)
 		yahoo_packet_hash(pkt, 3, (char *)who->data);
-	}
-	yahoo_packet_hash(pkt, 57, room);
 
 	yahoo_send_packet(yid, pkt, 0);
@@ -4657,20 +4204,23 @@
 }
 
-void yahoo_conference_decline(int id, const char *from, YList *who, const char *room, const char *msg)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_conference_decline(int id, const char *from, YList *who,
+	const char *room, const char *msg)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
-		
+
 	if (!yid)
 		return;
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFDECLINE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, 1, (from?from:yd->user));
-	for (; who; who = who->next) {
+	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFDECLINE,
+		YPACKET_STATUS_DEFAULT, yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, (from ? from : yd->user));
+	yahoo_packet_hash(pkt, 3, (from ? from : yd->user));
+	for (; who; who = who->next)
 		yahoo_packet_hash(pkt, 3, (char *)who->data);
-	}
 	yahoo_packet_hash(pkt, 57, room);
 	yahoo_packet_hash(pkt, 14, msg);
@@ -4681,20 +4231,24 @@
 }
 
-void yahoo_conference_logoff(int id, const char *from, YList *who, const char *room)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_conference_logoff(int id, const char *from, YList *who,
+	const char *room)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
-		
+
 	if (!yid)
 		return;
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, 1, (from?from:yd->user));
-	for (; who; who = who->next) {
+	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, (from ? from : yd->user));
+	yahoo_packet_hash(pkt, 3, (from ? from : yd->user));
+	for (; who; who = who->next)
 		yahoo_packet_hash(pkt, 3, (char *)who->data);
-	}
+
 	yahoo_packet_hash(pkt, 57, room);
 
@@ -4704,20 +4258,24 @@
 }
 
-void yahoo_conference_message(int id, const char *from, YList *who, const char *room, const char *msg, int utf8)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_conference_message(int id, const char *from, YList *who,
+	const char *room, const char *msg, int utf8)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
-		
+
 	if (!yid)
 		return;
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, 1, (from?from:yd->user));
-	for (; who; who = who->next) {
+	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, (from ? from : yd->user));
+	yahoo_packet_hash(pkt, 53, (from ? from : yd->user));
+	for (; who; who = who->next)
 		yahoo_packet_hash(pkt, 53, (char *)who->data);
-	}
+
 	yahoo_packet_hash(pkt, 57, room);
 	yahoo_packet_hash(pkt, 14, msg);
@@ -4746,7 +4304,10 @@
 
 	if (chatroomid == 0) {
-		snprintf(url, 1024, "http://insider.msg.yahoo.com/ycontent/?chatcat=0");
+		snprintf(url, 1024,
+			"http://insider.msg.yahoo.com/ycontent/?chatcat=0");
 	} else {
-		snprintf(url, 1024, "http://insider.msg.yahoo.com/ycontent/?chatroom_%d=0",chatroomid);
+		snprintf(url, 1024,
+			"http://insider.msg.yahoo.com/ycontent/?chatroom_%d=0",
+			chatroomid);
 	}
 
@@ -4755,13 +4316,16 @@
 	inputs = y_list_prepend(inputs, yid);
 
-	yahoo_http_get(yid->yd->client_id, url, buff, _yahoo_http_connected, yid);
-}
-
-void yahoo_chat_logon(int id, const char *from, const char *room, const char *roomid)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	yahoo_http_get(yid->yd->client_id, url, buff, 0, 0,
+		_yahoo_http_connected, yid);
+}
+
+void yahoo_chat_logon(int id, const char *from, const char *room,
+	const char *roomid)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
-		
+
 	if (!yid)
 		return;
@@ -4769,7 +4333,8 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, 1, (from?from:yd->user));
+	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, (from ? from : yd->user));
 	yahoo_packet_hash(pkt, 109, yd->user);
 	yahoo_packet_hash(pkt, 6, "abcde");
@@ -4779,10 +4344,11 @@
 	yahoo_packet_free(pkt);
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, 1, (from?from:yd->user));
+	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, (from ? from : yd->user));
 	yahoo_packet_hash(pkt, 104, room);
 	yahoo_packet_hash(pkt, 129, roomid);
-	yahoo_packet_hash(pkt, 62, "2"); /* ??? */
+	yahoo_packet_hash(pkt, 62, "2");	/* ??? */
 
 	yahoo_send_packet(yid, pkt, 0);
@@ -4791,12 +4357,13 @@
 }
 
-
-void  yahoo_chat_message(int id, const char *from, const char *room, const char *msg, const int msgtype, const int utf8)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_chat_message(int id, const char *from, const char *room,
+	const char *msg, const int msgtype, const int utf8)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
 	char buf[2];
-		
+
 	if (!yid)
 		return;
@@ -4804,10 +4371,11 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, 1, (from?from:yd->user));
+	pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, (from ? from : yd->user));
 	yahoo_packet_hash(pkt, 104, room);
 	yahoo_packet_hash(pkt, 117, msg);
-	
+
 	snprintf(buf, sizeof(buf), "%d", msgtype);
 	yahoo_packet_hash(pkt, 124, buf);
@@ -4821,11 +4389,11 @@
 }
 
-
 void yahoo_chat_logoff(int id, const char *from)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
-		
+
 	if (!yid)
 		return;
@@ -4833,7 +4401,8 @@
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, 1, (from?from:yd->user));
+	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, (from ? from : yd->user));
 
 	yahoo_send_packet(yid, pkt, 0);
@@ -4844,14 +4413,16 @@
 void yahoo_buddyicon_request(int id, const char *who)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
 
-	if ( !yid )
+	if (!yid)
 		return;
 
 	yd = yid->yd;
-	
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0);
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YPACKET_STATUS_DEFAULT,
+		0);
 	yahoo_packet_hash(pkt, 4, yd->user);
 	yahoo_packet_hash(pkt, 5, who);
@@ -4862,12 +4433,14 @@
 }
 
-void yahoo_send_picture_info(int id, const char *who, const char *url, int checksum)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+void yahoo_send_picture_info(int id, const char *who, const char *url,
+	int checksum)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
 	char checksum_str[10];
 
-	if ( !yid )
+	if (!yid)
 		return;
 
@@ -4876,5 +4449,6 @@
 	snprintf(checksum_str, sizeof(checksum_str), "%d", checksum);
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YPACKET_STATUS_DEFAULT,
+		0);
 	yahoo_packet_hash(pkt, 1, yd->user);
 	yahoo_packet_hash(pkt, 4, yd->user);
@@ -4890,10 +4464,11 @@
 void yahoo_send_picture_update(int id, const char *who, int type)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
 	char type_str[10];
 
-	if ( !yid )
+	if (!yid)
 		return;
 
@@ -4902,5 +4477,6 @@
 	snprintf(type_str, sizeof(type_str), "%d", type);
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE, YAHOO_STATUS_AVAILABLE, 0);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE,
+		YPACKET_STATUS_DEFAULT, 0);
 	yahoo_packet_hash(pkt, 1, yd->user);
 	yahoo_packet_hash(pkt, 5, who);
@@ -4913,19 +4489,21 @@
 void yahoo_send_picture_checksum(int id, const char *who, int checksum)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
 	char checksum_str[10];
 
-	if ( !yid )
+	if (!yid)
 		return;
 
 	yd = yid->yd;
-	
+
 	snprintf(checksum_str, sizeof(checksum_str), "%d", checksum);
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, 0);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM,
+		YPACKET_STATUS_DEFAULT, 0);
 	yahoo_packet_hash(pkt, 1, yd->user);
-	if ( who != 0 )
+	if (who != 0)
 		yahoo_packet_hash(pkt, 5, who);
 	yahoo_packet_hash(pkt, 192, checksum_str);
@@ -4938,5 +4516,6 @@
 void yahoo_webcam_close_feed(int id, const char *who)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_webcam_user(id, who);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_webcam_user(id, who);
 
 	if (yid)
@@ -4946,8 +4525,9 @@
 void yahoo_webcam_get_feed(int id, const char *who)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_data *yd;
 	struct yahoo_packet *pkt;
-		
+
 	if (!yid)
 		return;
@@ -4960,9 +4540,10 @@
 	 * The queue is popped in yahoo_process_webcam_key
 	 */
-	webcam_queue = y_list_append(webcam_queue, who?strdup(who):NULL);
+	webcam_queue = y_list_append(webcam_queue, who ? strdup(who) : NULL);
 
 	yd = yid->yd;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_WEBCAM, YAHOO_STATUS_AVAILABLE, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_WEBCAM, YPACKET_STATUS_DEFAULT,
+		yd->session_id);
 
 	yahoo_packet_hash(pkt, 1, yd->user);
@@ -4974,7 +4555,9 @@
 }
 
-void yahoo_webcam_send_image(int id, unsigned char *image, unsigned int length, unsigned int timestamp)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM);
+void yahoo_webcam_send_image(int id, unsigned char *image, unsigned int length,
+	unsigned int timestamp)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM);
 	unsigned char *packet;
 	unsigned char header_len = 13;
@@ -4988,8 +4571,8 @@
 	packet[pos++] = header_len;
 	packet[pos++] = 0;
-	packet[pos++] = 5; /* version byte?? */
+	packet[pos++] = 5;	/* version byte?? */
 	packet[pos++] = 0;
 	pos += yahoo_put32(packet + pos, length);
-	packet[pos++] = 2; /* packet type, image */
+	packet[pos++] = 2;	/* packet type, image */
 	pos += yahoo_put32(packet + pos, timestamp);
 	yahoo_add_to_send_queue(yid, packet, header_len);
@@ -5000,7 +4583,8 @@
 }
 
-void yahoo_webcam_accept_viewer(int id, const char* who, int accept)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM);
+void yahoo_webcam_accept_viewer(int id, const char *who, int accept)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM);
 	char *packet = NULL;
 	char *data = NULL;
@@ -5013,5 +4597,5 @@
 
 	data = strdup("u=");
-	data = y_string_append(data, (char*)who);
+	data = y_string_append(data, (char *)who);
 	data = y_string_append(data, "\r\n");
 	len = strlen(data);
@@ -5020,8 +4604,8 @@
 	packet[pos++] = header_len;
 	packet[pos++] = 0;
-	packet[pos++] = 5; /* version byte?? */
+	packet[pos++] = 5;	/* version byte?? */
 	packet[pos++] = 0;
 	pos += yahoo_put32(packet + pos, len);
-	packet[pos++] = 0; /* packet type */
+	packet[pos++] = 0;	/* packet type */
 	pos += yahoo_put32(packet + pos, accept);
 	memcpy(packet + pos, data, len);
@@ -5033,11 +4617,13 @@
 void yahoo_webcam_invite(int id, const char *who)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_packet *pkt;
-		
+
 	if (!yid)
 		return;
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_NOTIFY, yid->yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YPACKET_STATUS_NOTIFY,
+		yid->yd->session_id);
 
 	yahoo_packet_hash(pkt, 49, "WEBCAMINVITE");
@@ -5051,5 +4637,6 @@
 }
 
-static void yahoo_search_internal(int id, int t, const char *text, int g, int ar, int photo, int yahoo_only, int startpos, int total)
+static void yahoo_search_internal(int id, int t, const char *text, int g,
+	int ar, int photo, int yahoo_only, int startpos, int total)
 {
 	struct yahoo_data *yd = find_conn_by_id(id);
@@ -5067,9 +4654,10 @@
 
 	/*
-	age range
-	.ar=1 - 13-18, 2 - 18-25, 3 - 25-35, 4 - 35-50, 5 - 50-70, 6 - 70+
-	*/
-
-	snprintf(buff, sizeof(buff), "&.sq=%%20&.tt=%d&.ss=%d", total, startpos);
+	   age range
+	   .ar=1 - 13-18, 2 - 18-25, 3 - 25-35, 4 - 35-50, 5 - 50-70, 6 - 70+
+	 */
+
+	snprintf(buff, sizeof(buff), "&.sq=%%20&.tt=%d&.ss=%d", total,
+		startpos);
 
 	ctext = strdup(text);
@@ -5077,7 +4665,8 @@
 		*p = '+';
 
-	snprintf(url, 1024, "http://members.yahoo.com/interests?.oc=m&.kw=%s&.sb=%d&.g=%d&.ar=0%s%s%s",
-			ctext, t, g, photo ? "&.p=y" : "", yahoo_only ? "&.pg=y" : "",
-			startpos ? buff : "");
+	snprintf(url, 1024,
+		"http://members.yahoo.com/interests?.oc=m&.kw=%s&.sb=%d&.g=%d&.ar=0%s%s%s",
+		ctext, t, g, photo ? "&.p=y" : "", yahoo_only ? "&.pg=y" : "",
+		startpos ? buff : "");
 
 	FREE(ctext);
@@ -5086,11 +4675,14 @@
 
 	inputs = y_list_prepend(inputs, yid);
-	yahoo_http_get(yid->yd->client_id, url, buff, _yahoo_http_connected, yid);
-}
-
-void yahoo_search(int id, enum yahoo_search_type t, const char *text, enum yahoo_search_gender g, enum yahoo_search_agerange ar, 
-		int photo, int yahoo_only)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	yahoo_http_get(yid->yd->client_id, url, buff, 0, 0,
+		_yahoo_http_connected, yid);
+}
+
+void yahoo_search(int id, enum yahoo_search_type t, const char *text,
+	enum yahoo_search_gender g, enum yahoo_search_agerange ar, int photo,
+	int yahoo_only)
+{
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_search_state *yss;
 
@@ -5116,5 +4708,6 @@
 void yahoo_search_again(int id, int start)
 {
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	struct yahoo_input_data *yid =
+		find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
 	struct yahoo_search_state *yss;
 
@@ -5127,27 +4720,128 @@
 		start = yss->lsearch_nstart + yss->lsearch_nfound;
 
-	yahoo_search_internal(id, yss->lsearch_type, yss->lsearch_text, 
-			yss->lsearch_gender, yss->lsearch_agerange, 
-			yss->lsearch_photo, yss->lsearch_yahoo_only, 
-			start, yss->lsearch_ntotal);
-}
+	yahoo_search_internal(id, yss->lsearch_type, yss->lsearch_text,
+		yss->lsearch_gender, yss->lsearch_agerange,
+		yss->lsearch_photo, yss->lsearch_yahoo_only,
+		start, yss->lsearch_ntotal);
+}
+
+void yahoo_send_picture(int id, const char *name, unsigned long size,
+	yahoo_get_fd_callback callback, void *data)
+{
+	/* Not Implemented */
+}
+
+/* File Transfer */
+static YList *active_file_transfers = NULL;
+
+enum {
+	FT_STATE_HEAD = 1,
+	FT_STATE_RECV,
+	FT_STATE_RECV_START,
+	FT_STATE_SEND
+};
 
 struct send_file_data {
-	struct yahoo_packet *pkt;
+	int client_id;
+	char *id;
+	char *who;
+	char *filename;
+	char *ip_addr;
+	char *token;
+	int size;
+
+	struct yahoo_input_data *yid;
+	int state;
+
 	yahoo_get_fd_callback callback;
-	void *user_data;
+	void *data;
 };
 
-static void _yahoo_send_picture_connected(int id, int fd, int error, void *data)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_FT);
+static char *yahoo_get_random(void)
+{
+	int i = 0;
+	int r = 0;
+	int c = 0;
+	char out[25];
+
+	out[24] = '\0';
+	out[23] = '$';
+	out[22] = '$';
+	
+	for (i = 0; i < 22; i++) {
+		if(r == 0)
+			r = rand();
+
+		c = r%61;
+
+		if(c<26)
+			out[i] = c + 'a';
+		else if (c<52)
+			out[i] = c - 26 + 'A';
+		else
+			out[i] = c - 52 + '0';
+
+		r /= 61;
+	}
+
+	return strdup(out);
+}
+
+static int _are_same_id(const void *sfd1, const void *id)
+{
+	return strcmp(((struct send_file_data *)sfd1)->id, (char *)id);
+}
+
+static int _are_same_yid(const void *sfd1, const void *yid)
+{
+	if(((struct send_file_data *)sfd1)->yid == yid)
+		return 0;
+	else
+		return 1;
+}
+
+static struct send_file_data *yahoo_get_active_transfer(char *id)
+{
+	YList *l = y_list_find_custom(active_file_transfers, id,
+		_are_same_id);
+
+	if(l)
+		return (struct send_file_data *)l->data;
+	
+	return NULL;
+}
+
+static struct send_file_data *yahoo_get_active_transfer_with_yid(void *yid)
+{
+	YList *l = y_list_find_custom(active_file_transfers, yid,
+		_are_same_yid);
+
+	if(l)
+		return (struct send_file_data *)l->data;
+	
+	return NULL;
+}
+
+static void yahoo_add_active_transfer(struct send_file_data *sfd)
+{
+	active_file_transfers = y_list_prepend(active_file_transfers, sfd);
+}
+
+static void yahoo_remove_active_transfer(struct send_file_data *sfd)
+{
+	active_file_transfers = y_list_remove(active_file_transfers, sfd);
+	free(sfd->id);
+	free(sfd->who);
+	free(sfd->filename);
+	free(sfd->ip_addr);
+	FREE(sfd);
+}
+
+static void _yahoo_ft_upload_connected(int id, void *fd, int error, void *data)
+{
 	struct send_file_data *sfd = data;
-	struct yahoo_packet *pkt = sfd->pkt;
-	unsigned char buff[1024];
-
-	if (fd <= 0) {
-		sfd->callback(id, fd, error, sfd->user_data);
-		FREE(sfd);
-		yahoo_packet_free(pkt);
+	struct yahoo_input_data *yid = sfd->yid;
+
+	if (!fd) {
 		inputs = y_list_remove(inputs, yid);
 		FREE(yid);
@@ -5155,171 +4849,513 @@
 	}
 
+	sfd->callback(id, fd, error, sfd->data);
+
 	yid->fd = fd;
-	yahoo_send_packet(yid, pkt, 8);
+	yid->read_tag =
+		YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd,
+		YAHOO_INPUT_READ, yid);
+}
+
+static void yahoo_file_transfer_upload(struct yahoo_data *yd,
+	struct send_file_data *sfd)
+{
+	char url[256];
+	char buff[4096];
+	char *sender_enc = NULL, *recv_enc = NULL, *token_enc = NULL;
+
+	struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1);
+
+	yid->yd = yd;
+	yid->type = YAHOO_CONNECTION_FT;
+
+	inputs = y_list_prepend(inputs, yid);
+	sfd->yid = yid;
+	sfd->state = FT_STATE_SEND;
+
+	token_enc = yahoo_urlencode(sfd->token);
+	sender_enc = yahoo_urlencode(yd->user);
+	recv_enc = yahoo_urlencode(sfd->who);
+
+	snprintf(url, sizeof(url), 
+		"http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr,
+		token_enc, sender_enc, recv_enc);
+
+	snprintf(buff, sizeof(buff), "T=%s; Y=%s", yd->cookie_t, yd->cookie_y);
+
+	yahoo_http_post(yd->client_id, url, buff, sfd->size,
+		_yahoo_ft_upload_connected, sfd);
+
+	FREE(token_enc);
+	FREE(sender_enc);
+	FREE(recv_enc);
+}
+
+static void yahoo_init_ft_recv(struct yahoo_data *yd,
+	struct send_file_data *sfd)
+{
+	char url[256];
+	char buff[1024];
+	char *sender_enc = NULL, *recv_enc = NULL, *token_enc = NULL;
+
+	struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1);
+
+	yid->yd = yd;
+	yid->type = YAHOO_CONNECTION_FT;
+
+	inputs = y_list_prepend(inputs, yid);
+	sfd->yid = yid;
+	sfd->state = FT_STATE_HEAD;
+
+	token_enc = yahoo_urlencode(sfd->token);
+	sender_enc = yahoo_urlencode(sfd->who);
+	recv_enc = yahoo_urlencode(yd->user);
+
+	snprintf(url, sizeof(url), 
+		"http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr,
+		token_enc, sender_enc, recv_enc);
+
+	snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
+
+	yahoo_http_head(yid->yd->client_id, url, buff, 0, NULL,
+		_yahoo_http_connected, yid);
+
+	FREE(token_enc);
+	FREE(sender_enc);
+	FREE(recv_enc);
+}
+
+static void yahoo_file_transfer_accept(struct yahoo_input_data *yid,
+	struct send_file_data *sfd)
+{
+	struct yahoo_packet *pkt;
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFERACCEPT,
+		YPACKET_STATUS_DEFAULT, yid->yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, yid->yd->user);
+	yahoo_packet_hash(pkt, 5, sfd->who);
+	yahoo_packet_hash(pkt, 265, sfd->id);
+	yahoo_packet_hash(pkt, 27, sfd->filename);
+	yahoo_packet_hash(pkt, 249, "3");
+	yahoo_packet_hash(pkt, 251, sfd->token);
+
+	yahoo_send_packet(yid, pkt, 0);
+
 	yahoo_packet_free(pkt);
 
-	snprintf((char *)buff, sizeof(buff), "29");
-	buff[2] = 0xc0;
-	buff[3] = 0x80;
-	
-	write(yid->fd, buff, 4);
-
-	/*	YAHOO_CALLBACK(ext_yahoo_add_handler) (nyd->fd, YAHOO_INPUT_READ); */
-
-	sfd->callback(id, fd, error, sfd->user_data);
-	FREE(sfd);
-	inputs = y_list_remove(inputs, yid);
-	/*
-	while (yahoo_tcp_readline(buff, sizeof(buff), nyd->fd) > 0) {
-	if (!strcmp(buff, ""))
-	break;
-}
-
-	*/
-	yahoo_input_close(yid);
-}
-
-void yahoo_send_picture(int id, const char *name, unsigned long size,
-							yahoo_get_fd_callback callback, void *data)
-{
-	struct yahoo_data *yd = find_conn_by_id(id);
+	yahoo_init_ft_recv(yid->yd, sfd);
+}
+
+static void yahoo_process_filetransferaccept(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
+{
+	YList *l;
+	struct send_file_data *sfd;
+	char *who = NULL;
+	char *filename = NULL;
+	char *id = NULL;
+	char *token = NULL;
+
+	for (l = pkt->hash; l; l = l->next) {
+		struct yahoo_pair *pair = l->data;
+		switch (pair->key) {
+		case 4:
+			who = pair->value;
+			break;
+		case 5:
+			/* Me... don't care */
+			break;
+		case 249:
+			break;
+		case 265:
+			id = pair->value;
+			break;
+		case 251:
+			token = pair->value;
+			break;
+		case 27:
+			filename = pair->value;
+			break;
+		}
+	}
+
+	sfd = yahoo_get_active_transfer(id);
+
+	if (sfd) {
+		sfd->token = strdup(token);
+
+		yahoo_file_transfer_upload(yid->yd, sfd);
+	}
+	else {
+		YAHOO_CALLBACK(ext_yahoo_file_transfer_done)
+			(yid->yd->client_id, YAHOO_FILE_TRANSFER_UNKNOWN,
+			sfd->data);
+
+		yahoo_remove_active_transfer(sfd);
+	}
+}
+
+static void yahoo_process_filetransferinfo(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
+{
+	YList *l;
+	char *who = NULL;
+	char *filename = NULL;
+	char *id = NULL;
+	char *token = NULL;
+	char *ip_addr = NULL;
+
+	struct send_file_data *sfd;
+
+	for (l = pkt->hash; l; l = l->next) {
+		struct yahoo_pair *pair = l->data;
+		switch (pair->key) {
+		case 1:
+		case 4:
+			who = pair->value;
+			break;
+		case 5:
+			/* Me... don't care */
+			break;
+		case 249:
+			break;
+		case 265:
+			id = pair->value;
+			break;
+		case 250:
+			ip_addr = pair->value;
+			break;
+		case 251:
+			token = pair->value;
+			break;
+		case 27:
+			filename = pair->value;
+			break;
+		}
+	}
+
+	sfd = yahoo_get_active_transfer(id);
+
+	if (sfd) {
+		sfd->token = strdup(token);
+		sfd->ip_addr = strdup(ip_addr);
+
+		yahoo_file_transfer_accept(yid, sfd);
+	}
+	else {
+		YAHOO_CALLBACK(ext_yahoo_file_transfer_done)
+			(yid->yd->client_id, YAHOO_FILE_TRANSFER_UNKNOWN,
+			sfd->data);
+
+		yahoo_remove_active_transfer(sfd);
+	}
+}
+
+static void yahoo_send_filetransferinfo(struct yahoo_data *yd,
+	struct send_file_data *sfd)
+{
 	struct yahoo_input_data *yid;
-	struct yahoo_server_settings *yss;
+	struct yahoo_packet *pkt;
+
+	yid = find_input_by_id_and_type(yd->client_id, YAHOO_CONNECTION_PAGER);
+	sfd->ip_addr = YAHOO_CALLBACK(ext_yahoo_get_ip_addr)("relay.yahoo.com");
+
+	if (!sfd->ip_addr) {
+		YAHOO_CALLBACK(ext_yahoo_file_transfer_done)
+			(yd->client_id, YAHOO_FILE_TRANSFER_RELAY, sfd->data);
+
+		yahoo_remove_active_transfer(sfd);
+
+		return;
+	}
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFERINFO,
+		YPACKET_STATUS_DEFAULT, yd->session_id);
+
+	yahoo_packet_hash(pkt, 1, yd->user);
+	yahoo_packet_hash(pkt, 5, sfd->who);
+	yahoo_packet_hash(pkt, 265, sfd->id);
+	yahoo_packet_hash(pkt, 27, sfd->filename);
+	yahoo_packet_hash(pkt, 249, "3");
+	yahoo_packet_hash(pkt, 250, sfd->ip_addr);
+
+	yahoo_send_packet(yid, pkt, 0);
+
+	yahoo_packet_free(pkt);
+}
+
+static void yahoo_process_filetransfer(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
+{
+	YList *l;
+	char *who = NULL;
+	char *filename = NULL;
+	char *msg = NULL;
+	char *id = NULL;
+	int action = 0;
+	int size = 0;
+	struct yahoo_data *yd = yid->yd;
+
+	struct send_file_data *sfd;
+
+	for (l = pkt->hash; l; l = l->next) {
+		struct yahoo_pair *pair = l->data;
+		switch (pair->key) {
+		case 4:
+			who = pair->value;
+			break;
+		case 5:
+			/* Me... don't care */
+			break;
+		case 222:
+			action = atoi(pair->value);
+			break;
+		case 265:
+			id = pair->value;
+			break;
+		case 266: /* Don't know */
+			break;
+		case 302: /* Start Data? */
+			break;
+		case 300:
+			break;
+		case 27:
+			filename = pair->value;
+			break;
+		case 28:
+			size = atoi(pair->value);
+			break;
+		case 14:
+			msg = pair->value;
+		case 301: /* End Data? */
+			break;
+		case 303:
+			break;
+
+		}
+	}
+
+	if (action == YAHOO_FILE_TRANSFER_INIT) {
+		/* Received a FT request from buddy */
+		sfd = y_new0(struct send_file_data, 1);
+        
+		sfd->client_id = yd->client_id;
+		sfd->id = strdup(id);
+		sfd->who = strdup(who);
+		sfd->filename = strdup(filename);
+		sfd->size = size;
+        
+		yahoo_add_active_transfer(sfd);
+
+		YAHOO_CALLBACK(ext_yahoo_got_file) (yd->client_id, yd->user,
+			who, msg, filename, size, sfd->id);
+	}
+	else {
+		/* Response to our request */
+		sfd = yahoo_get_active_transfer(id);
+
+		if (sfd && action == YAHOO_FILE_TRANSFER_ACCEPT) {
+			yahoo_send_filetransferinfo(yd, sfd);
+		}
+		else if (!sfd || action == YAHOO_FILE_TRANSFER_REJECT) {
+			YAHOO_CALLBACK(ext_yahoo_file_transfer_done)
+				(yd->client_id, YAHOO_FILE_TRANSFER_REJECT,
+				sfd->data);
+
+			yahoo_remove_active_transfer(sfd);
+		}
+	}
+}
+
+void yahoo_send_file(int id, const char *who, const char *msg,
+	const char *name, unsigned long size,
+	yahoo_get_fd_callback callback, void *data)
+{
 	struct yahoo_packet *pkt = NULL;
 	char size_str[10];
-	char expire_str[10];
-	long content_length = 0;
-	unsigned char buff[1024];
-	char url[255];
+	struct yahoo_input_data *yid;
+	struct yahoo_data *yd;
 	struct send_file_data *sfd;
+	
+	yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
+	yd = find_conn_by_id(id);
+	sfd = y_new0(struct send_file_data, 1);
+
+	sfd->client_id = id;
+	sfd->id = yahoo_get_random();
+	sfd->who = strdup(who);
+	sfd->filename = strdup(name);
+	sfd->size = size;
+	sfd->callback = callback;
+	sfd->data = data;
+
+	yahoo_add_active_transfer(sfd);
 
 	if (!yd)
 		return;
 
-	yss = yd->server_settings;
-
-	yid = y_new0(struct yahoo_input_data, 1);
-	yid->yd = yd;
-	yid->type = YAHOO_CONNECTION_FT;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPLOAD, YAHOO_STATUS_AVAILABLE, yd->session_id);
+	pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER,
+		YPACKET_STATUS_DEFAULT, yd->session_id);
 
 	snprintf(size_str, sizeof(size_str), "%ld", size);
-	snprintf(expire_str, sizeof(expire_str), "%ld", (long)604800);
-
-	yahoo_packet_hash(pkt, 0, yd->user);
+
 	yahoo_packet_hash(pkt, 1, yd->user);
-	yahoo_packet_hash(pkt, 14, "");
+	yahoo_packet_hash(pkt, 5, who);
+	yahoo_packet_hash(pkt, 265, sfd->id);
+	yahoo_packet_hash(pkt, 222, "1");
+	yahoo_packet_hash(pkt, 266, "1");
+	yahoo_packet_hash(pkt, 302, "268");
+	yahoo_packet_hash(pkt, 300, "268");
 	yahoo_packet_hash(pkt, 27, name);
 	yahoo_packet_hash(pkt, 28, size_str);
-	yahoo_packet_hash(pkt, 38, expire_str);
+	yahoo_packet_hash(pkt, 301, "268");
+	yahoo_packet_hash(pkt, 303, "268");
+
+	yahoo_send_packet(yid, pkt, 0);
+
+	yahoo_packet_free(pkt);
+}
+
+void yahoo_send_file_transfer_response(int client_id, int response, char *id, void *data)
+{
+	struct yahoo_packet *pkt = NULL;
+	char resp[2];
+	struct yahoo_input_data *yid;
 	
-
-	content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt);
-
-	snprintf(url, sizeof(url), "http://%s:%d/notifyft",
-				yss->filetransfer_host, yss->filetransfer_port);
-	snprintf((char *)buff, sizeof(buff), "Y=%s; T=%s",
-				 yd->cookie_y, yd->cookie_t);
-	inputs = y_list_prepend(inputs, yid);
-
-	sfd = y_new0(struct send_file_data, 1);
-	sfd->pkt = pkt;
-	sfd->callback = callback;
-	sfd->user_data = data;
-	yahoo_http_post(yid->yd->client_id, url, (char *)buff, content_length+4+size,
-						_yahoo_send_picture_connected, sfd);
-}
-
-static void _yahoo_send_file_connected(int id, int fd, int error, void *data)
-{
-	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_FT);
-	struct send_file_data *sfd = data;
-	struct yahoo_packet *pkt = sfd->pkt;
-	unsigned char buff[1024];
-
-	if (fd <= 0) {
-		sfd->callback(id, fd, error, sfd->user_data);
-		FREE(sfd);
-		yahoo_packet_free(pkt);
-		inputs = y_list_remove(inputs, yid);
-		FREE(yid);
-		return;
-	}
-
-	yid->fd = fd;
-	yahoo_send_packet(yid, pkt, 8);
+	struct send_file_data *sfd = yahoo_get_active_transfer(id);
+
+	sfd->data = data;
+
+	yid = find_input_by_id_and_type(client_id, YAHOO_CONNECTION_PAGER);
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER,
+		YPACKET_STATUS_DEFAULT, yid->yd->session_id);
+
+	snprintf(resp, sizeof(resp), "%d", response);
+
+	yahoo_packet_hash(pkt, 1, yid->yd->user);
+	yahoo_packet_hash(pkt, 5, sfd->who);
+	yahoo_packet_hash(pkt, 265, sfd->id);
+	yahoo_packet_hash(pkt, 222, resp);
+
+	yahoo_send_packet(yid, pkt, 0);
+
 	yahoo_packet_free(pkt);
 
-	snprintf((char *)buff, sizeof(buff), "29");
-	buff[2] = 0xc0;
-	buff[3] = 0x80;
+	if(response == YAHOO_FILE_TRANSFER_REJECT)
+		yahoo_remove_active_transfer(sfd);
+}
+
+static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over)
+{
+	struct send_file_data *sfd;
+	struct yahoo_data *yd = yid->yd;
 	
-	write(yid->fd, buff, 4);
-
-/*	YAHOO_CALLBACK(ext_yahoo_add_handler) (nyd->fd, YAHOO_INPUT_READ); */
-
-	sfd->callback(id, fd, error, sfd->user_data);
-	FREE(sfd);
-	inputs = y_list_remove(inputs, yid);
-	/*
-	while (yahoo_tcp_readline(buff, sizeof(buff), nyd->fd) > 0) {
-		if (!strcmp(buff, ""))
-			break;
-	}
-
-	*/
-	yahoo_input_close(yid);
-}
-
-void yahoo_send_file(int id, const char *who, const char *msg, 
-		const char *name, unsigned long size, 
-		yahoo_get_fd_callback callback, void *data)
-{
-	struct yahoo_data *yd = find_conn_by_id(id);
-	struct yahoo_input_data *yid;
-	struct yahoo_server_settings *yss;
-	struct yahoo_packet *pkt = NULL;
-	char size_str[10];
-	long content_length = 0;
-	unsigned char buff[1024];
-	char url[255];
-	struct send_file_data *sfd;
-
-	if (!yd)
-		return;
-
-	yss = yd->server_settings;
-
-	yid = y_new0(struct yahoo_input_data, 1);
-	yid->yd = yd;
-	yid->type = YAHOO_CONNECTION_FT;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	snprintf(size_str, sizeof(size_str), "%ld", size);
-
-	yahoo_packet_hash(pkt, 0, yd->user);
-	yahoo_packet_hash(pkt, 5, who);
-	yahoo_packet_hash(pkt, 14, msg);
-	yahoo_packet_hash(pkt, 27, name);
-	yahoo_packet_hash(pkt, 28, size_str);
-
-	content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt);
-
-	snprintf(url, sizeof(url), "http://%s:%d/notifyft", 
-			yss->filetransfer_host, yss->filetransfer_port);
-	snprintf((char *)buff, sizeof(buff), "Y=%s; T=%s",
-			yd->cookie_y, yd->cookie_t);
-	inputs = y_list_prepend(inputs, yid);
-
-	sfd = y_new0(struct send_file_data, 1);
-	sfd->pkt = pkt;
-	sfd->callback = callback;
-	sfd->user_data = data;
-	yahoo_http_post(yid->yd->client_id, url, (char *)buff, content_length+4+size,
-			_yahoo_send_file_connected, sfd);
-}
-
+	sfd = yahoo_get_active_transfer_with_yid(yid);
+
+	if (!sfd) {
+		LOG(("Something funny happened. yid %p has no sfd.\n", yid));
+		return;
+	}
+
+	/* 
+	 * We want to handle only the complete data with HEAD since we don't
+	 * want a situation where both the GET and HEAD are active.
+	 * With SEND, we really can't do much with partial response
+	 */
+	if ((sfd->state == FT_STATE_HEAD || sfd->state == FT_STATE_SEND) 
+			&& !over)
+		return;
+
+	if (sfd->state == FT_STATE_HEAD) {
+		/* Do a GET */
+		char url[256];
+		char buff[1024];
+		char *sender_enc = NULL, *recv_enc = NULL, *token_enc = NULL;
+
+		struct yahoo_input_data *yid_ft = 
+			y_new0(struct yahoo_input_data, 1);
+        
+		yid_ft->yd = yid->yd;
+		yid_ft->type = YAHOO_CONNECTION_FT;
+        
+		inputs = y_list_prepend(inputs, yid_ft);
+		sfd->yid = yid_ft;
+		sfd->state = FT_STATE_RECV;
+
+		token_enc = yahoo_urlencode(sfd->token);
+		sender_enc = yahoo_urlencode(sfd->who);
+		recv_enc = yahoo_urlencode(yd->user);
+        
+		snprintf(url, sizeof(url), 
+			"http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr,
+			token_enc, sender_enc, recv_enc);
+
+		snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y,
+			yd->cookie_t);
+
+
+		yahoo_http_get(yd->client_id, url, buff, 1, 1,
+			_yahoo_http_connected, yid_ft);
+
+		FREE(token_enc);
+		FREE(sender_enc);
+		FREE(recv_enc);
+	}
+	else if (sfd->state == FT_STATE_RECV || 
+		sfd->state == FT_STATE_RECV_START) {
+
+		unsigned char *data_begin = NULL;
+
+		if (yid->rxlen == 0)
+			yahoo_remove_active_transfer(sfd);
+
+		if (sfd->state != FT_STATE_RECV_START &&
+			(data_begin = 
+				(unsigned char *)strstr((char *)yid->rxqueue,
+				"\r\n\r\n"))) {
+
+			sfd->state = FT_STATE_RECV_START;
+
+			yid->rxlen -= 4+(data_begin-yid->rxqueue)/sizeof(char);
+			data_begin += 4;
+
+			if (yid->rxlen > 0)
+				YAHOO_CALLBACK(ext_yahoo_got_ft_data) 
+					(yd->client_id, data_begin,
+					yid->rxlen, sfd->data);
+		}
+		else if (sfd->state == FT_STATE_RECV_START)
+			YAHOO_CALLBACK(ext_yahoo_got_ft_data) (yd->client_id,
+				yid->rxqueue, yid->rxlen, sfd->data);
+
+		FREE(yid->rxqueue);
+		yid->rxqueue = NULL;
+		yid->rxlen = 0;
+	}
+	else if (sfd->state == FT_STATE_SEND) {
+		/* Sent file completed */
+		int len = 0;
+		char *off = strstr((char *)yid->rxqueue, "Content-Length: ");
+
+		if (off) {
+			off += 16;
+			len = atoi(off);
+		}
+
+		if (len < sfd->size)
+			YAHOO_CALLBACK(ext_yahoo_file_transfer_done)
+				(yd->client_id,
+				YAHOO_FILE_TRANSFER_FAILED, sfd->data);
+		else
+			YAHOO_CALLBACK(ext_yahoo_file_transfer_done)
+				(yd->client_id,
+				YAHOO_FILE_TRANSFER_DONE, sfd->data);
+
+		yahoo_remove_active_transfer(sfd);
+	}
+}
+
+/* End File Transfer */
 
 enum yahoo_status yahoo_current_status(int id)
@@ -5362,4 +5398,6 @@
 	if (!strncasecmp(which, "y", 1))
 		return yd->cookie_y;
+	if (!strncasecmp(which, "b", 1))
+		return yd->cookie_b;
 	if (!strncasecmp(which, "t", 1))
 		return yd->cookie_t;
@@ -5371,17 +5409,6 @@
 }
 
-void yahoo_get_url_handle(int id, const char *url, 
-		yahoo_get_url_handle_callback callback, void *data)
-{
-	struct yahoo_data *yd = find_conn_by_id(id);
-	if (!yd)
-		return;
-
-	yahoo_get_url_fd(id, url, yd, callback, data);
-}
-
-const char *yahoo_get_profile_url( void )
+const char *yahoo_get_profile_url(void)
 {
 	return profile_url;
 }
-
Index: protocols/yahoo/yahoo.c
===================================================================
--- protocols/yahoo/yahoo.c	(revision c36f73bd317dd55d7e70275a6425faa4be7bfd8c)
+++ protocols/yahoo/yahoo.c	(revision 9034ba002b8945aee0f905b928bb0f60da9afe9f)
@@ -2,5 +2,5 @@
  * libyahoo2 wrapper to BitlBee
  *
- * Mostly Copyright 2004 Wilmer van der Gaast <wilmer@gaast.net>
+ * Mostly Copyright 2004-2010 Wilmer van der Gaast <wilmer@gaast.net>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -339,14 +339,18 @@
 static void byahoo_auth_allow( struct im_connection *ic, const char *who )
 {
+	/*
 	struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
 	
 	yahoo_accept_buddy_ymsg13( yd->y2_id, NULL, who );
+	*/
 }
 
 static void byahoo_auth_deny( struct im_connection *ic, const char *who )
 {
+	/*
 	struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
 	
 	yahoo_reject_buddy_ymsg13( yd->y2_id, NULL, who, NULL );
+	*/
 }
 
@@ -421,5 +425,5 @@
 	}
 	
-	d->callback( d->fd, 0, d->data );
+	d->callback( NULL + d->fd, 0, d->data );
 	g_free( d );
 }
@@ -441,5 +445,5 @@
 		return FALSE;
 	
-	yahoo_read_ready( d->id, d->fd, d->data );
+	yahoo_read_ready( d->id, NULL + d->fd, d->data );
 	
 	return TRUE;
@@ -458,5 +462,5 @@
 	struct byahoo_write_ready_data *d = data;
 	
-	return yahoo_write_ready( d->id, d->fd, d->data );
+	return yahoo_write_ready( d->id, NULL + d->fd, d->data );
 }
 
@@ -606,7 +610,4 @@
 		flags = 0;
 		break;
-	case YAHOO_STATUS_NOTIFY:
-		state_string = "Notify";
-		break;
 	}
 	
@@ -615,4 +616,8 @@
 	if( stat == YAHOO_STATUS_IDLE )
 		imcb_buddy_times( ic, who, 0, idle );
+}
+
+void ext_yahoo_got_buzz( int id, const char *me, const char *who, long tm )
+{
 }
 
@@ -630,11 +635,18 @@
 }
 
-void ext_yahoo_got_file( int id,
-                         const char *ignored,
-                         const char *who, const char *url, long expires, const char *msg, const char *fname, unsigned long fesize )
+void ext_yahoo_got_file( int id, const char *ignored, const char *who, const char *msg,
+                         const char *fname, unsigned long fesize, char *trid )
 {
 	struct im_connection *ic = byahoo_get_ic_by_id( id );
 	
 	imcb_log( ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who );
+}
+
+void ext_yahoo_got_ft_data( int id, const unsigned char *in, int len, void *data )
+{
+}
+
+void ext_yahoo_file_transfer_done( int id, int result, void *data )
+{
 }
 
@@ -649,5 +661,5 @@
 }
 
-void ext_yahoo_system_message( int id, const char *msg )
+void ext_yahoo_system_message( int id, const char *me, const char *who, const char *msg )
 {
 	struct im_connection *ic = byahoo_get_ic_by_id( id );
@@ -671,7 +683,8 @@
 
 /* TODO: Clear up the mess of inp and d structures */
-int ext_yahoo_add_handler( int id, int fd, yahoo_input_condition cond, void *data )
+int ext_yahoo_add_handler( int id, void *fd_, yahoo_input_condition cond, void *data )
 {
 	struct byahoo_input_data *inp = g_new0( struct byahoo_input_data, 1 );
+	int fd = (int) fd_;
 	
 	if( cond == YAHOO_INPUT_READ )
@@ -700,10 +713,10 @@
 	{
 		g_free( inp );
-		return( -1 );
+		return -1;
 		/* Panic... */
 	}
 	
 	byahoo_inputs = g_slist_append( byahoo_inputs, inp );
-	return( inp->h );
+	return inp->h;
 }
 
@@ -729,5 +742,5 @@
 }
 
-int ext_yahoo_connect_async( int id, const char *host, int port, yahoo_connect_callback callback, void *data )
+int ext_yahoo_connect_async( int id, const char *host, int port, yahoo_connect_callback callback, void *data, int use_ssl )
 {
 	struct byahoo_connect_callback_data *d;
@@ -745,6 +758,31 @@
 	d->id = id;
 	
-	return( fd );
-}
+	return fd;
+}
+
+char *ext_yahoo_get_ip_addr( const char *domain )
+{
+	return NULL;
+}
+
+int ext_yahoo_write( void *fd, char *buf, int len )
+{
+	return write( (int) fd, buf, len );
+}
+
+int ext_yahoo_read( void *fd, char *buf, int len )
+{
+	return read( (int) fd, buf, len );
+}
+
+void ext_yahoo_close( void *fd )
+{
+	close( (int) fd );
+}
+
+void ext_yahoo_got_buddy_change_group( int id, const char *me, const char *who,
+                                       const char *old_group, const char *new_group )
+{
+}                                
 
 /* Because we don't want asynchronous connects in BitlBee, and because
@@ -752,39 +790,4 @@
 int ext_yahoo_connect(const char *host, int port)
 {
-#if 0
-	struct sockaddr_in serv_addr;
-	static struct hostent *server;
-	static char last_host[256];
-	int servfd;
-	char **p;
-
-	if(last_host[0] || g_strcasecmp(last_host, host)!=0) {
-		if(!(server = gethostbyname(host))) {
-			return -1;
-		}
-		strncpy(last_host, host, 255);
-	}
-
-	if((servfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		return -1;
-	}
-
-	for (p = server->h_addr_list; *p; p++)
-	{
-		memset(&serv_addr, 0, sizeof(serv_addr));
-		serv_addr.sin_family = AF_INET;
-		memcpy(&serv_addr.sin_addr.s_addr, *p, server->h_length);
-		serv_addr.sin_port = htons(port);
-
-		if(connect(servfd, (struct sockaddr *) &serv_addr, 
-					sizeof(serv_addr)) == -1) {
-			return -1;
-		} else {
-			return servfd;
-		}
-	}
-
-	closesocket(servfd);
-#endif
 	return -1;
 }
@@ -898,5 +901,5 @@
 }
 
-void ext_yahoo_chat_join( int id, const char *who, const char *room, const char *topic, YList *members, int fd )
+void ext_yahoo_chat_join( int id, const char *who, const char *room, const char *topic, YList *members, void *fd )
 {
 }
@@ -928,7 +931,5 @@
 void ext_yahoo_contact_auth_request( int id, const char *myid, const char *who, const char *msg )
 {
-	struct im_connection *ic = byahoo_get_ic_by_id( id );
-	
-	imcb_ask_auth( ic, who, NULL );
+	/* Apparently no longer implemented.. */
 }
 
@@ -944,5 +945,5 @@
 }
 
-void ext_yahoo_game_notify( int id, const char *me, const char *who, int stat )
+void ext_yahoo_game_notify( int id, const char *me, const char *who, int stat, const char *msg )
 {
 }
Index: protocols/yahoo/yahoo2.h
===================================================================
--- protocols/yahoo/yahoo2.h	(revision c36f73bd317dd55d7e70275a6425faa4be7bfd8c)
+++ protocols/yahoo/yahoo2.h	(revision 9034ba002b8945aee0f905b928bb0f60da9afe9f)
@@ -51,11 +51,11 @@
 #include "yahoo2_types.h"
 
-/* returns the socket descriptor for a given pager connection. shouldn't be needed */
-int  yahoo_get_fd(int id);
+/* returns the socket descriptor object for a given pager connection. shouldn't be needed */
+	void *yahoo_get_fd(int id);
 
 /* says how much logging to do */
 /* see yahoo2_types.h for the different values */
-int  yahoo_set_log_level(enum yahoo_log_level level);
-enum yahoo_log_level  yahoo_get_log_level( void );
+	int yahoo_set_log_level(enum yahoo_log_level level);
+	enum yahoo_log_level yahoo_get_log_level(void);
 
 /* these functions should be self explanatory */
@@ -222,6 +222,6 @@
 /* registered by ext_yahoo_add_handler */
 /* if these return negative values, errno may be set */
-int  yahoo_read_ready(int id, int fd, void *data);
-int  yahoo_write_ready(int id, int fd, void *data);
+	int yahoo_read_ready(int id, void *fd, void *data);
+	int yahoo_write_ready(int id, void *fd, void *data);
 
 /* utility functions. these do not hit the server */
@@ -240,7 +240,4 @@
 	void yahoo_buddyicon_request(int id, const char *who);
 
-	void yahoo_accept_buddy_ymsg13(int,const char*, const char*);
-	void yahoo_reject_buddy_ymsg13(int,const char*, const char*, const char*);
-
 #include "yahoo_httplib.h"
 
Index: protocols/yahoo/yahoo2_callbacks.h
===================================================================
--- protocols/yahoo/yahoo2_callbacks.h	(revision c36f73bd317dd55d7e70275a6425faa4be7bfd8c)
+++ protocols/yahoo/yahoo2_callbacks.h	(revision 9034ba002b8945aee0f905b928bb0f60da9afe9f)
@@ -55,5 +55,6 @@
  * 
  * Params:
- *     fd    - The file descriptor that has been connected, or -1 on error
+ *     fd    - The file descriptor object that has been connected, or NULL on 
+ *             error
  *     error - The value of errno set by the call to connect or 0 if no error
  *	       Set both fd and error to 0 if the connect was cancelled by the
@@ -62,6 +63,6 @@
  *	       function
  */
-typedef void (*yahoo_connect_callback)(int fd, int error, void *callback_data);
-
+	typedef void (*yahoo_connect_callback) (void *fd, int error,
+		void *callback_data);
 
 /*
@@ -262,8 +263,8 @@
  *	members - the initial members of the chatroom (null terminated YList 
  *	          of yahoo_chat_member's) Must be freed by the client
- *	fd	- the socket where the connection is coming from (for tracking)
+ *	fd	- the object where the connection is coming from (for tracking)
  */
 	void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_join) (int id, const char *me,
-		const char *room, const char *topic, YList *members, int fd);
+		const char *room, const char *topic, YList *members, void *fd);
 
 /*
@@ -364,24 +365,40 @@
  * 	me   - the identity the file was sent to
  * 	who  - the user who sent the file
- * 	url  - the file url
- * 	expires  - the expiry date of the file on the server (timestamp)
  * 	msg  - the message
  * 	fname- the file name if direct transfer
  * 	fsize- the file size if direct transfer
- */
-void YAHOO_CALLBACK_TYPE(ext_yahoo_got_file)(int id, const char *me, const char *who, const char *url, long expires, const char *msg, const char *fname, unsigned long fesize);
-
-
-/*
- * Name: ext_yahoo_contact_auth_request
- * 	Called when a contact wants to add you to his/her contact list
- * Params:
- * 	id   - the id that identifies the server connection
- * 	myid - the identity s/he added
- * 	who  - who did it
- * 	msg  - any message sent
- */
-void YAHOO_CALLBACK_TYPE(ext_yahoo_contact_auth_request)(int id, const char *myid, const char *who, const char *msg);
-
+ * 	trid - transfer id. Unique for this transfer
+ *
+ * NOTE: Subsequent callbacks for file transfer do not send all of this
+ * information again since it is wasteful. Implementations are expected to
+ * save this information and supply it as callback data when the file or
+ * confirmation is sent
+ */
+	void YAHOO_CALLBACK_TYPE(ext_yahoo_got_file) (int id, const char *me,
+		const char *who, const char *msg, const char *fname,
+		unsigned long fesize, char *trid);
+
+/*
+ * Name: ext_yahoo_got_ft_data
+ * 	Called multiple times when parts of the file are received
+ * Params:
+ * 	id   - the id that identifies the server connection
+ * 	in   - The data
+ * 	len  - Length of the data
+ * 	data - callback data
+ */
+	void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ft_data) (int id,
+		const unsigned char *in, int len, void *data);
+
+/*
+ * Name: ext_yahoo_file_transfer_done
+ * 	File transfer is done
+ * Params:
+ * 	id     - the id that identifies the server connection
+ * 	result - To notify if it finished successfully or with a failure
+ * 	data   - callback data
+ */
+	void YAHOO_CALLBACK_TYPE(ext_yahoo_file_transfer_done) (int id,
+		int result, void *data);
 
 /*
@@ -428,7 +445,8 @@
  * 	who  - the handle of the remote user
  * 	stat - 1 if game, 0 if stopped gaming
- */
-void YAHOO_CALLBACK_TYPE(ext_yahoo_game_notify)(int id, const char *me, const char *who, int stat);
-
+ * 	msg  - game description and/or other text
+ */
+	void YAHOO_CALLBACK_TYPE(ext_yahoo_game_notify) (int id, const char *me,
+		const char *who, int stat, const char *msg);
 
 /*
@@ -449,7 +467,10 @@
  * Params:
  * 	id   - the id that identifies the server connection
+ * 	me   - the handle of the identity the notification is sent to
+ * 	who  - the source of the system message (there are different types)
  * 	msg  - the message
  */
-void YAHOO_CALLBACK_TYPE(ext_yahoo_system_message)(int id, const char *msg);
+	void YAHOO_CALLBACK_TYPE(ext_yahoo_system_message) (int id,
+		const char *me, const char *who, const char *msg);
 
 /*
@@ -630,5 +651,5 @@
  * Params:
  * 	id   - the id that identifies the server connection
- * 	fd   - the fd on which to listen
+ * 	fd   - the fd object on which to listen
  * 	cond - the condition on which to call the callback
  * 	data - callback data to pass to yahoo_*_ready
@@ -636,5 +657,5 @@
  * Returns: a tag to be used when removing the handler
  */
-	int YAHOO_CALLBACK_TYPE(ext_yahoo_add_handler) (int id, int fd,
+	int YAHOO_CALLBACK_TYPE(ext_yahoo_add_handler) (int id, void *fd,
 		yahoo_input_condition cond, void *data);
 
@@ -674,10 +695,72 @@
  * 	callback - function to call when connect completes
  * 	callback_data - data to pass to the callback function
- * Returns:
- * 	a unix file descriptor to the socket
+ * 	use_ssl - Whether we need an SSL connection
+ * Returns:
+ * 	a tag signifying the connection attempt
  */
 	int YAHOO_CALLBACK_TYPE(ext_yahoo_connect_async) (int id,
 		const char *host, int port, yahoo_connect_callback callback,
-		void *callback_data);
+		void *callback_data, int use_ssl);
+
+/*
+ * Name: ext_yahoo_get_ip_addr
+ * 	get IP Address for a domain name
+ * Params:
+ * 	domain - Domain name
+ * Returns:
+ * 	Newly allocated string containing the IP Address in IPv4 notation
+ */
+	char *YAHOO_CALLBACK_TYPE(ext_yahoo_get_ip_addr) (const char *domain);
+
+/*
+ * Name: ext_yahoo_write
+ * 	Write data from the buffer into the socket for the specified connection
+ * Params:
+ * 	fd  - the file descriptor object that identifies this connection
+ * 	buf - Buffer to write the data from
+ * 	len - Length of the data
+ * Returns:
+ * 	Number of bytes written or -1 for error
+ */
+	int YAHOO_CALLBACK_TYPE(ext_yahoo_write) (void *fd, char *buf, int len);
+
+/*
+ * Name: ext_yahoo_read
+ * 	Read data into a buffer from socket for the specified connection
+ * Params:
+ * 	fd  - the file descriptor object that identifies this connection
+ * 	buf - Buffer to read the data into
+ * 	len - Max length to read
+ * Returns:
+ * 	Number of bytes read or -1 for error
+ */
+	int YAHOO_CALLBACK_TYPE(ext_yahoo_read) (void *fd, char *buf, int len);
+
+/*
+ * Name: ext_yahoo_close
+ * 	Close the file descriptor object and free its resources. Libyahoo2 will not
+ * 	use this object again.
+ * Params:
+ * 	fd  - the file descriptor object that identifies this connection
+ * Returns:
+ * 	Nothing
+ */
+	void YAHOO_CALLBACK_TYPE(ext_yahoo_close) (void *fd);
+
+/*
+ * Name: ext_yahoo_got_buddy_change_group
+ * 	Acknowledgement of buddy changing group
+ * Params:
+ * 	id: client id
+ * 	me: The user
+ * 	who: Buddy name
+ * 	old_group: Old group name
+ * 	new_group: New group name
+ * Returns:
+ * 	Nothing
+ */
+	void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddy_change_group) (int id,
+		const char *me, const char *who, const char *old_group,
+		const char *new_group);
 
 #ifdef USE_STRUCT_CALLBACKS
@@ -699,3 +782,2 @@
 
 #endif
-
Index: protocols/yahoo/yahoo2_types.h
===================================================================
--- protocols/yahoo/yahoo2_types.h	(revision c36f73bd317dd55d7e70275a6425faa4be7bfd8c)
+++ protocols/yahoo/yahoo2_types.h	(revision 9034ba002b8945aee0f905b928bb0f60da9afe9f)
@@ -29,72 +29,173 @@
 #endif
 
-enum yahoo_status {
-	YAHOO_STATUS_DISCONNECTED = -1,
-	YAHOO_STATUS_AVAILABLE = 0,
-	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_WEBLOGIN = 0x5a55aa55,
-	YAHOO_STATUS_OFFLINE = 0x5a55aa56, /* don't ask */
-	YAHOO_STATUS_NOTIFY = 0x16 /* TYPING */
-};
-#define YAHOO_STATUS_GAME	0x2 		/* Games don't fit into the regular status model */
-
-enum yahoo_login_status {
-	YAHOO_LOGIN_OK = 0,
-	YAHOO_LOGIN_LOGOFF = 2,
-	YAHOO_LOGIN_UNAME = 3,
-	YAHOO_LOGIN_PASSWD = 13,
-	YAHOO_LOGIN_LOCK = 14,
-	YAHOO_LOGIN_DUPL = 99,
-	YAHOO_LOGIN_SOCK = -1,
-};
-
-enum ypacket_status {
-	YPACKET_STATUS_DISCONNECTED = -1,
-	YPACKET_STATUS_DEFAULT = 0,
-	YPACKET_STATUS_SERVERACK = 1,
-	YPACKET_STATUS_GAME     = 0x2,
-	YPACKET_STATUS_AWAY     = 0x4,
-	YPACKET_STATUS_CONTINUED = 0x5,
-	YPACKET_STATUS_INVISIBLE = 12,
-	YPACKET_STATUS_NOTIFY = 0x16, /* TYPING */
-	YPACKET_STATUS_WEBLOGIN = 0x5a55aa55,
-	YPACKET_STATUS_OFFLINE = 0x5a55aa56
-};
-
-enum yahoo_error {
-	E_UNKNOWN = -1,
-	E_CONNECTION = -2,
-	E_SYSTEM = -3,
-	E_CUSTOM = 0,
-
-	/* responses from ignore buddy */
-	E_IGNOREDUP = 2,
-	E_IGNORENONE = 3,
-	E_IGNORECONF = 12,
-	
-	/* conference */
-	E_CONFNOTAVAIL = 20
-};
-
-enum yahoo_log_level {
-	YAHOO_LOG_NONE = 0,
-	YAHOO_LOG_FATAL,
-	YAHOO_LOG_ERR,
-	YAHOO_LOG_WARNING,
-	YAHOO_LOG_NOTICE,
-	YAHOO_LOG_INFO,
-	YAHOO_LOG_DEBUG
-};
+	enum yahoo_service {	/* these are easier to see in hex */
+		YAHOO_SERVICE_LOGON = 1,
+		YAHOO_SERVICE_LOGOFF,
+		YAHOO_SERVICE_ISAWAY,
+		YAHOO_SERVICE_ISBACK,
+		YAHOO_SERVICE_IDLE,	/* 5 (placemarker) */
+		YAHOO_SERVICE_MESSAGE,
+		YAHOO_SERVICE_IDACT,
+		YAHOO_SERVICE_IDDEACT,
+		YAHOO_SERVICE_MAILSTAT,
+		YAHOO_SERVICE_USERSTAT,	/* 0xa */
+		YAHOO_SERVICE_NEWMAIL,
+		YAHOO_SERVICE_CHATINVITE,
+		YAHOO_SERVICE_CALENDAR,
+		YAHOO_SERVICE_NEWPERSONALMAIL,
+		YAHOO_SERVICE_NEWCONTACT,
+		YAHOO_SERVICE_ADDIDENT,	/* 0x10 */
+		YAHOO_SERVICE_ADDIGNORE,
+		YAHOO_SERVICE_PING,
+		YAHOO_SERVICE_GOTGROUPRENAME,	/* < 1, 36(old), 37(new) */
+		YAHOO_SERVICE_SYSMESSAGE = 0x14,
+		YAHOO_SERVICE_SKINNAME = 0x15,
+		YAHOO_SERVICE_PASSTHROUGH2 = 0x16,
+		YAHOO_SERVICE_CONFINVITE = 0x18,
+		YAHOO_SERVICE_CONFLOGON,
+		YAHOO_SERVICE_CONFDECLINE,
+		YAHOO_SERVICE_CONFLOGOFF,
+		YAHOO_SERVICE_CONFADDINVITE,
+		YAHOO_SERVICE_CONFMSG,
+		YAHOO_SERVICE_CHATLOGON,
+		YAHOO_SERVICE_CHATLOGOFF,
+		YAHOO_SERVICE_CHATMSG = 0x20,
+		YAHOO_SERVICE_GAMELOGON = 0x28,
+		YAHOO_SERVICE_GAMELOGOFF,
+		YAHOO_SERVICE_GAMEMSG = 0x2a,
+		YAHOO_SERVICE_FILETRANSFER = 0x46,
+		YAHOO_SERVICE_VOICECHAT = 0x4A,
+		YAHOO_SERVICE_NOTIFY,
+		YAHOO_SERVICE_VERIFY,
+		YAHOO_SERVICE_P2PFILEXFER,
+		YAHOO_SERVICE_PEERTOPEER = 0x4F,	/* Checks if P2P possible */
+		YAHOO_SERVICE_WEBCAM,
+		YAHOO_SERVICE_AUTHRESP = 0x54,
+		YAHOO_SERVICE_LIST,
+		YAHOO_SERVICE_AUTH = 0x57,
+		YAHOO_SERVICE_AUTHBUDDY = 0x6d,
+		YAHOO_SERVICE_ADDBUDDY = 0x83,
+		YAHOO_SERVICE_REMBUDDY,
+		YAHOO_SERVICE_IGNORECONTACT,	/* > 1, 7, 13 < 1, 66, 13, 0 */
+		YAHOO_SERVICE_REJECTCONTACT,
+		YAHOO_SERVICE_GROUPRENAME = 0x89,	/* > 1, 65(new), 66(0), 67(old) */
+		YAHOO_SERVICE_Y7_PING = 0x8A,
+		YAHOO_SERVICE_CHATONLINE = 0x96,	/* > 109(id), 1, 6(abcde) < 0,1 */
+		YAHOO_SERVICE_CHATGOTO,
+		YAHOO_SERVICE_CHATJOIN,	/* > 1 104-room 129-1600326591 62-2 */
+		YAHOO_SERVICE_CHATLEAVE,
+		YAHOO_SERVICE_CHATEXIT = 0x9b,
+		YAHOO_SERVICE_CHATADDINVITE = 0x9d,
+		YAHOO_SERVICE_CHATLOGOUT = 0xa0,
+		YAHOO_SERVICE_CHATPING,
+		YAHOO_SERVICE_COMMENT = 0xa8,
+		YAHOO_SERVICE_GAME_INVITE = 0xb7,
+		YAHOO_SERVICE_STEALTH_PERM = 0xb9,
+		YAHOO_SERVICE_STEALTH_SESSION = 0xba,
+		YAHOO_SERVICE_AVATAR = 0xbc,
+		YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd,
+		YAHOO_SERVICE_PICTURE = 0xbe,
+		YAHOO_SERVICE_PICTURE_UPDATE = 0xc1,
+		YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2,
+		YAHOO_SERVICE_YAB_UPDATE = 0xc4,
+		YAHOO_SERVICE_Y6_VISIBLE_TOGGLE = 0xc5,	/* YMSG13, key 13: 2 = invisible, 1 = visible */
+		YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6,	/* YMSG13 */
+		YAHOO_SERVICE_PICTURE_STATUS = 0xc7,	/* YMSG13, key 213: 0 = none, 1 = avatar, 2 = picture */
+		YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8,
+		YAHOO_SERVICE_AUDIBLE = 0xd0,
+		YAHOO_SERVICE_Y7_PHOTO_SHARING = 0xd2,
+		YAHOO_SERVICE_Y7_CONTACT_DETAILS = 0xd3,	/* YMSG13 */
+		YAHOO_SERVICE_Y7_CHAT_SESSION = 0xd4,
+		YAHOO_SERVICE_Y7_AUTHORIZATION = 0xd6,	/* YMSG13 */
+		YAHOO_SERVICE_Y7_FILETRANSFER = 0xdc,	/* YMSG13 */
+		YAHOO_SERVICE_Y7_FILETRANSFERINFO,	/* YMSG13 */
+		YAHOO_SERVICE_Y7_FILETRANSFERACCEPT,	/* YMSG13 */
+		YAHOO_SERVICE_Y7_MINGLE = 0xe1,	/* YMSG13 */
+		YAHOO_SERVICE_Y7_CHANGE_GROUP = 0xe7,	/* YMSG13 */
+		YAHOO_SERVICE_MYSTERY = 0xef,	/* Don't know what this is for */
+		YAHOO_SERVICE_Y8_STATUS = 0xf0,	/* YMSG15 */
+		YAHOO_SERVICE_Y8_LIST = 0Xf1,	/* YMSG15 */
+		YAHOO_SERVICE_MESSAGE_CONFIRM = 0xfb,
+		YAHOO_SERVICE_WEBLOGIN = 0x0226,
+		YAHOO_SERVICE_SMS_MSG = 0x02ea
+	};
+
+	enum yahoo_status {
+		YAHOO_STATUS_AVAILABLE = 0,
+		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	/* don't ask */
+	};
+
+	enum ypacket_status {
+		YPACKET_STATUS_DISCONNECTED = -1,
+		YPACKET_STATUS_DEFAULT = 0,
+		YPACKET_STATUS_SERVERACK = 1,
+		YPACKET_STATUS_GAME = 0x2,
+		YPACKET_STATUS_AWAY = 0x4,
+		YPACKET_STATUS_CONTINUED = 0x5,
+		YPACKET_STATUS_INVISIBLE = 12,
+		YPACKET_STATUS_NOTIFY = 0x16,	/* TYPING */
+		YPACKET_STATUS_WEBLOGIN = 0x5a55aa55,
+		YPACKET_STATUS_OFFLINE = 0x5a55aa56
+	};
+
+#define YAHOO_STATUS_GAME	0x2	/* Games don't fit into the regular status model */
+
+	enum yahoo_login_status {
+		YAHOO_LOGIN_OK = 0,
+		YAHOO_LOGIN_LOGOFF = 1,
+		YAHOO_LOGIN_UNAME = 3,
+		YAHOO_LOGIN_PASSWD = 13,
+		YAHOO_LOGIN_LOCK = 14,
+		YAHOO_LOGIN_DUPL = 99,
+		YAHOO_LOGIN_SOCK = -1,
+		YAHOO_LOGIN_UNKNOWN = 999
+	};
+
+	enum yahoo_error {
+		E_UNKNOWN = -1,
+		E_CONNECTION = -2,
+		E_SYSTEM = -3,
+		E_CUSTOM = 0,
+
+		/* responses from ignore buddy */
+		E_IGNOREDUP = 2,
+		E_IGNORENONE = 3,
+		E_IGNORECONF = 12,
+
+		/* conference */
+		E_CONFNOTAVAIL = 20
+	};
+
+	enum yahoo_log_level {
+		YAHOO_LOG_NONE = 0,
+		YAHOO_LOG_FATAL,
+		YAHOO_LOG_ERR,
+		YAHOO_LOG_WARNING,
+		YAHOO_LOG_NOTICE,
+		YAHOO_LOG_INFO,
+		YAHOO_LOG_DEBUG
+	};
+
+	enum yahoo_file_transfer {
+		YAHOO_FILE_TRANSFER_INIT = 1,
+		YAHOO_FILE_TRANSFER_ACCEPT = 3,
+		YAHOO_FILE_TRANSFER_REJECT = 4,
+		YAHOO_FILE_TRANSFER_DONE = 5,
+		YAHOO_FILE_TRANSFER_RELAY,
+		YAHOO_FILE_TRANSFER_FAILED,
+		YAHOO_FILE_TRANSFER_UNKNOWN
+	};
 
 #define YAHOO_PROTO_VER 0x0010
@@ -121,171 +222,175 @@
 #define YAHOO_STYLE_URLOFF "\033[xlm"
 
-enum yahoo_connection_type {
-	YAHOO_CONNECTION_PAGER=0,
-	YAHOO_CONNECTION_FT,
-	YAHOO_CONNECTION_YAB,
-	YAHOO_CONNECTION_WEBCAM_MASTER,
-	YAHOO_CONNECTION_WEBCAM,
-	YAHOO_CONNECTION_CHATCAT,
-	YAHOO_CONNECTION_SEARCH,
-	YAHOO_CONNECTION_AUTH,
-};
-
-enum yahoo_webcam_direction_type {
-        YAHOO_WEBCAM_DOWNLOAD=0,
-        YAHOO_WEBCAM_UPLOAD
-};
-
-enum yahoo_stealth_visibility_type {
-	YAHOO_STEALTH_DEFAULT = 0,
-  	YAHOO_STEALTH_ONLINE,
-  	YAHOO_STEALTH_PERM_OFFLINE
-};
+	enum yahoo_connection_type {
+		YAHOO_CONNECTION_PAGER = 0,
+		YAHOO_CONNECTION_FT,
+		YAHOO_CONNECTION_YAB,
+		YAHOO_CONNECTION_WEBCAM_MASTER,
+		YAHOO_CONNECTION_WEBCAM,
+		YAHOO_CONNECTION_CHATCAT,
+		YAHOO_CONNECTION_SEARCH,
+		YAHOO_CONNECTION_AUTH
+	};
+
+	enum yahoo_webcam_direction_type {
+		YAHOO_WEBCAM_DOWNLOAD = 0,
+		YAHOO_WEBCAM_UPLOAD
+	};
+
+	enum yahoo_stealth_visibility_type {
+		YAHOO_STEALTH_DEFAULT = 0,
+		YAHOO_STEALTH_ONLINE,
+		YAHOO_STEALTH_PERM_OFFLINE
+	};
 
 /* chat member attribs */
 #define YAHOO_CHAT_MALE 0x8000
 #define YAHOO_CHAT_FEMALE 0x10000
+#define YAHOO_CHAT_FEMALE 0x10000
 #define YAHOO_CHAT_DUNNO 0x400
 #define YAHOO_CHAT_WEBCAM 0x10
 
-enum yahoo_webcam_conn_type { Y_WCM_DIALUP, Y_WCM_DSL, Y_WCM_T1 };
-
-struct yahoo_webcam {
-	int direction;     /* Uploading or downloading */
-	int conn_type;     /* 0=Dialup, 1=DSL/Cable, 2=T1/Lan */
-
-	char *user;        /* user we are viewing */
-	char *server;      /* webcam server to connect to */
-	int   port;        /* webcam port to connect on */
-	char *key;         /* key to connect to the server with */
-	char *description; /* webcam description */
-	char *my_ip;       /* own ip number */
-};
-
-struct yahoo_webcam_data {
-	unsigned int data_size;
-	unsigned int to_read;
-	unsigned int timestamp;
-	unsigned char packet_type;
-};
-
-struct yahoo_data {
-	char  *user;
-	char  *password;
-
-	char  *cookie_y;
-	char  *cookie_t;
-	char  *cookie_c;
-	char  *login_cookie;
-
-	YList *buddies;
-	YList *ignore;
-	YList *identities;
-	char  *login_id;
-
-	int   current_status;
-	int   initial_status;
-	int   logged_in;
-
-	int   session_id;
-
-	int   client_id;
-
-	char  *rawbuddylist;
-	char  *ignorelist;
-
-	void  *server_settings;
-	
-	struct yahoo_process_status_entry *half_user;
-};
-
-struct yab {
-	int yid;
-	char *id;
-	char *fname;
-	char *lname;
-	char *nname;
-	char *email;
-	char *hphone;
-	char *wphone;
-	char *mphone;
-	int  dbid;
-};
-
-struct yahoo_buddy {
-	char *group;
-	char *id;
-	char *real_name;
-	struct yab *yab_entry;
-};
-
-enum yahoo_search_type {
-	YAHOO_SEARCH_KEYWORD = 0,
-	YAHOO_SEARCH_YID,
-	YAHOO_SEARCH_NAME
-};
-
-enum yahoo_search_gender {
-	YAHOO_GENDER_NONE = 0,
-	YAHOO_GENDER_MALE,
-	YAHOO_GENDER_FEMALE
-};
-
-enum yahoo_search_agerange {
-	YAHOO_AGERANGE_NONE = 0
-};
-
-struct yahoo_found_contact {
-	char *id;
-	char *gender;
-	char *location;
-	int age;
-	int online;
-};
+	enum yahoo_webcam_conn_type { Y_WCM_DIALUP, Y_WCM_DSL, Y_WCM_T1 };
+
+	struct yahoo_webcam {
+		int direction;	/* Uploading or downloading */
+		int conn_type;	/* 0=Dialup, 1=DSL/Cable, 2=T1/Lan */
+
+		char *user;	/* user we are viewing */
+		char *server;	/* webcam server to connect to */
+		int port;	/* webcam port to connect on */
+		char *key;	/* key to connect to the server with */
+		char *description;	/* webcam description */
+		char *my_ip;	/* own ip number */
+	};
+
+	struct yahoo_webcam_data {
+		unsigned int data_size;
+		unsigned int to_read;
+		unsigned int timestamp;
+		unsigned char packet_type;
+	};
+
+	struct yahoo_data {
+		char *user;
+		char *password;
+
+		char *cookie_y;
+		char *cookie_t;
+		char *cookie_c;
+		char *cookie_b;
+		char *login_cookie;
+		char *crumb;
+		char *seed;
+
+		YList *buddies;
+		YList *ignore;
+		YList *identities;
+		char *login_id;
+
+		int current_status;
+		int initial_status;
+		int logged_in;
+
+		int session_id;
+
+		int client_id;
+
+		char *rawbuddylist;
+		char *ignorelist;
+
+		void *server_settings;
+
+		struct yahoo_process_status_entry *half_user;
+	};
+
+	struct yab {
+		int yid;
+		char *id;
+		char *fname;
+		char *lname;
+		char *nname;
+		char *email;
+		char *hphone;
+		char *wphone;
+		char *mphone;
+		int dbid;
+	};
+
+	struct yahoo_buddy {
+		char *group;
+		char *id;
+		char *real_name;
+		struct yab *yab_entry;
+	};
+
+	enum yahoo_search_type {
+		YAHOO_SEARCH_KEYWORD = 0,
+		YAHOO_SEARCH_YID,
+		YAHOO_SEARCH_NAME
+	};
+
+	enum yahoo_search_gender {
+		YAHOO_GENDER_NONE = 0,
+		YAHOO_GENDER_MALE,
+		YAHOO_GENDER_FEMALE
+	};
+
+	enum yahoo_search_agerange {
+		YAHOO_AGERANGE_NONE = 0
+	};
+
+	struct yahoo_found_contact {
+		char *id;
+		char *gender;
+		char *location;
+		int age;
+		int online;
+	};
 
 /*
  * Function pointer to be passed to http get/post and send file
  */
-typedef void (*yahoo_get_fd_callback)(int id, int fd, int error, void *data);
+	typedef void (*yahoo_get_fd_callback) (int id, void *fd, int error,
+		void *data);
 
 /*
  * Function pointer to be passed to yahoo_get_url_handle
  */
-typedef void (*yahoo_get_url_handle_callback)(int id, int fd, int error,
-		const char *filename, unsigned long size, void *data);
-
-
-struct yahoo_chat_member {
-	char *id;
-	int  age;
-	int  attribs;
-	char *alias;
-	char *location;
-};
-
-struct yahoo_process_status_entry {
-	char *name;	/* 7      name */
-	int state;	/* 10     state */
-	int flags;	/* 13     flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
-	int mobile;	/* 60     mobile */
-	char *msg;	/* 19     custom status message */
-	int away;	/* 47     away (or invisible) */
-	int buddy_session; /* 11  state */
-	int f17;	/* 17     in chat? then what about flags? */
-	int idle;	/* 137    seconds idle */
-	int f138;	/* 138    state */
-	char *f184;	/* 184    state */
-	int f192;	/* 192    state */
-	int f10001;	/* 10001  state */
-	int f10002;	/* 10002  state */
-	int f198;	/* 198    state */
-	char *f197;	/* 197    state */
-	char *f205;	/* 205    state */
-	int f213;	/* 213    state */
-};
+	typedef void (*yahoo_get_url_handle_callback) (int id, void *fd,
+		int error, const char *filename, unsigned long size,
+		void *data);
+
+	struct yahoo_chat_member {
+		char *id;
+		int age;
+		int attribs;
+		char *alias;
+		char *location;
+	};
+
+	struct yahoo_process_status_entry { 
+		char *name;     /* 7      name */ 
+		int state;      /* 10     state */ 
+		int flags;      /* 13     flags, bit 0 = pager, bit 1 = chat, bit 2 = game */ 
+		int mobile;     /* 60     mobile */ 
+		char *msg;      /* 19     custom status message */ 
+		int away;       /* 47     away (or invisible) */ 
+		int buddy_session; /* 11  state */ 
+		int f17;        /* 17     in chat? then what about flags? */ 
+		int idle;       /* 137    seconds idle */ 
+		int f138;       /* 138    state */ 
+		char *f184;     /* 184    state */ 
+		int f192;       /* 192    state */ 
+		int f10001;     /* 10001  state */ 
+		int f10002;     /* 10002  state */ 
+		int f198;       /* 198    state */ 
+		char *f197;     /* 197    state */ 
+		char *f205;     /* 205    state */ 
+		int f213;       /* 213    state */ 
+	};
 
 #ifdef __cplusplus
 }
 #endif
-
 #endif
Index: protocols/yahoo/yahoo_httplib.c
===================================================================
--- protocols/yahoo/yahoo_httplib.c	(revision c36f73bd317dd55d7e70275a6425faa4be7bfd8c)
+++ protocols/yahoo/yahoo_httplib.c	(revision 9034ba002b8945aee0f905b928bb0f60da9afe9f)
@@ -30,5 +30,5 @@
 #  define strrchr rindex
 # endif
-char *strchr (), *strrchr ();
+char *strchr(), *strrchr();
 # if !HAVE_MEMCPY
 #  define memcpy(d, s, n) bcopy ((s), (d), (n))
@@ -36,5 +36,4 @@
 # endif
 #endif
-
 
 #include <errno.h>
@@ -63,5 +62,5 @@
 extern enum yahoo_log_level log_level;
 
-int yahoo_tcp_readline(char *ptr, int maxlen, int fd)
+int yahoo_tcp_readline(char *ptr, int maxlen, void *fd)
 {
 	int n, rc;
@@ -71,9 +70,9 @@
 
 		do {
-			rc = read(fd, &c, 1);
-		} while(rc == -1 && (errno == EINTR || errno == EAGAIN)); /* this is bad - it should be done asynchronously */
+			rc = YAHOO_CALLBACK(ext_yahoo_read) (fd, &c, 1);
+		} while (rc == -1 && (errno == EINTR || errno == EAGAIN));	/* this is bad - it should be done asynchronously */
 
 		if (rc == 1) {
-			if(c == '\r')			/* get rid of \r */
+			if (c == '\r')	/* get rid of \r */
 				continue;
 			*ptr = c;
@@ -83,7 +82,7 @@
 		} else if (rc == 0) {
 			if (n == 1)
-				return (0);		/* EOF, no data */
+				return (0);	/* EOF, no data */
 			else
-				break;			/* EOF, w/ data */
+				break;	/* EOF, w/ data */
 		} else {
 			return -1;
@@ -96,10 +95,10 @@
 
 static int url_to_host_port_path(const char *url,
-		char *host, int *port, char *path)
-{
-	char *urlcopy=NULL;
-	char *slash=NULL;
-	char *colon=NULL;
-	
+	char *host, int *port, char *path, int *ssl)
+{
+	char *urlcopy = NULL;
+	char *slash = NULL;
+	char *colon = NULL;
+
 	/*
 	 * http://hostname
@@ -111,8 +110,12 @@
 	 * http://hostname:port/path
 	 * http://hostname:port/path:foo
+	 * and https:// variants of the above
 	 */
 
-	if(strstr(url, "http://") == url) {
-		urlcopy = strdup(url+7);
+	if (strstr(url, "http://") == url) {
+		urlcopy = strdup(url + 7);
+	} else if (strstr(url, "https://") == url) {
+		urlcopy = strdup(url + 8);
+		*ssl = 1;
 	} else {
 		WARNING(("Weird url - unknown protocol: %s", url));
@@ -123,12 +126,15 @@
 	colon = strchr(urlcopy, ':');
 
-	if(!colon || (slash && slash < colon)) {
-		*port = 80;
+	if (!colon || (slash && slash < colon)) {
+		if (*ssl)
+			*port = 443;
+		else
+			*port = 80;
 	} else {
 		*colon = 0;
-		*port = atoi(colon+1);
-	}
-
-	if(!slash) {
+		*port = atoi(colon + 1);
+	}
+
+	if (!slash) {
 		strcpy(path, "/");
 	} else {
@@ -138,5 +144,5 @@
 
 	strcpy(host, urlcopy);
-	
+
 	FREE(urlcopy);
 
@@ -146,31 +152,31 @@
 static int isurlchar(unsigned char c)
 {
-	return (isalnum(c) || '-' == c || '_' == c);
+	return (isalnum(c));
 }
 
 char *yahoo_urlencode(const char *instr)
 {
-	int ipos=0, bpos=0;
+	int ipos = 0, bpos = 0;
 	char *str = NULL;
 	int len = strlen(instr);
 
-	if(!(str = y_new(char, 3*len + 1) ))
-		return "";
-
-	while(instr[ipos]) {
-		while(isurlchar(instr[ipos]))
+	if (!(str = y_new(char, 3 *len + 1)))
+		 return "";
+
+	while (instr[ipos]) {
+		while (isurlchar(instr[ipos]))
 			str[bpos++] = instr[ipos++];
-		if(!instr[ipos])
+		if (!instr[ipos])
 			break;
-		
-		snprintf(&str[bpos], 4, "%%%.2x", instr[ipos]);
-		bpos+=3;
+
+		snprintf(&str[bpos], 4, "%%%02x", instr[ipos] & 0xff);
+		bpos += 3;
 		ipos++;
 	}
-	str[bpos]='\0';
+	str[bpos] = '\0';
 
 	/* free extra alloc'ed mem. */
 	len = strlen(str);
-	str = y_renew(char, str, len+1);
+	str = y_renew(char, str, len + 1);
 
 	return (str);
@@ -179,27 +185,27 @@
 char *yahoo_urldecode(const char *instr)
 {
-	int ipos=0, bpos=0;
+	int ipos = 0, bpos = 0;
 	char *str = NULL;
-	char entity[3]={0,0,0};
+	char entity[3] = { 0, 0, 0 };
 	unsigned dec;
 	int len = strlen(instr);
 
-	if(!(str = y_new(char, len+1) ))
-		return "";
-
-	while(instr[ipos]) {
-		while(instr[ipos] && instr[ipos]!='%')
-			if(instr[ipos]=='+') {
-				str[bpos++]=' ';
+	if (!(str = y_new(char, len + 1)))
+		 return "";
+
+	while (instr[ipos]) {
+		while (instr[ipos] && instr[ipos] != '%')
+			if (instr[ipos] == '+') {
+				str[bpos++] = ' ';
 				ipos++;
 			} else
 				str[bpos++] = instr[ipos++];
-		if(!instr[ipos])
+		if (!instr[ipos])
 			break;
-		
-		if(instr[ipos+1] && instr[ipos+2]) {
+
+		if (instr[ipos + 1] && instr[ipos + 2]) {
 			ipos++;
-			entity[0]=instr[ipos++];
-			entity[1]=instr[ipos++];
+			entity[0] = instr[ipos++];
+			entity[1] = instr[ipos++];
 			sscanf(entity, "%2x", &dec);
 			str[bpos++] = (char)dec;
@@ -208,9 +214,9 @@
 		}
 	}
-	str[bpos]='\0';
+	str[bpos] = '\0';
 
 	/* free extra alloc'ed mem. */
 	len = strlen(str);
-	str = y_renew(char, str, len+1);
+	str = y_renew(char, str, len + 1);
 
 	return (str);
@@ -219,12 +225,12 @@
 char *yahoo_xmldecode(const char *instr)
 {
-	int ipos=0, bpos=0, epos=0;
+	int ipos = 0, bpos = 0, epos = 0;
 	char *str = NULL;
-	char entity[4]={0,0,0,0};
-	char *entitymap[5][2]={
-		{"amp;",  "&"}, 
+	char entity[4] = { 0, 0, 0, 0 };
+	char *entitymap[5][2] = {
+		{"amp;", "&"},
 		{"quot;", "\""},
-		{"lt;",   "<"}, 
-		{"gt;",   "<"}, 
+		{"lt;", "<"},
+		{"gt;", "<"},
 		{"nbsp;", " "}
 	};
@@ -232,23 +238,23 @@
 	int len = strlen(instr);
 
-	if(!(str = y_new(char, len+1) ))
-		return "";
-
-	while(instr[ipos]) {
-		while(instr[ipos] && instr[ipos]!='&')
-			if(instr[ipos]=='+') {
-				str[bpos++]=' ';
+	if (!(str = y_new(char, len + 1)))
+		 return "";
+
+	while (instr[ipos]) {
+		while (instr[ipos] && instr[ipos] != '&')
+			if (instr[ipos] == '+') {
+				str[bpos++] = ' ';
 				ipos++;
 			} else
 				str[bpos++] = instr[ipos++];
-		if(!instr[ipos] || !instr[ipos+1])
+		if (!instr[ipos] || !instr[ipos + 1])
 			break;
 		ipos++;
 
-		if(instr[ipos] == '#') {
+		if (instr[ipos] == '#') {
 			ipos++;
-			epos=0;
-			while(instr[ipos] != ';')
-				entity[epos++]=instr[ipos++];
+			epos = 0;
+			while (instr[ipos] != ';')
+				entity[epos++] = instr[ipos++];
 			sscanf(entity, "%u", &dec);
 			str[bpos++] = (char)dec;
@@ -256,8 +262,8 @@
 		} else {
 			int i;
-			for (i=0; i<5; i++) 
-				if(!strncmp(instr+ipos, entitymap[i][0], 
-					       strlen(entitymap[i][0]))) {
-				       	str[bpos++] = entitymap[i][1][0];
+			for (i = 0; i < 5; i++)
+				if (!strncmp(instr + ipos, entitymap[i][0],
+						strlen(entitymap[i][0]))) {
+					str[bpos++] = entitymap[i][1][0];
 					ipos += strlen(entitymap[i][0]);
 					break;
@@ -265,14 +271,14 @@
 		}
 	}
-	str[bpos]='\0';
+	str[bpos] = '\0';
 
 	/* free extra alloc'ed mem. */
 	len = strlen(str);
-	str = y_renew(char, str, len+1);
+	str = y_renew(char, str, len + 1);
 
 	return (str);
 }
 
-typedef void (*http_connected)(int id, int fd, int error);
+typedef void (*http_connected) (int id, void *fd, int error);
 
 struct callback_data {
@@ -283,28 +289,30 @@
 };
 
-static void connect_complete(int fd, int error, void *data)
+static void connect_complete(void *fd, int error, void *data)
 {
 	struct callback_data *ccd = data;
-	if(error == 0 && fd > 0)
-		write(fd, ccd->request, strlen(ccd->request));
-	FREE(ccd->request);
+	if (error == 0)
+		YAHOO_CALLBACK(ext_yahoo_write) (fd, ccd->request,
+			strlen(ccd->request));
+	free(ccd->request);
 	ccd->callback(ccd->id, fd, error, ccd->user_data);
 	FREE(ccd);
 }
 
-static void yahoo_send_http_request(int id, char *host, int port, char *request, 
-		yahoo_get_fd_callback callback, void *data)
-{
-	struct callback_data *ccd=y_new0(struct callback_data, 1);
+static void yahoo_send_http_request(int id, char *host, int port, char *request,
+	yahoo_get_fd_callback callback, void *data, int use_ssl)
+{
+	struct callback_data *ccd = y_new0(struct callback_data, 1);
 	ccd->callback = callback;
 	ccd->id = id;
 	ccd->request = strdup(request);
 	ccd->user_data = data;
-	
-	YAHOO_CALLBACK(ext_yahoo_connect_async)(id, host, port, connect_complete, ccd);
-}
-
-void yahoo_http_post(int id, const char *url, const char *cookies, long content_length,
-		yahoo_get_fd_callback callback, void *data)
+
+	YAHOO_CALLBACK(ext_yahoo_connect_async) (id, host, port,
+		connect_complete, ccd, use_ssl);
+}
+
+void yahoo_http_post(int id, const char *url, const char *cookies,
+	long content_length, yahoo_get_fd_callback callback, void *data)
 {
 	char host[255];
@@ -312,120 +320,85 @@
 	char path[255];
 	char buff[1024];
-	
-	if(!url_to_host_port_path(url, host, &port, path))
+	int ssl = 0;
+
+	if (!url_to_host_port_path(url, host, &port, path, &ssl))
 		return;
 
-	snprintf(buff, sizeof(buff), 
-			"POST %s HTTP/1.0\r\n"
-			"Content-length: %ld\r\n"
-			"User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n"
-			"Host: %s:%d\r\n"
-			"Cookie: %s\r\n"
-			"\r\n",
-			path, content_length, 
-			host, port,
-			cookies);
-
-	yahoo_send_http_request(id, host, port, buff, callback, data);
-}
-
-void yahoo_http_get(int id, const char *url, const char *cookies,
-		yahoo_get_fd_callback callback, void *data)
+	/* thanks to kopete dumpcap */
+	snprintf(buff, sizeof(buff),
+		"POST %s HTTP/1.1\r\n"
+		"Cookie: %s\r\n"
+		"User-Agent: Mozilla/5.0\r\n"
+		"Host: %s\r\n"
+		"Content-Length: %ld\r\n"
+		"Cache-Control: no-cache\r\n"
+		"\r\n", path, cookies, host, content_length);
+
+	yahoo_send_http_request(id, host, port, buff, callback, data, ssl);
+}
+
+void yahoo_http_get(int id, const char *url, const char *cookies, int http11,
+	int keepalive, yahoo_get_fd_callback callback, void *data)
 {
 	char host[255];
 	int port = 80;
 	char path[255];
-	char buff[1024];
-	
-	if(!url_to_host_port_path(url, host, &port, path))
+	char buff[2048];
+	char cookiebuff[1024];
+	int ssl = 0;
+
+	if (!url_to_host_port_path(url, host, &port, path, &ssl))
 		return;
 
-	snprintf(buff, sizeof(buff), 
-			"GET %s HTTP/1.0\r\n"
-			"Host: %s:%d\r\n"
-			"User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n"
-			"Cookie: %s\r\n"
-			"\r\n",
-			path, host, port, cookies);
-
-	yahoo_send_http_request(id, host, port, buff, callback, data);
-}
-
-struct url_data {
-	yahoo_get_url_handle_callback callback;
-	void *user_data;
-};
-
-static void yahoo_got_url_fd(int id, int fd, int error, void *data)
-{
-	char *tmp=NULL;
-	char buff[1024];
-	unsigned long filesize=0;
-	char *filename=NULL;
-	int n;
-
-	struct url_data *ud = data;
-
-	if(error || fd < 0) {
-		ud->callback(id, fd, error, filename, filesize, ud->user_data);
-		FREE(ud);
+	/* Allow cases when we don't need to send a cookie */
+	if (cookies)
+		snprintf(cookiebuff, sizeof(cookiebuff), "Cookie: %s\r\n",
+			cookies);
+	else
+		cookiebuff[0] = '\0';
+
+	snprintf(buff, sizeof(buff),
+		"GET %s HTTP/1.%s\r\n"
+		"%sHost: %s\r\n"
+		"User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n"
+		"Accept: */*\r\n"
+		"%s" "\r\n", path, http11?"1":"0", cookiebuff, host,
+		keepalive? "Connection: Keep-Alive\r\n":"Connection: close\r\n");
+
+	yahoo_send_http_request(id, host, port, buff, callback, data, ssl);
+}
+
+void yahoo_http_head(int id, const char *url, const char *cookies, int len,
+	char *payload, yahoo_get_fd_callback callback, void *data)
+{
+	char host[255];
+	int port = 80;
+	char path[255];
+	char buff[2048];
+	char cookiebuff[1024];
+	int ssl = 0;
+
+	if (!url_to_host_port_path(url, host, &port, path, &ssl))
 		return;
-	}
-
-	while((n=yahoo_tcp_readline(buff, sizeof(buff), fd)) > 0) {
-		LOG(("Read:%s:\n", buff));
-		if(!strcmp(buff, ""))
-			break;
-
-		if( !strncasecmp(buff, "Content-length:", 
-				strlen("Content-length:")) ) {
-			tmp = strrchr(buff, ' ');
-			if(tmp)
-				filesize = atol(tmp);
-		}
-
-		if( !strncasecmp(buff, "Content-disposition:", 
-				strlen("Content-disposition:")) ) {
-			tmp = strstr(buff, "name=");
-			if(tmp) {
-				tmp+=strlen("name=");
-				if(tmp[0] == '"') {
-					char *tmp2;
-					tmp++;
-					tmp2 = strchr(tmp, '"');
-					if(tmp2)
-						*tmp2 = '\0';
-				} else {
-					char *tmp2;
-					tmp2 = strchr(tmp, ';');
-					if(!tmp2)
-						tmp2 = strchr(tmp, '\r');
-					if(!tmp2)
-						tmp2 = strchr(tmp, '\n');
-					if(tmp2)
-						*tmp2 = '\0';
-				}
-
-				filename = strdup(tmp);
-			}
-		}
-	}
-
-	LOG(("n == %d\n", n));
-	LOG(("Calling callback, filename:%s, size: %ld\n", filename, filesize));
-	ud->callback(id, fd, error, filename, filesize, ud->user_data);
-	FREE(ud);
-	FREE(filename);
-}
-
-void yahoo_get_url_fd(int id, const char *url, const struct yahoo_data *yd,
-		yahoo_get_url_handle_callback callback, void *data)
-{
-	char buff[1024];
-	struct url_data *ud = y_new0(struct url_data, 1);
-	snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
-	ud->callback = callback;
-	ud->user_data = data;
-	yahoo_http_get(id, url, buff, yahoo_got_url_fd, ud);
-}
-
+
+	/* Allow cases when we don't need to send a cookie */
+	if (cookies)
+		snprintf(cookiebuff, sizeof(cookiebuff), "Cookie: %s\r\n",
+			cookies);
+	else
+		cookiebuff[0] = '\0';
+
+	snprintf(buff, sizeof(buff),
+		"HEAD %s HTTP/1.0\r\n"
+		"Accept: */*\r\n"
+		"Host: %s:%d\r\n"
+		"User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n"
+		"%s"
+		"Content-Length: %d\r\n"
+		"Cache-Control: no-cache\r\n"
+		"\r\n%s", path, host, port, cookiebuff, len,
+		payload?payload:"");
+
+	yahoo_send_http_request(id, host, port, buff, callback, data, ssl);
+}
+
Index: protocols/yahoo/yahoo_httplib.h
===================================================================
--- protocols/yahoo/yahoo_httplib.h	(revision c36f73bd317dd55d7e70275a6425faa4be7bfd8c)
+++ protocols/yahoo/yahoo_httplib.h	(revision 9034ba002b8945aee0f905b928bb0f60da9afe9f)
@@ -29,20 +29,20 @@
 #include "yahoo2_types.h"
 
-char *yahoo_urlencode(const char *instr);
-char *yahoo_urldecode(const char *instr);
-char *yahoo_xmldecode(const char *instr);
+	char *yahoo_urlencode(const char *instr);
+	char *yahoo_urldecode(const char *instr);
+	char *yahoo_xmldecode(const char *instr);
 
-int yahoo_tcp_readline(char *ptr, int maxlen, int fd);
-void yahoo_http_post(int id, const char *url, const char *cookies, long size,
-		yahoo_get_fd_callback callback, void *data);
-void yahoo_http_get(int id, const char *url, const char *cookies,
-		yahoo_get_fd_callback callback, void *data);
-void yahoo_get_url_fd(int id, const char *url, const struct yahoo_data *yd,
-		yahoo_get_url_handle_callback callback, void *data);
-
+	int yahoo_tcp_readline(char *ptr, int maxlen, void *fd);
+	void yahoo_http_post(int id, const char *url, const char *cookies,
+		long size, yahoo_get_fd_callback callback, void *data);
+	void yahoo_http_get(int id, const char *url, const char *cookies,
+		int http11, int keepalive, yahoo_get_fd_callback callback,
+		void *data);
+	void yahoo_http_head(int id, const char *url, const char *cookies,
+		int size, char *payload, yahoo_get_fd_callback callback,
+		void *data);
 
 #ifdef __cplusplus
 }
 #endif
-
 #endif
Index: protocols/yahoo/yahoo_list.h
===================================================================
--- protocols/yahoo/yahoo_list.h	(revision c36f73bd317dd55d7e70275a6425faa4be7bfd8c)
+++ protocols/yahoo/yahoo_list.h	(revision 9034ba002b8945aee0f905b928bb0f60da9afe9f)
@@ -24,5 +24,5 @@
 #define __YLIST_H__
 
-/* GLib has linked list already, so I don't see why libyahoo2 has to copy this... */
+/* BitlBee already uses GLib so use it. */
 
 typedef GList YList;
