File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / mod_staticfile.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 "base.h"
    4: #include "log.h"
    5: #include "buffer.h"
    6: 
    7: #include "plugin.h"
    8: 
    9: #include "stat_cache.h"
   10: #include "etag.h"
   11: #include "http_chunk.h"
   12: #include "response.h"
   13: 
   14: #include <ctype.h>
   15: #include <stdlib.h>
   16: #include <stdio.h>
   17: #include <string.h>
   18: 
   19: /**
   20:  * this is a staticfile for a lighttpd plugin
   21:  *
   22:  */
   23: 
   24: 
   25: 
   26: /* plugin config for all request/connections */
   27: 
   28: typedef struct {
   29: 	array *exclude_ext;
   30: 	unsigned short etags_used;
   31: 	unsigned short disable_pathinfo;
   32: } plugin_config;
   33: 
   34: typedef struct {
   35: 	PLUGIN_DATA;
   36: 
   37: 	plugin_config **config_storage;
   38: 
   39: 	plugin_config conf;
   40: } plugin_data;
   41: 
   42: /* init the plugin data */
   43: INIT_FUNC(mod_staticfile_init) {
   44: 	plugin_data *p;
   45: 
   46: 	p = calloc(1, sizeof(*p));
   47: 
   48: 	return p;
   49: }
   50: 
   51: /* detroy the plugin data */
   52: FREE_FUNC(mod_staticfile_free) {
   53: 	plugin_data *p = p_d;
   54: 
   55: 	UNUSED(srv);
   56: 
   57: 	if (!p) return HANDLER_GO_ON;
   58: 
   59: 	if (p->config_storage) {
   60: 		size_t i;
   61: 		for (i = 0; i < srv->config_context->used; i++) {
   62: 			plugin_config *s = p->config_storage[i];
   63: 
   64: 			if (NULL == s) continue;
   65: 
   66: 			array_free(s->exclude_ext);
   67: 
   68: 			free(s);
   69: 		}
   70: 		free(p->config_storage);
   71: 	}
   72: 
   73: 	free(p);
   74: 
   75: 	return HANDLER_GO_ON;
   76: }
   77: 
   78: /* handle plugin config and check values */
   79: 
   80: SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
   81: 	plugin_data *p = p_d;
   82: 	size_t i = 0;
   83: 
   84: 	config_values_t cv[] = {
   85: 		{ "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
   86: 		{ "static-file.etags",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
   87: 		{ "static-file.disable-pathinfo", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
   88: 		{ NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
   89: 	};
   90: 
   91: 	if (!p) return HANDLER_ERROR;
   92: 
   93: 	p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
   94: 
   95: 	for (i = 0; i < srv->config_context->used; i++) {
   96: 		data_config const* config = (data_config const*)srv->config_context->data[i];
   97: 		plugin_config *s;
   98: 
   99: 		s = calloc(1, sizeof(plugin_config));
  100: 		s->exclude_ext    = array_init();
  101: 		s->etags_used     = 1;
  102: 		s->disable_pathinfo = 0;
  103: 
  104: 		cv[0].destination = s->exclude_ext;
  105: 		cv[1].destination = &(s->etags_used);
  106: 		cv[2].destination = &(s->disable_pathinfo);
  107: 
  108: 		p->config_storage[i] = s;
  109: 
  110: 		if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
  111: 			return HANDLER_ERROR;
  112: 		}
  113: 	}
  114: 
  115: 	return HANDLER_GO_ON;
  116: }
  117: 
  118: #define PATCH(x) \
  119: 	p->conf.x = s->x;
  120: static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
  121: 	size_t i, j;
  122: 	plugin_config *s = p->config_storage[0];
  123: 
  124: 	PATCH(exclude_ext);
  125: 	PATCH(etags_used);
  126: 	PATCH(disable_pathinfo);
  127: 
  128: 	/* skip the first, the global context */
  129: 	for (i = 1; i < srv->config_context->used; i++) {
  130: 		data_config *dc = (data_config *)srv->config_context->data[i];
  131: 		s = p->config_storage[i];
  132: 
  133: 		/* condition didn't match */
  134: 		if (!config_check_cond(srv, con, dc)) continue;
  135: 
  136: 		/* merge config */
  137: 		for (j = 0; j < dc->value->used; j++) {
  138: 			data_unset *du = dc->value->data[j];
  139: 
  140: 			if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
  141: 				PATCH(exclude_ext);
  142: 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.etags"))) {
  143: 				PATCH(etags_used);
  144: 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.disable-pathinfo"))) {
  145: 				PATCH(disable_pathinfo);
  146: 			}
  147: 		}
  148: 	}
  149: 
  150: 	return 0;
  151: }
  152: #undef PATCH
  153: 
  154: URIHANDLER_FUNC(mod_staticfile_subrequest) {
  155: 	plugin_data *p = p_d;
  156: 	size_t k;
  157: 	data_string *ds;
  158: 
  159: 	/* someone else has done a decision for us */
  160: 	if (con->http_status != 0) return HANDLER_GO_ON;
  161: 	if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON;
  162: 	if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
  163: 
  164: 	/* someone else has handled this request */
  165: 	if (con->mode != DIRECT) return HANDLER_GO_ON;
  166: 
  167: 	/* we only handle GET, POST and HEAD */
  168: 	switch(con->request.http_method) {
  169: 	case HTTP_METHOD_GET:
  170: 	case HTTP_METHOD_POST:
  171: 	case HTTP_METHOD_HEAD:
  172: 		break;
  173: 	default:
  174: 		return HANDLER_GO_ON;
  175: 	}
  176: 
  177: 	mod_staticfile_patch_connection(srv, con, p);
  178: 
  179: 	if (p->conf.disable_pathinfo && !buffer_string_is_empty(con->request.pathinfo)) {
  180: 		if (con->conf.log_request_handling) {
  181: 			log_error_write(srv, __FILE__, __LINE__,  "s",  "-- NOT handling file as static file, pathinfo forbidden");
  182: 		}
  183: 		return HANDLER_GO_ON;
  184: 	}
  185: 
  186: 	/* ignore certain extensions */
  187: 	for (k = 0; k < p->conf.exclude_ext->used; k++) {
  188: 		ds = (data_string *)p->conf.exclude_ext->data[k];
  189: 
  190: 		if (buffer_is_empty(ds->value)) continue;
  191: 
  192: 		if (buffer_is_equal_right_len(con->physical.path, ds->value, buffer_string_length(ds->value))) {
  193: 			if (con->conf.log_request_handling) {
  194: 				log_error_write(srv, __FILE__, __LINE__,  "s",  "-- NOT handling file as static file, extension forbidden");
  195: 			}
  196: 			return HANDLER_GO_ON;
  197: 		}
  198: 	}
  199: 
  200: 
  201: 	if (con->conf.log_request_handling) {
  202: 		log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling file as static file");
  203: 	}
  204: 
  205: 	if (!p->conf.etags_used) con->etag_flags = 0;
  206: 	http_response_send_file(srv, con, con->physical.path);
  207: 
  208: 	return HANDLER_FINISHED;
  209: }
  210: 
  211: /* this function is called at dlopen() time and inits the callbacks */
  212: 
  213: int mod_staticfile_plugin_init(plugin *p);
  214: int mod_staticfile_plugin_init(plugin *p) {
  215: 	p->version     = LIGHTTPD_VERSION_ID;
  216: 	p->name        = buffer_init_string("staticfile");
  217: 
  218: 	p->init        = mod_staticfile_init;
  219: 	p->handle_subrequest_start = mod_staticfile_subrequest;
  220: 	p->set_defaults  = mod_staticfile_set_defaults;
  221: 	p->cleanup     = mod_staticfile_free;
  222: 
  223: 	p->data        = NULL;
  224: 
  225: 	return 0;
  226: }

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