Annotation of embedaddon/lighttpd/src/mod_simple_vhost.c, revision 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>