im.pidgin.pidgin: 10720dc998c08a66c7431e39bdfa7e072d49bd05
datallah at pidgin.im
datallah at pidgin.im
Sun Dec 9 21:11:03 EST 2007
-----------------------------------------------------------------
Revision: 10720dc998c08a66c7431e39bdfa7e072d49bd05
Ancestor: a32d9ba1c9795def41626bba1a1196cd996f38c0
Author: datallah at pidgin.im
Date: 2007-12-10T02:07:01
Branch: im.pidgin.pidgin
Modified files:
libpurple/protocols/yahoo/yahoo.c
libpurple/protocols/yahoo/yahoo.h
libpurple/protocols/yahoo/yahoo_filexfer.c
libpurple/protocols/yahoo/yahoo_filexfer.h
libpurple/protocols/yahoo/yahoo_packet.h
ChangeLog:
Patch from Alex Badea to support receiving files from Yahoo users using the newer yahoo protocol. Committing this is very long overdue, it somehow slipped through the cracks for a long time. References #708.
-------------- next part --------------
============================================================
--- libpurple/protocols/yahoo/yahoo.c 7d6acdda737d9d9ce2ed0645e2ec295427be64a3
+++ libpurple/protocols/yahoo/yahoo.c 6cdb54f25d9518f09c4b1b9aed970201745e54e6
@@ -493,13 +493,14 @@ static void yahoo_process_cookie(struct
static void yahoo_process_cookie(struct yahoo_data *yd, char *c)
{
if (c[0] == 'Y') {
- if (yd->cookie_y)
- g_free(yd->cookie_y);
+ g_free(yd->cookie_y);
yd->cookie_y = _getcookie(c);
} else if (c[0] == 'T') {
- if (yd->cookie_t)
- g_free(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]);
}
@@ -2433,6 +2434,12 @@ static void yahoo_packet_process(PurpleC
case YAHOO_SERVICE_AUDIBLE:
yahoo_process_audible(gc, pkt);
break;
+ case YAHOO_SERVICE_Y7_FILETRANSFER:
+ yahoo_process_y7_filetransfer(gc, pkt);
+ break;
+ case YAHOO_SERVICE_Y7_FILETRANSFER_INFO:
+ yahoo_process_y7_filetransfer_info(gc, pkt);
+ break;
default:
purple_debug(PURPLE_DEBUG_ERROR, "yahoo",
"Unhandled service 0x%02x\n", pkt->service);
@@ -3012,6 +3019,7 @@ static void yahoo_close(PurpleConnection
g_free(yd->cookie_y);
g_free(yd->cookie_t);
+ g_free(yd->cookie_c);
if (yd->txhandler)
purple_input_remove(yd->txhandler);
============================================================
--- libpurple/protocols/yahoo/yahoo.h 6d20a9b3ecdc3b40270af5b8e6b8015d960410b6
+++ libpurple/protocols/yahoo/yahoo.h 5e20f9cd1b973a4bc9385cb88d3ebe0eec9eb170
@@ -134,6 +134,7 @@ struct yahoo_data {
gsize auth_written;
char *cookie_y;
char *cookie_t;
+ char *cookie_c;
int session_id;
gboolean jp;
gboolean wm; /* connected w/ web messenger method */
============================================================
--- libpurple/protocols/yahoo/yahoo_filexfer.c d5e4c78e154de7ffdf613c0f80e2f59ca85a32c1
+++ libpurple/protocols/yahoo/yahoo_filexfer.c 2e8787967696ae8427bdc696b6387039106ab35e
@@ -46,6 +46,10 @@ struct yahoo_xfer_data {
guint tx_handler;
gchar *rxqueue;
guint rxlen;
+
+ gboolean y7; /* true for Y7 transfers (receive only for now) */
+ gchar *token;
+ gchar *tid;
};
static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd)
@@ -53,11 +57,70 @@ static void yahoo_xfer_data_free(struct
g_free(xd->host);
g_free(xd->path);
g_free(xd->txbuf);
+ g_free(xd->token);
+ g_free(xd->tid);
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;
@@ -97,6 +160,7 @@ static void yahoo_receivefile_connected(
{
PurpleXfer *xfer;
struct yahoo_xfer_data *xd;
+ struct yahoo_data *yd;
purple_debug(PURPLE_DEBUG_INFO, "yahoo",
"AAA - in yahoo_receivefile_connected\n");
@@ -112,11 +176,22 @@ static void yahoo_receivefile_connected(
}
xfer->fd = source;
+ yd = xd->gc->proto_data;
/* The first time we get here, assemble the tx buffer */
if (xd->txbuflen == 0) {
- xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n",
- xd->path, xd->host);
+ 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->txbuflen = strlen(xd->txbuf);
xd->txbuf_written = 0;
}
@@ -281,6 +356,9 @@ static void yahoo_xfer_init(PurpleXfer *
}
}
} 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) {
@@ -340,6 +418,8 @@ static gssize yahoo_xfer_read(guchar **b
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;
@@ -430,11 +510,24 @@ static void yahoo_xfer_cancel_recv(Purpl
xfer_data = xfer->data;
- if (xfer_data)
+ if (xfer_data) {
+ if (xfer_data->y7)
+ yahoo_xfer_y7_cancel_receive(xfer);
yahoo_xfer_data_free(xfer_data);
+ }
xfer->data = NULL;
}
+static void yahoo_xfer_request_denied(PurpleXfer *xfer)
+{
+ struct yahoo_xfer_data *xfer_data;
+
+ xfer_data = xfer->data;
+
+ if (xfer_data->y7)
+ yahoo_xfer_y7_cancel_receive(xfer);
+}
+
void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt)
{
GSList *l = pkt->hash;
@@ -628,6 +721,165 @@ void yahoo_process_filetransfer(PurpleCo
}
}
+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;
============================================================
--- libpurple/protocols/yahoo/yahoo_filexfer.h a75f10d2a0592643ced9d557449f7d621724e2c0
+++ libpurple/protocols/yahoo/yahoo_filexfer.h 5209d841ca6d5976a7959965f3cb5e9077174828
@@ -30,6 +30,16 @@ void yahoo_process_p2pfilexfer( PurpleCo
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);
============================================================
--- libpurple/protocols/yahoo/yahoo_packet.h d207c32b02fd3d4dc33f7fd07dfe80c1dfa6900b
+++ libpurple/protocols/yahoo/yahoo_packet.h 226333c6004341193b28cc7a57dcfda845f287f4
@@ -99,9 +99,12 @@ enum yahoo_service { /* these are easier
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_WEBLOGIN = 0x0226,
YAHOO_SERVICE_SMS_MSG = 0x02ea
};
More information about the Commits
mailing list