diff --git a/doc/Modes.txt b/doc/Modes.txt index 20e927b6..0b0e488f 100644 --- a/doc/Modes.txt +++ b/doc/Modes.txt @@ -23,6 +23,7 @@ channels he is using at the moment. a 0.3.0 User is away. c 17 IRC operator wants to receive connect/disconnect NOTICEs. + 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. r 0.0.1 User is restricted. diff --git a/src/ngircd/defines.h b/src/ngircd/defines.h index e7a14ef8..9dc5e92d 100644 --- a/src/ngircd/defines.h +++ b/src/ngircd/defines.h @@ -158,7 +158,7 @@ #endif /** Supported user modes. */ -#define USERMODES "aciorRswx" +#define USERMODES "acCiorRswx" /** Supported channel modes. */ #define CHANMODES "biIklmnoOPRstvz" diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index c85faa04..3dd61e7c 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -214,6 +214,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) /* Validate modes */ x[0] = '\0'; switch (*mode_ptr) { + case 'C': /* Only messages from clients sharing a channel */ case 'i': /* Invisible */ case 's': /* Server messages */ case 'w': /* Wallops messages */ diff --git a/src/ngircd/irc.c b/src/ngircd/irc.c index 10e3e456..2b94e33a 100644 --- a/src/ngircd/irc.c +++ b/src/ngircd/irc.c @@ -349,6 +349,7 @@ static bool Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) { CLIENT *cl, *from; + CL2CHAN *cl2chan; CHANNEL *chan; char *currentTarget = Req->argv[0]; char *lastCurrentTarget = NULL; @@ -485,6 +486,23 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) } #endif + if (Client_HasMode(cl, 'C')) { + cl2chan = Channel_FirstChannelOf(cl); + while (cl2chan) { + chan = Channel_GetChannel(cl2chan); + if (Channel_IsMemberOf(chan, from)) + break; + cl2chan = Channel_NextChannelOf(cl, cl2chan); + } + if (!cl2chan) { + if (SendErrors && !IRC_WriteStrClient( + from, ERR_NOTONSAMECHANNEL_MSG, + Client_ID(from), Client_ID(cl))) + return DISCONNECTED; + goto send_next_target; + } + } + if (SendErrors && (Client_Type(Client) != CLIENT_SERVER) && strchr(Client_Modes(cl), 'a')) { /* Target is away */ @@ -522,6 +540,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) return DISCONNECTED; } + send_next_target: currentTarget = strtok_r(NULL, ",", &lastCurrentTarget); if (currentTarget) Conn_SetPenalty(Client_Conn(Client), 1); diff --git a/src/ngircd/messages.h b/src/ngircd/messages.h index 0070e701..6a784fe9 100644 --- a/src/ngircd/messages.h +++ b/src/ngircd/messages.h @@ -134,6 +134,7 @@ #define ERR_CANTKILLSERVER_MSG "483 %s :You can't kill a server!" #define ERR_RESTRICTED_MSG "484 %s :Your connection is restricted" #define ERR_NOOPERHOST_MSG "491 %s :Not configured for your host" +#define ERR_NOTONSAMECHANNEL_MSG "493 %s :You must share a common channel with %s" #define ERR_UMODEUNKNOWNFLAG_MSG "501 %s :Unknown mode" #define ERR_UMODEUNKNOWNFLAG2_MSG "501 %s :Unknown mode \"%c%c\""