changeset 10392:a8f9e5ce4f92

[gaim-migrate @ 11620] a little bit of clean up and reorganization of the yahoo prpl. I moved the packet functions to their own file, renamed a couple of them, added a convience function and used it a lot. I plan on adding several more convience functions. committer: Tailor Script <tailor@pidgin.im>
author Tim Ringenbach <marv@pidgin.im>
date Thu, 16 Dec 2004 21:47:54 +0000
parents 38256d3e8324
children a7a2c27248af
files src/protocols/yahoo/Makefile.am src/protocols/yahoo/yahoo.c src/protocols/yahoo/yahoo.h src/protocols/yahoo/yahoo_filexfer.c src/protocols/yahoo/yahoo_packet.c src/protocols/yahoo/yahoo_packet.h src/protocols/yahoo/yahoo_picture.c src/protocols/yahoo/yahoochat.c src/protocols/yahoo/ycht.c
diffstat 9 files changed, 479 insertions(+), 448 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/yahoo/Makefile.am	Thu Dec 16 15:36:49 2004 +0000
+++ b/src/protocols/yahoo/Makefile.am	Thu Dec 16 21:47:54 2004 +0000
@@ -16,6 +16,8 @@
 	yahoo_filexfer.c \
 	yahoo_friend.h \
 	yahoo_friend.c \
+	yahoo_packet.h \
+	yahoo_packet.c \
 	yahoo_picture.c \
 	yahoo_picture.h \
 	yahoo_profile.c \
--- a/src/protocols/yahoo/yahoo.c	Thu Dec 16 15:36:49 2004 +0000
+++ b/src/protocols/yahoo/yahoo.c	Thu Dec 16 21:47:54 2004 +0000
@@ -39,6 +39,7 @@
 
 #include "sha.h"
 #include "yahoo.h"
+#include "yahoo_packet.h"
 #include "yahoo_friend.h"
 #include "yahoochat.h"
 #include "ycht.h"
@@ -55,266 +56,6 @@
 static void yahoo_login_page_cb(void *user_data, const char *buf, size_t len);
 
 
-struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id)
-{
-	struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1);
-
-	pkt->service = service;
-	pkt->status = status;
-	pkt->id = id;
-
-	return pkt;
-}
-
-void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value)
-{
-	struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1);
-	pair->key = key;
-	pair->value = g_strdup(value);
-	pkt->hash = g_slist_append(pkt->hash, pair);
-}
-
-int yahoo_packet_length(struct yahoo_packet *pkt)
-{
-	GSList *l;
-
-	int len = 0;
-
-	l = pkt->hash;
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-		int tmp = pair->key;
-		do {
-			tmp /= 10;
-			len++;
-		} while (tmp);
-		len += 2;
-		len += strlen(pair->value);
-		len += 2;
-		l = l->next;
-	}
-
-	return len;
-}
-
-static void yahoo_packet_read(struct yahoo_packet *pkt, guchar *data, int len)
-{
-	int pos = 0;
-
-	while (pos + 1 < len) {
-		char key[64], *value = NULL, *esc;
-		int accept;
-		int x;
-
-		struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1);
-
-		/* this is weird, and in one of the chat packets, and causes us
-		 * think all the values are keys and all the keys are values after
-		 * this point if we don't handle it */
-		if (data[pos] == '\0') {
-			while (pos + 1 < len) {
-				if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
-					break;
-				pos++;
-			}
-			pos += 2;
-			g_free(pair);
-			continue;
-		}
-
-		x = 0;
-		while (pos + 1 < len) {
-			if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
-				break;
-			if (x >= sizeof(key)-1) {
-				x++;
-				pos++;
-				continue;
-			}
-			key[x++] = data[pos++];
-		}
-		if (x >= sizeof(key)-1) {
-			x = 0;
-		}
-		key[x] = 0;
-		pos += 2;
-		pair->key = strtol(key, NULL, 10);
-		accept = x; /* if x is 0 there was no key, so don't accept it */
-
-		if (len - pos + 1 <= 0) {
-			/* Truncated. Garbage or something. */
-			accept = 0;
-		}
-
-		if (accept) {
-			value = g_malloc(len - pos + 1);
-			x = 0;
-			while (pos + 1 < len) {
-				if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
-					break;
-				value[x++] = data[pos++];
-			}
-			value[x] = 0;
-			pair->value = g_strdup(value);
-			g_free(value);
-			pkt->hash = g_slist_append(pkt->hash, pair);
-			esc = g_strescape(pair->value, NULL);
-			gaim_debug(GAIM_DEBUG_MISC, "yahoo",
-					   "Key: %d  \tValue: %s\n", pair->key, esc);
-			g_free(esc);
-		} else {
-			g_free(pair);
-		}
-		pos += 2;
-
-		/* Skip over garbage we've noticed in the mail notifications */
-		if (data[0] == '9' && data[pos] == 0x01)
-			pos++;
-	}
-}
-
-void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data)
-{
-	GSList *l = pkt->hash;
-	int pos = 0;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-		guchar buf[100];
-
-		g_snprintf(buf, sizeof(buf), "%d", pair->key);
-		strcpy(data + pos, buf);
-		pos += strlen(buf);
-		data[pos++] = 0xc0;
-		data[pos++] = 0x80;
-
-		strcpy(data + pos, pair->value);
-		pos += strlen(pair->value);
-		data[pos++] = 0xc0;
-		data[pos++] = 0x80;
-
-		l = l->next;
-	}
-}
-
-static void yahoo_packet_dump(guchar *data, int len)
-{
-#ifdef YAHOO_DEBUG
-	int i;
-
-	gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
-
-	for (i = 0; i + 1 < len; i += 2) {
-		if ((i % 16 == 0) && i) {
-			gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
-			gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
-		}
-
-		gaim_debug(GAIM_DEBUG_MISC, NULL, "%02x%02x ", data[i], data[i + 1]);
-	}
-	if (i < len)
-		gaim_debug(GAIM_DEBUG_MISC, NULL, "%02x", data[i]);
-
-	gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
-	gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
-
-	for (i = 0; i < len; i++) {
-		if ((i % 16 == 0) && i) {
-			gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
-			gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
-		}
-
-		if (g_ascii_isprint(data[i]))
-			gaim_debug(GAIM_DEBUG_MISC, NULL, "%c ", data[i]);
-		else
-			gaim_debug(GAIM_DEBUG_MISC, NULL, ". ");
-	}
-
-	gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
-#endif
-}
-
-int yahoo_send_packet(struct yahoo_data *yd, struct yahoo_packet *pkt)
-{
-	int pktlen = yahoo_packet_length(pkt);
-	int len = YAHOO_PACKET_HDRLEN + pktlen;
-	int ret;
-
-	guchar *data;
-	int pos = 0;
-
-	if (yd->fd < 0)
-		return -1;
-
-	data = g_malloc0(len + 1);
-
-	memcpy(data + pos, "YMSG", 4); pos += 4;
-
-	if (yd->wm)
-		pos += yahoo_put16(data + pos, YAHOO_WEBMESSENGER_PROTO_VER);
-	else
-		pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);
-
-	pos += yahoo_put16(data + pos, 0x0000);
-	pos += yahoo_put16(data + pos, pktlen);
-	pos += yahoo_put16(data + pos, pkt->service);
-	pos += yahoo_put32(data + pos, pkt->status);
-	pos += yahoo_put32(data + pos, pkt->id);
-
-	yahoo_packet_write(pkt, data + pos);
-
-	yahoo_packet_dump(data, len);
-	ret = write(yd->fd, data, len);
-	if (ret != len)
-		gaim_debug_warning("yahoo", "Only wrote %d of %d bytes!", ret, len);
-	g_free(data);
-
-	return ret;
-}
-
-int yahoo_send_packet_special(int fd, struct yahoo_packet *pkt, int pad)
-{
-	int pktlen = yahoo_packet_length(pkt);
-	int len = YAHOO_PACKET_HDRLEN + pktlen;
-	int ret;
-
-	guchar *data;
-	int pos = 0;
-
-	if (fd < 0)
-		return -1;
-
-	data = g_malloc0(len + 1);
-
-	memcpy(data + pos, "YMSG", 4); pos += 4;
-
-	pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);
-
-	pos += yahoo_put16(data + pos, 0x0000);
-	pos += yahoo_put16(data + pos, pktlen + pad);
-	pos += yahoo_put16(data + pos, pkt->service);
-	pos += yahoo_put32(data + pos, pkt->status);
-	pos += yahoo_put32(data + pos, pkt->id);
-
-	yahoo_packet_write(pkt, data + pos);
-
-	ret = write(fd, data, len);
-	g_free(data);
-
-	return ret;
-}
-
-void yahoo_packet_free(struct yahoo_packet *pkt)
-{
-	while (pkt->hash) {
-		struct yahoo_pair *pair = pkt->hash->data;
-		g_free(pair->value);
-		g_free(pair);
-		pkt->hash = g_slist_remove(pkt->hash, pair);
-	}
-	g_free(pkt);
-}
-
 static void yahoo_update_status(GaimConnection *gc, const char *name, YahooFriend *f)
 {
 	gboolean online = TRUE;
@@ -425,8 +166,7 @@
 				 *
 				 * do_import(gc, NULL);
 				 * newpkt = yahoo_packet_new(YAHOO_SERVICE_LIST, YAHOO_STATUS_OFFLINE, 0);
-				 * yahoo_send_packet(yd, newpkt);
-				 * yahoo_packet_free(newpkt);
+				 * yahoo_packet_send_and_free(newpkt, yd);
 				 */
 
 				}
@@ -1280,13 +1020,10 @@
 	yahoo_packet_hash(pack, 96, result96);
 	yahoo_packet_hash(pack, 1, name);
 
-	yahoo_send_packet(yd, pack);
+	yahoo_packet_send_and_free(pack, yd);
 
 	g_free(hash_string_p);
 	g_free(hash_string_c);
-
-	yahoo_packet_free(pack);
-
 }
 
 /* I'm dishing out some uber-mad props to Cerulean Studios for cracking this
@@ -1743,8 +1480,7 @@
 		yahoo_packet_hash(pack, 192, cksum);
 		g_free(cksum);
 	}
-	yahoo_send_packet(yd, pack);
-	yahoo_packet_free(pack);
+	yahoo_packet_send_and_free(pack, yd);
 
 	g_free(password_hash);
 	g_free(crypt_hash);
@@ -2287,9 +2023,7 @@
 	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YAHOO_STATUS_AVAILABLE, 0);
 
 	yahoo_packet_hash(pkt, 1, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc))));
-	yahoo_send_packet(yd, pkt);
-
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc);
 }
@@ -2318,9 +2052,8 @@
 	yahoo_packet_hash(pkt, 0, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc))));
 	yahoo_packet_hash(pkt, 1, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc))));
 	yahoo_packet_hash(pkt, 6, yd->auth);
-	yahoo_send_packet(yd, pkt);
-
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
+
 	g_free(yd->auth);
 	gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc);
 }
@@ -2878,8 +2611,7 @@
 
 	struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_IDACT, YAHOO_STATUS_AVAILABLE, 0);
 	yahoo_packet_hash(pkt, 3, entry);
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	gaim_connection_set_display_name(gc, entry);
 }
@@ -2944,7 +2676,7 @@
 
 	/* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */
 	if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000)
-		yahoo_send_packet(yd, pkt);
+		yahoo_packet_send(pkt, yd);
 	else
 		ret = -E2BIG;
 
@@ -2967,9 +2699,7 @@
 	yahoo_packet_hash(pkt, 5, who);
 	yahoo_packet_hash(pkt, 1002, "1");
 
-	yahoo_send_packet(yd, pkt);
-
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	return 0;
 }
@@ -3023,8 +2753,7 @@
 	if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
 		pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, YAHOO_STATUS_AVAILABLE, 0);
 		yahoo_packet_hash(pkt, 13, "2");
-		yahoo_send_packet(yd, pkt);
-		yahoo_packet_free(pkt);
+		yahoo_packet_send_and_free(pkt, yd);
 
 		return;
 	}
@@ -3054,8 +2783,7 @@
 	else if (!gaim_status_type_is_available(gaim_status_get_type(status)))
 		yahoo_packet_hash(pkt, 47, "1");
 
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	g_free(conv_msg);
 	g_free(conv_msg2);
@@ -3063,8 +2791,7 @@
 	if (old_status == YAHOO_STATUS_INVISIBLE) {
 		pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, YAHOO_STATUS_AVAILABLE, 0);
 		yahoo_packet_hash(pkt, 13, "1");
-		yahoo_send_packet(yd, pkt);
-		yahoo_packet_free(pkt);
+		yahoo_packet_send_and_free(pkt, yd);
 	}
 }
 
@@ -3101,8 +2828,7 @@
 		yahoo_packet_hash(pkt, 47, "1");
 
 
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	g_free(msg);
 	g_free(msg2);
@@ -3179,8 +2905,7 @@
 {
 	struct yahoo_data *yd = gc->proto_data;
 	struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, 0);
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	if (!yd->chat_online)
 		return;
@@ -3192,8 +2917,7 @@
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YAHOO_STATUS_AVAILABLE, 0);
 	yahoo_packet_hash(pkt, 109, gaim_connection_get_display_name(gc));
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(yd, pkt);
 }
 
 /* XXX - What's the deal with GaimGroup *foo? */
@@ -3224,8 +2948,7 @@
 	yahoo_packet_hash(pkt, 7, buddy->name);
 	yahoo_packet_hash(pkt, 65, group2);
 	yahoo_packet_hash(pkt, 14, "");
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 	g_free(group2);
 }
 
@@ -3261,8 +2984,7 @@
 	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));
 	yahoo_packet_hash(pkt, 7, buddy->name);
 	yahoo_packet_hash(pkt, 65, cg);
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 	g_free(cg);
 }
 
@@ -3284,8 +3006,7 @@
 	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));
 	yahoo_packet_hash(pkt, 7, who);
 	yahoo_packet_hash(pkt, 13, "1");
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 }
 
 static void yahoo_rem_deny(GaimConnection *gc, const char *who) {
@@ -3302,8 +3023,7 @@
 	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));
 	yahoo_packet_hash(pkt, 7, who);
 	yahoo_packet_hash(pkt, 13, "2");
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 }
 
 static void yahoo_set_permit_deny(GaimConnection *gc) {
@@ -3374,16 +3094,14 @@
 	yahoo_packet_hash(pkt, 7, who);
 	yahoo_packet_hash(pkt, 65, gpn);
 	yahoo_packet_hash(pkt, 14, "");
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	/* Step 2:  Remove buddy from old group */
 	pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0);
 	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));
 	yahoo_packet_hash(pkt, 7, who);
 	yahoo_packet_hash(pkt, 65, gpo);
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 	g_free(gpn);
 	g_free(gpo);
 }
@@ -3407,8 +3125,7 @@
 	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));
 	yahoo_packet_hash(pkt, 65, gpo);
 	yahoo_packet_hash(pkt, 67, gpn);
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 	g_free(gpn);
 	g_free(gpo);
 }
--- a/src/protocols/yahoo/yahoo.h	Thu Dec 16 15:36:49 2004 +0000
+++ b/src/protocols/yahoo/yahoo.h	Thu Dec 16 21:47:54 2004 +0000
@@ -50,79 +50,7 @@
 #define YAHOO_PICCKSUM_SETTING "picture_checksum"
 #define YAHOO_PICEXPIRE_SETTING "picture_expire"
 
-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,
-	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 = 0x4B,
-	YAHOO_SERVICE_VERIFY,
-	YAHOO_SERVICE_P2PFILEXFER,
-	YAHOO_SERVICE_PEEPTOPEER = 0x4F,
-	YAHOO_SERVICE_WEBCAM,
-	YAHOO_SERVICE_AUTHRESP = 0x54,
-	YAHOO_SERVICE_LIST = 0x55,
-	YAHOO_SERVICE_AUTH = 0x57,
-	YAHOO_SERVICE_ADDBUDDY = 0x83,
-	YAHOO_SERVICE_REMBUDDY = 0x84,
-	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_??? = 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_AVATAR = 0xbc,
-	YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd,
-	YAHOO_SERVICE_PICTURE = 0xbe,
-	YAHOO_SERVICE_PICTURE_UPDATE = 0xc1,
-	YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2,
-	YAHOO_SERVICE_Y6_VISIBLE_TOGGLE = 0xc5,
-	YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6,
-	YAHOO_SERVICE_AVATAR_UPDATE = 0xc7,
-	YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8,
-	YAHOO_SERVICE_AUDIBLE = 0xd0,
-	YAHOO_SERVICE_WEBLOGIN = 0x0226,
-	YAHOO_SERVICE_SMS_MSG = 0x02ea
-};
+
 
 #define YAHOO_STATUS_TYPE_OFFLINE "offline"
 #define YAHOO_STATUS_TYPE_ONLINE "online"
@@ -200,28 +128,10 @@
 	struct _YchtConn *ycht;
 };
 
-struct yahoo_pair {
-	int key;
-	char *value;
-};
-
-struct yahoo_packet {
-	guint16 service;
-	guint32 status;
-	guint32 id;
-	GSList *hash;
-};
-
 
 #define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255)
 
 
-#define YAHOO_WEBMESSENGER_PROTO_VER 0x0065
-#define YAHOO_PROTO_VER 0x000c
-
-
-#define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
-
 /* sometimes i wish prpls could #include things from other prpls. then i could just
  * use the routines from libfaim and not have to admit to knowing how they work. */
 #define yahoo_put16(buf, data) ( \
@@ -241,13 +151,6 @@
 		(((*((buf)+3)    )&0x000000ff)))
 
 
-struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id);
-void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value);
-int yahoo_send_packet(struct yahoo_data *yd, struct yahoo_packet *pkt);
-int yahoo_send_packet_special(int fd, struct yahoo_packet *pkt, int pad);
-void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data);
-int yahoo_packet_length(struct yahoo_packet *pkt);
-void yahoo_packet_free(struct yahoo_packet *pkt);
 
 /* util.c */
 void yahoo_init_colorht();
--- a/src/protocols/yahoo/yahoo_filexfer.c	Thu Dec 16 15:36:49 2004 +0000
+++ b/src/protocols/yahoo/yahoo_filexfer.c	Thu Dec 16 21:47:54 2004 +0000
@@ -28,6 +28,7 @@
 #include "proxy.h"
 #include "ft.h"
 #include "yahoo.h"
+#include "yahoo_packet.h"
 #include "yahoo_filexfer.h"
 
 
@@ -141,7 +142,7 @@
 			       buf);
 	write(xfer->fd, post, strlen(post));
 
-	yahoo_send_packet_special(xfer->fd, pkt, 8);
+	yahoo_packet_send_special(pkt, xfer->fd, 8);
 	yahoo_packet_free(pkt);
 
 	write(xfer->fd, "29\xc0\x80", 4);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/yahoo/yahoo_packet.c	Thu Dec 16 21:47:54 2004 +0000
@@ -0,0 +1,297 @@
+/*
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "internal.h"
+#include "debug.h"
+
+#include "yahoo.h"
+#include "yahoo_packet.h"
+
+struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id)
+{
+	struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1);
+
+	pkt->service = service;
+	pkt->status = status;
+	pkt->id = id;
+
+	return pkt;
+}
+
+void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value)
+{
+	struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1);
+	pair->key = key;
+	pair->value = g_strdup(value);
+	pkt->hash = g_slist_append(pkt->hash, pair);
+}
+
+int yahoo_packet_length(struct yahoo_packet *pkt)
+{
+	GSList *l;
+
+	int len = 0;
+
+	l = pkt->hash;
+	while (l) {
+		struct yahoo_pair *pair = l->data;
+		int tmp = pair->key;
+		do {
+			tmp /= 10;
+			len++;
+		} while (tmp);
+		len += 2;
+		len += strlen(pair->value);
+		len += 2;
+		l = l->next;
+	}
+
+	return len;
+}
+
+void yahoo_packet_read(struct yahoo_packet *pkt, guchar *data, int len)
+{
+	int pos = 0;
+
+	while (pos + 1 < len) {
+		char key[64], *value = NULL, *esc;
+		int accept;
+		int x;
+
+		struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1);
+
+		/* this is weird, and in one of the chat packets, and causes us
+		 * think all the values are keys and all the keys are values after
+		 * this point if we don't handle it */
+		if (data[pos] == '\0') {
+			while (pos + 1 < len) {
+				if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
+					break;
+				pos++;
+			}
+			pos += 2;
+			g_free(pair);
+			continue;
+		}
+
+		x = 0;
+		while (pos + 1 < len) {
+			if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
+				break;
+			if (x >= sizeof(key)-1) {
+				x++;
+				pos++;
+				continue;
+			}
+			key[x++] = data[pos++];
+		}
+		if (x >= sizeof(key)-1) {
+			x = 0;
+		}
+		key[x] = 0;
+		pos += 2;
+		pair->key = strtol(key, NULL, 10);
+		accept = x; /* if x is 0 there was no key, so don't accept it */
+
+		if (len - pos + 1 <= 0) {
+			/* Truncated. Garbage or something. */
+			accept = 0;
+		}
+
+		if (accept) {
+			value = g_malloc(len - pos + 1);
+			x = 0;
+			while (pos + 1 < len) {
+				if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
+					break;
+				value[x++] = data[pos++];
+			}
+			value[x] = 0;
+			pair->value = g_strdup(value);
+			g_free(value);
+			pkt->hash = g_slist_append(pkt->hash, pair);
+			esc = g_strescape(pair->value, NULL);
+			gaim_debug(GAIM_DEBUG_MISC, "yahoo",
+					   "Key: %d  \tValue: %s\n", pair->key, esc);
+			g_free(esc);
+		} else {
+			g_free(pair);
+		}
+		pos += 2;
+
+		/* Skip over garbage we've noticed in the mail notifications */
+		if (data[0] == '9' && data[pos] == 0x01)
+			pos++;
+	}
+}
+
+void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data)
+{
+	GSList *l = pkt->hash;
+	int pos = 0;
+
+	while (l) {
+		struct yahoo_pair *pair = l->data;
+		guchar buf[100];
+
+		g_snprintf(buf, sizeof(buf), "%d", pair->key);
+		strcpy(data + pos, buf);
+		pos += strlen(buf);
+		data[pos++] = 0xc0;
+		data[pos++] = 0x80;
+
+		strcpy(data + pos, pair->value);
+		pos += strlen(pair->value);
+		data[pos++] = 0xc0;
+		data[pos++] = 0x80;
+
+		l = l->next;
+	}
+}
+
+void yahoo_packet_dump(guchar *data, int len)
+{
+#ifdef YAHOO_DEBUG
+	int i;
+
+	gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
+
+	for (i = 0; i + 1 < len; i += 2) {
+		if ((i % 16 == 0) && i) {
+			gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
+			gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
+		}
+
+		gaim_debug(GAIM_DEBUG_MISC, NULL, "%02x%02x ", data[i], data[i + 1]);
+	}
+	if (i < len)
+		gaim_debug(GAIM_DEBUG_MISC, NULL, "%02x", data[i]);
+
+	gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
+	gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
+
+	for (i = 0; i < len; i++) {
+		if ((i % 16 == 0) && i) {
+			gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
+			gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
+		}
+
+		if (g_ascii_isprint(data[i]))
+			gaim_debug(GAIM_DEBUG_MISC, NULL, "%c ", data[i]);
+		else
+			gaim_debug(GAIM_DEBUG_MISC, NULL, ". ");
+	}
+
+	gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
+#endif
+}
+
+int yahoo_packet_send(struct yahoo_packet *pkt, struct yahoo_data *yd)
+{
+	int pktlen = yahoo_packet_length(pkt);
+	int len = YAHOO_PACKET_HDRLEN + pktlen;
+	int ret;
+
+	guchar *data;
+	int pos = 0;
+
+	if (yd->fd < 0)
+		return -1;
+
+	data = g_malloc0(len + 1);
+
+	memcpy(data + pos, "YMSG", 4); pos += 4;
+
+	if (yd->wm)
+		pos += yahoo_put16(data + pos, YAHOO_WEBMESSENGER_PROTO_VER);
+	else
+		pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);
+
+	pos += yahoo_put16(data + pos, 0x0000);
+	pos += yahoo_put16(data + pos, pktlen);
+	pos += yahoo_put16(data + pos, pkt->service);
+	pos += yahoo_put32(data + pos, pkt->status);
+	pos += yahoo_put32(data + pos, pkt->id);
+
+	yahoo_packet_write(pkt, data + pos);
+
+	yahoo_packet_dump(data, len);
+	ret = write(yd->fd, data, len);
+	if (ret != len)
+		gaim_debug_warning("yahoo", "Only wrote %d of %d bytes!", ret, len);
+	g_free(data);
+
+	return ret;
+}
+
+int yahoo_packet_send_and_free(struct yahoo_packet *pkt, struct yahoo_data *yd)
+{
+	int ret;
+	
+	ret = yahoo_packet_send(pkt, yd);
+	yahoo_packet_free(pkt);
+	return ret;
+}
+
+int yahoo_packet_send_special(struct yahoo_packet *pkt, int fd, int pad)
+{
+	int pktlen = yahoo_packet_length(pkt);
+	int len = YAHOO_PACKET_HDRLEN + pktlen;
+	int ret;
+
+	guchar *data;
+	int pos = 0;
+
+	if (fd < 0)
+		return -1;
+
+	data = g_malloc0(len + 1);
+
+	memcpy(data + pos, "YMSG", 4); pos += 4;
+
+	pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);
+
+	pos += yahoo_put16(data + pos, 0x0000);
+	pos += yahoo_put16(data + pos, pktlen + pad);
+	pos += yahoo_put16(data + pos, pkt->service);
+	pos += yahoo_put32(data + pos, pkt->status);
+	pos += yahoo_put32(data + pos, pkt->id);
+
+	yahoo_packet_write(pkt, data + pos);
+
+	ret = write(fd, data, len);
+	g_free(data);
+
+	return ret;
+}
+
+void yahoo_packet_free(struct yahoo_packet *pkt)
+{
+	while (pkt->hash) {
+		struct yahoo_pair *pair = pkt->hash->data;
+		g_free(pair->value);
+		g_free(pair);
+		pkt->hash = g_slist_remove(pkt->hash, pair);
+	}
+	g_free(pkt);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/yahoo/yahoo_packet.h	Thu Dec 16 21:47:54 2004 +0000
@@ -0,0 +1,132 @@
+/**
+ * @file yahoo_packet.h The Yahoo! protocol plugin
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _YAHOO_PACKET_H_
+#define _YAHOO_PACKET_H_
+
+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,
+	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 = 0x4B,
+	YAHOO_SERVICE_VERIFY,
+	YAHOO_SERVICE_P2PFILEXFER,
+	YAHOO_SERVICE_PEEPTOPEER = 0x4F,
+	YAHOO_SERVICE_WEBCAM,
+	YAHOO_SERVICE_AUTHRESP = 0x54,
+	YAHOO_SERVICE_LIST = 0x55,
+	YAHOO_SERVICE_AUTH = 0x57,
+	YAHOO_SERVICE_ADDBUDDY = 0x83,
+	YAHOO_SERVICE_REMBUDDY = 0x84,
+	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_??? = 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_AVATAR = 0xbc,
+	YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd,
+	YAHOO_SERVICE_PICTURE = 0xbe,
+	YAHOO_SERVICE_PICTURE_UPDATE = 0xc1,
+	YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2,
+	YAHOO_SERVICE_Y6_VISIBLE_TOGGLE = 0xc5,
+	YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6,
+	YAHOO_SERVICE_AVATAR_UPDATE = 0xc7,
+	YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8,
+	YAHOO_SERVICE_AUDIBLE = 0xd0,
+	YAHOO_SERVICE_WEBLOGIN = 0x0226,
+	YAHOO_SERVICE_SMS_MSG = 0x02ea
+};
+
+struct yahoo_pair {
+	int key;
+	char *value;
+};
+
+struct yahoo_packet {
+	guint16 service;
+	guint32 status;
+	guint32 id;
+	GSList *hash;
+};
+
+#define YAHOO_WEBMESSENGER_PROTO_VER 0x0065
+#define YAHOO_PROTO_VER 0x000c
+
+#define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
+
+
+struct yahoo_packet *yahoo_packet_new(enum yahoo_service service,
+				      enum yahoo_status status, int id);
+void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value);
+int yahoo_packet_send(struct yahoo_packet *pkt, struct yahoo_data *yd);
+int yahoo_packet_send_and_free(struct yahoo_packet *pkt, struct yahoo_data *yd);
+int yahoo_packet_send_special(struct yahoo_packet *pkt, int fd, int pad);
+void yahoo_packet_read(struct yahoo_packet *pkt, guchar *data, int len);
+void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data);
+void yahoo_packet_dump(guchar *data, int len);
+int yahoo_packet_length(struct yahoo_packet *pkt);
+void yahoo_packet_free(struct yahoo_packet *pkt);
+
+#endif /* _YAHOO_PACKET_H_ */
--- a/src/protocols/yahoo/yahoo_picture.c	Thu Dec 16 15:36:49 2004 +0000
+++ b/src/protocols/yahoo/yahoo_picture.c	Thu Dec 16 21:47:54 2004 +0000
@@ -32,6 +32,7 @@
 #include "util.h"
 
 #include "yahoo.h"
+#include "yahoo_packet.h"
 #include "yahoo_friend.h"
 #include "yahoo_picture.h"
 
@@ -247,8 +248,7 @@
 	buf = g_strdup_printf("%d", yd->picture_checksum);
 	yahoo_packet_hash(pkt, 192, buf);
 
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 	g_free(buf);
 }
 
@@ -261,8 +261,7 @@
 	yahoo_packet_hash(pkt, 4, gaim_connection_get_display_name(gc)); /* me */
 	yahoo_packet_hash(pkt, 5, who); /* the other guy */
 	yahoo_packet_hash(pkt, 13, "1"); /* 1 = request, 2 = reply */
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 }
 
 void yahoo_send_picture_checksum(GaimConnection *gc)
@@ -275,8 +274,7 @@
 	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));
 	yahoo_packet_hash(pkt, 212, "1");
 	yahoo_packet_hash(pkt, 192, cksum);
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 	g_free(cksum);
 }
 
@@ -290,8 +288,7 @@
 	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));
 	yahoo_packet_hash(pkt, 5, who);
 	yahoo_packet_hash(pkt, 206, typestr);
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	g_free(typestr);
 }
@@ -432,7 +429,7 @@
 			       buf);
 	write(d->fd, post, strlen(post));
 
-	yahoo_send_packet_special(d->fd, pkt, 8);
+	yahoo_packet_send_special(pkt, d->fd, 8);
 	yahoo_packet_free(pkt);
 
 	write(d->fd, "29\xc0\x80", 4);
--- a/src/protocols/yahoo/yahoochat.c	Thu Dec 16 15:36:49 2004 +0000
+++ b/src/protocols/yahoo/yahoochat.c	Thu Dec 16 21:47:54 2004 +0000
@@ -39,6 +39,7 @@
 #include "internal.h"
 
 #include "yahoo.h"
+#include "yahoo_packet.h"
 #include "yahoochat.h"
 #include "ycht.h"
 
@@ -62,10 +63,7 @@
 	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));
 	yahoo_packet_hash(pkt, 109, gaim_connection_get_display_name(gc));
 	yahoo_packet_hash(pkt, 6, "abcde");
-
-	yahoo_send_packet(yd, pkt);
-
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 }
 
 /* this is slow, and different from the gaim_* version in that it (hopefully) won't add a user twice */
@@ -603,9 +601,7 @@
 
 	yahoo_packet_hash(pkt, 57, room);
 
-	yahoo_send_packet(yd, pkt);
-
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 }
 
 static int yahoo_conf_send(GaimConnection *gc, const char *dn, const char *room,
@@ -633,9 +629,7 @@
 	if (utf8)
 		yahoo_packet_hash(pkt, 97, "1"); /* utf-8 */
 
-	yahoo_send_packet(yd, pkt);
-
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 	g_free(msg);
 	g_free(msg2);
 
@@ -666,9 +660,7 @@
 			gaim_conv_chat_add_user(GAIM_CONV_CHAT(c), memarr[i], NULL, GAIM_CBFLAGS_NONE, TRUE);
 		}
 	}
-	yahoo_send_packet(yd, pkt);
-
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	if (memarr)
 		g_strfreev(memarr);
@@ -701,11 +693,9 @@
 		yahoo_packet_hash(pkt, 52, name);
 		yahoo_packet_hash(pkt, 53, name);
 	}
-	yahoo_send_packet(yd, pkt);
-
-	yahoo_packet_free(pkt);
-	if (msg)
-		g_free(msg2);
+	
+	yahoo_packet_send_and_free(pkt, yd);
+	g_free(msg2);
 }
 
 /*
@@ -736,9 +726,7 @@
 	yahoo_packet_hash(pkt, 108, "1");
 	yahoo_packet_hash(pkt, 112, "0"); /* what does this one mean? */
 
-	yahoo_send_packet(yd, pkt);
-
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	yd->in_chat = 0;
 	if (yd->chat_name) {
@@ -755,8 +743,7 @@
 	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT,
 			YAHOO_STATUS_AVAILABLE, 0);
 	yahoo_packet_hash(pkt, 1, dn);
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	yd->chat_online = 0;
 	g_free(eroom);
@@ -839,8 +826,7 @@
 	if (utf8)
 		yahoo_packet_hash(pkt, 97, "1");
 
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 	g_free(msg1);
 	g_free(room2);
 
@@ -872,9 +858,7 @@
 	yahoo_packet_hash(pkt, 104, room2);
 	yahoo_packet_hash(pkt, 129, "0");
 
-	yahoo_send_packet(yd, pkt);
-
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 	g_free(room2);
 }
 
@@ -904,12 +888,10 @@
 	yahoo_packet_hash(pkt, 117, (msg2?msg2:""));
 	yahoo_packet_hash(pkt, 129, "0");
 
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	g_free(room2);
-	if (msg2)
-		g_free(msg2);
+	g_free(msg2);
 }
 
 void yahoo_chat_goto(GaimConnection *gc, const char *name)
@@ -935,8 +917,7 @@
 	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));
 	yahoo_packet_hash(pkt, 62, "2");
 
-	yahoo_send_packet(yd, pkt);
-	yahoo_packet_free(pkt);
+	yahoo_packet_send_and_free(pkt, yd);
 }
 /*
  * These are the functions registered with the core
--- a/src/protocols/yahoo/ycht.c	Thu Dec 16 15:36:49 2004 +0000
+++ b/src/protocols/yahoo/ycht.c	Thu Dec 16 21:47:54 2004 +0000
@@ -37,6 +37,7 @@
 #include "util.h"
 
 #include "yahoo.h"
+#include "yahoo_packet.h"
 #include "ycht.h"
 #include "yahoochat.h"