diff options
Diffstat (limited to 'protocols')
| -rw-r--r-- | protocols/jabber/Makefile | 2 | ||||
| -rw-r--r-- | protocols/jabber/io.c | 12 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 55 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 6 | ||||
| -rw-r--r-- | protocols/jabber/jabber_util.c | 67 | ||||
| -rw-r--r-- | protocols/jabber/message.c | 17 | ||||
| -rw-r--r-- | protocols/jabber/xmltree.c | 589 | ||||
| -rw-r--r-- | protocols/jabber/xmltree.h | 97 | ||||
| -rw-r--r-- | protocols/msn/msn.h | 2 | ||||
| -rw-r--r-- | protocols/msn/msn_util.c | 8 | ||||
| -rw-r--r-- | protocols/msn/ns.c | 77 | ||||
| -rw-r--r-- | protocols/msn/passport.c | 280 | ||||
| -rw-r--r-- | protocols/msn/passport.h | 93 | ||||
| -rw-r--r-- | protocols/nogaim.c | 17 | ||||
| -rw-r--r-- | protocols/nogaim.h | 8 | ||||
| -rw-r--r-- | protocols/oscar/oscar.c | 98 | ||||
| -rw-r--r-- | protocols/yahoo/libyahoo2.c | 17 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo.c | 19 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo_httplib.c | 2 | 
19 files changed, 459 insertions, 1007 deletions
| diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index 3ce78127..e7a505ba 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -9,7 +9,7 @@  -include ../../Makefile.settings  # [SH] Program variables -objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o +objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o  CFLAGS += -Wall  LFLAGS += -r diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 86c216ef..10efad37 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -240,8 +240,13 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition  		return FALSE;  	} -	/* EAGAIN/etc or a successful read. */ -	return TRUE; +	if( ssl_pending( jd->ssl ) ) +		/* OpenSSL empties the TCP buffers completely but may keep some +		   data in its internap buffers. select() won't see that, but +		   ssl_pending() does. */ +		return jabber_read_callback( data, fd, cond ); +	else +		return TRUE;  }  gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ) @@ -520,8 +525,7 @@ gboolean jabber_start_stream( struct im_connection *ic )  	/* We'll start our stream now, so prepare everything to receive one  	   from the server too. */  	xt_free( jd->xt );	/* In case we're RE-starting. */ -	jd->xt = xt_new( ic ); -	jd->xt->handlers = (struct xt_handler_entry*) jabber_handlers; +	jd->xt = xt_new( jabber_handlers, ic );  	if( jd->r_inpa <= 0 )  		jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic ); diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index dac18bae..5fb2c4fc 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -32,15 +32,33 @@  #include "bitlbee.h"  #include "jabber.h"  #include "md5.h" -#include "base64.h"  GSList *jabber_connections; +/* First enty is the default */ +static const int jabber_port_list[] = { +	5222, +	5223, +	5220, +	5221, +	5224, +	5225, +	5226, +	5227, +	5228, +	5229, +	80, +	443, +	0 +}; +  static void jabber_init( account_t *acc )  {  	set_t *s; +	char str[16]; -	s = set_add( &acc->set, "port", JABBER_PORT_DEFAULT, set_eval_int, acc ); +	g_snprintf( str, sizeof( str ), "%d", jabber_port_list[0] ); +	s = set_add( &acc->set, "port", str, set_eval_int, acc );  	s->flags |= ACC_SET_OFFLINE_ONLY;  	s = set_add( &acc->set, "priority", "0", set_eval_priority, acc ); @@ -71,6 +89,7 @@ static void jabber_login( account_t *acc )  	struct jabber_data *jd = g_new0( struct jabber_data, 1 );  	struct ns_srv_reply *srv = NULL;  	char *connect_to, *s; +	int i;  	/* For now this is needed in the _connected() handlers if using  	   GLib event handling, to make sure we're not handling events @@ -176,11 +195,13 @@ static void jabber_login( account_t *acc )  	imcb_log( ic, "Connecting" ); -	if( set_getint( &acc->set, "port" ) < JABBER_PORT_MIN || -	    set_getint( &acc->set, "port" ) > JABBER_PORT_MAX ) +	for( i = 0; jabber_port_list[i] > 0; i ++ ) +		if( set_getint( &acc->set, "port" ) == jabber_port_list[i] ) +			break; + +	if( jabber_port_list[i] == 0 )  	{ -		imcb_log( ic, "Incorrect port number, must be in the %d-%d range", -		               JABBER_PORT_MIN, JABBER_PORT_MAX ); +		imcb_log( ic, "Illegal port number" );  		imc_logout( ic, FALSE );  		return;  	} @@ -218,24 +239,20 @@ static void jabber_login( account_t *acc )  	jabber_generate_id_hash( jd );  } +/* This generates an unfinished md5_state_t variable. Every time we generate +   an ID, we finish the state by adding a sequence number and take the hash. */  static void jabber_generate_id_hash( struct jabber_data *jd )  { -	md5_state_t id_hash; -	md5_byte_t binbuf[16]; +	md5_byte_t binbuf[4];  	char *s; -	md5_init( &id_hash ); -	md5_append( &id_hash, (unsigned char *) jd->username, strlen( jd->username ) ); -	md5_append( &id_hash, (unsigned char *) jd->server, strlen( jd->server ) ); +	md5_init( &jd->cached_id_prefix ); +	md5_append( &jd->cached_id_prefix, (unsigned char *) jd->username, strlen( jd->username ) ); +	md5_append( &jd->cached_id_prefix, (unsigned char *) jd->server, strlen( jd->server ) );  	s = set_getstr( &jd->ic->acc->set, "resource" ); -	md5_append( &id_hash, (unsigned char *) s, strlen( s ) ); -	random_bytes( binbuf, 16 ); -	md5_append( &id_hash, binbuf, 16 ); -	md5_finish( &id_hash, binbuf ); -	 -	s = base64_encode( binbuf, 9 ); -	jd->cached_id_prefix = g_strdup_printf( "%s%s", JABBER_CACHED_ID, s ); -	g_free( s ); +	md5_append( &jd->cached_id_prefix, (unsigned char *) s, strlen( s ) ); +	random_bytes( binbuf, 4 ); +	md5_append( &jd->cached_id_prefix, binbuf, 4 );  }  static void jabber_logout( struct im_connection *ic ) diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 1ff0e8dd..904bf0c4 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -85,7 +85,7 @@ struct jabber_data  	struct jabber_away_state *away_state;  	char *away_message; -	char *cached_id_prefix; +	md5_state_t cached_id_prefix;  	GHashTable *node_cache;  	GHashTable *buddies;  }; @@ -134,10 +134,6 @@ struct jabber_chat  #define JABBER_XMLCONSOLE_HANDLE "xmlconsole" -#define JABBER_PORT_DEFAULT "5222" -#define JABBER_PORT_MIN 5220 -#define JABBER_PORT_MAX 5229 -  /* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the     first one should be used, but when storing a packet in the cache, a     "special" kind of ID is assigned to make it easier later to figure out diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 6e872040..1bee5009 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -22,6 +22,8 @@  \***************************************************************************/  #include "jabber.h" +#include "md5.h" +#include "base64.h"  static unsigned int next_id = 1; @@ -133,11 +135,21 @@ void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_ca  {  	struct jabber_data *jd = ic->proto_data;  	struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 ); -	char *id; +	md5_state_t id_hash; +	md5_byte_t id_sum[16]; +	char *id, *asc_hash; -	id = g_strdup_printf( "%s%05x", jd->cached_id_prefix, ( next_id++ ) & 0xfffff ); +	next_id ++; +	 +	id_hash = jd->cached_id_prefix; +	md5_append( &id_hash, (md5_byte_t*) &next_id, sizeof( next_id ) ); +	md5_finish( &id_hash, id_sum ); +	asc_hash = base64_encode( id_sum, 12 ); +	 +	id = g_strdup_printf( "%s%s", JABBER_CACHED_ID, asc_hash );  	xt_add_attr( node, "id", id );  	g_free( id ); +	g_free( asc_hash );  	entry->node = node;  	entry->func = func; @@ -183,7 +195,7 @@ xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *  	char *s;  	if( ( s = xt_find_attr( node, "id" ) ) == NULL || -	    strncmp( s, jd->cached_id_prefix, strlen( jd->cached_id_prefix ) ) != 0 ) +	    strncmp( s, JABBER_CACHED_ID, strlen( JABBER_CACHED_ID ) ) != 0 )  	{  		/* Silently ignore it, without an ID (or a non-cache  		   ID) we don't know how to handle the packet and we @@ -195,8 +207,14 @@ xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *  	if( entry == NULL )  	{ +		/* +		There's no longer an easy way to see if we generated this +		one or someone else, and there's a ten-minute timeout anyway, +		so meh. +		  		imcb_log( ic, "Warning: Received %s-%s packet with unknown/expired ID %s!",  		              node->name, xt_find_attr( node, "type" ) ? : "(no type)", s ); +		*/  	}  	else if( entry->func )  	{ @@ -245,8 +263,10 @@ struct jabber_buddy_ask_data  	char *realname;  }; -static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla ) +static void jabber_buddy_ask_yes( void *data )  { +	struct jabber_buddy_ask_data *bla = data; +	  	presence_send_request( bla->ic, bla->handle, "subscribed" );  	if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) @@ -256,8 +276,10 @@ static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla  	g_free( bla );  } -static void jabber_buddy_ask_no( gpointer w, struct jabber_buddy_ask_data *bla ) +static void jabber_buddy_ask_no( void *data )  { +	struct jabber_buddy_ask_data *bla = data; +	  	presence_send_request( bla->ic, bla->handle, "subscribed" );  	g_free( bla->handle ); @@ -285,8 +307,13 @@ char *jabber_normalize( const char *orig )  	len = strlen( orig );  	new = g_new( char, len + 1 ); -	for( i = 0; i < len; i ++ ) +	 +	/* So it turns out the /resource part is case sensitive. Yeah, and +	   it's Unicode but feck Unicode. :-P So stop once we see a slash. */ +	for( i = 0; i < len && orig[i] != '/' ; i ++ )  		new[i] = tolower( orig[i] ); +	for( ; orig[i]; i ++ ) +		new[i] = orig[i];  	new[i] = 0;  	return new; @@ -329,7 +356,7 @@ struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_  		for( bi = bud; bi; bi = bi->next )  		{  			/* Check for dupes. */ -			if( g_strcasecmp( bi->resource, s + 1 ) == 0 ) +			if( strcmp( bi->resource, s + 1 ) == 0 )  			{  				*s = '/';  				g_free( new ); @@ -382,7 +409,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,  	if( ( s = strchr( jid, '/' ) ) )  	{ -		int none_found = 0; +		int bare_exists = 0;  		*s = 0;  		if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) @@ -405,21 +432,19 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,  			/* See if there's an exact match. */  			for( ; bud; bud = bud->next ) -				if( g_strcasecmp( bud->resource, s + 1 ) == 0 ) +				if( strcmp( bud->resource, s + 1 ) == 0 )  					break;  		}  		else  		{ -			/* This hack is there to make sure that O_CREAT will -			   work if there's already another resouce present -			   for this JID, even if it's an unknown buddy. This -			   is done to handle conferences properly. */ -			none_found = 1; -			/* TODO(wilmer): Find out what I was thinking when I -			   wrote this??? And then fix it. This makes me sad... */ +			/* This variable tells the if down here that the bare +			   JID already exists and we should feel free to add +			   more resources, if the caller asked for that. */ +			bare_exists = 1;  		} -		if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && ( imcb_find_buddy( ic, jid ) || !none_found ) ) +		if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && +		    ( !bare_exists || imcb_find_buddy( ic, jid ) ) )  		{  			*s = '/';  			bud = jabber_buddy_add( ic, jid ); @@ -444,7 +469,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,  		else if( bud->resource && ( flags & GET_BUDDY_EXACT ) )  			/* We want an exact match, so in thise case there shouldn't be a /resource. */  			return NULL; -		else if( ( bud->resource == NULL || bud->next == NULL ) ) +		else if( bud->resource == NULL || bud->next == NULL )  			/* No need for selection if there's only one option. */  			return bud;  		else if( flags & GET_BUDDY_FIRST ) @@ -520,7 +545,9 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ )  		/* If there's only one item in the list (and if the resource  		   matches), removing it is simple. (And the hash reference  		   should be removed too!) */ -		if( bud->next == NULL && ( ( s == NULL || bud->resource == NULL ) || g_strcasecmp( bud->resource, s + 1 ) == 0 ) ) +		if( bud->next == NULL && +		    ( ( s == NULL && bud->resource == NULL ) || +		      ( bud->resource && s && strcmp( bud->resource, s + 1 ) == 0 ) ) )  		{  			g_hash_table_remove( jd->buddies, bud->bare_jid );  			g_free( bud->bare_jid ); @@ -543,7 +570,7 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ )  		else  		{  			for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next ) -				if( g_strcasecmp( bi->resource, s + 1 ) == 0 ) +				if( strcmp( bi->resource, s + 1 ) == 0 )  					break;  			g_free( full_jid ); diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index fab62a91..6cb67d42 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -48,6 +48,23 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )  	else /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */  	{  		GString *fullmsg = g_string_new( "" ); + +		for( c = node->children; ( c = xt_find_node( c, "x" ) ); c = c->next ) +		{ +			char *ns = xt_find_attr( c, "xmlns" ), *room; +			struct xt_node *inv, *reason; +			 +			if( strcmp( ns, XMLNS_MUC_USER ) == 0 && +			    ( inv = xt_find_node( c->children, "invite" ) ) ) +			{ +				room = from; +				from = xt_find_attr( inv, "from" ) ? : from; + +				g_string_append_printf( fullmsg, "<< \002BitlBee\002 - Invitation to chatroom %s >>\n", room ); +				if( ( reason = xt_find_node( inv->children, "reason" ) ) && reason->text_len > 0 ) +					g_string_append( fullmsg, reason->text ); +			} +		}  		if( ( s = strchr( from, '/' ) ) )  		{ diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c deleted file mode 100644 index 62549eb5..00000000 --- a/protocols/jabber/xmltree.c +++ /dev/null @@ -1,589 +0,0 @@ -/***************************************************************************\ -*                                                                           * -*  BitlBee - An IRC to IM gateway                                           * -*  Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly)       * -*                                                                           * -*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   * -*                                                                           * -*  This library is free software; you can redistribute it and/or            * -*  modify it under the terms of the GNU Lesser General Public               * -*  License as published by the Free Software Foundation, version            * -*  2.1.                                                                     * -*                                                                           * -*  This library is distributed in the hope that it will be useful,          * -*  but WITHOUT ANY WARRANTY; without even the implied warranty of           * -*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        * -*  Lesser General Public License for more details.                          * -*                                                                           * -*  You should have received a copy of the GNU Lesser General Public License * -*  along with this library; if not, write to the Free Software Foundation,  * -*  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA           * -*                                                                           * -****************************************************************************/ - -#include <glib.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> -#include <stdio.h> - -#include "xmltree.h" - -static void xt_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error ) -{ -	struct xt_parser *xt = data; -	struct xt_node *node = g_new0( struct xt_node, 1 ), *nt; -	int i; -	 -	node->parent = xt->cur; -	node->name = g_strdup( element_name ); -	 -	/* First count the number of attributes */ -	for( i = 0; attr_names[i]; i ++ ); -	 -	/* Then allocate a NULL-terminated array. */ -	node->attr = g_new0( struct xt_attr, i + 1 ); -	 -	/* And fill it, saving one variable by starting at the end. */ -	for( i --; i >= 0; i -- ) -	{ -		node->attr[i].key = g_strdup( attr_names[i] ); -		node->attr[i].value = g_strdup( attr_values[i] ); -	} -	 -	/* Add it to the linked list of children nodes, if we have a current -	   node yet. */ -	if( xt->cur ) -	{ -		if( xt->cur->children ) -		{ -			for( nt = xt->cur->children; nt->next; nt = nt->next ); -			nt->next = node; -		} -		else -		{ -			xt->cur->children = node; -		} -	} -	else if( xt->root ) -	{ -		/* ERROR situation: A second root-element??? */ -	} -	 -	/* Now this node will be the new current node. */ -	xt->cur = node; -	/* And maybe this is the root? */ -	if( xt->root == NULL ) -		xt->root = node; -} - -static void xt_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error ) -{ -	struct xt_parser *xt = data; -	struct xt_node *node = xt->cur; -	 -	if( node == NULL ) -		return; -	 -	/* FIXME: Does g_renew also OFFICIALLY accept NULL arguments? */ -	node->text = g_renew( char, node->text, node->text_len + text_len + 1 ); -	memcpy( node->text + node->text_len, text, text_len ); -	node->text_len += text_len; -	/* Zero termination is always nice to have. */ -	node->text[node->text_len] = 0; -} - -static void xt_end_element( GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error ) -{ -	struct xt_parser *xt = data; -	 -	xt->cur->flags |= XT_COMPLETE; -	xt->cur = xt->cur->parent; -} - -GMarkupParser xt_parser_funcs = -{ -	xt_start_element, -	xt_end_element, -	xt_text, -	NULL, -	NULL -}; - -struct xt_parser *xt_new( gpointer data ) -{ -	struct xt_parser *xt = g_new0( struct xt_parser, 1 ); -	 -	xt->data = data; -	xt_reset( xt ); -	 -	return xt; -} - -/* Reset the parser, flush everything we have so far. For example, we need -   this for XMPP when doing TLS/SASL to restart the stream. */ -void xt_reset( struct xt_parser *xt ) -{ -	if( xt->parser ) -		g_markup_parse_context_free( xt->parser ); -	 -	xt->parser = g_markup_parse_context_new( &xt_parser_funcs, 0, xt, NULL ); -	 -	if( xt->root ) -	{ -		xt_free_node( xt->root ); -		xt->root = NULL; -		xt->cur = NULL; -	} -} - -/* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on -   end-of-stream and 1 otherwise. */ -int xt_feed( struct xt_parser *xt, char *text, int text_len ) -{ -	if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) ) -	{ -		return -1; -	} -	 -	return !( xt->root && xt->root->flags & XT_COMPLETE ); -} - -/* Find completed nodes and see if a handler has to be called. Passing -   a node isn't necessary if you want to start at the root, just pass -   NULL. This second argument is needed for recursive calls. */ -int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) -{ -	struct xt_node *c; -	xt_status st; -	int i; -	 -	/* Just in case someone likes infinite loops... */ -	if( xt->root == NULL ) -		return 0; -	 -	if( node == NULL ) -		return xt_handle( xt, xt->root, depth ); -	 -	if( depth != 0 ) -		for( c = node->children; c; c = c->next ) -			if( !xt_handle( xt, c, depth > 0 ? depth - 1 : depth ) ) -				return 0; -	 -	if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) ) -	{ -		for( i = 0; xt->handlers[i].func; i ++ ) -		{ -			/* This one is fun! \o/ */ -			 -						/* If handler.name == NULL it means it should always match. */ -			if( ( xt->handlers[i].name == NULL ||  -						/* If it's not, compare. There should always be a name. */ -			      g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) && -						/* If handler.parent == NULL, it's a match. */ -			    ( xt->handlers[i].parent == NULL || -						/* If there's a parent node, see if the name matches. */ -			      ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 :  -						/* If there's no parent, the handler should mention <root> as a parent. */ -			                       g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) -			{ -				st = xt->handlers[i].func( node, xt->data ); -				 -				if( st == XT_ABORT ) -					return 0; -				else if( st != XT_NEXT ) -					break; -			} -		} -		 -		node->flags |= XT_SEEN; -	} -	 -	return 1; -} - -/* Garbage collection: Cleans up all nodes that are handled. Useful for -   streams because there's no reason to keep a complete packet history -   in memory. */ -void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ) -{ -	struct xt_node *c, *prev; -	 -	if( !xt || !xt->root ) -		return; -	 -	if( node == NULL ) -		return xt_cleanup( xt, xt->root, depth ); -	 -	if( node->flags & XT_SEEN && node == xt->root ) -	{ -		xt_free_node( xt->root ); -		xt->root = xt->cur = NULL; -		/* xt->cur should be NULL already, BTW... */ -		 -		return; -	} -	 -	/* c contains the current node, prev the previous node (or NULL). -	   I admit, this one's pretty horrible. */ -	for( c = node->children, prev = NULL; c; prev = c, c = c ? c->next : node->children ) -	{ -		if( c->flags & XT_SEEN ) -		{ -			/* Remove the node from the linked list. */ -			if( prev ) -				prev->next = c->next; -			else -				node->children = c->next; -			 -			xt_free_node( c ); -			 -			/* Since the for loop wants to get c->next, make sure -			   c points at something that exists (and that c->next -			   will actually be the next item we should check). c -			   can be NULL now, if we just removed the first item. -			   That explains the ? thing in for(). */ -			c = prev; -		} -		else -		{ -			/* This node can't be cleaned up yet, but maybe a -			   subnode can. */ -			if( depth != 0 ) -				xt_cleanup( xt, c, depth > 0 ? depth - 1 : depth ); -		} -	} -} - -static void xt_to_string_real( struct xt_node *node, GString *str ) -{ -	char *buf; -	struct xt_node *c; -	int i; -	 -	g_string_append_printf( str, "<%s", node->name ); -	 -	for( i = 0; node->attr[i].key; i ++ ) -	{ -		buf = g_markup_printf_escaped( " %s=\"%s\"", node->attr[i].key, node->attr[i].value ); -		g_string_append( str, buf ); -		g_free( buf ); -	} -	 -	if( node->text == NULL && node->children == NULL ) -	{ -		g_string_append( str, "/>" ); -		return; -	} -	 -	g_string_append( str, ">" ); -	if( node->text_len > 0 ) -	{ -		buf = g_markup_escape_text( node->text, node->text_len ); -		g_string_append( str, buf ); -		g_free( buf ); -	} -	 -	for( c = node->children; c; c = c->next ) -		xt_to_string_real( c, str ); -	 -	g_string_append_printf( str, "</%s>", node->name ); -} - -char *xt_to_string( struct xt_node *node ) -{ -	GString *ret; -	char *real; -	 -	ret = g_string_new( "" ); -	xt_to_string_real( node, ret ); -	 -	real = ret->str; -	g_string_free( ret, FALSE ); -	 -	return real; -} - -#ifdef DEBUG -void xt_print( struct xt_node *node ) -{ -	int i; -	struct xt_node *c; -	 -	/* Indentation */ -	for( c = node; c->parent; c = c->parent ) -		printf( "\t" ); -	 -	/* Start the tag */ -	printf( "<%s", node->name ); -	 -	/* Print the attributes */ -	for( i = 0; node->attr[i].key; i ++ ) -		printf( " %s=\"%s\"", node->attr[i].key, g_markup_escape_text( node->attr[i].value, -1 ) ); -	 -	/* /> in case there's really *nothing* inside this tag, otherwise -	   just >. */ -	/* If this tag doesn't have any content at all... */ -	if( node->text == NULL && node->children == NULL ) -	{ -		printf( "/>\n" ); -		return; -		/* Then we're finished! */ -	} -	 -	/* Otherwise... */ -	printf( ">" ); -	 -	/* Only print the text if it contains more than whitespace (TEST). */ -	if( node->text_len > 0 ) -	{ -		for( i = 0; node->text[i] && isspace( node->text[i] ); i ++ ); -		if( node->text[i] ) -			printf( "%s", g_markup_escape_text( node->text, -1 ) ); -	} -	 -	if( node->children ) -		printf( "\n" ); -	 -	for( c = node->children; c; c = c->next ) -		xt_print( c ); -	 -	if( node->children ) -		for( c = node; c->parent; c = c->parent ) -			printf( "\t" ); -	 -	/* Non-empty tag is now finished. */ -	printf( "</%s>\n", node->name ); -} -#endif - -struct xt_node *xt_dup( struct xt_node *node ) -{ -	struct xt_node *dup = g_new0( struct xt_node, 1 ); -	struct xt_node *c, *dc = NULL; -	int i; -	 -	/* Let's NOT copy the parent element here BTW! Only do it for children. */ -	 -	dup->name = g_strdup( node->name ); -	dup->flags = node->flags; -	if( node->text ) -	{ -		dup->text = g_memdup( node->text, node->text_len + 1 ); -		dup->text_len = node->text_len; -	} -	 -	/* Count the number of attributes and allocate the new array. */ -	for( i = 0; node->attr[i].key; i ++ ); -	dup->attr = g_new0( struct xt_attr, i + 1 ); -	 -	/* Copy them all! */ -	for( i --; i >= 0; i -- ) -	{ -		dup->attr[i].key = g_strdup( node->attr[i].key ); -		dup->attr[i].value = g_strdup( node->attr[i].value ); -	} -	 -	/* This nice mysterious loop takes care of the children. */ -	for( c = node->children; c; c = c->next ) -	{ -		if( dc == NULL ) -			dc = dup->children = xt_dup( c ); -		else -			dc = ( dc->next = xt_dup( c ) ); -		 -		dc->parent = dup; -	} -	 -	return dup; -} - -/* Frees a node. This doesn't clean up references to itself from parents! */ -void xt_free_node( struct xt_node *node ) -{ -	int i; -	 -	if( !node ) -		return; -	 -	g_free( node->name ); -	g_free( node->text ); -	 -	for( i = 0; node->attr[i].key; i ++ ) -	{ -		g_free( node->attr[i].key ); -		g_free( node->attr[i].value ); -	} -	g_free( node->attr ); -	 -	while( node->children ) -	{ -		struct xt_node *next = node->children->next; -		 -		xt_free_node( node->children ); -		node->children = next; -	} -	 -	g_free( node ); -} - -void xt_free( struct xt_parser *xt ) -{ -	if( !xt ) -		return; -	 -	if( xt->root ) -		xt_free_node( xt->root ); -	 -	g_markup_parse_context_free( xt->parser ); -	 -	g_free( xt ); -} - -/* To find a node's child with a specific name, pass the node's children -   list, not the node itself! The reason you have to do this by hand: So -   that you can also use this function as a find-next. */ -struct xt_node *xt_find_node( struct xt_node *node, const char *name ) -{ -	while( node ) -	{ -		if( g_strcasecmp( node->name, name ) == 0 ) -			break; -		 -		node = node->next; -	} -	 -	return node; -} - -char *xt_find_attr( struct xt_node *node, const char *key ) -{ -	int i; -	 -	if( !node ) -		return NULL; -	 -	for( i = 0; node->attr[i].key; i ++ ) -		if( g_strcasecmp( node->attr[i].key, key ) == 0 ) -			break; -	 -	return node->attr[i].value; -} - -struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ) -{ -	struct xt_node *node, *c; -	 -	node = g_new0( struct xt_node, 1 ); -	node->name = g_strdup( name ); -	node->children = children; -	node->attr = g_new0( struct xt_attr, 1 ); -	 -	if( text ) -	{ -		node->text_len = strlen( text ); -		node->text = g_memdup( text, node->text_len + 1 ); -	} -	 -	for( c = children; c; c = c->next ) -	{ -		if( c->parent != NULL ) -		{ -			/* ERROR CONDITION: They seem to have a parent already??? */ -		} -		 -		c->parent = node; -	} -	 -	return node; -} - -void xt_add_child( struct xt_node *parent, struct xt_node *child ) -{ -	struct xt_node *node; -	 -	/* This function can actually be used to add more than one child, so -	   do handle this properly. */ -	for( node = child; node; node = node->next ) -	{ -		if( node->parent != NULL ) -		{ -			/* ERROR CONDITION: They seem to have a parent already??? */ -		} -		 -		node->parent = parent; -	} -	 -	if( parent->children == NULL ) -	{ -		parent->children = child; -	} -	else -	{ -		for( node = parent->children; node->next; node = node->next ); -		node->next = child; -	} -} - -void xt_add_attr( struct xt_node *node, const char *key, const char *value ) -{ -	int i; -	 -	/* Now actually it'd be nice if we can also change existing attributes -	   (which actually means this function doesn't have the right name). -	   So let's find out if we have this attribute already... */ -	for( i = 0; node->attr[i].key; i ++ ) -		if( strcmp( node->attr[i].key, key ) == 0 ) -			break; -	 -	if( node->attr[i].key == NULL ) -	{ -		/* If not, allocate space for a new attribute. */ -		node->attr = g_renew( struct xt_attr, node->attr, i + 2 ); -		node->attr[i].key = g_strdup( key ); -		node->attr[i+1].key = NULL; -	} -	else -	{ -		/* Otherwise, free the old value before setting the new one. */ -		g_free( node->attr[i].value ); -	} -	 -	node->attr[i].value = g_strdup( value ); -} - -int xt_remove_attr( struct xt_node *node, const char *key ) -{ -	int i, last; -	 -	for( i = 0; node->attr[i].key; i ++ ) -		if( strcmp( node->attr[i].key, key ) == 0 ) -			break; -	 -	/* If we didn't find the attribute... */ -	if( node->attr[i].key == NULL ) -		return 0; -	 -	g_free( node->attr[i].key ); -	g_free( node->attr[i].value ); -	 -	/* If it's the last, this is easy: */ -	if( node->attr[i+1].key == NULL ) -	{ -		node->attr[i].key = node->attr[i].value = NULL; -	} -	else /* It's also pretty easy, actually. */ -	{ -		/* Find the last item. */ -		for( last = i + 1; node->attr[last+1].key; last ++ ); -		 -		node->attr[i] = node->attr[last]; -		node->attr[last].key = NULL; -		node->attr[last].value = NULL; -	} -	 -	/* Let's not bother with reallocating memory here. It takes time and -	   most packets don't stay in memory for long anyway. */ -	 -	return 1; -} diff --git a/protocols/jabber/xmltree.h b/protocols/jabber/xmltree.h deleted file mode 100644 index b8b61641..00000000 --- a/protocols/jabber/xmltree.h +++ /dev/null @@ -1,97 +0,0 @@ -/***************************************************************************\ -*                                                                           * -*  BitlBee - An IRC to IM gateway                                           * -*  Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly)       * -*                                                                           * -*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   * -*                                                                           * -*  This library is free software; you can redistribute it and/or            * -*  modify it under the terms of the GNU Lesser General Public               * -*  License as published by the Free Software Foundation, version            * -*  2.1.                                                                     * -*                                                                           * -*  This library is distributed in the hope that it will be useful,          * -*  but WITHOUT ANY WARRANTY; without even the implied warranty of           * -*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        * -*  Lesser General Public License for more details.                          * -*                                                                           * -*  You should have received a copy of the GNU Lesser General Public License * -*  along with this library; if not, write to the Free Software Foundation,  * -*  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA           * -*                                                                           * -****************************************************************************/ - -#ifndef _XMLTREE_H -#define _XMLTREE_H - -typedef enum -{ -	XT_COMPLETE	= 1,	/* </tag> reached */ -	XT_SEEN		= 2,	/* Handler called (or not defined) */ -} xt_flags; - -typedef enum -{ -	XT_ABORT,		/* Abort, don't handle the rest anymore */ -	XT_HANDLED,		/* Handled this tag properly, go to the next one */ -	XT_NEXT			/* Try if there's another matching handler */ -} xt_status; - -struct xt_attr -{ -	char *key, *value; -}; - -struct xt_node -{ -	struct xt_node *parent; -	struct xt_node *children; -	 -	char *name; -	struct xt_attr *attr; -	char *text; -	int text_len; -	 -	struct xt_node *next; -	xt_flags flags; -}; - -typedef xt_status (*xt_handler_func) ( struct xt_node *node, gpointer data ); - -struct xt_handler_entry -{ -	char *name, *parent; -	xt_handler_func func; -}; - -struct xt_parser -{ -	GMarkupParseContext *parser; -	struct xt_node *root; -	struct xt_node *cur; -	 -	struct xt_handler_entry *handlers; -	gpointer data; -	 -	GError *gerr; -}; - -struct xt_parser *xt_new( gpointer data ); -void xt_reset( struct xt_parser *xt ); -int xt_feed( struct xt_parser *xt, char *text, int text_len ); -int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ); -void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ); -char *xt_to_string( struct xt_node *node ); -void xt_print( struct xt_node *node ); -struct xt_node *xt_dup( struct xt_node *node ); -void xt_free_node( struct xt_node *node ); -void xt_free( struct xt_parser *xt ); -struct xt_node *xt_find_node( struct xt_node *node, const char *name ); -char *xt_find_attr( struct xt_node *node, const char *key ); - -struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ); -void xt_add_child( struct xt_node *parent, struct xt_node *child ); -void xt_add_attr( struct xt_node *node, const char *key, const char *value ); -int xt_remove_attr( struct xt_node *node, const char *key ); - -#endif diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index c8f4f4c6..63759303 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -28,7 +28,7 @@  #define TYPING_NOTIFICATION_MESSAGE "\r\r\rBEWARE, ME R TYPINK MESSAGE!!!!\r\r\r"  #define GROUPCHAT_SWITCHBOARD_MESSAGE "\r\r\rME WANT TALK TO MANY PEOPLE\r\r\r" -#ifdef DEBUG +#ifdef DEBUG_MSN  #define debug( text... ) imcb_log( ic, text );  #else  #define debug( text... ) diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index fae2877d..58ad22f8 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -89,8 +89,10 @@ struct msn_buddy_ask_data  	char *realname;  }; -static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla ) +static void msn_buddy_ask_yes( void *data )  { +	struct msn_buddy_ask_data *bla = data; +	  	msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname );  	if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) @@ -101,8 +103,10 @@ static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla )  	g_free( bla );  } -static void msn_buddy_ask_no( gpointer w, struct msn_buddy_ask_data *bla ) +static void msn_buddy_ask_no( void *data )  { +	struct msn_buddy_ask_data *bla = data; +	  	msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname );  	g_free( bla->handle ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 0bb84a74..fe48f96d 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -33,7 +33,7 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c  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 void msn_auth_got_passport_id( struct passport_reply *rep ); +static void msn_auth_got_passport_token( struct msn_auth_data *mad );  gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )  { @@ -177,7 +177,15 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  			}  			debug( "Connecting to a new switchboard with key %s", cmd[5] ); -			sb = msn_sb_create( ic, server, port, cmd[5], MSN_SB_NEW ); + +			if( ( sb = msn_sb_create( ic, server, port, cmd[5], MSN_SB_NEW ) ) == NULL ) +			{ +				/* Although this isn't strictly fatal for the NS connection, it's +				   definitely something serious (we ran out of file descriptors?). */ +				imcb_error( ic, "Could not create new switchboard" ); +				imc_logout( ic, TRUE ); +				return( 0 ); +			}  			if( md->msgq )  			{ @@ -213,7 +221,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  		if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 )  		{  			/* Time for some Passport black magic... */ -			if( !passport_get_id( msn_auth_got_passport_id, ic, ic->acc->user, ic->acc->pass, cmd[4] ) ) +			if( !passport_get_token( msn_auth_got_passport_token, ic, ic->acc->user, ic->acc->pass, cmd[4] ) )  			{  				imcb_error( ic, "Error while contacting Passport server" );  				imc_logout( ic, TRUE ); @@ -269,11 +277,25 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  	{  		if( num_parts == 5 )  		{ -			md->buddycount = atoi( cmd[3] ); -			md->groupcount = atoi( cmd[4] ); -			if( md->groupcount > 0 ) +			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 );  		} @@ -467,8 +489,18 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  		debug( "Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4] ); -		sb = msn_sb_create( ic, server, port, cmd[4], session ); -		sb->who = g_strdup( cmd[5] ); +		if( ( sb = msn_sb_create( ic, server, port, cmd[4], session ) ) == NULL ) +		{ +			/* Although this isn't strictly fatal for the NS connection, it's +			   definitely something serious (we ran out of file descriptors?). */ +			imcb_error( ic, "Could not create new switchboard" ); +			imc_logout( ic, TRUE ); +			return( 0 ); +		} +		else +		{ +			sb->who = g_strdup( cmd[5] ); +		}  	}  	else if( strcmp( cmd[0], "ADD" ) == 0 )  	{ @@ -646,6 +678,9 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int  				{  					imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders );  				} +				 +				g_free( inbox ); +				g_free( folders );  			}  			else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 )  			{ @@ -673,22 +708,26 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int  	return( 1 );  } -static void msn_auth_got_passport_id( struct passport_reply *rep ) +static void msn_auth_got_passport_token( struct msn_auth_data *mad )  { -	struct im_connection *ic = rep->data; -	struct msn_data *md = ic->proto_data; -	char *key = rep->result; -	char buf[1024]; +	struct im_connection *ic = mad->data; +	struct msn_data *md; -	if( key == NULL ) +	/* Dead connection? */ +	if( g_slist_find( msn_connections, ic ) == NULL ) +		return; +	 +	md = ic->proto_data; +	if( mad->token )  	{ -		imcb_error( ic, "Error during Passport authentication (%s)", -		               rep->error_string ? rep->error_string : "Unknown error" ); -		imc_logout( ic, TRUE ); +		char buf[1024]; +		 +		g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token ); +		msn_write( ic, buf, strlen( buf ) );  	}  	else  	{ -		g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, key ); -		msn_write( ic, buf, strlen( buf ) ); +		imcb_error( ic, "Error during Passport authentication: %s", mad->error ); +		imc_logout( ic, TRUE );  	}  } diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index 9fe6a174..565d15f3 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -1,8 +1,7 @@ -/* passport.c +/** passport.c   * - * Functions to login to microsoft passport service for Messenger - * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be> - * Copyright (C) 2004 Wilmer van der Gaast <wilmer@gaast.net> + * Functions to login to Microsoft Passport service for Messenger + * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net>   *   * This program is free software; you can redistribute it and/or modify                * it under the terms of the GNU General Public License version 2                    @@ -23,208 +22,149 @@  #include "passport.h"  #include "msn.h"  #include "bitlbee.h" +#include "url.h" +#include "misc.h" +#include "xmltree.h"  #include <ctype.h>  #include <errno.h> -#define MSN_BUF_LEN 8192 +static int passport_get_token_real( struct msn_auth_data *mad ); +static void passport_get_token_ready( struct http_request *req ); -static char *prd_cached = NULL; - -static int passport_get_id_real( gpointer func, gpointer data, char *header ); -static void passport_get_id_ready( struct http_request *req ); - -static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header ); -static void passport_retrieve_dalogin_ready( struct http_request *req ); - -static char *passport_create_header( char *cookie, char *email, char *pwd ); -static void destroy_reply( struct passport_reply *rep ); - -int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie ) -{ -	char *header = passport_create_header( cookie, username, password ); -	 -	if( prd_cached == NULL ) -		return passport_retrieve_dalogin( func, data, header ); -	else -		return passport_get_id_real( func, data, header ); -} - -static int passport_get_id_real( gpointer func, gpointer data, char *header ) +int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie )  { -	struct passport_reply *rep; -	char *server, *dummy, *reqs; -	struct http_request *req; -	 -	rep = g_new0( struct passport_reply, 1 ); -	rep->data = data; -	rep->func = func; -	rep->header = header; -	 -	server = g_strdup( prd_cached ); -	dummy = strchr( server, '/' ); -	 -	if( dummy == NULL ) -	{ -		destroy_reply( rep ); -		return( 0 ); -	} -	 -	reqs = g_strdup_printf( "GET %s HTTP/1.0\r\n%s\r\n\r\n", dummy, header ); +	struct msn_auth_data *mad = g_new0( struct msn_auth_data, 1 ); +	int i; -	*dummy = 0; -	req = http_dorequest( server, 443, 1, reqs, passport_get_id_ready, rep ); +	mad->username = g_strdup( username ); +	mad->password = g_strdup( password ); +	mad->cookie = g_strdup( cookie ); -	g_free( server ); -	g_free( reqs ); +	mad->callback = func; +	mad->data = data; -	if( req == NULL ) -		destroy_reply( rep ); +	mad->url = g_strdup( SOAP_AUTHENTICATION_URL ); +	mad->ttl = 3; /* Max. # of redirects. */ -	return( req != NULL ); -} - -static void passport_get_id_ready( struct http_request *req ) -{ -	struct passport_reply *rep = req->data; -	 -	if( !g_slist_find( msn_connections, rep->data ) ) -	{ -		destroy_reply( rep ); -		return; -	} +	/* HTTP-escape stuff and s/,/&/ */ +	http_decode( mad->cookie ); +	for( i = 0; mad->cookie[i]; i ++ ) +		if( mad->cookie[i] == ',' ) +			mad->cookie[i] = '&'; -	if( req->finished && req->reply_headers && req->status_code == 200 ) -	{ -		char *dummy; -		 -		if( ( dummy = strstr( req->reply_headers, "from-PP='" ) ) ) -		{ -			char *responseend; -			 -			dummy += strlen( "from-PP='" ); -			responseend = strchr( dummy, '\'' ); -			if( responseend ) -				*responseend = 0; -			 -			rep->result = g_strdup( dummy ); -		} -		else -		{ -			rep->error_string = g_strdup( "Could not parse Passport server response" ); -		} -	} -	else -	{ -		rep->error_string = g_strdup_printf( "HTTP error: %s", -		                      req->status_string ? req->status_string : "Unknown error" ); -	} +	/* Microsoft doesn't allow password longer than 16 chars and silently +	   fails authentication if you give the "full version" of your passwd. */ +	if( strlen( mad->password ) > MAX_PASSPORT_PWLEN ) +		mad->password[MAX_PASSPORT_PWLEN] = 0; -	rep->func( rep ); -	destroy_reply( rep ); +	return passport_get_token_real( mad );  } -static char *passport_create_header( char *cookie, char *email, char *pwd ) +static int passport_get_token_real( struct msn_auth_data *mad )  { -	char *buffer; -	char *currenttoken; -	char *email_enc, *pwd_enc; -	 -	currenttoken = strstr( cookie, "lc=" ); -	if( currenttoken == NULL ) -		return NULL; +	char *post_payload, *post_request; +	struct http_request *req; +	url_t url; -	email_enc = g_new0( char, strlen( email ) * 3 + 1 ); -	strcpy( email_enc, email ); -	http_encode( email_enc ); +	url_set( &url, mad->url ); -	pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 ); -	strcpy( pwd_enc, pwd ); -	http_encode( pwd_enc ); +	post_payload = g_markup_printf_escaped( SOAP_AUTHENTICATION_PAYLOAD, +	                                        mad->username, +	                                        mad->password, +	                                        mad->cookie ); -	buffer = g_strdup_printf( "Authorization: Passport1.4 OrgVerb=GET," -	                          "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom," -	                          "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc, -	                          currenttoken ); +	post_request = g_strdup_printf( SOAP_AUTHENTICATION_REQUEST, +	                                url.file, url.host, +	                                (int) strlen( post_payload ), +	                                post_payload ); +	                                 +	req = http_dorequest( url.host, url.port, 1, post_request, +	                      passport_get_token_ready, mad ); -	g_free( email_enc ); -	g_free( pwd_enc ); +	g_free( post_request ); +	g_free( post_payload ); -	return buffer; +	return req != NULL;  } -static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header ) -{ -	struct passport_reply *rep = g_new0( struct passport_reply, 1 ); -	struct http_request *req; -	 -	rep->data = data; -	rep->func = func; -	rep->header = header; -	 -	req = http_dorequest_url( "https://nexus.passport.com/rdr/pprdr.asp", passport_retrieve_dalogin_ready, rep ); -	 -	if( !req ) -		destroy_reply( rep ); -	 -	return( req != NULL ); -} +static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data ); +static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data ); -static void passport_retrieve_dalogin_ready( struct http_request *req ) +static const struct xt_handler_entry passport_xt_handlers[] = { +	{ "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", passport_xt_extract_token }, +	{ "S:Fault",                  "S:Envelope",                 passport_xt_handle_fault  }, +	{ NULL,                       NULL,                         NULL                      } +}; + +static void passport_get_token_ready( struct http_request *req )  { -	struct passport_reply *rep = req->data; -	char *dalogin; -	char *urlend; +	struct msn_auth_data *mad = req->data; +	struct xt_parser *parser; +	 +	g_free( mad->url ); +	g_free( mad->error ); +	mad->url = mad->error = NULL; -	if( !g_slist_find( msn_connections, rep->data ) ) +	if( req->status_code == 200 )  	{ -		destroy_reply( rep ); -		return; +		parser = xt_new( passport_xt_handlers, mad ); +		xt_feed( parser, req->reply_body, req->body_size ); +		xt_handle( parser, NULL, -1 ); +		xt_free( parser );  	} -	 -	if( !req->finished || !req->reply_headers || req->status_code != 200 ) +	else  	{ -		rep->error_string = g_strdup_printf( "HTTP error while fetching DALogin: %s", -		                        req->status_string ? req->status_string : "Unknown error" ); -		goto failure; +		mad->error = g_strdup_printf( "HTTP error %d (%s)", req->status_code, +		                              req->status_string ? req->status_string : "unknown" );  	} -	dalogin = strstr( req->reply_headers, "DALogin=" );	 +	if( mad->error == NULL && mad->token == NULL ) +		mad->error = g_strdup( "Could not parse Passport server response" ); -	if( !dalogin ) +	if( mad->url && mad->token == NULL )  	{ -		rep->error_string = g_strdup( "Parse error while fetching DALogin" ); -		goto failure; +		passport_get_token_real( mad );  	} -	 -	dalogin += strlen( "DALogin=" ); -	urlend = strchr( dalogin, ',' ); -	if( urlend ) -		*urlend = 0; -	 -	/* strip the http(s):// part from the url */ -	urlend = strstr( urlend, "://" ); -	if( urlend ) -		dalogin = urlend + strlen( "://" ); -	 -	if( prd_cached == NULL ) -		prd_cached = g_strdup( dalogin ); -	 -	if( passport_get_id_real( rep->func, rep->data, rep->header ) ) +	else  	{ -		rep->header = NULL; -		destroy_reply( rep ); -		return; +		mad->callback( mad ); +		 +		g_free( mad->url ); +		g_free( mad->username ); +		g_free( mad->password ); +		g_free( mad->cookie ); +		g_free( mad->token ); +		g_free( mad->error ); +		g_free( mad );  	} +} + +static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data ) +{ +	struct msn_auth_data *mad = data; +	char *s; +	 +	if( ( s = xt_find_attr( node, "Id" ) ) && strcmp( s, "PPToken1" ) == 0 ) +		mad->token = g_memdup( node->text, node->text_len + 1 ); -failure:	 -	rep->func( rep ); -	destroy_reply( rep ); +	return XT_HANDLED;  } -static void destroy_reply( struct passport_reply *rep ) +static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data )  { -	g_free( rep->result ); -	g_free( rep->header ); -	g_free( rep->error_string ); -	g_free( rep ); +	struct msn_auth_data *mad = data; +	struct xt_node *code = xt_find_node( node->children, "faultcode" ); +	struct xt_node *string = xt_find_node( node->children, "faultstring" ); +	struct xt_node *redirect = xt_find_node( node->children, "psf:redirectUrl" ); +	 +	if( redirect && redirect->text_len && mad->ttl-- > 0 ) +		mad->url = g_memdup( redirect->text, redirect->text_len + 1 ); +	 +	if( code == NULL || code->text_len == 0 ) +		mad->error = g_strdup( "Unknown error" ); +	else +		mad->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ? +		                              string->text : "no description available" ); +	 +	return XT_HANDLED;  } diff --git a/protocols/msn/passport.h b/protocols/msn/passport.h index 9fd81a82..517d2e91 100644 --- a/protocols/msn/passport.h +++ b/protocols/msn/passport.h @@ -1,10 +1,7 @@ -#ifndef __PASSPORT_H__ -#define __PASSPORT_H__  /* passport.h   * - * Functions to login to Microsoft Passport Service for Messenger - * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be>, - *                    Wilmer van der Gaast <wilmer@gaast.net> + * Functions to login to Microsoft Passport service for Messenger + * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net>   *   * This program is free software; you can redistribute it and/or modify                * it under the terms of the GNU General Public License version 2                    @@ -17,9 +14,15 @@   *                                                                                      * You should have received a copy of the GNU General Public License                   * along with this program; if not, write to the Free Software                       - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA           + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA             */ +/* Thanks to http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener +   for the specs! */ + +#ifndef __PASSPORT_H__ +#define __PASSPORT_H__ +  #include <stdio.h>  #include <stdlib.h>  #include <string.h> @@ -32,15 +35,79 @@  #endif  #include "nogaim.h" -struct passport_reply +#define MAX_PASSPORT_PWLEN 16 + +struct msn_auth_data  { -	void (*func)( struct passport_reply * ); -	void *data; -	char *result; -	char *header; -	char *error_string; +	char *url; +	int ttl; +	 +	char *username; +	char *password; +	char *cookie; +	 +	/* The end result, the only thing we'll really be interested in +	   once finished. */ +	char *token; +	char *error; /* Yeah, or that... */ +	 +	void (*callback)( struct msn_auth_data *mad ); +	gpointer data;  }; -int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie ); +#define SOAP_AUTHENTICATION_URL "https://loginnet.passport.com/RST.srf" + +#define SOAP_AUTHENTICATION_REQUEST \ +"POST %s HTTP/1.0\r\n" \ +"Accept: text/*\r\n" \ +"User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ +"Host: %s\r\n" \ +"Content-Length: %d\r\n" \ +"Cache-Control: no-cache\r\n" \ +"\r\n" \ +"%s" + +#define SOAP_AUTHENTICATION_PAYLOAD \ +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \ +"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">" \ +  "<Header>" \ +    "<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">" \ +      "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>" \ +      "<ps:BinaryVersion>4</ps:BinaryVersion>" \ +      "<ps:UIVersion>1</ps:UIVersion>" \ +      "<ps:Cookies></ps:Cookies>" \ +      "<ps:RequestParams>AQAAAAIAAABsYwQAAAAzMDg0</ps:RequestParams>" \ +    "</ps:AuthInfo>" \ +    "<wsse:Security>" \ +       "<wsse:UsernameToken Id=\"user\">" \ +         "<wsse:Username>%s</wsse:Username>" \ +         "<wsse:Password>%s</wsse:Password>" \ +       "</wsse:UsernameToken>" \ +    "</wsse:Security>" \ +  "</Header>" \ +  "<Body>" \ +    "<ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">" \ +      "<wst:RequestSecurityToken Id=\"RST0\">" \ +        "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ +        "<wsp:AppliesTo>" \ +          "<wsa:EndpointReference>" \ +            "<wsa:Address>http://Passport.NET/tb</wsa:Address>" \ +          "</wsa:EndpointReference>" \ +        "</wsp:AppliesTo>" \ +      "</wst:RequestSecurityToken>" \ +      "<wst:RequestSecurityToken Id=\"RST1\">" \ +       "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ +        "<wsp:AppliesTo>" \ +          "<wsa:EndpointReference>" \ +            "<wsa:Address>messenger.msn.com</wsa:Address>" \ +          "</wsa:EndpointReference>" \ +        "</wsp:AppliesTo>" \ +        "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>" \ +      "</wst:RequestSecurityToken>" \ +    "</ps:RequestMultipleSecurityTokens>" \ +  "</Body>" \ +"</Envelope>" + +int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie );  #endif /* __PASSPORT_H__ */ diff --git a/protocols/nogaim.c b/protocols/nogaim.c index c2966323..95d950ca 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -342,7 +342,8 @@ void imc_logout( struct im_connection *ic, int allow_reconnect )  /* dialogs.c */ -void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ) +void imcb_ask( struct im_connection *ic, char *msg, void *data, +               query_callback doit, query_callback dont )  {  	query_add( ic->irc, ic, msg, doit, dont, data );  } @@ -494,18 +495,20 @@ struct show_got_added_data  	char *handle;  }; -void show_got_added_no( gpointer w, struct show_got_added_data *data ) +void show_got_added_no( void *data )  { -	g_free( data->handle ); +	g_free( ((struct show_got_added_data*)data)->handle );  	g_free( data );  } -void show_got_added_yes( gpointer w, struct show_got_added_data *data ) +void show_got_added_yes( void *data )  { -	data->ic->acc->prpl->add_buddy( data->ic, data->handle, NULL ); -	/* imcb_add_buddy( data->ic, NULL, data->handle, data->handle ); */ +	struct show_got_added_data *sga = data; -	return show_got_added_no( w, data ); +	sga->ic->acc->prpl->add_buddy( sga->ic, sga->handle, NULL ); +	/* imcb_add_buddy( sga->ic, NULL, sga->handle, sga->handle ); */ +	 +	return show_got_added_no( data );  }  void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname ) diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 3caefe2b..7e14c560 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -41,13 +41,9 @@  #include "bitlbee.h"  #include "account.h"  #include "proxy.h" +#include "query.h"  #include "md5.h" -#define BUF_LEN MSG_LEN -#define BUF_LONG ( BUF_LEN * 2 ) -#define MSG_LEN 2048 -#define BUF_LEN MSG_LEN -  #define BUDDY_ALIAS_MAXLEN 388   /* because MSN names can be 387 characters */  #define WEBSITE "http://www.bitlbee.org/" @@ -264,7 +260,7 @@ G_MODULE_EXPORT void imcb_error( struct im_connection *ic, char *format, ... ) G   * - 'data' can be your custom struct - it will be passed to the callbacks.   * - 'doit' or 'dont' will be called depending of the answer of the user.   */ -G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ); +G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, query_callback doit, query_callback dont );  G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname );  /* Buddy management */ diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 120ebc3e..28207103 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -60,6 +60,9 @@  #define OSCAR_GROUP "Friends" +#define BUF_LEN 2048 +#define BUF_LONG ( BUF_LEN * 2 ) +  /* Don't know if support for UTF8 is really working. For now it's UTF16 here.     static int gaim_caps = AIM_CAPS_UTF8; */ @@ -240,6 +243,32 @@ static char *msgerrreason[] = {  };  static int msgerrreasonlen = 25; +/* Hurray, this function is NOT thread-safe \o/ */ +static char *normalize(const char *s) +{ +	static char buf[BUF_LEN]; +	char *t, *u; +	int x = 0; + +	g_return_val_if_fail((s != NULL), NULL); + +	u = t = g_strdup(s); + +	strcpy(t, s); +	g_strdown(t); + +	while (*t && (x < BUF_LEN - 1)) { +		if (*t != ' ' && *t != '!') { +			buf[x] = *t; +			x++; +		} +		t++; +	} +	buf[x] = '\0'; +	g_free(u); +	return buf; +} +  static gboolean oscar_callback(gpointer data, gint source,  				b_input_condition condition) {  	aim_conn_t *conn = (aim_conn_t *)data; @@ -1001,13 +1030,13 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) {  			g_hash_table_insert(od->ips, uin, (gpointer) (long) info->icqinfo.ipaddr);  	} -	tmp = g_strdup(normalize(ic->acc->user)); -	if (!strcmp(tmp, normalize(info->sn))) +	if (!aim_sncmp(ic->acc->user, info->sn))  		g_snprintf(ic->displayname, sizeof(ic->displayname), "%s", info->sn); -	g_free(tmp); -	imcb_buddy_status(ic, info->sn, flags, state_string, NULL); -	/* imcb_buddy_times(ic, info->sn, signon, time_idle); */ +	tmp = normalize(info->sn); +	imcb_buddy_status(ic, tmp, flags, state_string, NULL); +	/* imcb_buddy_times(ic, tmp, signon, time_idle); */ +  	return 1;  } @@ -1021,7 +1050,7 @@ static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) {  	info = va_arg(ap, aim_userinfo_t *);  	va_end(ap); -	imcb_buddy_status(ic, info->sn, 0, NULL, NULL ); +	imcb_buddy_status(ic, normalize(info->sn), 0, NULL, NULL );  	return 1;  } @@ -1077,14 +1106,14 @@ static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_  	}  	strip_linefeed(tmp); -	imcb_buddy_msg(ic, userinfo->sn, tmp, flags, 0); +	imcb_buddy_msg(ic, normalize(userinfo->sn), tmp, flags, 0);  	g_free(tmp);  	return 1;  } -void oscar_accept_chat(gpointer w, struct aim_chat_invitation * inv); -void oscar_reject_chat(gpointer w, struct aim_chat_invitation * inv); +void oscar_accept_chat(void *data); +void oscar_reject_chat(void *data);  static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args) {  	struct im_connection *ic = sess->aux_data; @@ -1118,7 +1147,8 @@ static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_  	return 1;  } -static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) { +static void gaim_icq_authgrant(void *data_) { +	struct icq_auth *data = data_;  	char *uin, message;  	struct oscar_data *od = (struct oscar_data *)data->ic->proto_data; @@ -1133,7 +1163,8 @@ static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) {  	g_free(data);  } -static void gaim_icq_authdeny(gpointer w, struct icq_auth *data) { +static void gaim_icq_authdeny(void *data_) { +	struct icq_auth *data = data_;  	char *uin, *message;  	struct oscar_data *od = (struct oscar_data *)data->ic->proto_data; @@ -1174,7 +1205,7 @@ static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_  			uin = g_strdup_printf("%u", args->uin);  			message = g_strdup(args->msg);  			strip_linefeed(message); -			imcb_buddy_msg(ic, uin, message, 0, 0); +			imcb_buddy_msg(ic, normalize(uin), message, 0, 0);  			g_free(uin);  			g_free(message);  		} break; @@ -1193,7 +1224,7 @@ static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_  			}  			strip_linefeed(message); -			imcb_buddy_msg(ic, uin, message, 0, 0); +			imcb_buddy_msg(ic, normalize(uin), message, 0, 0);  			g_free(uin);  			g_free(m);  			g_free(message); @@ -1468,7 +1499,7 @@ static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) {  		return 1;  	for (i = 0; i < count; i++) -		imcb_chat_add_buddy(c->cnv, info[i].sn); +		imcb_chat_add_buddy(c->cnv, normalize(info[i].sn));  	return 1;  } @@ -1491,7 +1522,7 @@ static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) {  		return 1;  	for (i = 0; i < count; i++) -		imcb_chat_remove_buddy(c->cnv, info[i].sn, NULL); +		imcb_chat_remove_buddy(c->cnv, normalize(info[i].sn), NULL);  	return 1;  } @@ -1542,7 +1573,7 @@ static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) {  	tmp = g_malloc(BUF_LONG);  	g_snprintf(tmp, BUF_LONG, "%s", msg); -	imcb_chat_msg(ccon->cnv, info->sn, tmp, 0, 0); +	imcb_chat_msg(ccon->cnv, normalize(info->sn), tmp, 0, 0);  	g_free(tmp);  	return 1; @@ -1755,7 +1786,7 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) {  			time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0);  			g_snprintf(sender, sizeof(sender), "%u", msg->sender);  			strip_linefeed(dialog_msg); -			imcb_buddy_msg(ic, sender, dialog_msg, 0, t); +			imcb_buddy_msg(ic, normalize(sender), dialog_msg, 0, t);  			g_free(dialog_msg);  		} break; @@ -1776,7 +1807,7 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) {  			}  			strip_linefeed(dialog_msg); -			imcb_buddy_msg(ic, sender, dialog_msg, 0, t); +			imcb_buddy_msg(ic, normalize(sender), dialog_msg, 0, t);  			g_free(dialog_msg);  			g_free(m);  		} break; @@ -2014,23 +2045,26 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {  	struct im_connection *ic = sess->aux_data;  	struct aim_ssi_item *curitem;  	int tmp; +	char *nrm;  	/* Add from server list to local list */  	tmp = 0;  	for (curitem=sess->ssi.items; curitem; curitem=curitem->next) { +		nrm = curitem->name ? normalize(curitem->name) : NULL; +		  		switch (curitem->type) {  			case 0x0000: /* Buddy */ -				if ((curitem->name) && (!imcb_find_buddy(ic, curitem->name))) { +				if ((curitem->name) && (!imcb_find_buddy(ic, nrm))) {  					char *realname = NULL;  					if (curitem->data && aim_gettlv(curitem->data, 0x0131, 1))  						    realname = aim_gettlv_str(curitem->data, 0x0131, 1); -					imcb_add_buddy(ic, curitem->name, NULL); +					imcb_add_buddy(ic, nrm, NULL);  					if (realname) { -						imcb_buddy_nick_hint(ic, curitem->name, realname); -						imcb_rename_buddy(ic, curitem->name, realname); +						imcb_buddy_nick_hint(ic, nrm, realname); +						imcb_rename_buddy(ic, nrm, realname);  						g_free(realname);  					}  				} @@ -2042,7 +2076,7 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {  					for (list=ic->permit; (list && aim_sncmp(curitem->name, list->data)); list=list->next);  					if (!list) {  						char *name; -						name = g_strdup(normalize(curitem->name)); +						name = g_strdup(nrm);  						ic->permit = g_slist_append(ic->permit, name);  						tmp++;  					} @@ -2055,7 +2089,7 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {  					for (list=ic->deny; (list && aim_sncmp(curitem->name, list->data)); list=list->next);  					if (!list) {  						char *name; -						name = g_strdup(normalize(curitem->name)); +						name = g_strdup(nrm);  						ic->deny = g_slist_append(ic->deny, name);  						tmp++;  					} @@ -2117,7 +2151,7 @@ static int gaim_ssi_parseack( aim_session_t *sess, aim_frame_t *fr, ... )  			st = aimbs_get16( &fr->data );  			if( st == 0x00 )  			{ -				imcb_add_buddy( sess->aux_data, list, NULL ); +				imcb_add_buddy( sess->aux_data, normalize(list), NULL );  			}  			else if( st == 0x0E )  			{ @@ -2447,15 +2481,15 @@ int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...)  	if(type2 == 0x0002) {  		/* User is typing */ -		imcb_buddy_typing(ic, sn, OPT_TYPING); +		imcb_buddy_typing(ic, normalize(sn), OPT_TYPING);  	}   	else if (type2 == 0x0001) {  		/* User has typed something, but is not actively typing (stale) */ -		imcb_buddy_typing(ic, sn, OPT_THINKING); +		imcb_buddy_typing(ic, normalize(sn), OPT_THINKING);  	}  	else {  		/* User has stopped typing */ -		imcb_buddy_typing(ic, sn, 0); +		imcb_buddy_typing(ic, normalize(sn), 0);  	}  	return 1; @@ -2587,15 +2621,19 @@ struct groupchat *oscar_chat_with(struct im_connection * ic, char *who)  	return NULL;  } -void oscar_accept_chat(gpointer w, struct aim_chat_invitation * inv) +void oscar_accept_chat(void *data)  { +	struct aim_chat_invitation * inv = data; +	  	oscar_chat_join(inv->ic, inv->name, NULL, NULL);  	g_free(inv->name);  	g_free(inv);  } -void oscar_reject_chat(gpointer w, struct aim_chat_invitation * inv) +void oscar_reject_chat(void *data)  { +	struct aim_chat_invitation * inv = data; +	  	g_free(inv->name);  	g_free(inv);  } diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index ce38bc73..a61955c4 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -68,8 +68,6 @@ char *strchr (), *strrchr ();  #ifdef __MINGW32__  # include <winsock2.h> -# define write(a,b,c) send(a,b,c,0) -# define read(a,b,c)  recv(a,b,c,0)  #endif  #include <stdlib.h> @@ -380,7 +378,6 @@ static void del_from_list(struct yahoo_data *yd)  }  /* call repeatedly to get the next one */ -/*  static struct yahoo_input_data * find_input_by_id(int id)  {  	YList *l; @@ -391,7 +388,6 @@ static struct yahoo_input_data * find_input_by_id(int id)  	}  	return NULL;  } -*/  static struct yahoo_input_data * find_input_by_id_and_webcam_user(int id, const char * who)  { @@ -736,7 +732,7 @@ static void yahoo_send_packet(struct yahoo_input_data *yid, struct yahoo_packet  	data = y_new0(unsigned char, len + 1);  	memcpy(data + pos, "YMSG", 4); pos += 4; -	pos += yahoo_put16(data + pos, 0x0a00); +	pos += yahoo_put16(data + pos, 0x000c);  	pos += yahoo_put16(data + pos, 0x0000);  	pos += yahoo_put16(data + pos, pktlen + extra_pad);  	pos += yahoo_put16(data + pos, pkt->service); @@ -796,6 +792,7 @@ static int yahoo_send_data(int fd, void *data, int len)  void yahoo_close(int id)   {  	struct yahoo_data *yd = find_conn_by_id(id); +	  	if(!yd)  		return; @@ -3165,7 +3162,7 @@ int yahoo_write_ready(int id, int fd, void *data)  	struct data_queue *tx;  	LOG(("write callback: id=%d fd=%d data=%p", id, fd, data)); -	if(!yid || !yid->txqueues) +	if(!yid || !yid->txqueues || !find_conn_by_id(id))  		return -2;  	tx = yid->txqueues->data; @@ -3350,7 +3347,7 @@ static void yahoo_process_search_connection(struct yahoo_input_data *yid, int ov  					yct->age = atoi(cp);  					break;  				case 5:  -					if(cp != "\005") +					if(strcmp(cp, "5") != 0)  						yct->location = cp;  					k = 0;  					break; @@ -3841,11 +3838,9 @@ void yahoo_logoff(int id)  		}  	} -	 -/*	do { +	do {  		yahoo_input_close(yid); -	} while((yid = find_input_by_id(id)));*/ -	 +	} while((yid = find_input_by_id(id)));  }  void yahoo_get_list(int id) diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 52747bb4..0db6e27a 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -162,10 +162,7 @@ static void byahoo_logout( struct im_connection *ic )  	}  	g_slist_free( yd->buddygroups ); -	if( yd->logged_in ) -		yahoo_logoff( yd->y2_id ); -	else -		yahoo_close( yd->y2_id ); +	yahoo_logoff( yd->y2_id );  	g_free( yd );  } @@ -314,7 +311,7 @@ static void byahoo_chat_invite( struct groupchat *c, char *who, char *msg )  {  	struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; -	yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg ); +	yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg ? msg : "" );  }  static void byahoo_chat_leave( struct groupchat *c ) @@ -454,10 +451,6 @@ gboolean byahoo_write_ready_callback( gpointer data, gint source, b_input_condit  {  	struct byahoo_write_ready_data *d = data; -	if( !byahoo_get_ic_by_id( d->id ) ) -		/* WTF doesn't libyahoo clean this up? */ -		return FALSE; -	  	yahoo_write_ready( d->id, d->fd, d->data );  	return FALSE; @@ -797,16 +790,20 @@ int ext_yahoo_connect(const char *host, int port)  	return -1;  } -static void byahoo_accept_conf( gpointer w, struct byahoo_conf_invitation *inv ) +static void byahoo_accept_conf( void *data )  { +	struct byahoo_conf_invitation *inv = data; +	  	yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name );  	imcb_chat_add_buddy( inv->c, inv->ic->acc->user );  	g_free( inv->name );  	g_free( inv );  } -static void byahoo_reject_conf( gpointer w, struct byahoo_conf_invitation *inv ) +static void byahoo_reject_conf( void *data )  { +	struct byahoo_conf_invitation *inv = data; +	  	yahoo_conference_decline( inv->yid, NULL, inv->members, inv->name, "User rejected groupchat" );  	imcb_chat_free( inv->c );  	g_free( inv->name ); diff --git a/protocols/yahoo/yahoo_httplib.c b/protocols/yahoo/yahoo_httplib.c index dbbe2a84..1b084992 100644 --- a/protocols/yahoo/yahoo_httplib.c +++ b/protocols/yahoo/yahoo_httplib.c @@ -50,8 +50,6 @@ char *strchr (), *strrchr ();  #include "yahoo_debug.h"  #ifdef __MINGW32__  # include <winsock2.h> -# define write(a,b,c) send(a,b,c,0) -# define read(a,b,c)  recv(a,b,c,0)  # define snprintf _snprintf  #endif | 
