File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / mod_evhost.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 "plugin.h"
    2: #include "log.h"
    3: #include "response.h"
    4: #include "stat_cache.h"
    5: 
    6: #include <string.h>
    7: #include <errno.h>
    8: #include <ctype.h>
    9: 
   10: typedef struct {
   11: 	/* unparsed pieces */
   12: 	buffer *path_pieces_raw;
   13: 
   14: 	/* pieces for path creation */
   15: 	size_t len;
   16: 	buffer **path_pieces;
   17: } plugin_config;
   18: 
   19: typedef struct {
   20: 	PLUGIN_DATA;
   21: 	buffer *tmp_buf;
   22: 
   23: 	plugin_config **config_storage;
   24: 	plugin_config conf;
   25: } plugin_data;
   26: 
   27: INIT_FUNC(mod_evhost_init) {
   28: 	plugin_data *p;
   29: 
   30: 	p = calloc(1, sizeof(*p));
   31: 
   32: 	p->tmp_buf = buffer_init();
   33: 
   34: 	return p;
   35: }
   36: 
   37: FREE_FUNC(mod_evhost_free) {
   38: 	plugin_data *p = p_d;
   39: 
   40: 	UNUSED(srv);
   41: 
   42: 	if (!p) return HANDLER_GO_ON;
   43: 
   44: 	if (p->config_storage) {
   45: 		size_t i;
   46: 		for (i = 0; i < srv->config_context->used; i++) {
   47: 			plugin_config *s = p->config_storage[i];
   48: 
   49: 			if (!s) continue;
   50: 
   51: 			if(s->path_pieces) {
   52: 				size_t j;
   53: 				for (j = 0; j < s->len; j++) {
   54: 					buffer_free(s->path_pieces[j]);
   55: 				}
   56: 
   57: 				free(s->path_pieces);
   58: 			}
   59: 
   60: 			buffer_free(s->path_pieces_raw);
   61: 
   62: 			free(s);
   63: 		}
   64: 		free(p->config_storage);
   65: 	}
   66: 
   67: 	buffer_free(p->tmp_buf);
   68: 
   69: 	free(p);
   70: 
   71: 	return HANDLER_GO_ON;
   72: }
   73: 
   74: static void mod_evhost_parse_pattern(plugin_config *s) {
   75: 	char *ptr = s->path_pieces_raw->ptr,*pos;
   76: 
   77: 	s->path_pieces = NULL;
   78: 
   79: 	for(pos=ptr;*ptr;ptr++) {
   80: 		if(*ptr == '%') {
   81: 			s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
   82: 			s->path_pieces[s->len] = buffer_init();
   83: 			s->path_pieces[s->len+1] = buffer_init();
   84: 
   85: 			buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
   86: 			pos = ptr + 2;
   87: 
   88: 			buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
   89: 
   90: 			s->len += 2;
   91: 		}
   92: 	}
   93: 
   94: 	if(*pos != '\0') {
   95: 		s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
   96: 		s->path_pieces[s->len] = buffer_init();
   97: 
   98: 		buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
   99: 
  100: 		s->len += 1;
  101: 	}
  102: }
  103: 
  104: SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
  105: 	plugin_data *p = p_d;
  106: 	size_t i;
  107: 
  108: 	/**
  109: 	 *
  110: 	 * #
  111: 	 * # define a pattern for the host url finding
  112: 	 * # %% => % sign
  113: 	 * # %0 => domain name + tld
  114: 	 * # %1 => tld
  115: 	 * # %2 => domain name without tld
  116: 	 * # %3 => subdomain 1 name
  117: 	 * # %4 => subdomain 2 name
  118: 	 * # %_ => fqdn (without port info)
  119: 	 * #
  120: 	 * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
  121: 	 *
  122: 	 */
  123: 
  124: 	config_values_t cv[] = {
  125: 		{ "evhost.path-pattern",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
  126: 		{ NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
  127: 	};
  128: 
  129: 	if (!p) return HANDLER_ERROR;
  130: 
  131: 	p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
  132: 
  133: 	for (i = 0; i < srv->config_context->used; i++) {
  134: 		plugin_config *s;
  135: 
  136: 		s = calloc(1, sizeof(plugin_config));
  137: 		s->path_pieces_raw = buffer_init();
  138: 		s->path_pieces     = NULL;
  139: 		s->len             = 0;
  140: 
  141: 		cv[0].destination = s->path_pieces_raw;
  142: 
  143: 		p->config_storage[i] = s;
  144: 
  145: 		if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value,  cv)) {
  146: 			return HANDLER_ERROR;
  147: 		}
  148: 
  149: 		if (s->path_pieces_raw->used != 0) {
  150: 			mod_evhost_parse_pattern(s);
  151: 		}
  152: 	}
  153: 
  154: 	return HANDLER_GO_ON;
  155: }
  156: 
  157: /**
  158:  * assign the different parts of the domain to array-indezes (sub2.sub1.domain.tld)
  159:  * - %0 - domain.tld
  160:  * - %1 - tld
  161:  * - %2 - domain
  162:  * - %3 - sub1
  163:  * - ...
  164:  */
  165: 
  166: static int mod_evhost_parse_host(connection *con,array *host) {
  167: 	/* con->uri.authority->used is always > 0 if we come here */
  168: 	register char *ptr = con->uri.authority->ptr + con->uri.authority->used - 1;
  169: 	char *colon = ptr; /* needed to filter out the colon (if exists) */
  170: 	int first = 1;
  171: 	data_string *ds;
  172: 	int i;
  173: 
  174: 	/* first, find the domain + tld */
  175: 	for(;ptr > con->uri.authority->ptr;ptr--) {
  176: 		if(*ptr == '.') {
  177: 			if(first) first = 0;
  178: 			else      break;
  179: 		} else if(*ptr == ':') {
  180: 			colon = ptr;
  181: 			first = 1;
  182: 		}
  183: 	}
  184: 
  185: 	ds = data_string_init();
  186: 	buffer_copy_string_len(ds->key,CONST_STR_LEN("%0"));
  187: 
  188: 	/* if we stopped at a dot, skip the dot */
  189: 	if (*ptr == '.') ptr++;
  190: 	buffer_copy_string_len(ds->value, ptr, colon-ptr);
  191: 
  192: 	array_insert_unique(host,(data_unset *)ds);
  193: 
  194: 	/* if the : is not the start of the authority, go on parsing the hostname */
  195: 
  196: 	if (colon != con->uri.authority->ptr) {
  197: 		for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
  198: 			if(*ptr == '.') {
  199: 				if (ptr != colon - 1) {
  200: 					/* is something between the dots */
  201: 					ds = data_string_init();
  202: 					buffer_copy_string_len(ds->key,CONST_STR_LEN("%"));
  203: 					buffer_append_long(ds->key, i++);
  204: 					buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
  205: 
  206: 					array_insert_unique(host,(data_unset *)ds);
  207: 				}
  208: 				colon = ptr;
  209: 			}
  210: 		}
  211: 
  212: 		/* if the . is not the first charactor of the hostname */
  213: 		if (colon != ptr) {
  214: 			ds = data_string_init();
  215: 			buffer_copy_string_len(ds->key,CONST_STR_LEN("%"));
  216: 			buffer_append_long(ds->key, i /* ++ */);
  217: 			buffer_copy_string_len(ds->value,ptr,colon-ptr);
  218: 
  219: 			array_insert_unique(host,(data_unset *)ds);
  220: 		}
  221: 	}
  222: 
  223: 	return 0;
  224: }
  225: 
  226: #define PATCH(x) \
  227: 	p->conf.x = s->x;
  228: static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
  229: 	size_t i, j;
  230: 	plugin_config *s = p->config_storage[0];
  231: 
  232: 	PATCH(path_pieces);
  233: 	PATCH(len);
  234: 
  235: 	/* skip the first, the global context */
  236: 	for (i = 1; i < srv->config_context->used; i++) {
  237: 		data_config *dc = (data_config *)srv->config_context->data[i];
  238: 		s = p->config_storage[i];
  239: 
  240: 		/* condition didn't match */
  241: 		if (!config_check_cond(srv, con, dc)) continue;
  242: 
  243: 		/* merge config */
  244: 		for (j = 0; j < dc->value->used; j++) {
  245: 			data_unset *du = dc->value->data[j];
  246: 
  247: 			if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
  248: 				PATCH(path_pieces);
  249: 				PATCH(len);
  250: 			}
  251: 		}
  252: 	}
  253: 
  254: 	return 0;
  255: }
  256: #undef PATCH
  257: 
  258: 
  259: static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
  260: 	plugin_data *p = p_d;
  261: 	size_t i;
  262: 	array *parsed_host;
  263: 	register char *ptr;
  264: 	int not_good = 0;
  265: 	stat_cache_entry *sce = NULL;
  266: 
  267: 	/* not authority set */
  268: 	if (con->uri.authority->used == 0) return HANDLER_GO_ON;
  269: 
  270: 	mod_evhost_patch_connection(srv, con, p);
  271: 
  272: 	/* missing even default(global) conf */
  273: 	if (0 == p->conf.len) {
  274: 		return HANDLER_GO_ON;
  275: 	}
  276: 
  277: 	parsed_host = array_init();
  278: 
  279: 	mod_evhost_parse_host(con, parsed_host);
  280: 
  281: 	/* build document-root */
  282: 	buffer_reset(p->tmp_buf);
  283: 
  284: 	for (i = 0; i < p->conf.len; i++) {
  285: 		ptr = p->conf.path_pieces[i]->ptr;
  286: 		if (*ptr == '%') {
  287: 			data_string *ds;
  288: 
  289: 			if (*(ptr+1) == '%') {
  290: 				/* %% */
  291: 				buffer_append_string_len(p->tmp_buf,CONST_STR_LEN("%"));
  292: 			} else if (*(ptr+1) == '_' ) {
  293: 				/* %_ == full hostname */
  294: 				char *colon = strchr(con->uri.authority->ptr, ':');
  295: 
  296: 				if(colon == NULL) {
  297: 					buffer_append_string_buffer(p->tmp_buf, con->uri.authority); /* adds fqdn */
  298: 				} else {
  299: 					/* strip the port out of the authority-part of the URI scheme */
  300: 					buffer_append_string_len(p->tmp_buf, con->uri.authority->ptr, colon - con->uri.authority->ptr); /* adds fqdn */
  301: 				}
  302: 			} else if (NULL != (ds = (data_string *)array_get_element(parsed_host,p->conf.path_pieces[i]->ptr))) {
  303: 				if (ds->value->used) {
  304: 					buffer_append_string_buffer(p->tmp_buf,ds->value);
  305: 				}
  306: 			} else {
  307: 				/* unhandled %-sequence */
  308: 			}
  309: 		} else {
  310: 			buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
  311: 		}
  312: 	}
  313: 
  314: 	BUFFER_APPEND_SLASH(p->tmp_buf);
  315: 
  316: 	array_free(parsed_host);
  317: 
  318: 	if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
  319: 		log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
  320: 		not_good = 1;
  321: 	} else if(!S_ISDIR(sce->st.st_mode)) {
  322: 		log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
  323: 		not_good = 1;
  324: 	}
  325: 
  326: 	if (!not_good) {
  327: 		buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
  328: 	}
  329: 
  330: 	return HANDLER_GO_ON;
  331: }
  332: 
  333: int mod_evhost_plugin_init(plugin *p);
  334: int mod_evhost_plugin_init(plugin *p) {
  335: 	p->version     = LIGHTTPD_VERSION_ID;
  336: 	p->name                    = buffer_init_string("evhost");
  337: 	p->init                    = mod_evhost_init;
  338: 	p->set_defaults            = mod_evhost_set_defaults;
  339: 	p->handle_docroot          = mod_evhost_uri_handler;
  340: 	p->cleanup                 = mod_evhost_free;
  341: 
  342: 	p->data                    = NULL;
  343: 
  344: 	return 0;
  345: }
  346: 
  347: /* eof */

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