diff options
author | Eric Covener <covener@apache.org> | 2023-03-11 23:10:09 +0100 |
---|---|---|
committer | Eric Covener <covener@apache.org> | 2023-03-11 23:10:09 +0100 |
commit | 3fc1d07f3b33412a123311e7147be7a60bd31238 (patch) | |
tree | 07d0786532aecd2b3aa1dfbabac81c6159fdaf5c | |
parent | followup to r1908296: only for redirects (diff) | |
download | apache2-3fc1d07f3b33412a123311e7147be7a60bd31238.tar.xz apache2-3fc1d07f3b33412a123311e7147be7a60bd31238.zip |
add [BCTLS] alternative to [B] for 2.4.56 problems
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1908301 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | changes-entries/rewrite-bctls | 3 | ||||
-rw-r--r-- | docs/manual/rewrite/flags.xml | 7 | ||||
-rw-r--r-- | modules/mappers/mod_rewrite.c | 31 |
3 files changed, 34 insertions, 7 deletions
diff --git a/changes-entries/rewrite-bctls b/changes-entries/rewrite-bctls new file mode 100644 index 0000000000..2d567c9a2f --- /dev/null +++ b/changes-entries/rewrite-bctls @@ -0,0 +1,3 @@ + *) mod_rewrite: Add BCTLS flag similar to B, but only escaping the characters + checked by 2.4.56 in the query string. [Eric Covener] + diff --git a/docs/manual/rewrite/flags.xml b/docs/manual/rewrite/flags.xml index c199ee0f6c..3e2012153f 100644 --- a/docs/manual/rewrite/flags.xml +++ b/docs/manual/rewrite/flags.xml @@ -119,6 +119,13 @@ will be used in the path component rather than the query string.</p> <p>This flag is available in version 2.4.26 and later.</p> +<section id="flag_bctls"><title>BCTLS</title> + <p>The [BCTLS] flag is simular to the [B] flag, but only escapes + control characters and the space character. This is the same set of + characters rejected when they are copied into the query string unencoded. + </p> +<p>This flag is available in version 2.5.1 and later.</p> + </section> <section id="flag_c"><title>C|chain</title> diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index 8f81a89715..458d0c0e8e 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -174,6 +174,7 @@ static const char* really_last_key = "rewrite_really_last"; #define RULEFLAG_ESCAPENOPLUS (1<<18) #define RULEFLAG_QSLAST (1<<19) #define RULEFLAG_QSNONE (1<<20) /* programattic only */ +#define RULEFLAG_ESCAPECTLS (1<<21) /* return code of the rewrite rule * the result may be escaped - or not @@ -425,7 +426,7 @@ static apr_global_mutex_t *rewrite_mapr_lock_acquire = NULL; static const char *rewritemap_mutex_type = "rewrite-map"; /* Optional functions imported from mod_ssl when loaded: */ -static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int noplus); +static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int flags); /* * +-------------------------------------------------------+ @@ -684,14 +685,27 @@ static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix, * Escapes a backreference in a similar way as php's urlencode does. * Based on ap_os_escape_path in server/util.c */ -static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int noplus) { +static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int flags) { char *copy = apr_palloc(p, 3 * strlen(path) + 3); const unsigned char *s = (const unsigned char *)path; unsigned char *d = (unsigned char *)copy; unsigned c; + int noplus = flags & RULEFLAG_ESCAPENOPLUS; + int ctls = flags & RULEFLAG_ESCAPECTLS; while ((c = *s)) { - if (!escapeme) { + if (ctls) { + if (c == ' ' && !noplus) { + *d++ = '+'; + } + else if (apr_iscntrl(c)) { + d = c2x(c, '%', d); + } + else { + *d++ = c; + } + } + else if (!escapeme) { if (apr_isalnum(c) || c == '_') { *d++ = c; } @@ -702,9 +716,9 @@ static char *escape_backref(apr_pool_t *p, const char *path, const char *escapem d = c2x(c, '%', d); } } - else { + else { const char *esc = escapeme; - while (*esc) { + while (*esc) { if (c == *esc) { if (c == ' ' && !noplus) { *d++ = '+'; @@ -2497,7 +2511,7 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry, /* escape the backreference */ char *tmp2, *tmp; tmp = apr_pstrmemdup(pool, bri->source + bri->regmatch[n].rm_so, span); - tmp2 = escape_backref(pool, tmp, entry->escapes, entry->flags & RULEFLAG_ESCAPENOPLUS); + tmp2 = escape_backref(pool, tmp, entry->escapes, entry->flags); rewritelog(ctx->r, 5, ctx->perdir, "escaping backreference '%s' to '%s'", tmp, tmp2); @@ -3585,13 +3599,16 @@ static const char *cmd_rewriterule_setflag(apr_pool_t *p, void *_cfg, case 'B': if (!*key || !strcasecmp(key, "ackrefescaping")) { cfg->flags |= RULEFLAG_ESCAPEBACKREF; - if (val && *val) { + if (val && *val) { cfg->escapes = val; } } else if (!strcasecmp(key, "NP") || !strcasecmp(key, "ackrefernoplus")) { cfg->flags |= RULEFLAG_ESCAPENOPLUS; } + else if (!strcasecmp(key, "CTLS")) { + cfg->flags |= RULEFLAG_ESCAPECTLS|RULEFLAG_ESCAPEBACKREF; + } else { ++error; } |