• 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 "plugin.h"
2#include "log.h"
3#include "response.h"
4#include "stat_cache.h"
5
6#include <string.h>
7#include <errno.h>
8#include <ctype.h>
9
10typedef struct {
11	/* unparsed pieces */
12	buffer *path_pieces_raw;
13
14	/* pieces for path creation */
15	size_t len;
16	buffer **path_pieces;
17} plugin_config;
18
19typedef struct {
20	PLUGIN_DATA;
21	buffer *tmp_buf;
22
23	plugin_config **config_storage;
24	plugin_config conf;
25} plugin_data;
26
27INIT_FUNC(mod_evhost_init) {
28	plugin_data *p;
29
30	p = calloc(1, sizeof(*p));
31
32	p->tmp_buf = buffer_init();
33
34	return p;
35}
36
37FREE_FUNC(mod_evhost_free) {
38	plugin_data *p = p_d;
39
40	UNUSED(srv);
41
42	if (!p) return HANDLER_GO_ON;
43
44	if (p->config_storage) {
45		size_t i;
46		for (i = 0; i < srv->config_context->used; i++) {
47			plugin_config *s = p->config_storage[i];
48
49			if (NULL == s) continue;
50
51			if(s->path_pieces) {
52				size_t j;
53				for (j = 0; j < s->len; j++) {
54					buffer_free(s->path_pieces[j]);
55				}
56
57				free(s->path_pieces);
58			}
59
60			buffer_free(s->path_pieces_raw);
61
62			free(s);
63		}
64		free(p->config_storage);
65	}
66
67	buffer_free(p->tmp_buf);
68
69	free(p);
70
71	return HANDLER_GO_ON;
72}
73
74static void mod_evhost_parse_pattern(plugin_config *s) {
75	char *ptr = s->path_pieces_raw->ptr,*pos;
76
77	s->path_pieces = NULL;
78
79	for(pos=ptr;*ptr;ptr++) {
80		if(*ptr == '%') {
81			s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
82			s->path_pieces[s->len] = buffer_init();
83			s->path_pieces[s->len+1] = buffer_init();
84
85			buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
86			pos = ptr + 2;
87
88			buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
89
90			s->len += 2;
91		}
92	}
93
94	if(*pos != '\0') {
95		s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
96		s->path_pieces[s->len] = buffer_init();
97
98		buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
99
100		s->len += 1;
101	}
102}
103
104SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
105	plugin_data *p = p_d;
106	size_t i;
107
108	/**
109	 *
110	 * #
111	 * # define a pattern for the host url finding
112	 * # %% => % sign
113	 * # %0 => domain name + tld
114	 * # %1 => tld
115	 * # %2 => domain name without tld
116	 * # %3 => subdomain 1 name
117	 * # %4 => subdomain 2 name
118	 * # %_ => fqdn (without port info)
119	 * #
120	 * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
121	 *
122	 */
123
124	config_values_t cv[] = {
125		{ "evhost.path-pattern",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
126		{ NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
127	};
128
129	if (!p) return HANDLER_ERROR;
130
131	p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
132
133	for (i = 0; i < srv->config_context->used; i++) {
134		data_config const* config = (data_config const*)srv->config_context->data[i];
135		plugin_config *s;
136
137		s = calloc(1, sizeof(plugin_config));
138		s->path_pieces_raw = buffer_init();
139		s->path_pieces     = NULL;
140		s->len             = 0;
141
142		cv[0].destination = s->path_pieces_raw;
143
144		p->config_storage[i] = s;
145
146		if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
147			return HANDLER_ERROR;
148		}
149
150		if (!buffer_string_is_empty(s->path_pieces_raw)) {
151			mod_evhost_parse_pattern(s);
152		}
153	}
154
155	return HANDLER_GO_ON;
156}
157
158/**
159 * assign the different parts of the domain to array-indezes (sub2.sub1.domain.tld)
160 * - %0 - domain.tld
161 * - %1 - tld
162 * - %2 - domain
163 * - %3 - sub1
164 * - ...
165 */
166
167static int mod_evhost_parse_host(connection *con,array *host) {
168	register char *ptr = con->uri.authority->ptr + buffer_string_length(con->uri.authority);
169	char *colon = ptr; /* needed to filter out the colon (if exists) */
170	int first = 1;
171	data_string *ds;
172	int i;
173
174	/* first, find the domain + tld */
175	for(;ptr > con->uri.authority->ptr;ptr--) {
176		if(*ptr == '.') {
177			if(first) first = 0;
178			else      break;
179		} else if(*ptr == ':') {
180			colon = ptr;
181			first = 1;
182		}
183	}
184
185	ds = data_string_init();
186	buffer_copy_string_len(ds->key,CONST_STR_LEN("%0"));
187
188	/* if we stopped at a dot, skip the dot */
189	if (*ptr == '.') ptr++;
190	buffer_copy_string_len(ds->value, ptr, colon-ptr);
191
192	array_insert_unique(host,(data_unset *)ds);
193
194	/* if the : is not the start of the authority, go on parsing the hostname */
195
196	if (colon != con->uri.authority->ptr) {
197		for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
198			if(*ptr == '.') {
199				if (ptr != colon - 1) {
200					/* is something between the dots */
201					ds = data_string_init();
202					buffer_copy_string_len(ds->key,CONST_STR_LEN("%"));
203					buffer_append_int(ds->key, i++);
204					buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
205
206					array_insert_unique(host,(data_unset *)ds);
207				}
208				colon = ptr;
209			}
210		}
211
212		/* if the . is not the first charactor of the hostname */
213		if (colon != ptr) {
214			ds = data_string_init();
215			buffer_copy_string_len(ds->key,CONST_STR_LEN("%"));
216			buffer_append_int(ds->key, i /* ++ */);
217			buffer_copy_string_len(ds->value,ptr,colon-ptr);
218
219			array_insert_unique(host,(data_unset *)ds);
220		}
221	}
222
223	return 0;
224}
225
226#define PATCH(x) \
227	p->conf.x = s->x;
228static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
229	size_t i, j;
230	plugin_config *s = p->config_storage[0];
231
232	PATCH(path_pieces);
233	PATCH(len);
234
235	/* skip the first, the global context */
236	for (i = 1; i < srv->config_context->used; i++) {
237		data_config *dc = (data_config *)srv->config_context->data[i];
238		s = p->config_storage[i];
239
240		/* condition didn't match */
241		if (!config_check_cond(srv, con, dc)) continue;
242
243		/* merge config */
244		for (j = 0; j < dc->value->used; j++) {
245			data_unset *du = dc->value->data[j];
246
247			if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
248				PATCH(path_pieces);
249				PATCH(len);
250			}
251		}
252	}
253
254	return 0;
255}
256#undef PATCH
257
258
259static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
260	plugin_data *p = p_d;
261	size_t i;
262	array *parsed_host;
263	register char *ptr;
264	int not_good = 0;
265	stat_cache_entry *sce = NULL;
266
267	/* not authority set */
268	if (buffer_string_is_empty(con->uri.authority)) return HANDLER_GO_ON;
269
270	mod_evhost_patch_connection(srv, con, p);
271
272	/* missing even default(global) conf */
273	if (0 == p->conf.len) {
274		return HANDLER_GO_ON;
275	}
276
277	parsed_host = array_init();
278
279	mod_evhost_parse_host(con, parsed_host);
280
281	/* build document-root */
282	buffer_reset(p->tmp_buf);
283
284	for (i = 0; i < p->conf.len; i++) {
285		ptr = p->conf.path_pieces[i]->ptr;
286		if (*ptr == '%') {
287			data_string *ds;
288
289			if (*(ptr+1) == '%') {
290				/* %% */
291				buffer_append_string_len(p->tmp_buf,CONST_STR_LEN("%"));
292			} else if (*(ptr+1) == '_' ) {
293				/* %_ == full hostname */
294				char *colon = strchr(con->uri.authority->ptr, ':');
295
296				if(colon == NULL) {
297					buffer_append_string_buffer(p->tmp_buf, con->uri.authority); /* adds fqdn */
298				} else {
299					/* strip the port out of the authority-part of the URI scheme */
300					buffer_append_string_len(p->tmp_buf, con->uri.authority->ptr, colon - con->uri.authority->ptr); /* adds fqdn */
301				}
302			} else if (NULL != (ds = (data_string *)array_get_element(parsed_host,p->conf.path_pieces[i]->ptr))) {
303				buffer_append_string_buffer(p->tmp_buf,ds->value);
304			} else {
305				/* unhandled %-sequence */
306			}
307		} else {
308			buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
309		}
310	}
311
312	buffer_append_slash(p->tmp_buf);
313
314	array_free(parsed_host);
315
316	if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
317		log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
318		not_good = 1;
319	} else if(!S_ISDIR(sce->st.st_mode)) {
320		log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
321		not_good = 1;
322	}
323
324	if (!not_good) {
325		buffer_copy_buffer(con->physical.doc_root, p->tmp_buf);
326	}
327
328	return HANDLER_GO_ON;
329}
330
331int mod_evhost_plugin_init(plugin *p);
332int mod_evhost_plugin_init(plugin *p) {
333	p->version     = LIGHTTPD_VERSION_ID;
334	p->name                    = buffer_init_string("evhost");
335	p->init                    = mod_evhost_init;
336	p->set_defaults            = mod_evhost_set_defaults;
337	p->handle_docroot          = mod_evhost_uri_handler;
338	p->cleanup                 = mod_evhost_free;
339
340	p->data                    = NULL;
341
342	return 0;
343}
344
345/* eof */
346