[MAJOR] merged the 'setbe' actions to switch the backend on a regex

Sin Yu's patch to permit to change the proxy from a regex was merged
with little changes :
  - req_cap/rsp_cap are not reassigned to the new proxy, they stay
    attached to the frontend

  - the actions have been renamed "reqsetbe" and "reqisetbe" for
    "set BackEnd".

  - the buffer is not reset after the switch, instead, the headers are
    parsed again by the backend

  - in Sin's patch, it was theorically possible to switch multiple times,
    but the switching track was lost, making it impossible to apply
    server responsesin the reverse order. Now switching is limited to
    1 action (separation between frontend and backend) but the filters
    remain.

Now it will be extremely easy to add other switching conditions, such
as host matching, URI matching, etc...

There's still a hard work to be done on the logs and stats.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index b3747c4..0034bda 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -1416,6 +1416,46 @@
 	
 		chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
 	}
+	else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
+		regex_t *preg;
+		if(curproxy == &defproxy) {
+			Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
+			return -1;
+		}
+
+		if(*(args[1]) == 0 || *(args[2]) == 0) {
+			Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n", 
+				file, linenum, args[0]);
+			return -1;	
+		}
+		
+		preg = calloc(1, sizeof(regex_t));
+		if(regcomp(preg, args[1], REG_EXTENDED) != 0) {
+			Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
+		}
+
+		chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
+	}
+	else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
+		regex_t *preg;
+		if(curproxy == &defproxy) {
+			Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
+			return -1;
+		}
+
+		if(*(args[1]) == 0 || *(args[2]) == 0) {
+			Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n", 
+			      file, linenum, args[0]);
+			return -1;	
+		}
+		
+		preg = calloc(1, sizeof(regex_t));
+		if(regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
+			Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
+		}
+
+		chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
+	}
 	else if (!strcmp(args[0], "reqirep")) {  /* replace request header from a regex, ignoring case */
 		regex_t *preg;
 		if (curproxy == &defproxy) {
@@ -1945,8 +1985,6 @@
 			Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
 			return -1;
 		}
-	    
-	    
 	}
 	fclose(f);
 
@@ -2030,6 +2068,30 @@
 			}
 		}
 
+		if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
+			/* map jump target for ACT_SETBE in req_rep chain */ 
+			struct hdr_exp *exp;
+			struct proxy *target;
+			for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
+				if (exp->action != ACT_SETBE)
+					continue;
+				for (target = proxy; target != NULL; target = target->next) {
+					if (strcmp(target->id, exp->replace) == 0)
+						break;
+				}
+				if (target == NULL) {
+					Alert("parsing %s : backend '%s' in HTTP proxy %s was not found !\n", 
+						file, exp->replace, curproxy->id);
+					cfgerr++;
+				} else if (target == curproxy) {
+					Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
+					cfgerr++;
+				} else {
+					free((void *)exp->replace);
+					exp->replace = (const char *)target;
+				}
+			}
+		}
 		if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
 		    (!curproxy->clitimeout || !curproxy->contimeout || !curproxy->srvtimeout)) {
 			Warning("parsing %s : missing timeouts for listener '%s'.\n"