* and ap_proxy_tunnel_run() to proxy_util.
* 20190312.6 (2.5.1-dev) Add proxy check_trans hook
* 20190312.7 (2.5.1-dev) AP_REG_DEFAULT macro in ap_regex.h
+ * 20190312.8 (2.5.1-dev) ap_is_chunked() in httpd.h
*/
#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20190312
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 7 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 8 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
AP_DECLARE(const char *)ap_dir_fnmatch(ap_dir_match_t *w, const char *path,
const char *fname) __attribute__((nonnull(1,3)));
+/**
+ * Determine if the final Transfer-Encoding is "chunked".
+ *
+ * @param p The pool to allocate from
+ * @param line the header field-value to scan
+ * @return 1 if the last Transfer-Encoding is "chunked", else 0
+ */
+AP_DECLARE(int) ap_is_chunked(apr_pool_t *p, const char *line);
+
#ifdef __cplusplus
}
#endif
lenp = apr_table_get(f->r->headers_in, "Content-Length");
if (tenc) {
- if (ap_cstr_casecmp(tenc, "chunked") == 0 /* fast path */
- || ap_find_last_token(f->r->pool, tenc, "chunked")) {
+ if (ap_is_chunked(f->r->pool, tenc)) {
ctx->state = BODY_CHUNK;
}
else if (f->r->proxyreq == PROXYREQ_RESPONSE) {
&& (r->header_only
|| AP_STATUS_IS_HEADER_ONLY(r->status)
|| apr_table_get(r->headers_out, "Content-Length")
- || ap_find_last_token(r->pool,
+ || ap_is_chunked(r->pool,
apr_table_get(r->headers_out,
- "Transfer-Encoding"),
- "chunked")
+ "Transfer-Encoding"))
|| ((r->proto_num >= HTTP_VERSION(1,1))
&& (r->chunked = 1))) /* THIS CODE IS CORRECT, see above. */
&& r->server->keep_alive
if (!(r->header_only
|| AP_STATUS_IS_HEADER_ONLY(r->status)
|| apr_table_get(r->headers_out, "Content-Length")
- || ap_find_last_token(r->pool, apr_table_get(r->headers_out,
- "Transfer-Encoding"), "chunked")
+ || ap_is_chunked(r->pool, apr_table_get(r->headers_out,
+ "Transfer-Encoding"))
|| r->proto_num >= HTTP_VERSION(1, 1))) {
handle_policy(r, result, "Keepalive should be possible (supply Content-Length or HTTP/1.1 Transfer-Encoding)",
* the final encoding ...; the server MUST respond with the 400
* (Bad Request) status code and then close the connection".
*/
- if (!(ap_cstr_casecmp(tenc, "chunked") == 0 /* fast path */
- || ap_find_last_token(r->pool, tenc, "chunked"))) {
+ if (!ap_is_chunked(r->pool, tenc)) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02539)
"client sent unknown Transfer-Encoding "
"(%s): %s", tenc, r->uri);
}
}
-
-AP_DECLARE(int) ap_find_last_token(apr_pool_t *p, const char *line,
- const char *tok)
+static const char *find_last_token(apr_pool_t *p, const char *line,
+ const char *tok)
{
int llen, tlen, lidx;
if (!line)
- return 0;
+ return NULL;
llen = strlen(line);
tlen = strlen(tok);
if (lidx < 0 ||
(lidx > 0 && !(apr_isspace(line[lidx - 1]) || line[lidx - 1] == ',')))
+ return NULL;
+
+ if (ap_cstr_casecmpn(&line[lidx], tok, tlen) == 0) {
+ return &line[lidx];
+ }
+ return NULL;
+}
+
+AP_DECLARE(int) ap_find_last_token(apr_pool_t *p, const char *line,
+ const char *tok)
+{
+ return find_last_token(p, line, tok) != NULL;
+}
+
+AP_DECLARE(int) ap_is_chunked(apr_pool_t *p, const char *line)
+{
+ const char *s;
+
+ if (!line)
return 0;
+ if (!ap_cstr_casecmp(line, "chunked")) {
+ return 1;
+ }
- return (ap_cstr_casecmpn(&line[lidx], tok, tlen) == 0);
+ s = find_last_token(p, line, "chunked");
+
+ if (!s) return 0;
+
+ /* eat spaces right-to-left to see what precedes "chunked" */
+ while (--s > line) {
+ if (*s != ' ') break;
+ }
+
+ /* found delim, or leading ws (input wasn't parsed by httpd as a header) */
+ if (*s == ',' || *s == ' ') {
+ return 1;
+ }
+ return 0;
}
AP_DECLARE(char *) ap_escape_shell_cmd(apr_pool_t *p, const char *str)