summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Sales de Andrade <qulogic@pidgin.im>2009-11-20 00:35:30 +0000
committerElliott Sales de Andrade <qulogic@pidgin.im>2009-11-20 00:35:30 +0000
commitacb547f79901793e261eed3817399b4711f446d6 (patch)
treebf7c0d980d365a462de59f9fd259baa2be190b4e
parentac7164ce530ec784a47326c596724f05d99baf29 (diff)
parentc0f7985685359639dd0159498dc0087c9eac1b8a (diff)
downloadpidgin-acb547f79901793e261eed3817399b4711f446d6.tar.gz
propagate from branch 'im.pidgin.pidgin' (head 7c6adca0766f4f4ee1a0ce9a2c0680e9d1339df3)
to branch 'im.pidgin.cpw.darkrain42.msn.ft' (head 76761af122e89f59262882e9d39c289243815b01)
-rw-r--r--libpurple/protocols/msn/slp.c56
-rw-r--r--libpurple/protocols/msn/slp.h3
-rw-r--r--libpurple/protocols/msn/slpcall.c6
-rw-r--r--libpurple/protocols/msn/slpcall.h8
-rw-r--r--libpurple/protocols/msn/slplink.c43
-rw-r--r--libpurple/protocols/msn/slplink.h3
-rw-r--r--libpurple/protocols/msn/slpmsg.h1
7 files changed, 105 insertions, 15 deletions
diff --git a/libpurple/protocols/msn/slp.c b/libpurple/protocols/msn/slp.c
index 39b67f3f37..4aa235fbbd 100644
--- a/libpurple/protocols/msn/slp.c
+++ b/libpurple/protocols/msn/slp.c
@@ -96,6 +96,8 @@ msn_xfer_init(PurpleXfer *xfer)
g_free(content);
msn_slplink_send_queued_slpmsgs(slpcall->slplink);
+
+ purple_xfer_start(xfer, -1, NULL, 0);
}
void
@@ -131,6 +133,54 @@ msn_xfer_cancel(PurpleXfer *xfer)
}
}
+gssize
+msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer)
+{
+ MsnSlpCall *slpcall;
+
+ g_return_val_if_fail(xfer != NULL, -1);
+ g_return_val_if_fail(data != NULL, -1);
+ g_return_val_if_fail(len > 0, -1);
+
+ g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND, -1);
+
+ slpcall = xfer->data;
+ /* Not sure I trust it'll be there */
+ g_return_val_if_fail(slpcall != NULL, -1);
+
+ g_return_val_if_fail(slpcall->xfer_msg != NULL, -1);
+
+ slpcall->u.outgoing.len = len;
+ slpcall->u.outgoing.data = data;
+ msn_slplink_send_msgpart(slpcall->slplink, slpcall->xfer_msg);
+ return MIN(1202, len);
+}
+
+gssize
+msn_xfer_read(guchar **data, PurpleXfer *xfer)
+{
+ MsnSlpCall *slpcall;
+ gsize len;
+
+ g_return_val_if_fail(xfer != NULL, -1);
+ g_return_val_if_fail(data != NULL, -1);
+
+ g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE, -1);
+
+ slpcall = xfer->data;
+ /* Not sure I trust it'll be there */
+ g_return_val_if_fail(slpcall != NULL, -1);
+
+ /* Just pass up the whole GByteArray. We'll make another. */
+ *data = slpcall->u.incoming_data->data;
+ len = slpcall->u.incoming_data->len;
+
+ g_byte_array_free(slpcall->u.incoming_data, FALSE);
+ slpcall->u.incoming_data = g_byte_array_new();
+
+ return len;
+}
+
void
msn_xfer_progress_cb(MsnSlpCall *slpcall, gsize total_length, gsize len, gsize offset)
{
@@ -332,9 +382,7 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch,
account = slpcall->slplink->session->account;
- slpcall->cb = msn_xfer_completed_cb;
slpcall->end_cb = msn_xfer_end_cb;
- slpcall->progress_cb = msn_xfer_progress_cb;
slpcall->branch = g_strdup(branch);
slpcall->pending = TRUE;
@@ -357,6 +405,10 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch,
purple_xfer_set_init_fnc(xfer, msn_xfer_init);
purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel);
purple_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel);
+ purple_xfer_set_read_fnc(xfer, msn_xfer_read);
+ purple_xfer_set_write_fnc(xfer, msn_xfer_write);
+
+ slpcall->u.incoming_data = g_byte_array_new();
slpcall->xfer = xfer;
purple_xfer_ref(slpcall->xfer);
diff --git a/libpurple/protocols/msn/slp.h b/libpurple/protocols/msn/slp.h
index c9cee83f18..b2de049fb0 100644
--- a/libpurple/protocols/msn/slp.h
+++ b/libpurple/protocols/msn/slp.h
@@ -41,6 +41,9 @@ void msn_xfer_completed_cb(MsnSlpCall *slpcall,
const guchar *body, gsize size);
void msn_xfer_cancel(PurpleXfer *xfer);
+gssize msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer);
+gssize msn_xfer_read(guchar **data, PurpleXfer *xfer);
+
void msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session);
void msn_queue_buddy_icon_request(MsnUser *user);
diff --git a/libpurple/protocols/msn/slpcall.c b/libpurple/protocols/msn/slpcall.c
index 5a656cb50c..87f7ecec08 100644
--- a/libpurple/protocols/msn/slpcall.c
+++ b/libpurple/protocols/msn/slpcall.c
@@ -105,10 +105,13 @@ msn_slpcall_destroy(MsnSlpCall *slpcall)
slpcall->end_cb(slpcall, slpcall->slplink->session);
if (slpcall->xfer != NULL) {
+ if (purple_xfer_get_type(slpcall->xfer) == PURPLE_XFER_RECEIVE)
+ g_byte_array_free(slpcall->u.incoming_data, TRUE);
slpcall->xfer->data = NULL;
purple_xfer_unref(slpcall->xfer);
}
+
msn_slplink_remove_slpcall(slpcall->slplink, slpcall);
g_free(slpcall->id);
@@ -272,7 +275,8 @@ msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
slpcall->timer = 0;
}
- slpcall->cb(slpcall, body, body_len);
+ if (slpcall->cb)
+ slpcall->cb(slpcall, body, body_len);
slpcall->wasted = TRUE;
}
diff --git a/libpurple/protocols/msn/slpcall.h b/libpurple/protocols/msn/slpcall.h
index 445bac734b..5c7664a7da 100644
--- a/libpurple/protocols/msn/slpcall.h
+++ b/libpurple/protocols/msn/slpcall.h
@@ -72,6 +72,14 @@ struct _MsnSlpCall
char *data_info;
PurpleXfer *xfer;
+ union {
+ GByteArray *incoming_data;
+ struct {
+ gsize len;
+ const guchar *data;
+ } outgoing;
+ } u;
+ MsnSlpMessage *xfer_msg; /* A dirty hack */
MsnSlpCb cb;
void (*end_cb)(MsnSlpCall *slpcall, MsnSession *session);
diff --git a/libpurple/protocols/msn/slplink.c b/libpurple/protocols/msn/slplink.c
index 0b921fa633..89c727065c 100644
--- a/libpurple/protocols/msn/slplink.c
+++ b/libpurple/protocols/msn/slplink.c
@@ -232,7 +232,7 @@ msn_slplink_send_msg(MsnSlpLink *slplink, MsnMessage *msg)
}
}
-static void
+void
msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
{
MsnMessage *msg;
@@ -247,7 +247,13 @@ msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
if (slpmsg->offset < real_size)
{
- if (slpmsg->fp)
+ if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND &&
+ purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
+ {
+ len = MIN(1202, slpmsg->slpcall->u.outgoing.len);
+ msn_message_set_bin_data(msg, slpmsg->slpcall->u.outgoing.data, len);
+ }
+ else if (slpmsg->fp)
{
char data[1202];
len = fread(data, 1, sizeof(data), slpmsg->fp);
@@ -309,7 +315,13 @@ msg_ack(MsnMessage *msg, void *data)
if (slpmsg->offset < real_size)
{
- msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
+ if (slpmsg->slpcall->xfer)
+ {
+ slpmsg->slpcall->xfer_msg = slpmsg;
+ purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
+ }
+ else
+ msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
}
else
{
@@ -458,10 +470,10 @@ send_file_cb(MsnSlpCall *slpcall)
xfer = (PurpleXfer *)slpcall->xfer;
purple_xfer_start(slpcall->xfer, -1, NULL, 0);
- slpmsg->fp = xfer->dest_fp;
if (g_stat(purple_xfer_get_local_filename(xfer), &st) == 0)
slpmsg->size = st.st_size;
- xfer->dest_fp = NULL; /* Disable double fclose() */
+ else if (purple_xfer_get_size(xfer))
+ slpmsg->size = purple_xfer_get_size(xfer);
msn_slplink_send_slpmsg(slpcall->slplink, slpmsg);
}
@@ -489,6 +501,7 @@ msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
const char *data;
guint64 offset;
gsize len;
+ PurpleXfer *xfer = NULL;
if (purple_debug_is_verbose())
msn_slpmsg_show(msg);
@@ -525,12 +538,12 @@ msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
if (slpmsg->flags == 0x20 ||
slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030)
{
- PurpleXfer *xfer;
-
xfer = slpmsg->slpcall->xfer;
-
if (xfer != NULL)
{
+ slpmsg->ft = TRUE;
+ slpmsg->slpcall->xfer_msg = slpmsg;
+
purple_xfer_ref(xfer);
purple_xfer_start(xfer, -1, NULL, 0);
@@ -540,14 +553,12 @@ msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
g_return_if_reached();
} else {
purple_xfer_unref(xfer);
- slpmsg->fp = xfer->dest_fp;
- xfer->dest_fp = NULL; /* Disable double fclose() */
}
}
}
}
}
- if (!slpmsg->fp && slpmsg->size)
+ if (!slpmsg->fp && !slpmsg->ft && slpmsg->size)
{
slpmsg->buffer = g_try_malloc(slpmsg->size);
if (slpmsg->buffer == NULL)
@@ -574,6 +585,13 @@ msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
/* fseek(slpmsg->fp, offset, SEEK_SET); */
len = fwrite(data, 1, len, slpmsg->fp);
}
+ else if (slpmsg->ft)
+ {
+ xfer = slpmsg->slpcall->xfer;
+ slpmsg->slpcall->u.incoming_data =
+ g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)data, len);
+ purple_xfer_prpl_ready(xfer);
+ }
else if (slpmsg->size && slpmsg->buffer)
{
if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size)
@@ -732,7 +750,6 @@ msn_slplink_request_ft(MsnSlpLink *slplink, PurpleXfer *xfer)
slpcall->session_init_cb = send_file_cb;
slpcall->end_cb = msn_xfer_end_cb;
- slpcall->progress_cb = msn_xfer_progress_cb;
slpcall->cb = msn_xfer_completed_cb;
slpcall->xfer = xfer;
purple_xfer_ref(slpcall->xfer);
@@ -740,6 +757,8 @@ msn_slplink_request_ft(MsnSlpLink *slplink, PurpleXfer *xfer)
slpcall->pending = TRUE;
purple_xfer_set_cancel_send_fnc(xfer, msn_xfer_cancel);
+ purple_xfer_set_read_fnc(xfer, msn_xfer_read);
+ purple_xfer_set_write_fnc(xfer, msn_xfer_write);
xfer->data = slpcall;
diff --git a/libpurple/protocols/msn/slplink.h b/libpurple/protocols/msn/slplink.h
index 2f11c97e5b..ea8ca2e5f6 100644
--- a/libpurple/protocols/msn/slplink.h
+++ b/libpurple/protocols/msn/slplink.h
@@ -84,6 +84,9 @@ void msn_slplink_send_queued_slpmsgs(MsnSlpLink *slplink);
void msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg);
void msn_slplink_request_ft(MsnSlpLink *slplink, PurpleXfer *xfer);
+/* Only exported for msn_xfer_write */
+void msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
+
void msn_slplink_request_object(MsnSlpLink *slplink,
const char *info,
MsnSlpCb cb,
diff --git a/libpurple/protocols/msn/slpmsg.h b/libpurple/protocols/msn/slpmsg.h
index 6f1349aa4c..5852bcb78c 100644
--- a/libpurple/protocols/msn/slpmsg.h
+++ b/libpurple/protocols/msn/slpmsg.h
@@ -55,6 +55,7 @@ struct _MsnSlpMessage
long flags;
FILE *fp;
+ gboolean ft;
PurpleStoredImage *img;
guchar *buffer;
long long offset;