From: André Malo Date: Wed, 2 Apr 2003 21:11:41 +0000 (+0000) Subject: Fix the misunderstandings between local URL paths and local X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=abaeb01724c9bfd8c991cae7b07a58ef29bf2360;p=thirdparty%2Fapache%2Fhttpd.git Fix the misunderstandings between local URL paths and local system paths. Note that mod_rewrite handles _both_. Fixed also some comments to make the explanations more clear. PR: 12902 Obtained from: 2.1 (r1.144) Reviewed by: Brad Nicholes, Will Rowe git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@99179 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/CHANGES b/src/CHANGES index a6b9ee40d54..690c187c723 100644 --- a/src/CHANGES +++ b/src/CHANGES @@ -1,5 +1,9 @@ Changes with Apache 1.3.28 + *) Fix path handling of mod_rewrite, especially on non-unix systems. + There was some confusion between local paths and URL paths. + PR 12902. [André Malo] + *) backport from 2.x series: Prevent endless loops of internal redirects in mod_rewrite by aborting after exceeding a limit of internal redirects. The limit defaults to 10 and can be changed using the RewriteOptions diff --git a/src/modules/standard/mod_rewrite.c b/src/modules/standard/mod_rewrite.c index fff2e6ea3b1..d5e33fe0cc1 100644 --- a/src/modules/standard/mod_rewrite.c +++ b/src/modules/standard/mod_rewrite.c @@ -1245,8 +1245,11 @@ static int hook_uri2file(request_rec *r) #endif rewritelog(r, 2, "local path result: %s", r->filename); - /* the filename has to start with a slash! */ - if (!ap_os_is_path_absolute(r->filename)) { + /* the filename must be either an absolute local path or an + * absolute local URL. + */ + if ( *r->filename != '/' + && !ap_os_is_path_absolute(r->filename)) { return BAD_REQUEST; } @@ -1441,14 +1444,39 @@ static int hook_fixup(request_rec *r) ; /* skip '://' */ cp += 3; - if ((cp = strchr(cp, '/')) != NULL) { + if ((cp = strchr(cp, '/')) != NULL && *(++cp)) { rewritelog(r, 2, "[per-dir %s] trying to replace " "prefix %s with %s", dconf->directory, dconf->directory, dconf->baseurl); - cp2 = subst_prefix_path(r, cp, dconf->directory, - dconf->baseurl); + + /* I think, that hack needs an explanation: + * well, here is it: + * mod_rewrite was written for unix systems, were + * absolute file-system paths start with a slash. + * URL-paths _also_ start with slashes, so they + * can be easily compared with system paths. + * + * the following assumes, that the actual url-path + * may be prefixed by the current directory path and + * tries to replace the system path with the RewriteBase + * URL. + * That assumption is true if we use a RewriteRule like + * + * RewriteRule ^foo bar [R] + * + * (see apply_rewrite_rule function) + * However on systems that don't have a / as system + * root this will never match, so we skip the / after the + * hostname and compare/substitute only the stuff after it. + * + * (note that cp was already increased to the right value) + */ + cp2 = subst_prefix_path(r, cp, (*dconf->directory == '/') + ? dconf->directory + 1 + : dconf->directory, + dconf->baseurl + 1); if (strcmp(cp2, cp) != 0) { *cp = '\0'; r->filename = ap_pstrcat(r->pool, r->filename, @@ -1530,8 +1558,11 @@ static int hook_fixup(request_rec *r) r->filename = ap_pstrdup(r->pool, r->filename+12); } - /* the filename has to start with a slash! */ - if (!ap_os_is_path_absolute(r->filename)) { + /* the filename must be either an absolute local path or an + * absolute local URL. + */ + if ( *r->filename != '/' + && !ap_os_is_path_absolute(r->filename)) { return BAD_REQUEST; } @@ -2067,12 +2098,12 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p, splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND); /* - * Again add the previously stripped per-directory location - * prefix if the new URI is not a new one for this - * location, i.e. if it's not starting with either a slash - * or a fully qualified URL scheme. + * Add the previously stripped per-directory location + * prefix if the new URI is not a new one for this + * location, i.e. if it's not an absolute URL (!) path nor + * a fully qualified URL scheme. */ - if (prefixstrip && !ap_os_is_path_absolute(r->filename) + if (prefixstrip && *r->filename != '/' && !is_absolute_uri(r->filename)) { rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s", perdir, r->filename, perdir, r->filename);