X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fngircd%2Firc-mode.c;h=28e5327e07dc36625d53ad9596b37580290c851c;hb=56227abc5e09e274877fda7ad5986be6a9853c10;hp=381811e456c5ee6a3830e22fee44c1a7c23eca8f;hpb=7f61f413f42ac7969cd1d0abebc6ab6a4bf2947f;p=ngircd-alex.git diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index 381811e4..28e5327e 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -14,10 +14,12 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc-mode.c,v 1.22 2002/12/16 10:52:53 alex Exp $"; +static char UNUSED id[] = "$Id: irc-mode.c,v 1.33 2004/02/29 16:28:44 alex Exp $"; #include "imp.h" #include +#include +#include #include #include "conn.h" @@ -140,7 +142,8 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) else { /* Append modifier character to result string */ - x[0] = *mode_ptr; strcat( the_modes, x ); + x[0] = *mode_ptr; + strlcat( the_modes, x, sizeof( the_modes )); } if( *mode_ptr == '+' ) set = TRUE; else set = FALSE; @@ -152,13 +155,22 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) x[0] = '\0'; switch( *mode_ptr ) { + case 'a': + /* Away */ + if( Client_Type( Client ) == CLIENT_SERVER ) + { + x[0] = 'a'; + Client_SetAway( Client, DEFAULT_AWAY_MSG ); + } + else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin )); + break; case 'i': /* Invisible */ x[0] = 'i'; break; case 'o': /* IRC operator (only unsetable!) */ - if( ! set ) + if(( ! set ) || ( Client_Type( Client ) == CLIENT_SERVER )) { Client_SetOperByMe( Target, FALSE ); x[0] = 'o'; @@ -167,7 +179,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) break; case 'r': /* Restricted (only setable) */ - if( set ) x[0] = 'r'; + if(( set ) || ( Client_Type( Client ) == CLIENT_SERVER )) x[0] = 'r'; else ok = IRC_WriteStrClient( Origin, ERR_RESTRICTED_MSG, Client_ID( Origin )); break; case 's': @@ -178,6 +190,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin )); if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr ); x[0] = '\0'; + goto client_exit; } if( ! ok ) break; @@ -187,16 +200,17 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) if( set ) { /* Set mode */ - if( Client_ModeAdd( Target, x[0] )) strcat( the_modes, x ); + if( Client_ModeAdd( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes )); } else { /* Unset mode */ - if( Client_ModeDel( Target, x[0] )) strcat( the_modes, x ); + if( Client_ModeDel( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes )); } } - +client_exit: + /* Are there changed modes? */ if( the_modes[1] ) { @@ -211,12 +225,13 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) else { /* Send reply to client and inform other servers */ - ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s", Client_ID( Target ), the_modes ); + ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes ); IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes ); } Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( Target ), Client_Modes( Target )); } - + + IRC_SetPenalty( Client, 1 ); return ok; } /* Client_Mode */ @@ -226,17 +241,49 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) { /* Handle channel and channel-user modes */ - CHAR the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], *mode_ptr; + CHAR the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], argadd[CLIENT_PASS_LEN], *mode_ptr; BOOLEAN ok, set, modeok, skiponce; INT mode_arg, arg_arg; CLIENT *client; + LONG l; /* Mode request: let's answer it :-) */ - if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), Channel_Modes( Channel )); + if( Req->argc == 1 ) + { + /* Member or not? -- That's the question! */ + if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), Channel_Modes( Channel )); + + /* The sender is a member: generate extended reply */ + strlcpy( the_modes, Channel_Modes( Channel ), sizeof( the_modes )); + mode_ptr = the_modes; + strcpy( the_args, "" ); + while( *mode_ptr ) + { + switch( *mode_ptr ) + { + case 'l': + snprintf( argadd, sizeof( argadd ), " %ld", Channel_MaxUsers( Channel )); + strlcat( the_args, argadd, sizeof( the_args )); + break; + case 'k': + strlcat( the_args, " ", sizeof( the_args )); + strlcat( the_args, Channel_Key( Channel ), sizeof( the_args )); + break; + } + mode_ptr++; + } + if( the_args[0] ) strlcat( the_modes, the_args, sizeof( the_modes )); + + return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), the_modes ); + } /* Is the user allowed to change modes? */ if( Client_Type( Client ) == CLIENT_USER ) { + /* Is the originating user on that channel? */ + if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, Client_ID( Origin ), Channel_Name( Channel )); + + /* Is he channel operator? */ if( strchr( Channel_UserModes( Channel, Origin ), 'o' )) modeok = TRUE; else modeok = FALSE; if( Conf_OperCanMode ) @@ -295,7 +342,8 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) else { /* Append modifier character to result string */ - x[0] = *mode_ptr; strcat( the_modes, x ); + x[0] = *mode_ptr; + strlcat( the_modes, x, sizeof( the_modes )); } if( *mode_ptr == '+' ) set = TRUE; else set = FALSE; @@ -308,6 +356,7 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) /* Validate modes */ x[0] = '\0'; + argadd[0] = '\0'; client = NULL; switch( *mode_ptr ) { @@ -365,6 +414,56 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) } else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command ); break; + case 'k': + /* Channel key */ + if( ! set ) + { + if( modeok ) x[0] = *mode_ptr; + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + break; + } + if( arg_arg > mode_arg ) + { + if( modeok ) + { + Channel_ModeDel( Channel, 'k' ); + Channel_SetKey( Channel, Req->argv[arg_arg] ); + strlcpy( argadd, Channel_Key( Channel ), sizeof( argadd )); + x[0] = *mode_ptr; + } + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + Req->argv[arg_arg][0] = '\0'; + arg_arg++; + } + else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command ); + break; + case 'l': + /* Member limit */ + if( ! set ) + { + if( modeok ) x[0] = *mode_ptr; + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + break; + } + if( arg_arg > mode_arg ) + { + if( modeok ) + { + l = atol( Req->argv[arg_arg] ); + if( l > 0 && l < 0xFFFF ) + { + Channel_ModeDel( Channel, 'l' ); + Channel_SetMaxUsers( Channel, l ); + snprintf( argadd, sizeof( argadd ), "%ld", l ); + x[0] = *mode_ptr; + } + } + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + Req->argv[arg_arg][0] = '\0'; + arg_arg++; + } + else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command ); + break; /* Channel lists */ case 'I': @@ -404,12 +503,20 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\" on %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ), Channel_Name( Channel )); if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr ); x[0] = '\0'; + goto chan_exit; } if( ! ok ) break; /* Is there a valid mode change? */ if( ! x[0] ) continue; + /* Validate target client */ + if( client && ( ! Channel_IsMemberOf( Channel, client ))) + { + if( ! IRC_WriteStrClient( Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID( Origin ), Client_ID( client ), Channel_Name( Channel ))) break; + continue; + } + if( set ) { /* Set mode */ @@ -418,8 +525,9 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) /* Channel-User-Mode */ if( Channel_UserModeAdd( Channel, client, x[0] )) { - strcat( the_args, Client_ID( client )); - strcat( the_args, " " ); strcat( the_modes, x ); + strlcat( the_args, Client_ID( client ), sizeof( the_args )); + strlcat( the_args, " ", sizeof( the_args )); + strlcat( the_modes, x, sizeof( the_modes )); Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client )); } } @@ -428,7 +536,7 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) /* Channel-Mode */ if( Channel_ModeAdd( Channel, x[0] )) { - strcat( the_modes, x ); + strlcat( the_modes, x, sizeof( the_modes )); Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel )); } } @@ -441,8 +549,9 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) /* Channel-User-Mode */ if( Channel_UserModeDel( Channel, client, x[0] )) { - strcat( the_args, Client_ID( client )); - strcat( the_args, " " ); strcat( the_modes, x ); + strlcat( the_args, Client_ID( client ), sizeof( the_args )); + strlcat( the_args, " ", sizeof( the_args )); + strlcat( the_modes, x, sizeof( the_modes )); Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client )); } } @@ -451,12 +560,20 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) /* Channel-Mode */ if( Channel_ModeDel( Channel, x[0] )) { - strcat( the_modes, x ); + strlcat( the_modes, x, sizeof( the_modes )); Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel )); } } - } + } + + /* Are there additional arguments to add? */ + if( argadd[0] ) + { + if( the_args[strlen( the_args ) - 1] != ' ' ) strlcat( the_args, " ", sizeof( the_args )); + strlcat( the_args, argadd, sizeof( the_args )); + } } +chan_exit: /* Are there changed modes? */ if( the_modes[1] ) @@ -482,6 +599,7 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) } } + IRC_SetPenalty( Client, 1 ); return CONNECTED; } /* Channel_Mode */ @@ -499,13 +617,14 @@ IRC_AWAY( CLIENT *Client, REQUEST *Req ) { /* AWAY setzen */ Client_SetAway( Client, Req->argv[0] ); + Client_ModeAdd( Client, 'a' ); IRC_WriteStrServersPrefix( Client, Client, "MODE %s :+a", Client_ID( Client )); return IRC_WriteStrClient( Client, RPL_NOWAWAY_MSG, Client_ID( Client )); } else { /* AWAY loeschen */ - Client_SetAway( Client, NULL ); + Client_ModeDel( Client, 'a' ); IRC_WriteStrServersPrefix( Client, Client, "MODE %s :-a", Client_ID( Client )); return IRC_WriteStrClient( Client, RPL_UNAWAY_MSG, Client_ID( Client )); }