# HG changeset patch # User andrew.victor@mxit.com # Date 1313185294 0 # Node ID 5cb66143ae2aaa913c6540a6243d82cef44172b7 # Parent 88a1d883e65f4183fcbac443e33c7088fdab4fa1# Parent 04ff99311108efcf14318864d900708b5879ce75 propagate from branch 'im.pidgin.pidgin' (head 8f0dbb75e0842b6df34c773ceb3a62e07819c532) to branch 'im.pidgin.pidgin.mxit' (head 58ce8d40af953c67a284a42e026ccdbfd25ffaa8) diff -r 04ff99311108 -r 5cb66143ae2a libpurple/protocols/mxit/cipher.c --- a/libpurple/protocols/mxit/cipher.c Thu Aug 11 18:31:02 2011 +0000 +++ b/libpurple/protocols/mxit/cipher.c Fri Aug 12 21:41:34 2011 +0000 @@ -34,6 +34,7 @@ /* password encryption */ #define INITIAL_KEY "6170383452343567" #define SECRET_HEADER "" +#define ENCRYPT_HEADER "" /*------------------------------------------------------------------------ @@ -106,3 +107,62 @@ return base64; } + +/*------------------------------------------------------------------------ + * Decrypt a transport-layer encryptede message. + * + * @param session The MXit session object + * @param message The encrypted message data. + * @return The decrypted message. Must be g_free'd when no longer needed. + */ +char* mxit_decrypt_message( struct MXitSession* session, char* message ) +{ + gsize raw_len; + guchar* raw_message; + char key[64]; + int pwdlen = strlen( session->acc->password ); + char exkey[512]; + int i; + GString* decoded = NULL; + + /* remove optional header: */ + if ( strncmp( message, ENCRYPT_HEADER, strlen( ENCRYPT_HEADER ) ) == 0 ) + message += strlen( ENCRYPT_HEADER ); + + /* base64 decode the message */ + raw_message = purple_base64_decode( message, &raw_len ); + + /* build the key - Client key, appended with last 8 characters of the PIN. (no padding) */ + memset( key, 0x00, sizeof( key ) ); + memcpy( key, session->clientkey, strlen( session->clientkey ) ); + if ( pwdlen <= 8 ) + strcat( key, session->acc->password ); + else + strncat( key, session->acc->password + ( pwdlen - 8 ), 8 ); + ExpandKey( (unsigned char*) key, (unsigned char*) exkey ); + + /* decode each block */ + decoded = g_string_sized_new( raw_len ); + for ( i = 0; i < raw_len; i += 16 ) { + char block[16]; + + Decrypt( (unsigned char*) raw_message + i, (unsigned char*) exkey, (unsigned char*) block ); + g_string_append_len( decoded, block, 16 ); + } + + g_free( raw_message ); + + purple_debug_info( MXIT_PLUGIN_ID, "decrypted: '%s'\n", decoded->str ); + + /* check that the decrypted message starts with header: */ + if ( strncmp( decoded->str, SECRET_HEADER, strlen( SECRET_HEADER ) != 0 ) ) { + g_string_free( decoded, TRUE ); + return NULL; /* message could not be decoded */ + } + g_string_erase( decoded, 0, strlen( SECRET_HEADER ) ); /* remove header */ + + /* remove ISO10126 padding */ +// TODO + + return g_string_free( decoded, FALSE ); +} diff -r 04ff99311108 -r 5cb66143ae2a libpurple/protocols/mxit/cipher.h --- a/libpurple/protocols/mxit/cipher.h Thu Aug 11 18:31:02 2011 +0000 +++ b/libpurple/protocols/mxit/cipher.h Fri Aug 12 21:41:34 2011 +0000 @@ -32,5 +32,7 @@ char* mxit_encrypt_password( struct MXitSession* session ); +char* mxit_decrypt_message( struct MXitSession* session, char* message ); + #endif /* _MXIT_CIPHER_H_ */ diff -r 04ff99311108 -r 5cb66143ae2a libpurple/protocols/mxit/markup.c --- a/libpurple/protocols/mxit/markup.c Thu Aug 11 18:31:02 2011 +0000 +++ b/libpurple/protocols/mxit/markup.c Fri Aug 12 21:41:34 2011 +0000 @@ -735,6 +735,7 @@ gboolean tag_bold = FALSE; gboolean tag_under = FALSE; gboolean tag_italic = FALSE; + int font_size = 0; #ifdef MXIT_DEBUG_MARKUP purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (original): '%s'\n", message ); @@ -862,59 +863,54 @@ } break; case '.' : - if ( !( msgflags & CP_MSG_EMOTICON ) ) { - g_string_append_c( mx->msg, message[i] ); - break; - } - else if ( i + 1 >= len ) { + if ( i + 1 >= len ) { /* message too short */ g_string_append_c( mx->msg, '.' ); break; } - switch ( message[i+1] ) { - case '+' : - /* increment text size */ - g_string_append( mx->msg, "" ); - i++; - break; - case '-' : - /* decrement text size */ - g_string_append( mx->msg, "" ); - i++; - break; - case '{' : - /* custom emoticon */ - if ( i + 2 >= len ) { - /* message too short */ - g_string_append_c( mx->msg, '.' ); - break; - } + if ( ( msgflags & CP_MSG_EMOTICON ) && ( message[i+1] == '{' ) ) { + /* custom emoticon */ + if ( i + 2 >= len ) { + /* message too short */ + g_string_append_c( mx->msg, '.' ); + break; + } + + parse_emoticon_str( &message[i+2], tmpstr1 ); + if ( tmpstr1[0] != '\0' ) { + mx->got_img = TRUE; + + if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) { + /* emoticon found in the cache, so we do not have to request it from the WAPsite */ + } + else { + /* request emoticon from the WAPsite */ + mx->img_count++; + emoticon_request( mx, tmpstr1 ); + } - parse_emoticon_str( &message[i+2], tmpstr1 ); - if ( tmpstr1[0] != '\0' ) { - mx->got_img = TRUE; + g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 ); + i += strlen( tmpstr1 ) + 2; + } + else + g_string_append_c( mx->msg, '.' ); + } + else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '+' ) ) { + /* increment text size */ + font_size++; + g_string_append_printf( mx->msg, "", font_size ); + i++; + } + else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '-' ) ) { + /* decrement text size */ + font_size--; + g_string_append_printf( mx->msg, "", font_size ); + i++; + } + else + g_string_append_c( mx->msg, '.' ); - if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) { - /* emoticon found in the cache, so we do not have to request it from the WAPsite */ - } - else { - /* request emoticon from the WAPsite */ - mx->img_count++; - emoticon_request( mx, tmpstr1 ); - } - - g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 ); - i += strlen( tmpstr1 ) + 2; - } - else - g_string_append_c( mx->msg, '.' ); - - break; - default : - g_string_append_c( mx->msg, '.' ); - break; - } break; case '\\' : if ( i + 1 >= len ) { diff -r 04ff99311108 -r 5cb66143ae2a libpurple/protocols/mxit/protocol.c --- a/libpurple/protocols/mxit/protocol.c Thu Aug 11 18:31:02 2011 +0000 +++ b/libpurple/protocols/mxit/protocol.c Fri Aug 12 21:41:34 2011 +0000 @@ -1516,6 +1516,7 @@ { struct RXMsgData* mx = NULL; char* message = NULL; + char* sender = NULL; int msglen = 0; int msgflags = 0; int msgtype = 0; @@ -1529,10 +1530,11 @@ msglen = strlen( message ); /* strip off dummy domain */ - mxit_strip_domain( records[0]->fields[0]->data ); + sender = records[0]->fields[0]->data; + mxit_strip_domain( sender ); #ifdef DEBUG_PROTOCOL - purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", records[0]->fields[0]->data ); + purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender ); #endif /* decode message flags (if any) */ @@ -1540,33 +1542,42 @@ msgflags = atoi( records[0]->fields[4]->data ); msgtype = atoi( records[0]->fields[2]->data ); - if ( msgflags & CP_MSG_ENCRYPTED ) { - /* this is an encrypted message. we do not currently support those so ignore it */ + if ( msgflags & CP_MSG_PWD_ENCRYPTED ) { + /* this is a password encrypted message. we do not currently support those so ignore it */ PurpleBuddy* buddy; const char* name; char msg[128]; - buddy = purple_find_buddy( session->acc, records[0]->fields[0]->data ); + buddy = purple_find_buddy( session->acc, sender ); if ( buddy ) name = purple_buddy_get_alias( buddy ); else - name = records[0]->fields[0]->data; + name = sender; g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name ); mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg ); return; } + else if ( msgflags & CP_MSG_TL_ENCRYPTED ) { + /* this is a transport-layer encrypted message. */ + message = mxit_decrypt_message( session, message ); + if ( !message ) { + /* could not be decrypted */ + serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) ); + 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 ); + mxit_send_msgevent( session, sender, 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 ); mx->session = session; - mx->from = g_strdup( records[0]->fields[0]->data ); + mx->from = g_strdup( sender ); mx->timestamp = atoi( records[0]->fields[1]->data ); mx->got_img = FALSE; mx->chatid = -1; @@ -1597,6 +1608,10 @@ * so the image received callback function will eventually display * the message. */ } + + /* cleanup */ + if ( msgflags & CP_MSG_TL_ENCRYPTED ) + g_free( message ); } diff -r 04ff99311108 -r 5cb66143ae2a libpurple/protocols/mxit/protocol.h --- a/libpurple/protocols/mxit/protocol.h Thu Aug 11 18:31:02 2011 +0000 +++ b/libpurple/protocols/mxit/protocol.h Fri Aug 12 21:41:34 2011 +0000 @@ -155,7 +155,10 @@ /* message flags */ #define CP_MSG_NOTIFY_DELIVERY 0x0002 /* request delivery notification */ #define CP_MSG_NOTIFY_READ 0x0004 /* request read notification */ -#define CP_MSG_ENCRYPTED 0x0010 /* message is encrypted */ +#define CP_MSG_PWD_ENCRYPTED 0x0010 /* message is password encrypted */ +#define CP_MSG_TL_ENCRYPTED 0x0020 /* message is transport encrypted */ +#define CP_MSG_RPLY_PWD_ENCRYPT 0x0040 /* reply should be password encrypted */ +#define CP_MSG_RPLY_TL_ENCRYPT 0x0080 /* reply should be transport encrypted */ #define CP_MSG_MARKUP 0x0200 /* message may contain markup */ #define CP_MSG_EMOTICON 0x0400 /* message may contain custom emoticons */ diff -r 04ff99311108 -r 5cb66143ae2a libpurple/protocols/mxit/roster.h --- a/libpurple/protocols/mxit/roster.h Thu Aug 11 18:31:02 2011 +0000 +++ b/libpurple/protocols/mxit/roster.h Fri Aug 12 21:41:34 2011 +0000 @@ -96,7 +96,7 @@ /* client protocol constants */ #define MXIT_CP_MAX_JID_LEN 64 #define MXIT_CP_MAX_GROUP_LEN 32 -#define MXIT_CP_MAX_ALIAS_LEN 48 +#define MXIT_CP_MAX_ALIAS_LEN 100 #define MXIT_DEFAULT_GROUP "MXit" @@ -106,8 +106,8 @@ */ struct contact { char username[MXIT_CP_MAX_JID_LEN+1]; /* unique contact name (with domain) */ - char alias[MXIT_CP_MAX_GROUP_LEN+1]; /* contact alias (what will be seen) */ - char groupname[MXIT_CP_MAX_ALIAS_LEN+1]; /* contact group name */ + char alias[MXIT_CP_MAX_ALIAS_LEN+1]; /* contact alias (what will be seen) */ + char groupname[MXIT_CP_MAX_GROUP_LEN+1]; /* contact group name */ short type; /* contact type */ short mood; /* contact current mood */