From a63bf4d4e3217119872496853225930370b9d079 Mon Sep 17 00:00:00 2001
From: cyan <>
Date: Fri, 3 Feb 2006 09:13:58 +0000
Subject: [PATCH] * searchbyserver() split out into two functions, correcting
 the bug which   would cause a server with a wildcard C:Line to continue to
 attempt to   connect to its uplink even after a connection was established. *
 When connecting to another server, it was possible that the IRCd would   send
 its PASS/SERVER command pair again in error.  This would generate   warning
 messages on the receiving server side stating "Refusing to comply   with
 supposedly bogus SERVER command." * When a channel was both +k and +l, the
 IRCd would incorrectly interpret   the incoming SJOIN message for that
 channel.  (i.e. +kl 1 1 would return   +k 11) * The IRCd now crunches modes
 on an incoming SJOIN message.

---
 exec/ircd.js             | 44 +++++++++++++++++++++-------------------
 exec/load/ircd_server.js | 28 ++++++++++++++++++++-----
 exec/load/ircd_unreg.js  |  6 +++---
 3 files changed, 49 insertions(+), 29 deletions(-)

diff --git a/exec/ircd.js b/exec/ircd.js
index eb30e4436c..931990c697 100644
--- a/exec/ircd.js
+++ b/exec/ircd.js
@@ -127,30 +127,32 @@ function terminate_everything(terminate_reason, error) {
 	exit(error);
 }
 
-function searchbyserver(server_name,ignore_wildcards) {
+function search_server_only(server_name) {
 	if (!server_name)
 		return 0;
-	if ((ignore_wildcards &&
-	    (servername.toUpperCase() == server_name.toUpperCase()) ) ||
-	   (!ignore_wildcards && IRC_match(servername,server_name)) )
-		return -1; // the server passed to us is our own.
 	for(thisServer in Servers) {
 		var Server=Servers[thisServer];
-		if ((ignore_wildcards && 
-		    (Server.nick.toUpperCase() == server_name.toUpperCase())) ||
-		   (!ignore_wildcards &&
-		     IRC_match(Server.nick,server_name) ) )
+		if (IRC_match(Server.nick,server_name))
 			return Server;
 	}
-	// No wildcards implies not doing searches on nicks, either.
-	if (ignore_wildcards)
+	if (IRC_match(servername,server_name))
+		return -1; // the server passed to us is our own.
+	// No success.
+	return 0;
+}
+
+function searchbyserver(servnick) {
+	if (!servnick)
 		return 0;
-	// if we've had no success so far, try nicknames and glean a server
-	// from there.
-	for(thisNick in Users) {
-		var Nick=Users[thisNick];
-		if (IRC_match(Nick.nick,server_name))
-			return searchbyserver(Nick.servername);
+	var server_try = search_server_only(servnick);
+	if (server_try) {
+		return server_try;
+	} else {
+		for(thisNick in Users) {
+			var Nick=Users[thisNick];
+			if (IRC_match(Nick.nick,servnick))
+				return search_server_only(Nick.servername);
+		}
 	}
 	return 0; // looks like we failed after all that hard work :(
 }
@@ -407,7 +409,7 @@ function connect_to_server(this_cline,the_port) {
 		new_id = "id" + next_client_id;
 		next_client_id++;
 		Unregistered[new_id]=new Unregistered_Client(new_id,connect_sock);
-		Unregistered[new_id].sentps = true;
+		Unregistered[new_id].sendps = false; // Don't do P/S pair again
 	}
 	this_cline.lastconnect = time();
 }
@@ -785,7 +787,7 @@ while (!server.terminated) {
 	for(thisCL in CLines) {
 		my_cline = CLines[thisCL];
 		if (my_cline.port && YLines[my_cline.ircclass].connfreq &&
-		    !searchbyserver(my_cline.servername,true) &&
+		    (search_server_only(my_cline.servername) < 1) &&
 		     ((time() - my_cline.lastconnect) >
 		     YLines[my_cline.ircclass].connfreq)
 		   ) {
@@ -2762,13 +2764,13 @@ function IRCClient_check_sendq() {
 	}
 }
 
-function IRCClient_finalize_server_connect(states) {
+function IRCClient_finalize_server_connect(states,sendps) {
 	hcc_counter++;
 	gnotice("Link with " + this.nick + "[unknown@" + this.hostname +
 		"] established, states: " + states);
 	if (server.client_update != undefined)
 		server.client_update(this.socket, this.nick, this.hostname);
-	if (!this.sentps) {
+	if (sendps) {
 		for (cl in CLines) {
 			if(IRC_match(this.nick,CLines[cl].servername)) {
 				this.rawout("PASS " + CLines[cl].password + " :" + states);
diff --git a/exec/load/ircd_server.js b/exec/load/ircd_server.js
index a4ed81f239..f687c5963e 100644
--- a/exec/load/ircd_server.js
+++ b/exec/load/ircd_server.js
@@ -576,7 +576,7 @@ function Server_Work() {
 					ns.info = my_server.realname;
 					ns.socket = my_server.socket;
 					delete Unregistered[my_server.id];
-					ns.finalize_server_connect("QWK");
+					ns.finalize_server_connect("QWK",true);
 					break;
 				} else if (dest_server) {
 					if (dest_server == -1)
@@ -697,16 +697,34 @@ function Server_Work() {
 			var cm_array;
 
 			if (cmd[3]) {
-				var mode_args = "";
+				var incoming_modes = new Array;
 				var tmp_modeargs = 0;
 
 				for (tmpmc in cmd[3]) {
-					if ((cmd[3][tmpmc] == "k") ||
-					    (cmd[3][tmpmc] == "l")) {
+					var my_modechar = cmd[3][tmpmc];
+					if (my_modechar == "+")
+						continue;
+					if ((my_modechar == "k") ||
+					    (my_modechar == "l")) {
 						tmp_modeargs++;
-						mode_args += cmd[3 + tmp_modeargs];
+						incoming_modes[my_modechar] = cmd[3 + tmp_modeargs];
+					} else {
+						incoming_modes[my_modechar] = true;
 					}
 				}
+
+				/* Reconstruct our modes into a string now */
+				var mode_args_chars = "+";
+				var mode_args_args = "";
+				for (my_mc in incoming_modes) {
+					mode_args_chars += my_mc;
+					if ((my_mc == "k") || (my_mc == "l")) {
+						mode_args_args += " " + incoming_modes[my_mc];
+					}
+				}
+				var mode_args = mode_args_chars + mode_args_args;
+
+				/* The following corrects a bug in Bahamut.. */
 				if ((cmd[4] == "") && cmd[5])
 					tmp_modeargs++;
 				
diff --git a/exec/load/ircd_unreg.js b/exec/load/ircd_unreg.js
index 29707be46c..cc5527c372 100644
--- a/exec/load/ircd_unreg.js
+++ b/exec/load/ircd_unreg.js
@@ -27,7 +27,6 @@ function Unregistered_Client(id,socket) {
 	////////// VARIABLES
 	// Bools/Flags that change depending on connection state.
 	this.pinged = false;	   // Sent PING?
-	this.sentps = false;	   // Sent PASS/SERVER?
 	this.local = true;	   // FIXME: this is redundant.
 	this.criteria_met = false; // Have we met registration criteria?
 	// Variables containing user/server information as we receive it.
@@ -42,6 +41,7 @@ function Unregistered_Client(id,socket) {
 	this.ip = socket.remote_ip_address;
 	this.pending_resolve = false;
 	this.pending_resolve_time = time();
+	this.sendps = true; // Send the PASS/SERVER pair by default.
 	// Variables (consts, really) that point to various state information
 	this.socket = socket;
 	////////// FUNCTIONS
@@ -198,7 +198,7 @@ function Unregistered_Commands() {
 				}
 			}
 			if ( (!this_nline ||
-			      ( (this_nline.password == "*") && !this.sentps &&
+			      ( (this_nline.password == "*") && 
 				!(this_nline.flags&NLINE_CHECK_QWKPASSWD) )
 			     ) && !qwk_slave) {
 				this.quit("Server not configured.");
@@ -237,7 +237,7 @@ function Unregistered_Commands() {
 					}
 				}
 			}
-			new_server.finalize_server_connect("TS");
+			new_server.finalize_server_connect("TS",this.sendps);
 			break;
 		case "USER":
 			if (this.uprefix)
-- 
GitLab