summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Covener <covener@apache.org>2023-03-11 23:10:09 +0100
committerEric Covener <covener@apache.org>2023-03-11 23:10:09 +0100
commit3fc1d07f3b33412a123311e7147be7a60bd31238 (patch)
tree07d0786532aecd2b3aa1dfbabac81c6159fdaf5c
parentfollowup to r1908296: only for redirects (diff)
downloadapache2-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-bctls3
-rw-r--r--docs/manual/rewrite/flags.xml7
-rw-r--r--modules/mappers/mod_rewrite.c31
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;
}