Commit Diff


commit - 2546a13ad2949192eb70bf21e114ec60af287ee4
commit + d4eb55c79fb130844a08279cd574a19f188ffa99
blob - 43f2c1b6e4c1949724fa2e6281b70a11375a3ea3
blob + 000cb848f82f92df6f4760a32e20c7b4ccdcd165
--- src/ngircd/irc-info.c
+++ src/ngircd/irc-info.c
@@ -764,20 +764,6 @@ IRC_Send_WHO(CLIENT *Client, CHANNEL *Chan, bool OnlyO
 	}
 	return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan));
 } /* IRC_Send_WHO */
-
-
-
-static bool
-MatchCaseInsensitive(const char *pattern, const char *searchme)
-{
-	char haystack[COMMAND_LEN];
-
-	strlcpy(haystack, searchme, sizeof(haystack));
-
-	ngt_LowerStr(haystack);
-
-	return Match(pattern, haystack);
-}
 
 
 GLOBAL bool
blob - 2e3af757584b0d9630640da16029a6fe9e18b03f
blob + 9da8d38dc68c83630d4588046797e4dc91d3af87
--- src/ngircd/irc.c
+++ src/ngircd/irc.c
@@ -41,7 +41,6 @@ static char UNUSED id[] = "$Id: irc.c,v 1.132 2008/01/
 static char *Option_String PARAMS((CONN_ID Idx));
 static bool Send_Message PARAMS((CLIENT *Client, REQUEST *Req, int ForceType, bool SendErrors));
 static bool Send_Message_Mask PARAMS((CLIENT *from, char *targetMask, char *message, bool SendErrors));
-static bool MatchCaseInsensitive PARAMS((const char *pattern, const char *searchme));
 
 
 GLOBAL bool
@@ -309,12 +308,11 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
 {
 	CLIENT *cl, *from;
 	CHANNEL *chan;
-	char *targetList = Req->argv[0];
 	char *currentTarget = Req->argv[0];
-	unsigned int targetCount = 1;
+	char *lastCurrentTarget;
 
-	assert( Client != NULL );
-	assert( Req != NULL );
+	assert(Client != NULL);
+	assert(Req != NULL);
 
 	if (Req->argc == 0) {
 		if (!SendErrors)
@@ -344,28 +342,35 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
 					  Client_ID(Client), Req->prefix);
 	}
 
-	while (*targetList) {
-		if (*targetList == ',') {
-			*targetList = '\0';
-			targetCount++;
-		}
-		targetList++;
-	}
+	/* handle msgtarget = msgto *("," msgto) */
+	currentTarget = strtok_r(currentTarget, ",", &lastCurrentTarget);
 
-	while (targetCount > 0) {
+	while (currentTarget) {
+		/* Check for and handle valid <msgto> of form:
+		 * RFC 2812 2.3.1:
+		 *   msgto =  channel / ( user [ "%" host ] "@" servername )
+		 *   msgto =/ ( user "%" host ) / targetmask
+		 *   msgto =/ nickname / ( nickname "!" user "@" host )
+		 */
 		if (strchr(currentTarget, '!') == NULL)
+			/* nickname */
 			cl = Client_Search(currentTarget);
 		else
 			cl = NULL;
+
 		if (cl == NULL) {
-			char target[513]; // max mesage length plus null terminator
+			/* If currentTarget isn't a nickname check for:
+			 * user ["%" host] "@" servername
+			 * user "%" host
+			 * nickname "!" user "@" host
+			 */
+			char target[COMMAND_LEN];
 			char * nick = NULL;
 			char * user = NULL;
 			char * host = NULL;
 			char * server = NULL;
 
-			strncpy(target, currentTarget, 512);
-			target[512] = '\0';
+			strlcpy(target, currentTarget, COMMAND_LEN);
 			server = strchr(target, '@');
 			if (server) {
 				*server = '\0';
@@ -378,32 +383,34 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
 			}
 			user = strchr(target, '!');
 			if (user) {
+				/* msgto form: nick!user@host */
 				*user = '\0';
 				user++;
 				nick = target;
-				host = server; // <msgto> form: nick!user@host
+				host = server; /* not "@server" but "@host" */
 			} else {
 				user = target;
 			}
 
-			if (user != NULL) {
-				for (cl = Client_First(); cl != NULL; cl = Client_Next(cl)) {
-					if (Client_Type(cl) != CLIENT_USER)
-						continue;
-					if (nick != NULL) {
-						if (strcmp(nick, Client_ID(cl)) == 0 && strcmp(user, Client_User(cl)) == 0 && strcasecmp(host, Client_Hostname(cl)) == 0)
-							break;
-						else
-							continue;
-					}
-					if (strcasecmp(user, Client_User(cl)) != 0)
-						continue;
-					if (host != NULL && strcasecmp(host, Client_Hostname(cl)) != 0)
-						continue;
-					if (server != NULL && strcasecmp(server, Client_ID(Client_Introducer(cl))) != 0)
-						continue;
-					break;
+			for (cl = Client_First(); cl != NULL; cl = Client_Next(cl)) {
+				if (Client_Type(cl) != CLIENT_USER)
+					continue;
+				if (nick != NULL) {
+					if (strcmp(nick, Client_ID(cl)) == 0 &&
+							strcmp(user, Client_User(cl)) == 0 &&
+							strcasecmp(host, Client_Hostname(cl)) == 0)
+						break;
+					else
+						continue;
 				}
+				if (strcasecmp(user, Client_User(cl)) != 0)
+					continue;
+				if (host != NULL && strcasecmp(host, Client_Hostname(cl)) != 0)
+					continue;
+				if (server != NULL && strcasecmp(server,
+				 		Client_ID(Client_Introducer(cl))) != 0)
+					continue;
+				break;
 			}
 		}
 
@@ -416,8 +423,8 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
 							  Client_ID(from),
 							  currentTarget))
 					return false;
-			} else if ((Client_Type(Client) != CLIENT_SERVER
-						&& (strchr(Client_Modes(cl), 'a')))) {
+			} else if (SendErrors && (Client_Type(Client) != CLIENT_SERVER)
+						&& strchr(Client_Modes(cl), 'a')) {
 				/* Target is away */
 				if (!SendErrors)
 					return true;
@@ -425,18 +432,22 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
 				    (from, RPL_AWAY_MSG, Client_ID(from), Client_ID(cl),
 				     Client_Away(cl)))
 					return DISCONNECTED;
-			}	if (Client_Conn(from) > NONE) {
+			}
+			if (Client_Conn(from) > NONE) {
 				Conn_UpdateIdle(Client_Conn(from));
 			}
 			if (!IRC_WriteStrClientPrefix(cl, from, "PRIVMSG %s :%s",
 						Client_ID(cl), Req->argv[1]))
 				return false;
 		} else if (strchr("$#", currentTarget[0]) && strchr(currentTarget, '.')) {
-			if (!Send_Message_Mask(from, currentTarget, Req->argv[1], SendErrors))
+			/* targetmask */
+			if (!Send_Message_Mask(from, currentTarget, Req->argv[1],
+			 		SendErrors))
 				return false;
 		} else if ((chan = Channel_Search(currentTarget))) {
-				if (!Channel_Write(chan, from, Client, Req->argv[1]))
-					return false;
+			/* channel */
+			if (!Channel_Write(chan, from, Client, Req->argv[1]))
+				return false;
 		} else {
 			if (!SendErrors)
 				return true;
@@ -445,11 +456,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
 				return false;
 		}
 
-		while (*currentTarget)
-			currentTarget++;
-
-		currentTarget++;
-		targetCount--;
+		currentTarget = strtok_r(NULL, ",", &lastCurrentTarget);
 	}
 
 	return CONNECTED;
@@ -478,16 +485,19 @@ Send_Message_Mask(CLIENT * from, char * targetMask, ch
 				continue;
 			client_match = MatchCaseInsensitive(mask, Client_Hostname(cl));
 			if (client_match)
-				if (!IRC_WriteStrClientPrefix(cl, from, "PRIVMSG %s :%s", Client_ID(cl), message))
+				if (!IRC_WriteStrClientPrefix(cl, from, "PRIVMSG %s :%s",
+				 		Client_ID(cl), message))
 					return false;
 		}
 	} else {
 		for (cl = Client_First(); cl != NULL; cl = Client_Next(cl)) {
 			if (Client_Type(cl) != CLIENT_USER)
 				continue;
-			client_match = MatchCaseInsensitive(mask, Client_ID(Client_Introducer(cl)));
+			client_match = MatchCaseInsensitive(mask,
+			 		Client_ID(Client_Introducer(cl)));
 			if (client_match)
-				if (!IRC_WriteStrClientPrefix(cl, from, "PRIVMSG %s :%s", Client_ID(cl), message))
+				if (!IRC_WriteStrClientPrefix(cl, from, "PRIVMSG %s :%s",
+				 		Client_ID(cl), message))
 					return false;
 		}
 	}
@@ -495,16 +505,4 @@ Send_Message_Mask(CLIENT * from, char * targetMask, ch
 } /* Send_Message_Mask */
 
 
-static bool
-MatchCaseInsensitive(const char *pattern, const char *searchme)
-{
-	char haystack[COMMAND_LEN];
-
-	strlcpy(haystack, searchme, sizeof(haystack));
-
-	ngt_LowerStr(haystack);
-
-	return Match(pattern, haystack);
-}
-
 /* -eof- */
blob - 8f2fa2a60da60e2fb4a52b8a402e85c1aa7edd55
blob + 0f9009df815469ac9a97377127dc50cb72fe9bc3
--- src/ngircd/match.c
+++ src/ngircd/match.c
@@ -22,6 +22,8 @@ static char UNUSED id[] = "$Id: match.c,v 1.5 2006/10/
 
 #include "exp.h"
 #include "match.h"
+#include "defines.h"
+#include "tool.h"
 
 
 /*
@@ -53,6 +55,19 @@ Match( const char *Pattern, const char *String )
 } /* Match */
 
 
+GLOBAL bool
+MatchCaseInsensitive(const char *pattern, const char *searchme)
+{
+	char haystack[COMMAND_LEN];
+
+	strlcpy(haystack, searchme, sizeof(haystack));
+
+	ngt_LowerStr(haystack);
+
+	return Match(pattern, haystack);
+} /* MatchCaseInsensitive */
+
+
 static int
 Matche( const char *p, const char *t )
 {
blob - ac1aa962d9948b47067e7567d3b00f110349ca1a
blob + 0e8df74a25df204f50ce896247c12a9c81ea3134
--- src/ngircd/match.h
+++ src/ngircd/match.h
@@ -19,6 +19,7 @@
 
 
 GLOBAL bool Match PARAMS(( const char *Pattern, const char *String ));
+GLOBAL bool MatchCaseInsensitive PARAMS(( const char *Pattern, const char *searchme ));
 
 
 #endif
blob - 000334649d53e07230e36cff0c7be7c0a2abdb3c
blob + dd164822e418292bd46a412ffb76319e79257a39
--- src/testsuite/message-test.e
+++ src/testsuite/message-test.e
@@ -1,5 +1,3 @@
-# $Id: mode-test.e,v 1.7 2008/02/16 11:27:49 fw Exp $
-
 spawn telnet localhost 6789
 expect {
 	timeout { exit 1 }
@@ -43,14 +41,31 @@ expect {
 	"@* PRIVMSG nick :test\r*401*@* PRIVMSG nick :test"
 }
 
-send "JOIN #testChannel\r"
-
 send "privmsg doesnotexist :test\r"
 expect {
 	timeout { exit 1 }
 	"401"
 }
 
+send "privmsg ~user@ngircd.test.server :test\r"
+expect {
+	timeout { exit 1 }
+	"@* PRIVMSG nick :test"
+}
+
+
+send "privmsg ~user\%localhost :test\r"
+expect {
+	timeout { exit 1 }
+	"@* PRIVMSG nick :test"
+}
+
+send "privmsg nick!~user@localhost :test\r"
+expect {
+	timeout { exit 1 }
+	"@* PRIVMSG nick :test"
+}
+
 send "away :away\r"
 expect {
 	timeout { exit 1 }