Mercurial > pidgin.yaz
changeset 22080:d6f174c2a83e
propagate from branch 'im.pidgin.pidgin' (head cc7917983d28560aebe8a2b4ba1d8135b856dce5)
to branch 'im.pidgin.cpw.rekkanoryo.yahoop15ft' (head 3ad28b49e94fba6bc334942467f846240663721f)
author | John Bailey <rekkanoryo@rekkanoryo.org> |
---|---|
date | Sat, 12 Jan 2008 02:24:51 +0000 |
parents | eeba86c553be (diff) f808629a0123 (current diff) |
children | 9bddfb6df976 |
files | COPYRIGHT libpurple/protocols/yahoo/yahoo.c |
diffstat | 9 files changed, 1053 insertions(+), 302 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Fri Jan 11 00:01:33 2008 +0000 +++ b/COPYRIGHT Sat Jan 12 02:24:51 2008 +0000 @@ -322,6 +322,7 @@ Jean-Francois Roy Peter Ruibal Sam S. +Thanumalayan S. Pradyumna Sampath Arvind Samptur Tom Samstag
--- a/ChangeLog Fri Jan 11 00:01:33 2008 +0000 +++ b/ChangeLog Sat Jan 12 02:24:51 2008 +0000 @@ -9,6 +9,7 @@ now required to use Bonjour. * Partial support for viewing ICQ status notes (Collin from ComBOTS GmbH). + * Support for Yahoo Messenger 7.0+ file transfer method (Thanumalayan S.) Pidgin: * Added the ability to theme conversation name colors (red and blue)
--- a/libpurple/protocols/yahoo/util.c Fri Jan 11 00:01:33 2008 +0000 +++ b/libpurple/protocols/yahoo/util.c Sat Jan 12 02:24:51 2008 +0000 @@ -31,6 +31,70 @@ #include "yahoo.h" #include <string.h> +/* + * Returns cookies formatted as a null terminated string for the given connection. + * Must g_free return value. + * + * TODO:will work, but must test for strict correctness + */ +gchar* yahoo_get_cookies(PurpleConnection *gc) +{ + gchar *ans = NULL; + gchar *cur; + char firstflag = 1; + gchar *t1,*t2,*t3; + GSList *tmp; + GSList *cookies; + cookies = ((struct yahoo_data*)(gc->proto_data))->cookies; + tmp = cookies; + while(tmp) + { + cur = tmp->data; + t1 = ans; + t2 = g_strrstr(cur, ";expires="); + if(t2 == NULL) + t2 = g_strrstr(cur, "; expires="); + if(t2 == NULL) + { + if(firstflag) + ans = g_strdup_printf("%c=%s", cur[0], cur+2); + else + ans = g_strdup_printf("%s; %c=%s", t1, cur[0], cur+2); + } + else + { + t3 = strstr(t2+1, ";"); + if(t3 != NULL) + { + t2[0] = '\0'; + + if(firstflag) + ans = g_strdup_printf("%c=%s%s", cur[0], cur+2, t3); + else + ans = g_strdup_printf("%s; %c=%s%s", t1, cur[0], cur+2, t3); + + t2[0] = ';'; + } + else + { + t2[0] = '\0'; + + if(firstflag) + ans = g_strdup_printf("%c=%s", cur[0], cur+2); + else + ans = g_strdup_printf("%s; %c=%s", t1, cur[0], cur+2); + + t2[0] = ';'; + } + } + if(firstflag) + firstflag = 0; + else + g_free(t1); + tmp = g_slist_next(tmp); + } + return ans; +} /** * Encode some text to send to the yahoo server.
--- a/libpurple/protocols/yahoo/yahoo.c Fri Jan 11 00:01:33 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Sat Jan 12 02:24:51 2008 +0000 @@ -392,6 +392,10 @@ case 97: /* Unicode status message */ unicode = !strcmp(pair->value, "1"); break; + case 244: /* client version number. Yahoo Client Detection */ + if(f && strtol(pair->value, NULL, 10)) + f->version_id = strtol(pair->value, NULL, 10); + break; default: purple_debug(PURPLE_DEBUG_ERROR, "yahoo", @@ -493,16 +497,16 @@ static void yahoo_process_cookie(struct yahoo_data *yd, char *c) { if (c[0] == 'Y') { - g_free(yd->cookie_y); + if (yd->cookie_y) + g_free(yd->cookie_y); yd->cookie_y = _getcookie(c); } else if (c[0] == 'T') { - g_free(yd->cookie_t); + if (yd->cookie_t) + g_free(yd->cookie_t); yd->cookie_t = _getcookie(c); - } else if (c[0] == 'C') { - g_free(yd->cookie_c); - yd->cookie_c = _getcookie(c); } else - purple_debug_info("yahoo", "Ignoring unrecognized cookie '%c'\n", c[0]); + purple_debug_info("yahoo", "Unrecognized cookie '%c'\n", c[0]); + yd->cookies = g_slist_prepend(yd->cookies, g_strdup(c)); } static void yahoo_process_list_15(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -510,6 +514,7 @@ GSList *l = pkt->hash; PurpleAccount *account = purple_connection_get_account(gc); + struct yahoo_data *yd = gc->proto_data; GHashTable *ht; char *grp = NULL; char *norm_bud = NULL; @@ -575,6 +580,9 @@ purple_debug_info("yahoo", "Setting protocol to %d\n", f->protocol); } break; + case 59: /* somebody told cookies come here too, but im not sure */ + yahoo_process_cookie(yd, pair->value); + break; case 317: /* Stealth Setting */ if (f && (strtol(pair->value, NULL, 10) == 2)) { f->presence = YAHOO_PRESENCE_PERM_OFFLINE; @@ -1507,7 +1515,13 @@ to_y64(result96, digest, 16); pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pack, "ssss", 0, name, 6, result6, 96, result96, 1, name); + yahoo_packet_hash(pack, "ssssss", + 0, name, + 6, result6, + 96, result96, + 1, name, + 244, YAHOO_CLIENT_VERSION_ID, + 135, YAHOO_CLIENT_VERSION); yahoo_packet_send_and_free(pack, yd); g_free(hash_string_p); @@ -1526,11 +1540,11 @@ char *enc_pass; struct yahoo_data *yd = gc->proto_data; - PurpleCipher *md5_cipher; + PurpleCipher *md5_cipher; PurpleCipherContext *md5_ctx; guchar md5_digest[16]; - PurpleCipher *sha1_cipher; + PurpleCipher *sha1_cipher; PurpleCipherContext *sha1_ctx1; PurpleCipherContext *sha1_ctx2; @@ -1542,7 +1556,7 @@ char *delimit_lookup = ",;"; char *password_hash = (char *)g_malloc(25); - char *crypt_hash = (char *)g_malloc(25); + char *crypt_hash = (char *)g_malloc(25); char *crypt_result = NULL; unsigned char pass_hash_xor1[64]; @@ -1596,7 +1610,7 @@ magic_ptr = seed; - while (*magic_ptr != (int)NULL) { + while (*magic_ptr != '\0') { char *loc; /* Ignore parentheses. */ @@ -1649,7 +1663,7 @@ * dust on the values. */ - for (magic_cnt = magic_len-2; magic_cnt >= 0; magic_cnt--) { + for (magic_cnt = magic_len - 2; magic_cnt >= 0; magic_cnt--) { unsigned char byte1; unsigned char byte2; @@ -1665,7 +1679,7 @@ byte1 ^= byte2; magic[magic_cnt+1] = byte1; - } + } /* * Magic: Phase 3. This computes 20 bytes. The first 4 bytes are used as our magic @@ -1680,8 +1694,8 @@ x = 0; do { - unsigned int bl = 0; - unsigned int cl = magic[magic_cnt++]; + unsigned int bl = 0; + unsigned int cl = magic[magic_cnt++]; if (magic_cnt >= magic_len) break; @@ -1706,17 +1720,18 @@ /* First four bytes are magic key. */ memcpy(&magic_key_char[0], comparison_src, 4); - magic_4 = magic_key_char[0] | (magic_key_char[1]<<8) | (magic_key_char[2]<<16) | (magic_key_char[3]<<24); + magic_4 = magic_key_char[0] | (magic_key_char[1] << 8) | + (magic_key_char[2] << 16) | (magic_key_char[3] << 24); /* * Magic: Phase 4. Determine what function to use later by getting outside/inside * loop values until we match our previous buffer. */ for (x = 0; x < 65535; x++) { - int leave = 0; + int leave = 0; for (y = 0; y < 5; y++) { - unsigned char test[3]; + unsigned char test[3]; /* Calculate buffer. */ test[0] = x; @@ -1952,8 +1967,13 @@ } purple_debug_info("yahoo", "yahoo status: %d\n", yd->current_status); pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->current_status, 0); - yahoo_packet_hash(pack, "sssss", 0, name, 6, resp_6, 96, resp_96, 1, - name, 135, "6,0,0,1710"); + yahoo_packet_hash(pack, "ssssss", + 0, name, + 6, resp_6, + 96, resp_96, + 1, name, + 244, YAHOO_CLIENT_VERSION_ID, + 135, YAHOO_CLIENT_VERSION); if (yd->picture_checksum) yahoo_packet_hash_int(pack, 192, yd->picture_checksum); @@ -2443,12 +2463,16 @@ case YAHOO_SERVICE_AUDIBLE: yahoo_process_audible(gc, pkt); break; - case YAHOO_SERVICE_Y7_FILETRANSFER: - yahoo_process_y7_filetransfer(gc, pkt); + case YAHOO_SERVICE_FILETRANS_15: + yahoo_process_filetrans_15(gc, pkt); break; - case YAHOO_SERVICE_Y7_FILETRANSFER_INFO: - yahoo_process_y7_filetransfer_info(gc, pkt); + case YAHOO_SERVICE_FILETRANS_INFO_15: + yahoo_process_filetrans_info_15(gc, pkt); break; + case YAHOO_SERVICE_FILETRANS_ACC_15: + yahoo_process_filetrans_acc_15(gc, pkt); + break; + default: purple_debug(PURPLE_DEBUG_ERROR, "yahoo", "Unhandled service 0x%02x\n", pkt->service); @@ -2670,11 +2694,15 @@ s = g_string_sized_new(len); while ((i = strstr(i, "Set-Cookie: "))) { + i += strlen("Set-Cookie: "); for (;*i != ';' && *i != '\0'; i++) g_string_append_c(s, *i); - + g_string_append(s, "; "); + /* Should these cookies be included too when trying for xfer? + * It seems to work without these + */ } yd->auth = g_string_free(s, FALSE); @@ -2964,6 +2992,7 @@ yd->txbuf = purple_circ_buffer_new(0); yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); yd->confs = NULL; yd->conf_id = 2; @@ -3018,17 +3047,23 @@ } g_slist_free(yd->confs); + for (l = yd->cookies; l; l = l->next) { + g_free(l->data); + l->data=NULL; + } + g_slist_free(yd->cookies); + yd->chat_online = 0; if (yd->in_chat) yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */ g_hash_table_destroy(yd->friends); g_hash_table_destroy(yd->imvironments); + g_hash_table_destroy(yd->xfer_peer_idstring_map); g_free(yd->chat_name); g_free(yd->cookie_y); g_free(yd->cookie_t); - g_free(yd->cookie_c); if (yd->txhandler) purple_input_remove(yd->txhandler);
--- a/libpurple/protocols/yahoo/yahoo.h Fri Jan 11 00:01:33 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.h Sat Jan 12 02:24:51 2008 +0000 @@ -34,6 +34,8 @@ #define YAHOO_MAIL_URL "https://login.yahoo.com/config/login?.src=ym" #define YAHOO_XFER_HOST "filetransfer.msg.yahoo.com" #define YAHOO_XFER_PORT 80 +#define YAHOO_XFER_RELAY_HOST "relay.msg.yahoo.com" +#define YAHOO_XFER_RELAY_PORT 80 #define YAHOO_ROOMLIST_URL "http://insider.msg.yahoo.com/ycontent/" #define YAHOO_ROOMLIST_LOCALE "us" /* really we should get the list of servers from @@ -43,6 +45,9 @@ #define YAHOOJP_MAIL_URL "http://mail.yahoo.co.jp/" #define YAHOOJP_XFER_HOST "filetransfer.msg.yahoo.co.jp" #define YAHOOJP_WEBCAM_HOST "wc.yahoo.co.jp" +/*not sure, must test:*/ +#define YAHOOJP_XFER_RELAY_HOST "relay.msg.yahoo.com" +#define YAHOOJP_XFER_RELAY_PORT 80 #define YAHOO_AUDIBLE_URL "http://us.dl1.yimg.com/download.yahoo.com/dl/aud" @@ -67,6 +72,9 @@ #define YAHOO_STATUS_TYPE_INVISIBLE "invisible" #define YAHOO_STATUS_TYPE_MOBILE "mobile" +#define YAHOO_CLIENT_VERSION_ID "2097087" +#define YAHOO_CLIENT_VERSION "8.1.0.421" + /* Index into attention types list. */ #define YAHOO_BUZZ 0 @@ -86,7 +94,8 @@ YAHOO_STATUS_IDLE = 999, YAHOO_STATUS_WEBLOGIN = 0x5a55aa55, YAHOO_STATUS_OFFLINE = 0x5a55aa56, /* don't ask */ - YAHOO_STATUS_TYPING = 0x16 + YAHOO_STATUS_TYPING = 0x16, + YAHOO_STATUS_DISCONNECTED = 0xffffffff /* in ymsg 15. doesnt mean the normal sense of 'disconnected' */ }; struct yahoo_buddy_icon_upload_data { @@ -134,7 +143,6 @@ gsize auth_written; char *cookie_y; char *cookie_t; - char *cookie_c; int session_id; gboolean jp; gboolean wm; /* connected w/ web messenger method */ @@ -154,6 +162,8 @@ * for when we lookup people profile or photo information. */ GSList *url_datas; + GHashTable *xfer_peer_idstring_map;/*Hey, i dont know, but putting this HashTable next to friends gives a run time fault...*/ + GSList *cookies;/*contains all cookies, including _y and _t*/ }; #define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255) @@ -212,6 +222,12 @@ /* yahoo_profile.c */ void yahoo_get_info(PurpleConnection *gc, const char *name); +/* needed for xfer, thought theyd be useful for other enhancements later on + Returns list of cookies stored in yahoo_data formatted as a single null terminated string + returned value must be g_freed +*/ +gchar* yahoo_get_cookies(PurpleConnection *gc); + /** * Check to see whether the sender is permitted to send *
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c Fri Jan 11 00:01:33 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Sat Jan 12 02:24:51 2008 +0000 @@ -21,6 +21,7 @@ */ #include "internal.h" +#include "dnsquery.h" #include "prpl.h" #include "util.h" @@ -32,6 +33,7 @@ #include "yahoo_packet.h" #include "yahoo_filexfer.h" #include "yahoo_doodle.h" +#include "yahoo_friend.h" struct yahoo_xfer_data { gchar *host; @@ -46,81 +48,65 @@ guint tx_handler; gchar *rxqueue; guint rxlen; + gchar *xfer_peer_idstring; + gchar *xfer_idstring_for_relay; + int version; /*0 for old, 15 for Y7(YMSG 15)*/ + int info_val_249; - gboolean y7; /* true for Y7 transfers (receive only for now) */ - gchar *token; - gchar *tid; + enum { + STARTED = 0, + HEAD_REQUESTED, + HEAD_REPLY_RECEIVED, + TRANSFER_PHASE, + ACCEPTED + } status_15; + + /* contains all filenames, in case of multiple transfers, with the first + * one in the list being the current file's name (ymsg15) */ + GSList *filename_list; + GSList *size_list; /*corresponds to filename_list, with size as **STRING** */ + gboolean firstoflist; }; static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd) { + PurpleConnection *gc; + struct yahoo_data *yd; + PurpleXfer *xfer; + GSList *l; + + gc = xd->gc; + yd = gc->proto_data; + + /*remove entry from map*/ + if(xd->xfer_peer_idstring) { + xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring); + if(xfer) + g_hash_table_remove(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring); + } + + /*empty file & filesize list*/ + for (l = xd->filename_list; l; l = l->next) { + g_free(l->data); + l->data=NULL; + } + for (l = xd->size_list; l; l = l->next) { + g_free(l->data); + l->data=NULL; + } + g_slist_free(xd->filename_list); + g_slist_free(xd->size_list); + g_free(xd->host); g_free(xd->path); g_free(xd->txbuf); - g_free(xd->token); - g_free(xd->tid); + g_free(xd->xfer_peer_idstring); + g_free(xd->xfer_idstring_for_relay); if (xd->tx_handler) purple_input_remove(xd->tx_handler); g_free(xd); } - -static void yahoo_xfer_y7_request_next_file(PurpleXfer *xfer) -{ - struct yahoo_packet *pack; - struct yahoo_xfer_data *xd = xfer->data; - PurpleConnection *gc = xd->gc; - struct yahoo_data *yd = gc->proto_data; - - g_return_if_fail(xd->y7); - - pack = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER_ACCEPT, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pack, "sssi", - 1, purple_connection_get_display_name(xd->gc), - 5, xfer->who, - 265, xd->tid, - 271, 1); - yahoo_packet_send_and_free(pack, yd); -} - -static void yahoo_xfer_y7_cancel_receive(PurpleXfer *xfer) -{ - struct yahoo_packet *pack; - struct yahoo_xfer_data *xd = xfer->data; - PurpleConnection *gc = xd->gc; - struct yahoo_data *yd = gc->proto_data; - - g_return_if_fail(xd->y7); - - pack = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER_ACCEPT, -1, 0); - yahoo_packet_hash(pack, "sssi", - 1, purple_connection_get_display_name(gc), - 5, xfer->who, - 265, xd->tid, - 66, -1); - yahoo_packet_send_and_free(pack, yd); -} - -static void yahoo_xfer_y7_accept_file(PurpleXfer *xfer) -{ - struct yahoo_packet *pack; - struct yahoo_xfer_data *xd = xfer->data; - PurpleConnection *gc = xd->gc; - struct yahoo_data *yd = gc->proto_data; - - g_return_if_fail(xd->y7); - - pack = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER_ACCEPT, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pack, "ssssis", - 1, purple_connection_get_display_name(gc), - 5, xfer->who, /* XXX this needs an accessor */ - 265, xd->tid, - 27, purple_xfer_get_filename(xfer), /* XXX this might be of incorrect encoding */ - 249, 3, - 251, xd->token); - yahoo_packet_send_and_free(pack, yd); -} - static void yahoo_receivefile_send_cb(gpointer data, gint source, PurpleInputCondition condition) { PurpleXfer *xfer; @@ -160,7 +146,6 @@ { PurpleXfer *xfer; struct yahoo_xfer_data *xd; - struct yahoo_data *yd; purple_debug(PURPLE_DEBUG_INFO, "yahoo", "AAA - in yahoo_receivefile_connected\n"); @@ -176,22 +161,11 @@ } xfer->fd = source; - yd = xd->gc->proto_data; /* The first time we get here, assemble the tx buffer */ if (xd->txbuflen == 0) { - if (!xd->y7) - xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", - xd->path, xd->host); - else - xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\n" - "Connection: close\r\n" - "Accept: */*\r\n" - "Host: %s\r\n" - "Cookie: Y=%s; T=%s\r\n" - "\r\n", - xd->path, xd->host, yd->cookie_y, yd->cookie_t); - purple_debug(PURPLE_DEBUG_INFO, "yahoo_filexfer", "HTTP request: [%s]\n", xd->txbuf); + xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", + xd->path, xd->host); xd->txbuflen = strlen(xd->txbuf); xd->txbuf_written = 0; } @@ -356,9 +330,6 @@ } } } else { - if (xfer_data->y7) - yahoo_xfer_y7_accept_file(xfer); - xfer->fd = -1; if (purple_proxy_connect(NULL, account, xfer_data->host, xfer_data->port, yahoo_receivefile_connected, xfer) == NULL) { @@ -369,23 +340,67 @@ } } +static void yahoo_xfer_init_15(PurpleXfer *xfer) +{ + struct yahoo_xfer_data *xfer_data; + PurpleConnection *gc; + PurpleAccount *account; + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + xfer_data = xfer->data; + gc = xfer_data->gc; + yd = gc->proto_data; + account = purple_connection_get_account(gc); + + if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { + gchar *filename; + filename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15, + YAHOO_STATUS_AVAILABLE, + yd->session_id); + yahoo_packet_hash(pkt, "sssiiiisiii", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 222, 1, + 266, 1, + 302, 268, + 300, 268, + 27, filename, + 28, xfer->size, + 301, 268, + 303, 268); + g_free(filename); + } else { + if(xfer_data->firstoflist == TRUE) { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15, + YAHOO_STATUS_AVAILABLE, yd->session_id); + + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 222, 3); + } else { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15, + YAHOO_STATUS_AVAILABLE, yd->session_id); + + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 271, 1); + } + } + yahoo_packet_send_and_free(pkt, yd); +} + static void yahoo_xfer_start(PurpleXfer *xfer) { /* We don't need to do anything here, do we? */ } -static void yahoo_xfer_end(PurpleXfer *xfer) -{ - struct yahoo_xfer_data *xfer_data; - - xfer_data = xfer->data; - - if (xfer_data) - yahoo_xfer_data_free(xfer_data); - xfer->data = NULL; - -} - static guint calculate_length(const gchar *l, size_t len) { int i; @@ -418,8 +433,6 @@ if ((purple_xfer_get_size(xfer) > 0) && (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer))) { purple_xfer_set_completed(xfer, TRUE); - if (xd->y7) - yahoo_xfer_y7_request_next_file(xfer); return 0; } else return -1; @@ -499,6 +512,42 @@ xfer_data = xfer->data; + if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15) + { + PurpleConnection *gc; + PurpleAccount *account; + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + gc = xfer_data->gc; + yd = gc->proto_data; + account = purple_connection_get_account(gc); + if(xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */ + { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, + YAHOO_STATUS_DISCONNECTED, + yd->session_id); + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 66, -1); + } + else + { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15, + YAHOO_STATUS_AVAILABLE, + yd->session_id); + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 222, 2); + } + yahoo_packet_send_and_free(pkt, yd); + } + + if (xfer_data) yahoo_xfer_data_free(xfer_data); xfer->data = NULL; @@ -510,22 +559,145 @@ xfer_data = xfer->data; - if (xfer_data) { - if (xfer_data->y7) - yahoo_xfer_y7_cancel_receive(xfer); + if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15) + { + + PurpleConnection *gc; + PurpleAccount *account; + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + gc = xfer_data->gc; + yd = gc->proto_data; + account = purple_connection_get_account(gc); + if(!xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */ + { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15, + YAHOO_STATUS_AVAILABLE, + yd->session_id); + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 222, 4); + } + else + { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15, + YAHOO_STATUS_DISCONNECTED, + yd->session_id); + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 66, -1); + } + yahoo_packet_send_and_free(pkt, yd); + } + + if (xfer_data) yahoo_xfer_data_free(xfer_data); - } xfer->data = NULL; } -static void yahoo_xfer_request_denied(PurpleXfer *xfer) +static void yahoo_xfer_end(PurpleXfer *xfer_old) { struct yahoo_xfer_data *xfer_data; + PurpleXfer *xfer = NULL; + PurpleConnection *gc; + struct yahoo_data *yd; - xfer_data = xfer->data; + xfer_data = xfer_old->data; + if(xfer_data && xfer_data->version == 15 + && purple_xfer_get_type(xfer_old) == PURPLE_XFER_RECEIVE + && xfer_data->filename_list) { + + /* removing top of filename & size list completely */ + g_free( xfer_data->filename_list->data ); + g_free( xfer_data->size_list->data ); + + xfer_data->filename_list->data = NULL; + xfer_data->size_list->data = NULL; + + xfer_data->filename_list = g_slist_delete_link(xfer_data->filename_list, xfer_data->filename_list); + xfer_data->size_list = g_slist_delete_link(xfer_data->size_list, xfer_data->size_list); + + /* if there are still more files */ + if(xfer_data->filename_list) + { + gchar* filename; + long filesize; + + filename = xfer_data->filename_list->data; + filesize = atol( xfer_data->size_list->data ); + + gc = xfer_data->gc; + yd = gc->proto_data; - if (xfer_data->y7) - yahoo_xfer_y7_cancel_receive(xfer); + /* setting up xfer_data for next file's tranfer */ + g_free(xfer_data->host); + g_free(xfer_data->path); + g_free(xfer_data->txbuf); + g_free(xfer_data->rxqueue); + g_free(xfer_data->xfer_idstring_for_relay); + if (xfer_data->tx_handler) + purple_input_remove(xfer_data->tx_handler); + xfer_data->host = NULL; + xfer_data->host = NULL; + xfer_data->port = 0; + xfer_data->expires = 0; + xfer_data->started = FALSE; + xfer_data->txbuf = NULL; + xfer_data->txbuflen = 0; + xfer_data->txbuf_written = 0; + xfer_data->tx_handler = 0; + xfer_data->rxqueue = NULL; + xfer_data->rxlen = 0; + xfer_data->xfer_idstring_for_relay = NULL; + xfer_data->info_val_249 = 0; + xfer_data->status_15 = STARTED; + xfer_data->firstoflist = FALSE; + + /* Dereference xfer_data from old xfer */ + xfer_old->data = NULL; + + /* Build the file transfer handle. */ + xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, xfer_old->who); + + + if (xfer) { + /* Set the info about the incoming file. */ + char *utf8_filename = yahoo_string_decode(gc, filename, TRUE); + purple_xfer_set_filename(xfer, utf8_filename); + g_free(utf8_filename); + purple_xfer_set_size(xfer, filesize); + + xfer->data = xfer_data; + + /* Setup our I/O op functions */ + purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); + purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); + purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); + purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); + purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); + purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); + purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); + purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv); + + /*update map to current xfer*/ + g_hash_table_remove(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring); + g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer); + + /* Now perform the request */ + purple_xfer_request(xfer); + } + return; + } + } + if (xfer_data) + yahoo_xfer_data_free(xfer_data); + xfer_old->data = NULL; + } void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -721,165 +893,6 @@ } } -void yahoo_process_y7_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = gc->proto_data; - char *who = NULL, *name = NULL; - int ttype = 0; - char *tid = NULL; - GSList *l = pkt->hash; - - while (l) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 4: - /* them */ - who = pair->value; - break; - case 5: - /* us */ - name = pair->value; - break; - case 222: - /* 1=send, 2=cancel, 3=accept, 4=reject */ - if(pair->value) - ttype = atoi(pair->value); - break; - case 265: - /* transfer ID */ - tid = pair->value; - break; - case 266: - /* number of files */ - break; - case 27: - /* filename */ - break; - case 28: - /* filesize */ - break; - } - - l = l->next; - } - if (ttype == 1 && tid) { - /* We auto-accept all offers here, and ask the user about each individual - * file in yahoo_process_y7_filetransfer_info. This works fine for receiving - * a single file; when receiving multiple canceling one in the middle - * will also cancel the rest of them. - * Maybe TODO: UI and API allowing transfer of multiple files as a package. */ - struct yahoo_packet *pack; - pack = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pack, "sssi", 1, name, 5, who, 265, tid, 222, 3); - yahoo_packet_send_and_free(pack, yd); - } -} - -void yahoo_process_y7_filetransfer_info(PurpleConnection *gc, struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = gc->proto_data; - char *who = NULL, *name = NULL; - int medium = 0; - char *tid = NULL, *server_host = NULL, *server_token = NULL, *filename = NULL; - GSList *l = pkt->hash; - struct yahoo_packet *pack; - PurpleXfer *xfer; - struct yahoo_xfer_data *xfer_data; - - while (l) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 4: - /* them */ - who = pair->value; - break; - case 5: - /* us */ - name = pair->value; - break; - case 249: - /* 1=p2p, 3=reflection server */ - if(pair->value) - medium = atoi(pair->value); - break; - case 265: - /* transfer ID */ - tid = pair->value; - break; - case 27: - filename = pair->value; - break; - case 250: - server_host = pair->value; - break; - case 251: - server_token = pair->value; - break; - } - - l = l->next; - } - if (medium == 1) { - /* reject P2P transfers */ - pack = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER_ACCEPT, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pack, "sssi", 1, name, 5, who, 265, tid, 66, -3); - yahoo_packet_send_and_free(pack, yd); - return; - } - - if (medium != 3) { - purple_debug_error("yahoo", "Unexpected medium %d.\n", medium); - /* weird */ - return; - } - - /* Setup the Yahoo-specific file transfer data */ - xfer_data = g_new0(struct yahoo_xfer_data, 1); - xfer_data->gc = gc; - xfer_data->host = g_strdup(server_host); - xfer_data->token = g_strdup(server_token); - xfer_data->tid = g_strdup(tid); - xfer_data->port = 80; - xfer_data->y7 = TRUE; - - /* TODO: full urlencode here */ - server_token = purple_strreplace(server_token, "\002", "%02"); - xfer_data->path = g_strdup_printf("relay?token=%s&sender=%s&recver=%s", - server_token, who, name); - g_free(server_token); - - purple_debug_misc("yahoo_filexfer", "Host is %s, port is %d, path is %s.\n", - xfer_data->host, xfer_data->port, xfer_data->path); - - /* Build the file transfer handle. */ - xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, who); - xfer->data = xfer_data; - - /* Set the info about the incoming file. */ - { - char *utf8_filename = yahoo_string_decode(gc, filename, TRUE); - purple_xfer_set_filename(xfer, utf8_filename); - g_free(utf8_filename); - } - - /* purple_xfer_set_size(xfer, filesize); */ - - /* Setup our I/O op functions */ - purple_xfer_set_init_fnc(xfer, yahoo_xfer_init); - purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); - purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); - purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); - purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); - purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); - purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); - purple_xfer_set_request_denied_fnc(xfer, yahoo_xfer_request_denied); - - /* Now perform the request */ - purple_xfer_request(xfer); -} - PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who) { PurpleXfer *xfer; @@ -909,15 +922,641 @@ return xfer; } +static gchar* yahoo_xfer_new_xfer_id() +{ + gchar *ans; + int i,j; + ans = g_strnfill(24, ' '); + ans[23] = '$'; + ans[22] = '$'; + for(i = 0; i < 22; i++) + { + j = g_random_int_range (0,61); + if(j < 26) + ans[i] = j + 'a'; + else if(j < 52) + ans[i] = j - 26 + 'A'; + else + ans[i] = j - 52 + '0'; + } + return ans; +} + +static void yahoo_xfer_dns_connected_15(GSList *hosts, gpointer data, const char *error_message) +{ + PurpleXfer *xfer; + struct yahoo_xfer_data *xd; + struct sockaddr_in *addr; + struct yahoo_packet *pkt; + long actaddr; + long a,b,c,d; + PurpleConnection *gc; + PurpleAccount *account; + struct yahoo_data *yd; + gchar *url; + gchar *filename; + + if (!(xfer = data)) + return; + if (!(xd = xfer->data)) + return; + gc = xd->gc; + account = purple_connection_get_account(gc); + yd = gc->proto_data; + + if(!hosts) + { + purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n"); + purple_xfer_cancel_remote(xfer); + return; + } + + /* Discard the length... */ + hosts = g_slist_remove(hosts, hosts->data); + if(!hosts) + { + purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n"); + purple_xfer_cancel_remote(xfer); + return; + } + + /*TODO:actually, u must try with addr no.1 , if its not working addr no.2 .....*/ + addr = hosts->data; + actaddr = addr->sin_addr.s_addr; + d = actaddr % 256; + actaddr = (actaddr - d) / 256; + c = actaddr % 256; + actaddr = (actaddr - c) / 256; + b = actaddr % 256; + actaddr = (actaddr - b) / 256; + a = actaddr; + if(yd->jp) + xd->port = YAHOOJP_XFER_RELAY_PORT; + else + xd->port = YAHOO_XFER_RELAY_PORT; + + url = g_strdup_printf("%ld.%ld.%ld.%ld", d, c, b, a); + if (!purple_url_parse(url, &(xd->host), &(xd->port), &(xd->path), NULL, NULL)) { + purple_xfer_cancel_remote(xfer); + return; + } + g_free(url); + /* Free the address... */ + g_free(hosts->data); + hosts = g_slist_remove(hosts, hosts->data); + addr = NULL; + while (hosts != NULL) + { + /* Discard the length... */ + hosts = g_slist_remove(hosts, hosts->data); + /* Free the address... */ + g_free(hosts->data); + hosts = g_slist_remove(hosts, hosts->data); + } + + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id); + filename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); + + yahoo_packet_hash(pkt, "ssssis", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xd->xfer_peer_idstring, + 27, filename, + 249, 3, + 250, xd->host); + + g_free(filename); + yahoo_packet_send_and_free(pkt, yd); +} + + void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file) { + struct yahoo_xfer_data *xfer_data; + struct yahoo_data *yd; + int ver = 0; PurpleXfer *xfer = yahoo_new_xfer(gc, who); + YahooFriend *yf = yahoo_friend_find(gc, who); + /* To determine whether client uses ymsg 15 i.e. client is higher than YM 7 */ + if(yf && yf->version_id > 500000) + ver=15; g_return_if_fail(xfer != NULL); + if(ver == 15) { + yd = gc->proto_data; + xfer_data = xfer->data; + xfer_data->status_15 = STARTED; + purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); + xfer_data->version = 15; + xfer_data->xfer_peer_idstring = yahoo_xfer_new_xfer_id(); + g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer); + } + /* Now perform the request */ if (file) purple_xfer_request_accepted(xfer, file); else purple_xfer_request(xfer); } + +static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message);/*using this in recv_cb*/ +static void yahoo_xfer_recv_cb_15(gpointer data, gint source, PurpleInputCondition condition) +{ + PurpleXfer *xfer; + struct yahoo_xfer_data *xd; + int did; + gchar* buf; + gchar* t; + PurpleAccount *account; + PurpleConnection *gc; + + xfer = data; + xd = xfer->data; + account = purple_connection_get_account(xd->gc); + gc = xd->gc; + + buf=g_strnfill(1000, 0); + while((did = read(source, buf, 998)) > 0) + { + xd->txbuflen += did; + buf[did] = '\0'; + t = xd->txbuf; + xd->txbuf = g_strconcat(t,buf,NULL); + g_free(t); + } + g_free(buf); + + if (did < 0 && errno == EAGAIN) return; + else if (did < 0) { + purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno); + purple_xfer_cancel_remote(xfer); + return; + } + + purple_input_remove(xd->tx_handler); + xd->tx_handler = 0; + xd->txbuflen = 0; + + if(xd->status_15 == HEAD_REQUESTED) { + xd->status_15 = HEAD_REPLY_RECEIVED; + close(source);/*Is this required?*/ + g_free(xd->txbuf); + xd->txbuf = NULL; + if (purple_proxy_connect(NULL, account, xd->host, xd->port, yahoo_xfer_connected_15, xfer) == NULL) + { + purple_notify_error(gc, NULL, _("File Transfer Failed"), + _("Unable to establish file descriptor.")); + purple_xfer_cancel_remote(xfer); + } + } else { + purple_debug_error("yahoo","Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", + purple_xfer_get_type(xfer), + xd->status_15); + return; + } +} + +static void yahoo_xfer_send_cb_15(gpointer data, gint source, PurpleInputCondition condition) +{ + PurpleXfer *xfer; + struct yahoo_xfer_data *xd; + int remaining, written; + + xfer = data; + xd = xfer->data; + remaining = xd->txbuflen - xd->txbuf_written; + written = write(source, xd->txbuf + xd->txbuf_written, remaining); + + if (written < 0 && errno == EAGAIN) + written = 0; + else if (written <= 0) { + purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno); + purple_xfer_cancel_remote(xfer); + return; + } + + if (written < remaining) { + xd->txbuf_written += written; + return; + } + + purple_input_remove(xd->tx_handler); + xd->tx_handler = 0; + g_free(xd->txbuf); + xd->txbuf = NULL; + xd->txbuflen = 0; + xd->txbuf_written = 0; + + if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED) + { + xd->status_15 = HEAD_REQUESTED; + xd->tx_handler = purple_input_add(source, PURPLE_INPUT_READ, yahoo_xfer_recv_cb_15, xfer); + yahoo_xfer_recv_cb_15(xfer, source, PURPLE_INPUT_READ); + } + else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED) + { + xd->status_15 = TRANSFER_PHASE; + xfer->fd = source; + purple_xfer_start(xfer, source, NULL, 0); + } + else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == ACCEPTED) + { + xd->status_15 = TRANSFER_PHASE; + xfer->fd = source; + purple_xfer_start(xfer, source, NULL, 0); + } + else + { + purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15); + return; + } + +} + + +static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message) +{ + PurpleXfer *xfer; + struct yahoo_xfer_data *xd; + PurpleAccount *account; + struct yahoo_data* yd; + + if (!(xfer = data)) + return; + if (!(xd = xfer->data)) + return; + yd = xd->gc->proto_data; + account = purple_connection_get_account(xd->gc); + if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) { + purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer), + xfer->who, _("Unable to connect.")); + purple_xfer_cancel_remote(xfer); + return; + } + /* The first time we get here, assemble the tx buffer */ + if (xd->txbuflen == 0) + { + gchar* cookies; + cookies = yahoo_get_cookies(xd->gc); + if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == ACCEPTED) + { + xd->txbuf = g_strdup_printf("POST /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\nCookie:%s\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\nHost: %s\r\nContent-Length: %ld\r\nCache-Control: no-cache\r\n\r\n", + purple_url_encode(xd->xfer_idstring_for_relay), + purple_normalize(account, purple_account_get_username(account)), + xfer->who, + cookies, + xd->host, + (long int)xfer->size); + } + else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED) + { + xd->txbuf = g_strdup_printf("HEAD /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\nAccept:*/*\r\nCookie:%s\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\nHost:%s\r\nContent-Length: 0\r\nCache-Control: no-cache\r\n\r\n", + purple_url_encode(xd->xfer_idstring_for_relay), + purple_normalize(account, purple_account_get_username(account)), + xfer->who, + cookies, + xd->host); + } + else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED) + { + xd->txbuf = g_strdup_printf("GET /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\nCookie:%s\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\nHost:%s\r\nConnection: Keep-Alive\r\n\r\n", + purple_url_encode(xd->xfer_idstring_for_relay), + purple_normalize(account, purple_account_get_username(account)), + xfer->who, + cookies, + xd->host); + } + else + { + purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15); + g_free(cookies); + return; + } + xd->txbuflen = strlen(xd->txbuf); + xd->txbuf_written = 0; + g_free(cookies); + } + + if (!xd->tx_handler) + { + xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE, + yahoo_xfer_send_cb_15, xfer); + yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE); + } +} + +void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt) +{ + char *from = NULL; + char *to = NULL; + char *imv = NULL; + long val_222 = 0L; + PurpleXfer *xfer; + struct yahoo_data *yd; + struct yahoo_xfer_data *xfer_data; + char *service = NULL; + char *filename = NULL; + char *xfer_peer_idstring = NULL; + unsigned long filesize = 0L; + GSList *l; + GSList *filename_list = NULL; + GSList *size_list = NULL; + int nooffiles = 0; + + yd = gc->proto_data; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 4: + from = pair->value; + break; + case 5: + to = pair->value; + break; + case 265: + xfer_peer_idstring = pair->value; + break; + case 27: + filename_list = g_slist_prepend(filename_list, g_strdup(pair->value)); + nooffiles++; + break; + case 28: + size_list = g_slist_prepend(size_list, g_strdup(pair->value)); + break; + case 222: + val_222 = atol(pair->value); + /* 1=send, 2=cancel, 3=accept, 4=reject */ + break; + + /*check for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it.*/ + case 49: + service = pair->value; + break; + case 63: + imv = pair->value; + break; + /*end check*/ + + } + } + if(!xfer_peer_idstring) + return; + + if(val_222 == 2 || val_222 == 4) + { + xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, + xfer_peer_idstring); + if(!xfer) return; + purple_xfer_cancel_remote(xfer); + return; + } + if(val_222 == 3) + { + xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, + xfer_peer_idstring); + if(!xfer) + return; + /* + * In the file trans info packet tht we must reply with , we are supposed to mention the ip address... + * purple connect does not give me a way of finding the ip address... + * so, purple dnsquery is used... but retries, trying with next ip address etc. is not implemented..TODO + */ + if (yd->jp) + { + purple_dnsquery_a(YAHOOJP_XFER_RELAY_HOST, YAHOOJP_XFER_RELAY_PORT, yahoo_xfer_dns_connected_15, xfer); + } + else + { + purple_dnsquery_a(YAHOO_XFER_RELAY_HOST, YAHOO_XFER_RELAY_PORT, yahoo_xfer_dns_connected_15, xfer); + } + return; + } + + /*processing for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it.*/ + /* + * The remote user has changed their IMVironment. We + * record it for later use. + */ + if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) { + g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv)); + return; + } + + if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) { + if (service && (strcmp("FILEXFER", service) != 0)) { + purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service); + return; + } + } + /*end processing*/ + + if(!filename_list) + return; + /* have to change list into order in which client at other end sends */ + filename_list = g_slist_reverse(filename_list); + size_list = g_slist_reverse(size_list); + filename = filename_list->data; + filesize = atol(size_list->data); + + if(!from) return; + xfer_data = g_new0(struct yahoo_xfer_data, 1); + xfer_data->version = 15; + xfer_data->firstoflist = TRUE; + xfer_data->gc = gc; + xfer_data->xfer_peer_idstring = g_strdup(xfer_peer_idstring); + xfer_data->filename_list = filename_list; + xfer_data->size_list = size_list; + + /* Build the file transfer handle. */ + xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from); + xfer->message = NULL; + + if (xfer) + { + /* Set the info about the incoming file. */ + char *utf8_filename = yahoo_string_decode(gc, filename, TRUE); + purple_xfer_set_filename(xfer, utf8_filename); + g_free(utf8_filename); + purple_xfer_set_size(xfer, filesize); + + xfer->data = xfer_data; + + + /* Setup our I/O op functions */ + purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); + purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); + purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); + purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); + purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); + purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); + purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); + purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv); + + g_hash_table_insert(yd->xfer_peer_idstring_map, + xfer_data->xfer_peer_idstring, + xfer); + + if(nooffiles > 1) { + gchar* message; + message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), xfer->who, nooffiles); + purple_xfer_conversation_write(xfer, message, FALSE); + g_free(message); + } + /* Now perform the request */ + purple_xfer_request(xfer); + } +} + +void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt) +{ + char *from = NULL; + char *to = NULL; + char *url = NULL; + long val_249 = 0; + long val_66 = 0; + PurpleXfer *xfer; + struct yahoo_data *yd; + struct yahoo_xfer_data *xfer_data; + char *filename = NULL; + char *xfer_peer_idstring = NULL; + char *xfer_idstring_for_relay = NULL; + GSList *l; + struct yahoo_packet *pkt_to_send; + PurpleAccount *account; + + yd = gc->proto_data; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 4: + from = pair->value; + break; + case 5: + to = pair->value; + break; + case 265: + xfer_peer_idstring = pair->value; + break; + case 27: + filename = pair->value; + break; + case 66: + val_66 = strtol(pair->value, NULL, 10); + break; + case 249: + val_249 = strtol(pair->value, NULL, 10); /* + * really pissed off with this- i hv seen 2 occurences of this + * being 1(its normally 3) - and in those cases, the url + * format and corresponding processing seems to be different + * (i havent tested - couldnt reproduce a 1), although i + * guess its easier. + */ + break; + case 250: + url = pair->value; + break; + case 251: + xfer_idstring_for_relay = pair->value; + break; + } + } + + if(!xfer_peer_idstring) + return; + + xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring); + + if(!xfer) return; + + if(val_66==-1) + { + purple_xfer_cancel_remote(xfer); + return; + } + + xfer_data = xfer->data; + + xfer_data->info_val_249 = val_249; + xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay); + if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) { + purple_xfer_cancel_remote(xfer); + return; + } + + account = purple_connection_get_account(xfer_data->gc); + + pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15, + YAHOO_STATUS_AVAILABLE, yd->session_id); + + yahoo_packet_hash(pkt_to_send, "ssssisi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 27, xfer->filename, + 249, xfer_data->info_val_249, + 251, xfer_data->xfer_idstring_for_relay, + 222, 3); + + yahoo_packet_send_and_free(pkt_to_send, yd); + if (purple_proxy_connect(NULL, account, xfer_data->host, xfer_data->port, + yahoo_xfer_connected_15, xfer) == NULL) { + purple_notify_error(gc, NULL, _("File Transfer Failed"), + _("Unable to establish file descriptor.")); + purple_xfer_cancel_remote(xfer); + } + +} +/*TODO: Check filename etc. No probs till some hacker comes in the way*/ +void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt) +{ + gchar *xfer_peer_idstring = NULL; + gchar *xfer_idstring_for_relay = NULL; + PurpleXfer *xfer; + struct yahoo_data *yd; + struct yahoo_xfer_data *xfer_data; + GSList *l; + PurpleAccount *account; + long val_66 = 0; + + yd = gc->proto_data; + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 251: + xfer_idstring_for_relay = pair->value; + break; + case 265: + xfer_peer_idstring = pair->value; + break; + case 66: + val_66 = atol(pair->value); + } + } + + xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring); + if(!xfer) return; + + if(val_66 == -1 || !(xfer_idstring_for_relay)) + { + purple_xfer_cancel_remote(xfer); + return; + } + + xfer_data = xfer->data; + xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay); + xfer_data->status_15 = ACCEPTED; + account = purple_connection_get_account(gc); + + if (purple_proxy_connect(NULL, account, xfer_data->host, xfer_data->port, + yahoo_xfer_connected_15, xfer) == NULL) + { + purple_notify_error(gc, NULL, _("File Transfer Failed"),_("Unable to connect")); + purple_xfer_cancel_remote(xfer); + } +}
--- a/libpurple/protocols/yahoo/yahoo_filexfer.h Fri Jan 11 00:01:33 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.h Sat Jan 12 02:24:51 2008 +0000 @@ -30,16 +30,6 @@ void yahoo_process_p2pfilexfer( PurpleConnection *gc, struct yahoo_packet *pkt ); /** - * Process ymsg version 7 file receive invites. - */ -void yahoo_process_y7_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt); - -/** - * Process ymsg version 7 file receive connection setups. - */ -void yahoo_process_y7_filetransfer_info(PurpleConnection *gc, struct yahoo_packet *pkt); - -/** * Process ymsg file receive invites. */ void yahoo_process_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt); @@ -61,4 +51,8 @@ */ void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file); +void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt); +void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt); +void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt); + #endif
--- a/libpurple/protocols/yahoo/yahoo_friend.h Fri Jan 11 00:01:33 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_friend.h Sat Jan 12 02:24:51 2008 +0000 @@ -48,6 +48,7 @@ gboolean bicon_sent_request; YahooPresenceVisibility presence; int protocol; /* 1=LCS, 2=MSN*/ + long int version_id; } YahooFriend; YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name);
--- a/libpurple/protocols/yahoo/yahoo_packet.h Fri Jan 11 00:01:33 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_packet.h Sat Jan 12 02:24:51 2008 +0000 @@ -99,12 +99,12 @@ YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8, YAHOO_SERVICE_AUDIBLE = 0xd0, YAHOO_SERVICE_AUTH_REQ_15 = 0xd6, - YAHOO_SERVICE_Y7_FILETRANSFER = 0xdc, - YAHOO_SERVICE_Y7_FILETRANSFER_INFO = 0xdd, - YAHOO_SERVICE_Y7_FILETRANSFER_ACCEPT = 0xde, YAHOO_SERVICE_CHGRP_15 = 0xe7, YAHOO_SERVICE_STATUS_15 = 0xf0, - YAHOO_SERVICE_LIST_15 = 0xf1, + YAHOO_SERVICE_LIST_15 = 0Xf1, + YAHOO_SERVICE_FILETRANS_15 = 0xdc, + YAHOO_SERVICE_FILETRANS_INFO_15 = 0xdd, + YAHOO_SERVICE_FILETRANS_ACC_15 = 0xde, YAHOO_SERVICE_WEBLOGIN = 0x0226, YAHOO_SERVICE_SMS_MSG = 0x02ea };