Home | History | Annotate | Line # | Download | only in httpd
      1  1.15     alnsn /*	$NetBSD: lua-bozo.c,v 1.15 2017/05/28 22:37:36 alnsn Exp $	*/
      2   1.1   mbalmer 
      3   1.1   mbalmer /*
      4   1.1   mbalmer  * Copyright (c) 2013 Marc Balmer <marc (at) msys.ch>
      5   1.1   mbalmer  * All rights reserved.
      6   1.1   mbalmer  *
      7   1.1   mbalmer  * Redistribution and use in source and binary forms, with or without
      8   1.1   mbalmer  * modification, are permitted provided that the following conditions
      9   1.1   mbalmer  * are met:
     10   1.1   mbalmer  * 1. Redistributions of source code must retain the above copyright
     11   1.1   mbalmer  *    notice, this list of conditions and the following disclaimer.
     12   1.1   mbalmer  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1   mbalmer  *    notice, this list of conditions and the following disclaimer and
     14   1.1   mbalmer  *    dedication in the documentation and/or other materials provided
     15   1.1   mbalmer  *    with the distribution.
     16   1.1   mbalmer  *
     17   1.1   mbalmer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18   1.1   mbalmer  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19   1.1   mbalmer  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20   1.1   mbalmer  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21   1.1   mbalmer  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     22   1.1   mbalmer  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23   1.1   mbalmer  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     24   1.1   mbalmer  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     25   1.1   mbalmer  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26   1.1   mbalmer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27   1.1   mbalmer  * SUCH DAMAGE.
     28   1.1   mbalmer  *
     29   1.1   mbalmer  */
     30   1.1   mbalmer 
     31   1.1   mbalmer /* this code implements dynamic content generation using Lua for bozohttpd */
     32   1.1   mbalmer 
     33   1.1   mbalmer #ifndef NO_LUA_SUPPORT
     34   1.1   mbalmer 
     35   1.9       mrg #include <sys/param.h>
     36   1.9       mrg 
     37   1.1   mbalmer #include <lua.h>
     38   1.1   mbalmer #include <lauxlib.h>
     39   1.1   mbalmer #include <lualib.h>
     40   1.1   mbalmer #include <stdlib.h>
     41   1.1   mbalmer #include <string.h>
     42   1.1   mbalmer #include <unistd.h>
     43   1.1   mbalmer 
     44   1.1   mbalmer #include "bozohttpd.h"
     45   1.1   mbalmer 
     46   1.1   mbalmer /* Lua binding for bozohttp */
     47   1.1   mbalmer 
     48   1.1   mbalmer #if LUA_VERSION_NUM < 502
     49   1.1   mbalmer #define LUA_HTTPDLIBNAME "httpd"
     50   1.1   mbalmer #endif
     51   1.1   mbalmer 
     52   1.1   mbalmer #define FORM	"application/x-www-form-urlencoded"
     53   1.1   mbalmer 
     54  1.15     alnsn static bozohttpd_t *
     55  1.15     alnsn httpd_instance(lua_State *L)
     56   1.1   mbalmer {
     57   1.1   mbalmer 	bozohttpd_t *httpd;
     58   1.1   mbalmer 
     59   1.1   mbalmer 	lua_pushstring(L, "bozohttpd");
     60   1.1   mbalmer 	lua_gettable(L, LUA_REGISTRYINDEX);
     61   1.1   mbalmer 	httpd = lua_touserdata(L, -1);
     62   1.1   mbalmer 	lua_pop(L, 1);
     63   1.1   mbalmer 
     64  1.15     alnsn 	return httpd;
     65  1.15     alnsn }
     66  1.15     alnsn 
     67  1.15     alnsn static int
     68  1.15     alnsn lua_flush(lua_State *L)
     69  1.15     alnsn {
     70  1.15     alnsn 	bozohttpd_t *httpd = httpd_instance(L);
     71  1.15     alnsn 
     72   1.1   mbalmer 	bozo_flush(httpd, stdout);
     73   1.1   mbalmer 	return 0;
     74   1.1   mbalmer }
     75   1.1   mbalmer 
     76   1.1   mbalmer static int
     77   1.1   mbalmer lua_print(lua_State *L)
     78   1.1   mbalmer {
     79  1.15     alnsn 	bozohttpd_t *httpd = httpd_instance(L);
     80   1.1   mbalmer 
     81  1.15     alnsn 	bozo_printf(httpd, "%s\r\n", lua_tostring(L, 1));
     82   1.1   mbalmer 	return 0;
     83   1.1   mbalmer }
     84   1.1   mbalmer 
     85   1.1   mbalmer static int
     86   1.1   mbalmer lua_read(lua_State *L)
     87   1.1   mbalmer {
     88  1.15     alnsn 	bozohttpd_t *httpd = httpd_instance(L);
     89  1.15     alnsn 	luaL_Buffer lbuf;
     90   1.1   mbalmer 	char *data;
     91  1.15     alnsn 	lua_Integer len;
     92  1.15     alnsn 	ssize_t n;
     93   1.1   mbalmer 
     94  1.15     alnsn 	len = luaL_checkinteger(L, 1);
     95  1.15     alnsn 	data = luaL_buffinitsize(L, &lbuf, (size_t)len);
     96   1.1   mbalmer 
     97  1.15     alnsn 	if ((n = bozo_read(httpd, STDIN_FILENO, data, len)) >= 0) {
     98  1.15     alnsn 		luaL_pushresultsize(&lbuf, n);
     99  1.15     alnsn 		return 1;
    100  1.15     alnsn 	} else {
    101   1.4   mbalmer 		lua_pushnil(L);
    102  1.15     alnsn 		lua_pushstring(L, "bozo_read() call failed");
    103  1.15     alnsn 		return 2;
    104  1.15     alnsn 	}
    105   1.1   mbalmer }
    106   1.1   mbalmer 
    107   1.1   mbalmer static int
    108   1.1   mbalmer lua_register_handler(lua_State *L)
    109   1.1   mbalmer {
    110  1.15     alnsn 	bozohttpd_t *httpd = httpd_instance(L);
    111   1.1   mbalmer 	lua_state_map_t *map;
    112   1.1   mbalmer 	lua_handler_t *handler;
    113  1.15     alnsn 	const char *name;
    114  1.15     alnsn 	int ref;
    115   1.1   mbalmer 
    116   1.1   mbalmer 	lua_pushstring(L, "lua_state_map");
    117   1.1   mbalmer 	lua_gettable(L, LUA_REGISTRYINDEX);
    118   1.1   mbalmer 	map = lua_touserdata(L, -1);
    119  1.15     alnsn 	lua_pop(L, 1);
    120  1.15     alnsn 
    121  1.15     alnsn 	name = luaL_checkstring(L, 1);
    122   1.1   mbalmer 
    123   1.1   mbalmer 	luaL_checktype(L, 2, LUA_TFUNCTION);
    124  1.15     alnsn 	lua_pushvalue(L, 2);
    125  1.15     alnsn 	ref = luaL_ref(L, LUA_REGISTRYINDEX);
    126   1.1   mbalmer 
    127   1.1   mbalmer 	handler = bozomalloc(httpd, sizeof(lua_handler_t));
    128  1.15     alnsn 	handler->name = bozostrdup(httpd, NULL, name);
    129  1.15     alnsn 	handler->ref = ref;
    130   1.1   mbalmer 	SIMPLEQ_INSERT_TAIL(&map->handlers, handler, h_next);
    131   1.1   mbalmer 	httpd->process_lua = 1;
    132   1.1   mbalmer 	return 0;
    133   1.1   mbalmer }
    134   1.1   mbalmer 
    135   1.1   mbalmer static int
    136   1.1   mbalmer lua_write(lua_State *L)
    137   1.1   mbalmer {
    138  1.15     alnsn 	bozohttpd_t *httpd = httpd_instance(L);
    139   1.1   mbalmer 	const char *data;
    140  1.15     alnsn 	size_t len;
    141  1.15     alnsn 	ssize_t n;
    142   1.1   mbalmer 
    143  1.15     alnsn 	data = luaL_checklstring(L, 1, &len);
    144  1.15     alnsn 	if ((n = bozo_write(httpd, STDIN_FILENO, data, len)) >= 0) {
    145  1.15     alnsn 		lua_pushinteger(L, n);
    146  1.15     alnsn 		return 1;
    147  1.15     alnsn 	} else {
    148  1.15     alnsn 		lua_pushnil(L);
    149  1.15     alnsn 		lua_pushstring(L, "bozo_write() call failed");
    150  1.15     alnsn 		return 2;
    151  1.15     alnsn 	}
    152   1.1   mbalmer }
    153   1.1   mbalmer 
    154   1.1   mbalmer static int
    155   1.1   mbalmer luaopen_httpd(lua_State *L)
    156   1.1   mbalmer {
    157  1.15     alnsn 	static struct luaL_Reg functions[] = {
    158   1.1   mbalmer 		{ "flush",		lua_flush },
    159   1.1   mbalmer 		{ "print",		lua_print },
    160   1.1   mbalmer 		{ "read",		lua_read },
    161   1.1   mbalmer 		{ "register_handler",	lua_register_handler },
    162   1.1   mbalmer 		{ "write",		lua_write },
    163   1.1   mbalmer 		{ NULL, NULL }
    164   1.1   mbalmer 	};
    165   1.1   mbalmer #if LUA_VERSION_NUM >= 502
    166   1.1   mbalmer 	luaL_newlib(L, functions);
    167   1.1   mbalmer #else
    168   1.1   mbalmer 	luaL_register(L, LUA_HTTPDLIBNAME, functions);
    169   1.1   mbalmer #endif
    170   1.1   mbalmer 	lua_pushstring(L, "httpd 1.0.0");
    171   1.1   mbalmer 	lua_setfield(L, -2, "_VERSION");
    172   1.1   mbalmer 	return 1;
    173   1.1   mbalmer }
    174   1.1   mbalmer 
    175   1.1   mbalmer #if LUA_VERSION_NUM < 502
    176   1.1   mbalmer static void
    177   1.1   mbalmer lua_openlib(lua_State *L, const char *name, lua_CFunction fn)
    178   1.1   mbalmer {
    179   1.1   mbalmer 	lua_pushcfunction(L, fn);
    180   1.1   mbalmer 	lua_pushstring(L, name);
    181   1.1   mbalmer 	lua_call(L, 1, 0);
    182   1.1   mbalmer }
    183   1.1   mbalmer #endif
    184   1.1   mbalmer 
    185   1.1   mbalmer /* bozohttpd integration */
    186   1.1   mbalmer void
    187   1.1   mbalmer bozo_add_lua_map(bozohttpd_t *httpd, const char *prefix, const char *script)
    188   1.1   mbalmer {
    189   1.1   mbalmer 	lua_state_map_t *map;
    190   1.1   mbalmer 
    191   1.1   mbalmer 	map = bozomalloc(httpd, sizeof(lua_state_map_t));
    192  1.13       mrg 	map->prefix = bozostrdup(httpd, NULL, prefix);
    193   1.1   mbalmer 	if (*script == '/')
    194  1.13       mrg 		map->script = bozostrdup(httpd, NULL, script);
    195   1.1   mbalmer 	else {
    196   1.9       mrg 		char cwd[MAXPATHLEN], *path;
    197   1.9       mrg 
    198   1.9       mrg 		getcwd(cwd, sizeof(cwd) - 1);
    199  1.14       mrg 		bozoasprintf(httpd, &path, "%s/%s", cwd, script);
    200   1.1   mbalmer 		map->script = path;
    201   1.1   mbalmer 	}
    202   1.1   mbalmer 	map->L = luaL_newstate();
    203   1.1   mbalmer 	if (map->L == NULL)
    204  1.14       mrg 		bozoerr(httpd, 1, "can't create Lua state");
    205   1.1   mbalmer 	SIMPLEQ_INIT(&map->handlers);
    206   1.1   mbalmer 
    207   1.1   mbalmer #if LUA_VERSION_NUM >= 502
    208   1.1   mbalmer 	luaL_openlibs(map->L);
    209  1.10     lneto 	lua_getglobal(map->L, "package");
    210  1.10     lneto 	lua_getfield(map->L, -1, "preload");
    211  1.10     lneto 	lua_pushcfunction(map->L, luaopen_httpd);
    212  1.10     lneto 	lua_setfield(map->L, -2, "httpd");
    213  1.10     lneto 	lua_pop(map->L, 2);
    214   1.1   mbalmer #else
    215   1.1   mbalmer 	lua_openlib(map->L, "", luaopen_base);
    216   1.1   mbalmer 	lua_openlib(map->L, LUA_LOADLIBNAME, luaopen_package);
    217   1.1   mbalmer 	lua_openlib(map->L, LUA_TABLIBNAME, luaopen_table);
    218   1.1   mbalmer 	lua_openlib(map->L, LUA_STRLIBNAME, luaopen_string);
    219   1.1   mbalmer 	lua_openlib(map->L, LUA_MATHLIBNAME, luaopen_math);
    220   1.1   mbalmer 	lua_openlib(map->L, LUA_OSLIBNAME, luaopen_os);
    221   1.1   mbalmer 	lua_openlib(map->L, LUA_IOLIBNAME, luaopen_io);
    222   1.1   mbalmer 	lua_openlib(map->L, LUA_HTTPDLIBNAME, luaopen_httpd);
    223   1.1   mbalmer #endif
    224   1.1   mbalmer 	lua_pushstring(map->L, "lua_state_map");
    225   1.1   mbalmer 	lua_pushlightuserdata(map->L, map);
    226   1.1   mbalmer 	lua_settable(map->L, LUA_REGISTRYINDEX);
    227   1.1   mbalmer 
    228   1.1   mbalmer 	lua_pushstring(map->L, "bozohttpd");
    229   1.1   mbalmer 	lua_pushlightuserdata(map->L, httpd);
    230   1.1   mbalmer 	lua_settable(map->L, LUA_REGISTRYINDEX);
    231   1.1   mbalmer 
    232   1.1   mbalmer 	if (luaL_loadfile(map->L, script))
    233  1.14       mrg 		bozoerr(httpd, 1, "failed to load script %s: %s", script,
    234   1.1   mbalmer 		    lua_tostring(map->L, -1));
    235   1.1   mbalmer 	if (lua_pcall(map->L, 0, 0, 0))
    236  1.14       mrg 		bozoerr(httpd, 1, "failed to execute script %s: %s", script,
    237   1.1   mbalmer 		    lua_tostring(map->L, -1));
    238   1.1   mbalmer 	SIMPLEQ_INSERT_TAIL(&httpd->lua_states, map, s_next);
    239   1.1   mbalmer }
    240   1.1   mbalmer 
    241   1.1   mbalmer static void
    242   1.1   mbalmer lua_env(lua_State *L, const char *name, const char *value)
    243   1.1   mbalmer {
    244   1.1   mbalmer 	lua_pushstring(L, value);
    245   1.1   mbalmer 	lua_setfield(L, -2, name);
    246   1.1   mbalmer }
    247   1.1   mbalmer 
    248   1.1   mbalmer /* decode query string */
    249   1.1   mbalmer static void
    250   1.1   mbalmer lua_url_decode(lua_State *L, char *s)
    251   1.1   mbalmer {
    252   1.1   mbalmer 	char *v, *p, *val, *q;
    253   1.1   mbalmer 	char buf[3];
    254   1.1   mbalmer 	int c;
    255   1.1   mbalmer 
    256   1.1   mbalmer 	v = strchr(s, '=');
    257   1.1   mbalmer 	if (v == NULL)
    258   1.1   mbalmer 		return;
    259   1.1   mbalmer 	*v++ = '\0';
    260   1.1   mbalmer 	val = malloc(strlen(v) + 1);
    261   1.1   mbalmer 	if (val == NULL)
    262   1.1   mbalmer 		return;
    263   1.1   mbalmer 
    264   1.1   mbalmer 	for (p = v, q = val; *p; p++) {
    265   1.1   mbalmer 		switch (*p) {
    266   1.1   mbalmer 		case '%':
    267   1.3   mbalmer 			if (*(p + 1) == '\0' || *(p + 2) == '\0') {
    268   1.3   mbalmer 				free(val);
    269   1.1   mbalmer 				return;
    270   1.3   mbalmer 			}
    271   1.1   mbalmer 			buf[0] = *++p;
    272   1.1   mbalmer 			buf[1] = *++p;
    273   1.1   mbalmer 			buf[2] = '\0';
    274   1.1   mbalmer 			sscanf(buf, "%2x", &c);
    275   1.1   mbalmer 			*q++ = (char)c;
    276   1.1   mbalmer 			break;
    277   1.1   mbalmer 		case '+':
    278   1.1   mbalmer 			*q++ = ' ';
    279   1.1   mbalmer 			break;
    280   1.1   mbalmer 		default:
    281   1.1   mbalmer 			*q++ = *p;
    282   1.1   mbalmer 		}
    283   1.1   mbalmer 	}
    284  1.11   mbalmer 	*q = '\0';
    285   1.1   mbalmer 	lua_pushstring(L, val);
    286   1.1   mbalmer 	lua_setfield(L, -2, s);
    287   1.1   mbalmer 	free(val);
    288   1.1   mbalmer }
    289   1.1   mbalmer 
    290   1.1   mbalmer static void
    291   1.1   mbalmer lua_decode_query(lua_State *L, char *query)
    292   1.1   mbalmer {
    293   1.1   mbalmer 	char *s;
    294   1.1   mbalmer 
    295   1.1   mbalmer 	s = strtok(query, "&");
    296   1.1   mbalmer 	while (s) {
    297   1.1   mbalmer 		lua_url_decode(L, s);
    298   1.1   mbalmer 		s = strtok(NULL, "&");
    299   1.1   mbalmer 	}
    300   1.1   mbalmer }
    301   1.1   mbalmer 
    302   1.1   mbalmer int
    303   1.1   mbalmer bozo_process_lua(bozo_httpreq_t *request)
    304   1.1   mbalmer {
    305   1.1   mbalmer 	bozohttpd_t *httpd = request->hr_httpd;
    306   1.1   mbalmer 	lua_state_map_t *map;
    307   1.1   mbalmer 	lua_handler_t *hndlr;
    308   1.4   mbalmer 	int n, ret, length;
    309   1.1   mbalmer 	char date[40];
    310   1.1   mbalmer 	bozoheaders_t *headp;
    311   1.1   mbalmer 	char *s, *query, *uri, *file, *command, *info, *content;
    312   1.1   mbalmer 	const char *type, *clen;
    313   1.1   mbalmer 	char *prefix, *handler, *p;
    314   1.7  christos 	int rv = 0;
    315   1.1   mbalmer 
    316   1.1   mbalmer 	if (!httpd->process_lua)
    317   1.1   mbalmer 		return 0;
    318   1.1   mbalmer 
    319  1.12  christos 	info = NULL;
    320  1.12  christos 	query = NULL;
    321  1.12  christos 	prefix = NULL;
    322   1.1   mbalmer 	uri = request->hr_oldfile ? request->hr_oldfile : request->hr_file;
    323   1.1   mbalmer 
    324   1.1   mbalmer 	if (*uri == '/') {
    325  1.13       mrg 		file = bozostrdup(httpd, request, uri);
    326  1.12  christos 		if (file == NULL)
    327  1.12  christos 			goto out;
    328  1.13       mrg 		prefix = bozostrdup(httpd, request, &uri[1]);
    329   1.1   mbalmer 	} else {
    330  1.12  christos 		if (asprintf(&file, "/%s", uri) < 0)
    331  1.12  christos 			goto out;
    332  1.13       mrg 		prefix = bozostrdup(httpd, request, uri);
    333   1.1   mbalmer 	}
    334  1.12  christos 	if (prefix == NULL)
    335  1.12  christos 		goto out;
    336   1.1   mbalmer 
    337  1.12  christos 	if (request->hr_query && request->hr_query[0])
    338  1.13       mrg 		query = bozostrdup(httpd, request, request->hr_query);
    339   1.1   mbalmer 
    340   1.1   mbalmer 	p = strchr(prefix, '/');
    341  1.12  christos 	if (p == NULL)
    342  1.12  christos 		goto out;
    343   1.1   mbalmer 	*p++ = '\0';
    344   1.1   mbalmer 	handler = p;
    345  1.12  christos 	if (!*handler)
    346  1.12  christos 		goto out;
    347   1.1   mbalmer 	p = strchr(handler, '/');
    348   1.1   mbalmer 	if (p != NULL)
    349   1.1   mbalmer 		*p++ = '\0';
    350   1.1   mbalmer 
    351   1.1   mbalmer 	command = file + 1;
    352   1.1   mbalmer 	if ((s = strchr(command, '/')) != NULL) {
    353  1.13       mrg 		info = bozostrdup(httpd, request, s);
    354   1.1   mbalmer 		*s = '\0';
    355   1.1   mbalmer 	}
    356   1.1   mbalmer 
    357   1.1   mbalmer 	type = request->hr_content_type;
    358   1.1   mbalmer 	clen = request->hr_content_length;
    359   1.1   mbalmer 
    360   1.1   mbalmer 	SIMPLEQ_FOREACH(map, &httpd->lua_states, s_next) {
    361   1.1   mbalmer 		if (strcmp(map->prefix, prefix))
    362   1.1   mbalmer 			continue;
    363   1.1   mbalmer 
    364   1.1   mbalmer 		SIMPLEQ_FOREACH(hndlr, &map->handlers, h_next) {
    365   1.1   mbalmer 			if (strcmp(hndlr->name, handler))
    366   1.1   mbalmer 				continue;
    367   1.1   mbalmer 
    368   1.1   mbalmer 			lua_rawgeti(map->L, LUA_REGISTRYINDEX, hndlr->ref);
    369   1.1   mbalmer 
    370   1.1   mbalmer 			/* Create the "environment" */
    371   1.1   mbalmer 			lua_newtable(map->L);
    372   1.1   mbalmer 			lua_env(map->L, "SERVER_NAME",
    373   1.1   mbalmer 			    BOZOHOST(httpd, request));
    374   1.1   mbalmer 			lua_env(map->L, "GATEWAY_INTERFACE", "Luigi/1.0");
    375   1.1   mbalmer 			lua_env(map->L, "SERVER_PROTOCOL", request->hr_proto);
    376   1.1   mbalmer 			lua_env(map->L, "REQUEST_METHOD",
    377   1.1   mbalmer 			    request->hr_methodstr);
    378   1.1   mbalmer 			lua_env(map->L, "SCRIPT_PREFIX", map->prefix);
    379   1.1   mbalmer 			lua_env(map->L, "SCRIPT_NAME", file);
    380   1.1   mbalmer 			lua_env(map->L, "HANDLER_NAME", hndlr->name);
    381   1.1   mbalmer 			lua_env(map->L, "SCRIPT_FILENAME", map->script);
    382   1.1   mbalmer 			lua_env(map->L, "SERVER_SOFTWARE",
    383   1.1   mbalmer 			    httpd->server_software);
    384   1.1   mbalmer 			lua_env(map->L, "REQUEST_URI", uri);
    385   1.1   mbalmer 			lua_env(map->L, "DATE_GMT",
    386   1.1   mbalmer 			    bozo_http_date(date, sizeof(date)));
    387   1.1   mbalmer 			if (query && *query)
    388   1.1   mbalmer 				lua_env(map->L, "QUERY_STRING", query);
    389   1.1   mbalmer 			if (info && *info)
    390   1.1   mbalmer 				lua_env(map->L, "PATH_INFO", info);
    391   1.1   mbalmer 			if (type && *type)
    392   1.1   mbalmer 				lua_env(map->L, "CONTENT_TYPE", type);
    393   1.1   mbalmer 			if (clen && *clen)
    394   1.1   mbalmer 				lua_env(map->L, "CONTENT_LENGTH", clen);
    395   1.1   mbalmer 			if (request->hr_serverport && *request->hr_serverport)
    396   1.1   mbalmer 				lua_env(map->L, "SERVER_PORT",
    397   1.1   mbalmer 				    request->hr_serverport);
    398   1.1   mbalmer 			if (request->hr_remotehost && *request->hr_remotehost)
    399   1.1   mbalmer 				lua_env(map->L, "REMOTE_HOST",
    400   1.1   mbalmer 				    request->hr_remotehost);
    401   1.1   mbalmer 			if (request->hr_remoteaddr && *request->hr_remoteaddr)
    402   1.1   mbalmer 				lua_env(map->L, "REMOTE_ADDR",
    403   1.1   mbalmer 				    request->hr_remoteaddr);
    404   1.1   mbalmer 
    405   1.1   mbalmer 			/* Pass the headers in a separate table */
    406   1.1   mbalmer 			lua_newtable(map->L);
    407   1.1   mbalmer 			SIMPLEQ_FOREACH(headp, &request->hr_headers, h_next)
    408   1.1   mbalmer 				lua_env(map->L, headp->h_header,
    409   1.1   mbalmer 				    headp->h_value);
    410   1.1   mbalmer 
    411   1.1   mbalmer 			/* Pass the query variables */
    412   1.5   mbalmer 			if ((query && *query) ||
    413   1.5   mbalmer 			    (type && *type && !strcmp(type, FORM))) {
    414   1.1   mbalmer 				lua_newtable(map->L);
    415   1.1   mbalmer 				if (query && *query)
    416   1.1   mbalmer 					lua_decode_query(map->L, query);
    417   1.1   mbalmer 				if (type && *type && !strcmp(type, FORM)) {
    418   1.1   mbalmer 					if (clen && *clen && atol(clen) > 0) {
    419   1.1   mbalmer 						length = atol(clen);
    420   1.1   mbalmer 						content = bozomalloc(httpd,
    421   1.2   mbalmer 						    length + 1);
    422   1.4   mbalmer 						n = bozo_read(httpd,
    423   1.4   mbalmer 						    STDIN_FILENO, content,
    424   1.4   mbalmer 						    length);
    425   1.4   mbalmer 						if (n >= 0) {
    426   1.4   mbalmer 							content[n] = '\0';
    427   1.4   mbalmer 							lua_decode_query(map->L,
    428   1.4   mbalmer 							    content);
    429   1.5   mbalmer 						} else {
    430   1.5   mbalmer 							lua_pop(map->L, 1);
    431   1.5   mbalmer 							lua_pushnil(map->L);
    432   1.4   mbalmer 						}
    433   1.1   mbalmer 						free(content);
    434   1.1   mbalmer 					}
    435   1.1   mbalmer 				}
    436   1.1   mbalmer 			} else
    437   1.1   mbalmer 				lua_pushnil(map->L);
    438   1.1   mbalmer 
    439   1.1   mbalmer 			ret = lua_pcall(map->L, 3, 0, 0);
    440   1.1   mbalmer 			if (ret)
    441   1.1   mbalmer 				printf("<br>Lua error: %s\n",
    442   1.1   mbalmer 				    lua_tostring(map->L, -1));
    443   1.1   mbalmer 			bozo_flush(httpd, stdout);
    444   1.7  christos 			rv = 1;
    445   1.7  christos 			goto out;
    446   1.1   mbalmer 		}
    447   1.1   mbalmer 	}
    448   1.7  christos out:
    449   1.1   mbalmer 	free(prefix);
    450   1.1   mbalmer 	free(uri);
    451   1.1   mbalmer 	free(info);
    452   1.6  christos 	free(query);
    453   1.7  christos 	free(file);
    454   1.7  christos 	return rv;
    455   1.1   mbalmer }
    456   1.1   mbalmer 
    457   1.1   mbalmer #endif /* NO_LUA_SUPPORT */
    458