summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Kramlich <grim@reaperworld.com>2016-06-12 22:17:08 -0500
committerGary Kramlich <grim@reaperworld.com>2016-06-12 22:17:08 -0500
commit0fd7d75e85fcbff309783e7cbffb99329c520d01 (patch)
treed7f7d404492ee59136f54c07381cd078118e0cd3
parent055a6b2669e475134c5796916ed2c773868339bc (diff)
parented207a12683c877191a51b47e15bc07db0a6b7a8 (diff)
downloadpidgin-0fd7d75e85fcbff309783e7cbffb99329c520d01.tar.gz
Merged TALOS-CAN-0137
-rw-r--r--ChangeLog21
-rw-r--r--libpurple/plugins/ssl/ssl-gnutls.c16
-rw-r--r--libpurple/protocols/mxit/chunk.c259
-rw-r--r--libpurple/protocols/mxit/chunk.h79
-rw-r--r--libpurple/protocols/mxit/filexfer.c6
-rw-r--r--libpurple/protocols/mxit/filexfer.h4
-rw-r--r--libpurple/protocols/mxit/formcmds.c32
-rw-r--r--libpurple/protocols/mxit/http.c23
-rw-r--r--libpurple/protocols/mxit/http.h4
-rw-r--r--libpurple/protocols/mxit/markup.c19
-rw-r--r--libpurple/protocols/mxit/protocol.c337
-rw-r--r--libpurple/protocols/mxit/protocol.h8
-rw-r--r--libpurple/protocols/mxit/splashscreen.c6
-rw-r--r--libpurple/protocols/mxit/splashscreen.h2
14 files changed, 474 insertions, 342 deletions
diff --git a/ChangeLog b/ChangeLog
index 18fccba19c..27767b1548 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -14,6 +14,27 @@ version 2.10.13 (MM/DD/YY):
* 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)
+ * Fixed an invalid read. Discovered by Yves Younan of Cisco Talos
+ (TALOS-CAN-0118)
+ * Fixed a remote buffer overflow vulnerability. Discovered by Yves
+ Younan of Cisco Talos. (TALOS-CAN-0119)
+ * Fixed an out-of-bounds read discovered by Yves Younan of Cisco Talos.
+ (TALOS-CAN-0123)
+ * Fixed a directory traversal issue. Discovered by Yves Younan of Cisco
+ Talos (TALOS-CAN-0128)
+ * Fixed a remote denial of service vulnerability that could result in
+ a null pointer dereference. Discovered by Yves Younan of Cisco Talos.
+ (TALOS-CAN-0133)
+ * Fixed a remote denial of service that could result in an out-of-bounds
+ read. Discovered by Yves Younan of Cisco Talos (TALOS-CAN-0134)
+ * Fixed multiple remote buffer overflows. Discovered by Yves Younan of
+ Cisco Talos. (TALOS-CAN-0136)
* Fixed a remote NULL pointer dereference. Discovered by Yves Younan of
Cisco Talos (TALOS-CAN-0137)
diff --git a/libpurple/plugins/ssl/ssl-gnutls.c b/libpurple/plugins/ssl/ssl-gnutls.c
index 063ee69c53..e8306dd120 100644
--- a/libpurple/plugins/ssl/ssl-gnutls.c
+++ b/libpurple/plugins/ssl/ssl-gnutls.c
@@ -608,7 +608,7 @@ ssl_gnutls_get_peer_certificates(PurpleSslConnection * gsc)
TODO: Is anyone complaining? (Maybe elb?) */
/* only append if previous cert was actually signed by this one.
* Thanks Microsoft. */
- if ((prvcrt == NULL) || x509_certificate_signed_by(prvcrt, newcrt)) {
+ if ((newcrt != NULL) && ((prvcrt == NULL) || x509_certificate_signed_by(prvcrt, newcrt))) {
peer_certs = g_list_append(peer_certs, newcrt);
prvcrt = newcrt;
} else {
@@ -685,12 +685,18 @@ x509_import_from_datum(const gnutls_datum_t dt, gnutls_x509_crt_fmt_t mode)
/* Allocate and prepare the internal certificate data */
certdat = g_new0(x509_crtdata_t, 1);
- gnutls_x509_crt_init(&(certdat->crt));
+ if (gnutls_x509_crt_init(&(certdat->crt)) != 0) {
+ g_free(certdat);
+ return NULL;
+ }
certdat->refcount = 0;
/* Perform the actual certificate parse */
/* Yes, certdat->crt should be passed as-is */
- gnutls_x509_crt_import(certdat->crt, &dt, mode);
+ if (gnutls_x509_crt_import(certdat->crt, &dt, mode) != 0) {
+ g_free(certdat);
+ return NULL;
+ }
/* Allocate the certificate and load it with data */
crt = g_new0(PurpleCertificate, 1);
@@ -780,7 +786,9 @@ x509_importcerts_from_file(const gchar * filename)
/* Perform the conversion; files should be in PEM format */
crt = x509_import_from_datum(dt, GNUTLS_X509_FMT_PEM);
- crts = g_slist_prepend(crts, crt);
+ if (crt != NULL) {
+ crts = g_slist_prepend(crts, crt);
+ }
begin = end;
}
diff --git a/libpurple/protocols/mxit/chunk.c b/libpurple/protocols/mxit/chunk.c
index a575bcdd75..66dbb3a6b7 100644
--- a/libpurple/protocols/mxit/chunk.c
+++ b/libpurple/protocols/mxit/chunk.c
@@ -151,11 +151,15 @@ static int add_utf8_string( char* chunkdata, const char* str )
* 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 @@ static int get_int8( const char* chunkdata, char* value )
* 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 @@ static int get_int16( const char* chunkdata, short* value )
* 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 @@ static int get_int32( const char* chunkdata, int* value )
* 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 @@ static int get_int64( const char* chunkdata, int64_t* value )
* 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 @@ static int get_data( const char* chunkdata, char* dest, int datalen )
* 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 @@ static int get_utf8_string( const char* chunkdata, char* str, int maxstrlen )
}
/* 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 @@ static int get_utf8_string( const char* chunkdata, char* str, int maxstrlen )
* @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 @@ int mxit_chunk_create_reject( char* chunkdata, const char* fileid )
* @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 @@ int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, in
* @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 @@ int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned ch
* @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 @@ int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const c
* @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 @@ int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, in
* @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 @@ int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const cha
* @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 @@ void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chun
/* flags [4 bytes] */
/* not used by libPurple */
+
+ return TRUE;
}
@@ -492,27 +522,41 @@ void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chun
* @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 (%i bytes)\n", datalen );
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%zu 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 @@ void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* g
* @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 @@ static void mxit_chunk_parse_splash( char* chunkdata, int datalen, struct splash
* @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) );
+
+ /* total length of all the chunks that are included [4 bytes] */
+ pos += get_int32( &chunkdata[pos], datalen - pos, &chunkslen );
- /* chunk size [4 bytes] */
- pos += get_int32( &chunkdata[pos], &chunklen );
+ /* 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 @@ void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr )
}
/* 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 @@ void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr )
* @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 (%zu bytes)\n", datalen );
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%i 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 @@ void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_ch
* @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;
}
diff --git a/libpurple/protocols/mxit/chunk.h b/libpurple/protocols/mxit/chunk.h
index 6ef094f638..841c4e6172 100644
--- a/libpurple/protocols/mxit/chunk.h
+++ b/libpurple/protocols/mxit/chunk.h
@@ -85,7 +85,7 @@ static inline void set_chunk_type( gchar* chunkheader, guint type )
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 @@ static inline gchar* chunk_data( gchar* chunkheader )
* 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 @@ struct cr_chunk {
* 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 @@ struct splash_click_chunk {
* 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_ */
diff --git a/libpurple/protocols/mxit/filexfer.c b/libpurple/protocols/mxit/filexfer.c
index 5eef9cb140..b96f3f08e4 100644
--- a/libpurple/protocols/mxit/filexfer.c
+++ b/libpurple/protocols/mxit/filexfer.c
@@ -357,7 +357,7 @@ void mxit_xfer_tx( PurpleConnection* gc, const char* who, const char* filename )
* @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 @@ void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, cons
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 @@ static PurpleXfer* find_mxit_xfer( struct MXitSession* session, const char* file
* @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;
diff --git a/libpurple/protocols/mxit/filexfer.h b/libpurple/protocols/mxit/filexfer.h
index 4ec953d928..cd0a20f58e 100644
--- a/libpurple/protocols/mxit/filexfer.h
+++ b/libpurple/protocols/mxit/filexfer.h
@@ -43,8 +43,8 @@ void mxit_xfer_tx( PurpleConnection* gc, const char* who, const char* filename )
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_ */
diff --git a/libpurple/protocols/mxit/formcmds.c b/libpurple/protocols/mxit/formcmds.c
index 0e60a6a02a..1edad2d185 100644
--- a/libpurple/protocols/mxit/formcmds.c
+++ b/libpurple/protocols/mxit/formcmds.c
@@ -395,6 +395,9 @@ static void command_imagestrip(struct MXitSession* session, const char* from, GH
/* validator */
validator = g_hash_table_lookup(hash, "v");
+ if (!name || !validator)
+ return;
+
/* image data */
tmp = g_hash_table_lookup(hash, "dat");
if (tmp) {
@@ -430,13 +433,13 @@ static void command_imagestrip(struct MXitSession* session, const char* from, GH
}
tmp = g_hash_table_lookup(hash, "fw");
- width = atoi(tmp);
+ width = (tmp ? atoi(tmp) : 0);
tmp = g_hash_table_lookup(hash, "fh");
- height = atoi(tmp);
+ height = (tmp ? atoi(tmp) : 0);
tmp = g_hash_table_lookup(hash, "layer");
- layer = atoi(tmp);
+ layer = (tmp ? atoi(tmp) : 0);
purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip %s from %s: [w=%i h=%i l=%i validator=%s]\n", name, from, width, height, layer, validator);
}
@@ -519,29 +522,40 @@ static void command_table(struct RXMsgData* mx, GHashTable* hash)
const char* tmp;
const char* name;
int mode;
- int nr_columns = 0, nr_rows = 0;
+ unsigned int nr_columns = 0, nr_rows = 0;
gchar** coldata;
- int i, j;
+ unsigned int i, j;
/* table name */
name = g_hash_table_lookup(hash, "nm");
+ if (!name)
+ return;
/* number of columns */
tmp = g_hash_table_lookup(hash, "col");
- nr_columns = atoi(tmp);
+ nr_columns = (tmp ? atoi(tmp) : 0);
/* number of rows */
tmp = g_hash_table_lookup(hash, "row");
- nr_rows = atoi(tmp);
+ nr_rows = (tmp ? atoi(tmp) : 0);
/* mode */
tmp = g_hash_table_lookup(hash, "mode");
- mode = atoi(tmp);
+ mode = (tmp ? atoi(tmp) : 0);
/* table data */
tmp = g_hash_table_lookup(hash, "d");
+ if (!tmp)
+ tmp = "";
+
coldata = g_strsplit(tmp, "~", 0); /* split into entries for each row & column */
+ if (g_strv_length(coldata) != (nr_rows * nr_columns)) {
+ purple_debug_info(MXIT_PLUGIN_ID, "Invalid table data: cols=%i rows=%i\n", nr_columns, nr_rows);
+ g_strfreev(coldata);
+ return;
+ }
+
purple_debug_info(MXIT_PLUGIN_ID, "Table %s from %s: [cols=%i rows=%i mode=%i]\n", name, mx->from, nr_columns, nr_rows, mode);
for (i = 0; i < nr_rows; i++) {
@@ -549,6 +563,8 @@ static void command_table(struct RXMsgData* mx, GHashTable* hash)
purple_debug_info(MXIT_PLUGIN_ID, " Row %i Column %i = %s\n", i, j, coldata[i*nr_columns + j]);
}
}
+
+ g_strfreev(coldata);
}
diff --git a/libpurple/protocols/mxit/http.c b/libpurple/protocols/mxit/http.c
index 9a91775366..423659a52d 100644
--- a/libpurple/protocols/mxit/http.c
+++ b/libpurple/protocols/mxit/http.c
@@ -63,9 +63,9 @@ static void free_http_request( struct http_request* req )
* @param pktlen The length of the packet data
* @return Return -1 on error, otherwise 0
*/
-static int mxit_http_raw_write( int fd, const char* pktdata, int pktlen )
+static int mxit_http_raw_write( int fd, const char* pktdata, size_t pktlen )
{
- int written;
+ size_t written;
int res;
written = 0;
@@ -97,9 +97,9 @@ static void mxit_cb_http_read( gpointer user_data, gint source, PurpleInputCondi
{
struct MXitSession* session = (struct MXitSession*) user_data;
char buf[256];
- int buflen;
+ unsigned int buflen;
char* body;
- int bodylen;
+ unsigned int bodylen;
char* ch;
int len;
char* tmp;
@@ -182,7 +182,7 @@ nextpacket:
goto done;
}
tmp = g_strndup( ch, tmp - ch );
- bodylen = atoi( tmp );
+ bodylen = strtoul( tmp, NULL, 10 );
g_free( tmp );
tmp = NULL;
@@ -315,22 +315,25 @@ static void mxit_cb_http_connect( gpointer user_data, gint source, const gchar*
* @param session The MXit session object
* @param host The server name to connect to
* @param port The port number to connect to
- * @param data The HTTP request data (including HTTP headers etc.)
+ * @param header The HTTP header.
+ * @param data The HTTP request data.
* @param datalen The HTTP request data length
*/
-void mxit_http_send_request( struct MXitSession* session, char* host, int port, const char* data, int datalen )
+void mxit_http_send_request( struct MXitSession* session, char* host, int port, gchar* header, const char* data, size_t datalen )
{
PurpleProxyConnectData* con = NULL;
struct http_request* req;
+ size_t headerlen = strlen( header );
/* build the http request */
req = g_new0( struct http_request, 1 );
req->session = session;
req->host = host;
req->port = port;
- req->data = g_malloc0( datalen );
- memcpy( req->data, data, datalen );
- req->datalen = datalen;
+ req->data = g_malloc0( headerlen + datalen );
+ memcpy( req->data, header, headerlen );
+ memcpy( req->data + headerlen, data, datalen );
+ req->datalen = headerlen + datalen;
/* open connection to the HTTP server */
con = purple_proxy_connect( NULL, session->acc, host, port, mxit_cb_http_connect, req );
diff --git a/libpurple/protocols/mxit/http.h b/libpurple/protocols/mxit/http.h
index 03808fff58..eef0e4d464 100644
--- a/libpurple/protocols/mxit/http.h
+++ b/libpurple/protocols/mxit/http.h
@@ -35,11 +35,11 @@ struct http_request
char* host;
int port;
char* data;
- int datalen;
+ size_t datalen;
};
-void mxit_http_send_request( struct MXitSession* session, char* host, int port, const char* data, int datalen );
+void mxit_http_send_request( struct MXitSession* session, char* host, int port, gchar* header, const char* data, size_t datalen );
diff --git a/libpurple/protocols/mxit/markup.c b/libpurple/protocols/mxit/markup.c
index 92d8d67a16..040927f359 100644
--- a/libpurple/protocols/mxit/markup.c
+++ b/libpurple/protocols/mxit/markup.c
@@ -1083,7 +1083,6 @@ char* mxit_convert_markup_tx( const char* message, int* msgtype )
GList* entry;
GList* tagstack = NULL;
char* reply;
- char color[8];
int len = strlen ( message );
int i;
@@ -1145,12 +1144,18 @@ char* mxit_convert_markup_tx( const char* message, int* msgtype )
}
else if ( purple_str_has_prefix( &message[i], "<font color=" ) ) {
/* font colour */
- tag = g_new0( struct tag, 1 );
- tag->type = MXIT_TAG_COLOR;
- tagstack = g_list_append( tagstack, tag );
- memset( color, 0x00, sizeof( color ) );
- memcpy( color, &message[i + 13], 7 );
- g_string_append( mx, color );
+ char color[8];
+
+ /* ensure we have the complete tag: <font color="#123456"> */
+ if ( i + 20 < len ) {
+ tag = g_new0( struct tag, 1 );
+ tag->type = MXIT_TAG_COLOR;
+ tagstack = g_list_append( tagstack, tag );
+
+ memset( color, 0x00, sizeof( color ) );
+ memcpy( color, &message[i + 13], 7 );
+ g_string_append( mx, color );
+ }
}
else if ( purple_str_has_prefix( &message[i], "</font>" ) ) {
/* end of font tag */
diff --git a/libpurple/protocols/mxit/protocol.c b/libpurple/protocols/mxit/protocol.c
index fb4f747790..d88e15fdd1 100644
--- a/libpurple/protocols/mxit/protocol.c
+++ b/libpurple/protocols/mxit/protocol.c
@@ -148,6 +148,34 @@ gboolean find_active_chat( const GList* chats, const char* who )
}
+/*------------------------------------------------------------------------
+ * scnprintf
+ *
+ * @param string The destination buffer.
+ * @param size The maximum size of the destination buffer.
+ * @param format The format string
+ * @param ... The parameters to the format string.
+ * @return The number of characters actually stored in the buffer.
+ */
+static int scnprintf( gchar* string, size_t size, const char *format, ... )
+{
+ va_list args;
+ guint i;
+
+ va_start( args, format );
+ i = g_vsnprintf( string, size, format, args );
+ va_end( args );
+
+ if ( i < size )
+ return i;
+ else if ( size > 0 ) /* destination buffer too short - return number of characters actually inserted */
+ return size - 1;
+ else
+ return 0;
+}
+
+
+
/*========================================================================================================================
* Low-level Packet transmission
*/
@@ -334,11 +362,10 @@ static void mxit_write_http_get( struct MXitSession* session, struct tx_packet*
*/
static void mxit_write_http_post( struct MXitSession* session, struct tx_packet* packet )
{
- char request[256 + packet->datalen];
- int reqlen;
char* host_name;
int host_port;
gboolean ok;
+ gchar* httpheader;
/* extract the HTTP host name and host port number to connect to */
ok = purple_url_parse( session->http_server, &host_name, &host_port, NULL, NULL, NULL );
@@ -350,8 +377,8 @@ static void mxit_write_http_post( struct MXitSession* session, struct tx_packet*
packet->header[packet->headerlen - 1] = '\0';
packet->headerlen--;
- /* build the HTTP request packet */
- reqlen = g_snprintf( request, 256,
+ /* build the HTTP request header */
+ httpheader = g_strdup_printf(
"POST %s?%s HTTP/1.1\r\n"
"User-Agent: " MXIT_HTTP_USERAGENT "\r\n"
"Content-Type: application/octet-stream\r\n"
@@ -364,17 +391,17 @@ static void mxit_write_http_post( struct MXitSession* session, struct tx_packet*
packet->datalen - MXIT_MS_OFFSET
);
- /* copy over the packet body data (could be binary) */
- memcpy( request + reqlen, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
- reqlen += packet->datalen;
-
#ifdef DEBUG_PROTOCOL
purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST:\n" );
- dump_bytes( session, request, reqlen );
+ dump_bytes( session, httpheader, strlen( httpheader ) );
+ dump_bytes( session, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
#endif
/* send the request to the HTTP server */
- mxit_http_send_request( session, host_name, host_port, request, reqlen );
+ mxit_http_send_request( session, host_name, host_port, httpheader, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
+
+ /* cleanup */
+ g_free( httpheader );
}
@@ -463,23 +490,23 @@ static void mxit_queue_packet( struct MXitSession* session, const char* data, in
packet->headerlen = 0;
/* create generic packet header */
- hlen = g_snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */
+ hlen = scnprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */
if ( session->http ) {
/* http connection only */
- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "s=" );
+ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "s=" );
if ( session->http_sesid > 0 ) {
- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */
+ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */
}
session->http_seqno++;
- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */
+ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */
}
- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */
+ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */
if ( !session->http ) {
/* socket connection only */
- packet->headerlen = g_snprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */
+ packet->headerlen = scnprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */
}
/* copy the header to packet */
@@ -710,7 +737,7 @@ void mxit_send_register( struct MXitSession* session )
clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%i%c%s%c" /* "ms"=password\1version\1maxreplyLen\1name\1 */
"%s%c%i%c%s%c%s%c" /* dateOfBirth\1gender\1location\1capabilities\1 */
"%s%c%i%c%s%c%s" /* dc\1features\1dialingcode\1locale */
@@ -748,7 +775,7 @@ void mxit_send_login( struct MXitSession* session )
clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%i%c" /* "ms"=password\1version\1getContacts\1 */
"%s%c%s%c%i%c" /* capabilities\1dc\1features\1 */
"%s%c%s%c" /* dialingcode\1locale\1 */
@@ -762,7 +789,7 @@ void mxit_send_login( struct MXitSession* session )
/* include "custom resource" information */
splashId = splash_current( session );
if ( splashId != NULL )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN );
@@ -792,7 +819,7 @@ void mxit_send_message( struct MXitSession* session, const char* to, const char*
markuped_msg = g_strdup( msg );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%i%c%i", /* "ms"=jid\1msg\1type\1flags */
to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON
);
@@ -819,14 +846,14 @@ void mxit_send_extprofile_request( struct MXitSession* session, const char* user
int datalen;
unsigned int i;
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%i", /* "ms="mxitid\1nr_attributes */
( username ? username : "" ), CP_FLD_TERM, nr_attrib
);
/* add attributes */
for ( i = 0; i < nr_attrib; i++ )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET );
@@ -852,7 +879,7 @@ void mxit_send_extprofile_update( struct MXitSession* session, const char* passw
parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%i", /* "ms"=password\1nr_attibutes */
( password ) ? password : "", CP_FLD_TERM, nr_attrib
);
@@ -864,7 +891,7 @@ void mxit_send_extprofile_update( struct MXitSession* session, const char* passw
g_strfreev( parts );
return;
}
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen,
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen,
"%c%s%c%s%c%s", /* \1name\1type\1value */
CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] );
}
@@ -892,13 +919,13 @@ void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned i
unsigned int i;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
/* add attributes */
for ( i = 0; i < nr_attrib; i++ )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
@@ -921,13 +948,13 @@ void mxit_send_suggest_search( struct MXitSession* session, int max, const char*
unsigned int i;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
/* add attributes */
for ( i = 0; i < nr_attrib; i++ )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
@@ -947,14 +974,14 @@ void mxit_send_presence( struct MXitSession* session, int presence, const char*
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%i%c", /* "ms"=show\1status */
presence, CP_FLD_TERM
);
/* append status message (if one is set) */
if ( statusmsg )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_STATUS );
@@ -973,7 +1000,7 @@ void mxit_send_mood( struct MXitSession* session, int mood )
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%i", /* "ms"=mood */
mood
);
@@ -999,7 +1026,7 @@ void mxit_send_invite( struct MXitSession* session, const char* username, gboole
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%s%c%i%c%s%c%i", /* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */
groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias,
CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM,
@@ -1024,7 +1051,7 @@ void mxit_send_remove( struct MXitSession* session, const char* username )
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s", /* "ms"=username */
username
);
@@ -1047,7 +1074,7 @@ void mxit_send_allow_sub( struct MXitSession* session, const char* username, con
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%s", /* "ms"=username\1group\1alias */
username, CP_FLD_TERM, "", CP_FLD_TERM, alias
);
@@ -1070,14 +1097,14 @@ void mxit_send_deny_sub( struct MXitSession* session, const char* username, cons
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s", /* "ms"=username */
username
);
/* append reason (if one is set) */
if ( reason )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_DENY );
@@ -1098,7 +1125,7 @@ void mxit_send_update_contact( struct MXitSession* session, const char* username
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%s", /* "ms"=groupname\1username\1alias */
groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias
);
@@ -1120,7 +1147,7 @@ void mxit_send_splashclick( struct MXitSession* session, const char* splashid )
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s", /* "ms"=splashId */
splashid
);
@@ -1146,7 +1173,7 @@ void mxit_send_msgevent( struct MXitSession* session, const char* to, const char
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%i", /* "ms"=contactAddress \1 id \1 event */
to, CP_FLD_TERM, id, CP_FLD_TERM, event
);
@@ -1171,14 +1198,14 @@ void mxit_send_groupchat_create( struct MXitSession* session, const char* groupn
int i;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%i", /* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
groupname, CP_FLD_TERM, nr_usernames
);
/* add usernames */
for ( i = 0; i < nr_usernames; i++ )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE );
@@ -1200,14 +1227,14 @@ void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid
int i;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%i", /* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
roomid, CP_FLD_TERM, nr_usernames
);
/* add usernames */
for ( i = 0; i < nr_usernames; i++ )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE );
@@ -1223,30 +1250,26 @@ void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid
* @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;
+ size_t chunksize;
- 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=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* 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,25 +1287,21 @@ void mxit_send_file_reject( struct MXitSession* session, const char* fileid )
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" );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ), "ms=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* 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,30 +1316,26 @@ void mxit_send_file_reject( struct MXitSession* session, const char* fileid )
* @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" );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ), "ms=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* 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,25 +1353,21 @@ void mxit_send_file_received( struct MXitSession* session, const char* fileid, s
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" );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ), "ms=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* 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,30 +1381,26 @@ void mxit_send_file_received( struct MXitSession* session, const char* fileid, s
* @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;
+ size_t chunksize;
- 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=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* 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,25 +1421,21 @@ void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const cha
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 );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ), "ms=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* 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 +2103,6 @@ static void mxit_parse_cmd_msgevent( struct MXitSession* session, struct record*
/*------------------------------------------------------------------------
- * 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 +2111,52 @@ static int get_chunk_len( const char* chunkdata )
*/
static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount )
{
- char type;
- int size;
+ guint chunktype;
+ guint32 chunksize;
+ gchar* chunkdata;
- type = records[0]->fields[0]->data[0];
- size = get_chunk_len( records[0]->fields[0]->data );
+ /* 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 bytes)\n", rcount, size );
+ 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 );
+ 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 );
+ 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
+ /* 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 ( 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 +2165,10 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r
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 +2177,10 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r
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 +2190,8 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r
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 +2213,21 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r
/* 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 );
+ 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 );
- 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 ( chunk.status != 0 ) /* not success */
+ mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
+ }
}
break;
@@ -2240,7 +2236,7 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r
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 +2552,7 @@ static void dump_packet( struct rx_packet* p )
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 );
}
}
}
@@ -2678,7 +2674,7 @@ int mxit_parse_packet( struct MXitSession* session )
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 */
@@ -2807,8 +2803,9 @@ void mxit_cb_rx( gpointer user_data, gint source, PurpleInputCondition cond )
/* the end of the length record found */
session->rx_lbuf[session->rx_i] = '\0';
session->rx_res = atoi( &session->rx_lbuf[3] );
- if ( session->rx_res > CP_MAX_PACKET ) {
+ if ( ( session->rx_res <= 0 ) || ( session->rx_res > CP_MAX_PACKET ) ) {
purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x03)" ) );
+ return;
}
session->rx_state = RX_STATE_DATA;
session->rx_i = 0;
diff --git a/libpurple/protocols/mxit/protocol.h b/libpurple/protocols/mxit/protocol.h
index 8826f0d05c..fad7ae54c0 100644
--- a/libpurple/protocols/mxit/protocol.h
+++ b/libpurple/protocols/mxit/protocol.h
@@ -241,7 +241,7 @@ struct MXitSession;
struct field {
char* data;
- int len;
+ size_t len;
};
struct record {
@@ -332,11 +332,11 @@ void mxit_send_update_contact( struct MXitSession* session, const char* username
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[] );
diff --git a/libpurple/protocols/mxit/splashscreen.c b/libpurple/protocols/mxit/splashscreen.c
index 655cfd4879..2732e237a8 100644
--- a/libpurple/protocols/mxit/splashscreen.c
+++ b/libpurple/protocols/mxit/splashscreen.c
@@ -93,7 +93,7 @@ void splash_remove(struct MXitSession* session)
purple_debug_info(MXIT_PLUGIN_ID, "Removing splashId: '%s'\n", splashId);
/* Delete stored splash image */
- filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), splashId);
+ filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), purple_escape_filename(splashId));
g_unlink(filename);
g_free(filename);
@@ -112,7 +112,7 @@ void splash_remove(struct MXitSession* session)
* @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;
@@ -179,7 +179,7 @@ void splash_display(struct MXitSession* session)
purple_debug_info(MXIT_PLUGIN_ID, "Display Splash: '%s'\n", splashId);
/* Load splash-screen image from file */
- filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), splashId);
+ filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), purple_escape_filename(splashId));
if (g_file_get_contents(filename, &imgdata, &imglen, NULL)) {
char buf[128];
diff --git a/libpurple/protocols/mxit/splashscreen.h b/libpurple/protocols/mxit/splashscreen.h
index eb148d7aba..ddc959c50b 100644
--- a/libpurple/protocols/mxit/splashscreen.h
+++ b/libpurple/protocols/mxit/splashscreen.h
@@ -44,7 +44,7 @@ gboolean splash_popup_enabled(struct MXitSession* session);
/*
* 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).