diff options
| -rw-r--r-- | doc/user-guide/commands.xml | 4 | ||||
| -rw-r--r-- | irc.h | 1 | ||||
| -rw-r--r-- | irc_channel.c | 25 | ||||
| -rw-r--r-- | irc_im.c | 16 | ||||
| -rw-r--r-- | irc_send.c | 7 | ||||
| -rw-r--r-- | irc_user.c | 6 | ||||
| -rw-r--r-- | lib/misc.c | 80 | ||||
| -rw-r--r-- | lib/misc.h | 3 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 18 | ||||
| -rw-r--r-- | protocols/twitter/twitter.c | 2 | ||||
| -rw-r--r-- | protocols/twitter/twitter_lib.c | 7 | ||||
| -rw-r--r-- | root_commands.c | 12 | ||||
| -rw-r--r-- | sock.h | 2 | 
13 files changed, 123 insertions, 60 deletions
| diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 7cedffc3..8bbada95 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -1431,11 +1431,11 @@  	<bitlbee-command name="blist">  		<syntax>blist [all|online|offline|away]</syntax> -		<short-description>List all the buddies in your contact list</short-description> +		<short-description>List all the buddies in the current channel</short-description>  		<description>  			<para> -				You can get a better readable buddy list using the <emphasis>blist</emphasis> command. If you want a complete list (including the offline users) you can use the <emphasis>all</emphasis> argument. +				You can get a more readable buddy list using the <emphasis>blist</emphasis> command. If you want a complete list (including the offline users) you can use the <emphasis>all</emphasis> argument.  			</para>  		</description> @@ -257,6 +257,7 @@ void irc_channel_name_strip( char *name );  int irc_channel_name_cmp( const char *a_, const char *b_ );  void irc_channel_update_ops( irc_channel_t *ic, char *value );  char *set_eval_irc_channel_ops( struct set *set, char *value ); +gboolean irc_channel_wants_user( irc_channel_t *ic, irc_user_t *iu );  /* irc_commands.c */  void irc_exec( irc_t *irc, char **cmd ); diff --git a/irc_channel.c b/irc_channel.c index 0498cffa..118fef74 100644 --- a/irc_channel.c +++ b/irc_channel.c @@ -725,6 +725,31 @@ fail:  	return SET_INVALID;	  } +/* Figure out if a channel is supposed to have the user, assuming s/he is +   online or otherwise also selected by the show_users setting. Only works +   for control channels, but does *not* check if this channel is of that +   type. Beware! */ +gboolean irc_channel_wants_user( irc_channel_t *ic, irc_user_t *iu ) +{ +	struct irc_control_channel *icc = ic->data; +	 +	if( iu->bu == NULL ) +		return FALSE; +	 +	switch( icc->type ) +	{ +	case IRC_CC_TYPE_GROUP: +		return iu->bu->group == icc->group; +	case IRC_CC_TYPE_ACCOUNT: +		return iu->bu->ic->acc == icc->account; +	case IRC_CC_TYPE_PROTOCOL: +		return iu->bu->ic->acc->prpl == icc->protocol; +	case IRC_CC_TYPE_DEFAULT: +	default: +		return TRUE; +	} +} +  static gboolean control_channel_free( irc_channel_t *ic )  {  	struct irc_control_channel *icc = ic->data; @@ -140,9 +140,7 @@ static gboolean bee_irc_user_status( bee_t *bee, bee_user_t *bu, bee_user_t *old  void bee_irc_channel_update( irc_t *irc, irc_channel_t *ic, irc_user_t *iu )  { -	struct irc_control_channel *icc;  	GSList *l; -	gboolean match = FALSE;  	if( ic == NULL )  	{ @@ -167,23 +165,13 @@ void bee_irc_channel_update( irc_t *irc, irc_channel_t *ic, irc_user_t *iu )  		return;  	} -	icc = ic->data; -	 -	if( icc->type == IRC_CC_TYPE_DEFAULT ) -		match = TRUE; -	else if( icc->type == IRC_CC_TYPE_GROUP ) -		match = iu->bu->group == icc->group; -	else if( icc->type == IRC_CC_TYPE_ACCOUNT ) -		match = iu->bu->ic->acc == icc->account; -	else if( icc->type == IRC_CC_TYPE_PROTOCOL ) -		match = iu->bu->ic->acc->prpl == icc->protocol; -	 -	if( !match ) +	if( !irc_channel_wants_user( ic, iu ) )  	{  		irc_channel_del_user( ic, iu, IRC_CDU_PART, NULL );  	}  	else  	{ +		struct irc_control_channel *icc = ic->data;  		int mode = 0;  		if( !( iu->bu->flags & BEE_USER_ONLINE ) ) @@ -43,9 +43,10 @@ void irc_send_login( irc_t *irc )  	irc_send_num( irc,   2, ":Host %s is running BitlBee " BITLBEE_VERSION " " ARCH "/" CPU ".", irc->root->host );  	irc_send_num( irc,   3, ":%s", IRCD_INFO );  	irc_send_num( irc,   4, "%s %s %s %s", irc->root->host, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES ); -	irc_send_num( irc,   5, "PREFIX=(ov)@+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee " -	                        "CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server", -	                        CTYPES, CMODES, MAX_NICK_LENGTH - 1 ); +	irc_send_num( irc,   5, "PREFIX=(ohv)@%%+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d CHANNELLEN=%d " +	                        "NETWORK=BitlBee SAFELIST CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 " +	                        ":are supported by this server", +	                        CTYPES, CMODES, MAX_NICK_LENGTH - 1, MAX_NICK_LENGTH - 1 );  	irc_send_motd( irc );  } @@ -210,7 +210,11 @@ void irc_user_quit( irc_user_t *iu, const char *msg )  		return;  	for( l = iu->irc->channels; l; l = l->next ) -		send_quit |= irc_channel_del_user( (irc_channel_t*) l->data, iu, IRC_CDU_SILENT, NULL ); +	{ +		irc_channel_t *ic = l->data; +		send_quit |= irc_channel_del_user( ic, iu, IRC_CDU_SILENT, NULL ) && +		             ( ic->flags & IRC_CHANNEL_JOINED ); +	}  	if( send_quit )  		irc_send_quit( iu, msg ); @@ -504,16 +504,17 @@ int bool2int( char *value )  	return 0;  } -struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ) +struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain )  {	 -	struct ns_srv_reply *reply = NULL; +	struct ns_srv_reply **replies = NULL;  #ifdef HAVE_RESOLV_A +	struct ns_srv_reply *reply = NULL;  	char name[1024];  	unsigned char querybuf[1024];  	const unsigned char *buf;  	ns_msg nsh;  	ns_rr rr; -	int i, len, size; +	int i, n, len, size;  	g_snprintf( name, sizeof( name ), "_%s._%s.%s", service, protocol, domain ); @@ -523,37 +524,56 @@ struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain )  	if( ns_initparse( querybuf, size, &nsh ) != 0 )  		return NULL; -	if( ns_parserr( &nsh, ns_s_an, 0, &rr ) != 0 ) -		return NULL; -	 -	size = ns_rr_rdlen( rr ); -	buf = ns_rr_rdata( rr ); -	 -	len = 0; -	for( i = 6; i < size && buf[i]; i += buf[i] + 1 ) -		len += buf[i] + 1; -	 -	if( i > size ) -		return NULL; -	 -	reply = g_malloc( sizeof( struct ns_srv_reply ) + len ); -	memcpy( reply->name, buf + 7, len ); -	 -	for( i = buf[6]; i < len && buf[7+i]; i += buf[7+i] + 1 ) -		reply->name[i] = '.'; -	 -	if( i > len ) +	n = 0; +	while( ns_parserr( &nsh, ns_s_an, n, &rr ) == 0 )  	{ -		g_free( reply ); -		return NULL; +		size = ns_rr_rdlen( rr ); +		buf = ns_rr_rdata( rr ); +		 +		len = 0; +		for( i = 6; i < size && buf[i]; i += buf[i] + 1 ) +			len += buf[i] + 1; +		 +		if( i > size ) +			break; +		 +		reply = g_malloc( sizeof( struct ns_srv_reply ) + len ); +		memcpy( reply->name, buf + 7, len ); +		 +		for( i = buf[6]; i < len && buf[7+i]; i += buf[7+i] + 1 ) +			reply->name[i] = '.'; +		 +		if( i > len ) +		{ +			g_free( reply ); +			break; +		} +		 +		reply->prio = ( buf[0] << 8 ) | buf[1]; +		reply->weight = ( buf[2] << 8 ) | buf[3]; +		reply->port = ( buf[4] << 8 ) | buf[5]; +		 +		n ++; +		replies = g_renew( struct ns_srv_reply *, replies, n + 1 ); +		replies[n-1] = reply;  	} -	 -	reply->prio = ( buf[0] << 8 ) | buf[1]; -	reply->weight = ( buf[2] << 8 ) | buf[3]; -	reply->port = ( buf[4] << 8 ) | buf[5]; +	if( replies ) +		replies[n] = NULL;  #endif -	return reply; +	return replies; +} + +void srv_free( struct ns_srv_reply **srv ) +{ +	int i; +	 +	if( srv == NULL ) +		return; +	 +	for( i = 0; srv[i]; i ++ ) +		g_free( srv[i] ); +	g_free( srv );  }  /* Word wrapping. Yes, I know this isn't UTF-8 clean. I'm willing to take the risk. */ @@ -60,7 +60,8 @@ G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count );  G_MODULE_EXPORT int is_bool( char *value );  G_MODULE_EXPORT int bool2int( char *value ); -G_MODULE_EXPORT struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ); +G_MODULE_EXPORT struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain ); +G_MODULE_EXPORT void srv_free( struct ns_srv_reply **srv );  G_MODULE_EXPORT char *word_wrap( const char *msg, int line_len ); diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 229e35bf..f7e1e664 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -95,7 +95,7 @@ static void jabber_login( account_t *acc )  {  	struct im_connection *ic = imcb_new( acc );  	struct jabber_data *jd = g_new0( struct jabber_data, 1 ); -	struct ns_srv_reply *srv = NULL; +	struct ns_srv_reply **srvl = NULL, *srv = NULL;  	char *connect_to, *s;  	int i; @@ -195,9 +195,19 @@ static void jabber_login( account_t *acc )  	/* Figure out the hostname to connect to. */  	if( acc->server && *acc->server )  		connect_to = acc->server; -	else if( ( srv = srv_lookup( "xmpp-client", "tcp", jd->server ) ) || -		 ( srv = srv_lookup( "jabber-client", "tcp", jd->server ) ) ) +	else if( ( srvl = srv_lookup( "xmpp-client", "tcp", jd->server ) ) || +	         ( srvl = srv_lookup( "jabber-client", "tcp", jd->server ) ) ) +	{ +		/* Find the lowest-priority one. These usually come +		   back in random/shuffled order. Not looking at +		   weights etc for now. */ +		srv = *srvl; +		for( i = 1; srvl[i]; i ++ ) +			if( srvl[i]->prio < srv->prio ) +				srv = srvl[i]; +		  		connect_to = srv->name; +	}  	else  		connect_to = jd->server; @@ -226,7 +236,7 @@ static void jabber_login( account_t *acc )  	{  		jd->fd = proxy_connect( connect_to, srv ? srv->port : set_getint( &acc->set, "port" ), jabber_connected_plain, ic );  	} -	g_free( srv ); +	srv_free( srvl );  	if( jd->fd == -1 )  	{ diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c index a2f2325c..d5b71bc3 100644 --- a/protocols/twitter/twitter.c +++ b/protocols/twitter/twitter.c @@ -256,7 +256,7 @@ static void twitter_logout( struct im_connection *ic )  	struct twitter_data *td = ic->proto_data;  	// Set the status to logged out. -	ic->flags = 0; +	ic->flags &= ~ OPT_LOGGED_IN;  	// Remove the main_loop function from the function queue.  	b_event_remove(td->main_loop_id); diff --git a/protocols/twitter/twitter_lib.c b/protocols/twitter/twitter_lib.c index f9e808f7..22d2a3bd 100644 --- a/protocols/twitter/twitter_lib.c +++ b/protocols/twitter/twitter_lib.c @@ -356,6 +356,11 @@ static xt_status twitter_xt_get_user_list( struct xt_node *node, struct twitter_  	return XT_HANDLED;  } +#ifdef __GLIBC__ +#define TWITTER_TIME_FORMAT "%a %b %d %H:%M:%S %z %Y" +#else +#define TWITTER_TIME_FORMAT "%a %b %d %H:%M:%S +0000 %Y" +#endif  /**   * Function to fill a twitter_xml_status struct. @@ -392,7 +397,7 @@ static xt_status twitter_xt_get_status( struct xt_node *node, struct twitter_xml  			/* Very sensitive to changes to the formatting of  			   this field. :-( Also assumes the timezone used  			   is UTC since C time handling functions suck. */ -			if( strptime( child->text, "%a %b %d %H:%M:%S %z %Y", &parsed ) != NULL ) +			if( strptime( child->text, TWITTER_TIME_FORMAT, &parsed ) != NULL )  				txs->created_at = mktime_utc( &parsed );  		}  		else if (g_strcasecmp( "user", child->name ) == 0) diff --git a/root_commands.c b/root_commands.c index 6bd953fc..2cd1a617 100644 --- a/root_commands.c +++ b/root_commands.c @@ -1007,12 +1007,16 @@ static void cmd_blist( irc_t *irc, char **cmd )  	irc_usermsg( irc, format, "Nick", "Handle/Account", "Status" ); +	if( strcmp( set_getstr( &irc->root->last_channel->set, "type" ), "control" ) != 0 ) +		irc->root->last_channel = NULL; +	  	for( l = irc->users; l; l = l->next )  	{  		irc_user_t *iu = l->data;  		bee_user_t *bu = iu->bu; -		if( !bu || ( bu->flags & ( BEE_USER_ONLINE | BEE_USER_AWAY ) ) != BEE_USER_ONLINE ) +		if( !bu || ( irc->root->last_channel && !irc_channel_wants_user( irc->root->last_channel, iu ) ) || +		    ( bu->flags & ( BEE_USER_ONLINE | BEE_USER_AWAY ) ) != BEE_USER_ONLINE )  			continue;  		if( online == 1 ) @@ -1034,7 +1038,8 @@ static void cmd_blist( irc_t *irc, char **cmd )  		irc_user_t *iu = l->data;  		bee_user_t *bu = iu->bu; -		if( !bu || !( bu->flags & BEE_USER_ONLINE ) || !( bu->flags & BEE_USER_AWAY ) ) +		if( !bu || ( irc->root->last_channel && !irc_channel_wants_user( irc->root->last_channel, iu ) ) || +		    !( bu->flags & BEE_USER_ONLINE ) || !( bu->flags & BEE_USER_AWAY ) )  			continue;  		if( away == 1 ) @@ -1050,7 +1055,8 @@ static void cmd_blist( irc_t *irc, char **cmd )  		irc_user_t *iu = l->data;  		bee_user_t *bu = iu->bu; -		if( !bu || bu->flags & BEE_USER_ONLINE ) +		if( !bu || ( irc->root->last_channel && !irc_channel_wants_user( irc->root->last_channel, iu ) ) || +		    bu->flags & BEE_USER_ONLINE )  			continue;  		if( offline == 1 ) @@ -12,6 +12,8 @@  #define sockerr_again() (errno == EINPROGRESS || errno == EINTR)  #ifndef EVENTS_LIBEVENT  #define closesocket(a) close(a) +#else +void closesocket( int fd );  #endif  #else  # include <winsock2.h> | 
