Hi,
Basically it adds servletnormalizecheck to mod_proxy for
ProxyPass/ProxyPassMatch and mod_rewrite when using P
I have tested the following uses:
#ProxyPass /docs ajp://localhost:8009/docs secret=%A1b2!@
servletnormalizecheck
#ProxyPassMatch "^/docs(.*)$" "ajp://localhost:8009/docs$1"
secret=%A1b2!@ servletnormalizecheck
#RewriteEngine On
#RewriteRule "^/docs(.*)$" "ajp://localhost:8009/docs$1" [P,SNC]
#<Proxy "ajp://localhost:8009/docs">
#ProxySet connectiontimeout=5 timeout=30 secret=%A1b2!@
#</Proxy>
#<Location "/docs">
# ProxyPass ajp://localhost:8009/docs secret=%A1b2!@ servletnormalizecheck
#</Location>
What is not supported is
curl -v --path-as-is
"http://localhost:8000/docs/..;foo=bar/;foo=bar/test/index.jsp"
that could be remapped to
ProxyPass /test ajp://localhost:8009/test secret=%A1b2!@
servletnormalizecheck
or a <location test/>
Comments?
--
Cheers
Jean-Frederic
Index: build/find_apr.m4
===================================================================
--- build/find_apr.m4 (revision 1878566)
+++ build/find_apr.m4 (nonexistent)
@@ -1,202 +0,0 @@
-dnl -------------------------------------------------------- -*- autoconf -*-
-dnl Licensed to the Apache Software Foundation (ASF) under one or more
-dnl contributor license agreements. See the NOTICE file distributed with
-dnl this work for additional information regarding copyright ownership.
-dnl The ASF licenses this file to You under the Apache License, Version 2.0
-dnl (the "License"); you may not use this file except in compliance with
-dnl the License. You may obtain a copy of the License at
-dnl
-dnl http://www.apache.org/licenses/LICENSE-2.0
-dnl
-dnl Unless required by applicable law or agreed to in writing, software
-dnl distributed under the License is distributed on an "AS IS" BASIS,
-dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-dnl See the License for the specific language governing permissions and
-dnl limitations under the License.
-
-dnl
-dnl find_apr.m4 : locate the APR include files and libraries
-dnl
-dnl This macro file can be used by applications to find and use the APR
-dnl library. It provides a standardized mechanism for using APR. It supports
-dnl embedding APR into the application source, or locating an installed
-dnl copy of APR.
-dnl
-dnl APR_FIND_APR(srcdir, builddir, implicit-install-check, acceptable-majors,
-dnl detailed-check)
-dnl
-dnl where srcdir is the location of the bundled APR source directory, or
-dnl empty if source is not bundled.
-dnl
-dnl where builddir is the location where the bundled APR will will be built,
-dnl or empty if the build will occur in the srcdir.
-dnl
-dnl where implicit-install-check set to 1 indicates if there is no
-dnl --with-apr option specified, we will look for installed copies.
-dnl
-dnl where acceptable-majors is a space separated list of acceptable major
-dnl version numbers. Often only a single major version will be acceptable.
-dnl If multiple versions are specified, and --with-apr=PREFIX or the
-dnl implicit installed search are used, then the first (leftmost) version
-dnl in the list that is found will be used. Currently defaults to [0 1].
-dnl
-dnl where detailed-check is an M4 macro which sets the apr_acceptable to
-dnl either "yes" or "no". The macro will be invoked for each installed
-dnl copy of APR found, with the apr_config variable set appropriately.
-dnl Only installed copies of APR which are considered acceptable by
-dnl this macro will be considered found. If no installed copies are
-dnl considered acceptable by this macro, apr_found will be set to either
-dnl either "no" or "reconfig".
-dnl
-dnl Sets the following variables on exit:
-dnl
-dnl apr_found : "yes", "no", "reconfig"
-dnl
-dnl apr_config : If the apr-config tool exists, this refers to it. If
-dnl apr_found is "reconfig", then the bundled directory
-dnl should be reconfigured *before* using apr_config.
-dnl
-dnl Note: this macro file assumes that apr-config has been installed; it
-dnl is normally considered a required part of an APR installation.
-dnl
-dnl If a bundled source directory is available and needs to be (re)configured,
-dnl then apr_found is set to "reconfig". The caller should reconfigure the
-dnl (passed-in) source directory, placing the result in the build directory,
-dnl as appropriate.
-dnl
-dnl If apr_found is "yes" or "reconfig", then the caller should use the
-dnl value of apr_config to fetch any necessary build/link information.
-dnl
-
-AC_DEFUN([APR_FIND_APR], [
- apr_found="no"
-
- if test "$target_os" = "os2-emx"; then
- # Scripts don't pass test -x on OS/2
- TEST_X="test -f"
- else
- TEST_X="test -x"
- fi
-
- ifelse([$4], [], [
- ifdef(AC_WARNING,AC_WARNING([$0: missing argument 4 (acceptable-majors): Defaulting to APR 0.x then APR 1.x]))
- acceptable_majors="0 1"],
- [acceptable_majors="$4"])
-
- apr_temp_acceptable_apr_config=""
- for apr_temp_major in $acceptable_majors
- do
- case $apr_temp_major in
- 0)
- apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-config"
- ;;
- *)
- apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-$apr_temp_major-config"
- ;;
- esac
- done
-
- AC_MSG_CHECKING(for APR)
- AC_ARG_WITH(apr,
- [ --with-apr=PATH prefix for installed APR or the full path to
- apr-config],
- [
- if test "$withval" = "no" || test "$withval" = "yes"; then
- AC_MSG_ERROR([--with-apr requires a directory or file to be provided])
- fi
-
- for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config
- do
- for lookdir in "$withval/bin" "$withval"
- do
- if $TEST_X "$lookdir/$apr_temp_apr_config_file"; then
- apr_config="$lookdir/$apr_temp_apr_config_file"
- ifelse([$5], [], [], [
- apr_acceptable="yes"
- $5
- if test "$apr_acceptable" != "yes"; then
- AC_MSG_WARN([Found APR in $apr_config, but we think it is considered unacceptable])
- continue
- fi])
- apr_found="yes"
- break 2
- fi
- done
- done
-
- if test "$apr_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then
- apr_config="$withval"
- ifelse([$5], [], [apr_found="yes"], [
- apr_acceptable="yes"
- $5
- if test "$apr_acceptable" = "yes"; then
- apr_found="yes"
- fi])
- fi
-
- dnl if --with-apr is used, it is a fatal error for its argument
- dnl to be invalid
- if test "$apr_found" != "yes"; then
- AC_MSG_ERROR([the --with-apr parameter is incorrect. It must specify an install prefix, a build directory, or an apr-config file.])
- fi
- ],[
- dnl If we allow installed copies, check those before using bundled copy.
- if test -n "$3" && test "$3" = "1"; then
- for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config
- do
- if $apr_temp_apr_config_file --help > /dev/null 2>&1 ; then
- apr_config="$apr_temp_apr_config_file"
- ifelse([$5], [], [], [
- apr_acceptable="yes"
- $5
- if test "$apr_acceptable" != "yes"; then
- AC_MSG_WARN([skipped APR at $apr_config, version not acceptable])
- continue
- fi])
- apr_found="yes"
- break
- else
- dnl look in some standard places
- for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do
- if $TEST_X "$lookdir/bin/$apr_temp_apr_config_file"; then
- apr_config="$lookdir/bin/$apr_temp_apr_config_file"
- ifelse([$5], [], [], [
- apr_acceptable="yes"
- $5
- if test "$apr_acceptable" != "yes"; then
- AC_MSG_WARN([skipped APR at $apr_config, version not acceptable])
- continue
- fi])
- apr_found="yes"
- break 2
- fi
- done
- fi
- done
- fi
- dnl if we have not found anything yet and have bundled source, use that
- if test "$apr_found" = "no" && test -d "$1"; then
- apr_temp_abs_srcdir="`cd \"$1\" && pwd`"
- apr_found="reconfig"
- apr_bundled_major="`sed -n '/#define.*APR_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apr_version.h\"`"
- case $apr_bundled_major in
- "")
- AC_MSG_ERROR([failed to find major version of bundled APR])
- ;;
- 0)
- apr_temp_apr_config_file="apr-config"
- ;;
- *)
- apr_temp_apr_config_file="apr-$apr_bundled_major-config"
- ;;
- esac
- if test -n "$2"; then
- apr_config="$2/$apr_temp_apr_config_file"
- else
- apr_config="$1/$apr_temp_apr_config_file"
- fi
- fi
- ])
-
- AC_MSG_RESULT($apr_found)
-])
Property changes on: build/find_apr.m4
___________________________________________________________________
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Index: build/find_apu.m4
===================================================================
--- build/find_apu.m4 (revision 1878566)
+++ build/find_apu.m4 (nonexistent)
@@ -1,211 +0,0 @@
-dnl -------------------------------------------------------- -*- autoconf -*-
-dnl Licensed to the Apache Software Foundation (ASF) under one or more
-dnl contributor license agreements. See the NOTICE file distributed with
-dnl this work for additional information regarding copyright ownership.
-dnl The ASF licenses this file to You under the Apache License, Version 2.0
-dnl (the "License"); you may not use this file except in compliance with
-dnl the License. You may obtain a copy of the License at
-dnl
-dnl http://www.apache.org/licenses/LICENSE-2.0
-dnl
-dnl Unless required by applicable law or agreed to in writing, software
-dnl distributed under the License is distributed on an "AS IS" BASIS,
-dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-dnl See the License for the specific language governing permissions and
-dnl limitations under the License.
-
-dnl
-dnl find_apu.m4 : locate the APR-util (APU) include files and libraries
-dnl
-dnl This macro file can be used by applications to find and use the APU
-dnl library. It provides a standardized mechanism for using APU. It supports
-dnl embedding APU into the application source, or locating an installed
-dnl copy of APU.
-dnl
-dnl APR_FIND_APU(srcdir, builddir, implicit-install-check, acceptable-majors,
-dnl detailed-check)
-dnl
-dnl where srcdir is the location of the bundled APU source directory, or
-dnl empty if source is not bundled.
-dnl
-dnl where builddir is the location where the bundled APU will be built,
-dnl or empty if the build will occur in the srcdir.
-dnl
-dnl where implicit-install-check set to 1 indicates if there is no
-dnl --with-apr-util option specified, we will look for installed copies.
-dnl
-dnl where acceptable-majors is a space separated list of acceptable major
-dnl version numbers. Often only a single major version will be acceptable.
-dnl If multiple versions are specified, and --with-apr-util=PREFIX or the
-dnl implicit installed search are used, then the first (leftmost) version
-dnl in the list that is found will be used. Currently defaults to [0 1].
-dnl
-dnl where detailed-check is an M4 macro which sets the apu_acceptable to
-dnl either "yes" or "no". The macro will be invoked for each installed
-dnl copy of APU found, with the apu_config variable set appropriately.
-dnl Only installed copies of APU which are considered acceptable by
-dnl this macro will be considered found. If no installed copies are
-dnl considered acceptable by this macro, apu_found will be set to either
-dnl either "no" or "reconfig".
-dnl
-dnl Sets the following variables on exit:
-dnl
-dnl apu_found : "yes", "no", "reconfig"
-dnl
-dnl apu_config : If the apu-config tool exists, this refers to it. If
-dnl apu_found is "reconfig", then the bundled directory
-dnl should be reconfigured *before* using apu_config.
-dnl
-dnl Note: this macro file assumes that apr-config has been installed; it
-dnl is normally considered a required part of an APR installation.
-dnl
-dnl Note: At this time, we cannot find *both* a source dir and a build dir.
-dnl If both are available, the build directory should be passed to
-dnl the --with-apr-util switch.
-dnl
-dnl Note: the installation layout is presumed to follow the standard
-dnl PREFIX/lib and PREFIX/include pattern. If the APU config file
-dnl is available (and can be found), then non-standard layouts are
-dnl possible, since it will be described in the config file.
-dnl
-dnl If a bundled source directory is available and needs to be (re)configured,
-dnl then apu_found is set to "reconfig". The caller should reconfigure the
-dnl (passed-in) source directory, placing the result in the build directory,
-dnl as appropriate.
-dnl
-dnl If apu_found is "yes" or "reconfig", then the caller should use the
-dnl value of apu_config to fetch any necessary build/link information.
-dnl
-
-AC_DEFUN([APR_FIND_APU], [
- apu_found="no"
-
- if test "$target_os" = "os2-emx"; then
- # Scripts don't pass test -x on OS/2
- TEST_X="test -f"
- else
- TEST_X="test -x"
- fi
-
- ifelse([$4], [],
- [
- ifdef(AC_WARNING,([$0: missing argument 4 (acceptable-majors): Defaulting to APU 0.x then APU 1.x]))
- acceptable_majors="0 1"
- ], [acceptable_majors="$4"])
-
- apu_temp_acceptable_apu_config=""
- for apu_temp_major in $acceptable_majors
- do
- case $apu_temp_major in
- 0)
- apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-config"
- ;;
- *)
- apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-$apu_temp_major-config"
- ;;
- esac
- done
-
- AC_MSG_CHECKING(for APR-util)
- AC_ARG_WITH(apr-util,
- [ --with-apr-util=PATH prefix for installed APU or the full path to
- apu-config],
- [
- if test "$withval" = "no" || test "$withval" = "yes"; then
- AC_MSG_ERROR([--with-apr-util requires a directory or file to be provided])
- fi
-
- for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config
- do
- for lookdir in "$withval/bin" "$withval"
- do
- if $TEST_X "$lookdir/$apu_temp_apu_config_file"; then
- apu_config="$lookdir/$apu_temp_apu_config_file"
- ifelse([$5], [], [], [
- apu_acceptable="yes"
- $5
- if test "$apu_acceptable" != "yes"; then
- AC_MSG_WARN([Found APU in $apu_config, but it is considered unacceptable])
- continue
- fi])
- apu_found="yes"
- break 2
- fi
- done
- done
-
- if test "$apu_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then
- apu_config="$withval"
- ifelse([$5], [], [apu_found="yes"], [
- apu_acceptable="yes"
- $5
- if test "$apu_acceptable" = "yes"; then
- apu_found="yes"
- fi])
- fi
-
- dnl if --with-apr-util is used, it is a fatal error for its argument
- dnl to be invalid
- if test "$apu_found" != "yes"; then
- AC_MSG_ERROR([the --with-apr-util parameter is incorrect. It must specify an install prefix, a build directory, or an apu-config file.])
- fi
- ],[
- if test -n "$3" && test "$3" = "1"; then
- for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config
- do
- if $apu_temp_apu_config_file --help > /dev/null 2>&1 ; then
- apu_config="$apu_temp_apu_config_file"
- ifelse([$5], [], [], [
- apu_acceptable="yes"
- $5
- if test "$apu_acceptable" != "yes"; then
- AC_MSG_WARN([skipped APR-util at $apu_config, version not acceptable])
- continue
- fi])
- apu_found="yes"
- break
- else
- dnl look in some standard places (apparently not in builtin/default)
- for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do
- if $TEST_X "$lookdir/bin/$apu_temp_apu_config_file"; then
- apu_config="$lookdir/bin/$apu_temp_apu_config_file"
- ifelse([$5], [], [], [
- apu_acceptable="yes"
- $5
- if test "$apu_acceptable" != "yes"; then
- AC_MSG_WARN([skipped APR-util at $apu_config, version not acceptable])
- continue
- fi])
- apu_found="yes"
- break 2
- fi
- done
- fi
- done
- fi
- dnl if we have not found anything yet and have bundled source, use that
- if test "$apu_found" = "no" && test -d "$1"; then
- apu_temp_abs_srcdir="`cd \"$1\" && pwd`"
- apu_found="reconfig"
- apu_bundled_major="`sed -n '/#define.*APU_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apu_version.h\"`"
- case $apu_bundled_major in
- "")
- AC_MSG_ERROR([failed to find major version of bundled APU])
- ;;
- 0)
- apu_temp_apu_config_file="apu-config"
- ;;
- *)
- apu_temp_apu_config_file="apu-$apu_bundled_major-config"
- ;;
- esac
- if test -n "$2"; then
- apu_config="$2/$apu_temp_apu_config_file"
- else
- apu_config="$1/$apu_temp_apu_config_file"
- fi
- fi
- ])
-
- AC_MSG_RESULT($apu_found)
-])
Property changes on: build/find_apu.m4
___________________________________________________________________
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Index: include/httpd.h
===================================================================
--- include/httpd.h (revision 1878566)
+++ include/httpd.h (working copy)
@@ -1789,6 +1789,15 @@
AP_FN_ATTR_NONNULL_ALL;
/**
+ * Remove all ./ and xx/../ substrings from a file name. Also remove
+ * any leading ../ or /../ substrings.
+ * @param name the file name to parse
+ * @param servletnormalize if set also remove the ;foo=bar/ from any path segment
+ */
+AP_DECLARE(void) ap_getparents_ex(char *name, int servletnormalize)
+ AP_FN_ATTR_NONNULL_ALL;
+
+/**
* Escape a path segment, as defined in RFC 1808
* @param p The pool to allocate from
* @param s The path to convert
Index: modules/mappers/mod_rewrite.c
===================================================================
--- modules/mappers/mod_rewrite.c (revision 1878566)
+++ modules/mappers/mod_rewrite.c (working copy)
@@ -168,6 +168,7 @@
#define RULEFLAG_END (1<<17)
#define RULEFLAG_ESCAPENOPLUS (1<<18)
#define RULEFLAG_QSLAST (1<<19)
+#define RULEFLAG_SNC (1<<20)
/* return code of the rewrite rule
* the result may be escaped - or not
@@ -3763,6 +3764,9 @@
case 'S':
if (!*key || !strcasecmp(key, "kip")) { /* skip */
cfg->skip = atoi(val);
+ } else if ( !strcasecmp(key, "NC")
+ || !strcasecmp(key, "ervletnormalizecheck")) { /* servletnormalizecheck */
+ cfg->flags |= RULEFLAG_SNC;
}
else {
++error;
@@ -4305,6 +4309,19 @@
rewritelog(r, 2, ctx->perdir, "escaped URI in per-dir context "
"for proxy, %s -> %s", old_filename, r->filename);
}
+ if (p->flags & RULEFLAG_SNC) {
+ char *uri = apr_pstrdup(r->pool, ctx->uri);
+ ap_getparents_ex(uri, 1);
+ rewritelog(r, 2, ctx->perdir, "Checking pattern '%s' to normalized uri '%s'",
+ p->pattern, uri);
+ rc = !ap_regexec(p->regexp, uri, AP_MAX_REG_MATCH, regmatch, 0);
+ if (! (( rc && !(p->flags & RULEFLAG_NOTMATCH)) ||
+ (!rc && (p->flags & RULEFLAG_NOTMATCH)) ) ) {
+ rewritelog(r, 2, ctx->perdir, "rejecting via pattern '%s' for uri '%s'",
+ p->pattern, uri);
+ return -1;
+ }
+ }
fully_qualify_uri(r);
@@ -4478,6 +4495,10 @@
* last-rule and new-round flags.
*/
if (p->flags & (RULEFLAG_PROXY | RULEFLAG_LASTRULE)) {
+ if (rc == -1) {
+ r->status = HTTP_BAD_REQUEST;
+ return ACTION_STATUS;
+ }
break;
}
Index: modules/proxy/mod_proxy.c
===================================================================
--- modules/proxy/mod_proxy.c (revision 1878566)
+++ modules/proxy/mod_proxy.c (working copy)
@@ -679,6 +679,7 @@
char *found = NULL;
int mismatch = 0;
unsigned int nocanon = ent->flags & PROXYPASS_NOCANON;
+ unsigned int servletnormalizecheck = ent->flags & PROXY_SERVLET_NORMALIZE_CHECK;
const char *use_uri = nocanon ? r->unparsed_uri : r->uri;
if (dconf && (dconf->interpolate_env == 1) && (ent->flags & PROXYPASS_INTERPOLATE)) {
@@ -703,6 +704,16 @@
"'%s'; declining", r->uri);
return DECLINED;
}
+ if (servletnormalizecheck) {
+ /* check against the endback servlet url and return 400 in case something weird */
+ char *uri = apr_pstrdup(r->pool, r->uri);
+ ap_getparents_ex(uri, 1);
+ if (ap_regexec(ent->regex, uri, AP_MAX_REG_MATCH, regm, 0)) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "servlet_normalized URL path doesn't correctly match ProxyMatchPass");
+ return HTTP_BAD_REQUEST;
+ }
+ }
/* test that we haven't reduced the URI */
if (nocanon && ap_regexec(ent->regex, r->unparsed_uri,
AP_MAX_REG_MATCH, reg1, 0)) {
@@ -749,6 +760,18 @@
"'%s'; declining", r->uri);
return DECLINED;
}
+ if (servletnormalizecheck) {
+ /* check against the endback servlet url and return 400 in case something weird */
+ char *uri = apr_pstrdup(r->pool, r->uri);
+ int servlen;
+ ap_getparents_ex(uri, 1);
+ servlen = alias_match(uri, fake);
+ if (servlen != len) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "servlet_normalized URL path doesn't correctly match ProxyPass");
+ return HTTP_BAD_REQUEST;
+ }
+ }
if (nocanon && len != alias_match(r->unparsed_uri, ent->fake)) {
mismatch = 1;
use_uri = r->uri;
@@ -1806,6 +1829,9 @@
else if (!strcasecmp(word,"noquery")) {
flags |= PROXYPASS_NOQUERY;
}
+ else if (!strcasecmp(word,"servletnormalizecheck")) {
+ flags |= PROXY_SERVLET_NORMALIZE_CHECK;
+ }
else {
char *val = strchr(word, '=');
if (!val) {
Index: modules/proxy/mod_proxy.h
===================================================================
--- modules/proxy/mod_proxy.h (revision 1878566)
+++ modules/proxy/mod_proxy.h (working copy)
@@ -123,6 +123,7 @@
#define PROXYPASS_NOCANON 0x01
#define PROXYPASS_INTERPOLATE 0x02
#define PROXYPASS_NOQUERY 0x04
+#define PROXY_SERVLET_NORMALIZE_CHECK 0x08
struct proxy_alias {
const char *real;
const char *fake;
Index: server/util.c
===================================================================
--- server/util.c (revision 1878566)
+++ server/util.c (working copy)
@@ -493,13 +493,42 @@
}
/*
- * Parse .. so we don't compromise security
+ * Parse .. and remove parameters in path segments so we don't compromise security
*/
AP_DECLARE(void) ap_getparents(char *name)
{
+ ap_getparents_ex(name, 0);
+}
+AP_DECLARE(void) ap_getparents_ex(char *name, int servletnormalize)
+{
char *next;
int l, w, first_dot;
+ if (servletnormalize) {
+ for (l = 1, w = 1; name[l] != '\0';) {
+ /* first remove ;foo=bar in path segments */
+ if (name[l] == ';') {
+ l++;
+ while (!IS_SLASH(name[l]) && name[l] != '\0') {
+ l++;
+ }
+ continue;
+ }
+ /* Collapse ///// sequences to / */
+ if (name[w - 1] == '/') {
+ if (name[l] == '/') {
+ do {
+ l++;
+ } while (name[l] == '/');
+ continue;
+ }
+ }
+ /* The rest is done later by standard logic */
+ name[w++] = name[l++];
+ }
+ name[w] = '\0';
+ }
+
/* Four paseses, as per RFC 1808 */
/* a) remove ./ path segments */
for (next = name; *next && (*next != '.'); next++) {