• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/lighttpd-1.4.39/src/
1#include "base.h"
2#include "log.h"
3#include "buffer.h"
4#include "stat_cache.h"
5
6#include "plugin.h"
7
8#include <assert.h>
9#include <ctype.h>
10#include <stdlib.h>
11#include <string.h>
12#include <errno.h>
13
14typedef struct {
15	buffer *server_root;
16	buffer *default_host;
17	buffer *document_root;
18
19	buffer *docroot_cache_key;
20	buffer *docroot_cache_value;
21	buffer *docroot_cache_servername;
22
23	unsigned short debug;
24} plugin_config;
25
26typedef struct {
27	PLUGIN_DATA;
28
29	buffer *doc_root;
30
31	plugin_config **config_storage;
32	plugin_config conf;
33} plugin_data;
34
35INIT_FUNC(mod_simple_vhost_init) {
36	plugin_data *p;
37
38	p = calloc(1, sizeof(*p));
39
40	p->doc_root = buffer_init();
41
42	return p;
43}
44
45FREE_FUNC(mod_simple_vhost_free) {
46	plugin_data *p = p_d;
47
48	UNUSED(srv);
49
50	if (!p) return HANDLER_GO_ON;
51
52	if (p->config_storage) {
53		size_t i;
54		for (i = 0; i < srv->config_context->used; i++) {
55			plugin_config *s = p->config_storage[i];
56
57			buffer_free(s->document_root);
58			buffer_free(s->default_host);
59			buffer_free(s->server_root);
60
61			buffer_free(s->docroot_cache_key);
62			buffer_free(s->docroot_cache_value);
63			buffer_free(s->docroot_cache_servername);
64
65			free(s);
66		}
67
68		free(p->config_storage);
69	}
70
71	buffer_free(p->doc_root);
72
73	free(p);
74
75	return HANDLER_GO_ON;
76}
77
78SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
79	plugin_data *p = p_d;
80	size_t i;
81
82	config_values_t cv[] = {
83		{ "simple-vhost.server-root",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
84		{ "simple-vhost.default-host",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
85		{ "simple-vhost.document-root",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
86		{ "simple-vhost.debug",             NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
87		{ NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
88	};
89
90	if (!p) return HANDLER_ERROR;
91
92	p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
93
94	for (i = 0; i < srv->config_context->used; i++) {
95		data_config const* config = (data_config const*)srv->config_context->data[i];
96		plugin_config *s;
97
98		s = calloc(1, sizeof(plugin_config));
99
100		s->server_root = buffer_init();
101		s->default_host = buffer_init();
102		s->document_root = buffer_init();
103
104		s->docroot_cache_key = buffer_init();
105		s->docroot_cache_value = buffer_init();
106		s->docroot_cache_servername = buffer_init();
107
108		s->debug = 0;
109
110		cv[0].destination = s->server_root;
111		cv[1].destination = s->default_host;
112		cv[2].destination = s->document_root;
113		cv[3].destination = &(s->debug);
114
115
116		p->config_storage[i] = s;
117
118		if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
119			return HANDLER_ERROR;
120		}
121	}
122
123	return HANDLER_GO_ON;
124}
125
126static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
127	stat_cache_entry *sce = NULL;
128	force_assert(!buffer_string_is_empty(p->conf.server_root));
129
130	buffer_string_prepare_copy(out, 127);
131	buffer_copy_buffer(out, p->conf.server_root);
132
133	if (!buffer_string_is_empty(host)) {
134		/* a hostname has to start with a alpha-numerical character
135		 * and must not contain a slash "/"
136		 */
137		char *dp;
138
139		buffer_append_slash(out);
140
141		if (NULL == (dp = strchr(host->ptr, ':'))) {
142			buffer_append_string_buffer(out, host);
143		} else {
144			buffer_append_string_len(out, host->ptr, dp - host->ptr);
145		}
146	}
147	buffer_append_slash(out);
148
149	if (buffer_string_length(p->conf.document_root) > 1 && p->conf.document_root->ptr[0] == '/') {
150		buffer_append_string_len(out, p->conf.document_root->ptr + 1, buffer_string_length(p->conf.document_root) - 1);
151	} else {
152		buffer_append_string_buffer(out, p->conf.document_root);
153		buffer_append_slash(out);
154	}
155
156	if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
157		if (p->conf.debug) {
158			log_error_write(srv, __FILE__, __LINE__, "sb",
159					strerror(errno), out);
160		}
161		return -1;
162	} else if (!S_ISDIR(sce->st.st_mode)) {
163		return -1;
164	}
165
166	return 0;
167}
168
169
170#define PATCH(x) \
171	p->conf.x = s->x;
172static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
173	size_t i, j;
174	plugin_config *s = p->config_storage[0];
175
176	PATCH(server_root);
177	PATCH(default_host);
178	PATCH(document_root);
179
180	PATCH(docroot_cache_key);
181	PATCH(docroot_cache_value);
182	PATCH(docroot_cache_servername);
183
184	PATCH(debug);
185
186	/* skip the first, the global context */
187	for (i = 1; i < srv->config_context->used; i++) {
188		data_config *dc = (data_config *)srv->config_context->data[i];
189		s = p->config_storage[i];
190
191		/* condition didn't match */
192		if (!config_check_cond(srv, con, dc)) continue;
193
194		/* merge config */
195		for (j = 0; j < dc->value->used; j++) {
196			data_unset *du = dc->value->data[j];
197
198			if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
199				PATCH(server_root);
200				PATCH(docroot_cache_key);
201				PATCH(docroot_cache_value);
202				PATCH(docroot_cache_servername);
203			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
204				PATCH(default_host);
205			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
206				PATCH(document_root);
207			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
208				PATCH(debug);
209			}
210		}
211	}
212
213	return 0;
214}
215#undef PATCH
216
217static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
218	plugin_data *p = p_data;
219
220	/*
221	 * cache the last successfull translation from hostname (authority) to docroot
222	 * - this saves us a stat() call
223	 *
224	 */
225
226	mod_simple_vhost_patch_connection(srv, con, p);
227
228	/* build_doc_root() requires a server_root; skip module if simple-vhost.server-root is not set
229	 * or set to an empty string (especially don't cache any results!)
230	 */
231	if (buffer_string_is_empty(p->conf.server_root)) return HANDLER_GO_ON;
232
233	if (!buffer_string_is_empty(p->conf.docroot_cache_key) &&
234	    !buffer_string_is_empty(con->uri.authority) &&
235	    buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
236		/* cache hit */
237		buffer_copy_buffer(con->server_name,       p->conf.docroot_cache_servername);
238		buffer_copy_buffer(con->physical.doc_root, p->conf.docroot_cache_value);
239	} else {
240		/* build document-root */
241		if (buffer_string_is_empty(con->uri.authority) ||
242		    build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
243			/* not found, fallback the default-host */
244			if (0 == build_doc_root(srv, con, p,
245					   p->doc_root,
246					   p->conf.default_host)) {
247				/* default host worked */
248				buffer_copy_buffer(con->server_name, p->conf.default_host);
249				buffer_copy_buffer(con->physical.doc_root, p->doc_root);
250				/* do not cache default host */
251			}
252			return HANDLER_GO_ON;
253		}
254
255		/* found host */
256		buffer_copy_buffer(con->server_name, con->uri.authority);
257		buffer_copy_buffer(con->physical.doc_root, p->doc_root);
258
259		/* copy to cache */
260		buffer_copy_buffer(p->conf.docroot_cache_key,        con->uri.authority);
261		buffer_copy_buffer(p->conf.docroot_cache_value,      p->doc_root);
262		buffer_copy_buffer(p->conf.docroot_cache_servername, con->server_name);
263	}
264
265	return HANDLER_GO_ON;
266}
267
268
269int mod_simple_vhost_plugin_init(plugin *p);
270int mod_simple_vhost_plugin_init(plugin *p) {
271	p->version     = LIGHTTPD_VERSION_ID;
272	p->name        = buffer_init_string("simple_vhost");
273
274	p->init        = mod_simple_vhost_init;
275	p->set_defaults = mod_simple_vhost_set_defaults;
276	p->handle_docroot  = mod_simple_vhost_docroot;
277	p->cleanup     = mod_simple_vhost_free;
278
279	p->data        = NULL;
280
281	return 0;
282}
283