commit d3ae351236e605b400b94fcfa8e7670e26e19c89 from: Alexander Barton date: Sat Oct 06 16:13:01 2012 UTC Implement channel mode "Q" and user mode "q" Both modes protect users from channel kicks: only IRC operators and servers can kick users having mode "q" or in channels with mode "Q". Original patch by DNS777 , thanks! This closes bug #141. commit - 4790d78c980c79abfd71c064be1eb085717210f8 commit + d3ae351236e605b400b94fcfa8e7670e26e19c89 blob - e3b754d69815c1aaa0729177b25a80b35986d447 blob + fb7845112c960268c6a96b4aed2d9d61fae6f1b3 --- doc/Modes.txt +++ doc/Modes.txt @@ -27,6 +27,7 @@ channels he is using at the moment. C 19 Only users that share a channel are allowed to send messages. i 0.0.1 User is "invisible". o 0.0.1 User is IRC operator. + q 20 User is protected, can not be kicked from a channel. r 0.0.1 User is restricted. R (1) 19 User is registered (e.g. by NickServ). s 0.4.0 User wants to receive server notices. @@ -54,6 +55,7 @@ users to lists (e.g. "invite list", "ban list"), other n 0.3.0 Channel doesn't allow messages of users not being members. O 18 Only IRC operators are allowed to join this channel. P 0.5.0 Channel is "persistent". + Q 20 Nobody can be kicked from the channel. r (1) 19 Channel is "registered" (e.g. by ChanServ). R 19 Only registered users are allowed to join this channel. s 0.9.0 Channel is "secret". blob - 10b05405b5ad50b0ebb464d1c9ce5139fc4d12ae blob + c679daeb9a08cbee79ae2cd48150318959cf8c08 --- src/ngircd/channel.c +++ src/ngircd/channel.c @@ -327,6 +327,17 @@ Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Ori } if(Client_Type(Peer) == CLIENT_USER) { + /* Channel mode 'Q' and user mode 'q' on target: nobody but + * IRC Operators and servers can kick the target user */ + if ((strchr(Channel_Modes(chan), 'Q') + || Client_HasMode(Target, 'q')) + && !Client_HasMode(Origin, 'o')) { + IRC_WriteStrClient(Origin, ERR_KICKDENY_MSG, + Client_ID(Origin), Name, + Client_ID(Target)); + return; + } + /* Check if client has the rights to kick target */ ptr = Channel_UserModes(chan, Peer); target_modes = Channel_UserModes(chan, Target); blob - ba7adf17adb204840418b7482b75fef975844138 blob + c0be813a60f74ffec8821fcdff2535394d2a9414 --- src/ngircd/defines.h +++ src/ngircd/defines.h @@ -161,10 +161,10 @@ #endif /** Supported user modes. */ -#define USERMODES "aBcCiorRswx" +#define USERMODES "aBcCioqrRswx" /** Supported channel modes. */ -#define CHANMODES "abehiIklmMnoOPqrRstvz" +#define CHANMODES "abehiIklmMnoOPqQrRstvz" /** Away message for users connected to linked servers. */ #define DEFAULT_AWAY_MSG "Away" blob - 90f638d811219282b34af51c8cf8369e7548e4f7 blob + 7f04e9c5b867b51d92df2c6fd2d4b4ef4a51582e --- src/ngircd/irc-mode.c +++ src/ngircd/irc-mode.c @@ -253,6 +253,15 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Ori Client_SetOperByMe(Target, false); x[0] = 'o'; } else + ok = IRC_WriteStrClient(Origin, + 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)); @@ -569,6 +578,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Ori 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) blob - efc7524e11d35b22479c3726ac700844abd798f5 blob + ea24b2eb92708fabbcb4898cf03f3216ae5cf7f0 --- src/ngircd/messages.h +++ src/ngircd/messages.h @@ -21,7 +21,7 @@ #define RPL_YOURHOST_MSG "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)" #define RPL_CREATED_MSG "003 %s :This server has been started %s" #define RPL_MYINFO_MSG "004 %s %s ngircd-%s %s %s" -#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(qaohv)~&@%%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPRstz CHANLIMIT=#&+:%d :are supported on this server" +#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(qaohv)~&@%%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPQRstz CHANLIMIT=#&+:%d :are supported on this server" #define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=beI:%d EXCEPTS=e INVEX=I PENALTY :are supported on this server" #define RPL_TRACELINK_MSG "200 %s Link %s-%s %s %s V%s %ld %d %d" @@ -140,6 +140,7 @@ #define ERR_NOPRIVILEGES_MSG "481 %s :Permission denied" #define ERR_CHANOPRIVSNEEDED_MSG "482 %s %s :You are not channel operator" #define ERR_CHANOPPRIVTOOLOW_MSG "482 %s %s :Your privileges are too low" +#define ERR_KICKDENY_MSG "482 %s %s :Cannot kick, %s is protected" #define ERR_CANTKILLSERVER_MSG "483 %s :You can't kill a server!" #define ERR_RESTRICTED_MSG "484 %s :Your connection is restricted" #define ERR_NICKREGISTER_MSG "484 %s :Cannot modify user mode (+R) -- Use IRC services"