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

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