File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / mod_simple_vhost.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:20:06 2014 UTC (10 years ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_35p0, v1_4_35, HEAD
lighttpd 1.4.35

    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(plugin_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: 	force_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>