Apache HTTPD
mod_vhost_alias.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * mod_vhost_alias.c: support for dynamically configured mass virtual hosting
19 *
20 * Copyright (c) 1998-1999 Demon Internet Ltd.
21 *
22 * This software was submitted by Demon Internet to the Apache Software Foundation
23 * in May 1999. Future revisions and derivatives of this source code
24 * must acknowledge Demon Internet as the original contributor of
25 * this module. All other licensing and usage conditions are those
26 * of the Apache Software Foundation.
27 *
28 * Originally written by Tony Finch <[email protected]> <[email protected]>.
29 *
30 * Implementation ideas were taken from mod_alias.c. The overall
31 * concept is derived from the OVERRIDE_DOC_ROOT/OVERRIDE_CGIDIR
32 * patch to Apache 1.3b3 and a similar feature in Demon's thttpd,
33 * both written by James Grinter <[email protected]>.
34 */
35
36#include "apr.h"
37#include "apr_strings.h"
38#include "ap_hooks.h"
39#include "apr_lib.h"
40
41#define APR_WANT_STRFUNC
42#include "apr_want.h"
43
44#include "httpd.h"
45#include "http_config.h"
46#include "http_core.h"
47#include "http_request.h" /* for ap_hook_translate_name */
48
49
50module AP_MODULE_DECLARE_DATA vhost_alias_module;
51
52
53/*
54 * basic configuration things
55 * we abbreviate "mod_vhost_alias" to "mva" for shorter names
56 */
57
61
62/*
63 * Per-server module config record.
64 */
71
73{
74 mva_sconf_t *conf;
75
76 conf = (mva_sconf_t *) apr_pcalloc(p, sizeof(mva_sconf_t));
77 conf->doc_root = NULL;
78 conf->cgi_root = NULL;
81 return conf;
82}
83
85{
87 mva_sconf_t *child = (mva_sconf_t *) childv;
88 mva_sconf_t *conf;
89
90 conf = (mva_sconf_t *) apr_pcalloc(p, sizeof(*conf));
91 if (child->doc_root_mode == VHOST_ALIAS_UNSET) {
92 conf->doc_root_mode = parent->doc_root_mode;
93 conf->doc_root = parent->doc_root;
94 }
95 else {
96 conf->doc_root_mode = child->doc_root_mode;
97 conf->doc_root = child->doc_root;
98 }
99 if (child->cgi_root_mode == VHOST_ALIAS_UNSET) {
100 conf->cgi_root_mode = parent->cgi_root_mode;
101 conf->cgi_root = parent->cgi_root;
102 }
103 else {
104 conf->cgi_root_mode = child->cgi_root_mode;
105 conf->cgi_root = child->cgi_root;
106 }
107 return conf;
108}
109
110
111/*
112 * These are just here to tell us what vhost_alias_set should do.
113 * We don't put anything into them; we just use the cell addresses.
114 */
119
120static const char *vhost_alias_set(cmd_parms *cmd, void *dummy, const char *map)
121{
122 mva_sconf_t *conf;
124 const char **pmap;
125 const char *p;
126
127 conf = (mva_sconf_t *) ap_get_module_config(cmd->server->module_config,
128 &vhost_alias_module);
129 /* there ought to be a better way of doing this */
130 if (&vhost_alias_set_doc_root_ip == cmd->info) {
132 pmap = &conf->doc_root;
133 pmode = &conf->doc_root_mode;
134 }
135 else if (&vhost_alias_set_cgi_root_ip == cmd->info) {
137 pmap = &conf->cgi_root;
138 pmode = &conf->cgi_root_mode;
139 }
140 else if (&vhost_alias_set_doc_root_name == cmd->info) {
142 pmap = &conf->doc_root;
143 pmode = &conf->doc_root_mode;
144 }
145 else if (&vhost_alias_set_cgi_root_name == cmd->info) {
147 pmap = &conf->cgi_root;
148 pmode = &conf->cgi_root_mode;
149 }
150 else {
151 return "INTERNAL ERROR: unknown command info";
152 }
153
154 if (!ap_os_is_path_absolute(cmd->pool, map)) {
155 if (ap_cstr_casecmp(map, "none")) {
156 return "format string must be an absolute path, or 'none'";
157 }
158 *pmap = NULL;
160 return NULL;
161 }
162
163 /* sanity check */
164 p = map;
165 while (*p != '\0') {
166 if (*p++ != '%') {
167 continue;
168 }
169 /* we just found a '%' */
170 if (*p == 'p' || *p == '%') {
171 ++p;
172 continue;
173 }
174 /* optional dash */
175 if (*p == '-') {
176 ++p;
177 }
178 /* digit N */
179 if (apr_isdigit(*p)) {
180 ++p;
181 }
182 else {
183 return "syntax error in format string";
184 }
185 /* optional plus */
186 if (*p == '+') {
187 ++p;
188 }
189 /* do we end here? */
190 if (*p != '.') {
191 continue;
192 }
193 ++p;
194 /* optional dash */
195 if (*p == '-') {
196 ++p;
197 }
198 /* digit M */
199 if (apr_isdigit(*p)) {
200 ++p;
201 }
202 else {
203 return "syntax error in format string";
204 }
205 /* optional plus */
206 if (*p == '+') {
207 ++p;
208 }
209 }
210 *pmap = map;
211 *pmode = mode;
212 return NULL;
213}
214
215static const command_rec mva_commands[] =
216{
217 AP_INIT_TAKE1("VirtualScriptAlias", vhost_alias_set,
219 "how to create a ScriptAlias based on the host"),
220 AP_INIT_TAKE1("VirtualDocumentRoot", vhost_alias_set,
222 "how to create the DocumentRoot based on the host"),
223 AP_INIT_TAKE1("VirtualScriptAliasIP", vhost_alias_set,
225 "how to create a ScriptAlias based on the host"),
226 AP_INIT_TAKE1("VirtualDocumentRootIP", vhost_alias_set,
228 "how to create the DocumentRoot based on the host"),
229 { NULL }
230};
231
232
233/*
234 * This really wants to be a nested function
235 * but C is too feeble to support them.
236 */
238 char **pdest, int size)
239{
240 /* XXX: what if size > HUGE_STRING_LEN? */
241 if (*pdest + size > buf + HUGE_STRING_LEN) {
242 **pdest = '\0';
243 if (r->filename) {
245 }
246 else {
248 }
249 *pdest = buf;
250 }
251}
252
253static void vhost_alias_interpolate(request_rec *r, const char *name,
254 const char *map, const char *uri)
255{
256 /* 0..9 9..0 */
257 enum { MAXDOTS = 19 };
258 const char *dots[MAXDOTS+1];
259 int ndots;
260
261 char buf[HUGE_STRING_LEN];
262 char *dest;
263 const char *docroot;
264
265 int N, M, Np, Mp, Nd, Md;
266 const char *start, *end;
267
268 const char *p;
269
270 ndots = 0;
271 dots[ndots++] = name-1; /* slightly naughty */
272 for (p = name; *p; ++p) {
273 if (*p == '.' && ndots < MAXDOTS) {
274 dots[ndots++] = p;
275 }
276 }
277 dots[ndots] = p;
278
279 r->filename = NULL;
280
281 dest = buf;
282 while (*map) {
283 if (*map != '%') {
284 /* normal characters */
286 *dest++ = *map++;
287 continue;
288 }
289 /* we are in a format specifier */
290 ++map;
291 /* %% -> % */
292 if (*map == '%') {
293 ++map;
295 *dest++ = '%';
296 continue;
297 }
298 /* port number */
299 if (*map == 'p') {
300 ++map;
301 /* no. of decimal digits in a short plus one */
304 continue;
305 }
306 /* deal with %-N+.-M+ -- syntax is already checked */
307 M = 0; /* value */
308 Np = Mp = 0; /* is there a plus? */
309 Nd = Md = 0; /* is there a dash? */
310 if (*map == '-') ++map, Nd = 1;
311 N = *map++ - '0';
312 if (*map == '+') ++map, Np = 1;
313 if (*map == '.') {
314 ++map;
315 if (*map == '-') {
316 ++map, Md = 1;
317 }
318 M = *map++ - '0';
319 if (*map == '+') {
320 ++map, Mp = 1;
321 }
322 }
323 /* note that N and M are one-based indices, not zero-based */
324 start = dots[0]+1; /* ptr to the first character */
325 end = dots[ndots]; /* ptr to the character after the last one */
326 if (N != 0) {
327 if (N > ndots) {
328 start = "_";
329 end = start+1;
330 }
331 else if (!Nd) {
332 start = dots[N-1]+1;
333 if (!Np) {
334 end = dots[N];
335 }
336 }
337 else {
338 if (!Np) {
339 start = dots[ndots-N]+1;
340 }
341 end = dots[ndots-N+1];
342 }
343 }
344 if (M != 0) {
345 if (M > end - start) {
346 start = "_";
347 end = start+1;
348 }
349 else if (!Md) {
350 start = start+M-1;
351 if (!Mp) {
352 end = start+1;
353 }
354 }
355 else {
356 if (!Mp) {
357 start = end-M;
358 }
359 end = end-M+1;
360 }
361 }
363 for (p = start; p < end; ++p) {
364 *dest++ = apr_tolower(*p);
365 }
366 }
367 /* no double slashes */
368 if (dest - buf > 0 && dest[-1] == '/') {
369 --dest;
370 }
371 *dest = '\0';
372
373 if (r->filename)
375 else
380}
381
383{
384 mva_sconf_t *conf;
385 const char *name, *map, *uri;
387 const char *cgi;
388
390 &vhost_alias_module);
391 cgi = NULL;
392 if (conf->cgi_root) {
393 cgi = strstr(r->uri, "cgi-bin/");
394 if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) {
395 cgi = NULL;
396 }
397 }
398 if (cgi) {
399 mode = conf->cgi_root_mode;
400 map = conf->cgi_root;
401 uri = cgi + strlen("cgi-bin");
402 }
403 else if (r->uri[0] == '/') {
404 mode = conf->doc_root_mode;
405 map = conf->doc_root;
406 uri = r->uri;
407 }
408 else {
409 return DECLINED;
410 }
411
412 if (mode == VHOST_ALIAS_NAME) {
414 }
415 else if (mode == VHOST_ALIAS_IP) {
417 }
418 else {
419 return DECLINED;
420 }
421
422 /* ### There is an optimization available here to determine the
423 * absolute portion of the path from the server config phase,
424 * through the first % segment, and note that portion of the path
425 * canonical_path buffer.
426 */
427 r->canonical_filename = "";
429
430 if (cgi) {
431 /* see is_scriptaliased() in mod_cgi */
432 r->handler = "cgi-script";
433 apr_table_setn(r->notes, "alias-forced-type", r->handler);
434 ap_set_context_info(r, "/cgi-bin", NULL);
435 }
436
437 return OK;
438}
439
441{
442 static const char * const aszPre[]={ "mod_alias.c","mod_userdir.c",NULL };
443
445}
446
448{
450 NULL, /* dir config creater */
451 NULL, /* dir merger --- default is to override */
452 mva_create_server_config, /* server config */
453 mva_merge_server_config, /* merge server configs */
454 mva_commands, /* command apr_table_t */
455 register_hooks /* register hooks */
456};
457
ap hook functions and macros
char * strstr(char *s1, char *s2)
APR general purpose library routines.
APR Strings library.
APR Standard Headers Support.
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
#define AP_DECLARE_MODULE(foo)
request_rec * r
#define HUGE_STRING_LEN
Definition httpd.h:303
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
apr_port_t ap_get_server_port(const request_rec *r)
Definition core.c:1199
const char * ap_get_server_name(request_rec *r)
Definition core.c:1145
const unsigned char * buf
Definition util_md5.h:50
void ap_hook_translate_name(ap_HOOK_translate_name_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition request.c:81
void * dummy
Definition http_vhost.h:62
apr_file_t apr_off_t start
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
const char *const * aszPre
Definition apr_hooks.h:345
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
const char * uri
Definition apr_uri.h:159
#define RSRC_CONF
#define STANDARD20_MODULE_STUFF
void ap_set_document_root(request_rec *r, const char *document_root)
Definition core.c:857
int ap_cstr_casecmp(const char *s1, const char *s2)
Definition util.c:3542
void ap_set_context_info(request_rec *r, const char *prefix, const char *document_root)
Definition core.c:863
int ap_os_is_path_absolute(apr_pool_t *p, const char *dir)
Definition util.c:229
apr_size_t size
#define apr_isdigit(c)
Definition apr_lib.h:209
#define apr_tolower(c)
Definition apr_lib.h:231
apr_pool_t * parent
Definition apr_pools.h:197
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char char ** end
const char * s
Definition apr_strings.h:95
apr_cmdtype_e cmd
Apache Configuration.
CORE HTTP Daemon.
Apache Request library.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
static int mva_translate(request_rec *r)
static void vhost_alias_interpolate(request_rec *r, const char *name, const char *map, const char *uri)
static const char * vhost_alias_set(cmd_parms *cmd, void *dummy, const char *map)
static int vhost_alias_set_cgi_root_name
static int vhost_alias_set_doc_root_ip
static void * mva_merge_server_config(apr_pool_t *p, void *parentv, void *childv)
static void register_hooks(apr_pool_t *p)
static int vhost_alias_set_cgi_root_ip
static const command_rec mva_commands[]
static int vhost_alias_set_doc_root_name
mva_mode_e
@ VHOST_ALIAS_NONE
@ VHOST_ALIAS_UNSET
@ VHOST_ALIAS_NAME
@ VHOST_ALIAS_IP
static void * mva_create_server_config(apr_pool_t *p, server_rec *s)
static APR_INLINE void vhost_alias_checkspace(request_rec *r, char *buf, char **pdest, int size)
char * name
char * local_ip
Definition httpd.h:1181
mva_mode_e doc_root_mode
mva_mode_e cgi_root_mode
const char * cgi_root
const char * doc_root
A structure that represents the current request.
Definition httpd.h:845
char * uri
Definition httpd.h:1016
const char * handler
Definition httpd.h:994
apr_table_t * notes
Definition httpd.h:985
apr_pool_t * pool
Definition httpd.h:847
char * filename
Definition httpd.h:1018
conn_rec * connection
Definition httpd.h:849
char * canonical_filename
Definition httpd.h:1022
server_rec * server
Definition httpd.h:851
A structure to store information for each virtual server.
Definition httpd.h:1322
struct ap_conf_vector_t * module_config
Definition httpd.h:1341