6 #include "stat_cache.h"
17 buffer
*document_root
;
19 buffer
*docroot_cache_key
;
20 buffer
*docroot_cache_value
;
21 buffer
*docroot_cache_servername
;
31 plugin_config
**config_storage
;
35 INIT_FUNC(mod_simple_vhost_init
) {
38 p
= calloc(1, sizeof(*p
));
40 p
->doc_root
= buffer_init();
45 FREE_FUNC(mod_simple_vhost_free
) {
50 if (!p
) return HANDLER_GO_ON
;
52 if (p
->config_storage
) {
54 for (i
= 0; i
< srv
->config_context
->used
; i
++) {
55 plugin_config
*s
= p
->config_storage
[i
];
56 if (NULL
== s
) continue;
58 buffer_free(s
->document_root
);
59 buffer_free(s
->default_host
);
60 buffer_free(s
->server_root
);
62 buffer_free(s
->docroot_cache_key
);
63 buffer_free(s
->docroot_cache_value
);
64 buffer_free(s
->docroot_cache_servername
);
69 free(p
->config_storage
);
72 buffer_free(p
->doc_root
);
79 SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults
) {
83 config_values_t cv
[] = {
84 { "simple-vhost.server-root", NULL
, T_CONFIG_STRING
, T_CONFIG_SCOPE_CONNECTION
},
85 { "simple-vhost.default-host", NULL
, T_CONFIG_STRING
, T_CONFIG_SCOPE_CONNECTION
},
86 { "simple-vhost.document-root", NULL
, T_CONFIG_STRING
, T_CONFIG_SCOPE_CONNECTION
},
87 { "simple-vhost.debug", NULL
, T_CONFIG_SHORT
, T_CONFIG_SCOPE_CONNECTION
},
88 { NULL
, NULL
, T_CONFIG_UNSET
, T_CONFIG_SCOPE_UNSET
}
91 if (!p
) return HANDLER_ERROR
;
93 p
->config_storage
= calloc(srv
->config_context
->used
, sizeof(plugin_config
*));
95 for (i
= 0; i
< srv
->config_context
->used
; i
++) {
96 data_config
const* config
= (data_config
const*)srv
->config_context
->data
[i
];
99 s
= calloc(1, sizeof(plugin_config
));
101 s
->server_root
= buffer_init();
102 s
->default_host
= buffer_init();
103 s
->document_root
= buffer_init();
105 s
->docroot_cache_key
= buffer_init();
106 s
->docroot_cache_value
= buffer_init();
107 s
->docroot_cache_servername
= buffer_init();
111 cv
[0].destination
= s
->server_root
;
112 cv
[1].destination
= s
->default_host
;
113 cv
[2].destination
= s
->document_root
;
114 cv
[3].destination
= &(s
->debug
);
117 p
->config_storage
[i
] = s
;
119 if (0 != config_insert_values_global(srv
, config
->value
, cv
, i
== 0 ? T_CONFIG_SCOPE_SERVER
: T_CONFIG_SCOPE_CONNECTION
)) {
120 return HANDLER_ERROR
;
123 if (!buffer_string_is_empty(s
->server_root
))
124 buffer_append_slash(s
->server_root
);
125 if (!buffer_string_is_empty(s
->document_root
))
126 buffer_append_slash(s
->document_root
);
129 return HANDLER_GO_ON
;
132 static void build_doc_root_path(buffer
*out
, buffer
*sroot
, buffer
*host
, buffer
*droot
) {
133 force_assert(!buffer_string_is_empty(sroot
));
134 buffer_copy_buffer(out
, sroot
);
136 if (!buffer_string_is_empty(host
)) {
137 /* a hostname has to start with a alpha-numerical character
138 * and must not contain a slash "/"
141 if (NULL
== (dp
= strchr(host
->ptr
, ':'))) {
142 buffer_append_string_buffer(out
, host
);
144 buffer_append_string_len(out
, host
->ptr
, dp
- host
->ptr
);
148 if (!buffer_string_is_empty(droot
)) {
149 buffer_append_path_len(out
, CONST_BUF_LEN(droot
));
152 buffer_append_slash(out
);
156 static int build_doc_root(server
*srv
, connection
*con
, plugin_data
*p
, buffer
*out
, buffer
*host
) {
157 stat_cache_entry
*sce
= NULL
;
159 build_doc_root_path(out
, p
->conf
.server_root
, host
, p
->conf
.document_root
);
161 if (HANDLER_ERROR
== stat_cache_get_entry(srv
, con
, out
, &sce
)) {
163 log_error_write(srv
, __FILE__
, __LINE__
, "sb",
164 strerror(errno
), out
);
167 } else if (!S_ISDIR(sce
->st
.st_mode
)) {
177 static int mod_simple_vhost_patch_connection(server
*srv
, connection
*con
, plugin_data
*p
) {
179 plugin_config
*s
= p
->config_storage
[0];
183 PATCH(document_root
);
185 PATCH(docroot_cache_key
);
186 PATCH(docroot_cache_value
);
187 PATCH(docroot_cache_servername
);
191 /* skip the first, the global context */
192 for (i
= 1; i
< srv
->config_context
->used
; i
++) {
193 data_config
*dc
= (data_config
*)srv
->config_context
->data
[i
];
194 s
= p
->config_storage
[i
];
196 /* condition didn't match */
197 if (!config_check_cond(srv
, con
, dc
)) continue;
200 for (j
= 0; j
< dc
->value
->used
; j
++) {
201 data_unset
*du
= dc
->value
->data
[j
];
203 if (buffer_is_equal_string(du
->key
, CONST_STR_LEN("simple-vhost.server-root"))) {
205 PATCH(docroot_cache_key
);
206 PATCH(docroot_cache_value
);
207 PATCH(docroot_cache_servername
);
208 } else if (buffer_is_equal_string(du
->key
, CONST_STR_LEN("simple-vhost.default-host"))) {
210 } else if (buffer_is_equal_string(du
->key
, CONST_STR_LEN("simple-vhost.document-root"))) {
211 PATCH(document_root
);
212 } else if (buffer_is_equal_string(du
->key
, CONST_STR_LEN("simple-vhost.debug"))) {
222 static handler_t
mod_simple_vhost_docroot(server
*srv
, connection
*con
, void *p_data
) {
223 plugin_data
*p
= p_data
;
226 * cache the last successfull translation from hostname (authority) to docroot
227 * - this saves us a stat() call
231 mod_simple_vhost_patch_connection(srv
, con
, p
);
233 /* build_doc_root() requires a server_root; skip module if simple-vhost.server-root is not set
234 * or set to an empty string (especially don't cache any results!)
236 if (buffer_string_is_empty(p
->conf
.server_root
)) return HANDLER_GO_ON
;
238 if (!buffer_string_is_empty(p
->conf
.docroot_cache_key
) &&
239 !buffer_string_is_empty(con
->uri
.authority
) &&
240 buffer_is_equal(p
->conf
.docroot_cache_key
, con
->uri
.authority
)) {
242 buffer_copy_buffer(con
->server_name
, p
->conf
.docroot_cache_servername
);
243 buffer_copy_buffer(con
->physical
.doc_root
, p
->conf
.docroot_cache_value
);
245 /* build document-root */
246 if (buffer_string_is_empty(con
->uri
.authority
) ||
247 build_doc_root(srv
, con
, p
, p
->doc_root
, con
->uri
.authority
)) {
248 /* not found, fallback the default-host */
249 if (0 == build_doc_root(srv
, con
, p
,
251 p
->conf
.default_host
)) {
252 /* default host worked */
253 buffer_copy_buffer(con
->server_name
, p
->conf
.default_host
);
254 buffer_copy_buffer(con
->physical
.doc_root
, p
->doc_root
);
255 /* do not cache default host */
257 return HANDLER_GO_ON
;
261 buffer_copy_buffer(con
->server_name
, con
->uri
.authority
);
262 buffer_copy_buffer(con
->physical
.doc_root
, p
->doc_root
);
265 buffer_copy_buffer(p
->conf
.docroot_cache_key
, con
->uri
.authority
);
266 buffer_copy_buffer(p
->conf
.docroot_cache_value
, p
->doc_root
);
267 buffer_copy_buffer(p
->conf
.docroot_cache_servername
, con
->server_name
);
270 return HANDLER_GO_ON
;
274 int mod_simple_vhost_plugin_init(plugin
*p
);
275 int mod_simple_vhost_plugin_init(plugin
*p
) {
276 p
->version
= LIGHTTPD_VERSION_ID
;
277 p
->name
= buffer_init_string("simple_vhost");
279 p
->init
= mod_simple_vhost_init
;
280 p
->set_defaults
= mod_simple_vhost_set_defaults
;
281 p
->handle_docroot
= mod_simple_vhost_docroot
;
282 p
->cleanup
= mod_simple_vhost_free
;