X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fngircd%2Firc-mode.c;h=2ebbc91d5d9b81cba64cada755240353e8f9b5e0;hb=796dcf6a6203226d2a06635e94b4231b2c85f5b3;hp=5370a844e452b5475e1cf5e23a0546c8139752ac;hpb=1784180bf346b6cbea86dabb0e4fdf592b19b012;p=ngircd-alex.git diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index 5370a844..2ebbc91d 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -14,8 +14,6 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc-mode.c,v 1.51 2008/02/16 11:27:49 fw Exp $"; - #include "imp.h" #include #include @@ -41,13 +39,10 @@ static char UNUSED id[] = "$Id: irc-mode.c,v 1.51 2008/02/16 11:27:49 fw Exp $"; static bool Client_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )); static bool Channel_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )); -static bool Add_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )); -static bool Add_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )); - -static bool Del_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )); -static bool Del_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )); +static bool Add_Ban_Invite PARAMS((int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern)); +static bool Del_Ban_Invite PARAMS((int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern)); -static bool Send_ListChange PARAMS(( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask )); +static bool Send_ListChange PARAMS(( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Mask )); GLOBAL bool @@ -242,123 +237,140 @@ client_exit: } /* Client_Mode */ +static bool +Channel_Mode_Answer_Request(CLIENT *Origin, CHANNEL *Channel) +{ + char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], argadd[CLIENT_PASS_LEN]; + const char *mode_ptr; + + /* 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; + the_args[0] = '\0'; + + while(*mode_ptr) { + switch(*mode_ptr) { + case 'l': + snprintf(argadd, sizeof(argadd), " %lu", 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); +} + + static bool 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], argadd[CLIENT_PASS_LEN], *mode_ptr; - bool ok, set, modeok = false, skiponce, use_servermode = false; + bool ok, set, modeok = true, skiponce, use_servermode = false; int mode_arg, arg_arg; CLIENT *client; long l; size_t len; /* Mode request: let's answer it :-) */ - 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; - the_args[0] = '\0'; - while( *mode_ptr ) - { - switch( *mode_ptr ) - { - case 'l': - snprintf( argadd, sizeof( argadd ), " %lu", 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 ); - } + if (Req->argc <= 1) + return Channel_Mode_Answer_Request(Origin, Channel); /* Is the user allowed to change modes? */ - if( Client_Type( Client ) == CLIENT_USER ) - { + 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 if( Conf_OperCanMode ) - { + if (!Channel_IsMemberOf(Channel, Origin)) + return IRC_WriteStrClient(Origin, ERR_NOTONCHANNEL_MSG, + Client_ID(Origin), Channel_Name(Channel)); + modeok = false; + /* channel operator? */ + if (strchr(Channel_UserModes(Channel, Origin), 'o')) + modeok = true; + else if(Conf_OperCanMode) { /* IRC-Operators can use MODE as well */ - if( Client_OperByMe( Origin )) { + if (Client_OperByMe(Origin)) { modeok = true; - if ( Conf_OperServerMode ) use_servermode = true; /* Change Origin to Server */ + if (Conf_OperServerMode) + use_servermode = true; /* Change Origin to Server */ } } } - else modeok = true; mode_arg = 1; mode_ptr = Req->argv[mode_arg]; - if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1; - else arg_arg = -1; + if (Req->argc > mode_arg + 1) + arg_arg = mode_arg + 1; + else + arg_arg = -1; /* Initial state: set or unset modes? */ skiponce = false; - if( *mode_ptr == '-' ) set = false; - else if( *mode_ptr == '+' ) set = true; - else set = skiponce = true; + switch (*mode_ptr) { + case '-': set = false; break; + case '+': set = true; break; + default: + set = true; + skiponce = true; + } /* Prepare reply string */ - if( set ) strcpy( the_modes, "+" ); - else strcpy( the_modes, "-" ); + strcpy(the_modes, set ? "+" : "-"); the_args[0] = '\0'; x[1] = '\0'; ok = CONNECTED; - while( mode_ptr ) - { - if( ! skiponce ) mode_ptr++; - if( ! *mode_ptr ) - { + while (mode_ptr) { + if (! skiponce) + mode_ptr++; + if (!*mode_ptr) { /* Try next argument if there's any */ - if( arg_arg > mode_arg ) mode_arg = arg_arg; - else mode_arg++; - if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg]; - else break; - if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1; - else arg_arg = -1; + if (arg_arg > mode_arg) + mode_arg = arg_arg; + else + mode_arg++; + + if (mode_arg >= Req->argc) + break; + mode_ptr = Req->argv[mode_arg]; + + if (Req->argc > mode_arg + 1) + arg_arg = mode_arg + 1; + else + arg_arg = -1; } skiponce = false; - switch( *mode_ptr ) - { - case '+': - case '-': - if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set ))) - { - /* Action modifier ("+"/"-") must be changed ... */ - len = strlen( the_modes ) - 1; - if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) - { - /* Adjust last action modifier in result */ - the_modes[len] = *mode_ptr; - } - else - { - /* Append modifier character to result string */ - x[0] = *mode_ptr; - strlcat( the_modes, x, sizeof( the_modes )); - } - if( *mode_ptr == '+' ) set = true; - else set = false; + switch (*mode_ptr) { + case '+': + case '-': + if (((*mode_ptr == '+') && !set) || ((*mode_ptr == '-') && set)) { + /* Action modifier ("+"/"-") must be changed ... */ + len = strlen( the_modes ) - 1; + if ((the_modes[len] == '+') || (the_modes[len] == '-')) { + /* Adjust last action modifier in result */ + the_modes[len] = *mode_ptr; + } else { + /* Append modifier character to result string */ + x[0] = *mode_ptr; + strlcat(the_modes, x, sizeof(the_modes)); } - continue; + set = *mode_ptr == '+'; + } + continue; } /* Are there arguments left? */ @@ -469,39 +481,28 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) break; /* --- Channel lists --- */ - case 'I': /* Invite lists */ - if( arg_arg > mode_arg ) - { - /* modify list */ - if( modeok ) - { - if( set ) Add_Invite( Origin, Client, Channel, Req->argv[arg_arg] ); - else Del_Invite( Origin, Client, Channel, Req->argv[arg_arg] ); - } - else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); - Req->argv[arg_arg][0] = '\0'; - arg_arg++; - } - else Channel_ShowInvites( Origin, Channel ); - break; - case 'b': /* Ban lists */ - if( arg_arg > mode_arg ) - { + if (arg_arg > mode_arg) { /* modify list */ - if( modeok ) - { - if( set ) Add_Ban( Origin, Client, Channel, Req->argv[arg_arg] ); - else Del_Ban( Origin, Client, Channel, Req->argv[arg_arg] ); + if (modeok) { + if (set) + Add_Ban_Invite(*mode_ptr, Origin, Client, Channel, Req->argv[arg_arg]); + else + Del_Ban_Invite(*mode_ptr, Origin, Client, Channel, Req->argv[arg_arg]); + } else { + ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, + Client_ID(Origin), Channel_Name(Channel)); } - else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); Req->argv[arg_arg][0] = '\0'; arg_arg++; + } else { + if (*mode_ptr == 'I') + Channel_ShowInvites(Origin, Channel); + else + Channel_ShowBans(Origin, Channel); } - else Channel_ShowBans( Origin, Channel ); break; - default: 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 ); @@ -579,22 +580,19 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) chan_exit: /* Are there changed modes? */ - if( the_modes[1] ) - { + if (the_modes[1]) { /* Clean up mode string */ - len = strlen( the_modes ) - 1; - if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0'; + len = strlen(the_modes) - 1; + if ((the_modes[len] == '+') || (the_modes[len] == '-')) + the_modes[len] = '\0'; - if( Client_Type( Client ) == CLIENT_SERVER ) - { + if (Client_Type(Client) == CLIENT_SERVER) { /* Forward mode changes to channel users and other servers */ - IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); - IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); - } - else - { - if ( use_servermode ) Origin = Client_ThisServer(); - + IRC_WriteStrServersPrefix(Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args); + IRC_WriteStrChannelPrefix(Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args); + } else { + if (use_servermode) + Origin = Client_ThisServer(); /* Send reply to client and inform other servers and channel users */ ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); @@ -635,85 +633,64 @@ IRC_AWAY( CLIENT *Client, REQUEST *Req ) static bool -Add_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ) -{ - char *mask; - bool already; - - assert( Client != NULL ); - assert( Channel != NULL ); - assert( Pattern != NULL ); - - mask = Lists_MakeMask( Pattern ); - - already = Lists_CheckDupeMask(Channel_GetListInvites(Channel), mask ); - if (!already) { - if( ! Channel_AddInvite(Channel, mask, false )) - return CONNECTED; - } - if ( already && ( Client_Type( Prefix ) == CLIENT_SERVER )) - return CONNECTED; - - return Send_ListChange( "+I", Prefix, Client, Channel, mask ); -} /* Add_Invite */ - - -static bool -Add_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ) +Add_Ban_Invite(int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern) { - char *mask; + const char *mask; bool already; + bool ret; assert( Client != NULL ); assert( Channel != NULL ); assert( Pattern != NULL ); + assert(what == 'I' || what == 'b'); - mask = Lists_MakeMask( Pattern ); + mask = Lists_MakeMask(Pattern); - already = Lists_CheckDupeMask(Channel_GetListBans(Channel), mask ); + already = Lists_CheckDupeMask(Channel_GetListInvites(Channel), mask); if (!already) { - if( ! Channel_AddBan(Channel, mask)) + if (what == 'I') + ret = Channel_AddInvite(Channel, mask, false); + else + ret = Channel_AddBan(Channel, mask); + if (!ret) return CONNECTED; } - if ( already && ( Client_Type( Prefix ) == CLIENT_SERVER )) + if (already && (Client_Type(Prefix) == CLIENT_SERVER)) return CONNECTED; - return Send_ListChange( "+b", Prefix, Client, Channel, mask ); -} /* Add_Ban */ + if (what == 'I') + return Send_ListChange("+I", Prefix, Client, Channel, mask); + return Send_ListChange("+b", Prefix, Client, Channel, mask); +} static bool -Del_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ) +Del_Ban_Invite(int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern) { - char *mask; + const char *mask; + struct list_head *list; assert( Client != NULL ); assert( Channel != NULL ); assert( Pattern != NULL ); + assert(what == 'I' || what == 'b'); mask = Lists_MakeMask( Pattern ); - Lists_Del(Channel_GetListInvites(Channel), mask); - return Send_ListChange( "-I", Prefix, Client, Channel, mask ); -} /* Del_Invite */ - -static bool -Del_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ) -{ - char *mask; - - assert( Client != NULL ); - assert( Channel != NULL ); - assert( Pattern != NULL ); + if (what == 'I') + list = Channel_GetListInvites(Channel); + else + list = Channel_GetListBans(Channel); - mask = Lists_MakeMask( Pattern ); - Lists_Del(Channel_GetListBans(Channel), mask); + Lists_Del(list, mask); + if (what == 'I') + return Send_ListChange( "-I", Prefix, Client, Channel, mask ); return Send_ListChange( "-b", Prefix, Client, Channel, mask ); -} /* Del_Ban */ +} static bool -Send_ListChange( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask ) +Send_ListChange( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Mask ) { /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */