diff options
Diffstat (limited to 'protocols')
| -rw-r--r-- | protocols/jabber/io.c | 38 | ||||
| -rw-r--r-- | protocols/jabber/iq.c | 31 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 5 | ||||
| -rw-r--r-- | protocols/msn/msn.c | 4 | ||||
| -rw-r--r-- | protocols/msn/msn.h | 6 | ||||
| -rw-r--r-- | protocols/msn/msn_util.c | 6 | ||||
| -rw-r--r-- | protocols/msn/ns.c | 25 | ||||
| -rw-r--r-- | protocols/nogaim.c | 50 | ||||
| -rw-r--r-- | protocols/nogaim.h | 16 | ||||
| -rw-r--r-- | protocols/yahoo/libyahoo2.c | 332 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo2_types.h | 23 | 
11 files changed, 272 insertions, 264 deletions
| diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 3b0ef3ef..bff4e6c8 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -374,39 +374,23 @@ 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( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WANT_BIND | JFLAG_WANT_SESSION ) ) == 0 )  	{  		if( !jabber_get_roster( ic ) )  			return XT_ABORT;  	} +	else if( jd->flags & JFLAG_AUTHENTICATED ) +	{ +		return jabber_pkt_bind_sess( ic, NULL, NULL ); +	}  	return XT_HANDLED;  } @@ -440,6 +424,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 +515,10 @@ gboolean jabber_start_stream( struct im_connection *ic )  	if( jd->r_inpa <= 0 )  		jd->r_inpa = b_input_add( jd->fd, B_EV_IO_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..21e52da6 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -297,24 +297,43 @@ 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; +		jd->flags &= ~JFLAG_WANT_BIND;  	} -	else +	else if( node && ( c = xt_find_node( node->children, "session" ) ) ) +	{ +		jd->flags &= ~JFLAG_WANT_SESSION; +	} +	 +	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 ); +	} +	else if( jd->flags & JFLAG_WANT_SESSION ) +	{ +		reply = xt_new_node( "session", NULL, NULL ); +		xt_add_attr( reply, "xmlns", XMLNS_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.h b/protocols/jabber/jabber.h index 7bb66e0e..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 diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index e12fb3a9..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 ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 333ae7f0..84914bc3 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -134,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[]; @@ -143,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 6b12217b..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;  		} diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index b2b9cf81..9c4e1357 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" ); diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 1f46926a..96c2f512 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -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) @@ -378,7 +390,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; @@ -452,9 +464,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; @@ -467,9 +480,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; @@ -479,7 +509,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; @@ -691,7 +721,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; @@ -824,7 +854,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; @@ -896,7 +926,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; @@ -931,7 +961,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; @@ -1080,7 +1110,7 @@ static char *imc_away_state_find( GList *gcm, char *away, char **message );  int imc_away_send_update( struct im_connection *ic )  { -	char *away, *msg; +	char *away, *msg = NULL;  	away = set_getstr( &ic->acc->set, "away" ) ?  	     : set_getstr( &ic->irc->set, "away" ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 54761039..ff24acc2 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -275,11 +275,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 +289,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 +302,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'. */ diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index 721f4b7c..5b2ff44e 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,150 @@ 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) { +				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 +1463,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,141 +1476,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 { -				YList *last; -				struct yahoo_buddy *lastbud; -				 -				for (last = yd->buddies; last && last->next; last = last->next); -				if (last) { -					lastbud = last->data; -					newbud->group = strdup(lastbud->group); -				} else { -					newbud->group = strdup("Buddies"); -				} -			} +			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) 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 | 
