X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fngircd%2Firc-mode.c;h=b5f28fa36d73cc0f3bac75d394d1504c667b79a7;hb=999c11ad49ea1e9c2615e4668f23aae483e549dc;hp=3679531d6963909502bf1895c2ea3dc6a0801052;hpb=7b01bb833f5bc3386611dc0c015a99c236e941f6;p=ngircd-alex.git diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index 3679531d..b5f28fa3 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -138,6 +138,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) { char the_modes[COMMAND_LEN], x[2], *mode_ptr; bool ok, set; + bool send_RPL_HOSTHIDDEN_MSG = false; int mode_arg; size_t len; @@ -153,7 +154,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) /* Mode request: let's answer it :-) */ if (Req->argc == 1) return IRC_WriteStrClient(Origin, RPL_UMODEIS_MSG, - Client_ID(Origin), + Client_ID(Target), Client_Modes(Target)); mode_arg = 1; @@ -214,6 +215,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) /* Validate modes */ x[0] = '\0'; switch (*mode_ptr) { + case 'b': /* Block private msgs */ case 'C': /* Only messages from clients sharing a channel */ case 'i': /* Invisible */ case 's': /* Server messages */ @@ -229,6 +231,14 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); break; + case 'B': /* Bot */ + if (Client_HasMode(Client, 'r')) + ok = IRC_WriteStrClient(Origin, + ERR_RESTRICTED_MSG, + Client_ID(Origin)); + else + x[0] = 'B'; + break; case 'c': /* Receive connect notices * (only settable by IRC operators!) */ if (!set || Client_Type(Client) == CLIENT_SERVER @@ -248,6 +258,15 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); break; + case 'q': /* KICK-protected user */ + if (!set || Client_Type(Client) == CLIENT_SERVER + || Client_OperByMe(Origin)) + x[0] = 'q'; + else + ok = IRC_WriteStrClient(Origin, + ERR_NOPRIVILEGES_MSG, + Client_ID(Origin)); + break; case 'r': /* Restricted (only settable) */ if (set || Client_Type(Client) == CLIENT_SERVER) x[0] = 'r'; @@ -256,13 +275,28 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) ERR_RESTRICTED_MSG, Client_ID(Origin)); break; + case 'R': /* Registered (not [un]settable by clients) */ + if (Client_Type(Client) == CLIENT_SERVER) + x[0] = 'R'; + else + ok = IRC_WriteStrClient(Origin, + ERR_NICKREGISTER_MSG, + Client_ID(Origin)); + break; case 'x': /* Cloak hostname */ if (Client_HasMode(Client, 'r')) ok = IRC_WriteStrClient(Origin, ERR_RESTRICTED_MSG, Client_ID(Origin)); - else + else if (!set || Conf_CloakHostModeX[0] + || Client_Type(Client) == CLIENT_SERVER + || Client_OperByMe(Client)) { x[0] = 'x'; + send_RPL_HOSTHIDDEN_MSG = true; + } else + ok = IRC_WriteStrClient(Origin, + ERR_NOPRIVILEGES_MSG, + Client_ID(Origin)); break; default: if (Client_Type(Client) != CLIENT_SERVER) { @@ -333,6 +367,16 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) Client_ID(Target), the_modes); } + + if (send_RPL_HOSTHIDDEN_MSG && Client_Conn(Target) > NONE) { + /* A new (cloaked) hostname must be annoucned */ + IRC_WriteStrClientPrefix(Target, Origin, + RPL_HOSTHIDDEN_MSG, + Client_ID(Target), + Client_HostnameDisplayed(Target)); + + } + LogDebug("%s \"%s\": Mode change, now \"%s\".", Client_TypeText(Target), Client_Mask(Target), Client_Modes(Target)); @@ -419,7 +463,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) if(Client_OperByMe(Client) && Conf_OperCanMode) { is_oper = true; } - + /* Check if client is a server/service */ if(Client_Type(Client) == CLIENT_SERVER || Client_Type(Client) == CLIENT_SERVICE) { @@ -505,8 +549,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) /* Are there arguments left? */ if (arg_arg >= Req->argc) arg_arg = -1; - - if(!is_machine) { + + if(!is_machine && !is_oper) { o_mode_ptr = Channel_UserModes(Channel, Client); while( *o_mode_ptr ) { if ( *o_mode_ptr == 'q') @@ -538,8 +582,11 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) goto chan_exit; } case 'i': /* Invite only */ + case 'V': /* Invite disallow */ + case 'M': /* Only identified nicks can write */ case 'm': /* Moderated */ case 'n': /* Only members can write */ + case 'Q': /* No kicks */ case 't': /* Topic locked */ if(is_oper || is_machine || is_owner || is_admin || is_op || is_halfop) @@ -581,9 +628,13 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) Req->argv[arg_arg][0] = '\0'; arg_arg++; } else { +#ifdef STRICT_RFC + /* Only send error message in "strict" mode, + * this is how ircd2.11 and others behave ... */ connected = IRC_WriteStrClient(Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID(Origin), Req->command); +#endif goto chan_exit; } break; @@ -621,9 +672,13 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) Req->argv[arg_arg][0] = '\0'; arg_arg++; } else { +#ifdef STRICT_RFC + /* Only send error message in "strict" mode, + * this is how ircd2.11 and others behave ... */ connected = IRC_WriteStrClient(Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID(Origin), Req->command); +#endif goto chan_exit; } break; @@ -668,9 +723,9 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) /* --- Channel user modes --- */ case 'q': /* Owner */ case 'a': /* Channel admin */ - if(!is_oper && !is_machine && !is_owner) { + if(!is_oper && !is_machine && !is_owner && !is_admin) { connected = IRC_WriteStrClient(Origin, - ERR_CHANOPRIVSNEEDED_MSG, + ERR_CHANOPPRIVTOOLOW_MSG, Client_ID(Origin), Channel_Name(Channel)); goto chan_exit; @@ -714,9 +769,17 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) Req->argv[arg_arg][0] = '\0'; arg_arg++; } else { +#ifdef STRICT_RFC + /* Report an error to the client, when a user + * mode should be changed but no nickname is + * given. But don't do it when not in "strict" + * mode, because most other servers don't do + * it as well and some clients send "wired" + * MODE commands like "MODE #chan -ooo nick". */ connected = IRC_WriteStrClient(Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID(Origin), Req->command); +#endif goto chan_exit; } break;