File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / mod_setenv.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: 
    5: #include "plugin.h"
    6: 
    7: #include "response.h"
    8: 
    9: #include <stdlib.h>
   10: #include <string.h>
   11: 
   12: /* plugin config for all request/connections */
   13: 
   14: typedef struct {
   15: 	int handled; /* make sure that we only apply the headers once */
   16: } handler_ctx;
   17: 
   18: typedef struct {
   19: 	array *request_header;
   20: 	array *response_header;
   21: 
   22: 	array *environment;
   23: } plugin_config;
   24: 
   25: typedef struct {
   26: 	PLUGIN_DATA;
   27: 
   28: 	plugin_config **config_storage;
   29: 
   30: 	plugin_config conf;
   31: } plugin_data;
   32: 
   33: static handler_ctx * handler_ctx_init(void) {
   34: 	handler_ctx * hctx;
   35: 
   36: 	hctx = calloc(1, sizeof(*hctx));
   37: 
   38: 	hctx->handled = 0;
   39: 
   40: 	return hctx;
   41: }
   42: 
   43: static void handler_ctx_free(handler_ctx *hctx) {
   44: 	free(hctx);
   45: }
   46: 
   47: 
   48: /* init the plugin data */
   49: INIT_FUNC(mod_setenv_init) {
   50: 	plugin_data *p;
   51: 
   52: 	p = calloc(1, sizeof(*p));
   53: 
   54: 	return p;
   55: }
   56: 
   57: /* detroy the plugin data */
   58: FREE_FUNC(mod_setenv_free) {
   59: 	plugin_data *p = p_d;
   60: 
   61: 	UNUSED(srv);
   62: 
   63: 	if (!p) return HANDLER_GO_ON;
   64: 
   65: 	if (p->config_storage) {
   66: 		size_t i;
   67: 		for (i = 0; i < srv->config_context->used; i++) {
   68: 			plugin_config *s = p->config_storage[i];
   69: 
   70: 			array_free(s->request_header);
   71: 			array_free(s->response_header);
   72: 			array_free(s->environment);
   73: 
   74: 			free(s);
   75: 		}
   76: 		free(p->config_storage);
   77: 	}
   78: 
   79: 	free(p);
   80: 
   81: 	return HANDLER_GO_ON;
   82: }
   83: 
   84: /* handle plugin config and check values */
   85: 
   86: SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
   87: 	plugin_data *p = p_d;
   88: 	size_t i = 0;
   89: 
   90: 	config_values_t cv[] = {
   91: 		{ "setenv.add-request-header",  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
   92: 		{ "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
   93: 		{ "setenv.add-environment",     NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
   94: 		{ NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
   95: 	};
   96: 
   97: 	if (!p) return HANDLER_ERROR;
   98: 
   99: 	p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
  100: 
  101: 	for (i = 0; i < srv->config_context->used; i++) {
  102: 		plugin_config *s;
  103: 
  104: 		s = calloc(1, sizeof(plugin_config));
  105: 		s->request_header   = array_init();
  106: 		s->response_header  = array_init();
  107: 		s->environment      = array_init();
  108: 
  109: 		cv[0].destination = s->request_header;
  110: 		cv[1].destination = s->response_header;
  111: 		cv[2].destination = s->environment;
  112: 
  113: 		p->config_storage[i] = s;
  114: 
  115: 		if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
  116: 			return HANDLER_ERROR;
  117: 		}
  118: 	}
  119: 
  120: 	return HANDLER_GO_ON;
  121: }
  122: 
  123: #define PATCH(x) \
  124: 	p->conf.x = s->x;
  125: static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
  126: 	size_t i, j;
  127: 	plugin_config *s = p->config_storage[0];
  128: 
  129: 	PATCH(request_header);
  130: 	PATCH(response_header);
  131: 	PATCH(environment);
  132: 
  133: 	/* skip the first, the global context */
  134: 	for (i = 1; i < srv->config_context->used; i++) {
  135: 		data_config *dc = (data_config *)srv->config_context->data[i];
  136: 		s = p->config_storage[i];
  137: 
  138: 		/* condition didn't match */
  139: 		if (!config_check_cond(srv, con, dc)) continue;
  140: 
  141: 		/* merge config */
  142: 		for (j = 0; j < dc->value->used; j++) {
  143: 			data_unset *du = dc->value->data[j];
  144: 
  145: 			if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
  146: 				PATCH(request_header);
  147: 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
  148: 				PATCH(response_header);
  149: 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
  150: 				PATCH(environment);
  151: 			}
  152: 		}
  153: 	}
  154: 
  155: 	return 0;
  156: }
  157: #undef PATCH
  158: 
  159: URIHANDLER_FUNC(mod_setenv_uri_handler) {
  160: 	plugin_data *p = p_d;
  161: 	size_t k;
  162: 	handler_ctx *hctx;
  163: 
  164: 	if (con->plugin_ctx[p->id]) {
  165: 		hctx = con->plugin_ctx[p->id];
  166: 	} else {
  167: 		hctx = handler_ctx_init();
  168: 
  169: 		con->plugin_ctx[p->id] = hctx;
  170: 	}
  171: 
  172: 	if (hctx->handled) {
  173: 		return HANDLER_GO_ON;
  174: 	}
  175: 
  176: 	hctx->handled = 1;
  177: 
  178: 	mod_setenv_patch_connection(srv, con, p);
  179: 
  180: 	for (k = 0; k < p->conf.request_header->used; k++) {
  181: 		data_string *ds = (data_string *)p->conf.request_header->data[k];
  182: 		data_string *ds_dst;
  183: 
  184: 		if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
  185: 			ds_dst = data_string_init();
  186: 		}
  187: 
  188: 		buffer_copy_string_buffer(ds_dst->key, ds->key);
  189: 		buffer_copy_string_buffer(ds_dst->value, ds->value);
  190: 
  191: 		array_insert_unique(con->request.headers, (data_unset *)ds_dst);
  192: 	}
  193: 
  194: 	for (k = 0; k < p->conf.environment->used; k++) {
  195: 		data_string *ds = (data_string *)p->conf.environment->data[k];
  196: 		data_string *ds_dst;
  197: 
  198: 		if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
  199: 			ds_dst = data_string_init();
  200: 		}
  201: 
  202: 		buffer_copy_string_buffer(ds_dst->key, ds->key);
  203: 		buffer_copy_string_buffer(ds_dst->value, ds->value);
  204: 
  205: 		array_insert_unique(con->environment, (data_unset *)ds_dst);
  206: 	}
  207: 
  208: 	for (k = 0; k < p->conf.response_header->used; k++) {
  209: 		data_string *ds = (data_string *)p->conf.response_header->data[k];
  210: 
  211: 		response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
  212: 	}
  213: 
  214: 	/* not found */
  215: 	return HANDLER_GO_ON;
  216: }
  217: 
  218: CONNECTION_FUNC(mod_setenv_reset) {
  219: 	plugin_data *p = p_d;
  220: 
  221: 	UNUSED(srv);
  222: 
  223: 	if (con->plugin_ctx[p->id]) {
  224: 		handler_ctx_free(con->plugin_ctx[p->id]);
  225: 		con->plugin_ctx[p->id] = NULL;
  226: 	}
  227: 
  228: 	return HANDLER_GO_ON;
  229: }
  230: 
  231: /* this function is called at dlopen() time and inits the callbacks */
  232: 
  233: int mod_setenv_plugin_init(plugin *p);
  234: int mod_setenv_plugin_init(plugin *p) {
  235: 	p->version     = LIGHTTPD_VERSION_ID;
  236: 	p->name        = buffer_init_string("setenv");
  237: 
  238: 	p->init        = mod_setenv_init;
  239: 	p->handle_uri_clean  = mod_setenv_uri_handler;
  240: 	p->set_defaults  = mod_setenv_set_defaults;
  241: 	p->cleanup     = mod_setenv_free;
  242: 
  243: 	p->connection_reset  = mod_setenv_reset;
  244: 
  245: 	p->data        = NULL;
  246: 
  247: 	return 0;
  248: }

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