summaryrefslogtreecommitdiff
path: root/libpurple/protocols/mxit/protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpurple/protocols/mxit/protocol.c')
-rw-r--r--libpurple/protocols/mxit/protocol.c193
1 files changed, 140 insertions, 53 deletions
diff --git a/libpurple/protocols/mxit/protocol.c b/libpurple/protocols/mxit/protocol.c
index 166f54f472..851496dac2 100644
--- a/libpurple/protocols/mxit/protocol.c
+++ b/libpurple/protocols/mxit/protocol.c
@@ -445,7 +445,7 @@ static void mxit_queue_packet( struct MXitSession* session, const char* data, in
packet->headerlen = 0;
/* create generic packet header */
- hlen = sprintf( header, "id=%s%c", session->acc->username, CP_REC_TERM ); /* client msisdn */
+ hlen = snprintf( header, sizeof( header ), "id=%s%c", session->acc->username, CP_REC_TERM ); /* client msisdn */
if ( session->http ) {
/* http connection only */
@@ -520,7 +520,7 @@ gboolean mxit_manage_queue( gpointer user_data )
/* we are still waiting for an outstanding ACK from the MXit server */
if ( session->last_tx <= time( NULL ) - MXIT_ACK_TIMEOUT ) {
/* ack timeout! so we close the connection here */
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%X'\n", session->outack );
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%i'\n", session->outack );
purple_connection_error( session->con, _( "Timeout while waiting for a response from the MXit server." ) );
}
return TRUE;
@@ -642,7 +642,8 @@ void mxit_send_register( struct MXitSession* session )
locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s%c%s%c%i%c%s%c" /* "ms"=password\1version\1maxreplyLen\1name\1 */
+ datalen = snprintf( 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 */
session->encpwd, CP_FLD_TERM, MXIT_CP_VERSION, CP_FLD_TERM, CP_MAX_FILESIZE, CP_FLD_TERM, profile->nickname, CP_FLD_TERM,
@@ -670,12 +671,15 @@ void mxit_send_login( struct MXitSession* session )
locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s%c%s%c%i%c" /* "ms"=password\1version\1getContacts\1 */
+ datalen = snprintf( 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", /* dialingcode\1locale */
+ "%s%c%s%c" /* dialingcode\1locale\1 */
+ "%i%c%i%c%i", /* maxReplyLen\1protocolVer\1lastRosterUpdate */
session->encpwd, CP_FLD_TERM, MXIT_CP_VERSION, CP_FLD_TERM, 1, CP_FLD_TERM,
MXIT_CP_CAP, CP_FLD_TERM, session->distcode, CP_FLD_TERM, MXIT_CP_FEATURES, CP_FLD_TERM,
- session->dialcode, CP_FLD_TERM, locale
+ session->dialcode, CP_FLD_TERM, locale, CP_FLD_TERM,
+ CP_MAX_FILESIZE, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
);
/* include "custom resource" information */
@@ -709,7 +713,8 @@ 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 = sprintf( data, "ms=%s%c%s%c%i%c%i", /* "ms"=jid\1msg\1type\1flags */
+ datalen = snprintf( 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
);
@@ -735,7 +740,8 @@ void mxit_send_extprofile_request( struct MXitSession* session, const char* user
int datalen;
unsigned int i;
- datalen = sprintf( data, "ms=%s%c%i", /* "ms="mxitid\1nr_attributes */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%s%c%i", /* "ms="mxitid\1nr_attributes */
(username ? username : ""), CP_FLD_TERM, nr_attrib);
/* add attributes */
@@ -765,7 +771,8 @@ void mxit_send_extprofile_update( struct MXitSession* session, const char* passw
parts = g_strsplit( attributes, "\01", ( MXIT_MAX_ATTRIBS * 3 ) );
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s%c%i", /* "ms"=password\1nr_attibutes */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%s%c%i", /* "ms"=password\1nr_attibutes */
( password ) ? password : "", CP_FLD_TERM, nr_attrib
);
@@ -795,7 +802,8 @@ void mxit_send_presence( struct MXitSession* session, int presence, const char*
int datalen;
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%i%c", /* "ms"=show\1status */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%i%c", /* "ms"=show\1status */
presence, CP_FLD_TERM
);
@@ -820,7 +828,8 @@ void mxit_send_mood( struct MXitSession* session, int mood )
int datalen;
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%i", /* "ms"=mood */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%i", /* "ms"=mood */
mood
);
@@ -843,7 +852,8 @@ void mxit_send_invite( struct MXitSession* session, const char* username, const
int datalen;
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s%c%s%c%s%c%i%c%s", /* "ms"=group\1username\1alias\1type\1msg */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%s%c%i%c%s", /* "ms"=group\1username\1alias\1type\1msg */
groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias,
CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM, ""
);
@@ -865,7 +875,8 @@ void mxit_send_remove( struct MXitSession* session, const char* username )
int datalen;
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s", /* "ms"=username */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%s", /* "ms"=username */
username
);
@@ -887,7 +898,8 @@ void mxit_send_allow_sub( struct MXitSession* session, const char* username, con
int datalen;
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s%c%s%c%s", /* "ms"=username\1group\1alias */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%s", /* "ms"=username\1group\1alias */
username, CP_FLD_TERM, "", CP_FLD_TERM, alias
);
@@ -908,7 +920,8 @@ void mxit_send_deny_sub( struct MXitSession* session, const char* username )
int datalen;
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s", /* "ms"=username */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%s", /* "ms"=username */
username
);
@@ -931,7 +944,8 @@ void mxit_send_update_contact( struct MXitSession* session, const char* username
int datalen;
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s%c%s%c%s", /* "ms"=groupname\1username\1alias */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%s", /* "ms"=groupname\1username\1alias */
groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias
);
@@ -952,7 +966,8 @@ void mxit_send_splashclick( struct MXitSession* session, const char* splashid )
int datalen;
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s", /* "ms"=splashId */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%s", /* "ms"=splashId */
splashid
);
@@ -962,6 +977,32 @@ void mxit_send_splashclick( struct MXitSession* session, const char* splashid )
/*------------------------------------------------------------------------
+ * Send a message event packet.
+ *
+ * @param session The MXit session object
+ * @param to The username of the original sender (ie, recipient of the event)
+ * @param id The identifier of the event (received in message)
+ * @param event Identified the type of event
+ */
+void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event)
+{
+ char data[CP_MAX_PACKET];
+ int datalen;
+
+ 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 = snprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%i", /* "ms"=contactAddress \1 id \1 event */
+ to, CP_FLD_TERM, id, CP_FLD_TERM, event
+ );
+
+ /* queue packet for transmission */
+ mxit_queue_packet( session, data, datalen, CP_CMD_MSGEVENT );
+}
+
+
+/*------------------------------------------------------------------------
* Send packet to create a MultiMX room.
*
* @param session The MXit session object
@@ -976,7 +1017,8 @@ void mxit_send_groupchat_create( struct MXitSession* session, const char* groupn
int i;
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s%c%i", /* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%s%c%i", /* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
groupname, CP_FLD_TERM, nr_usernames
);
@@ -1005,7 +1047,8 @@ void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid
int i;
/* convert the packet to a byte stream */
- datalen = sprintf( data, "ms=%s%c%i", /* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
+ datalen = snprintf( data, sizeof( data ),
+ "ms=%s%c%i", /* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
roomid, CP_FLD_TERM, nr_usernames
);
@@ -1158,7 +1201,7 @@ void mxit_send_file_received( struct MXitSession* session, const char* fileid, s
return;
}
- set_chunk_type( chunk, CP_CHUNK_RECIEVED );
+ set_chunk_type( chunk, CP_CHUNK_RECEIVED );
set_chunk_length( chunk, size );
datalen += MXIT_CHUNK_HEADER_SIZE + size;
@@ -1257,7 +1300,7 @@ static void mxit_parse_cmd_login( struct MXitSession* session, struct record** r
const char* statusmsg;
const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_HIDENUMBER, CP_PROFILE_FULLNAME,
CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL,
- CP_PROFILE_MOBILENR };
+ CP_PROFILE_MOBILENR, CP_PROFILE_FLAGS };
purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
@@ -1266,6 +1309,19 @@ static void mxit_parse_cmd_login( struct MXitSession* session, struct record** r
purple_connection_update_progress( session->con, _( "Successfully Logged In..." ), 3, 4 );
purple_connection_set_state( session->con, PURPLE_CONNECTED );
+ /* save extra info if this is a HTTP connection */
+ if ( session->http ) {
+ /* save the http server to use for this session */
+ g_strlcpy( session->http_server, records[1]->fields[3]->data, sizeof( session->http_server ) );
+
+ /* save the session id */
+ session->http_sesid = atoi( records[0]->fields[0]->data );
+ }
+
+ /* extract MXitId (from protocol 5.9) */
+ if ( records[1]->fcount >= 9 )
+ session->uid = g_strdup( records[1]->fields[8]->data );
+
/* display the current splash-screen */
if ( splash_popup_enabled( session ) )
splash_display( session );
@@ -1290,15 +1346,6 @@ static void mxit_parse_cmd_login( struct MXitSession* session, struct record** r
g_free( statusmsg2 );
}
- /* save extra info if this is a HTTP connection */
- if ( session->http ) {
- /* save the http server to use for this session */
- g_strlcpy( session->http_server, records[1]->fields[3]->data, sizeof( session->http_server ) );
-
- /* save the session id */
- session->http_sesid = atoi( records[0]->fields[0]->data );
- }
-
/* retrieve our MXit profile */
mxit_send_extprofile_request( session, NULL, ARRAY_SIZE( profilelist ), profilelist );
}
@@ -1355,6 +1402,12 @@ static void mxit_parse_cmd_message( struct MXitSession* session, struct record**
return;
}
+ if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) {
+ /* delivery notification is requested */
+ if ( records[0]->fcount >= 4 )
+ mxit_send_msgevent( session, records[0]->fields[0]->data, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
+ }
+
/* create and initialise new markup struct */
mx = g_new0( struct RXMsgData, 1 );
mx->msg = g_string_sized_new( msglen );
@@ -1419,9 +1472,9 @@ static void mxit_parse_cmd_new_sub( struct MXitSession* session, struct record**
/* build up a new contact info struct */
contact = g_new0( struct contact, 1 );
- strcpy( contact->username, rec->fields[0]->data );
+ g_strlcpy( contact->username, rec->fields[0]->data, sizeof( contact->username ) );
mxit_strip_domain( contact->username ); /* remove dummy domain */
- strcpy( contact->alias, rec->fields[1]->data );
+ g_strlcpy( contact->alias, rec->fields[1]->data, sizeof( contact->alias ) );
contact->type = atoi( rec->fields[2]->data );
if ( rec->fcount >= 5 ) {
@@ -1472,20 +1525,24 @@ static void mxit_parse_cmd_contact( struct MXitSession* session, struct record**
/* build up a new contact info struct */
contact = g_new0( struct contact, 1 );
- strcpy( contact->groupname, rec->fields[0]->data );
- strcpy( contact->username, rec->fields[1]->data );
+ g_strlcpy( contact->groupname, rec->fields[0]->data, sizeof( contact->groupname ) );
+ g_strlcpy( contact->username, rec->fields[1]->data, sizeof( contact->username ) );
mxit_strip_domain( contact->username ); /* remove dummy domain */
- strcpy( contact->alias, rec->fields[2]->data );
+ g_strlcpy( contact->alias, rec->fields[2]->data, sizeof( contact->alias ) );
contact->presence = atoi( rec->fields[3]->data );
contact->type = atoi( rec->fields[4]->data );
contact->mood = atoi( rec->fields[5]->data );
if ( rec->fcount > 6 ) {
- /* added in protocol 5.9.0 - flags & subtype */
+ /* added in protocol 5.9 - flags & subtype */
contact->flags = atoi( rec->fields[6]->data );
contact->subtype = rec->fields[7]->data[0];
}
+ if ( rec->fcount > 8 ) {
+ /* added in protocol 6.0 - reject message */
+ contact->msg = g_strdup( rec->fields[8]->data );
+ }
/* add the contact to the buddy list */
if ( contact-> type == MXIT_TYPE_MULTIMX ) /* contact is a MultiMX room */
@@ -1525,12 +1582,13 @@ static void mxit_parse_cmd_presence( struct MXitSession* session, struct record*
/*
* The format of the record is:
- * contactAddressN\1presenceN\1\moodN\1customMoodN\1statusMsgN\1avatarIdN
+ * contactAddressN\1presenceN\1moodN\1customMoodN\1statusMsgN\1avatarIdN
*/
mxit_strip_domain( rec->fields[0]->data ); /* contactAddress */
mxit_update_buddy_presence( session, rec->fields[0]->data, atoi( rec->fields[1]->data ), atoi( rec->fields[2]->data ),
- rec->fields[3]->data, rec->fields[4]->data, rec->fields[5]->data );
+ rec->fields[3]->data, rec->fields[4]->data );
+ mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data );
}
}
@@ -1548,10 +1606,21 @@ static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct recor
struct MXitProfile* profile = NULL;
int count;
int i;
+ const char* avatarId = NULL;
+ const char* statusMsg = NULL;
purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_extprofile: profile for '%s'\n", mxitId );
- profile = g_new0( struct MXitProfile, 1 );
+ if ( ( records[0]->fields[0]->len == 0 ) || ( session->uid && ( strcmp( session->uid, records[0]->fields[0]->data ) == 0 ) ) ) {
+ /* No UserId or Our UserId provided, so this must be our own profile information */
+ if ( session->profile == NULL )
+ session->profile = g_new0( struct MXitProfile, 1 );
+ profile = session->profile;
+ }
+ else {
+ /* is a buddy's profile */
+ profile = g_new0( struct MXitProfile, 1 );
+ }
/* set the count for attributes */
count = atoi( records[0]->fields[1]->data );
@@ -1593,8 +1662,13 @@ static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct recor
/* nickname */
g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
}
+ else if ( strcmp( CP_PROFILE_STATUS, fname ) == 0 ) {
+ /* status message - just keep a reference to the value */
+ statusMsg = fvalue;
+ }
else if ( strcmp( CP_PROFILE_AVATAR, fname ) == 0 ) {
- /* avatar id, we just ingore it cause we dont need it */
+ /* avatar id - just keep a reference to the value */
+ avatarId = fvalue;
}
else if ( strcmp( CP_PROFILE_TITLE, fname ) == 0 ) {
/* title */
@@ -1616,23 +1690,31 @@ static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct recor
/* mobile number */
g_strlcpy( profile->mobilenr, fvalue, sizeof( profile->mobilenr ) );
}
+ else if ( strcmp( CP_PROFILE_REGCOUNTRY, fname ) == 0 ) {
+ /* registered country */
+ g_strlcpy( profile->regcountry, fvalue, sizeof( profile->regcountry ) );
+ }
+ else if ( strcmp( CP_PROFILE_FLAGS, fname ) == 0 ) {
+ /* profile flags */
+ profile->flags = strtoll( fvalue, NULL, 10 );
+ }
+ else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) {
+ /* last seen online */
+ profile->lastonline = strtoll( fvalue, NULL, 10 );
+ }
else {
/* invalid profile attribute */
purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname );
}
}
- if ( records[0]->fields[0]->len == 0 ) {
- /* no MXit id provided, so this must be our own profile information */
- if ( session->profile )
- g_free( session->profile );
- session->profile = profile;
- }
- else {
- /* display other user's profile */
- mxit_show_profile( session, mxitId, profile );
+ if ( profile != session->profile ) {
+ /* update avatar (if necessary) */
+ if ( avatarId )
+ mxit_update_buddy_avatar( session, mxitId, avatarId );
- /* cleanup */
+ /* if this is not our profile, just display it */
+ mxit_show_profile( session, mxitId, profile );
g_free( profile );
}
}
@@ -1752,7 +1834,7 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r
/* this is a ack for a file send. no action is required */
break;
- case CP_CHUNK_RECIEVED :
+ case CP_CHUNK_RECEIVED :
/* this is a ack for a file received. no action is required */
break;
@@ -1917,6 +1999,8 @@ static int process_success_response( struct MXitSession* session, struct rx_pack
/* profile update */
case CP_CMD_SPLASHCLICK :
/* splash-screen clickthrough */
+ case CP_CMD_MSGEVENT :
+ /* event message */
break;
default :
@@ -1962,12 +2046,12 @@ static int process_error_response( struct MXitSession* session, struct rx_packet
return 0;
}
else {
- sprintf( errmsg, _( "Login error: %s (%i)" ), errdesc, packet->errcode );
+ snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode );
purple_connection_error( session->con, errmsg );
return -1;
}
case CP_CMD_LOGOUT :
- sprintf( errmsg, _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
+ snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
return -1;
case CP_CMD_CONTACT :
@@ -2020,6 +2104,7 @@ static int process_error_response( struct MXitSession* session, struct rx_packet
mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile Error" ), _( errdesc ) );
break;
case CP_CMD_SPLASHCLICK :
+ case CP_CMD_MSGEVENT :
/* ignore error */
break;
case CP_CMD_PING :
@@ -2438,6 +2523,8 @@ void mxit_close_connection( struct MXitSession* session )
mxit_free_emoticon_cache( session );
/* free allocated memory */
+ if ( session->uid )
+ g_free( session->uid );
g_free( session->encpwd );
session->encpwd = NULL;