diff options
Diffstat (limited to 'modules/mappers/mod_alias.c')
-rw-r--r-- | modules/mappers/mod_alias.c | 186 |
1 files changed, 113 insertions, 73 deletions
diff --git a/modules/mappers/mod_alias.c b/modules/mappers/mod_alias.c index 79d58d8..35eca74 100644 --- a/modules/mappers/mod_alias.c +++ b/modules/mappers/mod_alias.c @@ -37,6 +37,12 @@ #include "ap_expr.h" +#define ALIAS_FLAG_DEFAULT -1 +#define ALIAS_FLAG_OFF 0 +#define ALIAS_FLAG_ON 1 + +#define ALIAS_PRESERVE_PATH_DEFAULT 0 + typedef struct { const char *real; const char *fake; @@ -55,9 +61,12 @@ typedef struct { unsigned int redirect_set:1; apr_array_header_t *redirects; const ap_expr_info_t *alias; + const char *alias_fake; char *handler; const ap_expr_info_t *redirect; int redirect_status; /* 301, 302, 303, 410, etc */ + int allow_relative; /* skip ap_construct_url() */ + int alias_preserve_path; /* map full path */ } alias_dir_conf; module AP_MODULE_DECLARE_DATA alias_module; @@ -80,6 +89,8 @@ static void *create_alias_dir_config(apr_pool_t *p, char *d) 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; + a->alias_preserve_path = ALIAS_FLAG_DEFAULT; return a; } @@ -105,12 +116,19 @@ static void *merge_alias_dir_config(apr_pool_t *p, void *basev, void *overridesv a->redirects = apr_array_append(p, overrides->redirects, base->redirects); a->alias = (overrides->alias_set == 0) ? base->alias : overrides->alias; + a->alias_fake = (overrides->alias_set == 0) ? base->alias_fake : overrides->alias_fake; a->handler = (overrides->alias_set == 0) ? base->handler : overrides->handler; a->alias_set = overrides->alias_set || base->alias_set; 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; + a->alias_preserve_path = (overrides->alias_preserve_path != ALIAS_FLAG_DEFAULT) + ? overrides->alias_preserve_path + : base->alias_preserve_path; return a; } @@ -210,6 +228,7 @@ static const char *add_alias(cmd_parms *cmd, void *dummy, const char *fake, NULL); } + dirconf->alias_fake = cmd->path; dirconf->handler = cmd->info; dirconf->alias_set = 1; @@ -373,33 +392,6 @@ static const char *add_redirect_regex(cmd_parms *cmd, void *dirconf, return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 1); } -static const command_rec alias_cmds[] = -{ - AP_INIT_TAKE12("Alias", add_alias, NULL, RSRC_CONF | ACCESS_CONF, - "a fakename and a realname, or a realname in a Location"), - AP_INIT_TAKE12("ScriptAlias", add_alias, "cgi-script", RSRC_CONF | ACCESS_CONF, - "a fakename and a realname, or a realname in a Location"), - AP_INIT_TAKE123("Redirect", add_redirect, (void *) HTTP_MOVED_TEMPORARILY, - OR_FILEINFO, - "an optional status, then document to be redirected and " - "destination URL"), - AP_INIT_TAKE2("AliasMatch", add_alias_regex, NULL, RSRC_CONF, - "a regular expression and a filename"), - AP_INIT_TAKE2("ScriptAliasMatch", add_alias_regex, "cgi-script", RSRC_CONF, - "a regular expression and a filename"), - AP_INIT_TAKE23("RedirectMatch", add_redirect_regex, - (void *) HTTP_MOVED_TEMPORARILY, OR_FILEINFO, - "an optional status, then a regular expression and " - "destination URL"), - AP_INIT_TAKE2("RedirectTemp", add_redirect2, - (void *) HTTP_MOVED_TEMPORARILY, OR_FILEINFO, - "a document to be redirected, then the destination URL"), - AP_INIT_TAKE2("RedirectPermanent", add_redirect2, - (void *) HTTP_MOVED_PERMANENTLY, OR_FILEINFO, - "a document to be redirected, then the destination URL"), - {NULL} -}; - static int alias_matches(const char *uri, const char *alias_fakename) { const char *aliasp = alias_fakename, *urip = uri; @@ -455,6 +447,17 @@ static char *try_alias(request_rec *r) return PREGSUB_ERROR; } + if (dirconf->alias_fake && dirconf->alias_preserve_path == ALIAS_FLAG_ON) { + int l; + + l = alias_matches(r->uri, dirconf->alias_fake); + + if (l > 0) { + ap_set_context_info(r, dirconf->alias_fake, found); + found = apr_pstrcat(r->pool, found, r->uri + l, NULL); + } + } + if (dirconf->handler) { /* Set handler, and leave a note for mod_cgi */ r->handler = dirconf->handler; apr_table_setn(r->notes, "alias-forced-type", r->handler); @@ -618,31 +621,33 @@ static int translate_alias_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(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)) { + 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); + return HTTP_INTERNAL_SERVER_ERROR; + } + } + /* 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; } @@ -673,31 +678,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); } - apr_table_setn(r->headers_out, "Location", ret); + if (!ap_is_url(ret)) { + 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); + return HTTP_INTERNAL_SERVER_ERROR; + } + } + /* 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; } @@ -705,6 +710,41 @@ static int fixup_redir(request_rec *r) return DECLINED; } +static const command_rec alias_cmds[] = +{ + AP_INIT_TAKE12("Alias", add_alias, NULL, RSRC_CONF | ACCESS_CONF, + "a fakename and a realname, or a realname in a Location"), + AP_INIT_TAKE12("ScriptAlias", add_alias, "cgi-script", RSRC_CONF | ACCESS_CONF, + "a fakename and a realname, or a realname in a Location"), + AP_INIT_TAKE123("Redirect", add_redirect, (void *) HTTP_MOVED_TEMPORARILY, + OR_FILEINFO, + "an optional status, then document to be redirected and " + "destination URL"), + AP_INIT_TAKE2("AliasMatch", add_alias_regex, NULL, RSRC_CONF, + "a regular expression and a filename"), + AP_INIT_TAKE2("ScriptAliasMatch", add_alias_regex, "cgi-script", RSRC_CONF, + "a regular expression and a filename"), + AP_INIT_TAKE23("RedirectMatch", add_redirect_regex, + (void *) HTTP_MOVED_TEMPORARILY, OR_FILEINFO, + "an optional status, then a regular expression and " + "destination URL"), + AP_INIT_TAKE2("RedirectTemp", add_redirect2, + (void *) HTTP_MOVED_TEMPORARILY, OR_FILEINFO, + "a document to be redirected, then the destination URL"), + 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"), + AP_INIT_FLAG("AliasPreservePath", ap_set_flag_slot, + (void*)APR_OFFSETOF(alias_dir_conf, alias_preserve_path), OR_FILEINFO, + "Set to ON to map the full path after the fakename to the realname."), + + {NULL} +}; + + static void register_hooks(apr_pool_t *p) { static const char * const aszSucc[]={ "mod_userdir.c", |