repo: ngircd
action: commit
revision: 
path_from: 
revision_from: a84f7dcee5a1b32c74188aa5374d30eddd24852b:
path_to: 
revision_to: 
git.thebackupbox.net
ngircd
git clone git://git.thebackupbox.net/ngircd
commit a84f7dcee5a1b32c74188aa5374d30eddd24852b
Author: Alexander Barton 
Date:   Wed Jun 11 16:00:38 2008 +0200

    Allow mixed line terminations (CR+LF/CR/LF) in non-RFC-compliant mode

    Up to now ngIRCd accepted CR+LF as well as a single CR or LF in "non RFC
    compliant" mode (the default). But ngIRCd became confused when it received
    data containing mixed line endings (e. g. "111\r222\n333\r\n").

    This patch enables ngIRCd (in "non RFC compliant" mode) to detect CR+LF,
    CR, and LF as equally good line termination sequences and to always end the
    command after the first one detected.

    Some clients (for exmaple Trilian) are that ... broken to send such mixed
    line terminations ...

    First patch proposed by Scott Perry ,
    Thanks to Ali Shemiran  for testing!

diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c
index decfeb684ef26b7027b6758c9e003ae65bf1bc0d..
index ..2e23ade8e8bf406a7c2c2f3771e8fe17abc1fce6 100644
--- a/src/ngircd/conn.c
+++ b/src/ngircd/conn.c
@@ -1238,7 +1238,7 @@ static void
 Handle_Buffer(CONN_ID Idx)
 {
 #ifndef STRICT_RFC
-	char *ptr1, *ptr2;
+	char *ptr1, *ptr2, *first_eol;
 #endif
 	char *ptr;
 	size_t len, delta;
@@ -1280,19 +1280,28 @@ Handle_Buffer(CONN_ID Idx)
 		ptr = strstr(array_start(&My_Connections[Idx].rbuf), "\r\n");

 #ifndef STRICT_RFC
-		if (!ptr) {
-			/* Check for non-RFC-compliant request (only CR or
-			 * LF)? Unfortunately, there are quite a few clients
-			 * out there that do this -- incl. "mIRC" :-( */
-			delta = 1;
-			ptr1 = strchr(array_start(&My_Connections[Idx].rbuf), '\r');
-			ptr2 = strchr(array_start(&My_Connections[Idx].rbuf), '\n');
+		/* Check for non-RFC-compliant request (only CR or LF)?
+		 * Unfortunately, there are quite a few clients out there
+		 * that do this -- e. g. mIRC, BitchX, and Trillian :-( */
+		ptr1 = strchr(array_start(&My_Connections[Idx].rbuf), '\r');
+		ptr2 = strchr(array_start(&My_Connections[Idx].rbuf), '\n');
+		if (ptr) {
+			/* Check if there is a single CR or LF _before_ the
+			 * corerct CR+LF line terminator:  */
+			first_eol = ptr1 < ptr2 ? ptr1 : ptr2;
+			if (first_eol < ptr) {
+				/* Single CR or LF before CR+LF found */
+				ptr = first_eol;
+				delta = 1;
+			}
+		} else if (ptr1 || ptr2) {
+			/* No CR+LF terminated command found, but single
+			 * CR or LF found ... */
 			if (ptr1 && ptr2)
-				ptr = ptr1 > ptr2 ? ptr2 : ptr1;
-			else if (ptr1)
-				ptr = ptr1;
-			else if (ptr2)
-				ptr = ptr2;
+				ptr = ptr1 < ptr2 ? ptr1 : ptr2;
+			else
+				ptr = ptr1 ? ptr1 : ptr2;
+			delta = 1;
 		}
 #endif

diff --git a/src/ngircd/parse.c b/src/ngircd/parse.c
index 00ae3cd7e93d5f415a596d3d4c6b50ffb27c7817..
index ..24de2bc818efb9a0893c4836e8ae41d8e6084a7b 100644
--- a/src/ngircd/parse.c
+++ b/src/ngircd/parse.c
@@ -340,12 +340,20 @@ Validate_Command( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed )
 static bool
 Validate_Args(CONN_ID Idx, REQUEST *Req, bool *Closed)
 {
+#ifdef STRICT_RFC
 	int i;
+#endif

 	assert( Idx >= 0 );
 	assert( Req != NULL );
 	*Closed = false;

+#ifdef STRICT_RFC
+	/* CR and LF are never allowed in command parameters.
+	 * But since we do accept lines terminated only with CR or LF in
+	 * "non-RFC-compliant mode" (besides the correct CR+LF combination),
+	 * this check can only trigger in "strict RFC" mode; therefore we
+	 * optimize it away otherwise ... */
 	for (i = 0; i < Req->argc; i++) {
 		if (strchr(Req->argv[i], '\r') || strchr(Req->argv[i], '\n')) {
 			Log(LOG_ERR,
@@ -357,6 +365,8 @@ Validate_Args(CONN_ID Idx, REQUEST *Req, bool *Closed)
 			return false;
 		}
 	}
+#endif
+
 	return true;
 } /* Validate_Args */

-----END OF PAGE-----