# HG changeset patch # User Tim Ringenbach # Date 1103233674 0 # Node ID a8f9e5ce4f92961d2260eeef30a0e614aeae42e2 # Parent 38256d3e83240e50dfb963b8864539c77784f6f7 [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 diff -r 38256d3e8324 -r a8f9e5ce4f92 src/protocols/yahoo/Makefile.am --- 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 \ diff -r 38256d3e8324 -r a8f9e5ce4f92 src/protocols/yahoo/yahoo.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); } diff -r 38256d3e8324 -r a8f9e5ce4f92 src/protocols/yahoo/yahoo.h --- 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(); diff -r 38256d3e8324 -r a8f9e5ce4f92 src/protocols/yahoo/yahoo_filexfer.c --- 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); diff -r 38256d3e8324 -r a8f9e5ce4f92 src/protocols/yahoo/yahoo_packet.c --- /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); +} diff -r 38256d3e8324 -r a8f9e5ce4f92 src/protocols/yahoo/yahoo_packet.h --- /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_ */ diff -r 38256d3e8324 -r a8f9e5ce4f92 src/protocols/yahoo/yahoo_picture.c --- 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); diff -r 38256d3e8324 -r a8f9e5ce4f92 src/protocols/yahoo/yahoochat.c --- 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 diff -r 38256d3e8324 -r a8f9e5ce4f92 src/protocols/yahoo/ycht.c --- 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"