pidgin/pidgin

Merged in rw_grim/pidgin-security (pull request #11)
release-2.x.y
2016-06-12, Gary Kramlich
6d984b02fa91
Merged in rw_grim/pidgin-security (pull request #11)

TALOS-CAN-0120 TALOS-CAN-0135 TALOS-CAN-0138 and TALOS-CAN-0140
--- a/ChangeLog Tue Jun 07 04:22:59 2016 -0300
+++ b/ChangeLog Sun Jun 12 21:57:32 2016 -0500
@@ -13,6 +13,14 @@
Bonjour
* Fixed building on Mac OSX (Patrick Cloke) (#16883)
+ MXit
+ * Fixed a buffer overflow. Discovered by Yves Younan of Cisco Talos.
+ (TALOS-CAN-0120)
+ * Fixed a remote out-of-bounds read. Discovered by Yves Younan of Cisco
+ Talos. (TALOS-CAN-0140)
+ * Fixed a remote out-of-band read. Discovered by Yves Younan of Cisco
+ Talos. (TALOS-CAN-0138, TALOS-CAN-0135)
+
version 2.10.12 (12/31/15):
General:
* purple-url-handler now works with Python 3.x (Daniƫl van Eeden)
--- a/libpurple/protocols/mxit/chunk.c Tue Jun 07 04:22:59 2016 -0300
+++ b/libpurple/protocols/mxit/chunk.c Sun Jun 12 21:57:32 2016 -0500
@@ -151,11 +151,15 @@
* Extract a single byte from the chunked data.
*
* @param chunkdata The chunked-data buffer
+ * @param chunklen The amount of data available in the buffer.
* @param value The byte
* @return The number of bytes extracted.
*/
-static int get_int8( const char* chunkdata, char* value )
+static int get_int8( const char* chunkdata, size_t chunklen, char* value )
{
+ if ( chunklen < sizeof( char ) )
+ return 0;
+
*value = *chunkdata;
return sizeof( char );
@@ -165,11 +169,15 @@
* Extract a 16-bit value from the chunked data.
*
* @param chunkdata The chunked-data buffer
+ * @param chunklen The amount of data available in the buffer.
* @param value The 16-bit value
* @return The number of bytes extracted
*/
-static int get_int16( const char* chunkdata, short* value )
+static int get_int16( const char* chunkdata, size_t chunklen, unsigned short* value )
{
+ if ( chunklen < sizeof( short ) )
+ return 0;
+
*value = ntohs( *( (const short*) chunkdata ) ); /* host byte-order */
return sizeof( short );
@@ -179,11 +187,15 @@
* Extract a 32-bit value from the chunked data.
*
* @param chunkdata The chunked-data buffer
+ * @param chunklen The amount of data available in the buffer.
* @param value The 32-bit value
* @return The number of bytes extracted
*/
-static int get_int32( const char* chunkdata, int* value )
+static int get_int32( const char* chunkdata, size_t chunklen, unsigned int* value )
{
+ if ( chunklen < sizeof( int ) )
+ return 0;
+
*value = ntohl( *( (const int*) chunkdata ) ); /* host byte-order */
return sizeof( int );
@@ -194,11 +206,15 @@
* Extract a 64-bit value from the chunked data.
*
* @param chunkdata The chunked-data buffer
+ * @param chunklen The amount of data available in the buffer.
* @param value The 64-bit value
* @return The number of bytes extracted
*/
-static int get_int64( const char* chunkdata, int64_t* value )
+static int get_int64( const char* chunkdata, size_t chunklen, int64_t* value )
{
+ if ( chunklen < sizeof( int64_t ) )
+ return 0;
+
*value = SWAP_64( *( (const int64_t*) chunkdata ) ); /* host byte-order */
return sizeof( int64_t );
@@ -209,12 +225,16 @@
* Copy a block of data from the chunked data.
*
* @param chunkdata The chunked-data buffer
+ * @param chunklen The amount of data available in the buffer.
* @param dest Where to store the extract data
* @param datalen The length of the data to extract
* @return The number of bytes extracted
*/
-static int get_data( const char* chunkdata, char* dest, int datalen )
+static int get_data( const char* chunkdata, size_t chunklen, char* dest, size_t datalen )
{
+ if ( chunklen < datalen )
+ return 0;
+
memcpy( dest, chunkdata, datalen );
return datalen;
@@ -224,20 +244,25 @@
* Extract a UTF-8 encoded string from the chunked data.
*
* @param chunkdata The chunked-data buffer
+ * @param chunklen The amount of data available in the buffer.
* @param str A pointer to extracted string. Must be g_free()'d.
* @param maxstrlen Maximum size of destination buffer.
* @return The number of bytes consumed
*/
-static int get_utf8_string( const char* chunkdata, char* str, int maxstrlen )
+static int get_utf8_string( const char* chunkdata, size_t chunklen, char* str, size_t maxstrlen )
{
- int pos = 0;
- short len;
- int skip = 0;
+ size_t pos = 0;
+ unsigned short len = 0;
+ size_t skip = 0;
/* string length [2 bytes] */
- pos += get_int16( &chunkdata[pos], &len );
+ pos += get_int16( &chunkdata[pos], chunklen - pos, &len );
- if ( len > maxstrlen ) {
+ if ( ( len + pos ) > chunklen ) {
+ /* string length is longer than chunk size */
+ return 0;
+ }
+ else if ( len > maxstrlen ) {
/* possible buffer overflow */
purple_debug_error( MXIT_PLUGIN_ID, "Buffer overflow detected (get_utf8_string)\n" );
skip = len - maxstrlen;
@@ -245,7 +270,7 @@
}
/* string data */
- pos += get_data( &chunkdata[pos], str, len );
+ pos += get_data( &chunkdata[pos], chunklen - pos, str, len );
str[len] = '\0'; /* terminate string */
return pos + skip;
@@ -263,9 +288,9 @@
* @param fileid A unique ID that identifies this file
* @return The number of bytes encoded in the buffer
*/
-int mxit_chunk_create_reject( char* chunkdata, const char* fileid )
+size_t mxit_chunk_create_reject( char* chunkdata, const char* fileid )
{
- int pos = 0;
+ size_t pos = 0;
/* file id [8 bytes] */
pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
@@ -289,9 +314,9 @@
* @param offset The start offset in the file
* @return The number of bytes encoded in the buffer
*/
-int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, int offset )
+size_t mxit_chunk_create_get( char* chunkdata, const char* fileid, size_t filesize, size_t offset )
{
- int pos = 0;
+ size_t pos = 0;
/* file id [8 bytes] */
pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
@@ -314,9 +339,9 @@
* @param status The status of the file transfer (see chunk.h)
* @return The number of bytes encoded in the buffer
*/
-int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status )
+size_t mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status )
{
- int pos = 0;
+ size_t pos = 0;
/* file id [8 bytes] */
pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
@@ -338,9 +363,9 @@
* @param datalen The size of the file contents
* @return The number of bytes encoded in the buffer
*/
-int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen )
+size_t mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, size_t datalen )
{
- int pos = 0;
+ size_t pos = 0;
const char* mime = NULL;
/* data length [4 bytes] */
@@ -380,10 +405,10 @@
* @param datalen The size of the avatar data
* @return The number of bytes encoded in the buffer
*/
-int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, int datalen )
+size_t mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, size_t datalen )
{
char fileid[MXIT_CHUNK_FILEID_LEN];
- int pos = 0;
+ size_t pos = 0;
/* id [8 bytes] */
memset( &fileid, 0, sizeof( fileid ) ); /* set to 0 for file upload */
@@ -410,9 +435,9 @@
* @param avatarId The Id of the avatar image (as string)
* @return The number of bytes encoded in the buffer
*/
-int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId )
+size_t mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId )
{
- int pos = 0;
+ size_t pos = 0;
/* number of avatars [4 bytes] */
pos += add_int32( &chunkdata[pos], 1 );
@@ -449,28 +474,31 @@
* @param chunkdata Chunked data buffer
* @param datalen The length of the chunked data
* @param offer Decoded offerfile information
+ * @return TRUE if successfully parsed, otherwise FALSE
*/
-void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer )
+gboolean mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer )
{
- int pos = 0;
+ size_t pos = 0;
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%i bytes)\n", datalen );
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%zu bytes)\n", datalen );
+
+ memset( offer, 0, sizeof( struct offerfile_chunk ) );
/* id [8 bytes] */
- pos += get_data( &chunkdata[pos], offer->fileid, 8);
+ pos += get_data( &chunkdata[pos], datalen - pos, offer->fileid, 8);
/* from username [UTF-8] */
- pos += get_utf8_string( &chunkdata[pos], offer->username, sizeof( offer->username ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->username, sizeof( offer->username ) );
mxit_strip_domain( offer->username );
/* file size [4 bytes] */
- pos += get_int32( &chunkdata[pos], &(offer->filesize) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(offer->filesize) );
/* filename [UTF-8] */
- pos += get_utf8_string( &chunkdata[pos], offer->filename, sizeof( offer->filename ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->filename, sizeof( offer->filename ) );
/* mime type [UTF-8] */
- pos += get_utf8_string( &chunkdata[pos], offer->mimetype, sizeof( offer->mimetype ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->mimetype, sizeof( offer->mimetype ) );
/* timestamp [8 bytes] */
/* not used by libPurple */
@@ -483,6 +511,8 @@
/* flags [4 bytes] */
/* not used by libPurple */
+
+ return TRUE;
}
@@ -492,27 +522,41 @@
* @param chunkdata Chunked data buffer
* @param datalen The length of the chunked data
* @param offer Decoded getfile information
+ * @return TRUE if successfully parsed, otherwise FALSE
*/
-void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile )
+gboolean mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile )
{
- int pos = 0;
+ size_t pos = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%zu bytes)\n", datalen );
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%i bytes)\n", datalen );
+ memset( getfile, 0, sizeof( struct getfile_chunk ) );
+
+ /* ensure that the chunk size is atleast the minimum size for a "get file" chunk */
+ if ( datalen < 20 )
+ return FALSE;
/* id [8 bytes] */
- pos += get_data( &chunkdata[pos], getfile->fileid, 8 );
+ pos += get_data( &chunkdata[pos], datalen - pos, getfile->fileid, 8 );
/* offset [4 bytes] */
- pos += get_int32( &chunkdata[pos], &(getfile->offset) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->offset) );
/* file length [4 bytes] */
- pos += get_int32( &chunkdata[pos], &(getfile->length) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->length) );
/* crc [4 bytes] */
- pos += get_int32( &chunkdata[pos], &(getfile->crc) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->crc) );
+
+ /* check length does not exceed chunked data length */
+ if ( getfile->length > datalen - pos )
+ return FALSE;
/* file data */
- getfile->data = &chunkdata[pos];
+ if ( getfile->length > 0 )
+ getfile->data = &chunkdata[pos];
+
+ return TRUE;
}
@@ -522,27 +566,37 @@
* @param chunkdata Chunked data buffer
* @param datalen The length of the chunked data
* @param splash Decoded splash image information
+ * @return TRUE if successfully parsed, otherwise FALSE
*/
-static void mxit_chunk_parse_splash( char* chunkdata, int datalen, struct splash_chunk* splash )
+gboolean mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash )
{
- int pos = 0;
+ size_t pos = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%zu bytes)\n", datalen );
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%i bytes)\n", datalen );
+ memset( splash, 0, sizeof( struct splash_chunk ) );
+
+ /* ensure that the chunk size is atleast the minimum size for a "splash screen" chunk */
+ if ( datalen < 6 )
+ return FALSE;
/* anchor [1 byte] */
- pos += get_int8( &chunkdata[pos], &(splash->anchor) );
+ pos += get_int8( &chunkdata[pos], datalen - pos, &(splash->anchor) );
/* time to show [1 byte] */
- pos += get_int8( &chunkdata[pos], &(splash->showtime) );
+ pos += get_int8( &chunkdata[pos], datalen - pos, &(splash->showtime) );
/* background color [4 bytes] */
- pos += get_int32( &chunkdata[pos], &(splash->bgcolor) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(splash->bgcolor) );
/* file data */
- splash->data = &chunkdata[pos];
+ if ( pos < datalen )
+ splash->data = &chunkdata[pos];
/* data length */
splash->datalen = datalen - pos;
+
+ return TRUE;
}
@@ -552,41 +606,51 @@
* @param chunkdata Chunked data buffer
* @param datalen The length of the chunked data
* @param offer Decoded custom resource
+ * @return TRUE if successfully parsed, otherwise FALSE
*/
-void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr )
+gboolean mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr )
{
- int pos = 0;
- int chunklen = 0;
+ size_t pos = 0;
+ unsigned int chunkslen = 0;
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%i bytes)\n", datalen );
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%zu bytes)\n", datalen );
+
+ memset( cr, 0, sizeof( struct cr_chunk ) );
/* id [UTF-8] */
- pos += get_utf8_string( &chunkdata[pos], cr->id, sizeof( cr->id ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, cr->id, sizeof( cr->id ) );
/* handle [UTF-8] */
- pos += get_utf8_string( &chunkdata[pos], cr->handle, sizeof( cr->handle ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, cr->handle, sizeof( cr->handle ) );
/* operation [1 byte] */
- pos += get_int8( &chunkdata[pos], &(cr->operation) );
+ pos += get_int8( &chunkdata[pos], datalen - pos, &(cr->operation) );
- /* chunk size [4 bytes] */
- pos += get_int32( &chunkdata[pos], &chunklen );
+ /* total length of all the chunks that are included [4 bytes] */
+ pos += get_int32( &chunkdata[pos], datalen - pos, &chunkslen );
+
+ /* ensure the chunks size does not exceed the data size */
+ if ( pos + chunkslen > datalen )
+ return FALSE;
/* parse the resource chunks */
- while ( chunklen > 0 ) {
- gchar* chunk = &chunkdata[pos];
+ while ( chunkslen >= MXIT_CHUNK_HEADER_SIZE ) {
+ gchar* chunk = &chunkdata[pos];
+ guint32 chunksize = chunk_length( chunk );
- /* start of chunk data */
- pos += MXIT_CHUNK_HEADER_SIZE;
+ /* check chunk size against length of received data */
+ if ( pos + MXIT_CHUNK_HEADER_SIZE + chunksize > datalen )
+ return FALSE;
switch ( chunk_type( chunk ) ) {
case CP_CHUNK_SPLASH : /* splash image */
{
struct splash_chunk* splash = g_new0( struct splash_chunk, 1 );
- mxit_chunk_parse_splash( &chunkdata[pos], chunk_length( chunk ), splash );
-
- cr->resources = g_list_append( cr->resources, splash );
+ if ( mxit_chunk_parse_splash( chunk_data( chunk ), chunksize, splash ) )
+ cr->resources = g_list_append( cr->resources, splash );
+ else
+ g_free( splash );
break;
}
case CP_CHUNK_CLICK : /* splash click */
@@ -601,9 +665,11 @@
}
/* skip over data to next resource chunk */
- pos += chunk_length( chunk );
- chunklen -= ( MXIT_CHUNK_HEADER_SIZE + chunk_length( chunk ) );
+ pos += MXIT_CHUNK_HEADER_SIZE + chunksize;
+ chunkslen -= ( MXIT_CHUNK_HEADER_SIZE + chunksize );
}
+
+ return TRUE;
}
@@ -613,28 +679,33 @@
* @param chunkdata Chunked data buffer
* @param datalen The length of the chunked data
* @param sendfile Decoded sendfile information
+ * @return TRUE if successfully parsed, otherwise FALSE
*/
-void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile )
+gboolean mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile )
{
- int pos = 0;
- short entries = 0;
+ size_t pos = 0;
+ unsigned short entries = 0;
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%i bytes)\n", datalen );
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%zu bytes)\n", datalen );
+
+ memset( sendfile, 0, sizeof( struct sendfile_chunk ) );
/* number of entries [2 bytes] */
- pos += get_int16( &chunkdata[pos], &entries );
+ pos += get_int16( &chunkdata[pos], datalen - pos, &entries );
if ( entries < 1 ) /* no data */
- return;
+ return FALSE;
/* contactAddress [UTF-8 string] */
- pos += get_utf8_string( &chunkdata[pos], sendfile->username, sizeof( sendfile->username ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, sendfile->username, sizeof( sendfile->username ) );
/* status [4 bytes] */
- pos += get_int32( &chunkdata[pos], &(sendfile->status) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(sendfile->status) );
/* status message [UTF-8 string] */
- pos += get_utf8_string( &chunkdata[pos], sendfile->statusmsg, sizeof( sendfile->statusmsg ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, sendfile->statusmsg, sizeof( sendfile->statusmsg ) );
+
+ return TRUE;
}
@@ -644,44 +715,54 @@
* @param chunkdata Chunked data buffer
* @param datalen The length of the chunked data
* @param avatar Decoded avatar information
+ * @return TRUE if successfully parsed, otherwise FALSE
*/
-void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar )
+gboolean mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar )
{
- int pos = 0;
- int numfiles = 0;
+ size_t pos = 0;
+ unsigned int numfiles = 0;
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%i bytes)\n", datalen );
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%zu bytes)\n", datalen );
+
+ memset( avatar, 0, sizeof( struct getavatar_chunk ) );
/* number of files [4 bytes] */
- pos += get_int32( &chunkdata[pos], &numfiles );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &numfiles );
if ( numfiles < 1 ) /* no data */
- return;
+ return FALSE;
/* mxitId [UTF-8 string] */
- pos += get_utf8_string( &chunkdata[pos], avatar->mxitid, sizeof( avatar->mxitid ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->mxitid, sizeof( avatar->mxitid ) );
/* avatar id [UTF-8 string] */
- pos += get_utf8_string( &chunkdata[pos], avatar->avatarid, sizeof( avatar->avatarid ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->avatarid, sizeof( avatar->avatarid ) );
/* format [UTF-8 string] */
- pos += get_utf8_string( &chunkdata[pos], avatar->format, sizeof( avatar->format ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->format, sizeof( avatar->format ) );
/* bit depth [1 byte] */
- pos += get_int8( &chunkdata[pos], &(avatar->bitdepth) );
+ pos += get_int8( &chunkdata[pos], datalen - pos, &(avatar->bitdepth) );
/* crc [4 bytes] */
- pos += get_int32( &chunkdata[pos], &(avatar->crc) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->crc) );
/* width [4 bytes] */
- pos += get_int32( &chunkdata[pos], &(avatar->width) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->width) );
/* height [4 bytes] */
- pos += get_int32( &chunkdata[pos], &(avatar->height) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->height) );
/* file length [4 bytes] */
- pos += get_int32( &chunkdata[pos], &(avatar->length) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->length) );
+
+ /* check length does not exceed chunked data length */
+ if ( avatar->length > datalen - pos )
+ return FALSE;
/* file data */
- avatar->data = &chunkdata[pos];
+ if ( avatar->length > 0 )
+ avatar->data = &chunkdata[pos];
+
+ return TRUE;
}
--- a/libpurple/protocols/mxit/chunk.h Tue Jun 07 04:22:59 2016 -0300
+++ b/libpurple/protocols/mxit/chunk.h Sun Jun 12 21:57:32 2016 -0500
@@ -85,7 +85,7 @@
static inline guint32 chunk_length( gchar* chunkheader )
{
guint32 length = *( (const guint32*) &chunkheader[1] );
- return htonl( length );
+ return ntohl( length );
}
static inline void set_chunk_length( gchar* chunkheader, guint32 size )
@@ -103,22 +103,22 @@
* Offer File chunk (6).
*/
struct offerfile_chunk {
- char fileid[MXIT_CHUNK_FILEID_LEN];
- char username[MXIT_CP_MAX_JID_LEN + 1];
- int filesize;
- char filename[FILENAME_MAX];
- char mimetype[64];
+ char fileid[MXIT_CHUNK_FILEID_LEN];
+ char username[MXIT_CP_MAX_JID_LEN + 1];
+ unsigned int filesize;
+ char filename[FILENAME_MAX];
+ char mimetype[64];
};
/*
* Get File chunk (8) response.
*/
struct getfile_chunk {
- char fileid[MXIT_CHUNK_FILEID_LEN];
- int offset;
- int length;
- int crc;
- char* data;
+ char fileid[MXIT_CHUNK_FILEID_LEN];
+ unsigned int offset;
+ unsigned int length;
+ unsigned int crc;
+ char* data;
};
/*
@@ -135,11 +135,11 @@
* Splash Image chunk (2)
*/
struct splash_chunk {
- char anchor;
- char showtime;
- int bgcolor;
- char* data;
- int datalen;
+ char anchor;
+ char showtime;
+ unsigned int bgcolor;
+ char* data;
+ unsigned int datalen;
};
/*
@@ -153,40 +153,41 @@
* Get Avatar chunk (14) response.
*/
struct getavatar_chunk {
- char mxitid[50];
- char avatarid[64];
- char format[16];
- char bitdepth;
- int crc;
- int width;
- int height;
- int length;
- char* data;
+ char mxitid[50];
+ char avatarid[64];
+ char format[16];
+ char bitdepth;
+ unsigned int crc;
+ unsigned int width;
+ unsigned int height;
+ unsigned int length;
+ char* data;
};
/*
* Send File Direct chunk (10) response.
*/
struct sendfile_chunk {
- char username[MXIT_CP_MAX_JID_LEN + 1];
- int status;
- char statusmsg[1024];
+ char username[MXIT_CP_MAX_JID_LEN + 1];
+ unsigned int status;
+ char statusmsg[1024];
};
/* Encode chunk */
-int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen );
-int mxit_chunk_create_reject( char* chunkdata, const char* fileid );
-int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, int offset );
-int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status );
-int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, int datalen );
-int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId );
+size_t mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, size_t datalen );
+size_t mxit_chunk_create_reject( char* chunkdata, const char* fileid );
+size_t mxit_chunk_create_get( char* chunkdata, const char* fileid, size_t filesize, size_t offset );
+size_t mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status );
+size_t mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, size_t datalen );
+size_t mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId );
/* Decode chunk */
-void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer );
-void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile );
-void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr );
-void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile );
-void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar );
+gboolean mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer );
+gboolean mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile );
+gboolean mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr );
+gboolean mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile );
+gboolean mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar );
+gboolean mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash );
#endif /* _MXIT_CHUNK_H_ */
--- a/libpurple/protocols/mxit/filexfer.c Tue Jun 07 04:22:59 2016 -0300
+++ b/libpurple/protocols/mxit/filexfer.c Sun Jun 12 21:57:32 2016 -0500
@@ -357,7 +357,7 @@
* @param filesize The size of the file being offered
* @param fileid A unique ID that identifies this file
*/
-void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, int filesize, const char* fileid )
+void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, unsigned int filesize, const char* fileid )
{
PurpleXfer* xfer = NULL;
struct mxitxfer* mx = NULL;
@@ -373,7 +373,7 @@
xfer->data = mx;
purple_xfer_set_filename( xfer, filename );
- if( filesize > 0 )
+ if ( filesize > 0 )
purple_xfer_set_size( xfer, filesize );
/* register file transfer callback functions */
@@ -429,7 +429,7 @@
* @param data The file data
* @param datalen The size of the data
*/
-void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen )
+void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, unsigned int datalen )
{
PurpleXfer* xfer = NULL;
--- a/libpurple/protocols/mxit/filexfer.h Tue Jun 07 04:22:59 2016 -0300
+++ b/libpurple/protocols/mxit/filexfer.h Sun Jun 12 21:57:32 2016 -0500
@@ -43,8 +43,8 @@
PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who );
/* MXit Protocol callbacks */
-void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, int filesize, const char* fileid );
-void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen );
+void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, unsigned int filesize, const char* fileid );
+void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, unsigned int datalen );
#endif /* _MXIT_FILEXFER_H_ */
--- a/libpurple/protocols/mxit/protocol.c Tue Jun 07 04:22:59 2016 -0300
+++ b/libpurple/protocols/mxit/protocol.c Sun Jun 12 21:57:32 2016 -0500
@@ -1223,14 +1223,14 @@
* @param buf The content of the file
* @param buflen The length of the file contents
*/
-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen )
+void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, size_t buflen )
{
char data[CP_MAX_PACKET];
int datalen = 0;
gchar* chunk;
- int size;
-
- purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username );
+ size_t chunksize;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %zu bytes to user '%s'\n", filename, buflen, username );
/* convert the packet to a byte stream */
datalen = g_snprintf( data, sizeof( data ), "ms=" );
@@ -1238,15 +1238,11 @@
/* map chunk header over data buffer */
chunk = &data[datalen];
- size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
- if ( size < 0 ) {
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating senddirect chunk (%i)\n", size );
- return;
- }
-
+ /* encode chunk */
+ chunksize = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
set_chunk_type( chunk, CP_CHUNK_DIRECT_SND );
- set_chunk_length( chunk, size );
- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+ set_chunk_length( chunk, chunksize );
+ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
/* send the byte stream to the mxit server */
mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
@@ -1264,7 +1260,7 @@
char data[CP_MAX_PACKET];
int datalen = 0;
gchar* chunk;
- int size;
+ size_t chunksize;
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
@@ -1274,15 +1270,11 @@
/* map chunk header over data buffer */
chunk = &data[datalen];
- size = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
- if ( size < 0 ) {
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating reject chunk (%i)\n", size );
- return;
- }
-
+ /* encode chunk */
+ chunksize = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
set_chunk_type( chunk, CP_CHUNK_REJECT );
- set_chunk_length( chunk, size );
- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+ set_chunk_length( chunk, chunksize );
+ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
/* send the byte stream to the mxit server */
mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
@@ -1297,12 +1289,12 @@
* @param filesize The number of bytes to retrieve
* @param offset Offset in file at which to start retrieving
*/
-void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset )
+void mxit_send_file_accept( struct MXitSession* session, const char* fileid, size_t filesize, size_t offset )
{
char data[CP_MAX_PACKET];
int datalen = 0;
gchar* chunk;
- int size;
+ size_t chunksize;
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
@@ -1312,15 +1304,11 @@
/* map chunk header over data buffer */
chunk = &data[datalen];
- size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
- if ( size < 0 ) {
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating getfile chunk (%i)\n", size );
- return;
- }
-
+ /* encode chunk */
+ chunksize = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
set_chunk_type( chunk, CP_CHUNK_GET );
- set_chunk_length( chunk, size );
- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+ set_chunk_length( chunk, chunksize );
+ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
/* send the byte stream to the mxit server */
mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
@@ -1338,7 +1326,7 @@
char data[CP_MAX_PACKET];
int datalen = 0;
gchar* chunk;
- int size;
+ size_t chunksize;
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
@@ -1348,15 +1336,11 @@
/* map chunk header over data buffer */
chunk = &data[datalen];
- size = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
- if ( size < 0 ) {
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating received chunk (%i)\n", size );
- return;
- }
-
+ /* encode chunk */
+ chunksize = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
set_chunk_type( chunk, CP_CHUNK_RECEIVED );
- set_chunk_length( chunk, size );
- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+ set_chunk_length( chunk, chunksize );
+ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
/* send the byte stream to the mxit server */
mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
@@ -1370,14 +1354,14 @@
* @param data The avatar data
* @param buflen The length of the avatar data
*/
-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen )
+void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, size_t avatarlen )
{
char data[CP_MAX_PACKET];
int datalen = 0;
gchar* chunk;
- int size;
-
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen );
+ size_t chunksize;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %zu bytes\n", avatarlen );
/* convert the packet to a byte stream */
datalen = g_snprintf( data, sizeof( data ), "ms=" );
@@ -1385,15 +1369,11 @@
/* map chunk header over data buffer */
chunk = &data[datalen];
- size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
- if ( size < 0 ) {
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating set avatar chunk (%i)\n", size );
- return;
- }
-
+ /* encode chunk */
+ chunksize = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
set_chunk_type( chunk, CP_CHUNK_SET_AVATAR );
- set_chunk_length( chunk, size );
- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+ set_chunk_length( chunk, chunksize );
+ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
/* send the byte stream to the mxit server */
mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
@@ -1414,7 +1394,7 @@
char data[CP_MAX_PACKET];
int datalen = 0;
gchar* chunk;
- int size;
+ size_t chunksize;
purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
@@ -1424,15 +1404,11 @@
/* map chunk header over data buffer */
chunk = &data[datalen];
- size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
- if ( size < 0 ) {
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating get avatar chunk (%i)\n", size );
- return;
- }
-
+ /* encode chunk */
+ chunksize = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
set_chunk_type( chunk, CP_CHUNK_GET_AVATAR );
- set_chunk_length( chunk, size );
- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+ set_chunk_length( chunk, chunksize );
+ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
/* send the byte stream to the mxit server */
mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
@@ -2100,21 +2076,6 @@
/*------------------------------------------------------------------------
- * Return the length of a multimedia chunk
- *
- * @return The actual chunk data length in bytes
- */
-static int get_chunk_len( const char* chunkdata )
-{
- int* sizeptr;
-
- sizeptr = (int*) &chunkdata[1]; /* we skip the first byte (type field) */
-
- return ntohl( *sizeptr );
-}
-
-
-/*------------------------------------------------------------------------
* Process a received multimedia packet.
*
* @param session The MXit session object
@@ -2123,42 +2084,52 @@
*/
static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount )
{
- char type;
- int size;
-
- type = records[0]->fields[0]->data[0];
- size = get_chunk_len( records[0]->fields[0]->data );
-
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i bytes)\n", rcount, size );
+ guint chunktype;
+ guint32 chunksize;
+ gchar* chunkdata;
+
+ /* received packet is too short to even contain a chunk header */
+ if ( records[0]->fields[0]->len < MXIT_CHUNK_HEADER_SIZE )
+ return;
+
+ /* decode the chunk header */
+ chunktype = chunk_type( records[0]->fields[0]->data );
+ chunksize = chunk_length( records[0]->fields[0]->data );
+ chunkdata = chunk_data( records[0]->fields[0]->data );
+
+ /* check chunk size against length of received data */
+ if ( MXIT_CHUNK_HEADER_SIZE + chunksize > records[0]->fields[0]->len )
+ return;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i type) (%i bytes)\n", rcount, chunktype, chunksize );
/* supported chunked data types */
- switch ( type ) {
+ switch ( chunktype ) {
case CP_CHUNK_CUSTOM : /* custom resource */
{
struct cr_chunk chunk;
/* decode the chunked data */
- memset( &chunk, 0, sizeof( struct cr_chunk ) );
- mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
- purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
-
- /* this is a splash-screen operation */
- if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
- if ( chunk.operation == CR_OP_UPDATE ) { /* update the splash-screen */
- struct splash_chunk *splash = chunk.resources->data; // TODO: Fix - assuming 1st resource is splash
- gboolean clickable = ( g_list_length( chunk.resources ) > 1 ); // TODO: Fix - if 2 resources, then is clickable
-
- if ( splash != NULL )
- splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
+ if ( mxit_chunk_parse_cr( chunkdata, chunksize, &chunk ) ) {
+
+ purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
+
+ /* this is a splash-screen operation */
+ if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
+ if ( chunk.operation == CR_OP_UPDATE ) { /* update the splash-screen */
+ struct splash_chunk *splash = chunk.resources->data; // TODO: Fix - assuming 1st resource is splash
+ gboolean clickable = ( g_list_length( chunk.resources ) > 1 ); // TODO: Fix - if 2 resources, then is clickable
+
+ if ( splash != NULL )
+ splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
+ }
+ else if ( chunk.operation == CR_OP_REMOVE ) /* remove the splash-screen */
+ splash_remove( session );
}
- else if ( chunk.operation == CR_OP_REMOVE ) /* remove the splash-screen */
- splash_remove( session );
+
+ /* cleanup custom resources */
+ g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
}
-
- /* cleanup custom resources */
- g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
-
}
break;
@@ -2167,11 +2138,10 @@
struct offerfile_chunk chunk;
/* decode the chunked data */
- memset( &chunk, 0, sizeof( struct offerfile_chunk ) );
- mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
- /* process the offer */
- mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
+ if ( mxit_chunk_parse_offer( chunkdata, chunksize, &chunk ) ) {
+ /* process the offer */
+ mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
+ }
}
break;
@@ -2180,11 +2150,10 @@
struct getfile_chunk chunk;
/* decode the chunked data */
- memset( &chunk, 0, sizeof( struct getfile_chunk ) );
- mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
- /* process the getfile */
- mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
+ if ( mxit_chunk_parse_get( chunkdata, chunksize, &chunk ) ) {
+ /* process the getfile */
+ mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
+ }
}
break;
@@ -2194,11 +2163,8 @@
struct contact* contact = NULL;
/* decode the chunked data */
- memset( &chunk, 0, sizeof( struct getavatar_chunk ) );
- mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
- /* update avatar image */
- if ( chunk.data ) {
+ if ( mxit_chunk_parse_get_avatar( chunkdata, chunksize, &chunk ) ) {
+ /* update avatar image */
purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid );
contact = get_mxit_invite_contact( session, chunk.mxitid );
@@ -2220,18 +2186,21 @@
/* this is a reply packet to a set avatar request. no action is required */
break;
+ case CP_CHUNK_REJECT :
+ /* this is a reply packet to a reject file request. no action is required */
+ break;
+
case CP_CHUNK_DIRECT_SND :
/* this is a ack for a file send. */
{
struct sendfile_chunk chunk;
- memset( &chunk, 0, sizeof( struct sendfile_chunk ) );
- mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
- purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
-
- if ( chunk.status != 0 ) /* not success */
- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
+ if ( mxit_chunk_parse_sendfile( chunkdata, chunksize, &chunk ) ) {
+ purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
+
+ if ( chunk.status != 0 ) /* not success */
+ mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
+ }
}
break;
@@ -2240,7 +2209,7 @@
break;
default :
- purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", type );
+ purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", chunktype );
break;
}
}
@@ -2556,7 +2525,7 @@
for ( j = 0; j < r->fcount; j++ ) {
f = r->fields[j];
- purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%i) '%s' \n", f->len, f->data );
+ purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%zu) '%s' \n", f->len, f->data );
}
}
}
@@ -2677,7 +2646,7 @@
field->data = &session->rx_dbuf[i + 1];
field->len = session->rx_i - i;
/* now skip the binary data */
- res = get_chunk_len( field->data );
+ res = chunk_length( field->data );
/* determine if we have more packets */
if ( res + 6 + i < session->rx_i ) {
/* we have more than one packet in this stream */
--- a/libpurple/protocols/mxit/protocol.h Tue Jun 07 04:22:59 2016 -0300
+++ b/libpurple/protocols/mxit/protocol.h Sun Jun 12 21:57:32 2016 -0500
@@ -241,7 +241,7 @@
struct field {
char* data;
- int len;
+ size_t len;
};
struct record {
@@ -332,11 +332,11 @@
void mxit_send_splashclick( struct MXitSession* session, const char* splashid );
void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event);
-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen );
+void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, size_t buflen );
void mxit_send_file_reject( struct MXitSession* session, const char* fileid );
-void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset );
+void mxit_send_file_accept( struct MXitSession* session, const char* fileid, size_t filesize, size_t offset );
void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status );
-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen );
+void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, size_t avatarlen );
void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId );
void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] );
--- a/libpurple/protocols/mxit/splashscreen.c Tue Jun 07 04:22:59 2016 -0300
+++ b/libpurple/protocols/mxit/splashscreen.c Sun Jun 12 21:57:32 2016 -0500
@@ -112,7 +112,7 @@
* @param data Splash-screen image data (PNG format)
* @param datalen Splash-screen image data size
*/
-void splash_update(struct MXitSession* session, const char* splashId, const char* data, int datalen, gboolean clickable)
+void splash_update(struct MXitSession* session, const char* splashId, const char* data, unsigned int datalen, gboolean clickable)
{
char* dir;
char* filename;
--- a/libpurple/protocols/mxit/splashscreen.h Tue Jun 07 04:22:59 2016 -0300
+++ b/libpurple/protocols/mxit/splashscreen.h Sun Jun 12 21:57:32 2016 -0500
@@ -44,7 +44,7 @@
/*
* Save a new splash-screen.
*/
-void splash_update(struct MXitSession* session, const char* splashId, const char* data, int datalen, gboolean clickable);
+void splash_update(struct MXitSession* session, const char* splashId, const char* data, unsigned int datalen, gboolean clickable);
/*
* Remove the stored splash-screen (if it exists).