On Sat, Mar 11, 2023 at 11:10 PM <[email protected]> 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;
}