From 9abfad57050835dcabca140aab678a4ee79b8054 Mon Sep 17 00:00:00 2001 From: Eric Covener Date: Tue, 8 Mar 2016 19:18:15 +0000 Subject: [PATCH] mod_rewrite: Add QSL|qslast flag to allow rewrites to files with literal question marks in their names. PR 58777. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1734125 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 +++ docs/manual/mod/mod_rewrite.xml | 8 ++++++++ docs/manual/rewrite/flags.xml | 17 +++++++++++++++++ modules/mappers/mod_rewrite.c | 18 ++++++++++++++---- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index dfab7323a9..0159bc56f9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_rewrite: Add QSL|qslast flag to allow rewrites to files with + literal question marks in their names. PR 58777. [Eric Covener] + *) core: Split ap_create_request() from ap_read_request(). [Graham Leggett] *) mod_ssl: Don't lose track of the SSL context if the ssl_run_pre_handshake() diff --git a/docs/manual/mod/mod_rewrite.xml b/docs/manual/mod/mod_rewrite.xml index 4996839388..24acc23aff 100644 --- a/docs/manual/mod/mod_rewrite.xml +++ b/docs/manual/mod/mod_rewrite.xml @@ -1364,6 +1364,14 @@ cannot use $N in the substitution string! details ... + + qslast|QSA + Interpret the last (right-most) question mark as the query string + delimeter, instead of the first (left-most) as normally used. + details + ... + + redirect|R[=code] Forces an external redirect, optionally with the specified diff --git a/docs/manual/rewrite/flags.xml b/docs/manual/rewrite/flags.xml index 98f8022f7f..f0fe2cec73 100644 --- a/docs/manual/rewrite/flags.xml +++ b/docs/manual/rewrite/flags.xml @@ -641,6 +641,23 @@ URI. +
QSL|qslast +

+By default, the first (left-most) question mark in the substitution +delimits the path from the query string. Using the [QSL] flag instructs +RewriteRule to instead split +the two components using the last (right-most) question mark.

+ +

+This is useful when mapping to files that have literal question marks in +their filename. If no query string is used in the substitution, +a question mark can be appended to it in combination with this flag.

+ +

This flag is available in version 2.5.0 and later.

+ +
+ +
R|redirect

Use of the [R] flag causes a HTTP redirect to be issued to the browser. diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index f82b4b20c9..549b5a4f25 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -171,6 +171,7 @@ static const char* really_last_key = "rewrite_really_last"; #define RULEFLAG_QSDISCARD (1<<16) #define RULEFLAG_END (1<<17) #define RULEFLAG_ESCAPENOPLUS (1<<18) +#define RULEFLAG_QSLAST (1<<19) /* return code of the rewrite rule * the result may be escaped - or not @@ -752,7 +753,8 @@ static char *escape_absolute_uri(apr_pool_t *p, char *uri, unsigned scheme) * split out a QUERY_STRING part from * the current URI string */ -static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard) +static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard, + int qslast) { char *q; int split; @@ -771,7 +773,8 @@ static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard) rewritelog((r, 2, NULL, "discarding query string")); } - q = ap_strchr(r->filename, '?'); + q = qslast ? ap_strrchr(r->filename, '?') : ap_strchr(r->filename, '?'); + if (q != NULL) { char *olduri; apr_size_t len; @@ -779,7 +782,9 @@ static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard) olduri = apr_pstrdup(r->pool, r->filename); *q++ = '\0'; if (qsappend) { - r->args = apr_pstrcat(r->pool, q, "&", r->args, NULL); + if (*q) { + r->args = apr_pstrcat(r->pool, q, "&" , r->args, NULL); + } } else { r->args = apr_pstrdup(r->pool, q); @@ -3638,6 +3643,9 @@ static const char *cmd_rewriterule_setflag(apr_pool_t *p, void *_cfg, } else if ( !strcasecmp(key, "SD") || !strcasecmp(key, "sdiscard") ) { /* qsdiscard */ cfg->flags |= RULEFLAG_QSDISCARD; + } else if ( !strcasecmp(key, "SL") + || !strcasecmp(key, "slast") ) { /* qslast */ + cfg->flags |= RULEFLAG_QSLAST; } else { ++error; @@ -4191,7 +4199,9 @@ static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx) r->path_info = NULL; } - splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND, p->flags & RULEFLAG_QSDISCARD); + splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND, + p->flags & RULEFLAG_QSDISCARD, + p->flags & RULEFLAG_QSLAST); /* Add the previously stripped per-directory location prefix, unless * (1) it's an absolute URL path and -- 2.40.0