# HG changeset patch # User Paul Aurich # Date 1267384777 0 # Node ID 5802999803dbc07ac9b4d8341b8b67d7a04468e3 # Parent 5ffe7f1d4efa58c5da857442c2dd057ceca344ee# Parent 1326fd4dfdc9a6d336a162d80aac4685c066b8af merge of 'bbf372ad40c4d6c10e323048d26215e4769e079c' and 'd6b03d30f4751e3fa383c0e15a03515536f9b57c' diff -r 5ffe7f1d4efa -r 5802999803db libpurple/ft.c --- a/libpurple/ft.c Sun Feb 28 19:17:29 2010 +0000 +++ b/libpurple/ft.c Sun Feb 28 19:19:37 2010 +0000 @@ -1085,7 +1085,7 @@ return; } } else if (xfer->type == PURPLE_XFER_SEND) { - size_t result; + size_t result = 0; size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size); PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer); @@ -1130,13 +1130,24 @@ result = tmp; } else { - buffer = g_malloc0(s); - result = fread(buffer, 1, s, xfer->dest_fp); - if (result != s) { - purple_debug_error("filetransfer", "Unable to read whole buffer.\n"); - purple_xfer_cancel_local(xfer); - g_free(buffer); - return; + gboolean read = TRUE; + if (priv->buffer) { + if (priv->buffer->len < s) { + s -= priv->buffer->len; + read = TRUE; + } else { + read = FALSE; + } + } + if (read) { + buffer = g_malloc(s); + result = fread(buffer, 1, s, xfer->dest_fp); + if (result != s) { + purple_debug_error("filetransfer", "Unable to read whole buffer.\n"); + purple_xfer_cancel_local(xfer); + g_free(buffer); + return; + } } } diff -r 5ffe7f1d4efa -r 5802999803db libpurple/protocols/msn/slp.c --- a/libpurple/protocols/msn/slp.c Sun Feb 28 19:17:29 2010 +0000 +++ b/libpurple/protocols/msn/slp.c Sun Feb 28 19:19:37 2010 +0000 @@ -308,8 +308,6 @@ return NULL; } -#define MAX_FILE_NAME_LEN 0x226 - static void got_sessionreq(MsnSlpCall *slpcall, const char *branch, const char *euf_guid, const char *context) @@ -382,7 +380,7 @@ /* File Transfer */ PurpleAccount *account; PurpleXfer *xfer; - char *bin; + MsnFileContext *header; gsize bin_len; guint32 file_size; char *file_name; @@ -396,16 +394,18 @@ xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE, slpcall->slplink->remote_user); - if (xfer) - { - bin = (char *)purple_base64_decode(context, &bin_len); - file_size = GUINT32_FROM_LE(*(gsize *)(bin + 8)); - file_name = g_convert(bin + 20, MAX_FILE_NAME_LEN, "UTF-8", "UTF-16LE", + header = (MsnFileContext *)purple_base64_decode(context, &bin_len); + if (bin_len >= sizeof(MsnFileContext) - 1 && + (header->version == 2 || + (header->version == 3 && header->length == sizeof(MsnFileContext) + 63))) { + file_size = GUINT64_FROM_LE(header->file_size); + + file_name = g_convert((const gchar *)&header->file_name, + MAX_FILE_NAME_LEN * 2, + "UTF-8", "UTF-16LE", NULL, NULL, NULL); - g_free(bin); - purple_xfer_set_filename(xfer, file_name ? file_name : ""); g_free(file_name); purple_xfer_set_size(xfer, file_size); @@ -424,6 +424,7 @@ purple_xfer_request(xfer); } + g_free(header); accepted = TRUE; diff -r 5ffe7f1d4efa -r 5802999803db libpurple/protocols/msn/slp.h --- a/libpurple/protocols/msn/slp.h Sun Feb 28 19:17:29 2010 +0000 +++ b/libpurple/protocols/msn/slp.h Sun Feb 28 19:19:37 2010 +0000 @@ -30,6 +30,25 @@ #include "session.h" #include "slpcall.h" +#define MAX_FILE_NAME_LEN 260 /* MAX_PATH in Windows */ + +/** + * The context data for a file transfer request + */ +#pragma pack(push,1) /* Couldn't they have made it the right size? */ +typedef struct +{ + guint32 length; /*< Length of header */ + guint32 version; /*< MSN version */ + guint64 file_size; /*< Size of file */ + guint32 type; /*< Transfer type */ + gunichar2 file_name[MAX_FILE_NAME_LEN]; /*< Self-explanatory */ + gchar unknown1[30]; /*< Used somehow for background sharing */ + guint32 unknown2; /*< Possibly for background sharing as well */ + gchar preview[1]; /*< File preview data, 96x96 PNG */ +} MsnFileContext; +#pragma pack(pop) + MsnSlpCall * msn_slp_sip_recv(MsnSlpLink *slplink, const char *body); diff -r 5ffe7f1d4efa -r 5802999803db libpurple/protocols/msn/slplink.c --- a/libpurple/protocols/msn/slplink.c Sun Feb 28 19:17:29 2010 +0000 +++ b/libpurple/protocols/msn/slplink.c Sun Feb 28 19:19:37 2010 +0000 @@ -307,6 +307,8 @@ slpmsg->offset += msg->msnslp_header.length; + slpmsg->msgs = g_list_remove(slpmsg->msgs, msg); + if (slpmsg->offset < real_size) { if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED) @@ -331,8 +333,6 @@ } } } - - slpmsg->msgs = g_list_remove(slpmsg->msgs, msg); } /* We have received the message nak. */ @@ -658,74 +658,51 @@ } } -typedef struct -{ - guint32 length; - guint32 unk1; - guint32 file_size; - guint32 unk2; - guint32 unk3; -} MsnContextHeader; - -#define MAX_FILE_NAME_LEN 0x226 - static gchar * gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path) { gsize size = 0; - MsnContextHeader header; + MsnFileContext header; gchar *u8 = NULL; - guchar *base; - guchar *n; gchar *ret; gunichar2 *uni = NULL; glong currentChar = 0; - glong uni_len = 0; - gsize len; + glong len = 0; size = purple_xfer_get_size(xfer); - if(!file_name) { + if (!file_name) { gchar *basename = g_path_get_basename(file_path); u8 = purple_utf8_try_convert(basename); g_free(basename); file_name = u8; } - uni = g_utf8_to_utf16(file_name, -1, NULL, &uni_len, NULL); + uni = g_utf8_to_utf16(file_name, -1, NULL, &len, NULL); - if(u8) { + if (u8) { g_free(u8); file_name = NULL; u8 = NULL; } - len = sizeof(MsnContextHeader) + MAX_FILE_NAME_LEN + 4; - - header.length = GUINT32_TO_LE(len); - header.unk1 = GUINT32_TO_LE(2); - header.file_size = GUINT32_TO_LE(size); - header.unk2 = GUINT32_TO_LE(0); - header.unk3 = GUINT32_TO_LE(0); - - base = g_malloc(len + 1); - n = base; + header.length = GUINT32_TO_LE(sizeof(MsnFileContext) - 1); + header.version = GUINT32_TO_LE(2); /* V.3 contains additional unnecessary data */ + header.file_size = GUINT64_TO_LE(size); + header.type = GUINT32_TO_LE(1); /* No file preview */ - memcpy(n, &header, sizeof(MsnContextHeader)); - n += sizeof(MsnContextHeader); + len = MIN(len, MAX_FILE_NAME_LEN); + for (currentChar = 0; currentChar < len; currentChar++) { + header.file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]); + } + memset(&header.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2); - memset(n, 0x00, MAX_FILE_NAME_LEN); - for(currentChar = 0; currentChar < uni_len; currentChar++) { - *((gunichar2 *)n + currentChar) = GUINT16_TO_LE(uni[currentChar]); - } - n += MAX_FILE_NAME_LEN; - - memset(n, 0xFF, 4); - n += 4; + memset(&header.unknown1, 0, sizeof(header.unknown1)); + header.unknown2 = GUINT32_TO_LE(0xffffffff); + header.preview[0] = '\0'; g_free(uni); - ret = purple_base64_encode(base, len); - g_free(base); + ret = purple_base64_encode((const guchar *)&header, sizeof(MsnFileContext)); return ret; } diff -r 5ffe7f1d4efa -r 5802999803db pidgin/gtkft.c --- a/pidgin/gtkft.c Sun Feb 28 19:17:29 2010 +0000 +++ b/pidgin/gtkft.c Sun Feb 28 19:19:37 2010 +0000 @@ -575,7 +575,7 @@ /* Build the tree model */ /* Transfer type, Progress Bar, Filename, Size, Remaining */ - model = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_DOUBLE, + model = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); dialog->model = model; @@ -609,7 +609,7 @@ /* Progress bar column */ renderer = gtk_cell_renderer_progress_new(); column = gtk_tree_view_column_new_with_attributes(_("Progress"), renderer, - "percentage", COLUMN_PROGRESS, NULL); + "value", COLUMN_PROGRESS, NULL); gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); @@ -906,7 +906,7 @@ lfilename = utf8; gtk_list_store_set(dialog->model, &data->iter, COLUMN_STATUS, pixbuf, - COLUMN_PROGRESS, 0.0, + COLUMN_PROGRESS, 0, COLUMN_FILENAME, (type == PURPLE_XFER_RECEIVE) ? purple_xfer_get_filename(xfer) : lfilename, @@ -1039,7 +1039,7 @@ remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer)); gtk_list_store_set(xfer_dialog->model, &data->iter, - COLUMN_PROGRESS, purple_xfer_get_progress(xfer), + COLUMN_PROGRESS, (gint)(purple_xfer_get_progress(xfer) * 100), COLUMN_SIZE, size_str, COLUMN_REMAINING, remaining_str, -1);