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