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