MEDIUM: h1: Add an option to sanitize connection headers during parsing

The flag H1_MF_CLEAN_CONN_HDR has been added to let the H1 parser sanitize
connection headers. It means it will remove all "close" and "keep-alive" values
during the parsing. One noticeable effect is that connection headers may be
unfolded. In practice, this is not a problem because it is not frequent to have
multiple values for the connection headers.

If this flag is set, during the parsing The function
h1_parse_next_connection_header() is called in a loop instead of
h1_parse_conection_header().

No need to backport this patch
diff --git a/src/h1.c b/src/h1.c
index 38d13c6..d89bcb5 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -132,15 +132,20 @@
  * "keep-alive", and "upgrade" values, and updating h1m->flags according to
  * what was found there. Note that flags are only added, not removed, so the
  * function is safe for being called multiple times if multiple occurrences
- * are found.
+ * are found. If the flag H1_MF_CLEAN_CONN_HDR, the header value is cleaned
+ * up from "keep-alive" and "close" values. To do so, the header value is
+ * rewritten in place and its length is updated.
  */
-void h1_parse_connection_header(struct h1m *h1m, struct ist value)
+void h1_parse_connection_header(struct h1m *h1m, struct ist *value)
 {
-	char *e, *n;
+	char *e, *n, *p;
 	struct ist word;
 
-	word.ptr = value.ptr - 1; // -1 for next loop's pre-increment
-	e = value.ptr + value.len;
+	word.ptr = value->ptr - 1; // -1 for next loop's pre-increment
+	p = value->ptr;
+	e = value->ptr + value->len;
+	if (h1m->flags & H1_MF_CLEAN_CONN_HDR)
+		value->len = 0;
 
 	while (++word.ptr < e) {
 		/* skip leading delimitor and blanks */
@@ -154,14 +159,33 @@
 		while (word.len && HTTP_IS_LWS(word.ptr[word.len-1]))
 			word.len--;
 
-		if (isteqi(word, ist("keep-alive")))
+		if (isteqi(word, ist("keep-alive"))) {
 			h1m->flags |= H1_MF_CONN_KAL;
-		else if (isteqi(word, ist("close")))
+			if (h1m->flags & H1_MF_CLEAN_CONN_HDR)
+				goto skip_val;
+		}
+		else if (isteqi(word, ist("close"))) {
 			h1m->flags |= H1_MF_CONN_CLO;
+			if (h1m->flags & H1_MF_CLEAN_CONN_HDR)
+				goto skip_val;
+		}
 		else if (isteqi(word, ist("upgrade")))
 			h1m->flags |= H1_MF_CONN_UPG;
 
-		word.ptr = n;
+		if (h1m->flags & H1_MF_CLEAN_CONN_HDR) {
+			if (value->ptr + value->len == p) {
+				/* no rewrite done till now */
+				value->len = n - value->ptr;
+			}
+			else {
+				if (value->len)
+					value->ptr[value->len++] = ',';
+				istcat(value, word, e - value->ptr);
+			}
+		}
+
+	  skip_val:
+		word.ptr = p = n;
 	}
 }
 
@@ -802,7 +826,11 @@
 					}
 				}
 				else if (isteqi(n, ist("connection"))) {
-					h1_parse_connection_header(h1m, v);
+					h1_parse_connection_header(h1m, &v);
+					if (!v.len) {
+						/* skip it */
+						break;
+					}
 				}
 
 				http_set_hdr(&hdr[hdr_count++], n, v);