MEDIUM: stream-int: replace occurrences of si->appctx with si_appctx()

We're about to remove si->appctx, so first let's replace all occurrences
of its usage with a dynamic extract from si->end. A lot of code was changed
by search-n-replace, but the behaviour was intentionally not altered.

The code surrounding calls to stream_int_register_handler() was slightly
changed since we can only use si->end *after* the registration.
diff --git a/src/proto_http.c b/src/proto_http.c
index 64de612..1c5ae3d 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2795,7 +2795,8 @@
  * and program a response message if something was unexpected. It cannot fail
  * and always relies on the stats applet to complete the job. It does not touch
  * analysers nor counters, which are left to the caller. It does not touch
- * s->target which is supposed to already point to the stats applet.
+ * s->target which is supposed to already point to the stats applet. The caller
+ * is expected to have already assigned an appctx to the session.
  */
 int http_handle_stats(struct session *s, struct channel *req)
 {
@@ -2805,17 +2806,20 @@
 	struct http_msg *msg = &txn->req;
 	struct uri_auth *uri_auth = s->be->uri_auth;
 	const char *uri, *h, *lookup;
+	struct appctx *appctx;
 
-	memset(&si->appctx.ctx.stats, 0, sizeof(si->appctx.ctx.stats));
-	si->appctx.ctx.stats.st_code = STAT_STATUS_INIT;
-	si->appctx.ctx.stats.flags |= STAT_FMT_HTML; /* assume HTML mode by default */
+	appctx = si_appctx(si);
+	memset(&appctx->ctx.stats, 0, sizeof(appctx->ctx.stats));
+	appctx->st1 = appctx->st2 = 0;
+	appctx->ctx.stats.st_code = STAT_STATUS_INIT;
+	appctx->ctx.stats.flags |= STAT_FMT_HTML; /* assume HTML mode by default */
 
 	uri = msg->chn->buf->p + msg->sl.rq.u;
 	lookup = uri + uri_auth->uri_len;
 
 	for (h = lookup; h <= uri + msg->sl.rq.u_l - 3; h++) {
 		if (memcmp(h, ";up", 3) == 0) {
-			si->appctx.ctx.stats.flags |= STAT_HIDE_DOWN;
+			appctx->ctx.stats.flags |= STAT_HIDE_DOWN;
 			break;
 		}
 	}
@@ -2823,7 +2827,7 @@
 	if (uri_auth->refresh) {
 		for (h = lookup; h <= uri + msg->sl.rq.u_l - 10; h++) {
 			if (memcmp(h, ";norefresh", 10) == 0) {
-				si->appctx.ctx.stats.flags |= STAT_NO_REFRESH;
+				appctx->ctx.stats.flags |= STAT_NO_REFRESH;
 				break;
 			}
 		}
@@ -2831,7 +2835,7 @@
 
 	for (h = lookup; h <= uri + msg->sl.rq.u_l - 4; h++) {
 		if (memcmp(h, ";csv", 4) == 0) {
-			si->appctx.ctx.stats.flags &= ~STAT_FMT_HTML;
+			appctx->ctx.stats.flags &= ~STAT_FMT_HTML;
 			break;
 		}
 	}
@@ -2840,10 +2844,10 @@
 		if (memcmp(h, ";st=", 4) == 0) {
 			int i;
 			h += 4;
-			si->appctx.ctx.stats.st_code = STAT_STATUS_UNKN;
+			appctx->ctx.stats.st_code = STAT_STATUS_UNKN;
 			for (i = STAT_STATUS_INIT + 1; i < STAT_STATUS_SIZE; i++) {
 				if (strncmp(stat_status_codes[i], h, 4) == 0) {
-					si->appctx.ctx.stats.st_code = i;
+					appctx->ctx.stats.st_code = i;
 					break;
 				}
 			}
@@ -2851,8 +2855,8 @@
 		}
 	}
 
-	si->appctx.ctx.stats.scope_str = 0;
-	si->appctx.ctx.stats.scope_len = 0;
+	appctx->ctx.stats.scope_str = 0;
+	appctx->ctx.stats.scope_len = 0;
 	for (h = lookup; h <= uri + msg->sl.rq.u_l - 8; h++) {
 		if (memcmp(h, STAT_SCOPE_INPUT_NAME "=", strlen(STAT_SCOPE_INPUT_NAME) + 1) == 0) {
 			int itx = 0;
@@ -2862,7 +2866,7 @@
 
 			h += strlen(STAT_SCOPE_INPUT_NAME) + 1;
 			h2 = h;
-			si->appctx.ctx.stats.scope_str = h2 - msg->chn->buf->p;
+			appctx->ctx.stats.scope_str = h2 - msg->chn->buf->p;
 			while (*h != ';' && *h != '\0' && *h != '&' && *h != ' ' && *h != '\n') {
 				itx++;
 				h++;
@@ -2870,16 +2874,16 @@
 
 			if (itx > STAT_SCOPE_TXT_MAXLEN)
 				itx = STAT_SCOPE_TXT_MAXLEN;
-			si->appctx.ctx.stats.scope_len = itx;
+			appctx->ctx.stats.scope_len = itx;
 
-			/* scope_txt = search query, si->appctx.ctx.stats.scope_len is always <= STAT_SCOPE_TXT_MAXLEN */
+			/* scope_txt = search query, appctx->ctx.stats.scope_len is always <= STAT_SCOPE_TXT_MAXLEN */
 			memcpy(scope_txt, h2, itx);
 			scope_txt[itx] = '\0';
 			err = invalid_char(scope_txt);
 			if (err) {
 				/* bad char in search text => clear scope */
-				si->appctx.ctx.stats.scope_str = 0;
-				si->appctx.ctx.stats.scope_len = 0;
+				appctx->ctx.stats.scope_str = 0;
+				appctx->ctx.stats.scope_len = 0;
 			}
 			break;
 		}
@@ -2898,14 +2902,14 @@
 
 		if (ret) {
 			/* no rule, or the rule matches */
-			s->rep->prod->appctx.ctx.stats.flags |= STAT_ADMIN;
+			appctx->ctx.stats.flags |= STAT_ADMIN;
 			break;
 		}
 	}
 
 	/* Was the status page requested with a POST ? */
 	if (unlikely(txn->meth == HTTP_METH_POST && txn->req.body_len > 0)) {
-		if (si->appctx.ctx.stats.flags & STAT_ADMIN) {
+		if (appctx->ctx.stats.flags & STAT_ADMIN) {
 			if (msg->msg_state < HTTP_MSG_100_SENT) {
 				/* If we have HTTP/1.1 and Expect: 100-continue, then we must
 				 * send an HTTP/1.1 100 Continue intermediate response.
@@ -2922,21 +2926,19 @@
 				msg->msg_state = HTTP_MSG_100_SENT;
 				s->logs.tv_request = now;  /* update the request timer to reflect full request */
 			}
-			s->rep->prod->appctx.st0 = STAT_HTTP_POST;
+			appctx->st0 = STAT_HTTP_POST;
 		}
 		else {
-			si->appctx.ctx.stats.st_code = STAT_STATUS_DENY;
-			s->rep->prod->appctx.st0 = STAT_HTTP_LAST;
+			appctx->ctx.stats.st_code = STAT_STATUS_DENY;
+			appctx->st0 = STAT_HTTP_LAST;
 		}
 	}
 	else {
 		/* So it was another method (GET/HEAD) */
-		s->rep->prod->appctx.st0 = STAT_HTTP_HEAD;
+		appctx->st0 = STAT_HTTP_HEAD;
 	}
 
 	s->task->nice = -32; /* small boost for HTTP statistics */
-	stream_int_register_handler(s->rep->prod, &http_stats_applet);
-	s->rep->prod->appctx.st1 = s->rep->prod->appctx.st2 = 0;
 	return 1;
 }
 
@@ -3459,6 +3461,8 @@
 	if (!http_req_last_rule) {
 		if (stats_check_uri(s->rep->prod, txn, px)) {
 			s->target = &http_stats_applet.obj_type;
+			stream_int_register_handler(s->rep->prod, objt_applet(s->target));
+
 			/* parse the whole stats request and extract the relevant information */
 			http_handle_stats(s, req);
 			http_req_last_rule = http_req_get_intercept_rule(px, &px->uri_auth->http_req_rules, s, txn);