File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / mod_cml.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, 8 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_41p8, HEAD
lighttpd 1.4.41

    1: #include "first.h"
    2: 
    3: #include "buffer.h"
    4: #include "server.h"
    5: #include "log.h"
    6: #include "plugin.h"
    7: #include "response.h"
    8: 
    9: #include "stream.h"
   10: 
   11: #include "mod_cml.h"
   12: 
   13: #include <sys/stat.h>
   14: #include <time.h>
   15: 
   16: #include <stdlib.h>
   17: #include <string.h>
   18: #include <errno.h>
   19: #include <unistd.h>
   20: #include <stdio.h>
   21: 
   22: /* init the plugin data */
   23: INIT_FUNC(mod_cml_init) {
   24: 	plugin_data *p;
   25: 
   26: 	p = calloc(1, sizeof(*p));
   27: 
   28: 	p->basedir         = buffer_init();
   29: 	p->baseurl         = buffer_init();
   30: 	p->trigger_handler = buffer_init();
   31: 
   32: 	return p;
   33: }
   34: 
   35: /* detroy the plugin data */
   36: FREE_FUNC(mod_cml_free) {
   37: 	plugin_data *p = p_d;
   38: 
   39: 	UNUSED(srv);
   40: 
   41: 	if (!p) return HANDLER_GO_ON;
   42: 
   43: 	if (p->config_storage) {
   44: 		size_t i;
   45: 		for (i = 0; i < srv->config_context->used; i++) {
   46: 			plugin_config *s = p->config_storage[i];
   47: 
   48: 			if (NULL == s) continue;
   49: 
   50: 			buffer_free(s->ext);
   51: 
   52: 			buffer_free(s->mc_namespace);
   53: 			buffer_free(s->power_magnet);
   54: 			array_free(s->mc_hosts);
   55: 
   56: #if defined(USE_MEMCACHED)
   57: 			if (s->memc) memcached_free(s->memc);
   58: #endif
   59: 
   60: 			free(s);
   61: 		}
   62: 		free(p->config_storage);
   63: 	}
   64: 
   65: 	buffer_free(p->trigger_handler);
   66: 	buffer_free(p->basedir);
   67: 	buffer_free(p->baseurl);
   68: 
   69: 	free(p);
   70: 
   71: 	return HANDLER_GO_ON;
   72: }
   73: 
   74: /* handle plugin config and check values */
   75: 
   76: SETDEFAULTS_FUNC(mod_cml_set_defaults) {
   77: 	plugin_data *p = p_d;
   78: 	size_t i = 0;
   79: 
   80: 	config_values_t cv[] = {
   81: 		{ "cml.extension",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
   82: 		{ "cml.memcache-hosts",         NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 1 */
   83: 		{ "cml.memcache-namespace",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
   84: 		{ "cml.power-magnet",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
   85: 		{ NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
   86: 	};
   87: 
   88: 	if (!p) return HANDLER_ERROR;
   89: 
   90: 	p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
   91: 
   92: 	for (i = 0; i < srv->config_context->used; i++) {
   93: 		data_config const* config = (data_config const*)srv->config_context->data[i];
   94: 		plugin_config *s;
   95: 
   96: 		s = malloc(sizeof(plugin_config));
   97: 		s->ext    = buffer_init();
   98: 		s->mc_hosts       = array_init();
   99: 		s->mc_namespace   = buffer_init();
  100: 		s->power_magnet   = buffer_init();
  101: #if defined(USE_MEMCACHED)
  102: 		s->memc = NULL;
  103: #endif
  104: 
  105: 		cv[0].destination = s->ext;
  106: 		cv[1].destination = s->mc_hosts;
  107: 		cv[2].destination = s->mc_namespace;
  108: 		cv[3].destination = s->power_magnet;
  109: 
  110: 		p->config_storage[i] = s;
  111: 
  112: 		if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
  113: 			return HANDLER_ERROR;
  114: 		}
  115: 
  116: 		if (s->mc_hosts->used) {
  117: #if defined(USE_MEMCACHED)
  118: 			buffer *option_string = buffer_init();
  119: 			size_t k;
  120: 
  121: 			{
  122: 				data_string *ds = (data_string *)s->mc_hosts->data[0];
  123: 
  124: 				buffer_append_string_len(option_string, CONST_STR_LEN("--SERVER="));
  125: 				buffer_append_string_buffer(option_string, ds->value);
  126: 			}
  127: 
  128: 			for (k = 1; k < s->mc_hosts->used; k++) {
  129: 				data_string *ds = (data_string *)s->mc_hosts->data[k];
  130: 
  131: 				buffer_append_string_len(option_string, CONST_STR_LEN(" --SERVER="));
  132: 				buffer_append_string_buffer(option_string, ds->value);
  133: 			}
  134: 
  135: 			s->memc = memcached(CONST_BUF_LEN(option_string));
  136: 
  137: 			if (NULL == s->memc) {
  138: 				log_error_write(srv, __FILE__, __LINE__, "sb",
  139: 					"configuring memcached failed for option string:",
  140: 					option_string);
  141: 			}
  142: 			buffer_free(option_string);
  143: 
  144: 			if (NULL == s->memc) return HANDLER_ERROR;
  145: #else
  146: 			log_error_write(srv, __FILE__, __LINE__, "s",
  147: 				"memcache support is not compiled in but cml.memcache-hosts is set, aborting");
  148: 			return HANDLER_ERROR;
  149: #endif
  150: 		}
  151: 	}
  152: 
  153: 	return HANDLER_GO_ON;
  154: }
  155: 
  156: #define PATCH(x) \
  157: 	p->conf.x = s->x;
  158: static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
  159: 	size_t i, j;
  160: 	plugin_config *s = p->config_storage[0];
  161: 
  162: 	PATCH(ext);
  163: #if defined(USE_MEMCACHED)
  164: 	PATCH(memc);
  165: #endif
  166: 	PATCH(mc_namespace);
  167: 	PATCH(power_magnet);
  168: 
  169: 	/* skip the first, the global context */
  170: 	for (i = 1; i < srv->config_context->used; i++) {
  171: 		data_config *dc = (data_config *)srv->config_context->data[i];
  172: 		s = p->config_storage[i];
  173: 
  174: 		/* condition didn't match */
  175: 		if (!config_check_cond(srv, con, dc)) continue;
  176: 
  177: 		/* merge config */
  178: 		for (j = 0; j < dc->value->used; j++) {
  179: 			data_unset *du = dc->value->data[j];
  180: 
  181: 			if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
  182: 				PATCH(ext);
  183: 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
  184: #if defined(USE_MEMCACHED)
  185: 				PATCH(memc);
  186: #endif
  187: 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
  188: 				PATCH(mc_namespace);
  189: 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
  190: 				PATCH(power_magnet);
  191: 			}
  192: 		}
  193: 	}
  194: 
  195: 	return 0;
  196: }
  197: #undef PATCH
  198: 
  199: static int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
  200: 	buffer *b;
  201: 	char *c;
  202: 
  203: 	/* cleanup basedir */
  204: 	b = p->baseurl;
  205: 	buffer_copy_buffer(b, con->uri.path);
  206: 	for (c = b->ptr + buffer_string_length(b); c > b->ptr && *c != '/'; c--);
  207: 
  208: 	if (*c == '/') {
  209: 		buffer_string_set_length(b, c - b->ptr + 1);
  210: 	}
  211: 
  212: 	b = p->basedir;
  213: 	buffer_copy_buffer(b, con->physical.path);
  214: 	for (c = b->ptr + buffer_string_length(b); c > b->ptr && *c != '/'; c--);
  215: 
  216: 	if (*c == '/') {
  217: 		buffer_string_set_length(b, c - b->ptr + 1);
  218: 	}
  219: 
  220: 
  221: 	/* prepare variables
  222: 	 *   - cookie-based
  223: 	 *   - get-param-based
  224: 	 */
  225: 	return cache_parse_lua(srv, con, p, cml_file);
  226: }
  227: 
  228: URIHANDLER_FUNC(mod_cml_power_magnet) {
  229: 	plugin_data *p = p_d;
  230: 
  231: 	mod_cml_patch_connection(srv, con, p);
  232: 
  233: 	buffer_reset(p->basedir);
  234: 	buffer_reset(p->baseurl);
  235: 	buffer_reset(p->trigger_handler);
  236: 
  237: 	if (buffer_string_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
  238: 
  239: 	/*
  240: 	 * power-magnet:
  241: 	 * cml.power-magnet = server.docroot + "/rewrite.cml"
  242: 	 *
  243: 	 * is called on EACH request, take the original REQUEST_URI and modifies the
  244: 	 * request header as neccesary.
  245: 	 *
  246: 	 * First use:
  247: 	 * if file_exists("/maintainance.html") {
  248: 	 *   output_include = ( "/maintainance.html" )
  249: 	 *   return CACHE_HIT
  250: 	 * }
  251: 	 *
  252: 	 * as we only want to rewrite HTML like requests we should cover it in a conditional
  253: 	 *
  254: 	 * */
  255: 
  256: 	switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
  257: 	case -1:
  258: 		/* error */
  259: 		if (con->conf.log_request_handling) {
  260: 			log_error_write(srv, __FILE__, __LINE__, "s", "cache-error");
  261: 		}
  262: 		con->http_status = 500;
  263: 		return HANDLER_COMEBACK;
  264: 	case 0:
  265: 		if (con->conf.log_request_handling) {
  266: 			log_error_write(srv, __FILE__, __LINE__, "s", "cache-hit");
  267: 		}
  268: 		/* cache-hit */
  269: 		buffer_reset(con->physical.path);
  270: 		return HANDLER_FINISHED;
  271: 	case 1:
  272: 		/* cache miss */
  273: 		return HANDLER_GO_ON;
  274: 	default:
  275: 		con->http_status = 500;
  276: 		return HANDLER_COMEBACK;
  277: 	}
  278: }
  279: 
  280: URIHANDLER_FUNC(mod_cml_is_handled) {
  281: 	plugin_data *p = p_d;
  282: 
  283: 	if (buffer_string_is_empty(con->physical.path)) return HANDLER_ERROR;
  284: 
  285: 	mod_cml_patch_connection(srv, con, p);
  286: 
  287: 	buffer_reset(p->basedir);
  288: 	buffer_reset(p->baseurl);
  289: 	buffer_reset(p->trigger_handler);
  290: 
  291: 	if (buffer_string_is_empty(p->conf.ext)) return HANDLER_GO_ON;
  292: 
  293: 	if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, buffer_string_length(p->conf.ext))) {
  294: 		return HANDLER_GO_ON;
  295: 	}
  296: 
  297: 	switch(cache_call_lua(srv, con, p, con->physical.path)) {
  298: 	case -1:
  299: 		/* error */
  300: 		if (con->conf.log_request_handling) {
  301: 			log_error_write(srv, __FILE__, __LINE__, "s", "cache-error");
  302: 		}
  303: 		con->http_status = 500;
  304: 		return HANDLER_COMEBACK;
  305: 	case 0:
  306: 		if (con->conf.log_request_handling) {
  307: 			log_error_write(srv, __FILE__, __LINE__, "s", "cache-hit");
  308: 		}
  309: 		/* cache-hit */
  310: 		buffer_reset(con->physical.path);
  311: 		return HANDLER_FINISHED;
  312: 	case 1:
  313: 		if (con->conf.log_request_handling) {
  314: 			log_error_write(srv, __FILE__, __LINE__, "s", "cache-miss");
  315: 		}
  316: 		/* cache miss */
  317: 		return HANDLER_COMEBACK;
  318: 	default:
  319: 		con->http_status = 500;
  320: 		return HANDLER_COMEBACK;
  321: 	}
  322: }
  323: 
  324: int mod_cml_plugin_init(plugin *p);
  325: int mod_cml_plugin_init(plugin *p) {
  326: 	p->version     = LIGHTTPD_VERSION_ID;
  327: 	p->name        = buffer_init_string("cache");
  328: 
  329: 	p->init        = mod_cml_init;
  330: 	p->cleanup     = mod_cml_free;
  331: 	p->set_defaults  = mod_cml_set_defaults;
  332: 
  333: 	p->handle_subrequest_start = mod_cml_is_handled;
  334: 	p->handle_physical         = mod_cml_power_magnet;
  335: 
  336: 	p->data        = NULL;
  337: 
  338: 	return 0;
  339: }

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