diff options
author | Gary Kramlich <grim@reaperworld.com> | 2016-06-12 22:17:08 -0500 |
---|---|---|
committer | Gary Kramlich <grim@reaperworld.com> | 2016-06-12 22:17:08 -0500 |
commit | 0fd7d75e85fcbff309783e7cbffb99329c520d01 (patch) | |
tree | d7f7d404492ee59136f54c07381cd078118e0cd3 | |
parent | 055a6b2669e475134c5796916ed2c773868339bc (diff) | |
parent | ed207a12683c877191a51b47e15bc07db0a6b7a8 (diff) | |
download | pidgin-0fd7d75e85fcbff309783e7cbffb99329c520d01.tar.gz |
Merged TALOS-CAN-0137
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | libpurple/plugins/ssl/ssl-gnutls.c | 16 | ||||
-rw-r--r-- | libpurple/protocols/mxit/chunk.c | 259 | ||||
-rw-r--r-- | libpurple/protocols/mxit/chunk.h | 79 | ||||
-rw-r--r-- | libpurple/protocols/mxit/filexfer.c | 6 | ||||
-rw-r--r-- | libpurple/protocols/mxit/filexfer.h | 4 | ||||
-rw-r--r-- | libpurple/protocols/mxit/formcmds.c | 32 | ||||
-rw-r--r-- | libpurple/protocols/mxit/http.c | 23 | ||||
-rw-r--r-- | libpurple/protocols/mxit/http.h | 4 | ||||
-rw-r--r-- | libpurple/protocols/mxit/markup.c | 19 | ||||
-rw-r--r-- | libpurple/protocols/mxit/protocol.c | 337 | ||||
-rw-r--r-- | libpurple/protocols/mxit/protocol.h | 8 | ||||
-rw-r--r-- | libpurple/protocols/mxit/splashscreen.c | 6 | ||||
-rw-r--r-- | libpurple/protocols/mxit/splashscreen.h | 2 |
14 files changed, 474 insertions, 342 deletions
@@ -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). |