aboutsummaryrefslogtreecommitdiffstats
path: root/protocols
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2010-08-12 23:13:26 +0100
committerWilmer van der Gaast <wilmer@gaast.net>2010-08-12 23:13:26 +0100
commitca7de3ac72f0ef10613badecb7eb6cc9a10f996b (patch)
tree2e00a3c8cf3a1f60f2a2c24614e7387d1759239b /protocols
parent7f34ce254c1a1587e5560456dd11acb29345206d (diff)
Successful login (including contact list sync). \o/
Diffstat (limited to 'protocols')
-rw-r--r--protocols/msn/msn.c8
-rw-r--r--protocols/msn/msn.h5
-rw-r--r--protocols/msn/msn_util.c12
-rw-r--r--protocols/msn/ns.c200
-rw-r--r--protocols/msn/soap.c1
5 files changed, 125 insertions, 101 deletions
diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c
index 0b9cffc2..4de2d822 100644
--- a/protocols/msn/msn.c
+++ b/protocols/msn/msn.c
@@ -67,6 +67,7 @@ static void msn_login( account_t *acc )
md->ic = ic;
md->away_state = msn_away_state_list;
+ md->domaintree = g_tree_new( msn_domaintree_cmp );
msn_connections = g_slist_append( msn_connections, ic );
}
@@ -106,6 +107,9 @@ static void msn_logout( struct im_connection *ic )
g_free( md->tokens[1] );
g_free( md->lock_key );
+ g_tree_destroy( md->domaintree );
+ md->domaintree = NULL;
+
while( md->grpq )
{
struct msn_groupadd *ga = md->grpq->data;
@@ -335,11 +339,15 @@ static char *set_eval_display_name( set_t *set, char *value )
static void msn_buddy_data_add( bee_user_t *bu )
{
+ struct msn_data *md = bu->ic->proto_data;
bu->data = g_new0( struct msn_buddy_data, 1 );
+ g_tree_insert( md->domaintree, bu->handle, bu );
}
static void msn_buddy_data_free( bee_user_t *bu )
{
+ struct msn_data *md = bu->ic->proto_data;
+ g_tree_remove( md->domaintree, bu->handle );
g_free( bu->data );
}
diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h
index 757359fe..6e447d7f 100644
--- a/protocols/msn/msn.h
+++ b/protocols/msn/msn.h
@@ -88,6 +88,7 @@ struct msn_data
int buddycount;
int groupcount;
char **grouplist;
+ GTree *domaintree;
};
struct msn_switchboard
@@ -152,7 +153,7 @@ struct msn_handler_data
typedef enum
{
- MSN_BUDDY_FL = 1,
+ MSN_BUDDY_FL = 1, /* Warning: FL,AL,BL *must* be 1,2,4. */
MSN_BUDDY_AL = 2,
MSN_BUDDY_BL = 4,
MSN_BUDDY_RL = 8,
@@ -186,6 +187,7 @@ extern GSList *msn_switchboards;
/* ns.c */
gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );
void msn_auth_got_passport_token( struct im_connection *ic, char *token );
+void msn_auth_got_contact_list( struct im_connection *ic );
/* msn_util.c */
int msn_write( struct im_connection *ic, char *s, int len );
@@ -200,6 +202,7 @@ char *msn_http_encode( const char *input );
void msn_msgq_purge( struct im_connection *ic, GSList **list );
gboolean msn_set_display_name( struct im_connection *ic, const char *rawname );
char *msn_p11_challenge( char *challenge );
+gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ );
/* tables.c */
const struct msn_away_state *msn_away_state_by_number( int number );
diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c
index 65b12476..3a19d92f 100644
--- a/protocols/msn/msn_util.c
+++ b/protocols/msn/msn_util.c
@@ -527,3 +527,15 @@ char *msn_p11_challenge( char *challenge )
return output;
}
+
+gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ )
+{
+ const char *a = a_, *b = b_;
+ gint ret;
+
+ if( !( a = strchr( a, '@' ) ) || !( b = strchr( b, '@' ) ) ||
+ ( ret = strcmp( a, b ) ) == 0 )
+ ret = strcmp( a_, b_ );
+
+ return ret;
+}
diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c
index f0d6a58d..ffb21c47 100644
--- a/protocols/msn/ns.c
+++ b/protocols/msn/ns.c
@@ -26,15 +26,16 @@
#include <ctype.h>
#include "nogaim.h"
#include "msn.h"
-#include "passport.h"
#include "md5.h"
#include "soap.h"
+#include "xmltree.h"
static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond );
static int msn_ns_command( gpointer data, char **cmd, int num_parts );
static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name );
+static void msn_ns_send_adl( struct im_connection *ic );
gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
{
@@ -134,7 +135,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
char *server;
int port;
- if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 )
+ if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 )
{
b_event_remove( ic->inpa );
ic->inpa = 0;
@@ -155,7 +156,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
md->fd = proxy_connect( server, port, msn_ns_connected, ic );
}
- else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 )
+ else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 )
{
struct msn_switchboard *sb;
@@ -260,109 +261,34 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
return( 0 );
}
}
- else if( strcmp( cmd[0], "SYN" ) == 0 )
+ else if( strcmp( cmd[0], "BLP" ) == 0 )
{
- if( num_parts == 5 )
- {
- int i, groupcount;
-
- groupcount = atoi( cmd[4] );
- if( groupcount > 0 )
- {
- /* valgrind says this is leaking memory, I'm guessing
- that this happens during server redirects. */
- if( md->grouplist )
- {
- for( i = 0; i < md->groupcount; i ++ )
- g_free( md->grouplist[i] );
- g_free( md->grouplist );
- }
-
- md->groupcount = groupcount;
- md->grouplist = g_new0( char *, md->groupcount );
- }
-
- md->buddycount = atoi( cmd[3] );
- if( !*cmd[3] || md->buddycount == 0 )
- msn_logged_in( ic );
- }
- else
- {
- /* Hrrm... This SYN reply doesn't really look like something we expected.
- Let's assume everything is okay. */
-
- msn_logged_in( ic );
- }
+ msn_ns_send_adl( ic );
}
- else if( strcmp( cmd[0], "LST" ) == 0 )
+ else if( strcmp( cmd[0], "ADL" ) == 0 )
{
- int list;
-
- if( num_parts != 4 && num_parts != 5 )
- {
- imcb_error( ic, "Syntax error" );
- imc_logout( ic, TRUE );
- return( 0 );
- }
-
- http_decode( cmd[2] );
- list = atoi( cmd[3] );
-
- if( list & 1 ) /* FL */
+ if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 )
{
- char *group = NULL;
- int num;
+ char buf[1024];
+ char *fn_raw = set_getstr( &ic->acc->set, "display_name" );
+ char *fn;
- if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 && num < md->groupcount )
- group = md->grouplist[num];
+ if( fn_raw == NULL )
+ fn_raw = ic->acc->user;
+ fn = g_malloc( strlen( fn_raw ) * 3 + 1 );
+ strcpy( fn, fn_raw );
+ http_encode( fn );
- imcb_add_buddy( ic, cmd[1], group );
- imcb_rename_buddy( ic, cmd[1], cmd[2] );
- }
- if( list & 2 ) /* AL */
- {
- ic->permit = g_slist_append( ic->permit, g_strdup( cmd[1] ) );
- }
- if( list & 4 ) /* BL */
- {
- ic->deny = g_slist_append( ic->deny, g_strdup( cmd[1] ) );
- }
- if( list & 8 ) /* RL */
- {
- if( ( list & 6 ) == 0 )
- msn_buddy_ask( ic, cmd[1], cmd[2] );
- }
-
- if( --md->buddycount == 0 )
- {
- if( ic->flags & OPT_LOGGED_IN )
- {
- imcb_log( ic, "Successfully transferred to different server" );
- g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 );
- return( msn_write( ic, buf, strlen( buf ) ) );
- }
- else
- {
- msn_logged_in( ic );
- }
+ g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n",
+ ++md->trId, fn );
+ g_free( fn );
+
+ msn_write( ic, buf, strlen( buf ) );
}
}
- else if( strcmp( cmd[0], "LSG" ) == 0 )
+ else if( strcmp( cmd[0], "PRP" ) == 0 )
{
- int num;
-
- if( num_parts != 4 )
- {
- imcb_error( ic, "Syntax error" );
- imc_logout( ic, TRUE );
- return( 0 );
- }
-
- http_decode( cmd[2] );
- num = atoi( cmd[1] );
-
- if( num < md->groupcount )
- md->grouplist[num] = g_strdup( cmd[2] );
+ imcb_connected( ic );
}
else if( strcmp( cmd[0], "CHL" ) == 0 )
{
@@ -392,15 +318,15 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
{
const struct msn_away_state *st;
- if( num_parts != 6 )
+ if( num_parts < 6 )
{
imcb_error( ic, "Syntax error" );
imc_logout( ic, TRUE );
return( 0 );
}
- http_decode( cmd[4] );
- imcb_rename_buddy( ic, cmd[3], cmd[4] );
+ http_decode( cmd[5] );
+ imcb_rename_buddy( ic, cmd[3], cmd[5] );
st = msn_away_state_by_code( cmd[2] );
if( !st )
@@ -786,6 +712,80 @@ void msn_auth_got_passport_token( struct im_connection *ic, char *token )
}
}
+void msn_auth_got_contact_list( struct im_connection *ic )
+{
+ char buf[64];
+ struct msn_data *md;
+
+ /* Dead connection? */
+ if( g_slist_find( msn_connections, ic ) == NULL )
+ return;
+
+ md = ic->proto_data;
+
+
+ g_snprintf( buf, sizeof( buf ), "BLP %d %s\r\n", ++md->trId, "BL" );
+ msn_write( ic, buf, strlen( buf ) );
+}
+
+static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data )
+{
+ struct xt_node *adl = data, *d, *c;
+ struct bee_user *bu = value;
+ struct msn_buddy_data *bd = bu->data;
+ char handle[strlen(bu->handle)];
+ char *domain;
+ char l[4];
+
+ strcpy( handle, bu->handle );
+ if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */
+ return FALSE;
+ *domain = '\0';
+ domain ++;
+
+ if( ( d = adl->children ) == NULL ||
+ g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 )
+ {
+ d = xt_new_node( "d", NULL, NULL );
+ xt_add_attr( d, "n", domain );
+ xt_insert_child( adl, d );
+ }
+
+ g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 );
+ c = xt_new_node( "c", NULL, NULL );
+ xt_add_attr( c, "n", handle );
+ xt_add_attr( c, "l", l );
+ xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */
+ xt_insert_child( d, c );
+
+ return FALSE;
+}
+
+static void msn_ns_send_adl( struct im_connection *ic )
+{
+ struct xt_node *adl;
+ struct msn_data *md;
+ char *adls, buf[64];
+
+ /* Dead connection? */
+ if( g_slist_find( msn_connections, ic ) == NULL )
+ return;
+
+ md = ic->proto_data;
+
+ adl = xt_new_node( "ml", NULL, NULL );
+ xt_add_attr( adl, "l", "1" );
+ g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl );
+ adls = xt_to_string( adl );
+
+ g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n", ++md->trId, strlen( adls ) );
+ if( msn_write( ic, buf, strlen( buf ) ) )
+ msn_write( ic, adls, strlen( adls ) );
+
+ g_free( adls );
+ xt_free_node( adl );
+}
+
static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name )
{
set_t *s;
diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c
index 62d58200..bb664861 100644
--- a/protocols/msn/soap.c
+++ b/protocols/msn/soap.c
@@ -577,6 +577,7 @@ static const struct xt_handler_entry msn_soap_addressbook_parser[] = {
static int msn_soap_addressbook_handle_response( struct msn_soap_req_data *soap_req )
{
+ msn_auth_got_contact_list( soap_req->ic );
return MSN_SOAP_OK;
}