You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by co...@apache.org on 2019/06/17 18:35:24 UTC

svn commit: r1861542 - in /httpd/httpd/trunk: docs/manual/mod/mod_alias.xml modules/mappers/mod_alias.c

Author: covener
Date: Mon Jun 17 18:35:24 2019
New Revision: 1861542

URL: http://svn.apache.org/viewvc?rev=1861542&view=rev
Log:
add RedirectRelative directive to allow relative Redirect targets

2616 forbade relative redirect URLs, but 7231 allows them
Early 2.2 maintenance levels did not fix them up, but later 2.2 and all 2.4
fixed them up with ap_construct_url().

Allow opt-in to not fixing up relative URLs with RedirectRelative



Modified:
    httpd/httpd/trunk/docs/manual/mod/mod_alias.xml
    httpd/httpd/trunk/modules/mappers/mod_alias.c

Modified: httpd/httpd/trunk/docs/manual/mod/mod_alias.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_alias.xml?rev=1861542&r1=1861541&r2=1861542&view=diff
==============================================================================
--- httpd/httpd/trunk/docs/manual/mod/mod_alias.xml (original)
+++ httpd/httpd/trunk/docs/manual/mod/mod_alias.xml Mon Jun 17 18:35:24 2019
@@ -621,4 +621,25 @@ ScriptAliasMatch "(?i)^/cgi-bin(.*)" "/u
 </usage>
 </directivesynopsis>
 
+<directivesynopsis>
+<name>RedirectRelative</name>
+<description>Allows relative redirect targets.</description>
+<syntax>RedirectRelative OFF|ON</syntax>
+<default>RedirectRelative OFF</default>
+<contextlist><context>server config</context><context>virtual host</context>
+<context>directory</context>
+<compatibility>2.5.1 and later</compatibility>
+</contextlist>
+
+<usage>
+    <p>By default, if the target URL of a <directive>Redirect</directive>
+    directive is a relative URL beginning with a '/' character, the server 
+    converts it to a an absolute URL before responding to the client. By
+    setting <directive>RedirectRelative</directive> to the value "ON",
+    the relative URL is presented to the client directly.</p>
+
+</usage>
+</directivesynopsis>
+
+
 </modulesynopsis>

Modified: httpd/httpd/trunk/modules/mappers/mod_alias.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mappers/mod_alias.c?rev=1861542&r1=1861541&r2=1861542&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/mappers/mod_alias.c (original)
+++ httpd/httpd/trunk/modules/mappers/mod_alias.c Mon Jun 17 18:35:24 2019
@@ -37,6 +37,10 @@
 #include "ap_expr.h"
 
 
+#define ALIAS_FLAG_DEFAULT -1
+#define ALIAS_FLAG_OFF 0
+#define ALIAS_FLAG_ON  1
+
 typedef struct {
     const char *real;
     const char *fake;
@@ -58,6 +62,7 @@ typedef struct {
     char *handler;
     const ap_expr_info_t *redirect;
     int redirect_status;                /* 301, 302, 303, 410, etc */
+    int allow_relative;                 /* skip ap_construct_url() */
 } alias_dir_conf;
 
 module AP_MODULE_DECLARE_DATA alias_module;
@@ -80,6 +85,7 @@ static void *create_alias_dir_config(apr
     alias_dir_conf *a =
     (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
     a->redirects = apr_array_make(p, 2, sizeof(alias_entry));
+    a->allow_relative = ALIAS_FLAG_DEFAULT;
     return a;
 }
 
@@ -111,7 +117,9 @@ static void *merge_alias_dir_config(apr_
     a->redirect = (overrides->redirect_set == 0) ? base->redirect : overrides->redirect;
     a->redirect_status = (overrides->redirect_set == 0) ? base->redirect_status : overrides->redirect_status;
     a->redirect_set = overrides->redirect_set || base->redirect_set;
-
+    a->allow_relative = (overrides->allow_relative != ALIAS_FLAG_DEFAULT)
+                                  ? overrides->allow_relative 
+                                  : base->allow_relative;
     return a;
 }
 
@@ -591,31 +599,33 @@ static int translate_alias_redir(request
         if (ret == PREGSUB_ERROR)
             return HTTP_INTERNAL_SERVER_ERROR;
         if (ap_is_HTTP_REDIRECT(status)) {
-            if (ret[0] == '/') {
-                char *orig_target = ret;
-
-                ret = ap_construct_url(r->pool, ret, r);
-                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00673)
-                              "incomplete redirection target of '%s' for "
-                              "URI '%s' modified to '%s'",
-                              orig_target, r->uri, ret);
-            }
-            if (!ap_is_url(ret)) {
-                status = HTTP_INTERNAL_SERVER_ERROR;
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00674)
-                              "cannot redirect '%s' to '%s'; "
-                              "target is not a valid absoluteURI or abs_path",
-                              r->uri, ret);
-            }
-            else {
-                /* append requested query only, if the config didn't
-                 * supply its own.
-                 */
-                if (r->args && !ap_strchr(ret, '?')) {
-                    ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
+            alias_dir_conf *dirconf = (alias_dir_conf *) 
+                ap_get_module_config(r->per_dir_config, &alias_module);
+            if (dirconf->allow_relative != ALIAS_FLAG_ON || ret[0] != '/') {
+                if (ret[0] == '/') {
+                    char *orig_target = ret;
+
+                    ret = ap_construct_url(r->pool, ret, r);
+                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00673)
+                                  "incomplete redirection target of '%s' for "
+                                  "URI '%s' modified to '%s'",
+                                  orig_target, r->uri, ret);
                 }
-                apr_table_setn(r->headers_out, "Location", ret);
+                if (!ap_is_url(ret)) {
+                    status = HTTP_INTERNAL_SERVER_ERROR;
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00674)
+                                  "cannot redirect '%s' to '%s'; "
+                                  "target is not a valid absoluteURI or abs_path",
+                                  r->uri, ret);
+                }
+            }
+            /* append requested query only, if the config didn't
+             * supply its own.
+             */
+            if (r->args && !ap_strchr(ret, '?')) {
+                ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
             }
+            apr_table_setn(r->headers_out, "Location", ret);
         }
         return status;
     }
@@ -646,31 +656,31 @@ static int fixup_redir(request_rec *r)
         if (ret == PREGSUB_ERROR)
             return HTTP_INTERNAL_SERVER_ERROR;
         if (ap_is_HTTP_REDIRECT(status)) {
-            if (ret[0] == '/') {
-                char *orig_target = ret;
-
-                ret = ap_construct_url(r->pool, ret, r);
-                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00675)
-                              "incomplete redirection target of '%s' for "
-                              "URI '%s' modified to '%s'",
-                              orig_target, r->uri, ret);
-            }
-            if (!ap_is_url(ret)) {
-                status = HTTP_INTERNAL_SERVER_ERROR;
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00676)
-                              "cannot redirect '%s' to '%s'; "
-                              "target is not a valid absoluteURI or abs_path",
-                              r->uri, ret);
-            }
-            else {
-                /* append requested query only, if the config didn't
-                 * supply its own.
-                 */
-                if (r->args && !ap_strchr(ret, '?')) {
-                    ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
+            if (dirconf->allow_relative != ALIAS_FLAG_ON || ret[0] != '/') {
+                if (ret[0] == '/') {
+                    char *orig_target = ret;
+
+                    ret = ap_construct_url(r->pool, ret, r);
+                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00675)
+                                  "incomplete redirection target of '%s' for "
+                                  "URI '%s' modified to '%s'",
+                                  orig_target, r->uri, ret);
+                }
+                if (!ap_is_url(ret)) {
+                    status = HTTP_INTERNAL_SERVER_ERROR;
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00676)
+                                  "cannot redirect '%s' to '%s'; "
+                                  "target is not a valid absoluteURI or abs_path",
+                                  r->uri, ret);
                 }
-                apr_table_setn(r->headers_out, "Location", ret);
             }
+            /* append requested query only, if the config didn't
+             * supply its own.
+             */
+            if (r->args && !ap_strchr(ret, '?')) {
+                ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
+            }
+            apr_table_setn(r->headers_out, "Location", ret);
         }
         return status;
     }
@@ -702,6 +712,10 @@ static const command_rec alias_cmds[] =
     AP_INIT_TAKE2("RedirectPermanent", add_redirect2,
                   (void *) HTTP_MOVED_PERMANENTLY, OR_FILEINFO,
                   "a document to be redirected, then the destination URL"),
+    AP_INIT_FLAG("RedirectRelative", ap_set_flag_slot,
+                  (void*)APR_OFFSETOF(alias_dir_conf, allow_relative), OR_FILEINFO,
+                  "Set to ON to allow relative redirect targets to be issued as-is"),
+
     {NULL}
 };
 



Re: svn commit: r1861542 - in /httpd/httpd/trunk: docs/manual/mod/mod_alias.xml modules/mappers/mod_alias.c

Posted by Eric Covener <co...@gmail.com>.
> In the old code path we did not set the Location header and did not append the args if
> apr_is_url fails. So shouldn't we do a

Thanks, r1861569

Re: svn commit: r1861542 - in /httpd/httpd/trunk: docs/manual/mod/mod_alias.xml modules/mappers/mod_alias.c

Posted by Ruediger Pluem <rp...@apache.org>.

On 06/17/2019 08:35 PM, covener@apache.org wrote:
> Author: covener
> Date: Mon Jun 17 18:35:24 2019
> New Revision: 1861542
> 
> URL: http://svn.apache.org/viewvc?rev=1861542&view=rev
> Log:
> add RedirectRelative directive to allow relative Redirect targets
> 
> 2616 forbade relative redirect URLs, but 7231 allows them
> Early 2.2 maintenance levels did not fix them up, but later 2.2 and all 2.4
> fixed them up with ap_construct_url().
> 
> Allow opt-in to not fixing up relative URLs with RedirectRelative
> 
> 
> 
> Modified:
>     httpd/httpd/trunk/docs/manual/mod/mod_alias.xml
>     httpd/httpd/trunk/modules/mappers/mod_alias.c
> 

> Modified: httpd/httpd/trunk/modules/mappers/mod_alias.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mappers/mod_alias.c?rev=1861542&r1=1861541&r2=1861542&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/modules/mappers/mod_alias.c (original)
> +++ httpd/httpd/trunk/modules/mappers/mod_alias.c Mon Jun 17 18:35:24 2019
> @@ -37,6 +37,10 @@
>  #include "ap_expr.h"
>  
>  
> +#define ALIAS_FLAG_DEFAULT -1
> +#define ALIAS_FLAG_OFF 0
> +#define ALIAS_FLAG_ON  1
> +
>  typedef struct {
>      const char *real;
>      const char *fake;
> @@ -58,6 +62,7 @@ typedef struct {
>      char *handler;
>      const ap_expr_info_t *redirect;
>      int redirect_status;                /* 301, 302, 303, 410, etc */
> +    int allow_relative;                 /* skip ap_construct_url() */
>  } alias_dir_conf;
>  
>  module AP_MODULE_DECLARE_DATA alias_module;
> @@ -80,6 +85,7 @@ static void *create_alias_dir_config(apr
>      alias_dir_conf *a =
>      (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
>      a->redirects = apr_array_make(p, 2, sizeof(alias_entry));
> +    a->allow_relative = ALIAS_FLAG_DEFAULT;
>      return a;
>  }
>  
> @@ -111,7 +117,9 @@ static void *merge_alias_dir_config(apr_
>      a->redirect = (overrides->redirect_set == 0) ? base->redirect : overrides->redirect;
>      a->redirect_status = (overrides->redirect_set == 0) ? base->redirect_status : overrides->redirect_status;
>      a->redirect_set = overrides->redirect_set || base->redirect_set;
> -
> +    a->allow_relative = (overrides->allow_relative != ALIAS_FLAG_DEFAULT)
> +                                  ? overrides->allow_relative 
> +                                  : base->allow_relative;
>      return a;
>  }
>  
> @@ -591,31 +599,33 @@ static int translate_alias_redir(request
>          if (ret == PREGSUB_ERROR)
>              return HTTP_INTERNAL_SERVER_ERROR;
>          if (ap_is_HTTP_REDIRECT(status)) {
> -            if (ret[0] == '/') {
> -                char *orig_target = ret;
> -
> -                ret = ap_construct_url(r->pool, ret, r);
> -                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00673)
> -                              "incomplete redirection target of '%s' for "
> -                              "URI '%s' modified to '%s'",
> -                              orig_target, r->uri, ret);
> -            }
> -            if (!ap_is_url(ret)) {
> -                status = HTTP_INTERNAL_SERVER_ERROR;
> -                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00674)
> -                              "cannot redirect '%s' to '%s'; "
> -                              "target is not a valid absoluteURI or abs_path",
> -                              r->uri, ret);
> -            }
> -            else {
> -                /* append requested query only, if the config didn't
> -                 * supply its own.
> -                 */
> -                if (r->args && !ap_strchr(ret, '?')) {
> -                    ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
> +            alias_dir_conf *dirconf = (alias_dir_conf *) 
> +                ap_get_module_config(r->per_dir_config, &alias_module);
> +            if (dirconf->allow_relative != ALIAS_FLAG_ON || ret[0] != '/') {
> +                if (ret[0] == '/') {
> +                    char *orig_target = ret;
> +
> +                    ret = ap_construct_url(r->pool, ret, r);
> +                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00673)
> +                                  "incomplete redirection target of '%s' for "
> +                                  "URI '%s' modified to '%s'",
> +                                  orig_target, r->uri, ret);
>                  }
> -                apr_table_setn(r->headers_out, "Location", ret);
> +                if (!ap_is_url(ret)) {
> +                    status = HTTP_INTERNAL_SERVER_ERROR;
> +                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00674)
> +                                  "cannot redirect '%s' to '%s'; "
> +                                  "target is not a valid absoluteURI or abs_path",
> +                                  r->uri, ret);

In the old code path we did not set the Location header and did not append the args if
apr_is_url fails. So shouldn't we do a

return status

here in the block?

> +                }
> +            }
> +            /* append requested query only, if the config didn't
> +             * supply its own.
> +             */
> +            if (r->args && !ap_strchr(ret, '?')) {
> +                ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
>              }
> +            apr_table_setn(r->headers_out, "Location", ret);
>          }
>          return status;
>      }
> @@ -646,31 +656,31 @@ static int fixup_redir(request_rec *r)
>          if (ret == PREGSUB_ERROR)
>              return HTTP_INTERNAL_SERVER_ERROR;
>          if (ap_is_HTTP_REDIRECT(status)) {
> -            if (ret[0] == '/') {
> -                char *orig_target = ret;
> -
> -                ret = ap_construct_url(r->pool, ret, r);
> -                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00675)
> -                              "incomplete redirection target of '%s' for "
> -                              "URI '%s' modified to '%s'",
> -                              orig_target, r->uri, ret);
> -            }
> -            if (!ap_is_url(ret)) {
> -                status = HTTP_INTERNAL_SERVER_ERROR;
> -                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00676)
> -                              "cannot redirect '%s' to '%s'; "
> -                              "target is not a valid absoluteURI or abs_path",
> -                              r->uri, ret);
> -            }
> -            else {
> -                /* append requested query only, if the config didn't
> -                 * supply its own.
> -                 */
> -                if (r->args && !ap_strchr(ret, '?')) {
> -                    ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
> +            if (dirconf->allow_relative != ALIAS_FLAG_ON || ret[0] != '/') {
> +                if (ret[0] == '/') {
> +                    char *orig_target = ret;
> +
> +                    ret = ap_construct_url(r->pool, ret, r);
> +                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00675)
> +                                  "incomplete redirection target of '%s' for "
> +                                  "URI '%s' modified to '%s'",
> +                                  orig_target, r->uri, ret);
> +                }
> +                if (!ap_is_url(ret)) {
> +                    status = HTTP_INTERNAL_SERVER_ERROR;
> +                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00676)
> +                                  "cannot redirect '%s' to '%s'; "
> +                                  "target is not a valid absoluteURI or abs_path",
> +                                  r->uri, ret);

Same comment as above.

>                  }
> -                apr_table_setn(r->headers_out, "Location", ret);
>              }
> +            /* append requested query only, if the config didn't
> +             * supply its own.
> +             */
> +            if (r->args && !ap_strchr(ret, '?')) {
> +                ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
> +            }
> +            apr_table_setn(r->headers_out, "Location", ret);
>          }
>          return status;
>      }


Regards

RĂ¼diger



Re: svn commit: r1861542 - in /httpd/httpd/trunk: docs/manual/mod/mod_alias.xml modules/mappers/mod_alias.c

Posted by Eric Covener <co...@gmail.com>.
On Tue, Jun 18, 2019 at 9:34 AM William A Rowe Jr <wr...@rowe-clan.net> wrote:
>
> Hi Eric,
>
> Looking at this feature, and the new allowance effective June 2014,
> is this something we would want to toggle by envvar (in addition to
> or in lieu of a directive) similar to various gzip, caching, downgrade
> and particularly the redirect-carefully overrides? This seems like
> the sort of feature to dodge for older unsuspecting clients based
> on browsermatch, once the exceptions are identified;
>
> https://httpd.apache.org/docs/2.4/env.html#special

I think in-addition-to would be confusing.

I considered the envvar in lieu of the directive, but over the years
I've come to think that style is not preferred.

My guess is that old browsers handled relative redirects long before
723X, but it would suck to have to use <If> or add the envvar if
someone really need to turn on this obscure flag AND cope with a
client that got confused by them.

Re: svn commit: r1861542 - in /httpd/httpd/trunk: docs/manual/mod/mod_alias.xml modules/mappers/mod_alias.c

Posted by William A Rowe Jr <wr...@rowe-clan.net>.
Hi Eric,

Looking at this feature, and the new allowance effective June 2014,
is this something we would want to toggle by envvar (in addition to
or in lieu of a directive) similar to various gzip, caching, downgrade
and particularly the redirect-carefully overrides? This seems like
the sort of feature to dodge for older unsuspecting clients based
on browsermatch, once the exceptions are identified;

https://httpd.apache.org/docs/2.4/env.html#special



On Mon, Jun 17, 2019 at 1:35 PM <co...@apache.org> wrote:

> Author: covener
> Date: Mon Jun 17 18:35:24 2019
> New Revision: 1861542
>
> URL: http://svn.apache.org/viewvc?rev=1861542&view=rev
> Log:
> add RedirectRelative directive to allow relative Redirect targets
>
> 2616 forbade relative redirect URLs, but 7231 allows them
> Early 2.2 maintenance levels did not fix them up, but later 2.2 and all 2.4
> fixed them up with ap_construct_url().
>
> Allow opt-in to not fixing up relative URLs with RedirectRelative
>
>
>
> Modified:
>     httpd/httpd/trunk/docs/manual/mod/mod_alias.xml
>     httpd/httpd/trunk/modules/mappers/mod_alias.c
>
> Modified: httpd/httpd/trunk/docs/manual/mod/mod_alias.xml
> URL:
> http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_alias.xml?rev=1861542&r1=1861541&r2=1861542&view=diff
>
> ==============================================================================
> --- httpd/httpd/trunk/docs/manual/mod/mod_alias.xml (original)
> +++ httpd/httpd/trunk/docs/manual/mod/mod_alias.xml Mon Jun 17 18:35:24
> 2019
> @@ -621,4 +621,25 @@ ScriptAliasMatch "(?i)^/cgi-bin(.*)" "/u
>  </usage>
>  </directivesynopsis>
>
> +<directivesynopsis>
> +<name>RedirectRelative</name>
> +<description>Allows relative redirect targets.</description>
> +<syntax>RedirectRelative OFF|ON</syntax>
> +<default>RedirectRelative OFF</default>
> +<contextlist><context>server config</context><context>virtual
> host</context>
> +<context>directory</context>
> +<compatibility>2.5.1 and later</compatibility>
> +</contextlist>
> +
> +<usage>
> +    <p>By default, if the target URL of a <directive>Redirect</directive>
> +    directive is a relative URL beginning with a '/' character, the
> server
> +    converts it to a an absolute URL before responding to the client. By
> +    setting <directive>RedirectRelative</directive> to the value "ON",
> +    the relative URL is presented to the client directly.</p>
> +
> +</usage>
> +</directivesynopsis>
> +
> +
>  </modulesynopsis>
>
> Modified: httpd/httpd/trunk/modules/mappers/mod_alias.c
> URL:
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mappers/mod_alias.c?rev=1861542&r1=1861541&r2=1861542&view=diff
>
> ==============================================================================
> --- httpd/httpd/trunk/modules/mappers/mod_alias.c (original)
> +++ httpd/httpd/trunk/modules/mappers/mod_alias.c Mon Jun 17 18:35:24 2019
> @@ -37,6 +37,10 @@
>  #include "ap_expr.h"
>
>
> +#define ALIAS_FLAG_DEFAULT -1
> +#define ALIAS_FLAG_OFF 0
> +#define ALIAS_FLAG_ON  1
> +
>  typedef struct {
>      const char *real;
>      const char *fake;
> @@ -58,6 +62,7 @@ typedef struct {
>      char *handler;
>      const ap_expr_info_t *redirect;
>      int redirect_status;                /* 301, 302, 303, 410, etc */
> +    int allow_relative;                 /* skip ap_construct_url() */
>  } alias_dir_conf;
>
>  module AP_MODULE_DECLARE_DATA alias_module;
> @@ -80,6 +85,7 @@ static void *create_alias_dir_config(apr
>      alias_dir_conf *a =
>      (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
>      a->redirects = apr_array_make(p, 2, sizeof(alias_entry));
> +    a->allow_relative = ALIAS_FLAG_DEFAULT;
>      return a;
>  }
>
> @@ -111,7 +117,9 @@ static void *merge_alias_dir_config(apr_
>      a->redirect = (overrides->redirect_set == 0) ? base->redirect :
> overrides->redirect;
>      a->redirect_status = (overrides->redirect_set == 0) ?
> base->redirect_status : overrides->redirect_status;
>      a->redirect_set = overrides->redirect_set || base->redirect_set;
> -
> +    a->allow_relative = (overrides->allow_relative != ALIAS_FLAG_DEFAULT)
> +                                  ? overrides->allow_relative
> +                                  : base->allow_relative;
>      return a;
>  }
>
> @@ -591,31 +599,33 @@ static int translate_alias_redir(request
>          if (ret == PREGSUB_ERROR)
>              return HTTP_INTERNAL_SERVER_ERROR;
>          if (ap_is_HTTP_REDIRECT(status)) {
> -            if (ret[0] == '/') {
> -                char *orig_target = ret;
> -
> -                ret = ap_construct_url(r->pool, ret, r);
> -                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
> APLOGNO(00673)
> -                              "incomplete redirection target of '%s' for "
> -                              "URI '%s' modified to '%s'",
> -                              orig_target, r->uri, ret);
> -            }
> -            if (!ap_is_url(ret)) {
> -                status = HTTP_INTERNAL_SERVER_ERROR;
> -                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00674)
> -                              "cannot redirect '%s' to '%s'; "
> -                              "target is not a valid absoluteURI or
> abs_path",
> -                              r->uri, ret);
> -            }
> -            else {
> -                /* append requested query only, if the config didn't
> -                 * supply its own.
> -                 */
> -                if (r->args && !ap_strchr(ret, '?')) {
> -                    ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
> +            alias_dir_conf *dirconf = (alias_dir_conf *)
> +                ap_get_module_config(r->per_dir_config, &alias_module);
> +            if (dirconf->allow_relative != ALIAS_FLAG_ON || ret[0] !=
> '/') {
> +                if (ret[0] == '/') {
> +                    char *orig_target = ret;
> +
> +                    ret = ap_construct_url(r->pool, ret, r);
> +                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
> APLOGNO(00673)
> +                                  "incomplete redirection target of '%s'
> for "
> +                                  "URI '%s' modified to '%s'",
> +                                  orig_target, r->uri, ret);
>                  }
> -                apr_table_setn(r->headers_out, "Location", ret);
> +                if (!ap_is_url(ret)) {
> +                    status = HTTP_INTERNAL_SERVER_ERROR;
> +                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
> APLOGNO(00674)
> +                                  "cannot redirect '%s' to '%s'; "
> +                                  "target is not a valid absoluteURI or
> abs_path",
> +                                  r->uri, ret);
> +                }
> +            }
> +            /* append requested query only, if the config didn't
> +             * supply its own.
> +             */
> +            if (r->args && !ap_strchr(ret, '?')) {
> +                ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
>              }
> +            apr_table_setn(r->headers_out, "Location", ret);
>          }
>          return status;
>      }
> @@ -646,31 +656,31 @@ static int fixup_redir(request_rec *r)
>          if (ret == PREGSUB_ERROR)
>              return HTTP_INTERNAL_SERVER_ERROR;
>          if (ap_is_HTTP_REDIRECT(status)) {
> -            if (ret[0] == '/') {
> -                char *orig_target = ret;
> -
> -                ret = ap_construct_url(r->pool, ret, r);
> -                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
> APLOGNO(00675)
> -                              "incomplete redirection target of '%s' for "
> -                              "URI '%s' modified to '%s'",
> -                              orig_target, r->uri, ret);
> -            }
> -            if (!ap_is_url(ret)) {
> -                status = HTTP_INTERNAL_SERVER_ERROR;
> -                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00676)
> -                              "cannot redirect '%s' to '%s'; "
> -                              "target is not a valid absoluteURI or
> abs_path",
> -                              r->uri, ret);
> -            }
> -            else {
> -                /* append requested query only, if the config didn't
> -                 * supply its own.
> -                 */
> -                if (r->args && !ap_strchr(ret, '?')) {
> -                    ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
> +            if (dirconf->allow_relative != ALIAS_FLAG_ON || ret[0] !=
> '/') {
> +                if (ret[0] == '/') {
> +                    char *orig_target = ret;
> +
> +                    ret = ap_construct_url(r->pool, ret, r);
> +                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
> APLOGNO(00675)
> +                                  "incomplete redirection target of '%s'
> for "
> +                                  "URI '%s' modified to '%s'",
> +                                  orig_target, r->uri, ret);
> +                }
> +                if (!ap_is_url(ret)) {
> +                    status = HTTP_INTERNAL_SERVER_ERROR;
> +                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
> APLOGNO(00676)
> +                                  "cannot redirect '%s' to '%s'; "
> +                                  "target is not a valid absoluteURI or
> abs_path",
> +                                  r->uri, ret);
>                  }
> -                apr_table_setn(r->headers_out, "Location", ret);
>              }
> +            /* append requested query only, if the config didn't
> +             * supply its own.
> +             */
> +            if (r->args && !ap_strchr(ret, '?')) {
> +                ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
> +            }
> +            apr_table_setn(r->headers_out, "Location", ret);
>          }
>          return status;
>      }
> @@ -702,6 +712,10 @@ static const command_rec alias_cmds[] =
>      AP_INIT_TAKE2("RedirectPermanent", add_redirect2,
>                    (void *) HTTP_MOVED_PERMANENTLY, OR_FILEINFO,
>                    "a document to be redirected, then the destination
> URL"),
> +    AP_INIT_FLAG("RedirectRelative", ap_set_flag_slot,
> +                  (void*)APR_OFFSETOF(alias_dir_conf, allow_relative),
> OR_FILEINFO,
> +                  "Set to ON to allow relative redirect targets to be
> issued as-is"),
> +
>      {NULL}
>  };
>
>
>
>