pidgin: 84710c18: Add functions for reading and writing a ...

qulogic at pidgin.im qulogic at pidgin.im
Fri Dec 17 04:11:23 EST 2010


----------------------------------------------------------------------
Revision: 84710c18b00e11881bb2eeece1223ace4c0e40fa
Parent:   7f5138e6a3c1380f94724c17a7d99cda3e0f2fad
Author:   qulogic at pidgin.im
Date:     12/17/10 03:53:34
Branch:   im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/84710c18b00e11881bb2eeece1223ace4c0e40fa

Changelog: 

Add functions for reading and writing a MsnFileContext which negates
the need for any more packing.

Fixes #12856.

Changes against parent 7f5138e6a3c1380f94724c17a7d99cda3e0f2fad

  patched  libpurple/protocols/msn/slp.c
  patched  libpurple/protocols/msn/slp.h
  patched  libpurple/protocols/msn/slpcall.c
  patched  libpurple/protocols/msn/xfer.c
  patched  libpurple/protocols/msn/xfer.h

-------------- next part --------------
============================================================
--- libpurple/protocols/msn/slp.c	7b801d9f520ce94a954e8e693aa1de7faf26a9a7
+++ libpurple/protocols/msn/slp.c	13ad54ab66239adc1cc5e958f3ee4d263b212fdc
@@ -293,7 +293,7 @@ gen_context(PurpleXfer *xfer, const char
 gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path)
 {
 	gsize size = 0;
-	MsnFileContext *header;
+	MsnFileContext header;
 	gchar *u8 = NULL;
 	gchar *ret;
 	gunichar2 *uni = NULL;
@@ -322,32 +322,34 @@ gen_context(PurpleXfer *xfer, const char
 	}
 
 	preview = purple_xfer_get_thumbnail(xfer, &preview_len);
-	header = g_malloc(sizeof(MsnFileContext) + preview_len);
 
-	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.length = MSN_FILE_CONTEXT_SIZE;
+	header.version = 2; /* V.3 contains additional unnecessary data */
+	header.file_size = size;
 	if (preview)
-		header->type = GUINT32_TO_LE(0);
+		header.type = 0;
 	else
-		header->type = GUINT32_TO_LE(1);
+		header.type = 1;
 
 	len = MIN(len, MAX_FILE_NAME_LEN);
 	for (currentChar = 0; currentChar < len; currentChar++) {
-		header->file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]);
+		header.file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]);
 	}
-	memset(&header->file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2);
+	memset(&header.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2);
 
-	memset(&header->unknown1, 0, sizeof(header->unknown1));
-	header->unknown2 = GUINT32_TO_LE(0xffffffff);
-	if (preview) {
-		memcpy(&header->preview, preview, preview_len);
-	}
-	header->preview[preview_len] = '\0';
+	memset(&header.unknown1, 0, sizeof(header.unknown1));
+	header.unknown2 = 0xffffffff;
 
+	/* Mind the cast, as in, don't free it after! */
+	header.preview = (char *)preview;
+	header.preview_len = preview_len;
+
+	u8 = msn_file_context_to_wire(&header);
+	ret = purple_base64_encode((const guchar *)u8, MSN_FILE_CONTEXT_SIZE + preview_len);
+
 	g_free(uni);
-	ret = purple_base64_encode((const guchar *)header, sizeof(MsnFileContext) + preview_len);
-	g_free(header);
+	g_free(u8);
+
 	return ret;
 }
 
============================================================
--- libpurple/protocols/msn/slp.h	dcc760e6adbf4d5624266fa9740ba15627537187
+++ libpurple/protocols/msn/slp.h	e4c84c3335d7bcfd5d58c8076b5a65fac072eef9
@@ -32,25 +32,6 @@
 #include "slplink.h"
 #include "user.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)
-
 void
 msn_slp_send_ok(MsnSlpCall *slpcall, const char *branch,
 		const char *type, const char *content);
============================================================
--- libpurple/protocols/msn/slpcall.c	7f7e68b86f1e0b4021722c8991f8710f28a8e951
+++ libpurple/protocols/msn/slpcall.c	d4ea65081df5ae275523f39429e97495b433d2c5
@@ -512,6 +512,7 @@ got_sessionreq(MsnSlpCall *slpcall, cons
 		PurpleAccount *account;
 		PurpleXfer *xfer;
 		MsnFileContext *header;
+		char *buf;
 		gsize bin_len;
 		guint32 file_size;
 		char *file_name;
@@ -526,12 +527,12 @@ got_sessionreq(MsnSlpCall *slpcall, cons
 		xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE,
 							 slpcall->slplink->remote_user);
 
-		header = (MsnFileContext *)purple_base64_decode(context, &bin_len);
-		if (header != NULL && bin_len >= sizeof(MsnFileContext) - 1 &&
-			(header->version == 2 ||
-			 (header->version == 3 && header->length == sizeof(MsnFileContext) + 63))) {
-			file_size = GUINT64_FROM_LE(header->file_size);
+		buf = (char *)purple_base64_decode(context, &bin_len);
+		header = msn_file_context_from_wire(buf, bin_len);
 
+		if (header != NULL) {
+			file_size = header->file_size;
+
 			file_name = g_convert((const gchar *)&header->file_name,
 			                      MAX_FILE_NAME_LEN * 2,
 			                      "UTF-8", "UTF-16LE",
@@ -553,15 +554,17 @@ got_sessionreq(MsnSlpCall *slpcall, cons
 
 			xfer->data = slpcall;
 
-			if (header->type == 0 && bin_len >= sizeof(MsnFileContext)) {
-				purple_xfer_set_thumbnail(xfer, &header->preview,
-				                          bin_len - sizeof(MsnFileContext),
+			if (header->preview) {
+				purple_xfer_set_thumbnail(xfer, header->preview,
+				                          header->preview_len,
 				    					  "image/png");
+				g_free(header->preview);
 			}
 
 			purple_xfer_request(xfer);
 		}
 		g_free(header);
+		g_free(buf);
 
 		accepted = TRUE;
 
============================================================
--- libpurple/protocols/msn/xfer.c	5e8f46a6750f079f16e6adf576c2173a3394065a
+++ libpurple/protocols/msn/xfer.c	75eb0983c0370be20175eb8643b71174e50a5309
@@ -25,6 +25,7 @@
 #include "internal.h"
 #include "debug.h"
 
+#include "msnutils.h"
 #include "sbconn.h"
 #include "xfer.h"
 
@@ -160,3 +161,72 @@ msn_xfer_completed_cb(MsnSlpCall *slpcal
 	purple_xfer_end(xfer);
 }
 
+gchar *
+msn_file_context_to_wire(MsnFileContext *header)
+{
+	gchar *ret, *tmp;
+
+	tmp = ret = g_new(gchar, MSN_FILE_CONTEXT_SIZE + header->preview_len + 1);
+
+	msn_push32le(tmp, header->length);
+	msn_push32le(tmp, header->version);
+	msn_push64le(tmp, header->file_size);
+	msn_push32le(tmp, header->type);
+	memcpy(tmp, header->file_name, MAX_FILE_NAME_LEN * 2);
+	tmp += MAX_FILE_NAME_LEN * 2;
+	memcpy(tmp, header->unknown1, sizeof(header->unknown1));
+	tmp += sizeof(header->unknown1);
+	msn_push32le(tmp, header->unknown2);
+	if (header->preview) {
+		memcpy(tmp, header->preview, header->preview_len);
+	}
+	tmp[header->preview_len] = '\0';
+
+	return ret;
+}
+
+MsnFileContext *
+msn_file_context_from_wire(const char *buf, gsize len)
+{
+	MsnFileContext *header;
+
+	if (!buf || len < MSN_FILE_CONTEXT_SIZE)
+		return NULL;
+
+	header = g_new(MsnFileContext, 1);
+
+	header->length = msn_pop32le(buf);
+	header->version = msn_pop32le(buf);
+	if (header->version == 2) {
+		/* The length field is broken for this version. No check. */
+		header->length = MSN_FILE_CONTEXT_SIZE;
+	} else if (header->version == 3) {
+		if (header->length != MSN_FILE_CONTEXT_SIZE + 63) {
+			g_free(header);
+			return NULL;
+		} else if (len < MSN_FILE_CONTEXT_SIZE + 63) {
+			g_free(header);
+			return NULL;
+		}
+	} else {
+		purple_debug_warning("msn", "Received MsnFileContext with unknown version: %d\n", header->version);
+		g_free(header);
+		return NULL;
+	}
+
+	header->file_size = msn_pop64le(buf);
+	header->type = msn_pop32le(buf);
+	memcpy(header->file_name, buf, MAX_FILE_NAME_LEN * 2);
+	buf += MAX_FILE_NAME_LEN * 2;
+	memcpy(header->unknown1, buf, sizeof(header->unknown1));
+	buf += sizeof(header->unknown1);
+	header->unknown2 = msn_pop32le(buf);
+
+	if (header->type == 0 && len > header->length) {
+		header->preview_len = len - header->length;
+		header->preview = g_memdup(buf, header->preview_len);
+	}
+
+	return header;
+}
+
============================================================
--- libpurple/protocols/msn/xfer.h	1c78ea535a6340661e06d23e96790730adcb451d
+++ libpurple/protocols/msn/xfer.h	ee4a124178fed58e4b3357049ce1e3eb53e8e790
@@ -25,6 +25,26 @@
 
 #include "slpcall.h"
 
+#define MAX_FILE_NAME_LEN 260 /* MAX_PATH in Windows */
+
+/**
+ * The context data for a file transfer request
+ */
+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;     /*< File preview data, 96x96 PNG */
+	gsize     preview_len;
+} MsnFileContext;
+
+#define MSN_FILE_CONTEXT_SIZE (4*4 + 1*8 + 2*MAX_FILE_NAME_LEN + 30)
+
 void msn_xfer_init(PurpleXfer *xfer);
 void msn_xfer_cancel(PurpleXfer *xfer);
 
@@ -34,3 +54,10 @@ void msn_xfer_end_cb(MsnSlpCall *slpcall
 void msn_xfer_completed_cb(MsnSlpCall *slpcall,
 						   const guchar *body, gsize size);
 void msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session);
+
+gchar *
+msn_file_context_to_wire(MsnFileContext *header);
+
+MsnFileContext *
+msn_file_context_from_wire(const char *buf, gsize len);
+


More information about the Commits mailing list