2 * mod_domaintree.c - Apache2
9 * DomainTreeMaxdepth 25
10 * DomainTreeStripWWW On
11 * DomainTreePrefix /sites
12 * DomainTreeSuffix /html
24 * | | +- /organisation
34 #define MODULE "mod_domaintree"
35 #define AUTHOR "mike@php.net"
41 #include "http_config.h"
44 #include "http_core.h"
48 #include "http_protocol.h"
49 #include "http_request.h"
54 #include "apr_strings.h"
56 #define APR_WANT_STRFUNC
60 /* {{{ domaintree_module */
62 module AP_MODULE_DECLARE_DATA domaintree_module
;
65 /* {{{ Macros & Types */
67 #define MOD_DT_CNF domaintree_conf
68 #define MOD_DT_PTR (&domaintree_module)
71 #define EMPTY(str) ((str == NULL) || (*(str) == NUL))
84 struct domaintree_entry
{
86 APR_RING_ENTRY(domaintree_entry
) link
;
88 APR_RING_HEAD(domaintree
, domaintree_entry
);
93 static APR_INLINE
char *domaintree_host(apr_pool_t
*pool
, MOD_DT_CNF
*DT
, const char *name
)
96 ap_log_error(APLOG_MARK
, APLOG_WARNING
, APR_SUCCESS
, DT
->server
, "DomainTree: no host/server name");
100 char *port
, *ptr
, *host
;
102 ptr
= host
= apr_pstrdup(pool
, name
);
103 ap_log_error(APLOG_MARK
, APLOG_DEBUG
, APR_SUCCESS
, DT
->server
, "DomainTree: host name = %s", host
);
105 /* check for :NN port */
106 if ((port
= strchr(ptr
, ':'))) {
112 /* strip leading and trailing dots */
113 while (ptr
[len
- 1] == '.') {
116 while (*ptr
== '.') {
122 /* terminate & lowercase */
128 ap_log_error(APLOG_MARK
, APLOG_DEBUG
, APR_SUCCESS
, DT
->server
, "DomainTree: sane host = %s", host
);
133 static APR_INLINE
const char *domaintree_append(apr_pool_t
*pool
, struct domaintree
*tree
, const char *name
, size_t length
)
135 struct domaintree_entry
*elem
= apr_palloc(pool
, sizeof(struct domaintree_entry
));
137 APR_RING_ELEM_INIT(elem
, link
);
138 APR_RING_INSERT_HEAD(tree
, elem
, domaintree_entry
, link
);
140 return elem
->name
= apr_pstrndup(pool
, name
, length
);
143 static APR_INLINE
struct domaintree
*domaintree_tree(apr_pool_t
*pool
, MOD_DT_CNF
*DT
, char *host
)
146 char *host_ptr
= host
;
147 struct domaintree
*tree
= apr_palloc(pool
, sizeof(struct domaintree
));
149 APR_RING_INIT(tree
, domaintree_entry
, link
);
151 while ((host_ptr
= strchr(host
, '.'))) {
153 /* check max depth */
154 if (++depth
> DT
->maxdepth
) {
155 ap_log_error(APLOG_MARK
, APLOG_ERR
, APR_SUCCESS
, DT
->server
, "DomainTree: maxdepth exceeded = %s", host
);
160 if (host_ptr
- host
) {
163 if (DT
->stripwww
&& (depth
== 1) && (!strncmp(host
, "www.", sizeof("www")))) {
164 ap_log_error(APLOG_MARK
, APLOG_DEBUG
, APR_SUCCESS
, DT
->server
, "DomainTree: stripping www.");
166 ap_log_error(APLOG_MARK
, APLOG_DEBUG
, APR_SUCCESS
, DT
->server
, "DomainTree: host part (%d) = %s",
167 depth
- 1, domaintree_append(pool
, tree
, host
, host_ptr
- host
)
175 /* append last part */
177 ap_log_error(APLOG_MARK
, APLOG_DEBUG
, APR_SUCCESS
, DT
->server
, "DomainTree: host part (%d) = %s",
178 depth
, domaintree_append(pool
, tree
, host
, strlen(host
))
185 static APR_INLINE
char *domaintree_path(apr_pool_t
*pool
, MOD_DT_CNF
*DT
, struct domaintree
*tree
)
187 struct domaintree_entry
*elem
;
188 char *path
= apr_pstrdup(pool
, DT
->prefix
);
189 APR_RING_FOREACH(elem
, tree
, domaintree_entry
, link
) {
190 path
= apr_pstrcat(pool
, path
, "/", elem
->name
, NULL
);
192 return path
= apr_pstrcat(pool
, path
, "/", DT
->suffix
, NULL
);
198 static STATUS
domaintree_hook_post_config(apr_pool_t
*pconf
, apr_pool_t
*plog
, apr_pool_t
*ptemp
, server_rec
*s
)
200 ap_add_version_component(pconf
, MODULE
"/" VERSION
);
204 static STATUS
domaintree_hook_translate_name(request_rec
*r
)
206 MOD_DT_CNF
*DT
= NULL
;
207 struct domaintree
*tree
;
210 DT
= ap_get_module_config(r
->server
->module_config
, MOD_DT_PTR
);
211 if ((!DT
) || (!DT
->enabled
)) {
215 /* get a usable host name */
216 if (!(host
= domaintree_host(r
->pool
, DT
, ap_get_server_name(r
)))) {
220 /* build domain tree */
221 if (!(tree
= domaintree_tree(r
->pool
, DT
, host
))) {
226 if (!(path
= domaintree_path(r
->pool
, DT
, tree
))) {
231 r
->canonical_filename
= "";
232 r
->filename
= apr_pstrcat(r
->pool
, path
, r
->uri
, NULL
);
233 ap_log_error(APLOG_MARK
, APLOG_DEBUG
, APR_SUCCESS
, DT
->server
, "DomainTree: final path = %s", r
->filename
);
238 static void domaintree_hooks(apr_pool_t
*pool
)
240 ap_hook_post_config(domaintree_hook_post_config
, NULL
, NULL
, APR_HOOK_MIDDLE
);
241 ap_hook_translate_name(domaintree_hook_translate_name
, NULL
, NULL
, APR_HOOK_MIDDLE
);
245 /* {{{ Configuration */
247 static void *domaintree_create_srv(apr_pool_t
*p
, server_rec
*s
)
251 DT
= (MOD_DT_CNF
*) apr_palloc(p
, sizeof(MOD_DT_CNF
));
258 DT
->prefix
= "/var/www";
259 DT
->suffix
= "public_html";
264 static const char *domaintree_enable(cmd_parms
*cmd
, void *conf
, int flag
)
268 DT
= ap_get_module_config(cmd
->server
->module_config
, MOD_DT_PTR
);
274 static const char *domaintree_stripwww(cmd_parms
*cmd
, void *conf
, int flag
)
278 DT
= ap_get_module_config(cmd
->server
->module_config
, MOD_DT_PTR
);
284 static const char *domaintree_prefix(cmd_parms
*cmd
, void *conf
, const char *prefix
)
288 DT
= ap_get_module_config(cmd
->server
->module_config
, MOD_DT_PTR
);
289 DT
->prefix
= EMPTY(prefix
) ? "/" : apr_pstrdup(cmd
->pool
, prefix
);
294 static const char *domaintree_suffix(cmd_parms
*cmd
, void *conf
, const char *suffix
)
298 DT
= ap_get_module_config(cmd
->server
->module_config
, MOD_DT_PTR
);
299 DT
->suffix
= EMPTY(suffix
) ? "/" : apr_pstrdup(cmd
->pool
, suffix
);
304 static const char *domaintree_maxdepth(cmd_parms
*cmd
, void *conf
, const char *max_depth
)
308 if ((depth
= atoi(max_depth
))) {
311 DT
= ap_get_module_config(cmd
->server
->module_config
, MOD_DT_PTR
);
312 DT
->maxdepth
= (size_t) depth
;
314 return "Maximum DomainTree depth cannot be negative.";
324 static command_rec domaintree_commands
[] = {
326 "DomainTreeEnabled", domaintree_enable
, NULL
, RSRC_CONF
,
327 "Turn the module on or off."
331 "DomainTreeStripWWW", domaintree_stripwww
, NULL
, RSRC_CONF
,
332 "Strip leading www from host. (default On)"
336 "DomainTreePrefix", domaintree_prefix
, NULL
, RSRC_CONF
,
337 "DomainTree path prefix. (default /var/www)"
341 "DomainTreeSuffix", domaintree_suffix
, NULL
, RSRC_CONF
,
342 "DomainTree path suffix. (default public_html)"
346 "DomainTreeMaxdepth", domaintree_maxdepth
, NULL
, RSRC_CONF
,
347 "DomainTree max path depth. (default 20)"
354 /* {{{ Module Administrativa */
356 module AP_MODULE_DECLARE_DATA domaintree_module
= {
357 STANDARD20_MODULE_STUFF
,
358 NULL
, /* create per-dir */
359 NULL
, /* merge per-dir */
360 domaintree_create_srv
, /* create per-server */
361 NULL
, /* merge per-server */
362 domaintree_commands
, /* apr_table_t commands */
363 domaintree_hooks
/* register hooks */
373 * vim600: noet sw=4 ts=4 fdm=marker
374 * vim<600: noet sw=4 ts=4