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
16 typedef struct {
17 array *indexfiles;
18 } plugin_config;
19
20 typedef 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 */
INIT_FUNC(mod_indexfile_init)31 INIT_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 */
FREE_FUNC(mod_indexfile_free)42 FREE_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 (!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
SETDEFAULTS_FUNC(mod_indexfile_set_defaults)72 SETDEFAULTS_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(specific_config *));
85
86 for (i = 0; i < srv->config_context->used; i++) {
87 plugin_config *s;
88
89 s = calloc(1, sizeof(plugin_config));
90 s->indexfiles = array_init();
91
92 cv[0].destination = s->indexfiles;
93 cv[1].destination = s->indexfiles; /* old name for [0] */
94
95 p->config_storage[i] = s;
96
97 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
98 return HANDLER_ERROR;
99 }
100 }
101
102 return HANDLER_GO_ON;
103 }
104
105 #define PATCH(x) \
106 p->conf.x = s->x;
mod_indexfile_patch_connection(server * srv,connection * con,plugin_data * p)107 static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
108 size_t i, j;
109 plugin_config *s = p->config_storage[0];
110
111 PATCH(indexfiles);
112
113 /* skip the first, the global context */
114 for (i = 1; i < srv->config_context->used; i++) {
115 data_config *dc = (data_config *)srv->config_context->data[i];
116 s = p->config_storage[i];
117
118 /* condition didn't match */
119 if (!config_check_cond(srv, con, dc)) continue;
120
121 /* merge config */
122 for (j = 0; j < dc->value->used; j++) {
123 data_unset *du = dc->value->data[j];
124
125 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
126 PATCH(indexfiles);
127 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
128 PATCH(indexfiles);
129 }
130 }
131 }
132
133 return 0;
134 }
135 #undef PATCH
136
URIHANDLER_FUNC(mod_indexfile_subrequest)137 URIHANDLER_FUNC(mod_indexfile_subrequest) {
138 plugin_data *p = p_d;
139 size_t k;
140 stat_cache_entry *sce = NULL;
141
142 if (con->mode != DIRECT) return HANDLER_GO_ON;
143
144 if (con->uri.path->used == 0) return HANDLER_GO_ON;
145 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
146
147 mod_indexfile_patch_connection(srv, con, p);
148
149 if (con->conf.log_request_handling) {
150 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Indexfile");
151 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
152 }
153
154 /* indexfile */
155 for (k = 0; k < p->conf.indexfiles->used; k++) {
156 data_string *ds = (data_string *)p->conf.indexfiles->data[k];
157
158 if (ds->value && ds->value->ptr[0] == '/') {
159 /* if the index-file starts with a prefix as use this file as
160 * index-generator */
161 buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
162 } else {
163 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
164 }
165 buffer_append_string_buffer(p->tmp_buf, ds->value);
166
167 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
168 if (errno == EACCES) {
169 con->http_status = 403;
170 buffer_reset(con->physical.path);
171
172 return HANDLER_FINISHED;
173 }
174
175 if (errno != ENOENT &&
176 errno != ENOTDIR) {
177 /* we have no idea what happend. let's tell the user so. */
178
179 con->http_status = 500;
180
181 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
182 "file not found ... or so: ", strerror(errno),
183 con->uri.path,
184 "->", con->physical.path);
185
186 buffer_reset(con->physical.path);
187
188 return HANDLER_FINISHED;
189 }
190 continue;
191 }
192
193 /* rewrite uri.path to the real path (/ -> /index.php) */
194 buffer_append_string_buffer(con->uri.path, ds->value);
195 buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
196
197 /* fce is already set up a few lines above */
198
199 return HANDLER_GO_ON;
200 }
201
202 /* not found */
203 return HANDLER_GO_ON;
204 }
205
206 /* this function is called at dlopen() time and inits the callbacks */
207
208 int mod_indexfile_plugin_init(plugin *p);
mod_indexfile_plugin_init(plugin * p)209 int mod_indexfile_plugin_init(plugin *p) {
210 p->version = LIGHTTPD_VERSION_ID;
211 p->name = buffer_init_string("indexfile");
212
213 p->init = mod_indexfile_init;
214 p->handle_subrequest_start = mod_indexfile_subrequest;
215 p->set_defaults = mod_indexfile_set_defaults;
216 p->cleanup = mod_indexfile_free;
217
218 p->data = NULL;
219
220 return 0;
221 }
222