summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2023-03-13 14:49:13 +0100
committerYann Ylavic <ylavic@apache.org>2023-03-13 14:49:13 +0100
commitbced8a7711cf1e48f7b8f0c77e1b78bc3944233f (patch)
tree0a246ab662f5870f531a180fdee71d8900bed059
parentDo not double encode encoded slashes (diff)
downloadapache2-bced8a7711cf1e48f7b8f0c77e1b78bc3944233f.tar.xz
apache2-bced8a7711cf1e48f7b8f0c77e1b78bc3944233f.zip
mod_rewrite: New BNEG flag to negate B=, BCTLS and B= not mutually exclusive.
* modules/mappers/mod_rewrite.c(escape_backref): Handle [B=...,BNEG] to encode anthing not in B=, and [B=...,BCTLS] to encode both controls/space characters and anything set in B=. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1908347 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--modules/mappers/mod_rewrite.c49
1 files changed, 16 insertions, 33 deletions
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
index 458d0c0e8e..8c1fd1a162 100644
--- a/modules/mappers/mod_rewrite.c
+++ b/modules/mappers/mod_rewrite.c
@@ -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_really_last";
#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
@@ -685,27 +688,19 @@ 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 flags) {
- char *copy = apr_palloc(p, 3 * strlen(path) + 3);
+static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int flags)
+{
+ char *copy = apr_palloc(p, 3 * strlen(path) + 1);
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;
+ int noplus = (flags & RULEFLAG_ESCAPENOPLUS) != 0;
+ int ctls = (flags & RULEFLAG_ESCAPECTLS) != 0;
+ int neg = (flags & RULEFLAG_ESCAPENEG) != 0;
+ unsigned char c;
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 ((ctls ? !TEST_CHAR(c, T_VCHAR_OBSTEXT) : !escapeme)
+ || (escapeme && ((ap_strchr_c(escapeme, c) != NULL) ^ neg))) {
if (apr_isalnum(c) || c == '_') {
*d++ = c;
}
@@ -717,22 +712,7 @@ static char *escape_backref(apr_pool_t *p, const char *path, const char *escapem
}
}
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 +3583,9 @@ static const char *cmd_rewriterule_setflag(apr_pool_t *p, void *_cfg,
cfg->escapes = val;
}
}
+ else if (!strcasecmp(key, "NEG")) {
+ cfg->flags |= RULEFLAG_ESCAPENEG;
+ }
else if (!strcasecmp(key, "NP") || !strcasecmp(key, "ackrefernoplus")) {
cfg->flags |= RULEFLAG_ESCAPENOPLUS;
}