You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
9.8 KiB
244 lines
9.8 KiB
diff --git a/docs/manual/mod/core.html.en b/docs/manual/mod/core.html.en |
|
index 86d9bee..e08034b 100644 |
|
--- a/docs/manual/mod/core.html.en |
|
+++ b/docs/manual/mod/core.html.en |
|
@@ -90,6 +90,7 @@ available</td></tr> |
|
<li><img alt="" src="../images/down.gif" /> <a href="#maxrangeoverlaps">MaxRangeOverlaps</a></li> |
|
<li><img alt="" src="../images/down.gif" /> <a href="#maxrangereversals">MaxRangeReversals</a></li> |
|
<li><img alt="" src="../images/down.gif" /> <a href="#maxranges">MaxRanges</a></li> |
|
+<li><img alt="" src="../images/down.gif" /> <a href="#mergeslashes">MergeSlashes</a></li> |
|
<li><img alt="" src="../images/down.gif" /> <a href="#mutex">Mutex</a></li> |
|
<li><img alt="" src="../images/down.gif" /> <a href="#namevirtualhost">NameVirtualHost</a></li> |
|
<li><img alt="" src="../images/down.gif" /> <a href="#options">Options</a></li> |
|
@@ -3170,6 +3171,30 @@ resource </td></tr> |
|
|
|
</div> |
|
<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> |
|
+<div class="directive-section"><h2><a name="MergeSlashes" id="MergeSlashes">MergeSlashes</a> <a name="mergeslashes" id="mergeslashes">Directive</a></h2> |
|
+<table class="directive"> |
|
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Controls whether the server merges consecutive slashes in URLs. </td></tr> |
|
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>MergeSlashes ON | OFF</code></td></tr> |
|
+<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>MergeSlashes ON</code></td></tr> |
|
+<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host</td></tr> |
|
+<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Core</td></tr> |
|
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>core</td></tr> |
|
+<tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>Available in Apache HTTP Server 2.4.6 in Red Hat Enterprise Linux 7</td></tr> |
|
+</table> |
|
+ <p>By default, the server merges (or collapses) multiple consecutive slash |
|
+ ('/') characters in the path component of the request URL.</p> |
|
+ |
|
+ <p>When mapping URL's to the filesystem, these multiple slashes are not |
|
+ significant. However, URL's handled other ways, such as by CGI or proxy, |
|
+ might prefer to retain the significance of multiple consecutive slashes. |
|
+ In these cases <code class="directive">MergeSlashes</code> can be set to |
|
+ <em>OFF</em> to retain the multiple consecutive slashes. In these |
|
+ configurations, regular expressions used in the configuration file that match |
|
+ the path component of the URL (<code class="directive">LocationMatch</code>, |
|
+ <code class="directive">RewriteRule</code>, ...) need to take into account multiple |
|
+ consecutive slashes.</p> |
|
+</div> |
|
+<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> |
|
<div class="directive-section"><h2><a name="Mutex" id="Mutex">Mutex</a> <a name="mutex" id="mutex">Directive</a></h2> |
|
<table class="directive"> |
|
<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Configures mutex mechanism and lock file directory for all |
|
diff --git a/include/http_core.h b/include/http_core.h |
|
index c05d06e..76bf5a4 100644 |
|
--- a/include/http_core.h |
|
+++ b/include/http_core.h |
|
@@ -465,6 +465,17 @@ typedef unsigned long etag_components_t; |
|
/* This is the default value used */ |
|
#define ETAG_BACKWARD (ETAG_MTIME | ETAG_SIZE) |
|
|
|
+/* Generic ON/OFF/UNSET for unsigned int foo :2 */ |
|
+#define AP_CORE_CONFIG_OFF (0) |
|
+#define AP_CORE_CONFIG_ON (1) |
|
+#define AP_CORE_CONFIG_UNSET (2) |
|
+ |
|
+/* Generic merge of flag */ |
|
+#define AP_CORE_MERGE_FLAG(field, to, base, over) to->field = \ |
|
+ over->field != AP_CORE_CONFIG_UNSET \ |
|
+ ? over->field \ |
|
+ : base->field |
|
+ |
|
/** |
|
* @brief Server Signature Enumeration |
|
*/ |
|
@@ -682,7 +693,7 @@ typedef struct { |
|
#define AP_HTTP_METHODS_LENIENT 1 |
|
#define AP_HTTP_METHODS_REGISTERED 2 |
|
char http_methods; |
|
- |
|
+ unsigned int merge_slashes; |
|
} core_server_config; |
|
|
|
/* for AddOutputFiltersByType in core.c */ |
|
diff --git a/include/httpd.h b/include/httpd.h |
|
index 176ef5e..a552358 100644 |
|
--- a/include/httpd.h |
|
+++ b/include/httpd.h |
|
@@ -1622,11 +1622,21 @@ AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes); |
|
AP_DECLARE(int) ap_unescape_urlencoded(char *query); |
|
|
|
/** |
|
- * Convert all double slashes to single slashes |
|
- * @param name The string to convert |
|
+ * Convert all double slashes to single slashes, except where significant |
|
+ * to the filesystem on the current platform. |
|
+ * @param name The string to convert, assumed to be a filesystem path |
|
*/ |
|
AP_DECLARE(void) ap_no2slash(char *name); |
|
|
|
+/** |
|
+ * Convert all double slashes to single slashes, except where significant |
|
+ * to the filesystem on the current platform. |
|
+ * @param name The string to convert |
|
+ * @param is_fs_path if set to 0, the significance of any double-slashes is |
|
+ * ignored. |
|
+ */ |
|
+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path); |
|
+ |
|
/** |
|
* Remove all ./ and xx/../ substrings from a file name. Also remove |
|
* any leading ../ or /../ substrings. |
|
diff --git a/server/core.c b/server/core.c |
|
index 0e69f8c..67efd7e 100644 |
|
--- a/server/core.c |
|
+++ b/server/core.c |
|
@@ -476,6 +476,7 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s) |
|
*/ |
|
|
|
conf->trace_enable = AP_TRACE_UNSET; |
|
+ conf->merge_slashes = AP_CORE_CONFIG_UNSET; |
|
|
|
return (void *)conf; |
|
} |
|
@@ -536,6 +537,8 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv) |
|
? virt->merge_trailers |
|
: base->merge_trailers; |
|
|
|
+ AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt); |
|
+ |
|
return conf; |
|
} |
|
|
|
@@ -1673,6 +1676,13 @@ static const char *set_override(cmd_parms *cmd, void *d_, const char *l) |
|
return NULL; |
|
} |
|
|
|
+static const char *set_core_server_flag(cmd_parms *cmd, void *s_, int flag) |
|
+{ |
|
+ core_server_config *conf = |
|
+ ap_get_core_module_config(cmd->server->module_config); |
|
+ return ap_set_flag_slot(cmd, conf, flag); |
|
+} |
|
+ |
|
static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[]) |
|
{ |
|
core_dir_config *d = d_; |
|
@@ -4216,6 +4226,10 @@ AP_INIT_ITERATE("HttpProtocolOptions", set_http_protocol_options, NULL, RSRC_CON |
|
, |
|
AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF, |
|
"Registers non-standard HTTP methods"), |
|
+AP_INIT_FLAG("MergeSlashes", set_core_server_flag, |
|
+ (void *)APR_OFFSETOF(core_server_config, merge_slashes), |
|
+ RSRC_CONF, |
|
+ "Controls whether consecutive slashes in the URI path are merged"), |
|
{ NULL } |
|
}; |
|
|
|
diff --git a/server/request.c b/server/request.c |
|
index 4eef097..cba3891 100644 |
|
--- a/server/request.c |
|
+++ b/server/request.c |
|
@@ -167,6 +167,8 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) |
|
int file_req = (r->main && r->filename); |
|
int access_status; |
|
core_dir_config *d; |
|
+ core_server_config *sconf = |
|
+ ap_get_core_module_config(r->server->module_config); |
|
|
|
/* Ignore embedded %2F's in path for proxy requests */ |
|
if (!r->proxyreq && r->parsed_uri.path) { |
|
@@ -191,6 +193,12 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) |
|
} |
|
|
|
ap_getparents(r->uri); /* OK --- shrinking transformations... */ |
|
+ if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) { |
|
+ ap_no2slash(r->uri); |
|
+ if (r->parsed_uri.path) { |
|
+ ap_no2slash(r->parsed_uri.path); |
|
+ } |
|
+ } |
|
|
|
/* All file subrequests are a huge pain... they cannot bubble through the |
|
* next several steps. Only file subrequests are allowed an empty uri, |
|
@@ -1383,20 +1391,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) |
|
|
|
cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r); |
|
cached = (cache->cached != NULL); |
|
- |
|
- /* Location and LocationMatch differ on their behaviour w.r.t. multiple |
|
- * slashes. Location matches multiple slashes with a single slash, |
|
- * LocationMatch doesn't. An exception, for backwards brokenness is |
|
- * absoluteURIs... in which case neither match multiple slashes. |
|
- */ |
|
- if (r->uri[0] != '/') { |
|
- entry_uri = r->uri; |
|
- } |
|
- else { |
|
- char *uri = apr_pstrdup(r->pool, r->uri); |
|
- ap_no2slash(uri); |
|
- entry_uri = uri; |
|
- } |
|
+ entry_uri = r->uri; |
|
|
|
/* If we have an cache->cached location that matches r->uri, |
|
* and the vhost's list of locations hasn't changed, we can skip |
|
@@ -1449,7 +1444,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) |
|
* terminated (or at the end of the string) to match. |
|
*/ |
|
if (entry_core->r |
|
- ? ap_regexec(entry_core->r, r->uri, 0, NULL, 0) |
|
+ ? ap_regexec(entry_core->r, entry_uri, 0, NULL, 0) |
|
: (entry_core->d_is_fnmatch |
|
? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME) |
|
: (strncmp(entry_core->d, cache->cached, len) |
|
diff --git a/server/util.c b/server/util.c |
|
index f9e3b51..4eac462 100644 |
|
--- a/server/util.c |
|
+++ b/server/util.c |
|
@@ -561,16 +561,20 @@ AP_DECLARE(void) ap_getparents(char *name) |
|
name[l] = '\0'; |
|
} |
|
} |
|
- |
|
-AP_DECLARE(void) ap_no2slash(char *name) |
|
+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path) |
|
{ |
|
+ |
|
char *d, *s; |
|
|
|
+ if (!*name) { |
|
+ return; |
|
+ } |
|
+ |
|
s = d = name; |
|
|
|
#ifdef HAVE_UNC_PATHS |
|
/* Check for UNC names. Leave leading two slashes. */ |
|
- if (s[0] == '/' && s[1] == '/') |
|
+ if (is_fs_path && s[0] == '/' && s[1] == '/') |
|
*d++ = *s++; |
|
#endif |
|
|
|
@@ -587,6 +591,10 @@ AP_DECLARE(void) ap_no2slash(char *name) |
|
*d = '\0'; |
|
} |
|
|
|
+AP_DECLARE(void) ap_no2slash(char *name) |
|
+{ |
|
+ ap_no2slash_ex(name, 1); |
|
+} |
|
|
|
/* |
|
* copy at most n leading directories of s into d
|
|
|