• 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
5#include "plugin.h"
6
7#include "stat_cache.h"
8
9#include <ctype.h>
10#include <stdlib.h>
11#include <string.h>
12#include <errno.h>
13
14/* plugin config for all request/connections */
15
16typedef struct {
17	array *indexfiles;
18} plugin_config;
19
20typedef struct {
21	PLUGIN_DATA;
22
23	buffer *tmp_buf;
24
25	plugin_config **config_storage;
26
27	plugin_config conf;
28} plugin_data;
29
30/* init the plugin data */
31INIT_FUNC(mod_indexfile_init) {
32	plugin_data *p;
33
34	p = calloc(1, sizeof(*p));
35
36	p->tmp_buf = buffer_init();
37
38	return p;
39}
40
41/* detroy the plugin data */
42FREE_FUNC(mod_indexfile_free) {
43	plugin_data *p = p_d;
44
45	UNUSED(srv);
46
47	if (!p) return HANDLER_GO_ON;
48
49	if (p->config_storage) {
50		size_t i;
51		for (i = 0; i < srv->config_context->used; i++) {
52			plugin_config *s = p->config_storage[i];
53
54			if (NULL == s) continue;
55
56			array_free(s->indexfiles);
57
58			free(s);
59		}
60		free(p->config_storage);
61	}
62
63	buffer_free(p->tmp_buf);
64
65	free(p);
66
67	return HANDLER_GO_ON;
68}
69
70/* handle plugin config and check values */
71
72SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
73	plugin_data *p = p_d;
74	size_t i = 0;
75
76	config_values_t cv[] = {
77		{ "index-file.names",           NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
78		{ "server.indexfiles",          NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
79		{ NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
80	};
81
82	if (!p) return HANDLER_ERROR;
83
84	p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
85
86	for (i = 0; i < srv->config_context->used; i++) {
87		data_config const* config = (data_config const*)srv->config_context->data[i];
88		plugin_config *s;
89
90		s = calloc(1, sizeof(plugin_config));
91		s->indexfiles    = array_init();
92
93		cv[0].destination = s->indexfiles;
94		cv[1].destination = s->indexfiles; /* old name for [0] */
95
96		p->config_storage[i] = s;
97
98		if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
99			return HANDLER_ERROR;
100		}
101	}
102
103	return HANDLER_GO_ON;
104}
105
106#define PATCH(x) \
107	p->conf.x = s->x;
108static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
109	size_t i, j;
110	plugin_config *s = p->config_storage[0];
111
112	PATCH(indexfiles);
113
114	/* skip the first, the global context */
115	for (i = 1; i < srv->config_context->used; i++) {
116		data_config *dc = (data_config *)srv->config_context->data[i];
117		s = p->config_storage[i];
118
119		/* condition didn't match */
120		if (!config_check_cond(srv, con, dc)) continue;
121
122		/* merge config */
123		for (j = 0; j < dc->value->used; j++) {
124			data_unset *du = dc->value->data[j];
125
126			if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
127				PATCH(indexfiles);
128			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
129				PATCH(indexfiles);
130			}
131		}
132	}
133
134	return 0;
135}
136#undef PATCH
137
138URIHANDLER_FUNC(mod_indexfile_subrequest) {
139	plugin_data *p = p_d;
140	size_t k;
141	stat_cache_entry *sce = NULL;
142
143	if (con->mode != DIRECT) return HANDLER_GO_ON;
144
145	if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON;
146	if (con->uri.path->ptr[buffer_string_length(con->uri.path) - 1] != '/') return HANDLER_GO_ON;
147
148	mod_indexfile_patch_connection(srv, con, p);
149
150	if (con->conf.log_request_handling) {
151		log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling the request as Indexfile");
152		log_error_write(srv, __FILE__, __LINE__,  "sb", "URI          :", con->uri.path);
153	}
154
155	/* indexfile */
156	for (k = 0; k < p->conf.indexfiles->used; k++) {
157		data_string *ds = (data_string *)p->conf.indexfiles->data[k];
158
159		if (ds->value && ds->value->ptr[0] == '/') {
160			/* if the index-file starts with a prefix as use this file as
161			 * index-generator */
162			buffer_copy_buffer(p->tmp_buf, con->physical.doc_root);
163		} else {
164			buffer_copy_buffer(p->tmp_buf, con->physical.path);
165		}
166		buffer_append_string_buffer(p->tmp_buf, ds->value);
167
168		if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
169			if (errno == EACCES) {
170				con->http_status = 403;
171				buffer_reset(con->physical.path);
172
173				return HANDLER_FINISHED;
174			}
175
176			if (errno != ENOENT &&
177			    errno != ENOTDIR) {
178				/* we have no idea what happend. let's tell the user so. */
179
180				con->http_status = 500;
181
182				log_error_write(srv, __FILE__, __LINE__, "ssbsb",
183						"file not found ... or so: ", strerror(errno),
184						con->uri.path,
185						"->", con->physical.path);
186
187				buffer_reset(con->physical.path);
188
189				return HANDLER_FINISHED;
190			}
191			continue;
192		}
193
194		/* rewrite uri.path to the real path (/ -> /index.php) */
195		buffer_append_string_buffer(con->uri.path, ds->value);
196		buffer_copy_buffer(con->physical.path, p->tmp_buf);
197
198		/* fce is already set up a few lines above */
199
200		return HANDLER_GO_ON;
201	}
202
203	/* not found */
204	return HANDLER_GO_ON;
205}
206
207/* this function is called at dlopen() time and inits the callbacks */
208
209int mod_indexfile_plugin_init(plugin *p);
210int mod_indexfile_plugin_init(plugin *p) {
211	p->version     = LIGHTTPD_VERSION_ID;
212	p->name        = buffer_init_string("indexfile");
213
214	p->init        = mod_indexfile_init;
215	p->handle_subrequest_start = mod_indexfile_subrequest;
216	p->set_defaults  = mod_indexfile_set_defaults;
217	p->cleanup     = mod_indexfile_free;
218
219	p->data        = NULL;
220
221	return 0;
222}
223