Annotation of embedaddon/lighttpd/src/mod_simple_vhost.c, revision 1.1.1.1
1.1 misho 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:
14: typedef 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:
26: typedef struct {
27: PLUGIN_DATA;
28:
29: buffer *doc_root;
30:
31: plugin_config **config_storage;
32: plugin_config conf;
33: } plugin_data;
34:
35: INIT_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:
45: FREE_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:
78: SETDEFAULTS_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(specific_config *));
93:
94: for (i = 0; i < srv->config_context->used; i++) {
95: plugin_config *s;
96:
97: s = calloc(1, sizeof(plugin_config));
98:
99: s->server_root = buffer_init();
100: s->default_host = buffer_init();
101: s->document_root = buffer_init();
102:
103: s->docroot_cache_key = buffer_init();
104: s->docroot_cache_value = buffer_init();
105: s->docroot_cache_servername = buffer_init();
106:
107: s->debug = 0;
108:
109: cv[0].destination = s->server_root;
110: cv[1].destination = s->default_host;
111: cv[2].destination = s->document_root;
112: cv[3].destination = &(s->debug);
113:
114:
115: p->config_storage[i] = s;
116:
117: if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
118: return HANDLER_ERROR;
119: }
120: }
121:
122: return HANDLER_GO_ON;
123: }
124:
125: static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
126: stat_cache_entry *sce = NULL;
127: assert(p->conf.server_root->used > 1);
128:
129: buffer_prepare_copy(out, 128);
130: buffer_copy_string_buffer(out, p->conf.server_root);
131:
132: if (host->used) {
133: /* a hostname has to start with a alpha-numerical character
134: * and must not contain a slash "/"
135: */
136: char *dp;
137:
138: BUFFER_APPEND_SLASH(out);
139:
140: if (NULL == (dp = strchr(host->ptr, ':'))) {
141: buffer_append_string_buffer(out, host);
142: } else {
143: buffer_append_string_len(out, host->ptr, dp - host->ptr);
144: }
145: }
146: BUFFER_APPEND_SLASH(out);
147:
148: if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
149: buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
150: } else {
151: buffer_append_string_buffer(out, p->conf.document_root);
152: BUFFER_APPEND_SLASH(out);
153: }
154:
155: if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
156: if (p->conf.debug) {
157: log_error_write(srv, __FILE__, __LINE__, "sb",
158: strerror(errno), out);
159: }
160: return -1;
161: } else if (!S_ISDIR(sce->st.st_mode)) {
162: return -1;
163: }
164:
165: return 0;
166: }
167:
168:
169: #define PATCH(x) \
170: p->conf.x = s->x;
171: static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
172: size_t i, j;
173: plugin_config *s = p->config_storage[0];
174:
175: PATCH(server_root);
176: PATCH(default_host);
177: PATCH(document_root);
178:
179: PATCH(docroot_cache_key);
180: PATCH(docroot_cache_value);
181: PATCH(docroot_cache_servername);
182:
183: PATCH(debug);
184:
185: /* skip the first, the global context */
186: for (i = 1; i < srv->config_context->used; i++) {
187: data_config *dc = (data_config *)srv->config_context->data[i];
188: s = p->config_storage[i];
189:
190: /* condition didn't match */
191: if (!config_check_cond(srv, con, dc)) continue;
192:
193: /* merge config */
194: for (j = 0; j < dc->value->used; j++) {
195: data_unset *du = dc->value->data[j];
196:
197: if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
198: PATCH(server_root);
199: PATCH(docroot_cache_key);
200: PATCH(docroot_cache_value);
201: PATCH(docroot_cache_servername);
202: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
203: PATCH(default_host);
204: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
205: PATCH(document_root);
206: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
207: PATCH(debug);
208: }
209: }
210: }
211:
212: return 0;
213: }
214: #undef PATCH
215:
216: static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
217: plugin_data *p = p_data;
218:
219: /*
220: * cache the last successfull translation from hostname (authority) to docroot
221: * - this saves us a stat() call
222: *
223: */
224:
225: mod_simple_vhost_patch_connection(srv, con, p);
226:
227: /* build_doc_root() requires a server_root; skip module if simple-vhost.server-root is not set
228: * or set to an empty string (especially don't cache any results!)
229: */
230: if (p->conf.server_root->used < 2) return HANDLER_GO_ON;
231:
232: if (p->conf.docroot_cache_key->used &&
233: con->uri.authority->used &&
234: buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
235: /* cache hit */
236: buffer_copy_string_buffer(con->server_name, p->conf.docroot_cache_servername);
237: buffer_copy_string_buffer(con->physical.doc_root, p->conf.docroot_cache_value);
238: } else {
239: /* build document-root */
240: if ((con->uri.authority->used == 0) ||
241: build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
242: /* not found, fallback the default-host */
243: if (0 == build_doc_root(srv, con, p,
244: p->doc_root,
245: p->conf.default_host)) {
246: /* default host worked */
247: buffer_copy_string_buffer(con->server_name, p->conf.default_host);
248: buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
249: /* do not cache default host */
250: }
251: return HANDLER_GO_ON;
252: }
253:
254: /* found host */
255: buffer_copy_string_buffer(con->server_name, con->uri.authority);
256: buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
257:
258: /* copy to cache */
259: buffer_copy_string_buffer(p->conf.docroot_cache_key, con->uri.authority);
260: buffer_copy_string_buffer(p->conf.docroot_cache_value, p->doc_root);
261: buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
262: }
263:
264: return HANDLER_GO_ON;
265: }
266:
267:
268: int mod_simple_vhost_plugin_init(plugin *p);
269: int mod_simple_vhost_plugin_init(plugin *p) {
270: p->version = LIGHTTPD_VERSION_ID;
271: p->name = buffer_init_string("simple_vhost");
272:
273: p->init = mod_simple_vhost_init;
274: p->set_defaults = mod_simple_vhost_set_defaults;
275: p->handle_docroot = mod_simple_vhost_docroot;
276: p->cleanup = mod_simple_vhost_free;
277:
278: p->data = NULL;
279:
280: return 0;
281: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>