File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / mod_simple_vhost.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:35:00 2016 UTC (7 years, 7 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_41p8, HEAD
lighttpd 1.4.41

    1: #include "first.h"
    2: 
    3: #include "base.h"
    4: #include "log.h"
    5: #include "buffer.h"
    6: #include "stat_cache.h"
    7: 
    8: #include "plugin.h"
    9: 
   10: #include <assert.h>
   11: #include <ctype.h>
   12: #include <stdlib.h>
   13: #include <string.h>
   14: #include <errno.h>
   15: 
   16: typedef struct {
   17: 	buffer *server_root;
   18: 	buffer *default_host;
   19: 	buffer *document_root;
   20: 
   21: 	buffer *docroot_cache_key;
   22: 	buffer *docroot_cache_value;
   23: 	buffer *docroot_cache_servername;
   24: 
   25: 	unsigned short debug;
   26: } plugin_config;
   27: 
   28: typedef struct {
   29: 	PLUGIN_DATA;
   30: 
   31: 	buffer *doc_root;
   32: 
   33: 	plugin_config **config_storage;
   34: 	plugin_config conf;
   35: } plugin_data;
   36: 
   37: INIT_FUNC(mod_simple_vhost_init) {
   38: 	plugin_data *p;
   39: 
   40: 	p = calloc(1, sizeof(*p));
   41: 
   42: 	p->doc_root = buffer_init();
   43: 
   44: 	return p;
   45: }
   46: 
   47: FREE_FUNC(mod_simple_vhost_free) {
   48: 	plugin_data *p = p_d;
   49: 
   50: 	UNUSED(srv);
   51: 
   52: 	if (!p) return HANDLER_GO_ON;
   53: 
   54: 	if (p->config_storage) {
   55: 		size_t i;
   56: 		for (i = 0; i < srv->config_context->used; i++) {
   57: 			plugin_config *s = p->config_storage[i];
   58: 
   59: 			buffer_free(s->document_root);
   60: 			buffer_free(s->default_host);
   61: 			buffer_free(s->server_root);
   62: 
   63: 			buffer_free(s->docroot_cache_key);
   64: 			buffer_free(s->docroot_cache_value);
   65: 			buffer_free(s->docroot_cache_servername);
   66: 
   67: 			free(s);
   68: 		}
   69: 
   70: 		free(p->config_storage);
   71: 	}
   72: 
   73: 	buffer_free(p->doc_root);
   74: 
   75: 	free(p);
   76: 
   77: 	return HANDLER_GO_ON;
   78: }
   79: 
   80: SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
   81: 	plugin_data *p = p_d;
   82: 	size_t i;
   83: 
   84: 	config_values_t cv[] = {
   85: 		{ "simple-vhost.server-root",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
   86: 		{ "simple-vhost.default-host",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
   87: 		{ "simple-vhost.document-root",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
   88: 		{ "simple-vhost.debug",             NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
   89: 		{ NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
   90: 	};
   91: 
   92: 	if (!p) return HANDLER_ERROR;
   93: 
   94: 	p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
   95: 
   96: 	for (i = 0; i < srv->config_context->used; i++) {
   97: 		data_config const* config = (data_config const*)srv->config_context->data[i];
   98: 		plugin_config *s;
   99: 
  100: 		s = calloc(1, sizeof(plugin_config));
  101: 
  102: 		s->server_root = buffer_init();
  103: 		s->default_host = buffer_init();
  104: 		s->document_root = buffer_init();
  105: 
  106: 		s->docroot_cache_key = buffer_init();
  107: 		s->docroot_cache_value = buffer_init();
  108: 		s->docroot_cache_servername = buffer_init();
  109: 
  110: 		s->debug = 0;
  111: 
  112: 		cv[0].destination = s->server_root;
  113: 		cv[1].destination = s->default_host;
  114: 		cv[2].destination = s->document_root;
  115: 		cv[3].destination = &(s->debug);
  116: 
  117: 
  118: 		p->config_storage[i] = s;
  119: 
  120: 		if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
  121: 			return HANDLER_ERROR;
  122: 		}
  123: 	}
  124: 
  125: 	return HANDLER_GO_ON;
  126: }
  127: 
  128: static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
  129: 	stat_cache_entry *sce = NULL;
  130: 	force_assert(!buffer_string_is_empty(p->conf.server_root));
  131: 
  132: 	buffer_string_prepare_copy(out, 127);
  133: 	buffer_copy_buffer(out, p->conf.server_root);
  134: 
  135: 	if (!buffer_string_is_empty(host)) {
  136: 		/* a hostname has to start with a alpha-numerical character
  137: 		 * and must not contain a slash "/"
  138: 		 */
  139: 		char *dp;
  140: 
  141: 		buffer_append_slash(out);
  142: 
  143: 		if (NULL == (dp = strchr(host->ptr, ':'))) {
  144: 			buffer_append_string_buffer(out, host);
  145: 		} else {
  146: 			buffer_append_string_len(out, host->ptr, dp - host->ptr);
  147: 		}
  148: 	}
  149: 	buffer_append_slash(out);
  150: 
  151: 	if (buffer_string_length(p->conf.document_root) > 1 && p->conf.document_root->ptr[0] == '/') {
  152: 		buffer_append_string_len(out, p->conf.document_root->ptr + 1, buffer_string_length(p->conf.document_root) - 1);
  153: 	} else {
  154: 		buffer_append_string_buffer(out, p->conf.document_root);
  155: 		buffer_append_slash(out);
  156: 	}
  157: 
  158: 	if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
  159: 		if (p->conf.debug) {
  160: 			log_error_write(srv, __FILE__, __LINE__, "sb",
  161: 					strerror(errno), out);
  162: 		}
  163: 		return -1;
  164: 	} else if (!S_ISDIR(sce->st.st_mode)) {
  165: 		return -1;
  166: 	}
  167: 
  168: 	return 0;
  169: }
  170: 
  171: 
  172: #define PATCH(x) \
  173: 	p->conf.x = s->x;
  174: static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
  175: 	size_t i, j;
  176: 	plugin_config *s = p->config_storage[0];
  177: 
  178: 	PATCH(server_root);
  179: 	PATCH(default_host);
  180: 	PATCH(document_root);
  181: 
  182: 	PATCH(docroot_cache_key);
  183: 	PATCH(docroot_cache_value);
  184: 	PATCH(docroot_cache_servername);
  185: 
  186: 	PATCH(debug);
  187: 
  188: 	/* skip the first, the global context */
  189: 	for (i = 1; i < srv->config_context->used; i++) {
  190: 		data_config *dc = (data_config *)srv->config_context->data[i];
  191: 		s = p->config_storage[i];
  192: 
  193: 		/* condition didn't match */
  194: 		if (!config_check_cond(srv, con, dc)) continue;
  195: 
  196: 		/* merge config */
  197: 		for (j = 0; j < dc->value->used; j++) {
  198: 			data_unset *du = dc->value->data[j];
  199: 
  200: 			if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
  201: 				PATCH(server_root);
  202: 				PATCH(docroot_cache_key);
  203: 				PATCH(docroot_cache_value);
  204: 				PATCH(docroot_cache_servername);
  205: 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
  206: 				PATCH(default_host);
  207: 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
  208: 				PATCH(document_root);
  209: 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
  210: 				PATCH(debug);
  211: 			}
  212: 		}
  213: 	}
  214: 
  215: 	return 0;
  216: }
  217: #undef PATCH
  218: 
  219: static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
  220: 	plugin_data *p = p_data;
  221: 
  222: 	/*
  223: 	 * cache the last successfull translation from hostname (authority) to docroot
  224: 	 * - this saves us a stat() call
  225: 	 *
  226: 	 */
  227: 
  228: 	mod_simple_vhost_patch_connection(srv, con, p);
  229: 
  230: 	/* build_doc_root() requires a server_root; skip module if simple-vhost.server-root is not set
  231: 	 * or set to an empty string (especially don't cache any results!)
  232: 	 */
  233: 	if (buffer_string_is_empty(p->conf.server_root)) return HANDLER_GO_ON;
  234: 
  235: 	if (!buffer_string_is_empty(p->conf.docroot_cache_key) &&
  236: 	    !buffer_string_is_empty(con->uri.authority) &&
  237: 	    buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
  238: 		/* cache hit */
  239: 		buffer_copy_buffer(con->server_name,       p->conf.docroot_cache_servername);
  240: 		buffer_copy_buffer(con->physical.doc_root, p->conf.docroot_cache_value);
  241: 	} else {
  242: 		/* build document-root */
  243: 		if (buffer_string_is_empty(con->uri.authority) ||
  244: 		    build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
  245: 			/* not found, fallback the default-host */
  246: 			if (0 == build_doc_root(srv, con, p,
  247: 					   p->doc_root,
  248: 					   p->conf.default_host)) {
  249: 				/* default host worked */
  250: 				buffer_copy_buffer(con->server_name, p->conf.default_host);
  251: 				buffer_copy_buffer(con->physical.doc_root, p->doc_root);
  252: 				/* do not cache default host */
  253: 			}
  254: 			return HANDLER_GO_ON;
  255: 		}
  256: 
  257: 		/* found host */
  258: 		buffer_copy_buffer(con->server_name, con->uri.authority);
  259: 		buffer_copy_buffer(con->physical.doc_root, p->doc_root);
  260: 
  261: 		/* copy to cache */
  262: 		buffer_copy_buffer(p->conf.docroot_cache_key,        con->uri.authority);
  263: 		buffer_copy_buffer(p->conf.docroot_cache_value,      p->doc_root);
  264: 		buffer_copy_buffer(p->conf.docroot_cache_servername, con->server_name);
  265: 	}
  266: 
  267: 	return HANDLER_GO_ON;
  268: }
  269: 
  270: 
  271: int mod_simple_vhost_plugin_init(plugin *p);
  272: int mod_simple_vhost_plugin_init(plugin *p) {
  273: 	p->version     = LIGHTTPD_VERSION_ID;
  274: 	p->name        = buffer_init_string("simple_vhost");
  275: 
  276: 	p->init        = mod_simple_vhost_init;
  277: 	p->set_defaults = mod_simple_vhost_set_defaults;
  278: 	p->handle_docroot  = mod_simple_vhost_docroot;
  279: 	p->cleanup     = mod_simple_vhost_free;
  280: 
  281: 	p->data        = NULL;
  282: 
  283: 	return 0;
  284: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>