libpurple/protocols/mxit/client.c

changeset 37901
41e45e18f3b2
parent 37850
43aa3fab2883
parent 37426
6fd4989b77e4
child 37939
8df8870e946c
--- a/libpurple/protocols/mxit/client.c	Fri Aug 12 21:36:10 2016 -0500
+++ b/libpurple/protocols/mxit/client.c	Fri Aug 19 23:03:37 2016 -0500
@@ -39,7 +39,6 @@
 #include	"formcmds.h"
 #include	"http.h"
 #include	"cipher.h"
-#include	"voicevideo.h"
 
 
 #define		MXIT_MS_OFFSET		3
@@ -149,6 +148,34 @@
 }
 
 
+/*------------------------------------------------------------------------
+ * 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
  */
@@ -435,23 +462,23 @@
 	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 */
@@ -678,17 +705,11 @@
 
 	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
 
-	/* Voice and Video supported */
-	if ( mxit_audio_enabled() && mxit_video_enabled() )
-		features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO );
-	else if ( mxit_audio_enabled() )
-		features |= MXIT_CF_VOICE;
-
 	/* generate client version string (eg, P-2.7.10-Y-PURPLE) */
 	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 */
@@ -722,17 +743,11 @@
 
 	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
 
-	/* Voice and Video supported */
-	if ( mxit_audio_enabled() && mxit_video_enabled() )
-		features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO );
-	else if ( mxit_audio_enabled() )
-		features |= MXIT_CF_VOICE;
-
 	/* generate client version string (eg, P-2.7.10-Y-PURPLE) */
 	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 */
@@ -746,7 +761,7 @@
 	/* 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 );
@@ -776,7 +791,7 @@
 		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
 	);
@@ -803,14 +818,14 @@
 	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 );
@@ -836,7 +851,7 @@
 		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
 	);
@@ -848,7 +863,7 @@
 			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] );
 	}
@@ -876,13 +891,13 @@
 	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 );
@@ -905,13 +920,13 @@
 	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 );
@@ -931,14 +946,14 @@
 	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 );
@@ -957,7 +972,7 @@
 	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
 	);
@@ -983,7 +998,7 @@
 	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,
@@ -1008,7 +1023,7 @@
 	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
 	);
@@ -1031,7 +1046,7 @@
 	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
 	);
@@ -1054,14 +1069,14 @@
 	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 );
@@ -1082,7 +1097,7 @@
 	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
 	);
@@ -1104,7 +1119,7 @@
 	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
 	);
@@ -1130,7 +1145,7 @@
 	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
 	);
@@ -1155,14 +1170,14 @@
 	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 );
@@ -1184,14 +1199,14 @@
 	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 );
@@ -1207,30 +1222,26 @@
  *  @param buf			The content of the file
  *  @param buflen		The length of the file contents
  */
-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen )
+void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, size_t buflen )
 {
 	char				data[CP_MAX_PACKET];
 	int					datalen		= 0;
 	gchar*				chunk;
-	int					size;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username );
+	size_t				chunksize;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %zu bytes to user '%s'\n", filename, buflen, username );
 
 	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ), "ms=" );
+	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 );
@@ -1248,25 +1259,21 @@
 	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 );
@@ -1281,30 +1288,26 @@
  *  @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 );
@@ -1322,25 +1325,21 @@
 	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 );
@@ -1354,30 +1353,26 @@
  *  @param data			The avatar data
  *  @param buflen		The length of the avatar data
  */
-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen )
+void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, size_t avatarlen )
 {
 	char				data[CP_MAX_PACKET];
 	int					datalen		= 0;
 	gchar*				chunk;
-	int					size;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen );
+	size_t				chunksize;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %zu bytes\n", avatarlen );
 
 	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ), "ms=" );
+	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 );
@@ -1398,25 +1393,21 @@
 	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 );
@@ -1459,10 +1450,6 @@
 	if ( records[1]->fcount >= 9 )
 		session->uid = g_strdup( records[1]->fields[8]->data );
 
-	/* extract VoIP server (from protocol 6.2) */
-	if ( records[1]->fcount >= 11 )
-		g_strlcpy( session->voip_server, records[1]->fields[10]->data, sizeof( session->voip_server ) );
-
 	/* display the current splash-screen */
 	if ( splash_popup_enabled( session ) )
 		splash_display( session );
@@ -1678,6 +1665,24 @@
 
 
 /*------------------------------------------------------------------------
+ * Parse the received mood value, and ensure that it is supported.
+ *
+ *  @param value		The received mood value.
+ *  @return				A valid mood value.
+ */
+static short mxit_parse_mood( const char* value )
+{
+	short mood = atoi( value );
+
+	/* ensure that the mood value is valid */
+	if ( ( mood >= MXIT_MOOD_NONE ) && ( mood <= MXIT_MOOD_STRESSED ) )
+		return mood;
+
+	return MXIT_MOOD_NONE;
+}
+
+
+/*------------------------------------------------------------------------
  * Process a received contact update packet.
  *
  *  @param session		The MXit session object
@@ -1710,7 +1715,7 @@
 
 		contact->presence = mxit_parse_presence( rec->fields[3]->data );
 		contact->type = atoi( rec->fields[4]->data );
-		contact->mood = atoi( rec->fields[5]->data );
+		contact->mood = mxit_parse_mood( rec->fields[5]->data );
 
 		if ( rec->fcount > 6 ) {
 			/* added in protocol 5.9 - flags & subtype */
@@ -1767,7 +1772,7 @@
 		if ( rec->fcount >= 7 )		/* flags field is included */
 			flags = atoi( rec->fields[6]->data );
 
-		mxit_update_buddy_presence( session, rec->fields[0]->data, mxit_parse_presence( rec->fields[1]->data ), atoi( rec->fields[2]->data ),
+		mxit_update_buddy_presence( session, rec->fields[0]->data, mxit_parse_presence( rec->fields[1]->data ), mxit_parse_mood( rec->fields[2]->data ),
 				rec->fields[3]->data, rec->fields[4]->data, flags );
 		mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data );
 	}
@@ -1806,6 +1811,12 @@
 	/* set the count for attributes */
 	count = atoi( records[0]->fields[1]->data );
 
+	/* ensure the packet has the correct number of fields */
+	if ( records[0]->fcount < ( 2 + ( count * 3 ) ) ) {
+		purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in extprofile response. fields=%i records=%i", records[0]->fcount, count );
+		return;
+	}
+
 	for ( i = 0; i < count; i++ ) {
 		char* fname;
 		char* fvalue;
@@ -1976,6 +1987,12 @@
 	 * userid \1 contactType \1 value0 \1 value1 ... valueN
 	 */
 
+	/* ensure that record[0] contacts the minumum number of fields */
+	if ( records[0]->fcount < 4 ) {
+		purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i", records[0]->fcount );
+		return;
+	}
+
 	/* the type of results */
 	searchType = atoi( records[0]->fields[0]->data );
 
@@ -1985,11 +2002,24 @@
 	/* set the count for attributes */
 	count = atoi( records[0]->fields[3]->data );
 
+	/* ensure that record[0] contains the specified number of attributes */
+	if ( records[0]->fcount < ( 4 + count ) ) {
+		purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i attributes=%i", records[0]->fcount, count );
+		return;
+	}
+
 	for ( i = 1; i < rcount; i ++ ) {
 		struct record*		rec		= records[i];
 		struct MXitProfile*	profile	= g_new0( struct MXitProfile, 1 );
 		int j;
 
+		/* ensure that each result contains the specified number of attributes */
+		if ( rec->fcount != ( 2 + count ) ) {
+			purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i attributes=%i", rec->fcount, count );
+			g_free( profile );
+			continue;
+		}
+
 		g_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) );
 		// TODO: ContactType - User or Service
 
@@ -2107,42 +2137,52 @@
  */
 static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount )
 {
-	char	type;
-	int		size;
-
-	type = records[0]->fields[0]->data[0];
-	size = get_chunk_len( records[0]->fields[0]->data );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i bytes)\n", rcount, size );
+	guint	chunktype;
+	guint32	chunksize;
+	gchar*	chunkdata;
+
+	/* received packet is too short to even contain a chunk header */
+	if ( records[0]->fields[0]->len < MXIT_CHUNK_HEADER_SIZE )
+		return;
+
+	/* decode the chunk header */
+	chunktype = chunk_type( records[0]->fields[0]->data );
+	chunksize = chunk_length( records[0]->fields[0]->data );
+	chunkdata = chunk_data( records[0]->fields[0]->data );
+
+	/* check chunk size against length of received data */
+	if ( MXIT_CHUNK_HEADER_SIZE + chunksize > records[0]->fields[0]->len )
+		return;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i type) (%i bytes)\n", rcount, chunktype, chunksize );
 
 	/* supported chunked data types */
-	switch ( type ) {
+	switch ( chunktype ) {
 		case CP_CHUNK_CUSTOM :				/* custom resource */
 			{
 				struct cr_chunk chunk;
 
 				/* decode the chunked data */
-				memset( &chunk, 0, sizeof( struct cr_chunk ) );
-				mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
-				purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
-
-				/* this is a splash-screen operation */
-				if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
-					if ( chunk.operation == CR_OP_UPDATE ) {		/* update the splash-screen */
-						struct splash_chunk *splash = chunk.resources->data;			// TODO: Fix - assuming 1st resource is splash
-						gboolean clickable = ( g_list_length( chunk.resources ) > 1 );	// TODO: Fix - if 2 resources, then is clickable
-
-						if ( splash != NULL )
-							splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
+				if ( mxit_chunk_parse_cr( chunkdata, chunksize, &chunk ) ) {
+
+					purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
+
+					/* this is a splash-screen operation */
+					if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
+						if ( chunk.operation == CR_OP_UPDATE ) {		/* update the splash-screen */
+							struct splash_chunk *splash = chunk.resources->data;			// TODO: Fix - assuming 1st resource is splash
+							gboolean clickable = ( g_list_length( chunk.resources ) > 1 );	// TODO: Fix - if 2 resources, then is clickable
+
+							if ( splash != NULL )
+								splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
+						}
+						else if ( chunk.operation == CR_OP_REMOVE )		/* remove the splash-screen */
+							splash_remove( session );
 					}
-					else if ( chunk.operation == CR_OP_REMOVE )		/* remove the splash-screen */
-						splash_remove( session );
+
+					/* cleanup custom resources */
+					g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
 				}
-
-				/* cleanup custom resources */
-				g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
-
 			}
 			break;
 
@@ -2151,11 +2191,10 @@
 				struct offerfile_chunk chunk;
 
 				/* decode the chunked data */
-				memset( &chunk, 0, sizeof( struct offerfile_chunk ) );
-				mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
-				/* process the offer */
-				mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
+				if ( mxit_chunk_parse_offer( chunkdata, chunksize, &chunk ) ) {
+					/* process the offer */
+					mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
+				}
 			}
 			break;
 
@@ -2164,11 +2203,10 @@
 				struct getfile_chunk chunk;
 
 				/* decode the chunked data */
-				memset( &chunk, 0, sizeof( struct getfile_chunk ) );
-				mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
-				/* process the getfile */
-				mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
+				if ( mxit_chunk_parse_get( chunkdata, chunksize, &chunk ) ) {
+					/* process the getfile */
+					mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
+				}
 			}
 			break;
 
@@ -2178,11 +2216,8 @@
 				struct contact* contact = NULL;
 
 				/* decode the chunked data */
-				memset( &chunk, 0, sizeof( struct getavatar_chunk ) );
-				mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
-				/* update avatar image */
-				if ( chunk.data ) {
+				if ( mxit_chunk_parse_get_avatar( chunkdata, chunksize, &chunk ) ) {
+					/* update avatar image */
 					purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid );
 
 					contact = get_mxit_invite_contact( session, chunk.mxitid );
@@ -2207,18 +2242,21 @@
 			/* this is a reply packet to a set avatar request. no action is required */
 			break;
 
+		case CP_CHUNK_REJECT :
+			/* this is a reply packet to a reject file request. no action is required */
+			break;
+
 		case CP_CHUNK_DIRECT_SND :
 			/* this is a ack for a file send. */
 			{
 				struct sendfile_chunk chunk;
 
-				memset( &chunk, 0, sizeof( struct sendfile_chunk ) );
-				mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
-				purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
-
-				if ( chunk.status != 0 )	/* not success */
-					mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
+				if ( mxit_chunk_parse_sendfile( chunkdata, chunksize, &chunk ) ) {
+					purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
+
+					if ( chunk.status != 0 )	/* not success */
+						mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
+				}
 			}
 			break;
 
@@ -2227,7 +2265,7 @@
 			break;
 
 		default :
-			purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", type );
+			purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", chunktype );
 			break;
 	}
 }
@@ -2543,7 +2581,7 @@
 
 		for ( j = 0; j < r->fcount; j++ ) {
 			f = r->fields[j];
-			purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%i) '%s' \n", f->len, f->data );
+			purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%zu) '%s' \n", f->len, f->data );
 		}
 	}
 }
@@ -2653,7 +2691,8 @@
 						/* new record */
 						if ( packet.rcount == 1 ) {
 							/* packet command */
-							packet.cmd = atoi( packet.records[0]->fields[0]->data );
+							if ( packet.records[0]->fcount > 0 )
+								packet.cmd = atoi( packet.records[0]->fields[0]->data );
 						}
 						else if ( packet.rcount == 2 ) {
 							/* special case: binary multimedia packets should not be parsed here */
@@ -2664,7 +2703,7 @@
 								field->data = &session->rx_dbuf[i + 1];
 								field->len = session->rx_i - i;
 								/* now skip the binary data */
-								res = get_chunk_len( field->data );
+								res = chunk_length( field->data );
 								/* determine if we have more packets */
 								if ( res + 6 + i < session->rx_i ) {
 									/* we have more than one packet in this stream */
@@ -2793,8 +2832,9 @@
 				/* 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x03)" ) );
+					return;
 				}
 				session->rx_state = RX_STATE_DATA;
 				session->rx_i = 0;

mercurial