On Sat, Mar 11, 2023 at 11:10 PM <cove...@apache.org> wrote: > > Author: covener > Date: Sat Mar 11 22:10:09 2023 > New Revision: 1908301 > > URL: http://svn.apache.org/viewvc?rev=1908301&view=rev > Log: > add [BCTLS] alternative to [B] for 2.4.56 problems
Nice, that was the missing bit I think. Would have been great if [BCTLS] was the default but I guess it's not possible with the redirect case which %-encodes by default (chicken and egg problem to avoid double encoding..). > > +++ httpd/httpd/trunk/modules/mappers/mod_rewrite.c Sat Mar 11 22:10:09 2023 > @@ -684,14 +685,27 @@ static APR_INLINE unsigned char *c2x(uns > * 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)) { Seems we should encode space here too => (apr_iscntrl(c) || 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 * > d = c2x(c, '%', d); > } > } > - else { > + else { Maybe we could make [B=] and [BTCLS] not mutually exclusive (encode both controls and whatever in B=). I was thinking of a [BNEG] flag too (encode everything but what's in B=), and never encode alnum or '_', so all in all some further patch like the attached one. WDYT? Regards; Yann.
Index: modules/mappers/mod_rewrite.c =================================================================== --- modules/mappers/mod_rewrite.c (revision 1908321) +++ modules/mappers/mod_rewrite.c (working copy) @@ -99,6 +99,8 @@ #include "util_charset.h" #endif +#include "test_char.h" + static ap_dbd_t *(*dbd_acquire)(request_rec*) = NULL; static void (*dbd_prepare)(server_rec*, const char*, const char*) = NULL; static const char* really_last_key = "rewrite_really_last"; @@ -175,6 +177,7 @@ static const char* really_last_key = "rewrite_real #define RULEFLAG_QSLAST (1<<19) #define RULEFLAG_QSNONE (1<<20) /* programattic only */ #define RULEFLAG_ESCAPECTLS (1<<21) +#define RULEFLAG_ESCAPENEG (1<<22) /* return code of the rewrite rule * the result may be escaped - or not @@ -688,51 +691,27 @@ static APR_INLINE unsigned char *c2x(unsigned what 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; + unsigned char *d = (unsigned char *)copy, c; + int noplus = (flags & RULEFLAG_ESCAPENOPLUS) != 0; + int ctls = (flags & RULEFLAG_ESCAPECTLS) != 0; + int neg = (flags & RULEFLAG_ESCAPENEG) != 0; while ((c = *s)) { - if (ctls) { - if (c == ' ' && !noplus) { - *d++ = '+'; - } - else if (apr_iscntrl(c)) { - d = c2x(c, '%', d); - } - else { - *d++ = c; - } - } - else if (!escapeme) { + if (!c + || (ctls ? !TEST_CHAR(c, T_VCHAR_OBSTEXT) : !escapeme) + || (escapeme && ((ap_strchr_c(escapeme, c) != NULL) ^ neg))) { if (apr_isalnum(c) || c == '_') { *d++ = c; } - else if (c == ' ' && !noplus) { + else if (c == ' ' && !noplus) { *d++ = '+'; } - else { + else { d = c2x(c, '%', d); } } else { - const char *esc = escapeme; - while (*esc) { - if (c == *esc) { - if (c == ' ' && !noplus) { - *d++ = '+'; - } - else { - d = c2x(c, '%', d); - } - break; - } - ++esc; - } - if (!*esc) { - *d++ = c; - } + *d++ = c; } ++s; } @@ -3603,6 +3582,9 @@ static const char *cmd_rewriterule_setflag(apr_poo cfg->escapes = val; } } + else if (!strcasecmp(key, "NEG")) { + cfg->flags |= RULEFLAG_ESCAPENEG; + } else if (!strcasecmp(key, "NP") || !strcasecmp(key, "ackrefernoplus")) { cfg->flags |= RULEFLAG_ESCAPENOPLUS; }