[MEDIUM] http: add support for conditional request header addition

Now the reqadd rules also support ACLs. All req* rules are converted
now.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index e3d38f1..e6cffa9 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -3578,7 +3578,7 @@
   See also : "option redispatch"
 
 
-reqadd  <string>
+reqadd  <string> [{if | unless} <cond>]
   Add a header at the end of the HTTP request
   May be used in sections :   defaults | frontend | listen | backend
                                  no    |    yes   |   yes  |   yes
@@ -3587,6 +3587,9 @@
               must be escaped using a backslash ('\'). Please refer to section
               6 about HTTP header manipulation for more information.
 
+    <cond>    is an optional matching condition built from ACLs. It makes it
+              possible to ignore this rule when other conditions are not met.
+
   A new line consisting in <string> followed by a line feed will be added after
   the last header of an HTTP request.
 
@@ -3594,7 +3597,12 @@
   and not to traffic generated by HAProxy, such as health-checks or error
   responses.
 
-  See also: "rspadd" and section 6 about HTTP header manipulation
+  Example : add "X-Proto: SSL" to requests coming via port 81
+     acl is-ssl  dst_port       81
+     reqadd      X-Proto:\ SSL  if is-ssl
+
+  See also: "rspadd", section 6 about HTTP header manipulation, and section 7
+            about ACLs.
 
 
 reqallow  <search> [{if | unless} <cond>]
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 4e724b2..c7f549d 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -3738,7 +3738,24 @@
 			goto out;
 		}
 
+		if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
+			if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
+				Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
+				      file, linenum, args[0]);
+				err_code |= ERR_ALERT | ERR_FATAL;
+				goto out;
+			}
+			err_code |= warnif_cond_requires_resp(cond, file, linenum);
+		}
+		else if (*args[2]) {
+			Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
+			      file, linenum, args[0], args[2]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+
 		wl = calloc(1, sizeof(*wl));
+		wl->cond = cond;
 		wl->s = strdup(args[1]);
 		LIST_ADDQ(&curproxy->req_add, &wl->list);
 		warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
diff --git a/src/proto_http.c b/src/proto_http.c
index 9759635..1ee2307 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2851,6 +2851,15 @@
 
 	/* add request headers from the rule sets in the same order */
 	list_for_each_entry(wl, &px->req_add, list) {
+		if (wl->cond) {
+			int ret = acl_exec_cond(wl->cond, px, s, txn, ACL_DIR_REQ);
+			ret = acl_pass(ret);
+			if (((struct acl_cond *)wl->cond)->pol == ACL_COND_UNLESS)
+				ret = !ret;
+			if (!ret)
+				continue;
+		}
+
 		if (unlikely(http_header_add_tail(req, &txn->req, &txn->hdr_idx, wl->s) < 0))
 			goto return_bad_req;
 	}