]> granicus.if.org Git - apache/commitdiff
mod_rewrite: Add QSL|qslast flag to allow rewrites to files with
authorEric Covener <covener@apache.org>
Tue, 8 Mar 2016 19:18:15 +0000 (19:18 +0000)
committerEric Covener <covener@apache.org>
Tue, 8 Mar 2016 19:18:15 +0000 (19:18 +0000)
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
docs/manual/mod/mod_rewrite.xml
docs/manual/rewrite/flags.xml
modules/mappers/mod_rewrite.c

diff --git a/CHANGES b/CHANGES
index dfab7323a935f2e776e979ac1dddaae677474531..0159bc56f97b5ad331787f0dc4738429f4c1a222 100644 (file)
--- 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()
index 4996839388ad3ee753a5a31a3bf9ae8aa571bc92..24acc23aff9a9d4a93581380475a25dc97655bdc 100644 (file)
@@ -1364,6 +1364,14 @@ cannot use <code>$N</code> in the substitution string!
         <em><a href="../rewrite/flags.html#flag_qsd">details
         ...</a></em></td>
     </tr>
+    <tr>
+        <td>qslast|QSA</td>
+        <td>Interpret the last (right-most) question mark as the query string
+            delimeter, instead of the first (left-most) as normally used.  
+        <em><a href="../rewrite/flags.html#flag_qsl">details
+        ...</a></em></td>
+    </tr>
     <tr>
         <td>redirect|R[=<em>code</em>]</td>
         <td>Forces an external redirect, optionally with the specified
index 98f8022f7f5bfb9bd396feb89aef9d2605a5e048..f0fe2cec73acd1698441d6fb68adcd3ed8021af4 100644 (file)
@@ -641,6 +641,23 @@ URI.
 
 </section>
 
+<section id="flag_qsl"><title>QSL|qslast</title>
+<p>
+By default, the first (left-most) question mark in the substitution
+delimits the path from the query string.  Using the [QSL] flag instructs
+<directive module="mod_rewrite">RewriteRule</directive> to instead split
+the two components using the last (right-most) question mark.  </p>
+
+<p>
+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.  </p>
+
+<p> This flag is available in version 2.5.0 and later.</p>
+
+</section>
+
+
 <section id="flag_r"><title>R|redirect</title>
 <p>
 Use of the [R] flag causes a HTTP redirect to be issued to the browser.
index f82b4b20c97f891535f4e2df430ff49e6fef238f..549b5a4f251774b13e943d2ba28179d0d15f6b1c 100644 (file)
@@ -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