diff options
Diffstat (limited to 'protocols')
| -rw-r--r-- | protocols/jabber/io.c | 42 | ||||
| -rw-r--r-- | protocols/jabber/iq.c | 29 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 22 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 7 | ||||
| -rw-r--r-- | protocols/jabber/jabber_util.c | 9 | ||||
| -rw-r--r-- | protocols/jabber/presence.c | 17 | ||||
| -rw-r--r-- | protocols/msn/msn.c | 22 | ||||
| -rw-r--r-- | protocols/msn/msn.h | 7 | ||||
| -rw-r--r-- | protocols/msn/msn_util.c | 8 | ||||
| -rw-r--r-- | protocols/msn/ns.c | 74 | ||||
| -rw-r--r-- | protocols/msn/tables.c | 37 | ||||
| -rw-r--r-- | protocols/nogaim.c | 159 | ||||
| -rw-r--r-- | protocols/nogaim.h | 23 | ||||
| -rw-r--r-- | protocols/oscar/oscar.c | 39 | ||||
| -rw-r--r-- | protocols/yahoo/libyahoo2.c | 366 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo.c | 41 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo2_types.h | 23 | 
17 files changed, 458 insertions, 467 deletions
| diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 10efad37..a14ad21c 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -374,39 +374,13 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )  	}  	if( ( c = xt_find_node( node->children, "bind" ) ) ) -	{ -		reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) ); -		xt_add_attr( reply, "xmlns", XMLNS_BIND ); -		reply = jabber_make_packet( "iq", "set", NULL, reply ); -		jabber_cache_add( ic, reply, jabber_pkt_bind_sess ); -		 -		if( !jabber_write_packet( ic, reply ) ) -			return XT_ABORT; -		 -		jd->flags |= JFLAG_WAIT_BIND; -	} +		jd->flags |= JFLAG_WANT_BIND;  	if( ( c = xt_find_node( node->children, "session" ) ) ) -	{ -		reply = xt_new_node( "session", NULL, NULL ); -		xt_add_attr( reply, "xmlns", XMLNS_SESSION ); -		reply = jabber_make_packet( "iq", "set", NULL, reply ); -		jabber_cache_add( ic, reply, jabber_pkt_bind_sess ); -		 -		if( !jabber_write_packet( ic, reply ) ) -			return XT_ABORT; -		 -		jd->flags |= JFLAG_WAIT_SESSION; -	} +		jd->flags |= JFLAG_WANT_SESSION; -	/* This flag is already set if we authenticated via SASL, so now -	   we can resume the session in the new stream, if we don't have -	   to bind/initialize the session. */ -	if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) -	{ -		if( !jabber_get_roster( ic ) ) -			return XT_ABORT; -	} +	if( jd->flags & JFLAG_AUTHENTICATED ) +		return jabber_pkt_bind_sess( ic, NULL, NULL );  	return XT_HANDLED;  } @@ -440,6 +414,7 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data )  	imcb_log( ic, "Converting stream to TLS" ); +	jd->flags |= JFLAG_STARTTLS_DONE;  	jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, ic );  	return XT_HANDLED; @@ -530,9 +505,10 @@ gboolean jabber_start_stream( struct im_connection *ic )  	if( jd->r_inpa <= 0 )  		jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic ); -	greet = g_strdup_printf( "<?xml version='1.0' ?>" -	                         "<stream:stream to=\"%s\" xmlns=\"jabber:client\" " -	                          "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", jd->server ); +	greet = g_strdup_printf( "%s<stream:stream to=\"%s\" xmlns=\"jabber:client\" " +	                          "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">",  +	                          ( jd->flags & JFLAG_STARTTLS_DONE ) ? "" : "<?xml version='1.0' ?>", +	                          jd->server );  	st = jabber_write( ic, greet, strlen( greet ) ); diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 875b5c81..1b76a761 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -297,24 +297,39 @@ static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node  xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )  {  	struct jabber_data *jd = ic->proto_data; -	struct xt_node *c; +	struct xt_node *c, *reply = NULL;  	char *s; -	if( ( c = xt_find_node( node->children, "bind" ) ) ) +	if( node && ( c = xt_find_node( node->children, "bind" ) ) )  	{  		c = xt_find_node( c->children, "jid" );  		if( c && c->text_len && ( s = strchr( c->text, '/' ) ) &&  		    strcmp( s + 1, set_getstr( &ic->acc->set, "resource" ) ) != 0 )  			imcb_log( ic, "Server changed session resource string to `%s'", s + 1 ); -		 -		jd->flags &= ~JFLAG_WAIT_BIND;  	} -	else +	 +	if( jd->flags & JFLAG_WANT_BIND )  	{ -		jd->flags &= ~JFLAG_WAIT_SESSION; +		reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) ); +		xt_add_attr( reply, "xmlns", XMLNS_BIND ); +		jd->flags &= ~JFLAG_WANT_BIND; +	} +	else if( jd->flags & JFLAG_WANT_SESSION ) +	{ +		reply = xt_new_node( "session", NULL, NULL ); +		xt_add_attr( reply, "xmlns", XMLNS_SESSION ); +		jd->flags &= ~JFLAG_WANT_SESSION;  	} -	if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) +	if( reply != NULL ) +	{ +		reply = jabber_make_packet( "iq", "set", NULL, reply ); +		jabber_cache_add( ic, reply, jabber_pkt_bind_sess ); +		 +		if( !jabber_write_packet( ic, reply ) ) +			return XT_ABORT; +	} +	else if( ( jd->flags & ( JFLAG_WANT_BIND | JFLAG_WANT_SESSION ) ) == 0 )  	{  		if( !jabber_get_roster( ic ) )  			return XT_ABORT; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index b8e88c26..a1fb8817 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -66,7 +66,7 @@ static void jabber_init( account_t *acc )  	s = set_add( &acc->set, "resource", "BitlBee", NULL, acc );  	s->flags |= ACC_SET_OFFLINE_ONLY; -	s = set_add( &acc->set, "resource_select", "priority", NULL, acc ); +	s = set_add( &acc->set, "resource_select", "activity", NULL, acc );  	s = set_add( &acc->set, "server", NULL, set_eval_account, acc );  	s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY | SET_NULL_OK; @@ -79,6 +79,8 @@ static void jabber_init( account_t *acc )  	s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc );  	s->flags |= ACC_SET_OFFLINE_ONLY; +	 +	acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;  }  static void jabber_generate_id_hash( struct jabber_data *jd ); @@ -363,10 +365,11 @@ static void jabber_get_info( struct im_connection *ic, char *who )  	while( bud )  	{ -		imcb_log( ic, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s", -		                   bud->full_jid, bud->priority, -		                   bud->away_state ? bud->away_state->full_name : "(none)", -		                   bud->away_message ? : "(none)" ); +		imcb_log( ic, "Buddy %s (%d) information:", bud->full_jid, bud->priority ); +		if( bud->away_state ) +			imcb_log( ic, "Away state: %s", bud->away_state->full_name ); +		imcb_log( ic, "Status message: %s", bud->away_message ? : "(none)" ); +		  		bud = bud->next;  	} @@ -376,11 +379,12 @@ static void jabber_get_info( struct im_connection *ic, char *who )  static void jabber_set_away( struct im_connection *ic, char *state_txt, char *message )  {  	struct jabber_data *jd = ic->proto_data; -	struct jabber_away_state *state; -	/* Save all this info. We need it, for example, when changing the priority setting. */ -	state = (void *) jabber_away_state_by_name( state_txt ); -	jd->away_state = state ? state : (void *) jabber_away_state_list; /* Fall back to "Away" if necessary. */ +	/* state_txt == NULL -> Not away. +	   Unknown state -> fall back to the first defined away state. */ +	jd->away_state = state_txt ? jabber_away_state_by_name( state_txt ) +	                 ? : jabber_away_state_list : NULL; +	  	g_free( jd->away_message );  	jd->away_message = ( message && *message ) ? g_strdup( message ) : NULL; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 1180d2b9..8e3bf036 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -39,12 +39,13 @@ typedef enum  	JFLAG_AUTHENTICATED = 2,        /* Set when we're successfully authenticatd. */  	JFLAG_STREAM_RESTART = 4,       /* Set when we want to restart the stream (after  	                                   SASL or TLS). */ -	JFLAG_WAIT_SESSION = 8,	        /* Set if we sent a <session> tag and need a reply +	JFLAG_WANT_SESSION = 8,	        /* Set if the server wants a <session/> tag  	                                   before we continue. */ -	JFLAG_WAIT_BIND = 16,           /* ... for <bind> tag. */ +	JFLAG_WANT_BIND = 16,           /* ... for <bind> tag. */  	JFLAG_WANT_TYPING = 32,         /* Set if we ever sent a typing notification, this  	                                   activates all XEP-85 related code. */  	JFLAG_XMLCONSOLE = 64,          /* If the user added an xmlconsole buddy. */ +	JFLAG_STARTTLS_DONE = 128,      /* If a plaintext session was converted to TLS. */  } jabber_flags_t;  typedef enum @@ -83,7 +84,7 @@ struct jabber_data  	/* After changing one of these two (or the priority setting), call  	   presence_send_update() to inform the server about the changes. */ -	struct jabber_away_state *away_state; +	const struct jabber_away_state *away_state;  	char *away_message;  	md5_state_t cached_id_prefix; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 19a73b6a..185d3878 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -227,10 +227,9 @@ xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *  const struct jabber_away_state jabber_away_state_list[] =  {  	{ "away",  "Away" }, -	{ "chat",  "Free for Chat" }, +	{ "chat",  "Free for Chat" },   /* WTF actually uses this? */  	{ "dnd",   "Do not Disturb" },  	{ "xa",    "Extended Away" }, -	{ "",      "Online" },  	{ "",      NULL }  }; @@ -238,6 +237,9 @@ const struct jabber_away_state *jabber_away_state_by_code( char *code )  {  	int i; +	if( code == NULL ) +		return NULL; +	  	for( i = 0; jabber_away_state_list[i].full_name; i ++ )  		if( g_strcasecmp( jabber_away_state_list[i].code, code ) == 0 )  			return jabber_away_state_list + i; @@ -249,6 +251,9 @@ const struct jabber_away_state *jabber_away_state_by_name( char *name )  {  	int i; +	if( name == NULL ) +		return NULL; +	  	for( i = 0; jabber_away_state_list[i].full_name; i ++ )  		if( g_strcasecmp( jabber_away_state_list[i].full_name, name ) == 0 )  			return jabber_away_state_list + i; diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 939bc888..28aaea1b 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -189,13 +189,12 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )  	{  		int is_away = 0; -		if( send_presence->away_state && !( *send_presence->away_state->code == 0 || -		    strcmp( send_presence->away_state->code, "chat" ) == 0 ) ) +		if( send_presence->away_state && +		    strcmp( send_presence->away_state->code, "chat" ) != 0 )  			is_away = OPT_AWAY;  		imcb_buddy_status( ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away, -		                   ( is_away && send_presence->away_state ) ? -		                   send_presence->away_state->full_name : NULL, +		                   is_away ? send_presence->away_state->full_name : NULL,  		                   send_presence->away_message );  	} @@ -208,17 +207,15 @@ int presence_send_update( struct im_connection *ic )  {  	struct jabber_data *jd = ic->proto_data;  	struct xt_node *node, *cap; -	char *show = jd->away_state->code; -	char *status = jd->away_message;  	struct groupchat *c;  	int st;  	node = jabber_make_packet( "presence", NULL, NULL, NULL );  	xt_add_child( node, xt_new_node( "priority", set_getstr( &ic->acc->set, "priority" ), NULL ) ); -	if( show && *show ) -		xt_add_child( node, xt_new_node( "show", show, NULL ) ); -	if( status ) -		xt_add_child( node, xt_new_node( "status", status, NULL ) ); +	if( jd->away_state ) +		xt_add_child( node, xt_new_node( "show", jd->away_state->code, NULL ) ); +	if( jd->away_message ) +		xt_add_child( node, xt_new_node( "status", jd->away_message, NULL ) );  	/* This makes the packet slightly bigger, but clients interested in  	   capabilities can now cache the discovery info. This reduces the diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 046b2772..8930847d 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -26,6 +26,10 @@  #include "nogaim.h"  #include "msn.h" +int msn_chat_id; +GSList *msn_connections; +GSList *msn_switchboards; +  static char *msn_set_display_name( set_t *set, char *value );  static void msn_init( account_t *acc ) @@ -138,8 +142,9 @@ static GList *msn_away_states( struct im_connection *ic )  	int i;  	if( l == NULL ) -		for( i = 0; msn_away_state_list[i].number > -1; i ++ ) -			l = g_list_append( l, (void*) msn_away_state_list[i].name ); +		for( i = 0; *msn_away_state_list[i].code; i ++ ) +			if( *msn_away_state_list[i].name ) +				l = g_list_append( l, (void*) msn_away_state_list[i].name );  	return l;  } @@ -148,17 +153,14 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message )  {  	char buf[1024];  	struct msn_data *md = ic->proto_data; -	const struct msn_away_state *st; -	if( strcmp( state, GAIM_AWAY_CUSTOM ) == 0 ) -		st = msn_away_state_by_name( "Away" ); +	if( state ) +		md->away_state = msn_away_state_by_name( state ) ? : +		                 msn_away_state_list + 1;  	else -		st = msn_away_state_by_name( state ); -	 -	if( !st ) st = msn_away_state_list; -	md->away_state = st; +		md->away_state = msn_away_state_list; -	g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, st->code ); +	g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, md->away_state->code );  	msn_write( ic, buf, strlen( buf ) );  } diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 7c849acf..84914bc3 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -96,7 +96,6 @@ struct msn_switchboard  struct msn_away_state  { -	int number;  	char code[4];  	char name[16];  }; @@ -135,7 +134,7 @@ struct msn_handler_data  #define STATUS_SB_IM_SPARE	4	/* Make one-to-one conversation switchboard available again, invite failed. */  #define STATUS_SB_CHAT_SPARE	8	/* Same, but also for groupchats (not used yet). */ -int msn_chat_id; +extern int msn_chat_id;  extern const struct msn_away_state msn_away_state_list[];  extern const struct msn_status_code msn_status_code_list[]; @@ -144,8 +143,8 @@ extern const struct msn_status_code msn_status_code_list[];     is down already (for example, when an impatient user disabled the     connection), the callback should check whether it's still listed here     before doing *anything* else. */ -GSList *msn_connections; -GSList *msn_switchboards; +extern GSList *msn_connections; +extern GSList *msn_switchboards;  /* ns.c */  gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 58ad22f8..668a8b8a 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -170,9 +170,9 @@ char *msn_findheader( char *text, char *header, int len )  		while( i < len && ( text[i] == '\r' || text[i] == '\n' ) ) i ++;  		/* End of headers? */ -		if( strncmp( text + i - 2, "\n\n", 2 ) == 0 || -		    strncmp( text + i - 4, "\r\n\r\n", 4 ) == 0 || -		    strncmp( text + i - 2, "\r\r", 2 ) == 0 ) +		if( ( i >= 4 && strncmp( text + i - 4, "\r\n\r\n", 4 ) == 0 ) || +		    ( i >= 2 && ( strncmp( text + i - 2, "\n\n", 2 ) == 0 ||    +		                  strncmp( text + i - 2, "\r\r", 2 ) == 0 ) ) )  		{  			break;  		} @@ -373,6 +373,6 @@ void msn_msgq_purge( struct im_connection *ic, GSList **list )  	g_slist_free( *list );  	*list = NULL; -	imcb_log( ic, ret->str ); +	imcb_log( ic, "%s", ret->str );  	g_string_free( ret, TRUE );  } diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index fe48f96d..d78d753a 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -228,19 +228,26 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  				return( 0 );  			}  		} -		else if( num_parts == 7 && strcmp( cmd[2], "OK" ) == 0 ) +		else if( num_parts >= 7 && strcmp( cmd[2], "OK" ) == 0 )  		{  			set_t *s; -			http_decode( cmd[4] ); -			 -			strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) ); -			ic->displayname[sizeof(ic->displayname)-1] = 0; -			 -			if( ( s = set_find( &ic->acc->set, "display_name" ) ) ) +			if( num_parts == 7 )  			{ -				g_free( s->value ); -				s->value = g_strdup( cmd[4] ); +				http_decode( cmd[4] ); +				 +				strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) ); +				ic->displayname[sizeof(ic->displayname)-1] = 0; +				 +				if( ( s = set_find( &ic->acc->set, "display_name" ) ) ) +				{ +					g_free( s->value ); +					s->value = g_strdup( cmd[4] ); +				} +			} +			else +			{ +				imcb_log( ic, "Warning: Friendly name in server response was corrupted" );  			}  			imcb_log( ic, "Authenticated, getting buddy list" ); @@ -419,11 +426,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  		if( !st )  		{  			/* FIXME: Warn/Bomb about unknown away state? */ -			st = msn_away_state_list; +			st = msn_away_state_list + 1;  		} -		imcb_buddy_status( ic, cmd[3], OPT_LOGGED_IN | -		                   ( st->number ? OPT_AWAY : 0 ), st->name, NULL ); +		imcb_buddy_status( ic, cmd[3], OPT_LOGGED_IN |  +		                   ( st != msn_away_state_list ? OPT_AWAY : 0 ), +		                   st->name, NULL );  	}  	else if( strcmp( cmd[0], "FLN" ) == 0 )  	{ @@ -448,11 +456,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  		if( !st )  		{  			/* FIXME: Warn/Bomb about unknown away state? */ -			st = msn_away_state_list; +			st = msn_away_state_list + 1;  		} -		imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN | -		                   ( st->number ? OPT_AWAY : 0 ), st->name, NULL ); +		imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN |  +		                   ( st != msn_away_state_list ? OPT_AWAY : 0 ), +		                   st->name, NULL );  	}  	else if( strcmp( cmd[0], "RNG" ) == 0 )  	{ @@ -662,8 +671,8 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int  						imcb_log( ic, "The server is going down for maintenance in %s minutes.", arg1 );  				} -				if( arg1 ) g_free( arg1 ); -				if( mtype ) g_free( mtype ); +				g_free( arg1 ); +				g_free( mtype );  			}  			else if( g_strncasecmp( ct, "text/x-msmsgsprofile", 20 ) == 0 )  			{ @@ -671,25 +680,30 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int  			}  			else if( g_strncasecmp( ct, "text/x-msmsgsinitialemailnotification", 37 ) == 0 )  			{ -				char *inbox = msn_findheader( body, "Inbox-Unread:", blen ); -				char *folders = msn_findheader( body, "Folders-Unread:", blen ); -				 -				if( inbox && folders && set_getbool( &ic->acc->set, "mail_notifications" ) ) +				if( set_getbool( &ic->acc->set, "mail_notifications" ) )  				{ -					imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); +					char *inbox = msn_findheader( body, "Inbox-Unread:", blen ); +					char *folders = msn_findheader( body, "Folders-Unread:", blen ); + +					if( inbox && folders ) +						imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); +					 +					g_free( inbox ); +					g_free( folders );  				} -				 -				g_free( inbox ); -				g_free( folders );  			}  			else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 )  			{ -				char *from = msn_findheader( body, "From-Addr:", blen ); -				char *fromname = msn_findheader( body, "From:", blen ); -				 -				if( from && fromname && set_getbool( &ic->acc->set, "mail_notifications" ) ) +				if( set_getbool( &ic->acc->set, "mail_notifications" ) )  				{ -					imcb_log( ic, "Received an e-mail message from %s <%s>.", fromname, from ); +					char *from = msn_findheader( body, "From-Addr:", blen ); +					char *fromname = msn_findheader( body, "From:", blen ); +					 +					if( from && fromname ) +						imcb_log( ic, "Received an e-mail message from %s <%s>.", fromname, from ); + +					g_free( from ); +					g_free( fromname );  				}  			}  			else if( g_strncasecmp( ct, "text/x-msmsgsactivemailnotification", 35 ) == 0 ) diff --git a/protocols/msn/tables.c b/protocols/msn/tables.c index 5ba9ea73..42b12aa9 100644 --- a/protocols/msn/tables.c +++ b/protocols/msn/tables.c @@ -28,48 +28,37 @@  const struct msn_away_state msn_away_state_list[] =  { -	{  0, "NLN", "Available" }, -	{  1, "BSY", "Busy" }, -	{  3, "IDL", "Idle" }, -	{  5, "BRB", "Be Right Back" }, -	{  7, "AWY", "Away" }, -	{  9, "PHN", "On the Phone" }, -	{ 11, "LUN", "Out to Lunch" }, -	{ 13, "HDN", "Hidden" }, -	{ -1, "",    "" } +	{ "NLN", "" }, +	{ "AWY", "Away" }, +	{ "BSY", "Busy" }, +	{ "IDL", "Idle" }, +	{ "BRB", "Be Right Back" }, +	{ "PHN", "On the Phone" }, +	{ "LUN", "Out to Lunch" }, +	{ "HDN", "Hidden" }, +	{ "",    "" }  }; -const struct msn_away_state *msn_away_state_by_number( int number ) -{ -	int i; -	 -	for( i = 0; msn_away_state_list[i].number > -1; i ++ ) -		if( msn_away_state_list[i].number == number ) -			return( msn_away_state_list + i ); -	 -	return( NULL ); -} -  const struct msn_away_state *msn_away_state_by_code( char *code )  {  	int i; -	for( i = 0; msn_away_state_list[i].number > -1; i ++ ) +	for( i = 0; *msn_away_state_list[i].code; i ++ )  		if( g_strcasecmp( msn_away_state_list[i].code, code ) == 0 )  			return( msn_away_state_list + i ); -	return( NULL ); +	return NULL;  }  const struct msn_away_state *msn_away_state_by_name( char *name )  {  	int i; -	for( i = 0; msn_away_state_list[i].number > -1; i ++ ) +	for( i = 0; *msn_away_state_list[i].code; i ++ )  		if( g_strcasecmp( msn_away_state_list[i].name, name ) == 0 )  			return( msn_away_state_list + i ); -	return( NULL ); +	return NULL;  }  const struct msn_status_code msn_status_code_list[] = diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 21f7dcb1..c326e378 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -1,7 +1,7 @@    /********************************************************************\    * BitlBee -- An IRC to other IM-networks gateway                     *    *                                                                    * -  * Copyright 2002-2006 Wilmer van der Gaast and others                * +  * Copyright 2002-2010 Wilmer van der Gaast and others                *    \********************************************************************/  /* @@ -97,7 +97,19 @@ GList *protocols = NULL;  void register_protocol (struct prpl *p)  { -	protocols = g_list_append(protocols, p); +	int i; +	gboolean refused = global.conf->protocols != NULL; +  +	for (i = 0; global.conf->protocols && global.conf->protocols[i]; i++) + 	{ + 		if (g_strcasecmp(p->name, global.conf->protocols[i]) == 0) +			refused = FALSE; + 	} + +	if (refused) +		log_message(LOGLVL_WARNING, "Protocol %s disabled\n", p->name); +	else +		protocols = g_list_append(protocols, p);  }  struct prpl *find_protocol(const char *name) @@ -267,9 +279,8 @@ void imcb_connected( struct im_connection *ic )  	ic->keepalive = b_timeout_add( 60000, send_keepalive, ic );  	ic->flags |= OPT_LOGGED_IN; -	/* Also necessary when we're not away, at least for some of the -	   protocols. */ -	imc_set_away( ic, u->away ); +	/* Necessary to send initial presence status, even if we're not away. */ +	imc_away_send_update( ic );  	/* Apparently we're connected successfully, so reset the  	   exponential backoff timer. */ @@ -371,7 +382,7 @@ void imcb_ask( struct im_connection *ic, char *msg, void *data,  /* list.c */ -void imcb_add_buddy( struct im_connection *ic, char *handle, char *group ) +void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group )  {  	user_t *u;  	char nick[MAX_NICK_LENGTH+1], *s; @@ -445,9 +456,10 @@ struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle )  	return( b );  } -void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ) +void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname )  {  	user_t *u = user_findhandle( ic, handle ); +	char *set;  	if( !u || !realname ) return; @@ -460,9 +472,26 @@ void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname )  		if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) )  			imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname );  	} +	 +	set = set_getstr( &ic->acc->set, "nick_source" ); +	if( strcmp( set, "handle" ) != 0 ) +	{ +		char *name = g_strdup( realname ); +		 +		if( strcmp( set, "first_name" ) == 0 ) +		{ +			int i; +			for( i = 0; name[i] && !isspace( name[i] ); i ++ ) {} +			name[i] = '\0'; +		} +		 +		imcb_buddy_nick_hint( ic, handle, name ); +		 +		g_free( name ); +	}  } -void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group ) +void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group )  {  	user_t *u; @@ -472,7 +501,7 @@ void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group )  /* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM     modules to suggest a nickname for a handle. */ -void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ) +void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick )  {  	user_t *u = user_findhandle( ic, handle );  	char newnick[MAX_NICK_LENGTH+1], *orig_nick; @@ -617,11 +646,9 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,  	oa = u->away != NULL;  	oo = u->online; -	if( u->away ) -	{ -		g_free( u->away ); -		u->away = NULL; -	} +	g_free( u->away ); +	g_free( u->status_msg ); +	u->away = u->status_msg = NULL;  	if( ( flags & OPT_LOGGED_IN ) && !u->online )  	{ @@ -659,7 +686,10 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,  			u->away = g_strdup( "Away" );  		}  	} -	/* else waste_any_state_information_for_now(); */ +	else +	{ +		u->status_msg = g_strdup( message ); +	}  	/* LISPy... */  	if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) &&		/* Don't do a thing when user doesn't want it */ @@ -684,7 +714,7 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,  	}  } -void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, uint32_t flags, time_t sent_at ) +void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at )  {  	irc_t *irc = ic->irc;  	char *wrapped; @@ -817,7 +847,7 @@ void imcb_chat_free( struct groupchat *c )  	}  } -void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at ) +void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at )  {  	struct im_connection *ic = c->ic;  	char *wrapped; @@ -889,7 +919,7 @@ void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at  /* buddy_chat.c */ -void imcb_chat_add_buddy( struct groupchat *b, char *handle ) +void imcb_chat_add_buddy( struct groupchat *b, const char *handle )  {  	user_t *u = user_findhandle( b->ic, handle );  	int me = 0; @@ -924,7 +954,7 @@ void imcb_chat_add_buddy( struct groupchat *b, char *handle )  }  /* This function is one BIG hack... :-( EREWRITE */ -void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ) +void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason )  {  	user_t *u;  	int me = 0; @@ -1069,51 +1099,30 @@ int imc_chat_msg( struct groupchat *c, char *msg, int flags )  	return 1;  } -static char *imc_away_alias_find( GList *gcm, char *away ); +static char *imc_away_state_find( GList *gcm, char *away, char **message ); -int imc_set_away( struct im_connection *ic, char *away ) +int imc_away_send_update( struct im_connection *ic )  { -	GList *m, *ms; -	char *s; -	 -	if( !away ) away = ""; -	ms = m = ic->acc->prpl->away_states( ic ); +	char *away, *msg = NULL; -	while( m ) +	away = set_getstr( &ic->acc->set, "away" ) ? +	     : set_getstr( &ic->irc->set, "away" ); +	if( away && *away )  	{ -		if( *away ) -		{ -			if( g_strncasecmp( m->data, away, strlen( m->data ) ) == 0 ) -				break; -		} -		else -		{ -			if( g_strcasecmp( m->data, "Available" ) == 0 ) -				break; -			if( g_strcasecmp( m->data, "Online" ) == 0 ) -				break; -		} -		m = m->next; -	} -	 -	if( m ) -	{ -		ic->acc->prpl->set_away( ic, m->data, *away ? away : NULL ); +		GList *m = ic->acc->prpl->away_states( ic ); +		msg = ic->acc->flags & ACC_FLAG_AWAY_MESSAGE ? away : NULL; +		away = imc_away_state_find( m, away, &msg ) ? : m->data;  	} -	else +	else if( ic->acc->flags & ACC_FLAG_STATUS_MESSAGE )  	{ -		s = imc_away_alias_find( ms, away ); -		if( s ) -		{ -			ic->acc->prpl->set_away( ic, s, away ); -			if( set_getbool( &ic->irc->set, "debug" ) ) -				imcb_log( ic, "Setting away state to %s", s ); -		} -		else -			ic->acc->prpl->set_away( ic, GAIM_AWAY_CUSTOM, away ); +		away = NULL; +		msg = set_getstr( &ic->acc->set, "status" ) ? +		    : set_getstr( &ic->irc->set, "status" );  	} -	return( 1 ); +	ic->acc->prpl->set_away( ic, away, msg ); +	 +	return 1;  }  static char *imc_away_alias_list[8][5] = @@ -1128,16 +1137,33 @@ static char *imc_away_alias_list[8][5] =  	{ NULL }  }; -static char *imc_away_alias_find( GList *gcm, char *away ) +static char *imc_away_state_find( GList *gcm, char *away, char **message )  {  	GList *m;  	int i, j; +	for( m = gcm; m; m = m->next ) +		if( g_strncasecmp( m->data, away, strlen( m->data ) ) == 0 ) +		{ +			/* At least the Yahoo! module works better if message +			   contains no data unless it adds something to what +			   we have in state already. */ +			if( strlen( m->data ) == strlen( away ) ) +				*message = NULL; +			 +			return m->data; +		} +	  	for( i = 0; *imc_away_alias_list[i]; i ++ )  	{ +		int keep_message; +		  		for( j = 0; imc_away_alias_list[i][j]; j ++ )  			if( g_strncasecmp( away, imc_away_alias_list[i][j], strlen( imc_away_alias_list[i][j] ) ) == 0 ) +			{ +				keep_message = strlen( away ) != strlen( imc_away_alias_list[i][j] );  				break; +			}  		if( !imc_away_alias_list[i][j] )	/* If we reach the end, this row */  			continue;			/* is not what we want. Next!    */ @@ -1145,17 +1171,22 @@ static char *imc_away_alias_find( GList *gcm, char *away )  		/* Now find an entry in this row which exists in gcm */  		for( j = 0; imc_away_alias_list[i][j]; j ++ )  		{ -			m = gcm; -			while( m ) -			{ +			for( m = gcm; m; m = m->next )  				if( g_strcasecmp( imc_away_alias_list[i][j], m->data ) == 0 ) -					return( imc_away_alias_list[i][j] ); -				m = m->next; -			} +				{ +					if( !keep_message ) +						*message = NULL; +					 +					return imc_away_alias_list[i][j]; +				}  		} +		 +		/* No need to look further, apparently this state doesn't +		   have any good alias for this protocol. */ +		break;  	} -	return( NULL ); +	return NULL;  }  void imc_add_allow( struct im_connection *ic, char *handle ) diff --git a/protocols/nogaim.h b/protocols/nogaim.h index dc6154e2..a523a3a5 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -48,7 +48,6 @@  #define BUDDY_ALIAS_MAXLEN 388   /* because MSN names can be 387 characters */  #define WEBSITE "http://www.bitlbee.org/" -#define GAIM_AWAY_CUSTOM "Custom"  /* Sharing flags between all kinds of things. I just hope I won't hit any     limits before 32-bit machines become extinct. ;-) */ @@ -217,8 +216,8 @@ struct prpl {  	void (* chat_topic)	(struct groupchat *, char *topic);  	/* You can tell what away states your protocol supports, so that -	 * BitlBee will try to map the IRC away reasons to them, or use -	 * GAIM_AWAY_CUSTOM when calling skype_set_away(). */ +	 * BitlBee will try to map the IRC away reasons to them. If your +	 * protocol doesn't have any, just return one generic "Away". */  	GList *(* away_states)(struct im_connection *ic);  	/* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* @@ -275,11 +274,11 @@ G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, const char *handle,  /* This function should be called for each handle which are visible to the   * user, usually after a login, or if the user added a buddy and the IM   * server confirms that the add was successful. Don't forget to do this! */ -G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, char *handle, char *group ); -G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group ); +G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group ); +G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group );  G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ); -G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ); -G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ); +G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname ); +G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick );  /* Buddy activity */  /* To manipulate the status of a handle. @@ -289,7 +288,7 @@ G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handl  G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message );  /* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle );  /* Call when a handle says something. 'flags' and 'sent_at may be just 0. */ -G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, uint32_t flags, time_t sent_at ); +G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at );  G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags );  G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle ); @@ -302,11 +301,11 @@ G_MODULE_EXPORT void imcb_chat_invited( struct im_connection *ic, char *handle,   *   the user her/himself. At that point the group chat will be visible to the   *   user, too. */  G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle ); -G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle ); +G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, const char *handle );  /* To remove a handle from a group chat. Reason can be NULL. */ -G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ); +G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason );  /* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */ -G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at ); +G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at );  /* System messages specific to a groupchat, so they can be displayed in the right context. */  G_MODULE_EXPORT void imcb_chat_log( struct groupchat *c, char *format, ... ) G_GNUC_PRINTF( 2, 3 );  /* To tell BitlBee 'who' changed the topic of 'c' to 'topic'. */ @@ -314,7 +313,7 @@ G_MODULE_EXPORT void imcb_chat_topic( struct groupchat *c, char *who, char *topi  G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c );  /* Actions, or whatever. */ -int imc_set_away( struct im_connection *ic, char *away ); +int imc_away_send_update( struct im_connection *ic );  int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags );  int imc_chat_msg( struct groupchat *c, char *msg, int flags ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 1118c26d..f0e65f9a 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -379,6 +379,8 @@ static void oscar_init(account_t *acc)  		s = set_add( &acc->set, "web_aware", "false", set_eval_bool, acc );  		s->flags |= ACC_SET_OFFLINE_ONLY;  	} +	 +	acc->flags |= ACC_FLAG_AWAY_MESSAGE;  }  static void oscar_login(account_t *acc) { @@ -1951,6 +1953,8 @@ static void oscar_get_away(struct im_connection *g, char *who) {  static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, const char *state, const char *message)  { +	if (state == NULL) +		state = "";  	if (!g_strcasecmp(state, _("Visible"))) {  		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); @@ -1958,7 +1962,9 @@ static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od,  	} else if (!g_strcasecmp(state, _("Invisible"))) {  		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE);  		return; -	} /* else... */ +	} else if (message == NULL) { +		message = state; +	}  	if (od->rights.maxawaymsglen == 0)  		imcb_error(ic, "oscar_set_away_aim called before locate rights received"); @@ -2001,7 +2007,7 @@ static void oscar_set_away_icq(struct im_connection *ic, struct oscar_data *od,  		no_message = TRUE;  	} -	if (!g_strcasecmp(state, "Online")) { +	if (state == NULL) {  		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);  	} else if (!g_strcasecmp(state, "Away")) {  		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY); @@ -2026,7 +2032,7 @@ static void oscar_set_away_icq(struct im_connection *ic, struct oscar_data *od,  	} else if (!g_strcasecmp(state, "Invisible")) {  		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE);  		ic->away = g_strdup(msg); -	} else if (!g_strcasecmp(state, GAIM_AWAY_CUSTOM)) { +	} else {  	 	if (no_message) {  			aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);  		} else { @@ -2275,20 +2281,21 @@ static void oscar_rem_deny(struct im_connection *ic, char *who) {  static GList *oscar_away_states(struct im_connection *ic)  {  	struct oscar_data *od = ic->proto_data; -	GList *m = NULL; - -	if (!od->icq) -		return g_list_append(m, GAIM_AWAY_CUSTOM); -	m = g_list_append(m, "Online"); -	m = g_list_append(m, "Away"); -	m = g_list_append(m, "Do Not Disturb"); -	m = g_list_append(m, "Not Available"); -	m = g_list_append(m, "Occupied"); -	m = g_list_append(m, "Free For Chat"); -	m = g_list_append(m, "Invisible"); - -	return m; +	if (od->icq) { +		static GList *m = NULL; +		m = g_list_append(m, "Away"); +		m = g_list_append(m, "Do Not Disturb"); +		m = g_list_append(m, "Not Available"); +		m = g_list_append(m, "Occupied"); +		m = g_list_append(m, "Free For Chat"); +		m = g_list_append(m, "Invisible"); +		return m; +	} else { +		static GList *m = NULL; +		m = g_list_append(m, "Away"); +		return m; +	}  }  static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index a1755cc9..1bfc2e59 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -854,55 +854,6 @@ static int is_same_bud(const void * a, const void * b) {  	return strcmp(subject->id, object->id);  } -static YList * bud_str2list(char *rawlist) -{ -	YList * l = NULL; - -	char **lines; -	char **split; -	char **buddies; -	char **tmp, **bud; - -	lines = y_strsplit(rawlist, "\n", -1); -	for (tmp = lines; *tmp; tmp++) { -		struct yahoo_buddy *newbud; - -		split = y_strsplit(*tmp, ":", 2); -		if (!split) -			continue; -		if (!split[0] || !split[1]) { -			y_strfreev(split); -			continue; -		} -		buddies = y_strsplit(split[1], ",", -1); - -		for (bud = buddies; bud && *bud; bud++) { -			newbud = y_new0(struct yahoo_buddy, 1); -			newbud->id = strdup(*bud); -			newbud->group = strdup(split[0]); - -			if(y_list_find_custom(l, newbud, is_same_bud)) { -				FREE(newbud->id); -				FREE(newbud->group); -				FREE(newbud); -				continue; -			} - -			newbud->real_name = NULL; - -			l = y_list_append(l, newbud); - -			NOTICE(("Added buddy %s to group %s", newbud->id, newbud->group)); -		} - -		y_strfreev(buddies); -		y_strfreev(split); -	} -	y_strfreev(lines); - -	return l; -} -  static char * getcookie(char *rawcookie)  {  	char * cookie=NULL; @@ -1359,140 +1310,154 @@ static void yahoo_process_message(struct yahoo_input_data *yid, struct yahoo_pac  	y_list_free(messages);  } - -static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +static void yahoo_process_status(struct yahoo_input_data *yid, +	struct yahoo_packet *pkt)  {  	YList *l;  	struct yahoo_data *yd = yid->yd; -	struct user -	{ -		char *name;	/* 7	name */ -		int   state;	/* 10	state */ -		int   flags;	/* 13	flags, bit 0 = pager, bit 1 = chat, bit 2 = game */ -		int   mobile;	/* 60	mobile */ -		char *msg;	/* 19	custom status message */ -		int   away;	/* 47	away (or invisible)*/ -		int   buddy_session;	/* 11	state */ -		int   f17;	/* 17	in chat? then what about flags? */ -		int   idle;	/* 137	seconds idle */ -		int   f138;	/* 138	state */ -		char *f184;	/* 184	state */ -		int   f192;	/* 192	state */ -		int   f10001;	/* 10001	state */ -		int   f10002;	/* 10002	state */ -		int   f198;	/* 198	state */ -		char *f197;	/* 197	state */ -		char *f205;	/* 205	state */ -		int   f213;	/* 213	state */ -	} *u; +	struct yahoo_process_status_entry *u;  	YList *users = 0; -	 +  	if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { -		YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_DUPL, NULL); +		YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, +			YAHOO_LOGIN_DUPL, NULL);  		return;  	} +	/* Status updates may be spread accross multiple packets and not +	   even on buddy boundaries, so keeping some state is important. +	   So, continue where we left off, and only add a user entry to +	   the list once it's complete (301-315 End buddy). */ +	u = yd->half_user; +  	for (l = pkt->hash; l; l = l->next) {  		struct yahoo_pair *pair = l->data;  		switch (pair->key) { -		case 0: /* we won't actually do anything with this */ +		case 300:	/* Begin buddy */ +			if (!strcmp(pair->value, "315") && !u) { +				u = yd->half_user = y_new0(struct yahoo_process_status_entry, 1); +			} +			break; +		case 301:	/* End buddy */ +			if (!strcmp(pair->value, "315") && u) { +				/* Sometimes user info comes in an odd format with no +				   "begin buddy" but *with* an "end buddy". Don't add +				   it twice. */ +				if (!y_list_find(users, u)) +					users = y_list_prepend(users, u); +				u = yd->half_user = NULL; +			} +			break; +		case 0:	/* we won't actually do anything with this */  			NOTICE(("key %d:%s", pair->key, pair->value));  			break; -		case 1: /* we don't get the full buddy list here. */ +		case 1:	/* we don't get the full buddy list here. */  			if (!yd->logged_in) { -				yd->logged_in = TRUE; -				if(yd->current_status < 0) +				yd->logged_in = 1; +				if (yd->current_status < 0)  					yd->current_status = yd->initial_status; -				YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL); +				YAHOO_CALLBACK(ext_yahoo_login_response) (yd-> +					client_id, YAHOO_LOGIN_OK, NULL);  			}  			break; -		case 8: /* how many online buddies we have */ +		case 8:	/* how many online buddies we have */  			NOTICE(("key %d:%s", pair->key, pair->value));  			break; -		case 7: /* the current buddy */ -			u = y_new0(struct user, 1); +		case 7:	/* the current buddy */ +			if (!u) { +				/* This will only happen in case of a single level message */ +				u = y_new0(struct yahoo_process_status_entry, 1); +				users = y_list_prepend(users, u); +			}  			u->name = pair->value; -			users = y_list_prepend(users, u);  			break; -		case 10: /* state */ -			((struct user*)users->data)->state = strtol(pair->value, NULL, 10); +		case 10:	/* state */ +			u->state = strtol(pair->value, NULL, 10);  			break; -		case 19: /* custom status message */ -			((struct user*)users->data)->msg = pair->value; +		case 19:	/* custom status message */ +			u->msg = pair->value;  			break; -		case 47: /* is it an away message or not */ -			((struct user*)users->data)->away = atoi(pair->value); +		case 47:	/* is it an away message or not. Not applicable for YMSG16 anymore */ +			u->away = atoi(pair->value);  			break; -		case 137: /* seconds idle */ -			((struct user*)users->data)->idle = atoi(pair->value); +		case 137:	/* seconds idle */ +			u->idle = atoi(pair->value);  			break; -		case 11: /* this is the buddy's session id */ -			((struct user*)users->data)->buddy_session = atoi(pair->value); +		case 11:	/* this is the buddy's session id */ +			u->buddy_session = atoi(pair->value);  			break; -		case 17: /* in chat? */ -			((struct user*)users->data)->f17 = atoi(pair->value); +		case 17:	/* in chat? */ +			u->f17 = atoi(pair->value);  			break; -		case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ -			((struct user*)users->data)->flags = atoi(pair->value); +		case 13:	/* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ +			u->flags = atoi(pair->value);  			break; -		case 60: /* SMS -> 1 MOBILE USER */ +		case 60:	/* SMS -> 1 MOBILE USER */  			/* sometimes going offline makes this 2, but invisible never sends it */ -			((struct user*)users->data)->mobile = atoi(pair->value); +			u->mobile = atoi(pair->value);  			break;  		case 138: -			((struct user*)users->data)->f138 = atoi(pair->value); +			u->f138 = atoi(pair->value);  			break;  		case 184: -			((struct user*)users->data)->f184 = pair->value; +			u->f184 = pair->value;  			break;  		case 192: -			((struct user*)users->data)->f192 = atoi(pair->value); +			u->f192 = atoi(pair->value);  			break;  		case 10001: -			((struct user*)users->data)->f10001 = atoi(pair->value); +			u->f10001 = atoi(pair->value);  			break;  		case 10002: -			((struct user*)users->data)->f10002 = atoi(pair->value); +			u->f10002 = atoi(pair->value);  			break;  		case 198: -			((struct user*)users->data)->f198 = atoi(pair->value); +			u->f198 = atoi(pair->value);  			break;  		case 197: -			((struct user*)users->data)->f197 = pair->value; +			u->f197 = pair->value;  			break;  		case 205: -			((struct user*)users->data)->f205 = pair->value; +			u->f205 = pair->value;  			break;  		case 213: -			((struct user*)users->data)->f213 = atoi(pair->value); +			u->f213 = atoi(pair->value);  			break; -		case 16: /* Custom error message */ -			YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0, E_CUSTOM); +		case 16:	/* Custom error message */ +			YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id, +				pair->value, 0, E_CUSTOM);  			break;  		default: -			WARNING(("unknown status key %d:%s", pair->key, pair->value)); +			WARNING(("unknown status key %d:%s", pair->key, +					pair->value));  			break;  		}  	} -	 +  	while (users) {  		YList *t = users; -		struct user *u = users->data; +		struct yahoo_process_status_entry *u = users->data;  		if (u->name != NULL) { -			if (pkt->service == YAHOO_SERVICE_LOGOFF) { /* || u->flags == 0) { Not in YMSG16 */ -				YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0); +			if (pkt->service == +				YAHOO_SERVICE_LOGOFF +				/*|| u->flags == 0 No flags for YMSG16 */ ) { +				YAHOO_CALLBACK(ext_yahoo_status_changed) (yd-> +					client_id, u->name, +					YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0);  			} else {  				/* Key 47 always seems to be 1 for YMSG16 */ -				if(!u->state) +				if (!u->state)  					u->away = 0;  				else  					u->away = 1; -				YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, u->state, u->msg, u->away, u->idle, u->mobile); +				YAHOO_CALLBACK(ext_yahoo_status_changed) (yd-> +					client_id, u->name, u->state, u->msg, +					u->away, u->idle, u->mobile);  			}  		} @@ -1502,7 +1467,8 @@ static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_pack  	}  } -static void yahoo_process_buddy_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +static void yahoo_process_buddy_list(struct yahoo_input_data *yid, +	struct yahoo_packet *pkt)  {  	struct yahoo_data *yd = yid->yd;  	YList *l; @@ -1514,134 +1480,117 @@ static void yahoo_process_buddy_list(struct yahoo_input_data *yid, struct yahoo_  	for (l = pkt->hash; l; l = l->next) {  		struct yahoo_pair *pair = l->data; -		switch(pair->key) { +		switch (pair->key) {  		case 300:  		case 301:  		case 302: +			break;	/* Separators. Our logic does not need them */  		case 303: -			if ( 315 == atoi(pair->value) ) +			if (318 == atoi(pair->value))  				last_packet = 1;  			break;  		case 65: -			g_free(cur_group);  			cur_group = strdup(pair->value);  			break;  		case 7:  			newbud = y_new0(struct yahoo_buddy, 1);  			newbud->id = strdup(pair->value); -			if(cur_group) +			if (cur_group)  				newbud->group = strdup(cur_group); -			else { -				struct yahoo_buddy *lastbud = (struct yahoo_buddy *)y_list_nth( -								yd->buddies, y_list_length(yd->buddies)-1)->data; +			else if (yd->buddies) { +				struct yahoo_buddy *lastbud = +					(struct yahoo_buddy *)y_list_nth(yd-> +					buddies, +					y_list_length(yd->buddies) - 1)->data;  				newbud->group = strdup(lastbud->group); -			} +			} else +				newbud->group = strdup("Buddies");  			yd->buddies = y_list_append(yd->buddies, newbud);  			break;  		}  	} -	 -	g_free(cur_group);  	/* we could be getting multiple packets here */ -	if (last_packet) +	if (pkt->hash && !last_packet)  		return; -	YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies); +	YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, yd->buddies); -	/*** We login at the very end of the packet communication */ +	/* Logged in */  	if (!yd->logged_in) { -		yd->logged_in = TRUE; -		if(yd->current_status < 0) +		yd->logged_in = 1; +		if (yd->current_status < 0)  			yd->current_status = yd->initial_status; -		YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL); +		YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, +			YAHOO_LOGIN_OK, NULL); + +		/* +		yahoo_set_away(yd->client_id, yd->initial_status, NULL, +			(yd->initial_status == YAHOO_STATUS_AVAILABLE) ? 0 : 1); + +		yahoo_get_yab(yd->client_id); +		*/  	} +  } -static void yahoo_process_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +static void yahoo_process_list(struct yahoo_input_data *yid, +	struct yahoo_packet *pkt)  {  	struct yahoo_data *yd = yid->yd;  	YList *l; -	if (!yd->logged_in) { -		yd->logged_in = TRUE; -		if(yd->current_status < 0) -			yd->current_status = yd->initial_status; -		YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL); -	} - +	/* we could be getting multiple packets here */  	for (l = pkt->hash; l; l = l->next) {  		struct yahoo_pair *pair = l->data; -		switch(pair->key) { -		case 87: /* buddies */ -			if(!yd->rawbuddylist) -				yd->rawbuddylist = strdup(pair->value); -			else { -				yd->rawbuddylist = y_string_append(yd->rawbuddylist, pair->value); -			} -			break; - -		case 88: /* ignore list */ -			if(!yd->ignorelist) -				yd->ignorelist = strdup("Ignore:"); -			yd->ignorelist = y_string_append(yd->ignorelist, pair->value); -			break; - -		case 89: /* identities */ +		switch (pair->key) { +		case 89:	/* identities */  			{ -			char **identities = y_strsplit(pair->value, ",", -1); -			int i; -			for(i=0; identities[i]; i++) -				yd->identities = y_list_append(yd->identities,  +				char **identities = +					y_strsplit(pair->value, ",", -1); +				int i; +				for (i = 0; identities[i]; i++) +					yd->identities = +						y_list_append(yd->identities,  						strdup(identities[i])); -			y_strfreev(identities); +				y_strfreev(identities);  			} -			YAHOO_CALLBACK(ext_yahoo_got_identities)(yd->client_id, yd->identities); +			YAHOO_CALLBACK(ext_yahoo_got_identities) (yd->client_id, +				yd->identities);  			break; -		case 59: /* cookies */ -			if(yd->ignorelist) { -				yd->ignore = bud_str2list(yd->ignorelist); -				FREE(yd->ignorelist); -				YAHOO_CALLBACK(ext_yahoo_got_ignore)(yd->client_id, yd->ignore); -			} -			if(yd->rawbuddylist) { -				yd->buddies = bud_str2list(yd->rawbuddylist); -				FREE(yd->rawbuddylist); -				YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies); -			} - -			if(pair->value[0]=='Y') { +		case 59:	/* cookies */ +			if (pair->value[0] == 'Y') {  				FREE(yd->cookie_y);  				FREE(yd->login_cookie);  				yd->cookie_y = getcookie(pair->value);  				yd->login_cookie = getlcookie(yd->cookie_y); -			} else if(pair->value[0]=='T') { +			} else if (pair->value[0] == 'T') {  				FREE(yd->cookie_t);  				yd->cookie_t = getcookie(pair->value); -			} else if(pair->value[0]=='C') { +			} else if (pair->value[0] == 'C') {  				FREE(yd->cookie_c);  				yd->cookie_c = getcookie(pair->value); -			}  - -			if(yd->cookie_y && yd->cookie_t) -				YAHOO_CALLBACK(ext_yahoo_got_cookies)(yd->client_id); +			}  			break; -		case 3: /* my id */ -		case 90: /* 1 */ -		case 100: /* 0 */ -		case 101: /* NULL */ -		case 102: /* NULL */ -		case 93: /* 86400/1440 */ +		case 3:	/* my id */ +		case 90:	/* 1 */ +		case 100:	/* 0 */ +		case 101:	/* NULL */ +		case 102:	/* NULL */ +		case 93:	/* 86400/1440 */  			break;  		}  	} + +	if (yd->cookie_y && yd->cookie_t)	/* We don't get cookie_c anymore */ +		YAHOO_CALLBACK(ext_yahoo_got_cookies) (yd->client_id);  }  static void yahoo_process_verify(struct yahoo_input_data *yid, struct yahoo_packet *pkt) @@ -2392,10 +2341,16 @@ static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had)  static void yahoo_https_auth_token_finish(struct http_request *req)  {  	struct yahoo_https_auth_data *had = req->data; -	struct yahoo_input_data *yid = had->yid; -	struct yahoo_data *yd = yid->yd; +	struct yahoo_input_data *yid; +	struct yahoo_data *yd;  	int st; +	if (y_list_find(inputs, had->yid) == NULL) +		return; +	 +	yid = had->yid; +	yd = yid->yd; +	  	if (req->status_code != 200) {  		YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, 2000 + req->status_code, NULL);  		goto fail; @@ -2435,12 +2390,18 @@ static void yahoo_https_auth_init(struct yahoo_https_auth_data *had)  static void yahoo_https_auth_finish(struct http_request *req)  {  	struct yahoo_https_auth_data *had = req->data; -	struct yahoo_input_data *yid = had->yid; -	struct yahoo_data *yd = yid->yd; +	struct yahoo_input_data *yid; +	struct yahoo_data *yd;  	struct yahoo_packet *pack; -	char *crumb; +	char *crumb = NULL;  	int st; +	if (y_list_find(inputs, had->yid) == NULL) +		return; +	 +	yid = had->yid; +	yd = yid->yd; +	  	md5_byte_t result[16];  	md5_state_t ctx; @@ -4079,14 +4040,8 @@ void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away)  		return;  	yd = yid->yd; -  	old_status = yd->current_status; - -	if (msg && strncmp(msg,"Invisible",9)) { -		yd->current_status = YAHOO_STATUS_CUSTOM; -	} else { -		yd->current_status = state; -	} +	yd->current_status = state;  	/* Thank you libpurple :) */  	if (yd->current_status == YAHOO_STATUS_INVISIBLE) { @@ -4101,15 +4056,8 @@ void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away)  	pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, yd->current_status, yd->session_id);  	snprintf(s, sizeof(s), "%d", yd->current_status);  	yahoo_packet_hash(pkt, 10, s); -	  -	if (yd->current_status == YAHOO_STATUS_CUSTOM) { -		yahoo_packet_hash(pkt, 19, msg); -	} else { -		yahoo_packet_hash(pkt, 19, ""); -	} -	 +	yahoo_packet_hash(pkt, 19, msg && state == YAHOO_STATUS_CUSTOM ? msg : "");  	yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0"); -  	yahoo_send_packet(yid, pkt, 0);  	yahoo_packet_free(pkt); diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index ac57d4b6..b61f6ff9 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -129,6 +129,8 @@ static char *byahoo_strip( const char *in )  static void byahoo_init( account_t *acc )  {  	set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); +	 +	acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;  }  static void byahoo_login( account_t *acc ) @@ -196,29 +198,12 @@ static int byahoo_send_typing( struct im_connection *ic, char *who, int typing )  static void byahoo_set_away( struct im_connection *ic, char *state, char *msg )  {  	struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; -	char *away; -	 -	away = NULL; -	if( state && msg && g_strcasecmp( state, msg ) != 0 ) +	if( state && msg == NULL )  	{ -		yd->current_status = YAHOO_STATUS_CUSTOM; -		away = ""; -	} -	else if( state ) -	{ -		/* Set msg to NULL since (if it isn't NULL already) it's equal -		   to state. msg must be empty if we want to use an existing -		   away state. */ -		msg = NULL; -		 -		away = ""; -		if( g_strcasecmp( state, "Available" ) == 0 ) -		{ -			yd->current_status = YAHOO_STATUS_AVAILABLE; -			away = NULL; -		} -		else if( g_strcasecmp( state, "Be Right Back" ) == 0 ) +		/* Use these states only if msg doesn't contain additional +		   info since away messages are only supported with CUSTOM. */ +		if( g_strcasecmp( state, "Be Right Back" ) == 0 )  			yd->current_status = YAHOO_STATUS_BRB;  		else if( g_strcasecmp( state, "Busy" ) == 0 )  			yd->current_status = YAHOO_STATUS_BUSY; @@ -238,17 +223,15 @@ static void byahoo_set_away( struct im_connection *ic, char *state, char *msg )  			yd->current_status = YAHOO_STATUS_STEPPEDOUT;  		else if( g_strcasecmp( state, "Invisible" ) == 0 )  			yd->current_status = YAHOO_STATUS_INVISIBLE; -		else if( g_strcasecmp( state, GAIM_AWAY_CUSTOM ) == 0 ) -		{ -			yd->current_status = YAHOO_STATUS_AVAILABLE; -			 -			away = NULL; -		} +		else +			yd->current_status = YAHOO_STATUS_CUSTOM;  	} +	else if( msg ) +		yd->current_status = YAHOO_STATUS_CUSTOM;  	else  		yd->current_status = YAHOO_STATUS_AVAILABLE; -	yahoo_set_away( yd->y2_id, yd->current_status, msg, away != NULL ? 2 : 0 ); +	yahoo_set_away( yd->y2_id, yd->current_status, msg, state ? 2 : 0 );  }  static GList *byahoo_away_states( struct im_connection *ic ) @@ -257,7 +240,6 @@ static GList *byahoo_away_states( struct im_connection *ic )  	if( m == NULL )  	{ -		m = g_list_append( m, "Available" );  		m = g_list_append( m, "Be Right Back" );  		m = g_list_append( m, "Busy" );  		m = g_list_append( m, "Not At Home" ); @@ -268,7 +250,6 @@ static GList *byahoo_away_states( struct im_connection *ic )  		m = g_list_append( m, "Out To Lunch" );  		m = g_list_append( m, "Stepped Out" );  		m = g_list_append( m, "Invisible" ); -		m = g_list_append( m, GAIM_AWAY_CUSTOM );  	}  	return m; diff --git a/protocols/yahoo/yahoo2_types.h b/protocols/yahoo/yahoo2_types.h index 3507e13a..f05acb3c 100644 --- a/protocols/yahoo/yahoo2_types.h +++ b/protocols/yahoo/yahoo2_types.h @@ -195,6 +195,8 @@ struct yahoo_data {  	char  *ignorelist;  	void  *server_settings; +	 +	struct yahoo_process_status_entry *half_user;  };  struct yab { @@ -260,6 +262,27 @@ struct yahoo_chat_member {  	char *location;  }; +struct yahoo_process_status_entry { +	char *name;	/* 7      name */ +	int state;	/* 10     state */ +	int flags;	/* 13     flags, bit 0 = pager, bit 1 = chat, bit 2 = game */ +	int mobile;	/* 60     mobile */ +	char *msg;	/* 19     custom status message */ +	int away;	/* 47     away (or invisible) */ +	int buddy_session; /* 11  state */ +	int f17;	/* 17     in chat? then what about flags? */ +	int idle;	/* 137    seconds idle */ +	int f138;	/* 138    state */ +	char *f184;	/* 184    state */ +	int f192;	/* 192    state */ +	int f10001;	/* 10001  state */ +	int f10002;	/* 10002  state */ +	int f198;	/* 198    state */ +	char *f197;	/* 197    state */ +	char *f205;	/* 205    state */ +	int f213;	/* 213    state */ +}; +  #ifdef __cplusplus  }  #endif | 
