diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-03-27 10:31:03 -0400 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-03-27 10:31:03 -0400 | 
| commit | b91936398b8ada486e246f769f1f8b8836fa3f43 (patch) | |
| tree | b6e0067faa86490295f74083d15bc886ad56d83d | |
| parent | 9b69eb789bdcb3667c4cc4ac74f3404ae3f60869 (diff) | |
Mode stuff. Also disallow unsetting +R umode which was possible so far
(and shouldn't be).
| -rw-r--r-- | irc.c | 60 | ||||
| -rw-r--r-- | irc.h | 17 | ||||
| -rw-r--r-- | irc_channel.c | 5 | ||||
| -rw-r--r-- | irc_commands.c | 50 | 
4 files changed, 98 insertions, 34 deletions
| @@ -52,8 +52,6 @@ irc_t *irc_new( int fd )  	irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal );  	irc->watches = g_hash_table_new( g_str_hash, g_str_equal ); -	strcpy( irc->umode, UMODE ); -	  	irc->iconv = (GIConv) -1;  	irc->oconv = (GIConv) -1; @@ -598,9 +596,6 @@ int irc_check_login( irc_t *irc )  			g_free( iu->nick );  			g_free( iu ); -			irc->umode[0] = '\0'; -			/*irc_umode_set( irc, "+" UMODE, 1 );*/ -			  			if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )  				ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname ); @@ -618,6 +613,9 @@ int irc_check_login( irc_t *irc )  			irc_send_login( irc ); +			irc->umode[0] = '\0'; +			irc_umode_set( irc, "+" UMODE, TRUE ); +			  			ic = irc_channel_new( irc, ROOT_CHAN );  			irc_channel_set_topic( ic, CONTROL_TOPIC, irc->root );  			irc_channel_add_user( ic, irc->user ); @@ -632,6 +630,58 @@ int irc_check_login( irc_t *irc )  	}  } +void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ) +{ +	/* allow_priv: Set to 0 if s contains user input, 1 if you want +	   to set a "privileged" mode (+o, +R, etc). */ +	char m[128], st = 1; +	const char *t; +	int i; +	char changes[512], *p, st2 = 2; +	char badflag = 0; +	 +	memset( m, 0, sizeof( m ) ); +	 +	for( t = irc->umode; *t; t ++ ) +		if( *t < sizeof( m ) ) +			m[(int)*t] = 1; +	 +	p = changes; +	for( t = s; *t; t ++ ) +	{ +		if( *t == '+' || *t == '-' ) +			st = *t == '+'; +		else if( ( st == 0 && ( !strchr( UMODES_KEEP, *t ) || allow_priv ) ) || +		         ( st == 1 && strchr( UMODES, *t ) ) || +		         ( st == 1 && allow_priv && strchr( UMODES_PRIV, *t ) ) ) +		{ +			if( m[(int)*t] != st) +			{ +				if( st != st2 ) +					st2 = st, *p++ = st ? '+' : '-'; +				*p++ = *t; +			} +			m[(int)*t] = st; +		} +		else +			badflag = 1; +	} +	*p = '\0'; +	 +	memset( irc->umode, 0, sizeof( irc->umode ) ); +	 +	for( i = 'A'; i <= 'z' && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ ) +		if( m[i] ) +			irc->umode[strlen(irc->umode)] = i; +	 +	if( badflag ) +		irc_send_num( irc, 501, ":Unknown MODE flag" ); +	if( *changes ) +		irc_write( irc, ":%s!%s@%s MODE %s :%s", irc->user->nick, +		           irc->user->user, irc->user->host, irc->user->nick, +		           changes ); +} +  static char *set_eval_charset( set_t *set, char *value ) @@ -32,12 +32,14 @@  #define IRC_LOGIN_TIMEOUT 60  #define IRC_PING_STRING "PinglBee" -#define UMODES "abisw" -#define UMODES_PRIV "Ro" -#define CMODES "nt" -#define CMODE "t" -#define UMODE "s" -#define CTYPES "&#" +#define UMODES "abisw"     /* Allowed umodes (although they mostly do nothing) */ +#define UMODES_PRIV "Ro"   /* Allowed, but not by user directly */ +#define UMODES_KEEP "R"    /* Don't allow unsetting using /MODE */ +#define CMODES "nt"        /* Allowed modes */ +#define CMODE "t"          /* Default mode */ +#define UMODE "s"          /* Default mode */ + +#define CTYPES "&#"        /* Valid channel name prefixes */  typedef enum  { @@ -143,6 +145,8 @@ void irc_vawrite( irc_t *irc, char *format, va_list params );  int irc_check_login( irc_t *irc ); +void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ); +  /* irc_channel.c */  irc_channel_t *irc_channel_new( irc_t *irc, const char *name );  irc_channel_t *irc_channel_by_name( irc_t *irc, const char *name ); @@ -150,6 +154,7 @@ int irc_channel_free( irc_channel_t *ic );  int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu );  int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu );  int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *who ); +gboolean irc_channel_name_ok( const char *name );  /* irc_commands.c */  void irc_exec( irc_t *irc, char **cmd ); diff --git a/irc_channel.c b/irc_channel.c index d15b73eb..c2e2c685 100644 --- a/irc_channel.c +++ b/irc_channel.c @@ -126,3 +126,8 @@ int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_  	return 1;  } + +gboolean irc_channel_name_ok( const char *name ) +{ +	return strchr( CTYPES, name[0] ) != NULL && nick_ok( name + 1 ); +} diff --git a/irc_commands.c b/irc_commands.c index 36807c54..5f9ae39f 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -183,29 +183,15 @@ static void irc_cmd_motd( irc_t *irc, char **cmd )  	irc_send_motd( irc );  } -#if 0 -//#if 0 -static void irc_cmd_oper( irc_t *irc, char **cmd ) -{ -	if( global.conf->oper_pass && -	    ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? -	        md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : -	        strcmp( cmd[2], global.conf->oper_pass ) == 0 ) ) -	{ -		irc_umode_set( irc, "+o", 1 ); -		irc_send_num( irc, 381, ":Password accepted" ); -	} -	else -	{ -		irc_send_num( irc, 432, ":Incorrect password" ); -	} -} -  static void irc_cmd_mode( irc_t *irc, char **cmd )  { -	if( strchr( CTYPES, *cmd[1] ) ) +	if( irc_channel_name_ok( cmd[1] ) )  	{ -		if( cmd[2] ) +		irc_channel_t *ic; +		 +		if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) +			irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); +		else if( cmd[2] )  		{  			if( *cmd[2] == '+' || *cmd[2] == '-' )  				irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] ); @@ -213,11 +199,11 @@ static void irc_cmd_mode( irc_t *irc, char **cmd )  				irc_send_num( irc, 368, "%s :No bans possible", cmd[1] );  		}  		else -			irc_send_num( irc, 324, "%s +%s", cmd[1], CMODE ); +			irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode );  	}  	else  	{ -		if( nick_cmp( cmd[1], irc->nick ) == 0 ) +		if( nick_cmp( cmd[1], irc->user->nick ) == 0 )  		{  			if( cmd[2] )  				irc_umode_set( irc, cmd[2], 0 ); @@ -229,6 +215,24 @@ static void irc_cmd_mode( irc_t *irc, char **cmd )  	}  } +#if 0 +//#if 0 +static void irc_cmd_oper( irc_t *irc, char **cmd ) +{ +	if( global.conf->oper_pass && +	    ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? +	        md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : +	        strcmp( cmd[2], global.conf->oper_pass ) == 0 ) ) +	{ +		irc_umode_set( irc, "+o", 1 ); +		irc_send_num( irc, 381, ":Password accepted" ); +	} +	else +	{ +		irc_send_num( irc, 432, ":Incorrect password" ); +	} +} +  static void irc_cmd_invite( irc_t *irc, char **cmd )  {  	char *nick = cmd[1], *channel = cmd[2]; @@ -565,9 +569,9 @@ static const command_t irc_commands[] = {  	{ "whois",       1, irc_cmd_whois,       IRC_CMD_LOGGED_IN },  	{ "whowas",      1, irc_cmd_whowas,      IRC_CMD_LOGGED_IN },  	{ "motd",        0, irc_cmd_motd,        IRC_CMD_LOGGED_IN }, +	{ "mode",        1, irc_cmd_mode,        IRC_CMD_LOGGED_IN },  #if 0  	{ "oper",        2, irc_cmd_oper,        IRC_CMD_LOGGED_IN }, -	{ "mode",        1, irc_cmd_mode,        IRC_CMD_LOGGED_IN },  	{ "invite",      2, irc_cmd_invite,      IRC_CMD_LOGGED_IN },  	{ "privmsg",     1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },  	{ "notice",      1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN }, | 
