--- 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. * @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 ) ) @@ -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 ) ) *value = ntohs( *( (const short*) chunkdata ) ); /* host byte-order */
@@ -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 ) ) *value = ntohl( *( (const int*) chunkdata ) ); /* host byte-order */
@@ -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 ) ) *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 ) memcpy( dest, chunkdata, 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 )
+ unsigned short len = 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 */ + else if ( len > maxstrlen ) { /* possible buffer overflow */
purple_debug_error( MXIT_PLUGIN_ID, "Buffer overflow detected (get_utf8_string)\n" );
@@ -245,7 +270,7 @@
- pos += get_data( &chunkdata[pos], str, len );
+ pos += get_data( &chunkdata[pos], chunklen - pos, str, len ); str[len] = '\0'; /* terminate string */
@@ -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 )
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 )
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 )
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 )
/* 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];
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 )
/* 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 )
- 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 ) ); - 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) ); - pos += get_utf8_string( &chunkdata[pos], offer->filename, sizeof( offer->filename ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->filename, sizeof( offer->filename ) ); - 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 @@
/* not used by libPurple */
@@ -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 )
+ 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 */ - pos += get_data( &chunkdata[pos], getfile->fileid, 8 );
+ pos += get_data( &chunkdata[pos], datalen - pos, getfile->fileid, 8 ); - 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) ); - 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 ) - getfile->data = &chunkdata[pos];
+ if ( getfile->length > 0 ) + getfile->data = &chunkdata[pos]; @@ -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 )
+ 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 */ - 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) ); - splash->data = &chunkdata[pos];
+ splash->data = &chunkdata[pos]; splash->datalen = datalen - pos;
@@ -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 )
+ 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 ) ); - pos += get_utf8_string( &chunkdata[pos], cr->id, sizeof( cr->id ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, cr->id, sizeof( cr->id ) ); - pos += get_utf8_string( &chunkdata[pos], cr->handle, sizeof( cr->handle ) );
+ pos += get_utf8_string( &chunkdata[pos], datalen - pos, cr->handle, sizeof( cr->handle ) ); - 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 ) /* 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 ) 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 ); 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 ); @@ -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 )
+ 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 */
/* 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 ) ); - 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 ) ); @@ -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 )
+ 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 */
/* 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 ) ); - pos += get_int8( &chunkdata[pos], &(avatar->bitdepth) );
+ pos += get_int8( &chunkdata[pos], datalen - pos, &(avatar->bitdepth) ); - pos += get_int32( &chunkdata[pos], &(avatar->crc) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->crc) ); - pos += get_int32( &chunkdata[pos], &(avatar->width) );
+ pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->width) ); - 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 ) - avatar->data = &chunkdata[pos];
+ if ( avatar->length > 0 ) + avatar->data = &chunkdata[pos]; --- 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];
- purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username );
+ 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 */
- size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating senddirect chunk (%i)\n", size );
+ 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];
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
@@ -1274,15 +1270,11 @@
/* map chunk header over data buffer */
- size = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating reject chunk (%i)\n", size );
+ 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];
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
@@ -1312,15 +1304,11 @@
/* map chunk header over data buffer */
- size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating getfile chunk (%i)\n", size );
+ 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];
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
@@ -1348,15 +1336,11 @@
/* map chunk header over data buffer */
- size = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating received chunk (%i)\n", size );
+ 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];
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen );
+ 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 */
- size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating set avatar chunk (%i)\n", size );
+ 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];
purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
@@ -1424,15 +1404,11 @@
/* map chunk header over data buffer */
- size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
- purple_debug_error( MXIT_PLUGIN_ID, "Error creating get avatar chunk (%i)\n", size );
+ 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 )
- 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 )
- 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 );
+ /* received packet is too short to even contain a chunk header */ + if ( records[0]->fields[0]->len < MXIT_CHUNK_HEADER_SIZE ) + /* 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 ) + purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i type) (%i bytes)\n", rcount, chunktype, chunksize ); /* supported chunked data types */
case CP_CHUNK_CUSTOM : /* custom resource */
/* 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
- 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 + 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 );
@@ -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 ); @@ -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 ); @@ -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 ( 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 */
+ /* this is a reply packet to a reject file request. no action is required */ 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 ); @@ -2240,7 +2209,7 @@
- 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 ); @@ -2556,7 +2525,7 @@
for ( j = 0; j < r->fcount; 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 */