Commit Diff


commit - 4d0069c3a8021c32b5bdeeec57f1d41d369587ce
commit + 1f4711a5474d2f0ea4664bd9b54f036af11f96cd
blob - 20e927b6e681a9743b9ae0854001cdca2959556e
blob + 0b0e488f46b212a306ec7ba01e694bf87575fe22
--- doc/Modes.txt
+++ 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.
blob - e7a14ef88959069a67f7ecb8f53c7c03c5b2071f
blob + 9dc5e92d4f4ec074247bd9f2741a8e4431b3b79f
--- src/ngircd/defines.h
+++ src/ngircd/defines.h
@@ -158,7 +158,7 @@
 #endif
 
 /** Supported user modes. */
-#define USERMODES "aciorRswx"
+#define USERMODES "acCiorRswx"
 
 /** Supported channel modes. */
 #define CHANMODES "biIklmnoOPRstvz"
blob - c85faa04d626f42569fe83c2a7e852bdeb768062
blob + 3dd61e7ca2031ad6727c64579da300b86cd9a038
--- src/ngircd/irc-mode.c
+++ src/ngircd/irc-mode.c
@@ -214,6 +214,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Ori
 		/* 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 */
blob - 10e3e45656bdb1cc996ef0d92ad2c0a1cd8fab2f
blob + 2b94e33ac229b44cf509277c23944034bebf5a51
--- src/ngircd/irc.c
+++ 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 Force
 			}
 #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 Force
 				return DISCONNECTED;
 		}
 
+	send_next_target:
 		currentTarget = strtok_r(NULL, ",", &lastCurrentTarget);
 		if (currentTarget)
 			Conn_SetPenalty(Client_Conn(Client), 1);
blob - 0070e70159f46bd533624e953225854e23975812
blob + 6a784fe9eb97a98ebc8194bee63232e7893f6c82
--- src/ngircd/messages.h
+++ 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\""