Lines 46-65
Link Here
|
46 |
} alias_entry; |
46 |
} alias_entry; |
47 |
|
47 |
|
48 |
typedef struct { |
48 |
typedef struct { |
49 |
apr_array_header_t *aliases; |
49 |
apr_array_header_t *aliases; |
50 |
apr_array_header_t *redirects; |
50 |
apr_array_header_t *redirects; |
51 |
} alias_server_conf; |
51 |
} alias_server_conf; |
52 |
|
52 |
|
53 |
typedef struct { |
53 |
typedef struct { |
54 |
unsigned int alias_set:1; |
54 |
unsigned int alias_set:1; |
55 |
unsigned int redirect_set:1; |
55 |
unsigned int redirect_set:1; |
|
|
56 |
apr_array_header_t *aliases; |
56 |
apr_array_header_t *redirects; |
57 |
apr_array_header_t *redirects; |
57 |
const ap_expr_info_t *alias; |
58 |
const ap_expr_info_t *alias; |
58 |
char *handler; |
59 |
char *handler; |
59 |
const ap_expr_info_t *redirect; |
60 |
const ap_expr_info_t *redirect; |
60 |
int redirect_status; /* 301, 302, 303, 410, etc */ |
61 |
int redirect_status; /* 301, 302, 303, 410, etc */ |
61 |
} alias_dir_conf; |
62 |
} alias_dir_conf; |
62 |
|
63 |
|
63 |
module AP_MODULE_DECLARE_DATA alias_module; |
64 |
module AP_MODULE_DECLARE_DATA alias_module; |
64 |
|
65 |
|
65 |
static char magic_error_value; |
66 |
static char magic_error_value; |
Lines 72-91
Link Here
|
72 |
|
73 |
|
73 |
a->aliases = apr_array_make(p, 20, sizeof(alias_entry)); |
74 |
a->aliases = apr_array_make(p, 20, sizeof(alias_entry)); |
74 |
a->redirects = apr_array_make(p, 20, sizeof(alias_entry)); |
75 |
a->redirects = apr_array_make(p, 20, sizeof(alias_entry)); |
75 |
return a; |
76 |
return a; |
76 |
} |
77 |
} |
77 |
|
78 |
|
78 |
static void *create_alias_dir_config(apr_pool_t *p, char *d) |
79 |
static void *create_alias_dir_config(apr_pool_t *p, char *d) |
79 |
{ |
80 |
{ |
80 |
alias_dir_conf *a = |
81 |
alias_dir_conf *a = |
81 |
(alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf)); |
82 |
(alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf)); |
|
|
83 |
a->aliases = apr_array_make(p, 2, sizeof(alias_entry)); |
82 |
a->redirects = apr_array_make(p, 2, sizeof(alias_entry)); |
84 |
a->redirects = apr_array_make(p, 2, sizeof(alias_entry)); |
83 |
return a; |
85 |
return a; |
84 |
} |
86 |
} |
85 |
|
87 |
|
86 |
static void *merge_alias_config(apr_pool_t *p, void *basev, void *overridesv) |
88 |
static void *merge_alias_config(apr_pool_t *p, void *basev, void *overridesv) |
87 |
{ |
89 |
{ |
88 |
alias_server_conf *a = |
90 |
alias_server_conf *a = |
89 |
(alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf)); |
91 |
(alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf)); |
90 |
alias_server_conf *base = (alias_server_conf *) basev; |
92 |
alias_server_conf *base = (alias_server_conf *) basev; |
91 |
alias_server_conf *overrides = (alias_server_conf *) overridesv; |
93 |
alias_server_conf *overrides = (alias_server_conf *) overridesv; |
Lines 95-203
Link Here
|
95 |
return a; |
97 |
return a; |
96 |
} |
98 |
} |
97 |
|
99 |
|
98 |
static void *merge_alias_dir_config(apr_pool_t *p, void *basev, void *overridesv) |
100 |
static void *merge_alias_dir_config(apr_pool_t *p, void *basev, void *overridesv) |
99 |
{ |
101 |
{ |
100 |
alias_dir_conf *a = |
102 |
alias_dir_conf *a = |
101 |
(alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf)); |
103 |
(alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf)); |
102 |
alias_dir_conf *base = (alias_dir_conf *) basev; |
104 |
alias_dir_conf *base = (alias_dir_conf *) basev; |
103 |
alias_dir_conf *overrides = (alias_dir_conf *) overridesv; |
105 |
alias_dir_conf *overrides = (alias_dir_conf *) overridesv; |
104 |
|
106 |
|
|
|
107 |
a->aliases = apr_array_append(p, overrides->aliases, base->aliases); |
105 |
a->redirects = apr_array_append(p, overrides->redirects, base->redirects); |
108 |
a->redirects = apr_array_append(p, overrides->redirects, base->redirects); |
106 |
|
109 |
|
107 |
a->alias = (overrides->alias_set == 0) ? base->alias : overrides->alias; |
110 |
a->alias = (overrides->alias_set == 0) ? base->alias : overrides->alias; |
108 |
a->handler = (overrides->alias_set == 0) ? base->handler : overrides->handler; |
111 |
a->handler = (overrides->alias_set == 0) ? base->handler : overrides->handler; |
109 |
a->alias_set = overrides->alias_set || base->alias_set; |
112 |
a->alias_set = overrides->alias_set || base->alias_set; |
110 |
|
113 |
|
111 |
a->redirect = (overrides->redirect_set == 0) ? base->redirect : overrides->redirect; |
114 |
a->redirect = (overrides->redirect_set == 0) ? base->redirect : overrides->redirect; |
112 |
a->redirect_status = (overrides->redirect_set == 0) ? base->redirect_status : overrides->redirect_status; |
115 |
a->redirect_status = (overrides->redirect_set == 0) ? base->redirect_status : overrides->redirect_status; |
113 |
a->redirect_set = overrides->redirect_set || base->redirect_set; |
116 |
a->redirect_set = overrides->redirect_set || base->redirect_set; |
114 |
|
117 |
|
115 |
return a; |
118 |
return a; |
116 |
} |
119 |
} |
117 |
|
120 |
|
118 |
/* need prototype for overlap check */ |
121 |
/* need prototype for overlap check */ |
119 |
static int alias_matches(const char *uri, const char *alias_fakename); |
122 |
static int alias_matches(const char *uri, const char *alias_fakename); |
120 |
|
123 |
|
121 |
static const char *add_alias_internal(cmd_parms *cmd, void *dummy, |
124 |
static const char *add_alias_internal(cmd_parms *cmd, alias_dir_conf *dirconf, |
122 |
const char *fake, const char *real, |
125 |
const char *fake, const char *real, |
123 |
int use_regex) |
126 |
int use_regex) |
124 |
{ |
127 |
{ |
|
|
128 |
alias_entry *new; |
125 |
server_rec *s = cmd->server; |
129 |
server_rec *s = cmd->server; |
126 |
alias_server_conf *conf = ap_get_module_config(s->module_config, |
130 |
alias_server_conf *serverconf = ap_get_module_config(s->module_config, |
127 |
&alias_module); |
131 |
&alias_module); |
128 |
alias_entry *new = apr_array_push(conf->aliases); |
|
|
129 |
alias_entry *entries = (alias_entry *)conf->aliases->elts; |
130 |
int i; |
131 |
|
132 |
|
132 |
/* XXX: real can NOT be relative to DocumentRoot here... compat bug. */ |
133 |
/* XXX: real can NOT be relative to DocumentRoot here... compat bug. */ |
133 |
|
134 |
|
134 |
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); |
135 |
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); |
135 |
|
136 |
|
136 |
if (err != NULL) { |
137 |
if (err != NULL) { |
137 |
return err; |
138 |
return err; |
138 |
} |
139 |
} |
139 |
|
140 |
|
140 |
if (use_regex) { |
|
|
141 |
new->regexp = ap_pregcomp(cmd->pool, fake, AP_REG_EXTENDED); |
142 |
if (new->regexp == NULL) |
143 |
return "Regular expression could not be compiled."; |
144 |
new->real = real; |
145 |
} |
146 |
else { |
147 |
/* XXX This may be optimized, but we must know that new->real |
148 |
* exists. If so, we can dir merge later, trusing new->real |
149 |
* and just canonicalizing the remainder. Not till I finish |
150 |
* cleaning out the old ap_canonical stuff first. |
151 |
*/ |
152 |
new->real = real; |
153 |
} |
154 |
new->fake = fake; |
155 |
new->handler = cmd->info; |
156 |
|
157 |
/* check for overlapping (Script)Alias directives |
141 |
/* check for overlapping (Script)Alias directives |
158 |
* and throw a warning if found one |
142 |
* and throw a warning if found one |
159 |
*/ |
143 |
*/ |
160 |
if (!use_regex) { |
144 |
if (!use_regex) { |
161 |
for (i = 0; i < conf->aliases->nelts - 1; ++i) { |
145 |
int num_server_elts = serverconf->aliases->nelts; |
162 |
alias_entry *alias = &entries[i]; |
146 |
int num_dir_elts = dirconf->aliases->nelts; |
|
|
147 |
int total_elts = num_server_elts + num_dir_elts; |
148 |
int i; |
149 |
|
150 |
for (i = 0; i < total_elts; ++i) { |
151 |
alias_entry *alias; |
152 |
if (i < num_server_elts) { |
153 |
alias = &serverconf->aliases->elts[i]; |
154 |
} |
155 |
else { |
156 |
alias = &dirconf->aliases->elts[i - num_server_elts]; |
157 |
} |
163 |
|
158 |
|
164 |
if ( (!alias->regexp && alias_matches(fake, alias->fake) > 0) |
159 |
if ( (!alias->regexp && alias_matches(fake, alias->fake) > 0) |
165 |
|| (alias->regexp && !ap_regexec(alias->regexp, fake, 0, NULL, 0))) { |
160 |
|| (alias->regexp && !ap_regexec(alias->regexp, fake, 0, NULL, 0))) { |
166 |
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(00671) |
161 |
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(00671) |
167 |
"The %s directive in %s at line %d will probably " |
162 |
"The %s directive in %s at line %d will probably " |
168 |
"never match because it overlaps an earlier " |
163 |
"never match because it overlaps an earlier " |
169 |
"%sAlias%s.", |
164 |
"%sAlias%s.", |
170 |
cmd->cmd->name, cmd->directive->filename, |
165 |
cmd->cmd->name, cmd->directive->filename, |
171 |
cmd->directive->line_num, |
166 |
cmd->directive->line_num, |
172 |
alias->handler ? "Script" : "", |
167 |
alias->handler ? "Script" : "", |
173 |
alias->regexp ? "Match" : ""); |
168 |
alias->regexp ? "Match" : ""); |
174 |
|
169 |
|
175 |
break; /* one warning per alias should be sufficient */ |
170 |
break; /* one warning per alias should be sufficient */ |
176 |
} |
171 |
} |
177 |
} |
172 |
} |
178 |
} |
173 |
} |
179 |
|
174 |
|
|
|
175 |
/* Add a new entry for the alias in either the server or per-directory |
176 |
* (including e.g. <If> section) configuration, as appropriate. |
177 |
*/ |
178 |
if (cmd->path) { |
179 |
new = apr_array_push(dirconf->aliases); |
180 |
} |
181 |
else { |
182 |
new = apr_array_push(serverconf->aliases); |
183 |
} |
184 |
|
185 |
if (use_regex) { |
186 |
new->regexp = ap_pregcomp(cmd->pool, fake, AP_REG_EXTENDED); |
187 |
if (new->regexp == NULL) |
188 |
return "Regular expression could not be compiled."; |
189 |
new->real = real; |
190 |
} |
191 |
else { |
192 |
/* XXX This may be optimized, but we must know that new->real |
193 |
* exists. If so, we can dir merge later, trusing new->real |
194 |
* and just canonicalizing the remainder. Not till I finish |
195 |
* cleaning out the old ap_canonical stuff first. |
196 |
*/ |
197 |
new->real = real; |
198 |
} |
199 |
new->fake = fake; |
200 |
new->handler = cmd->info; |
201 |
|
180 |
return NULL; |
202 |
return NULL; |
181 |
} |
203 |
} |
182 |
|
204 |
|
183 |
static const char *add_alias(cmd_parms *cmd, void *dummy, const char *fake, |
205 |
static const char *add_alias(cmd_parms *cmd, void *dirconfv, const char *fake, |
184 |
const char *real) |
206 |
const char *real) |
185 |
{ |
207 |
{ |
|
|
208 |
alias_dir_conf *dirconf = (alias_dir_conf *) dirconfv; |
186 |
if (real) { |
209 |
if (real) { |
187 |
|
210 |
|
188 |
return add_alias_internal(cmd, dummy, fake, real, 0); |
211 |
return add_alias_internal(cmd, dirconf, fake, real, 0); |
189 |
|
212 |
|
190 |
} |
213 |
} |
191 |
else { |
214 |
else { |
192 |
alias_dir_conf *dirconf = (alias_dir_conf *) dummy; |
|
|
193 |
|
194 |
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIRECTORY|NOT_IN_FILES); |
215 |
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIRECTORY|NOT_IN_FILES); |
195 |
|
216 |
|
196 |
if (err != NULL) { |
217 |
if (err != NULL) { |
197 |
return err; |
218 |
return err; |
198 |
} |
219 |
} |
199 |
|
220 |
|
200 |
if (!cmd->path) { |
221 |
if (!cmd->path) { |
201 |
return "Alias must have two arguments when used globally"; |
222 |
return "Alias must have two arguments when used globally"; |
202 |
} |
223 |
} |
203 |
|
224 |
|
Lines 211-234
Link Here
|
211 |
} |
232 |
} |
212 |
|
233 |
|
213 |
dirconf->handler = cmd->info; |
234 |
dirconf->handler = cmd->info; |
214 |
dirconf->alias_set = 1; |
235 |
dirconf->alias_set = 1; |
215 |
|
236 |
|
216 |
return NULL; |
237 |
return NULL; |
217 |
|
238 |
|
218 |
} |
239 |
} |
219 |
} |
240 |
} |
220 |
|
241 |
|
221 |
static const char *add_alias_regex(cmd_parms *cmd, void *dummy, |
242 |
static const char *add_alias_regex(cmd_parms *cmd, void *dirconfv, |
222 |
const char *fake, const char *real) |
243 |
const char *fake, const char *real) |
223 |
{ |
244 |
{ |
224 |
return add_alias_internal(cmd, dummy, fake, real, 1); |
245 |
return add_alias_internal(cmd, (alias_dir_conf *) dirconfv, fake, real, 1); |
225 |
} |
246 |
} |
226 |
|
247 |
|
227 |
static const char *add_redirect_internal(cmd_parms *cmd, |
248 |
static const char *add_redirect_internal(cmd_parms *cmd, |
228 |
alias_dir_conf *dirconf, |
249 |
alias_dir_conf *dirconf, |
229 |
const char *arg1, const char *arg2, |
250 |
const char *arg1, const char *arg2, |
230 |
const char *arg3, int use_regex) |
251 |
const char *arg3, int use_regex) |
231 |
{ |
252 |
{ |
232 |
alias_entry *new; |
253 |
alias_entry *new; |
233 |
server_rec *s = cmd->server; |
254 |
server_rec *s = cmd->server; |
234 |
alias_server_conf *serverconf = ap_get_module_config(s->module_config, |
255 |
alias_server_conf *serverconf = ap_get_module_config(s->module_config, |
Lines 598-626
Link Here
|
598 |
|
619 |
|
599 |
} |
620 |
} |
600 |
|
621 |
|
601 |
return NULL; |
622 |
return NULL; |
602 |
} |
623 |
} |
603 |
|
624 |
|
604 |
static int translate_alias_redir(request_rec *r) |
625 |
static int translate_alias_redir(request_rec *r) |
605 |
{ |
626 |
{ |
606 |
ap_conf_vector_t *sconf = r->server->module_config; |
627 |
ap_conf_vector_t *sconf = r->server->module_config; |
607 |
alias_server_conf *serverconf = ap_get_module_config(sconf, &alias_module); |
628 |
alias_server_conf *serverconf = ap_get_module_config(sconf, &alias_module); |
|
|
629 |
void *dconf = r->per_dir_config; |
630 |
alias_dir_conf *dirconf = |
631 |
(alias_dir_conf *) ap_get_module_config(dconf, &alias_module); |
608 |
char *ret; |
632 |
char *ret; |
609 |
int status; |
633 |
int status; |
610 |
|
634 |
|
611 |
if (r->uri[0] != '/' && r->uri[0] != '\0') { |
635 |
if (r->uri[0] != '/' && r->uri[0] != '\0') { |
612 |
return DECLINED; |
636 |
return DECLINED; |
613 |
} |
637 |
} |
614 |
|
638 |
|
|
|
639 |
/* Look for matching redirections in the following order: |
640 |
* - The whole-<Location> redirect in the <Location> that is relevant to |
641 |
* this request, if there is one. |
642 |
* - An unconditional server / vhost redirect. |
643 |
* - A per-directory redirect at the top-level for the server / vhost, |
644 |
* which may have come from a conditional <If> section -- we only expect |
645 |
* that much to have been merged into r->per_dir_config at this point, |
646 |
* since we are still translating URLs and mapping them to the file |
647 |
* system. |
648 |
*/ |
615 |
if ((ret = try_redirect(r, &status)) != NULL |
649 |
if ((ret = try_redirect(r, &status)) != NULL |
616 |
|| (ret = try_alias_list(r, serverconf->redirects, 1, &status)) |
650 |
|| (ret = try_alias_list(r, serverconf->redirects, 1, &status)) |
|
|
651 |
!= NULL |
652 |
|| (ret = try_alias_list(r, dirconf->redirects, 1, &status)) |
617 |
!= NULL) { |
653 |
!= NULL) { |
618 |
if (ret == PREGSUB_ERROR) |
654 |
if (ret == PREGSUB_ERROR) |
619 |
return HTTP_INTERNAL_SERVER_ERROR; |
655 |
return HTTP_INTERNAL_SERVER_ERROR; |
620 |
if (ap_is_HTTP_REDIRECT(status)) { |
656 |
if (ap_is_HTTP_REDIRECT(status)) { |
621 |
if (ret[0] == '/') { |
657 |
if (ret[0] == '/') { |
622 |
char *orig_target = ret; |
658 |
char *orig_target = ret; |
623 |
|
659 |
|
624 |
ret = ap_construct_url(r->pool, ret, r); |
660 |
ret = ap_construct_url(r->pool, ret, r); |
625 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00673) |
661 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00673) |
626 |
"incomplete redirection target of '%s' for " |
662 |
"incomplete redirection target of '%s' for " |
Lines 640-661
Link Here
|
640 |
*/ |
676 |
*/ |
641 |
if (r->args && !ap_strchr(ret, '?')) { |
677 |
if (r->args && !ap_strchr(ret, '?')) { |
642 |
ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL); |
678 |
ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL); |
643 |
} |
679 |
} |
644 |
apr_table_setn(r->headers_out, "Location", ret); |
680 |
apr_table_setn(r->headers_out, "Location", ret); |
645 |
} |
681 |
} |
646 |
} |
682 |
} |
647 |
return status; |
683 |
return status; |
648 |
} |
684 |
} |
649 |
|
685 |
|
|
|
686 |
/* Look for matching aliases in the following order: |
687 |
* - The whole-<Location> alias in the <Location> that is relevant to this |
688 |
* request, if there is one. |
689 |
* - An unconditional server / vhost alias. |
690 |
* - A per-directory alias at the top-level for the server / vhost, |
691 |
* which may have come from a conditional <If> section -- we only expect |
692 |
* that much to have been merged into r->per_dir_config since at this |
693 |
* point we are translating URLs, before mapping to the file system can |
694 |
* occur. |
695 |
*/ |
650 |
if ((ret = try_alias(r)) != NULL |
696 |
if ((ret = try_alias(r)) != NULL |
651 |
|| (ret = try_alias_list(r, serverconf->aliases, 0, &status)) |
697 |
|| (ret = try_alias_list(r, serverconf->aliases, 0, &status)) |
|
|
698 |
!= NULL |
699 |
|| (ret = try_alias_list(r, dirconf->aliases, 0, &status)) |
652 |
!= NULL) { |
700 |
!= NULL) { |
653 |
r->filename = ret; |
701 |
r->filename = ret; |
654 |
return OK; |
702 |
return OK; |
655 |
} |
703 |
} |
656 |
|
704 |
|
657 |
return DECLINED; |
705 |
return DECLINED; |
658 |
} |
706 |
} |
659 |
|
707 |
|
660 |
static int fixup_redir(request_rec *r) |
708 |
static int fixup_redir(request_rec *r) |
661 |
{ |
709 |
{ |