Commit Diff


commit - cedba36965c3b89a5ab7222764bd751fd7fc88bf
commit + 49ab79d0e64c73d575dfe87edce40637b8f2adef
blob - ff849bbeacb2b157c1a747b6a3f0783bafe612b5
blob + 6bea174e2d46725bd36284973e4a6d630d94e810
--- src/ngircd/defines.h
+++ src/ngircd/defines.h
@@ -206,6 +206,9 @@
 /** Max. number of channel modes with arguments per MODE command. */
 #define MAX_HNDL_MODES_ARG 5
 
+/** Max. number of targets per PRIVMSG/NOTICE/... command. */
+#define MAX_HNDL_TARGETS 25
+
 /** Max. number of WHO replies. */
 #define MAX_RPL_WHO 25
 
blob - bd741cbbad732df693a235ed17d3a6c89c7cd03c
blob + 15bb90f73ced63e4d7134d5f49b56fb893debd2a
--- src/ngircd/irc.c
+++ src/ngircd/irc.c
@@ -517,8 +517,10 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
 	CL2CHAN *cl2chan;
 	CHANNEL *chan;
 	char *currentTarget = Req->argv[0];
-	char *lastCurrentTarget = NULL;
+	char *strtok_last = NULL;
 	char *message = NULL;
+	char *targets[MAX_HNDL_TARGETS];
+	int i, target_nr = 0;
 
 	assert(Client != NULL);
 	assert(Req != NULL);
@@ -558,10 +560,17 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
 		message = Req->argv[1];
 
 	/* handle msgtarget = msgto *("," msgto) */
-	currentTarget = strtok_r(currentTarget, ",", &lastCurrentTarget);
+	currentTarget = strtok_r(currentTarget, ",", &strtok_last);
 	ngt_UpperStr(Req->command);
 
-	while (currentTarget) {
+	while (true) {
+		/* Make sure that there hasn't been such a target already: */
+		targets[target_nr++] = currentTarget;
+		for(i = 0; i < target_nr - 1; i++) {
+			if (strcasecmp(currentTarget, targets[i]) == 0)
+				goto send_next_target;
+		}
+
 		/* Check for and handle valid <msgto> of form:
 		 * RFC 2812 2.3.1:
 		 *   msgto =  channel / ( user [ "%" host ] "@" servername )
@@ -725,9 +734,18 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
 		}
 
 	send_next_target:
-		currentTarget = strtok_r(NULL, ",", &lastCurrentTarget);
-		if (currentTarget)
-			Conn_SetPenalty(Client_Conn(Client), 1);
+		currentTarget = strtok_r(NULL, ",", &strtok_last);
+		if (!currentTarget)
+			break;
+
+		Conn_SetPenalty(Client_Conn(Client), 1);
+
+		if (target_nr >= MAX_HNDL_TARGETS) {
+			/* Too many targets given! */
+			return IRC_WriteErrClient(Client,
+						  ERR_TOOMANYTARGETS_MSG,
+						  currentTarget);
+		}
 	}
 
 	return CONNECTED;
blob - 818d83b9e594102fc46ed01b1b79452b1533c057
blob + 90292a2b3aae492020b77c7e6b68a7e61a09a7f3
--- src/ngircd/messages.h
+++ src/ngircd/messages.h
@@ -110,6 +110,7 @@
 #define ERR_CANNOTSENDTOCHAN_MSG	"404 %s %s :Cannot send to channel"
 #define ERR_TOOMANYCHANNELS_MSG		"405 %s %s :You have joined too many channels"
 #define ERR_WASNOSUCHNICK_MSG		"406 %s %s :There was no such nickname"
+#define ERR_TOOMANYTARGETS_MSG		"407 %s :Too many recipients"
 #define ERR_NOORIGIN_MSG		"409 %s :No origin specified"
 #define ERR_INVALIDCAP_MSG		"410 %s %s :Invalid CAP subcommand"
 #define ERR_NORECIPIENT_MSG		"411 %s :No recipient given (%s)"
blob - 5dc325ded807cd68807c8d05dc54a31451394cf0
blob + e46378637b8c2ff44df43a85d13911484809eeec
--- src/testsuite/message-test.e
+++ src/testsuite/message-test.e
@@ -35,13 +35,13 @@ expect {
 send "privmsg nick,nick :test\r"
 expect {
 	timeout { exit 1 }
-	"@* PRIVMSG nick :test\r*@* PRIVMSG nick :test"
+	"@* PRIVMSG nick :test"
 }
 
 send "privmsg Nick,#testChannel,nick :test\r"
 expect {
 	timeout { exit 1 }
-	"@* PRIVMSG nick :test\r*401*@* PRIVMSG nick :test"
+	"@* PRIVMSG nick :test\r*401"
 }
 
 send "privmsg doesnotexist :test\r"