From f32c14c649e854fbfb7b8e495e2ebc8459ee5b6f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 9 Aug 2010 14:39:50 +0100 Subject: Oops. We're using channel mode +h (halfop) for a while already, but so far without advertising this in 005. This confuses irssi ans possibly other clients. Fixing that now. Also adding SAFELIST which may make some clients less afraid of using /LIST, and CHANNELLEN with an artifical limit (the code has no max. channel name limit). --- irc_send.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/irc_send.c b/irc_send.c index 003e0625..cb387059 100644 --- a/irc_send.c +++ b/irc_send.c @@ -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 ); } -- cgit v1.2.3 From ffdf2e71d9e67980727aa994b77fca36ef5246c6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 10 Aug 2010 12:18:09 +0100 Subject: When doing SRV lookups, return an array with all RRs instead of just the first one. The first isn't always the best one and this is currently causing GTalk issues when talk2.l.google.com (which is currently dead) is first. --- lib/misc.c | 80 +++++++++++++++++++++++++++++------------------ lib/misc.h | 3 +- protocols/jabber/jabber.c | 18 ++++++++--- 3 files changed, 66 insertions(+), 35 deletions(-) diff --git a/lib/misc.c b/lib/misc.c index fda19c19..b696b8c4 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -507,16 +507,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 ); @@ -526,37 +527,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. */ diff --git a/lib/misc.h b/lib/misc.h index 12a9edff..83ba9e67 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -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..e3717526 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; 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 ) { -- cgit v1.2.3 From 72176c140636532347141dc011959d676df50d2f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 11 Aug 2010 09:53:58 +0100 Subject: Small bug in the previous change: NULL-initialize srv. --- protocols/jabber/jabber.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index e3717526..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 **srvl = NULL, *srv; + struct ns_srv_reply **srvl = NULL, *srv = NULL; char *connect_to, *s; int i; -- cgit v1.2.3 From 2b02617289671ececbd98a209cb44aca81c22a65 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 11 Aug 2010 21:41:23 +0100 Subject: strptime() on FreeBSD (and possibly other non-glibc platforms) %z is not supported, so just insert the literal timezone there - let's hope Twitter won't ever change that. --- protocols/twitter/twitter_lib.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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) -- cgit v1.2.3 From 4ffd757724a657d2dc5c536473523a86f2331d9e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 11:21:44 +0100 Subject: Don't send a /QUIT for every Twitter contact when going offline, and show the twitter_$username /QUIT as a netsplit. --- irc_user.c | 6 +++++- protocols/twitter/twitter.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/irc_user.c b/irc_user.c index 8b290bbf..bf08c755 100644 --- a/irc_user.c +++ b/irc_user.c @@ -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 ); 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); -- cgit v1.2.3 From ac2717b6a60900d31236b7696f150d0120bda3da Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 11:55:20 +0100 Subject: blist should only show contacts that are (or would be if they were online) in the current channel. --- doc/user-guide/commands.xml | 4 ++-- irc.h | 1 + irc_channel.c | 25 +++++++++++++++++++++++++ irc_im.c | 16 ++-------------- root_commands.c | 12 +++++++++--- 5 files changed, 39 insertions(+), 19 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 @@ blist [all|online|offline|away] - List all the buddies in your contact list + List all the buddies in the current channel - You can get a better readable buddy list using the blist command. If you want a complete list (including the offline users) you can use the all argument. + You can get a more readable buddy list using the blist command. If you want a complete list (including the offline users) you can use the all argument. diff --git a/irc.h b/irc.h index aee9dccd..58ca19c9 100644 --- a/irc.h +++ b/irc.h @@ -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; diff --git a/irc_im.c b/irc_im.c index 2d4e8787..7ed2922e 100644 --- a/irc_im.c +++ b/irc_im.c @@ -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 ) ) 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 ) -- cgit v1.2.3 From 136c2bb632715ab83710c93c7b339c5cca7d2679 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 14 Aug 2010 11:57:17 +0100 Subject: Fix the libevent-specific compiler warning about closesocket(). --- sock.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sock.h b/sock.h index 848dc466..66e28987 100644 --- a/sock.h +++ b/sock.h @@ -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 -- cgit v1.2.3