/[Apache-SVN]/httpd/httpd/trunk/modules/mappers/mod_alias.c
ViewVC logotype

Contents of /httpd/httpd/trunk/modules/mappers/mod_alias.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 102949 - (hide annotations)
Sat Mar 13 21:19:56 2004 UTC (5 years, 8 months ago) by nd
File MIME type: text/plain
File size: 16345 byte(s)
emit the config filename when warning about overlapping aliases

Submitted by: Guenter Knauf <eflash gmx.net>
Reviewed by: Dirk-Willem van Gulik
1 nd 102618 /* Copyright 1999-2004 The Apache Software Foundation
2 fielding 83751 *
3 nd 102525 * Licensed under the Apache License, Version 2.0 (the "License");
4     * you may not use this file except in compliance with the License.
5     * You may obtain a copy of the License at
6 fielding 84879 *
7 nd 102525 * http://www.apache.org/licenses/LICENSE-2.0
8 fielding 83751 *
9 nd 102525 * Unless required by applicable law or agreed to in writing, software
10     * distributed under the License is distributed on an "AS IS" BASIS,
11     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12     * See the License for the specific language governing permissions and
13     * limitations under the License.
14 fielding 83751 */
15    
16     /*
17     * http_alias.c: Stuff for dealing with directory aliases
18     *
19     * Original by Rob McCool, rewritten in succession by David Robinson
20     * and rst.
21     *
22     */
23    
24 rbb 85867 #include "apr_strings.h"
25 gstein 88060 #include "apr_lib.h"
26    
27     #define APR_WANT_STRFUNC
28     #include "apr_want.h"
29    
30 rbb 84531 #include "ap_config.h"
31 fielding 83751 #include "httpd.h"
32 coar 93143 #include "http_core.h"
33 fielding 83751 #include "http_config.h"
34 fielding 83770 #include "http_request.h"
35 coar 93137 #include "http_log.h"
36 fielding 83751
37 gstein 88060
38 fielding 83751 typedef struct {
39 ben 85644 const char *real;
40     const char *fake;
41 fielding 83751 char *handler;
42     regex_t *regexp;
43 jerenkrantz 95503 int redir_status; /* 301, 302, 303, 410, etc */
44 fielding 83751 } alias_entry;
45    
46     typedef struct {
47 dougm 85976 apr_array_header_t *aliases;
48     apr_array_header_t *redirects;
49 fielding 83751 } alias_server_conf;
50    
51     typedef struct {
52 dougm 85976 apr_array_header_t *redirects;
53 fielding 83751 } alias_dir_conf;
54    
55 wrowe 86609 module AP_MODULE_DECLARE_DATA alias_module;
56 fielding 83751
57 dougm 85976 static void *create_alias_config(apr_pool_t *p, server_rec *s)
58 fielding 83751 {
59     alias_server_conf *a =
60 dougm 85976 (alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf));
61 fielding 83751
62 dougm 88019 a->aliases = apr_array_make(p, 20, sizeof(alias_entry));
63     a->redirects = apr_array_make(p, 20, sizeof(alias_entry));
64 fielding 83751 return a;
65     }
66    
67 dougm 85976 static void *create_alias_dir_config(apr_pool_t *p, char *d)
68 fielding 83751 {
69     alias_dir_conf *a =
70 dougm 85976 (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
71 dougm 88019 a->redirects = apr_array_make(p, 2, sizeof(alias_entry));
72 fielding 83751 return a;
73     }
74    
75 dougm 85976 static void *merge_alias_config(apr_pool_t *p, void *basev, void *overridesv)
76 fielding 83751 {
77     alias_server_conf *a =
78 dougm 85976 (alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf));
79 jerenkrantz 95503 alias_server_conf *base = (alias_server_conf *) basev;
80     alias_server_conf *overrides = (alias_server_conf *) overridesv;
81 fielding 83751
82 dougm 88019 a->aliases = apr_array_append(p, overrides->aliases, base->aliases);
83     a->redirects = apr_array_append(p, overrides->redirects, base->redirects);
84 fielding 83751 return a;
85     }
86    
87 dougm 85976 static void *merge_alias_dir_config(apr_pool_t *p, void *basev, void *overridesv)
88 fielding 83751 {
89     alias_dir_conf *a =
90 dougm 85976 (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
91 jerenkrantz 95503 alias_dir_conf *base = (alias_dir_conf *) basev;
92     alias_dir_conf *overrides = (alias_dir_conf *) overridesv;
93 dougm 88019 a->redirects = apr_array_append(p, overrides->redirects, base->redirects);
94 fielding 83751 return a;
95     }
96    
97 nd 98647 /* need prototype for overlap check */
98     static int alias_matches(const char *uri, const char *alias_fakename);
99    
100 ben 85644 static const char *add_alias_internal(cmd_parms *cmd, void *dummy,
101 jerenkrantz 95503 const char *f, const char *r,
102     int use_regex)
103 fielding 83751 {
104     server_rec *s = cmd->server;
105 gstein 88225 alias_server_conf *conf = ap_get_module_config(s->module_config,
106     &alias_module);
107 dougm 88019 alias_entry *new = apr_array_push(conf->aliases);
108 nd 98647 alias_entry *entries = (alias_entry *)conf->aliases->elts;
109     int i;
110 fielding 83751
111     /* XX r can NOT be relative to DocumentRoot here... compat bug. */
112    
113     if (use_regex) {
114 jerenkrantz 95503 new->regexp = ap_pregcomp(cmd->pool, f, REG_EXTENDED);
115     if (new->regexp == NULL)
116     return "Regular expression could not be compiled.";
117 rbb 88010 new->real = r;
118 fielding 83751 }
119 wrowe 90562 else {
120     /* XXX This may be optimized, but we must know that new->real
121     * exists. If so, we can dir merge later, trusing new->real
122     * and just canonicalizing the remainder. Not till I finish
123     * cleaning out the old ap_canonical stuff first.
124     */
125     new->real = r;
126     }
127 fielding 83751 new->fake = f;
128     new->handler = cmd->info;
129    
130 nd 98647 /* check for overlapping (Script)Alias directives
131     * and throw a warning if found one
132     */
133     if (!use_regex) {
134     for (i = 0; i < conf->aliases->nelts - 1; ++i) {
135     alias_entry *p = &entries[i];
136    
137 trawick 98741 if ( (!p->regexp && alias_matches(f, p->fake) > 0)
138     || (p->regexp && !ap_regexec(p->regexp, f, 0, NULL, 0))) {
139 nd 98647 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
140 nd 102949 "The %s directive in %s at line %d will probably "
141     "never match because it overlaps an earlier "
142     "%sAlias%s.",
143     cmd->cmd->name, cmd->directive->filename,
144     cmd->directive->line_num,
145 nd 98657 p->handler ? "Script" : "",
146     p->regexp ? "Match" : "");
147 nd 98647
148     break; /* one warning per alias should be sufficient */
149     }
150     }
151     }
152    
153 fielding 83751 return NULL;
154     }
155    
156 ben 85644 static const char *add_alias(cmd_parms *cmd, void *dummy, const char *f,
157 jerenkrantz 95503 const char *r)
158 fielding 83751 {
159     return add_alias_internal(cmd, dummy, f, r, 0);
160     }
161    
162 ben 85644 static const char *add_alias_regex(cmd_parms *cmd, void *dummy, const char *f,
163 jerenkrantz 95503 const char *r)
164 fielding 83751 {
165     return add_alias_internal(cmd, dummy, f, r, 1);
166     }
167    
168 ben 85644 static const char *add_redirect_internal(cmd_parms *cmd,
169 jerenkrantz 95503 alias_dir_conf *dirconf,
170     const char *arg1, const char *arg2,
171 trawick 85627 const char *arg3, int use_regex)
172 fielding 83751 {
173     alias_entry *new;
174     server_rec *s = cmd->server;
175 gstein 88225 alias_server_conf *serverconf = ap_get_module_config(s->module_config,
176     &alias_module);
177 fielding 83751 int status = (int) (long) cmd->info;
178     regex_t *r = NULL;
179 ben 85644 const char *f = arg2;
180     const char *url = arg3;
181 fielding 83751
182     if (!strcasecmp(arg1, "gone"))
183 jerenkrantz 95503 status = HTTP_GONE;
184 fielding 83751 else if (!strcasecmp(arg1, "permanent"))
185 jerenkrantz 95503 status = HTTP_MOVED_PERMANENTLY;
186 fielding 83751 else if (!strcasecmp(arg1, "temp"))
187 jerenkrantz 95503 status = HTTP_MOVED_TEMPORARILY;
188 fielding 83751 else if (!strcasecmp(arg1, "seeother"))
189 jerenkrantz 95503 status = HTTP_SEE_OTHER;
190 wrowe 86008 else if (apr_isdigit(*arg1))
191 jerenkrantz 95503 status = atoi(arg1);
192 fielding 83751 else {
193 jerenkrantz 95503 f = arg1;
194     url = arg2;
195 fielding 83751 }
196    
197     if (use_regex) {
198 jerenkrantz 95503 r = ap_pregcomp(cmd->pool, f, REG_EXTENDED);
199     if (r == NULL)
200     return "Regular expression could not be compiled.";
201 fielding 83751 }
202    
203     if (ap_is_HTTP_REDIRECT(status)) {
204 jerenkrantz 95503 if (!url)
205     return "URL to redirect to is missing";
206     if (!use_regex && !ap_is_url(url))
207     return "Redirect to non-URL";
208 fielding 83751 }
209     else {
210 jerenkrantz 95503 if (url)
211     return "Redirect URL not valid for this status";
212 fielding 83751 }
213    
214     if (cmd->path)
215 jerenkrantz 95503 new = apr_array_push(dirconf->redirects);
216 fielding 83751 else
217 jerenkrantz 95503 new = apr_array_push(serverconf->redirects);
218 fielding 83751
219     new->fake = f;
220     new->real = url;
221     new->regexp = r;
222     new->redir_status = status;
223     return NULL;
224     }
225    
226 ben 85644 static const char *add_redirect(cmd_parms *cmd, void *dirconf,
227     const char *arg1, const char *arg2,
228 jerenkrantz 95503 const char *arg3)
229 fielding 83751 {
230     return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 0);
231     }
232    
233 ben 85644 static const char *add_redirect2(cmd_parms *cmd, void *dirconf,
234 jerenkrantz 95503 const char *arg1, const char *arg2)
235 fielding 83751 {
236 ben 85644 return add_redirect_internal(cmd, dirconf, arg1, arg2, NULL, 0);
237     }
238    
239     static const char *add_redirect_regex(cmd_parms *cmd, void *dirconf,
240 jerenkrantz 95503 const char *arg1, const char *arg2,
241     const char *arg3)
242 ben 85644 {
243 fielding 83751 return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 1);
244     }
245    
246     static const command_rec alias_cmds[] =
247     {
248 trawick 85627 AP_INIT_TAKE2("Alias", add_alias, NULL, RSRC_CONF,
249     "a fakename and a realname"),
250     AP_INIT_TAKE2("ScriptAlias", add_alias, "cgi-script", RSRC_CONF,
251     "a fakename and a realname"),
252     AP_INIT_TAKE23("Redirect", add_redirect, (void *) HTTP_MOVED_TEMPORARILY,
253     OR_FILEINFO,
254     "an optional status, then document to be redirected and "
255     "destination URL"),
256     AP_INIT_TAKE2("AliasMatch", add_alias_regex, NULL, RSRC_CONF,
257     "a regular expression and a filename"),
258     AP_INIT_TAKE2("ScriptAliasMatch", add_alias_regex, "cgi-script", RSRC_CONF,
259     "a regular expression and a filename"),
260     AP_INIT_TAKE23("RedirectMatch", add_redirect_regex,
261     (void *) HTTP_MOVED_TEMPORARILY, OR_FILEINFO,
262     "an optional status, then a regular expression and "
263     "destination URL"),
264 ben 85644 AP_INIT_TAKE2("RedirectTemp", add_redirect2,
265 jerenkrantz 95503 (void *) HTTP_MOVED_TEMPORARILY, OR_FILEINFO,
266 trawick 85627 "a document to be redirected, then the destination URL"),
267 ben 85644 AP_INIT_TAKE2("RedirectPermanent", add_redirect2,
268 trawick 85627 (void *) HTTP_MOVED_PERMANENTLY, OR_FILEINFO,
269     "a document to be redirected, then the destination URL"),
270 fielding 83751 {NULL}
271     };
272    
273     static int alias_matches(const char *uri, const char *alias_fakename)
274     {
275     const char *aliasp = alias_fakename, *urip = uri;
276    
277 brianp 92138 while (*aliasp) {
278 jerenkrantz 95503 if (*aliasp == '/') {
279     /* any number of '/' in the alias matches any number in
280     * the supplied URI, but there must be at least one...
281     */
282     if (*urip != '/')
283     return 0;
284 fielding 83751
285 brianp 95584 do {
286 jerenkrantz 95503 ++aliasp;
287 brianp 95584 } while (*aliasp == '/');
288     do {
289 jerenkrantz 95503 ++urip;
290 brianp 95584 } while (*urip == '/');
291 jerenkrantz 95503 }
292     else {
293     /* Other characters are compared literally */
294     if (*urip++ != *aliasp++)
295     return 0;
296     }
297 fielding 83751 }
298    
299     /* Check last alias path component matched all the way */
300    
301     if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/')
302 jerenkrantz 95503 return 0;
303 fielding 83751
304     /* Return number of characters from URI which matched (may be
305     * greater than length of alias, since we may have matched
306     * doubled slashes)
307     */
308    
309     return urip - uri;
310     }
311    
312 jerenkrantz 95503 static char *try_alias_list(request_rec *r, apr_array_header_t *aliases,
313     int doesc, int *status)
314 fielding 83751 {
315     alias_entry *entries = (alias_entry *) aliases->elts;
316 striker 101556 regmatch_t regm[AP_MAX_REG_MATCH];
317 fielding 83751 char *found = NULL;
318     int i;
319    
320     for (i = 0; i < aliases->nelts; ++i) {
321 jerenkrantz 95503 alias_entry *p = &entries[i];
322     int l;
323 fielding 83751
324 jerenkrantz 95503 if (p->regexp) {
325 striker 101556 if (!ap_regexec(p->regexp, r->uri, AP_MAX_REG_MATCH, regm, 0)) {
326 jerenkrantz 95503 if (p->real) {
327     found = ap_pregsub(r->pool, p->real, r->uri,
328 striker 101556 AP_MAX_REG_MATCH, regm);
329 jerenkrantz 95503 if (found && doesc) {
330 dougm 90361 apr_uri_t uri;
331     apr_uri_parse(r->pool, found, &uri);
332 jerenkrantz 91672 /* Do not escape the query string or fragment. */
333     found = apr_uri_unparse(r->pool, &uri,
334     APR_URI_UNP_OMITQUERY);
335     found = ap_escape_uri(r->pool, found);
336 rbb 89041 if (uri.query) {
337 jerenkrantz 91672 found = apr_pstrcat(r->pool, found, "?",
338     uri.query, NULL);
339 rbb 89041 }
340 jerenkrantz 91672 if (uri.fragment) {
341     found = apr_pstrcat(r->pool, found, "#",
342     uri.fragment, NULL);
343 rbb 89041 }
344 jerenkrantz 95503 }
345     }
346     else {
347     /* need something non-null */
348     found = apr_pstrdup(r->pool, "");
349     }
350     }
351     }
352     else {
353     l = alias_matches(r->uri, p->fake);
354 fielding 83751
355 jerenkrantz 95503 if (l > 0) {
356     if (doesc) {
357     char *escurl;
358     escurl = ap_os_escape_path(r->pool, r->uri + l, 1);
359 fielding 83751
360 jerenkrantz 95503 found = apr_pstrcat(r->pool, p->real, escurl, NULL);
361     }
362     else
363     found = apr_pstrcat(r->pool, p->real, r->uri + l, NULL);
364     }
365     }
366 fielding 83751
367 jerenkrantz 95503 if (found) {
368     if (p->handler) { /* Set handler, and leave a note for mod_cgi */
369     r->handler = p->handler;
370     apr_table_setn(r->notes, "alias-forced-type", r->handler);
371     }
372 wrowe 90562 /* XXX This is as SLOW as can be, next step, we optimize
373     * and merge to whatever part of the found path was already
374     * canonicalized. After I finish eliminating os canonical.
375 wrowe 93965 * Better fail test for ap_server_root_relative needed here.
376 wrowe 90562 */
377 wrowe 93965 if (!doesc) {
378 wrowe 90562 found = ap_server_root_relative(r->pool, found);
379 wrowe 93965 }
380     if (found) {
381 jerenkrantz 95503 *status = p->redir_status;
382 wrowe 93965 }
383 jerenkrantz 95503 return found;
384     }
385 fielding 83751
386     }
387    
388     return NULL;
389     }
390    
391     static int translate_alias_redir(request_rec *r)
392     {
393 gstein 88225 ap_conf_vector_t *sconf = r->server->module_config;
394     alias_server_conf *serverconf = ap_get_module_config(sconf, &alias_module);
395 fielding 83751 char *ret;
396     int status;
397    
398 jerenkrantz 95503 if (r->uri[0] != '/' && r->uri[0] != '\0') {
399     return DECLINED;
400     }
401 fielding 83751
402     if ((ret = try_alias_list(r, serverconf->redirects, 1, &status)) != NULL) {
403 jerenkrantz 95503 if (ap_is_HTTP_REDIRECT(status)) {
404     /* include QUERY_STRING if any */
405     if (r->args) {
406     ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
407     }
408     apr_table_setn(r->headers_out, "Location", ret);
409     }
410     return status;
411 fielding 83751 }
412    
413     if ((ret = try_alias_list(r, serverconf->aliases, 0, &status)) != NULL) {
414 jerenkrantz 95503 r->filename = ret;
415     return OK;
416 fielding 83751 }
417    
418     return DECLINED;
419     }
420    
421     static int fixup_redir(request_rec *r)
422     {
423     void *dconf = r->per_dir_config;
424     alias_dir_conf *dirconf =
425     (alias_dir_conf *) ap_get_module_config(dconf, &alias_module);
426     char *ret;
427     int status;
428    
429     /* It may have changed since last time, so try again */
430    
431     if ((ret = try_alias_list(r, dirconf->redirects, 1, &status)) != NULL) {
432 coar 93137 if (ap_is_HTTP_REDIRECT(status)) {
433 coar 93143 if (ret[0] == '/') {
434     char *orig_target = ret;
435    
436     ret = ap_construct_url(r->pool, ret, r);
437 trawick 95150 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
438 coar 93143 "incomplete redirection target of '%s' for "
439     "URI '%s' modified to '%s'",
440     orig_target, r->uri, ret);
441     }
442 coar 93137 if (!ap_is_url(ret)) {
443     status = HTTP_INTERNAL_SERVER_ERROR;
444 trawick 95150 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
445 coar 93137 "cannot redirect '%s' to '%s'; "
446 coar 93143 "target is not a valid absoluteURI or abs_path",
447 coar 93137 r->uri, ret);
448     }
449     else {
450 nd 98796 /* append requested query only, if the config didn't
451     * supply its own.
452     */
453     if (r->args && !ap_strchr(ret, '?')) {
454     ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
455     }
456 coar 93137 apr_table_setn(r->headers_out, "Location", ret);
457     }
458     }
459 jerenkrantz 95503 return status;
460 fielding 83751 }
461    
462     return DECLINED;
463     }
464    
465 wrowe 87697 static void register_hooks(apr_pool_t *p)
466 fielding 83770 {
467 slive 96137 static const char * const aszSucc[]={ "mod_userdir.c",
468     "mod_vhost_alias.c",NULL };
469 fielding 83770
470 slive 94985 ap_hook_translate_name(translate_alias_redir,NULL,aszSucc,APR_HOOK_MIDDLE);
471 wrowe 87731 ap_hook_fixups(fixup_redir,NULL,NULL,APR_HOOK_MIDDLE);
472 fielding 83770 }
473    
474 wrowe 86609 module AP_MODULE_DECLARE_DATA alias_module =
475 fielding 83751 {
476 fielding 83770 STANDARD20_MODULE_STUFF,
477 jerenkrantz 95503 create_alias_dir_config, /* dir config creater */
478     merge_alias_dir_config, /* dir merger --- default is to override */
479     create_alias_config, /* server config */
480     merge_alias_config, /* merge server configs */
481     alias_cmds, /* command apr_table_t */
482     register_hooks /* register hooks */
483 fielding 83751 };

Properties

Name Value
cvs2svn:cvs-rev 1.55
svn:eol-style native
svn:keywords Author Date Id Revision

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2