1/* This file is part of the CivetWeb web server.
2 * See https://github.com/civetweb/civetweb/
3 */
4
5#if !defined(_WIN32)
6#include <dlfcn.h>
7#endif
8#include "civetweb_lua.h"
9#include "civetweb_private_lua.h"
10
11#if defined(_WIN32)
12static void *
13mmap(void *addr, int64_t len, int prot, int flags, int fd, int offset)
14{
15	/* TODO (low): This is an incomplete implementation of mmap for windows.
16	 * Currently it is sufficient, but there are a lot of unused parameters.
17	 * Better use a function "mg_map" which only has the required parameters,
18	 * and implement it using mmap in Linux and CreateFileMapping in Windows.
19	 * No one should expect a full mmap for Windows here.
20	 */
21	HANDLE fh = (HANDLE)_get_osfhandle(fd);
22	HANDLE mh = CreateFileMapping(fh, 0, PAGE_READONLY, 0, 0, 0);
23	void *p = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, (size_t)len);
24	CloseHandle(mh);
25
26	/* unused parameters */
27	(void)addr;
28	(void)prot;
29	(void)flags;
30	(void)offset;
31
32	return p;
33}
34
35static void
36munmap(void *addr, int64_t length)
37{
38	/* unused parameters */
39	(void)length;
40
41	UnmapViewOfFile(addr);
42}
43
44#define MAP_FAILED (NULL)
45#define MAP_PRIVATE (0)
46#define PROT_READ (0)
47#else
48#include <sys/mman.h>
49#endif
50
51static const char *const LUASOCKET = "luasocket";
52static const char lua_regkey_ctx = 1;
53static const char lua_regkey_connlist = 2;
54static const char lua_regkey_lsp_include_history = 3;
55static const char *const LUABACKGROUNDPARAMS = "mg";
56
57/* Limit nesting depth of mg.include.
58 * This takes a lot of stack (~10 kB per recursion),
59 * so do not use a too high limit. */
60#if !defined(LSP_INCLUDE_MAX_DEPTH)
61#define LSP_INCLUDE_MAX_DEPTH (10)
62#endif
63
64
65/* Forward declarations */
66static void handle_request(struct mg_connection *);
67static int handle_lsp_request(struct mg_connection *,
68                              const char *,
69                              struct mg_file *,
70                              struct lua_State *);
71
72static void
73reg_lstring(struct lua_State *L,
74            const char *name,
75            const void *buffer,
76            size_t buflen)
77{
78	if (name != NULL && buffer != NULL) {
79		lua_pushstring(L, name);
80		lua_pushlstring(L, (const char *)buffer, buflen);
81		lua_rawset(L, -3);
82	}
83}
84
85static void
86reg_llstring(struct lua_State *L,
87             const void *buffer1,
88             size_t buflen1,
89             const void *buffer2,
90             size_t buflen2)
91{
92	if (buffer1 != NULL && buffer2 != NULL) {
93		lua_pushlstring(L, (const char *)buffer1, buflen1);
94		lua_pushlstring(L, (const char *)buffer2, buflen2);
95		lua_rawset(L, -3);
96	}
97}
98
99#define reg_string(L, name, val)                                               \
100	reg_lstring(L, name, val, val ? strlen(val) : 0)
101
102static void
103reg_int(struct lua_State *L, const char *name, int val)
104{
105	if (name != NULL) {
106		lua_pushstring(L, name);
107		lua_pushinteger(L, val);
108		lua_rawset(L, -3);
109	}
110}
111
112static void
113reg_boolean(struct lua_State *L, const char *name, int val)
114{
115	if (name != NULL) {
116		lua_pushstring(L, name);
117		lua_pushboolean(L, val != 0);
118		lua_rawset(L, -3);
119	}
120}
121
122static void
123reg_conn_function(struct lua_State *L,
124                  const char *name,
125                  lua_CFunction func,
126                  struct mg_connection *conn)
127{
128	if (name != NULL && func != NULL && conn != NULL) {
129		lua_pushstring(L, name);
130		lua_pushlightuserdata(L, conn);
131		lua_pushcclosure(L, func, 1);
132		lua_rawset(L, -3);
133	}
134}
135
136static void
137reg_function(struct lua_State *L, const char *name, lua_CFunction func)
138{
139	if (name != NULL && func != NULL) {
140		lua_pushstring(L, name);
141		lua_pushcclosure(L, func, 0);
142		lua_rawset(L, -3);
143	}
144}
145
146static void
147lua_cry(struct mg_connection *conn,
148        int err,
149        lua_State *L,
150        const char *lua_title,
151        const char *lua_operation)
152{
153	DEBUG_TRACE("lua_cry (err=%i): %s: %s", err, lua_title, lua_operation);
154
155	switch (err) {
156	case LUA_OK:
157	case LUA_YIELD:
158		break;
159	case LUA_ERRRUN:
160		mg_cry_internal(conn,
161		                "%s: %s failed: runtime error: %s",
162		                lua_title,
163		                lua_operation,
164		                lua_tostring(L, -1));
165		break;
166	case LUA_ERRSYNTAX:
167		mg_cry_internal(conn,
168		                "%s: %s failed: syntax error: %s",
169		                lua_title,
170		                lua_operation,
171		                lua_tostring(L, -1));
172		break;
173	case LUA_ERRMEM:
174		mg_cry_internal(conn,
175		                "%s: %s failed: out of memory",
176		                lua_title,
177		                lua_operation);
178		break;
179	case LUA_ERRGCMM:
180		mg_cry_internal(conn,
181		                "%s: %s failed: error during garbage collection",
182		                lua_title,
183		                lua_operation);
184		break;
185	case LUA_ERRERR:
186		mg_cry_internal(conn,
187		                "%s: %s failed: error in error handling: %s",
188		                lua_title,
189		                lua_operation,
190		                lua_tostring(L, -1));
191		break;
192	default:
193		mg_cry_internal(
194		    conn, "%s: %s failed: error %i", lua_title, lua_operation, err);
195		break;
196	}
197}
198
199static int
200lsp_sock_close(lua_State *L)
201{
202	int num_args = lua_gettop(L);
203	size_t s;
204	SOCKET *psock;
205
206	if ((num_args == 1) && lua_istable(L, -1)) {
207		lua_getfield(L, -1, "sock");
208		psock = (SOCKET *)lua_tolstring(L, -1, &s);
209		if (s != sizeof(SOCKET)) {
210			return luaL_error(L, "invalid internal state in :close() call");
211		}
212		/* Do not closesocket(*psock); here, close it in __gc */
213		(void)psock;
214	} else {
215		return luaL_error(L, "invalid :close() call");
216	}
217	return 0;
218}
219
220static int
221lsp_sock_recv(lua_State *L)
222{
223	int num_args = lua_gettop(L);
224	char buf[2000];
225	int n;
226	size_t s;
227	SOCKET *psock;
228
229	if ((num_args == 1) && lua_istable(L, -1)) {
230		lua_getfield(L, -1, "sock");
231		psock = (SOCKET *)lua_tolstring(L, -1, &s);
232		if (s != sizeof(SOCKET)) {
233			return luaL_error(L, "invalid internal state in :recv() call");
234		}
235		n = recv(*psock, buf, sizeof(buf), 0);
236		if (n <= 0) {
237			lua_pushnil(L);
238		} else {
239			lua_pushlstring(L, buf, n);
240		}
241	} else {
242		return luaL_error(L, "invalid :recv() call");
243	}
244	return 1;
245}
246
247static int
248lsp_sock_send(lua_State *L)
249{
250	int num_args = lua_gettop(L);
251	const char *buf;
252	size_t len, sent = 0;
253	int n = 0;
254	size_t s;
255	SOCKET *psock;
256
257	if ((num_args == 2) && lua_istable(L, -2) && lua_isstring(L, -1)) {
258		buf = lua_tolstring(L, -1, &len);
259		lua_getfield(L, -2, "sock");
260		psock = (SOCKET *)lua_tolstring(L, -1, &s);
261		if (s != sizeof(SOCKET)) {
262			return luaL_error(L, "invalid internal state in :close() call");
263		}
264
265		while (sent < len) {
266			if ((n = send(*psock, buf + sent, (int)(len - sent), 0)) <= 0) {
267				break;
268			}
269			sent += n;
270		}
271		lua_pushnumber(L, n);
272	} else {
273		return luaL_error(L, "invalid :close() call");
274	}
275	return 1;
276}
277
278static int
279lsp_sock_gc(lua_State *L)
280{
281	int num_args = lua_gettop(L);
282	size_t s;
283	SOCKET *psock;
284
285	if ((num_args == 1) && lua_istable(L, -1)) {
286		lua_getfield(L, -1, "sock");
287		psock = (SOCKET *)lua_tolstring(L, -1, &s);
288		if (s != sizeof(SOCKET)) {
289			return luaL_error(
290			    L,
291			    "invalid internal state in __gc for object created by connect");
292		}
293		closesocket(*psock);
294	} else {
295		return luaL_error(L, "__gc for object created by connect failed");
296	}
297	return 0;
298}
299
300/* Methods and meta-methods supported by the object returned by connect.
301 * For meta-methods, see http://lua-users.org/wiki/MetatableEvents */
302static const struct luaL_Reg luasocket_methods[] = {{"close", lsp_sock_close},
303                                                    {"send", lsp_sock_send},
304                                                    {"recv", lsp_sock_recv},
305                                                    {"__gc", lsp_sock_gc},
306                                                    {NULL, NULL}};
307
308static int
309lsp_connect(lua_State *L)
310{
311	int num_args = lua_gettop(L);
312	char ebuf[100];
313	SOCKET sock;
314	union usa sa;
315	int ok;
316
317	if ((num_args == 3) && lua_isstring(L, -3) && lua_isnumber(L, -2)
318	    && lua_isnumber(L, -1)) {
319		ok = connect_socket(NULL,
320		                    lua_tostring(L, -3),
321		                    (int)lua_tonumber(L, -2),
322		                    (int)lua_tonumber(L, -1),
323		                    ebuf,
324		                    sizeof(ebuf),
325		                    &sock,
326		                    &sa);
327		if (!ok) {
328			return luaL_error(L, ebuf);
329		} else {
330			set_blocking_mode(sock);
331			lua_newtable(L);
332			reg_lstring(L, "sock", (const char *)&sock, sizeof(SOCKET));
333			reg_string(L, "host", lua_tostring(L, -4));
334			luaL_getmetatable(L, LUASOCKET);
335			lua_setmetatable(L, -2);
336		}
337	} else {
338		return luaL_error(
339		    L, "connect(host,port,is_ssl): invalid parameter given.");
340	}
341	return 1;
342}
343
344static int
345lsp_error(lua_State *L)
346{
347	DEBUG_TRACE("%s", "lsp_error");
348	lua_getglobal(L, "mg");
349	lua_getfield(L, -1, "onerror");
350	lua_pushvalue(L, -3);
351	lua_pcall(L, 1, 0, 0);
352	return 0;
353}
354
355/* Silently stop processing chunks. */
356static void
357lsp_abort(lua_State *L)
358{
359	int top = lua_gettop(L);
360	DEBUG_TRACE("%s", "lsp_abort");
361	lua_getglobal(L, "mg");
362	lua_pushnil(L);
363	lua_setfield(L, -2, "onerror");
364	lua_settop(L, top);
365	lua_pushstring(L, "aborting");
366	lua_error(L);
367}
368
369
370struct lsp_var_reader_data {
371	int64_t len;
372	int64_t consumed;
373	const char *begin;
374	unsigned char state;
375	char tag;
376};
377
378
379/* Helper function to read the content of variable values */
380static const char *
381lsp_var_reader(lua_State *L, void *ud, size_t *sz)
382{
383	struct lsp_var_reader_data *reader = (struct lsp_var_reader_data *)ud;
384	const char *ret;
385	(void)(L); /* unused */
386
387	/* This reader is called multiple times, to fetch the full Lua script */
388	switch (reader->state) {
389	case 0:
390		/* First call: what function to call */
391		reader->consumed = 0;
392		ret = "mg.write(";
393		*sz = strlen(ret);
394		break;
395	case 1:
396		/* Second call: forward variable name */
397		ret = reader->begin;
398		*sz = (size_t)reader->len;
399		reader->consumed += reader->len;
400		break;
401	case 2:
402		/* Third call: close function call */
403		ret = ")";
404		*sz = strlen(ret);
405		break;
406	default:
407		/* Forth/Final call: tell Lua we got the entire script */
408		ret = 0;
409		*sz = 0;
410	}
411
412	/* Step to the next state for the next call */
413	reader->state++;
414	return ret;
415}
416
417
418static const char *
419lsp_kepler_reader(lua_State *L, void *ud, size_t *sz)
420{
421	struct lsp_var_reader_data *reader = (struct lsp_var_reader_data *)ud;
422	const char *ret;
423	int64_t i;
424	int64_t left;
425
426	(void)(L); /* unused */
427
428	/* This reader is called multiple times, to fetch the full Lua script */
429
430	if (reader->state == 0) {
431		/* First call: Send opening tag - what function to call */
432		ret = "mg.write([=======[";
433		*sz = strlen(ret);
434		reader->state = 1;
435		reader->consumed = 0;
436		return ret;
437	}
438
439	if (reader->state == 4) {
440		/* Final call: Tell Lua reader, we reached the end */
441		*sz = 0;
442		return 0;
443	}
444
445	left = reader->len - reader->consumed;
446	if (left == 0) {
447		/* We reached the end of the file/available data. */
448		/* Send closing tag. */
449		ret = "]=======]);\n";
450		*sz = strlen(ret);
451		reader->state = 4; /* Next will be the final call */
452		return ret;
453	}
454	if (left > MG_BUF_LEN / 100) {
455		left = MG_BUF_LEN / 100; /* TODO XXX */
456	}
457	i = 0;
458
459	if (reader->state == 1) {
460		/* State 1: plain text - put inside mg.write(...) */
461		for (;;) {
462			/* Find next tag */
463			while ((i < left) && (reader->begin[i + reader->consumed] != '<')) {
464				i++;
465			}
466			if (i > 0) {
467				/* Forward all data until the next tag */
468				int64_t j = reader->consumed;
469				reader->consumed += i;
470				*sz = (size_t)i; /* cast is ok, i is limited to MG_BUF_LEN */
471				return reader->begin + j;
472			}
473
474			/* assert (reader->begin[reader->state] == '<') */
475			/* assert (i == 0) */
476			if (0 == memcmp(reader->begin + reader->consumed, "<?lua", 5)) {
477				/* kepler <?lua syntax */
478				i = 5;
479				reader->tag = '?';
480				break;
481			} else if (0 == memcmp(reader->begin + reader->consumed, "<%", 2)) {
482				/* kepler <% syntax */
483				i = 2;
484				reader->tag = '%';
485				break;
486			} else if (0 == memcmp(reader->begin + reader->consumed, "<?", 2)) {
487				/* civetweb <? syntax */
488				i = 2;
489				reader->tag = '?';
490				break;
491			} else {
492				i = 1;
493			}
494		}
495		/* We found an opening or closing tag, or we reached the end of the
496		 * file/data block */
497		if (reader->begin[reader->consumed + i] == '=') {
498			/* Lua= tag - Lua expression to print */
499			ret = "]=======]);\nmg.write(";
500			reader->state = 3;
501			i++;
502		} else {
503			/* Normal Lua tag - Lua chunk */
504			ret = "]=======]);\n";
505			reader->state = 2;
506		}
507		*sz = strlen(ret);
508		reader->consumed += i; /* length of <?lua or <% tag */
509		return ret;
510	}
511
512	if ((reader->state == 2) || (reader->state == 3)) {
513		/* State 2: Lua chunkg - keep outside mg.write(...) */
514		/* State 3: Lua expression - inside mg.write(...) */
515
516		for (;;) {
517			int close_tag_found = 0;
518
519			/* Find end tag */
520			while ((i < left)
521			       && (reader->begin[i + reader->consumed] != reader->tag)) {
522				i++;
523			}
524			if (i > 0) {
525				/* Forward all data inside the Lua script tag */
526				int64_t j = reader->consumed;
527				reader->consumed += i;
528				*sz = (size_t)i; /* cast is ok, i is limited to MG_BUF_LEN */
529
530				return reader->begin + j;
531			}
532
533			/* Is this the closing tag we are looking for? */
534			close_tag_found =
535			    ((i + 1 < left)
536			     && (reader->begin[i + 1 + reader->consumed] == '>'));
537
538			if (close_tag_found) {
539				/* Drop close tag */
540				reader->consumed += 2;
541
542				if (reader->state == 2) {
543					/* Send a new opening tag to Lua */
544					ret = ";\nmg.write([=======[";
545				} else {
546					ret = ");\nmg.write([=======[";
547				}
548				*sz = strlen(ret);
549				reader->state = 1;
550				return ret;
551			} else {
552				/* Not a close tag, continue searching */
553				i++;
554			}
555		}
556	}
557
558
559	/* Must never be reached */
560	*sz = 0;
561	return 0;
562}
563
564
565static int
566run_lsp_kepler(struct mg_connection *conn,
567               const char *path,
568               const char *p,
569               int64_t len,
570               lua_State *L,
571               int depth)
572{
573
574	int lua_ok;
575	struct lsp_var_reader_data data;
576	char date[64];
577	time_t curtime = time(NULL);
578
579	gmt_time_string(date, sizeof(date), &curtime);
580
581	if (depth == 1) {
582		/* Top level page assumes keep_alive is disabled.
583		 * Do not overwrite this setting for included pages. */
584		conn->must_close = 1;
585
586		/* Only send a HTML header, if this is the top level page.
587		 * If this page is included by some mg.include calls, do not add a
588		 * header. */
589		mg_printf(conn, "HTTP/1.1 200 OK\r\n");
590		send_no_cache_header(conn);
591		send_additional_header(conn);
592		mg_printf(conn,
593		          "Date: %s\r\n"
594		          "Connection: close\r\n"
595		          "Content-Type: text/html; charset=utf-8\r\n\r\n",
596		          date);
597	}
598
599	data.begin = p;
600	data.len = len;
601	data.state = 0;
602	data.consumed = 0;
603	data.tag = 0;
604	lua_ok = mg_lua_load(L, lsp_kepler_reader, &data, path, NULL);
605
606	if (lua_ok) {
607		/* Syntax error or OOM.
608		 * Error message is pushed on stack. */
609		lua_pcall(L, 1, 0, 0);
610		lua_cry(conn, lua_ok, L, "LSP", "execute"); /* XXX TODO: everywhere ! */
611
612	} else {
613		/* Success loading chunk. Call it. */
614		lua_pcall(L, 0, 0, 1);
615	}
616	return 0;
617}
618
619
620static int
621run_lsp_civetweb(struct mg_connection *conn,
622                 const char *path,
623                 const char *p,
624                 int64_t len,
625                 lua_State *L,
626                 int depth)
627{
628	int i, j, s, pos = 0, lines = 1, lualines = 0, is_var, lua_ok;
629	char chunkname[MG_BUF_LEN];
630	struct lsp_var_reader_data data;
631	const char lsp_mark1 = '?'; /* Use <? code ?> */
632	const char lsp_mark2 = '%'; /* Use <% code %> */
633
634	if (depth == 1) {
635		/* Assume the script does not support keep_alive. The script may change
636		 * this by calling mg.keep_alive(true). */
637		conn->must_close = 1;
638	}
639
640	for (i = 0; i < len; i++) {
641		if (p[i] == '\n') {
642			lines++;
643		}
644
645		/* Lua pages are normal text, unless there is a "<?" or "<%" tag. */
646		if (((i + 1) < len) && (p[i] == '<')
647		    && ((p[i + 1] == lsp_mark1) || (p[i + 1] == lsp_mark2))) {
648
649			/* Opening tag way "<?" or "<%", closing tag must be the same. */
650			char lsp_mark_used = p[i + 1];
651
652			/* <?= var ?> or <%= var %> means a variable is enclosed and its
653			 * value should be printed */
654			if (0 == memcmp("lua", p + i + 2, 3)) {
655				/* Syntax: <?lua code ?> or <?lua= var ?> */
656				/* This is added for compatibility to other LSP syntax
657				 * definitions. */
658				/* Skip 3 letters ("lua"). */
659				s = 3;
660			} else {
661				/* no additional letters to skip, only "<?" */
662				s = 0;
663			}
664
665			/* Check for '=' in "<?= ..." or "<%= ..." or "<?lua= ..." */
666			is_var = (((i + s + 2) < len) && (p[i + s + 2] == '='));
667			if (is_var) {
668				/* use variable value (print it later) */
669				j = i + 2;
670			} else {
671				/* execute script code */
672				j = i + 1;
673			}
674
675			while (j < len) {
676
677				if (p[j] == '\n') {
678					/* Add line (for line number offset) */
679					lualines++;
680				}
681
682				/* Check for closing tag. */
683				if (((j + 1) < len) && (p[j] == lsp_mark_used)
684				    && (p[j + 1] == '>')) {
685					/* We found the closing tag of the Lua tag. */
686
687					/* Print everything before the Lua opening tag. */
688					mg_write(conn, p + pos, i - pos);
689
690					/* Set a name for debugging purposes */
691					mg_snprintf(conn,
692					            NULL, /* ignore truncation for debugging */
693					            chunkname,
694					            sizeof(chunkname),
695					            "@%s+%i",
696					            path,
697					            lines);
698
699					/* Prepare data for Lua C functions */
700					lua_pushlightuserdata(L, conn);
701					lua_pushcclosure(L, lsp_error, 1);
702
703					/* Distinguish between <? script ?> (is_var == 0)
704					 * and <?= expression ?> (is_var != 0). */
705					if (is_var) {
706						/* For variables: Print the value */
707						/* Note: <?= expression ?> is equivalent to
708						 * <? mg.write( expression ) ?> */
709						data.begin = p + (i + 3 + s);
710						data.len = j - (i + 3 + s);
711						data.state = 0;
712						data.consumed = 0;
713						data.tag = 0;
714						lua_ok = mg_lua_load(
715						    L, lsp_var_reader, &data, chunkname, NULL);
716					} else {
717						/* For scripts: Execute them */
718						lua_ok = luaL_loadbuffer(L,
719						                         p + (i + 2 + s),
720						                         j - (i + 2 + s),
721						                         chunkname);
722					}
723
724					if (lua_ok) {
725						/* Syntax error or OOM.
726						 * Error message is pushed on stack. */
727						lua_pcall(L, 1, 0, 0);
728					} else {
729						/* Success loading chunk. Call it. */
730						lua_pcall(L, 0, 0, 1);
731					}
732
733					/* Progress until after the Lua closing tag. */
734					pos = j + 2;
735					i = pos - 1;
736					break;
737				}
738				j++;
739			}
740
741			/* Line number for debugging/error logging. */
742			if (lualines > 0) {
743				lines += lualines;
744				lualines = 0;
745			}
746		}
747	}
748
749	/* Print everything after the last Lua closing tag. */
750	if (i > pos) {
751		mg_write(conn, p + pos, i - pos);
752	}
753
754	return 0;
755}
756
757
758/* mg.write: Send data to the client */
759static int
760lsp_write(lua_State *L)
761{
762	struct mg_connection *conn =
763	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
764	int num_args = lua_gettop(L);
765	const char *str;
766	size_t size;
767	int i;
768	int rv = 1;
769
770	for (i = 1; i <= num_args; i++) {
771		if (lua_isstring(L, i)) {
772			str = lua_tolstring(L, i, &size);
773			if (mg_write(conn, str, size) != (int)size) {
774				rv = 0;
775			}
776		}
777	}
778	lua_pushboolean(L, rv);
779
780	return 1;
781}
782
783
784/* mg.read: Read data from the client (e.g., from a POST request) */
785static int
786lsp_read(lua_State *L)
787{
788	struct mg_connection *conn =
789	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
790	char buf[1024];
791	int len = mg_read(conn, buf, sizeof(buf));
792
793	if (len <= 0)
794		return 0;
795	lua_pushlstring(L, buf, len);
796
797	return 1;
798}
799
800
801/* mg.keep_alive: Allow Lua pages to use the http keep-alive mechanism */
802static int
803lsp_keep_alive(lua_State *L)
804{
805	struct mg_connection *conn =
806	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
807	int num_args = lua_gettop(L);
808
809	/* This function may be called with one parameter (boolean) to set the
810	keep_alive state.
811	Or without a parameter to just query the current keep_alive state. */
812	if ((num_args == 1) && lua_isboolean(L, 1)) {
813		conn->must_close = !lua_toboolean(L, 1);
814	} else if (num_args != 0) {
815		/* Syntax error */
816		return luaL_error(L, "invalid keep_alive() call");
817	}
818
819	/* Return the current "keep_alive" state. This may be false, even it
820	 * keep_alive(true) has been called. */
821	lua_pushboolean(L, should_keep_alive(conn));
822	return 1;
823}
824
825
826/* Stack of includes */
827struct lsp_include_history {
828	int depth;
829	const char *script[LSP_INCLUDE_MAX_DEPTH + 1];
830};
831
832
833/* mg.include: Include another .lp file */
834static int
835lsp_include(lua_State *L)
836{
837	struct mg_connection *conn =
838	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
839	int num_args = lua_gettop(L);
840	struct mg_file file = STRUCT_FILE_INITIALIZER;
841	const char *file_name = (num_args >= 1) ? lua_tostring(L, 1) : NULL;
842	const char *path_type = (num_args >= 2) ? lua_tostring(L, 2) : NULL;
843	struct lsp_include_history *include_history;
844
845	if (path_type == NULL) {
846		/* default to "absolute" */
847		path_type = "a";
848	}
849
850	if ((file_name != NULL) && (num_args <= 2)) {
851
852		lua_pushlightuserdata(L, (void *)&lua_regkey_lsp_include_history);
853		lua_gettable(L, LUA_REGISTRYINDEX);
854		include_history = (struct lsp_include_history *)lua_touserdata(L, -1);
855
856		if (include_history->depth >= ((int)(LSP_INCLUDE_MAX_DEPTH))) {
857			mg_cry_internal(
858			    conn,
859			    "lsp max include depth of %i reached while including %s",
860			    (int)(LSP_INCLUDE_MAX_DEPTH),
861			    file_name);
862		} else {
863			char file_name_path[512];
864			char *p;
865			size_t len;
866			int truncated = 0;
867
868			file_name_path[511] = 0;
869
870			if (*path_type == 'v') {
871				/* "virtual" = relative to document root. */
872				(void)mg_snprintf(conn,
873				                  &truncated,
874				                  file_name_path,
875				                  sizeof(file_name_path),
876				                  "%s/%s",
877				                  conn->dom_ctx->config[DOCUMENT_ROOT],
878				                  file_name);
879
880			} else if (*path_type == 'a') {
881				/* "absolute" = file name is relative to the
882				 * webserver working directory
883				 * or it is absolute system path. */
884				/* path_type==NULL is the legacy use case with 1 argument */
885				(void)mg_snprintf(conn,
886				                  &truncated,
887				                  file_name_path,
888				                  sizeof(file_name_path),
889				                  "%s",
890				                  file_name);
891
892			} else if ((*path_type == 'r') || (*path_type == 'f')) {
893				/* "relative" = file name is relative to the
894				 * currect document */
895				(void)mg_snprintf(
896				    conn,
897				    &truncated,
898				    file_name_path,
899				    sizeof(file_name_path),
900				    "%s",
901				    include_history->script[include_history->depth]);
902
903				if (!truncated) {
904					if ((p = strrchr(file_name_path, '/')) != NULL) {
905						p[1] = '\0';
906					}
907					len = strlen(file_name_path);
908					(void)mg_snprintf(conn,
909					                  &truncated,
910					                  file_name_path + len,
911					                  sizeof(file_name_path) - len,
912					                  "%s",
913					                  file_name);
914				}
915
916			} else {
917				return luaL_error(
918				    L,
919				    "invalid path_type in include(file_name, path_type) call");
920			}
921
922			if (handle_lsp_request(conn, file_name_path, &file, L)) {
923				/* handle_lsp_request returned an error code, meaning an error
924				 * occurred in the included page and mg.onerror returned
925				 * non-zero.
926				 * Stop processing.
927				 */
928
929				lsp_abort(L);
930			}
931		}
932
933	} else {
934		/* Syntax error */
935		return luaL_error(L, "invalid include() call");
936	}
937	return 0;
938}
939
940
941/* mg.cry: Log an error. Default value for mg.onerror. */
942static int
943lsp_cry(lua_State *L)
944{
945	struct mg_connection *conn =
946	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
947	int num_args = lua_gettop(L);
948	const char *text = (num_args == 1) ? lua_tostring(L, 1) : NULL;
949
950	if (text) {
951		mg_cry_internal(conn, "%s", lua_tostring(L, -1));
952	} else {
953		/* Syntax error */
954		return luaL_error(L, "invalid cry() call");
955	}
956	return 0;
957}
958
959
960/* mg.redirect: Redirect the request (internally). */
961static int
962lsp_redirect(lua_State *L)
963{
964	struct mg_connection *conn =
965	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
966	int num_args = lua_gettop(L);
967	const char *target = (num_args == 1) ? lua_tostring(L, 1) : NULL;
968
969	if (target) {
970		conn->request_info.local_uri = target;
971		handle_request(conn);
972		lsp_abort(L);
973	} else {
974		/* Syntax error */
975		return luaL_error(L, "invalid redirect() call");
976	}
977	return 0;
978}
979
980
981/* mg.send_file */
982static int
983lsp_send_file(lua_State *L)
984{
985	struct mg_connection *conn =
986	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
987	int num_args = lua_gettop(L);
988	const char *filename = (num_args == 1) ? lua_tostring(L, 1) : NULL;
989
990	if (filename) {
991		mg_send_file(conn, filename);
992	} else {
993		/* Syntax error */
994		return luaL_error(L, "invalid send_file() call");
995	}
996	return 0;
997}
998
999
1000/* mg.mg_send_file_body */
1001static int
1002lsp_send_file_body(lua_State *L)
1003{
1004	struct mg_connection *conn =
1005	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
1006	int num_args = lua_gettop(L);
1007	const char *filename = (num_args == 1) ? lua_tostring(L, 1) : NULL;
1008	int ret;
1009
1010	if (filename) {
1011		ret = mg_send_file_body(conn, filename);
1012	} else {
1013		/* Syntax error */
1014		return luaL_error(L, "invalid send_file() call");
1015	}
1016
1017	lua_pushboolean(L, ret >= 0);
1018	return 1;
1019}
1020
1021
1022/* mg.get_time */
1023static int
1024lsp_get_time(lua_State *L)
1025{
1026	int num_args = lua_gettop(L);
1027	int monotonic = (num_args > 0) ? lua_toboolean(L, 1) : 0;
1028	struct timespec ts;
1029	double d;
1030
1031	clock_gettime(monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME, &ts);
1032	d = (double)ts.tv_sec + ((double)ts.tv_nsec * 1.0E-9);
1033	lua_pushnumber(L, d);
1034	return 1;
1035}
1036
1037
1038/* mg.get_var */
1039static int
1040lsp_get_var(lua_State *L)
1041{
1042	int num_args = lua_gettop(L);
1043	const char *data, *var_name;
1044	size_t data_len, occurrence;
1045	int ret;
1046	struct mg_context *ctx;
1047
1048	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
1049	lua_gettable(L, LUA_REGISTRYINDEX);
1050	ctx = (struct mg_context *)lua_touserdata(L, -1);
1051
1052	if (num_args >= 2 && num_args <= 3) {
1053		char *dst;
1054		data = lua_tolstring(L, 1, &data_len);
1055		var_name = lua_tostring(L, 2);
1056		occurrence = (num_args > 2) ? (long)lua_tonumber(L, 3) : 0;
1057
1058		/* Allocate dynamically, so there is no internal limit for get_var */
1059		dst = (char *)mg_malloc_ctx(data_len + 1, ctx);
1060		if (!dst) {
1061			return luaL_error(L, "out of memory in get_var() call");
1062		}
1063
1064		ret = mg_get_var2(data, data_len, var_name, dst, data_len, occurrence);
1065		if (ret >= 0) {
1066			/* Variable found: return value to Lua */
1067			lua_pushstring(L, dst);
1068		} else {
1069			/* Variable not found */
1070			lua_pushnil(L);
1071		}
1072		mg_free(dst);
1073	} else {
1074		/* Syntax error */
1075		return luaL_error(L, "invalid get_var() call");
1076	}
1077	return 1;
1078}
1079
1080
1081/* mg.get_mime_type */
1082static int
1083lsp_get_mime_type(lua_State *L)
1084{
1085	int num_args = lua_gettop(L);
1086	struct vec mime_type = {0, 0};
1087	const char *text;
1088
1089	struct mg_connection *conn =
1090	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
1091
1092	if (num_args == 1) {
1093		text = lua_tostring(L, 1);
1094		if (text) {
1095			if (conn) {
1096				get_mime_type(conn, text, &mime_type);
1097				lua_pushlstring(L, mime_type.ptr, mime_type.len);
1098			} else {
1099				text = mg_get_builtin_mime_type(text);
1100				lua_pushstring(L, text);
1101			}
1102		} else {
1103			/* Syntax error */
1104			return luaL_error(L, "invalid argument for get_mime_type() call");
1105		}
1106	} else {
1107		/* Syntax error */
1108		return luaL_error(L, "invalid get_mime_type() call");
1109	}
1110	return 1;
1111}
1112
1113
1114/* mg.get_cookie */
1115static int
1116lsp_get_cookie(lua_State *L)
1117{
1118	int num_args = lua_gettop(L);
1119	const char *cookie;
1120	const char *var_name;
1121	int ret;
1122	struct mg_context *ctx;
1123
1124	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
1125	lua_gettable(L, LUA_REGISTRYINDEX);
1126	ctx = (struct mg_context *)lua_touserdata(L, -1);
1127
1128	if (num_args == 2) {
1129		/* Correct number of arguments */
1130		size_t data_len;
1131		char *dst;
1132
1133		cookie = lua_tolstring(L, 1, &data_len);
1134		var_name = lua_tostring(L, 2);
1135
1136		if (cookie == NULL || var_name == NULL) {
1137			/* Syntax error */
1138			return luaL_error(L, "invalid get_cookie() call");
1139		}
1140
1141		dst = (char *)mg_malloc_ctx(data_len + 1, ctx);
1142		if (!dst) {
1143			return luaL_error(L, "out of memory in get_cookie() call");
1144		}
1145
1146		ret = mg_get_cookie(cookie, var_name, dst, data_len);
1147
1148		if (ret >= 0) {
1149			lua_pushlstring(L, dst, ret);
1150		} else {
1151			lua_pushnil(L);
1152		}
1153		mg_free(dst);
1154
1155	} else {
1156		/* Syntax error */
1157		return luaL_error(L, "invalid get_cookie() call");
1158	}
1159	return 1;
1160}
1161
1162
1163/* mg.md5 */
1164static int
1165lsp_md5(lua_State *L)
1166{
1167	int num_args = lua_gettop(L);
1168	const char *text;
1169	md5_byte_t hash[16];
1170	md5_state_t ctx;
1171	size_t text_len;
1172	char buf[40];
1173
1174	if (num_args == 1) {
1175		text = lua_tolstring(L, 1, &text_len);
1176		if (text) {
1177			md5_init(&ctx);
1178			md5_append(&ctx, (const md5_byte_t *)text, text_len);
1179			md5_finish(&ctx, hash);
1180			bin2str(buf, hash, sizeof(hash));
1181			lua_pushstring(L, buf);
1182		} else {
1183			lua_pushnil(L);
1184		}
1185	} else {
1186		/* Syntax error */
1187		return luaL_error(L, "invalid md5() call");
1188	}
1189	return 1;
1190}
1191
1192
1193/* mg.url_encode */
1194static int
1195lsp_url_encode(lua_State *L)
1196{
1197	int num_args = lua_gettop(L);
1198	const char *text;
1199	size_t text_len;
1200	char *dst;
1201	int dst_len;
1202	struct mg_context *ctx;
1203
1204	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
1205	lua_gettable(L, LUA_REGISTRYINDEX);
1206	ctx = (struct mg_context *)lua_touserdata(L, -1);
1207
1208	if (num_args == 1) {
1209		text = lua_tolstring(L, 1, &text_len);
1210		if (text) {
1211			dst_len = 3 * (int)text_len + 1;
1212			dst = ((text_len < 0x2AAAAAAA) ? (char *)mg_malloc_ctx(dst_len, ctx)
1213			                               : (char *)NULL);
1214			if (dst) {
1215				mg_url_encode(text, dst, dst_len);
1216				lua_pushstring(L, dst);
1217				mg_free(dst);
1218			} else {
1219				return luaL_error(L, "out of memory in url_decode() call");
1220			}
1221		} else {
1222			lua_pushnil(L);
1223		}
1224	} else {
1225		/* Syntax error */
1226		return luaL_error(L, "invalid url_encode() call");
1227	}
1228	return 1;
1229}
1230
1231
1232/* mg.url_decode */
1233static int
1234lsp_url_decode(lua_State *L)
1235{
1236	int num_args = lua_gettop(L);
1237	const char *text;
1238	size_t text_len;
1239	int is_form;
1240	char *dst;
1241	int dst_len;
1242	struct mg_context *ctx;
1243
1244	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
1245	lua_gettable(L, LUA_REGISTRYINDEX);
1246	ctx = (struct mg_context *)lua_touserdata(L, -1);
1247
1248	if (num_args == 1 || (num_args == 2 && lua_isboolean(L, 2))) {
1249		text = lua_tolstring(L, 1, &text_len);
1250		is_form = (num_args == 2) ? lua_isboolean(L, 2) : 0;
1251		if (text) {
1252			dst_len = (int)text_len + 1;
1253			dst = ((text_len < 0x7FFFFFFF) ? (char *)mg_malloc_ctx(dst_len, ctx)
1254			                               : (char *)NULL);
1255			if (dst) {
1256				mg_url_decode(text, (int)text_len, dst, dst_len, is_form);
1257				lua_pushstring(L, dst);
1258				mg_free(dst);
1259			} else {
1260				return luaL_error(L, "out of memory in url_decode() call");
1261			}
1262		} else {
1263			lua_pushnil(L);
1264		}
1265	} else {
1266		/* Syntax error */
1267		return luaL_error(L, "invalid url_decode() call");
1268	}
1269	return 1;
1270}
1271
1272
1273/* mg.base64_encode */
1274static int
1275lsp_base64_encode(lua_State *L)
1276{
1277	int num_args = lua_gettop(L);
1278	const char *text;
1279	size_t text_len;
1280	char *dst;
1281	struct mg_context *ctx;
1282
1283	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
1284	lua_gettable(L, LUA_REGISTRYINDEX);
1285	ctx = (struct mg_context *)lua_touserdata(L, -1);
1286
1287	if (num_args == 1) {
1288		text = lua_tolstring(L, 1, &text_len);
1289		if (text) {
1290			dst = (char *)mg_malloc_ctx(text_len * 8 / 6 + 4, ctx);
1291			if (dst) {
1292				base64_encode((const unsigned char *)text, (int)text_len, dst);
1293				lua_pushstring(L, dst);
1294				mg_free(dst);
1295			} else {
1296				return luaL_error(L, "out of memory in base64_encode() call");
1297			}
1298		} else {
1299			lua_pushnil(L);
1300		}
1301	} else {
1302		/* Syntax error */
1303		return luaL_error(L, "invalid base64_encode() call");
1304	}
1305	return 1;
1306}
1307
1308
1309/* mg.base64_encode */
1310static int
1311lsp_base64_decode(lua_State *L)
1312{
1313	int num_args = lua_gettop(L);
1314	const char *text;
1315	size_t text_len, dst_len;
1316	int ret;
1317	char *dst;
1318	struct mg_context *ctx;
1319
1320	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
1321	lua_gettable(L, LUA_REGISTRYINDEX);
1322	ctx = (struct mg_context *)lua_touserdata(L, -1);
1323
1324	if (num_args == 1) {
1325		text = lua_tolstring(L, 1, &text_len);
1326		if (text) {
1327			dst = (char *)mg_malloc_ctx(text_len, ctx);
1328			if (dst) {
1329				ret = base64_decode((const unsigned char *)text,
1330				                    (int)text_len,
1331				                    dst,
1332				                    &dst_len);
1333				if (ret != -1) {
1334					mg_free(dst);
1335					return luaL_error(
1336					    L, "illegal character in lsp_base64_decode() call");
1337				} else {
1338					lua_pushlstring(L, dst, dst_len);
1339					mg_free(dst);
1340				}
1341			} else {
1342				return luaL_error(L,
1343				                  "out of memory in lsp_base64_decode() call");
1344			}
1345		} else {
1346			lua_pushnil(L);
1347		}
1348	} else {
1349		/* Syntax error */
1350		return luaL_error(L, "invalid lsp_base64_decode() call");
1351	}
1352	return 1;
1353}
1354
1355
1356/* mg.get_response_code_text */
1357static int
1358lsp_get_response_code_text(lua_State *L)
1359{
1360	int num_args = lua_gettop(L);
1361	int type1;
1362	double code;
1363	const char *text;
1364
1365	if (num_args == 1) {
1366		type1 = lua_type(L, 1);
1367		if (type1 == LUA_TNUMBER) {
1368			/* If the first argument is a number,
1369			   convert it to the corresponding text. */
1370			code = lua_tonumber(L, 1);
1371			text = mg_get_response_code_text(NULL, (int)code);
1372			if (text) { /* <-- should be always true */
1373				lua_pushstring(L, text);
1374			}
1375			return text ? 1 : 0;
1376		}
1377	}
1378
1379	/* Syntax error */
1380	return luaL_error(L, "invalid get_response_code_text() call");
1381}
1382
1383
1384/* mg.random - might be better than math.random on some systems */
1385static int
1386lsp_random(lua_State *L)
1387{
1388	int num_args = lua_gettop(L);
1389	if (num_args == 0) {
1390		/* The civetweb internal random number generator will generate
1391		 * a 64 bit random number. */
1392		uint64_t r = get_random();
1393		/* Lua "number" is a IEEE 754 double precission float:
1394		 * https://en.wikipedia.org/wiki/Double-precision_floating-point_format
1395		 * Thus, mask with 2^53-1 to get an integer with the maximum
1396		 * precission available. */
1397		r &= ((((uint64_t)1) << 53) - 1);
1398		lua_pushnumber(L, (double)r);
1399		return 1;
1400	}
1401
1402	/* Syntax error */
1403	return luaL_error(L, "invalid random() call");
1404}
1405
1406
1407/* mg.get_info */
1408static int
1409lsp_get_info(lua_State *L)
1410{
1411	int num_args = lua_gettop(L);
1412	int type1, type2;
1413	const char *arg1;
1414	double arg2;
1415	int len;
1416	char *buf;
1417
1418	if (num_args == 1) {
1419		type1 = lua_type(L, 1);
1420		if (type1 == LUA_TSTRING) {
1421			arg1 = lua_tostring(L, 1);
1422			/* Get info according to argument */
1423			if (!mg_strcasecmp(arg1, "system")) {
1424				/* Get system info */
1425				len = mg_get_system_info(NULL, 0);
1426				if (len > 0) {
1427					buf = (char *)mg_malloc(len + 64);
1428					if (!buf) {
1429						return luaL_error(L, "OOM in get_info() call");
1430					}
1431					len = mg_get_system_info(buf, len + 63);
1432					lua_pushlstring(L, buf, len);
1433					mg_free(buf);
1434				} else {
1435					lua_pushstring(L, "");
1436				}
1437				return 1;
1438			}
1439			if (!mg_strcasecmp(arg1, "context")) {
1440				/* Get context */
1441				struct mg_context *ctx;
1442				lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
1443				lua_gettable(L, LUA_REGISTRYINDEX);
1444				ctx = (struct mg_context *)lua_touserdata(L, -1);
1445
1446				/* Get context info for server context */
1447				len = mg_get_context_info(ctx, NULL, 0);
1448				if (len > 0) {
1449					buf = (char *)mg_malloc(len + 64);
1450					if (!buf) {
1451						return luaL_error(L, "OOM in get_info() call");
1452					}
1453					len = mg_get_context_info(ctx, buf, len + 63);
1454					lua_pushlstring(L, buf, len);
1455					mg_free(buf);
1456				} else {
1457					lua_pushstring(L, "");
1458				}
1459				return 1;
1460			}
1461			if (!mg_strcasecmp(arg1, "common")) {
1462				/* Get context info for NULL context */
1463				len = mg_get_context_info(NULL, NULL, 0);
1464				if (len > 0) {
1465					buf = (char *)mg_malloc(len + 64);
1466					if (!buf) {
1467						return luaL_error(L, "OOM in get_info() call");
1468					}
1469					len = mg_get_context_info(NULL, buf, len + 63);
1470					lua_pushlstring(L, buf, len);
1471					mg_free(buf);
1472				} else {
1473					lua_pushstring(L, "");
1474				}
1475				return 1;
1476			}
1477			return 0;
1478		}
1479	}
1480
1481	if (num_args == 2) {
1482		type1 = lua_type(L, 1);
1483		type2 = lua_type(L, 2);
1484		if ((type1 == LUA_TSTRING) && (type2 == LUA_TNUMBER)) {
1485			arg1 = lua_tostring(L, 1);
1486			arg2 = lua_tonumber(L, 2);
1487
1488			/* Get info according to argument */
1489			if (!mg_strcasecmp(arg1, "connection")) {
1490				int idx;
1491
1492				/* Get context */
1493				struct mg_context *ctx;
1494				lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
1495				lua_gettable(L, LUA_REGISTRYINDEX);
1496				ctx = (struct mg_context *)lua_touserdata(L, -1);
1497
1498				/* Get connection info for connection idx */
1499				idx = (int)(arg2 + 0.5);
1500
1501				/* Lua uses 1 based index, C uses 0 based index */
1502				idx--;
1503
1504#if defined(MG_EXPERIMENTAL_INTERFACES)
1505				len = mg_get_connection_info(ctx, idx, NULL, 0);
1506				if (len > 0) {
1507					buf = (char *)mg_malloc(len + 64);
1508					if (!buf) {
1509						return luaL_error(L, "OOM in get_info() call");
1510					}
1511					len = mg_get_connection_info(ctx, idx, buf, len + 63);
1512					lua_pushlstring(L, buf, len);
1513					mg_free(buf);
1514				} else {
1515					lua_pushstring(L, "");
1516				}
1517#else
1518				(void)ctx;
1519				(void)idx;
1520				lua_pushstring(L, "");
1521#endif
1522
1523				return 1;
1524			}
1525			return 0;
1526		}
1527	}
1528
1529	/* Syntax error */
1530	return luaL_error(L, "invalid get_info() call");
1531}
1532
1533
1534/* mg.get_option */
1535static int
1536lsp_get_option(lua_State *L)
1537{
1538	int num_args = lua_gettop(L);
1539	int type1;
1540	const char *arg1;
1541	const char *data;
1542	int optidx;
1543
1544	/* Get connection */
1545	struct mg_connection *conn =
1546	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
1547
1548	if (num_args == 0) {
1549		const struct mg_option *opts = mg_get_valid_options();
1550
1551		if (!opts) { /* <-- should be always false */
1552			return 0;
1553		}
1554
1555		lua_newtable(L);
1556		while (opts->name) {
1557			optidx = get_option_index(opts->name);
1558			if (optidx >= 0) {
1559				data = conn->dom_ctx->config[optidx];
1560				if (data) {
1561					reg_string(L, opts->name, data);
1562				}
1563			}
1564			opts++;
1565		}
1566
1567		return 1;
1568	}
1569
1570	if (num_args == 1) {
1571		type1 = lua_type(L, 1);
1572		if (type1 == LUA_TSTRING) {
1573			arg1 = lua_tostring(L, 1);
1574			/* Get option according to argument */
1575			optidx = get_option_index(arg1);
1576			if (optidx >= 0) {
1577				data = conn->dom_ctx->config[optidx];
1578				if (data) {
1579					lua_pushstring(L, data);
1580					return 1;
1581				}
1582			}
1583			return 0;
1584		}
1585	}
1586
1587	/* Syntax error */
1588	return luaL_error(L, "invalid get_option() call");
1589}
1590
1591
1592/* UUID library and function pointer */
1593union {
1594	void *p;
1595	void (*f)(unsigned char uuid[16]);
1596} pf_uuid_generate;
1597
1598
1599/* mg.uuid */
1600static int
1601lsp_uuid(lua_State *L)
1602{
1603	union {
1604		unsigned char uuid_array[16];
1605		struct uuid_struct_type {
1606			uint32_t data1;
1607			uint16_t data2;
1608			uint16_t data3;
1609			uint8_t data4[8];
1610		} uuid_struct;
1611	} uuid;
1612
1613	char uuid_str[40];
1614	int num_args = lua_gettop(L);
1615
1616	memset(&uuid, 0, sizeof(uuid));
1617	memset(uuid_str, 0, sizeof(uuid_str));
1618
1619	if (num_args == 0) {
1620
1621		pf_uuid_generate.f(uuid.uuid_array);
1622
1623		sprintf(uuid_str,
1624		        "{%08lX-%04X-%04X-%02X%02X-"
1625		        "%02X%02X%02X%02X%02X%02X}",
1626		        (unsigned long)uuid.uuid_struct.data1,
1627		        (unsigned)uuid.uuid_struct.data2,
1628		        (unsigned)uuid.uuid_struct.data3,
1629		        (unsigned)uuid.uuid_struct.data4[0],
1630		        (unsigned)uuid.uuid_struct.data4[1],
1631		        (unsigned)uuid.uuid_struct.data4[2],
1632		        (unsigned)uuid.uuid_struct.data4[3],
1633		        (unsigned)uuid.uuid_struct.data4[4],
1634		        (unsigned)uuid.uuid_struct.data4[5],
1635		        (unsigned)uuid.uuid_struct.data4[6],
1636		        (unsigned)uuid.uuid_struct.data4[7]);
1637
1638		lua_pushstring(L, uuid_str);
1639		return 1;
1640	}
1641
1642	/* Syntax error */
1643	return luaL_error(L, "invalid random() call");
1644}
1645
1646
1647#if defined(USE_WEBSOCKET)
1648struct lua_websock_data {
1649	lua_State *state;
1650	char *script;
1651	unsigned references;
1652	struct mg_connection *conn[MAX_WORKER_THREADS];
1653	pthread_mutex_t ws_mutex;
1654};
1655#endif
1656
1657
1658/* mg.write for websockets */
1659static int
1660lwebsock_write(lua_State *L)
1661{
1662#if defined(USE_WEBSOCKET)
1663	int num_args = lua_gettop(L);
1664	struct lua_websock_data *ws;
1665	const char *str;
1666	size_t size;
1667	int opcode = -1;
1668	unsigned i;
1669	struct mg_connection *client = NULL;
1670
1671	lua_pushlightuserdata(L, (void *)&lua_regkey_connlist);
1672	lua_gettable(L, LUA_REGISTRYINDEX);
1673	ws = (struct lua_websock_data *)lua_touserdata(L, -1);
1674
1675	(void)pthread_mutex_lock(&(ws->ws_mutex));
1676
1677	if (num_args == 1) {
1678		/* just one text: send it to all client */
1679		if (lua_isstring(L, 1)) {
1680			opcode = MG_WEBSOCKET_OPCODE_TEXT;
1681		}
1682	} else if (num_args == 2) {
1683		if (lua_isnumber(L, 1)) {
1684			/* opcode number and message text */
1685			opcode = (int)lua_tointeger(L, 1);
1686		} else if (lua_isstring(L, 1)) {
1687			/* opcode string and message text */
1688			str = lua_tostring(L, 1);
1689			if (!mg_strncasecmp(str, "text", 4))
1690				opcode = MG_WEBSOCKET_OPCODE_TEXT;
1691			else if (!mg_strncasecmp(str, "bin", 3))
1692				opcode = MG_WEBSOCKET_OPCODE_BINARY;
1693			else if (!mg_strncasecmp(str, "close", 5))
1694				opcode = MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE;
1695			else if (!mg_strncasecmp(str, "ping", 4))
1696				opcode = MG_WEBSOCKET_OPCODE_PING;
1697			else if (!mg_strncasecmp(str, "pong", 4))
1698				opcode = MG_WEBSOCKET_OPCODE_PONG;
1699			else if (!mg_strncasecmp(str, "cont", 4))
1700				opcode = MG_WEBSOCKET_OPCODE_CONTINUATION;
1701		} else if (lua_isuserdata(L, 1)) {
1702			/* client id and message text */
1703			client = (struct mg_connection *)lua_touserdata(L, 1);
1704			opcode = MG_WEBSOCKET_OPCODE_TEXT;
1705		}
1706	} else if (num_args == 3) {
1707		if (lua_isuserdata(L, 1)) {
1708			client = (struct mg_connection *)lua_touserdata(L, 1);
1709			if (lua_isnumber(L, 2)) {
1710				/* client id, opcode number and message text */
1711				opcode = (int)lua_tointeger(L, 2);
1712			} else if (lua_isstring(L, 2)) {
1713				/* client id, opcode string and message text */
1714				str = lua_tostring(L, 2);
1715				if (!mg_strncasecmp(str, "text", 4))
1716					opcode = MG_WEBSOCKET_OPCODE_TEXT;
1717				else if (!mg_strncasecmp(str, "bin", 3))
1718					opcode = MG_WEBSOCKET_OPCODE_BINARY;
1719				else if (!mg_strncasecmp(str, "close", 5))
1720					opcode = MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE;
1721				else if (!mg_strncasecmp(str, "ping", 4))
1722					opcode = MG_WEBSOCKET_OPCODE_PING;
1723				else if (!mg_strncasecmp(str, "pong", 4))
1724					opcode = MG_WEBSOCKET_OPCODE_PONG;
1725				else if (!mg_strncasecmp(str, "cont", 4))
1726					opcode = MG_WEBSOCKET_OPCODE_CONTINUATION;
1727			}
1728		}
1729	}
1730
1731	if (opcode >= 0 && opcode < 16 && lua_isstring(L, num_args)) {
1732		str = lua_tolstring(L, num_args, &size);
1733		if (client) {
1734			for (i = 0; i < ws->references; i++) {
1735				if (client == ws->conn[i]) {
1736					mg_lock_connection(ws->conn[i]);
1737					mg_websocket_write(ws->conn[i], opcode, str, size);
1738					mg_unlock_connection(ws->conn[i]);
1739				}
1740			}
1741		} else {
1742			for (i = 0; i < ws->references; i++) {
1743				mg_lock_connection(ws->conn[i]);
1744				mg_websocket_write(ws->conn[i], opcode, str, size);
1745				mg_unlock_connection(ws->conn[i]);
1746			}
1747		}
1748	} else {
1749		(void)pthread_mutex_unlock(&(ws->ws_mutex));
1750		return luaL_error(L, "invalid websocket write() call");
1751	}
1752
1753	(void)pthread_mutex_unlock(&(ws->ws_mutex));
1754
1755#else
1756	(void)(L);           /* unused */
1757#endif
1758	return 0;
1759}
1760
1761
1762struct laction_arg {
1763	lua_State *state;
1764	const char *script;
1765	pthread_mutex_t *pmutex;
1766	char txt[1];
1767};
1768
1769
1770static int
1771lua_action(struct laction_arg *arg)
1772{
1773	int err, ok;
1774	struct mg_context *ctx;
1775
1776	(void)pthread_mutex_lock(arg->pmutex);
1777
1778	lua_pushlightuserdata(arg->state, (void *)&lua_regkey_ctx);
1779	lua_gettable(arg->state, LUA_REGISTRYINDEX);
1780	ctx = (struct mg_context *)lua_touserdata(arg->state, -1);
1781	lua_pop(arg->state, 1);
1782
1783	err = luaL_loadstring(arg->state, arg->txt);
1784	if (err != 0) {
1785		struct mg_connection fc;
1786		lua_cry(
1787		    fake_connection(&fc, ctx), err, arg->state, arg->script, "timer");
1788		(void)pthread_mutex_unlock(arg->pmutex);
1789		mg_free(arg);
1790		return 0;
1791	}
1792	err = lua_pcall(arg->state, 0, 1, 0);
1793	if (err != 0) {
1794		struct mg_connection fc;
1795		lua_cry(
1796		    fake_connection(&fc, ctx), err, arg->state, arg->script, "timer");
1797		(void)pthread_mutex_unlock(arg->pmutex);
1798		mg_free(arg);
1799		return 0;
1800	}
1801
1802	ok = lua_type(arg->state, -1);
1803	if (lua_isboolean(arg->state, -1)) {
1804		ok = lua_toboolean(arg->state, -1);
1805	} else {
1806		ok = 0;
1807	}
1808	lua_pop(arg->state, 1);
1809
1810	(void)pthread_mutex_unlock(arg->pmutex);
1811
1812	if (!ok) {
1813		mg_free(arg);
1814	}
1815	return ok;
1816}
1817
1818
1819static int
1820lua_action_free(struct laction_arg *arg)
1821{
1822	if (lua_action(arg)) {
1823		mg_free(arg);
1824	}
1825	return 0;
1826}
1827
1828
1829static int
1830lwebsocket_set_timer(lua_State *L, int is_periodic)
1831{
1832#if defined(USE_TIMERS) && defined(USE_WEBSOCKET)
1833	int num_args = lua_gettop(L);
1834	struct lua_websock_data *ws;
1835	int type1, type2, ok = 0;
1836	double timediff;
1837	struct mg_context *ctx;
1838	struct laction_arg *arg;
1839	const char *txt;
1840	size_t txt_len;
1841
1842	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
1843	lua_gettable(L, LUA_REGISTRYINDEX);
1844	ctx = (struct mg_context *)lua_touserdata(L, -1);
1845
1846	lua_pushlightuserdata(L, (void *)&lua_regkey_connlist);
1847	lua_gettable(L, LUA_REGISTRYINDEX);
1848	ws = (struct lua_websock_data *)lua_touserdata(L, -1);
1849
1850	if (num_args < 2) {
1851		return luaL_error(L,
1852		                  "not enough arguments for set_timer/interval() call");
1853	}
1854
1855	type1 = lua_type(L, 1);
1856	type2 = lua_type(L, 2);
1857
1858	if (type1 == LUA_TSTRING && type2 == LUA_TNUMBER && num_args == 2) {
1859		timediff = (double)lua_tonumber(L, 2);
1860		txt = lua_tostring(L, 1);
1861		txt_len = strlen(txt);
1862		arg = (struct laction_arg *)mg_malloc_ctx(sizeof(struct laction_arg)
1863		                                              + txt_len + 10,
1864		                                          ctx);
1865		if (!arg) {
1866			return luaL_error(L, "out of memory");
1867		}
1868
1869		arg->state = L;
1870		arg->script = ws->script;
1871		arg->pmutex = &(ws->ws_mutex);
1872		memcpy(arg->txt, "return(", 7);
1873		memcpy(arg->txt + 7, txt, txt_len);
1874		arg->txt[txt_len + 7] = ')';
1875		arg->txt[txt_len + 8] = 0;
1876		ok =
1877		    (0
1878		     == timer_add(ctx,
1879		                  timediff,
1880		                  is_periodic,
1881		                  1,
1882		                  (taction)(is_periodic ? lua_action : lua_action_free),
1883		                  (void *)arg));
1884	} else if (type1 == LUA_TFUNCTION && type2 == LUA_TNUMBER) {
1885		/* TODO (mid): not implemented yet */
1886		return luaL_error(L, "invalid arguments for set_timer/interval() call");
1887	} else {
1888		return luaL_error(L, "invalid arguments for set_timer/interval() call");
1889	}
1890
1891	lua_pushboolean(L, ok);
1892	return 1;
1893
1894#else
1895	(void)(L);           /* unused */
1896	(void)(is_periodic); /* unused */
1897	return 0;
1898#endif
1899}
1900
1901
1902/* mg.set_timeout for websockets */
1903static int
1904lwebsocket_set_timeout(lua_State *L)
1905{
1906	return lwebsocket_set_timer(L, 0);
1907}
1908
1909
1910/* mg.set_interval for websockets */
1911static int
1912lwebsocket_set_interval(lua_State *L)
1913{
1914	return lwebsocket_set_timer(L, 1);
1915}
1916
1917
1918/* Debug hook */
1919static void
1920lua_debug_hook(lua_State *L, lua_Debug *ar)
1921{
1922	int i;
1923	int stack_len = lua_gettop(L);
1924
1925	lua_getinfo(L, "nSlu", ar);
1926
1927	if (ar->event == LUA_HOOKCALL) {
1928		printf("call\n");
1929	} else if (ar->event == LUA_HOOKRET) {
1930		printf("ret\n");
1931#if defined(LUA_HOOKTAILRET)
1932	} else if (ar->event == LUA_HOOKTAILRET) {
1933		printf("tail ret\n");
1934#endif
1935#if defined(LUA_HOOKTAILCALL)
1936	} else if (ar->event == LUA_HOOKTAILCALL) {
1937		printf("tail call\n");
1938#endif
1939	} else if (ar->event == LUA_HOOKLINE) {
1940		printf("line\n");
1941	} else if (ar->event == LUA_HOOKCOUNT) {
1942		printf("count\n");
1943	} else {
1944		printf("unknown (%i)\n", ar->event);
1945	}
1946
1947	if (ar->currentline >= 0) {
1948		printf("%s:%i\n", ar->source, ar->currentline);
1949	}
1950
1951	printf("%s (%s)\n", ar->name, ar->namewhat);
1952
1953
1954	for (i = 1; i <= stack_len; i++) { /* repeat for each level */
1955		int val_type = lua_type(L, i);
1956		const char *s;
1957		size_t n;
1958
1959		switch (val_type) {
1960
1961		case LUA_TNIL:
1962			/* nil value  on the stack */
1963			printf("nil\n");
1964			break;
1965
1966		case LUA_TBOOLEAN:
1967			/* boolean (true / false) */
1968			printf("boolean: %s\n", lua_toboolean(L, i) ? "true" : "false");
1969			break;
1970
1971		case LUA_TNUMBER:
1972			/* number */
1973			printf("number: %g\n", lua_tonumber(L, i));
1974			break;
1975
1976		case LUA_TSTRING:
1977			/* string with limited length */
1978			s = lua_tolstring(L, i, &n);
1979			printf("string: '%.*s%s\n",
1980			       ((n > 30) ? 28 : (int)n),
1981			       s,
1982			       ((n > 30) ? ".." : "'"));
1983			break;
1984
1985		default:
1986			/* other values */
1987			printf("%s\n", lua_typename(L, val_type));
1988			break;
1989		}
1990	}
1991
1992	printf("\n");
1993}
1994
1995
1996/* Lua Environment */
1997enum {
1998	LUA_ENV_TYPE_LUA_SERVER_PAGE = 0,
1999	LUA_ENV_TYPE_PLAIN_LUA_PAGE = 1,
2000	LUA_ENV_TYPE_LUA_WEBSOCKET = 2,
2001};
2002
2003
2004static void
2005prepare_lua_request_info(struct mg_connection *conn, lua_State *L)
2006{
2007	const char *s;
2008	int i;
2009
2010	/* Export mg.request_info */
2011	lua_pushstring(L, "request_info");
2012	lua_newtable(L);
2013	reg_string(L, "request_method", conn->request_info.request_method);
2014	reg_string(L, "request_uri", conn->request_info.request_uri);
2015	reg_string(L, "uri", conn->request_info.local_uri);
2016	reg_string(L, "http_version", conn->request_info.http_version);
2017	reg_string(L, "query_string", conn->request_info.query_string);
2018	reg_string(L, "remote_addr", conn->request_info.remote_addr);
2019	/* TODO (high): ip version */
2020	reg_int(L, "remote_port", conn->request_info.remote_port);
2021	reg_int(L, "num_headers", conn->request_info.num_headers);
2022	reg_int(L, "server_port", ntohs(conn->client.lsa.sin.sin_port));
2023
2024	if (conn->path_info != NULL) {
2025		reg_string(L, "path_info", conn->path_info);
2026	}
2027
2028	if (conn->request_info.content_length >= 0) {
2029		/* reg_int64: content_length */
2030		lua_pushstring(L, "content_length");
2031		lua_pushnumber(
2032		    L,
2033		    (lua_Number)conn->request_info
2034		        .content_length); /* lua_Number may be used as 52 bit integer */
2035		lua_rawset(L, -3);
2036	}
2037	if ((s = mg_get_header(conn, "Content-Type")) != NULL) {
2038		reg_string(L, "content_type", s);
2039	}
2040
2041	if (conn->request_info.remote_user != NULL) {
2042		reg_string(L, "remote_user", conn->request_info.remote_user);
2043		reg_string(L, "auth_type", "Digest");
2044	}
2045
2046	reg_boolean(L, "https", conn->ssl != NULL);
2047
2048	if (conn->status_code > 0) {
2049		/* Lua error handler should show the status code */
2050		reg_int(L, "status", conn->status_code);
2051	}
2052
2053	/* Table "HTTP headers" */
2054	lua_pushstring(L, "http_headers");
2055	lua_newtable(L);
2056	for (i = 0; i < conn->request_info.num_headers; i++) {
2057		reg_string(L,
2058		           conn->request_info.http_headers[i].name,
2059		           conn->request_info.http_headers[i].value);
2060	}
2061	lua_rawset(L, -3);
2062
2063	/* Table "Client Certificate" */
2064	if (conn->request_info.client_cert) {
2065		lua_pushstring(L, "client_cert");
2066		lua_newtable(L);
2067		reg_string(L, "subject", conn->request_info.client_cert->subject);
2068		reg_string(L, "issuer", conn->request_info.client_cert->issuer);
2069		reg_string(L, "serial", conn->request_info.client_cert->serial);
2070		reg_string(L, "finger", conn->request_info.client_cert->finger);
2071		lua_rawset(L, -3);
2072	}
2073
2074	/* End of request_info */
2075	lua_rawset(L, -3);
2076}
2077
2078
2079static void *
2080lua_allocator(void *ud, void *ptr, size_t osize, size_t nsize)
2081{
2082	(void)osize; /* not used */
2083
2084	if (nsize == 0) {
2085		mg_free(ptr);
2086		return NULL;
2087	}
2088	return mg_realloc_ctx(ptr, nsize, (struct mg_context *)ud);
2089}
2090
2091
2092/* In CivetWeb, Lua-Shared is used as *.inl file */
2093#define LUA_SHARED_INTERFACE static
2094#include "mod_lua_shared.inl"
2095
2096
2097static void
2098civetweb_open_lua_libs(lua_State *L)
2099{
2100	{
2101		extern void luaL_openlibs(lua_State *);
2102		luaL_openlibs(L);
2103	}
2104
2105#if defined(USE_LUA_SQLITE3)
2106	{
2107		extern int luaopen_lsqlite3(lua_State *);
2108		luaopen_lsqlite3(L);
2109	}
2110#endif
2111#if defined(USE_LUA_LUAXML)
2112	{
2113		extern int luaopen_LuaXML_lib(lua_State *);
2114		luaopen_LuaXML_lib(L);
2115	}
2116#endif
2117#if defined(USE_LUA_FILE_SYSTEM)
2118	{
2119		extern int luaopen_lfs(lua_State *);
2120		luaopen_lfs(L);
2121	}
2122#endif
2123}
2124
2125
2126static void
2127prepare_lua_environment(struct mg_context *ctx,
2128                        struct mg_connection *conn,
2129                        struct lua_websock_data *ws_conn_list,
2130                        lua_State *L,
2131                        const char *script_name,
2132                        int lua_env_type)
2133{
2134	const char *preload_file_name = NULL;
2135	const char *debug_params = NULL;
2136
2137	civetweb_open_lua_libs(L);
2138
2139#if defined(MG_EXPERIMENTAL_INTERFACES)
2140	/* Check if debugging should be enabled */
2141	if ((conn != NULL) && (conn->dom_ctx != NULL)) {
2142		debug_params = conn->dom_ctx->config[LUA_DEBUG_PARAMS];
2143	}
2144#endif
2145
2146#if LUA_VERSION_NUM == 502
2147	/* Keep the "connect" method for compatibility,
2148	 * but do not backport it to Lua 5.1.
2149	 * TODO: Redesign the interface.
2150	 */
2151	luaL_newmetatable(L, LUASOCKET);
2152	/* self.__index = self */
2153	lua_pushvalue(L, -1);
2154	lua_setfield(L, -2, "__index");
2155	luaL_setfuncs(L, luasocket_methods, 0);
2156	lua_pop(L, 1);
2157	lua_register(L, "connect", lsp_connect);
2158#endif
2159
2160	/* Store context in the registry */
2161	if (ctx != NULL) {
2162		lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
2163		lua_pushlightuserdata(L, (void *)ctx);
2164		lua_settable(L, LUA_REGISTRYINDEX);
2165	}
2166	if (ws_conn_list != NULL) {
2167		lua_pushlightuserdata(L, (void *)&lua_regkey_connlist);
2168		lua_pushlightuserdata(L, (void *)ws_conn_list);
2169		lua_settable(L, LUA_REGISTRYINDEX);
2170	}
2171
2172	/* Lua server pages store the depth of mg.include, in order
2173	 * to detect recursions and prevent stack overflows. */
2174	if (lua_env_type == LUA_ENV_TYPE_LUA_SERVER_PAGE) {
2175		struct lsp_include_history *h;
2176		lua_pushlightuserdata(L, (void *)&lua_regkey_lsp_include_history);
2177		h = (struct lsp_include_history *)
2178		    lua_newuserdata(L, sizeof(struct lsp_include_history));
2179		lua_settable(L, LUA_REGISTRYINDEX);
2180		memset(h, 0, sizeof(struct lsp_include_history));
2181	}
2182
2183	/* Register mg module */
2184	lua_newtable(L);
2185
2186	switch (lua_env_type) {
2187	case LUA_ENV_TYPE_LUA_SERVER_PAGE:
2188		reg_string(L, "lua_type", "page");
2189		break;
2190	case LUA_ENV_TYPE_PLAIN_LUA_PAGE:
2191		reg_string(L, "lua_type", "script");
2192		break;
2193	case LUA_ENV_TYPE_LUA_WEBSOCKET:
2194		reg_string(L, "lua_type", "websocket");
2195		break;
2196	}
2197
2198	if (lua_env_type == LUA_ENV_TYPE_LUA_SERVER_PAGE
2199	    || lua_env_type == LUA_ENV_TYPE_PLAIN_LUA_PAGE) {
2200		reg_conn_function(L, "cry", lsp_cry, conn);
2201		reg_conn_function(L, "read", lsp_read, conn);
2202		reg_conn_function(L, "write", lsp_write, conn);
2203		reg_conn_function(L, "keep_alive", lsp_keep_alive, conn);
2204		reg_conn_function(L, "send_file", lsp_send_file, conn);
2205		reg_conn_function(L, "send_file_body", lsp_send_file_body, conn);
2206		reg_conn_function(L, "redirect", lsp_redirect, conn);
2207	}
2208
2209	if (lua_env_type == LUA_ENV_TYPE_LUA_SERVER_PAGE) {
2210		reg_conn_function(L, "include", lsp_include, conn);
2211	}
2212
2213	if (lua_env_type == LUA_ENV_TYPE_LUA_WEBSOCKET) {
2214		reg_function(L, "write", lwebsock_write);
2215#if defined(USE_TIMERS)
2216		reg_function(L, "set_timeout", lwebsocket_set_timeout);
2217		reg_function(L, "set_interval", lwebsocket_set_interval);
2218#endif
2219	}
2220
2221	reg_conn_function(L, "get_mime_type", lsp_get_mime_type, conn);
2222	reg_conn_function(L, "get_option", lsp_get_option, conn);
2223
2224	reg_function(L, "time", lsp_get_time);
2225	reg_function(L, "get_var", lsp_get_var);
2226	reg_function(L, "get_cookie", lsp_get_cookie);
2227	reg_function(L, "md5", lsp_md5);
2228	reg_function(L, "url_encode", lsp_url_encode);
2229	reg_function(L, "url_decode", lsp_url_decode);
2230	reg_function(L, "base64_encode", lsp_base64_encode);
2231	reg_function(L, "base64_decode", lsp_base64_decode);
2232	reg_function(L, "get_response_code_text", lsp_get_response_code_text);
2233	reg_function(L, "random", lsp_random);
2234	reg_function(L, "get_info", lsp_get_info);
2235
2236	if (pf_uuid_generate.f) {
2237		reg_function(L, "uuid", lsp_uuid);
2238	}
2239
2240	reg_string(L, "version", CIVETWEB_VERSION);
2241
2242	reg_string(L, "script_name", script_name);
2243
2244	if ((conn != NULL) && (conn->dom_ctx != NULL)) {
2245		reg_string(L, "document_root", conn->dom_ctx->config[DOCUMENT_ROOT]);
2246		reg_string(L,
2247		           "auth_domain",
2248		           conn->dom_ctx->config[AUTHENTICATION_DOMAIN]);
2249#if defined(USE_WEBSOCKET)
2250		if (conn->dom_ctx->config[WEBSOCKET_ROOT]) {
2251			reg_string(L,
2252			           "websocket_root",
2253			           conn->dom_ctx->config[WEBSOCKET_ROOT]);
2254		} else {
2255			reg_string(L,
2256			           "websocket_root",
2257			           conn->dom_ctx->config[DOCUMENT_ROOT]);
2258		}
2259#endif
2260
2261		if ((ctx != NULL) && (ctx->systemName != NULL)) {
2262			reg_string(L, "system", ctx->systemName);
2263		}
2264	}
2265
2266	/* Export connection specific info */
2267	if (conn != NULL) {
2268		prepare_lua_request_info(conn, L);
2269	}
2270
2271	/* Store as global table "mg" */
2272	lua_setglobal(L, "mg");
2273
2274	/* Register "shared" table */
2275	lua_shared_register(L);
2276
2277	/* Register default mg.onerror function */
2278	IGNORE_UNUSED_RESULT(
2279	    luaL_dostring(L,
2280	                  "mg.onerror = function(e) mg.write('\\nLua error:\\n', "
2281	                  "debug.traceback(e, 1)) end"));
2282
2283	/* Check if a preload file is available */
2284	if ((conn != NULL) && (conn->dom_ctx != NULL)) {
2285		preload_file_name = conn->dom_ctx->config[LUA_PRELOAD_FILE];
2286	}
2287
2288	/* Preload file into new Lua environment */
2289	if (preload_file_name) {
2290		IGNORE_UNUSED_RESULT(luaL_dofile(L, preload_file_name));
2291	}
2292
2293	/* Call user init function */
2294	if (ctx != NULL) {
2295		if (ctx->callbacks.init_lua != NULL) {
2296			ctx->callbacks.init_lua(conn, L);
2297		}
2298	}
2299
2300	/* If debugging is enabled, add a hook */
2301	if (debug_params) {
2302		int mask = 0;
2303		if (0 != strchr(debug_params, 'c')) {
2304			mask |= LUA_MASKCALL;
2305		}
2306		if (0 != strchr(debug_params, 'r')) {
2307			mask |= LUA_MASKRET;
2308		}
2309		if (0 != strchr(debug_params, 'l')) {
2310			mask |= LUA_MASKLINE;
2311		}
2312		lua_sethook(L, lua_debug_hook, mask, 0);
2313	}
2314}
2315
2316
2317static int
2318lua_error_handler(lua_State *L)
2319{
2320	const char *error_msg = lua_isstring(L, -1) ? lua_tostring(L, -1) : "?\n";
2321
2322	lua_getglobal(L, "mg");
2323	if (!lua_isnil(L, -1)) {
2324		lua_getfield(L, -1, "write"); /* call mg.write() */
2325		lua_pushstring(L, error_msg);
2326		lua_pushliteral(L, "\n");
2327		lua_call(L, 2, 0);
2328		IGNORE_UNUSED_RESULT(
2329		    luaL_dostring(L, "mg.write(debug.traceback(), '\\n')"));
2330	} else {
2331		printf("Lua error: [%s]\n", error_msg);
2332		IGNORE_UNUSED_RESULT(
2333		    luaL_dostring(L, "print(debug.traceback(), '\\n')"));
2334	}
2335	/* TODO(lsm, low): leave the stack balanced */
2336
2337	return 0;
2338}
2339
2340
2341static void
2342mg_exec_lua_script(struct mg_connection *conn,
2343                   const char *path,
2344                   const void **exports)
2345{
2346	int i;
2347	lua_State *L;
2348
2349	/* Assume the script does not support keep_alive. The script may change this
2350	 * by calling mg.keep_alive(true). */
2351	conn->must_close = 1;
2352
2353	/* Execute a plain Lua script. */
2354	if (path != NULL
2355	    && (L = lua_newstate(lua_allocator, (void *)(conn->phys_ctx)))
2356	           != NULL) {
2357		prepare_lua_environment(
2358		    conn->phys_ctx, conn, NULL, L, path, LUA_ENV_TYPE_PLAIN_LUA_PAGE);
2359		lua_pushcclosure(L, &lua_error_handler, 0);
2360
2361		if (exports != NULL) {
2362#if LUA_VERSION_NUM > 501
2363			lua_pushglobaltable(L);
2364			for (i = 0; exports[i] != NULL && exports[i + 1] != NULL; i += 2) {
2365				lua_CFunction func;
2366				lua_pushstring(L, (const char *)(exports[i]));
2367				*(const void **)(&func) = exports[i + 1];
2368				lua_pushcclosure(L, func, 0);
2369				lua_rawset(L, -3);
2370			}
2371#else
2372			for (i = 0; exports[i] != NULL && exports[i + 1] != NULL; i += 2) {
2373				lua_CFunction func;
2374				const char *name = (const char *)(exports[i]);
2375				*(const void **)(&func) = exports[i + 1];
2376				lua_register(L, name, func);
2377			}
2378#endif
2379		}
2380
2381		if (luaL_loadfile(L, path) != 0) {
2382			lua_error_handler(L);
2383		}
2384		lua_pcall(L, 0, 0, -2);
2385		lua_close(L);
2386	}
2387}
2388
2389
2390static int
2391handle_lsp_request(struct mg_connection *conn,
2392                   const char *path,
2393                   struct mg_file *filep,
2394                   struct lua_State *ls)
2395{
2396	void *p = NULL;
2397	lua_State *L = NULL;
2398	struct lsp_include_history *include_history;
2399	int error = 1;
2400	void *file_in_memory; /* TODO(low): remove when removing "file in memory" */
2401	int (*run_lsp)(struct mg_connection *,
2402	               const char *,
2403	               const char *,
2404	               int64_t,
2405	               lua_State *,
2406	               int);
2407	const char *addr;
2408
2409	/* mg_fopen opens the file and sets the size accordingly */
2410	if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, filep)) {
2411
2412		/* File not found or not accessible */
2413		if (ls == NULL) {
2414			mg_send_http_error(conn,
2415			                   500,
2416			                   "Error: Cannot open script file %s",
2417			                   path);
2418		} else {
2419			luaL_error(ls, "Cannot include [%s]: not found", path);
2420		}
2421
2422		goto cleanup_handle_lsp_request;
2423	}
2424
2425#if defined(MG_USE_OPEN_FILE)
2426	/* The "file in memory" feature is going to be removed. For details see
2427	 * https://groups.google.com/forum/#!topic/civetweb/h9HT4CmeYqI */
2428	file_in_memory = filep->access.membuf;
2429#else
2430	file_in_memory = NULL;
2431#endif
2432
2433	/* Map file in memory (size is known). */
2434	if (file_in_memory == NULL
2435	    && (p = mmap(NULL,
2436	                 (size_t)filep->stat.size,
2437	                 PROT_READ,
2438	                 MAP_PRIVATE,
2439	                 fileno(filep->access.fp),
2440	                 0))
2441	           == MAP_FAILED) {
2442
2443		/* File was not already in memory, and mmap failed now.
2444		 * Since wi have no data, show an error. */
2445		if (ls == NULL) {
2446			/* No open Lua state - use generic error function */
2447			mg_send_http_error(
2448			    conn,
2449			    500,
2450			    "Error: Cannot open script\nFile %s can not be mapped",
2451			    path);
2452		} else {
2453			/* Lua state exists - use Lua error function */
2454			luaL_error(ls,
2455			           "mmap(%s, %zu, %d): %s",
2456			           path,
2457			           (size_t)filep->stat.size,
2458			           fileno(filep->access.fp),
2459			           strerror(errno));
2460		}
2461
2462		goto cleanup_handle_lsp_request;
2463	}
2464
2465	/* File content is now memory mapped. Get mapping address */
2466	addr = (file_in_memory == NULL) ? (const char *)p
2467	                                : (const char *)file_in_memory;
2468
2469	/* Get a Lua state */
2470	if (ls != NULL) {
2471		/* We got a Lua state as argument. Use it! */
2472		L = ls;
2473	} else {
2474		/* We need to create a Lua state. */
2475		L = lua_newstate(lua_allocator, (void *)(conn->phys_ctx));
2476		if (L == NULL) {
2477			/* We neither got a Lua state from the command line,
2478			 * nor did we succeed in creating our own state.
2479			 * Show an error, and stop further processing of this request. */
2480			mg_send_http_error(
2481			    conn,
2482			    500,
2483			    "%s",
2484			    "Error: Cannot execute script\nlua_newstate failed");
2485
2486			goto cleanup_handle_lsp_request;
2487		}
2488
2489		/* New Lua state needs CivetWeb functions (e.g., the "mg" library). */
2490		prepare_lua_environment(
2491		    conn->phys_ctx, conn, NULL, L, path, LUA_ENV_TYPE_LUA_SERVER_PAGE);
2492	}
2493
2494	/* Get LSP include history table */
2495	lua_pushlightuserdata(L, (void *)&lua_regkey_lsp_include_history);
2496	lua_gettable(L, LUA_REGISTRYINDEX);
2497	include_history = (struct lsp_include_history *)lua_touserdata(L, -1);
2498
2499	/* Store script name and increment depth */
2500	include_history->depth++;
2501	include_history->script[include_history->depth] = path;
2502
2503	/* Lua state is ready to use now. */
2504	/* Currently we have two different syntax options:
2505	 * Either "classic" CivetWeb syntax:
2506	 *    <? code ?>
2507	 *    <?= expression ?>
2508	 * Or "Kepler Syntax"
2509	 * https://keplerproject.github.io/cgilua/manual.html#templates
2510	 *    <?lua chunk ?>
2511	 *    <?lua= expression ?>
2512	 *    <% chunk %>
2513	 *    <%= expression %>
2514	 *
2515	 * Two important differences are:
2516	 * - In the "classic" CivetWeb syntax, the Lua Page had to send the HTTP
2517	 *   response headers itself. So the first lines are usually something like
2518	 *   HTTP/1.0 200 OK
2519	 *   Content-Type: text/html
2520	 *   followed by additional headers and an empty line, before the actual
2521	 *   Lua page in HTML syntax with <? code ?> tags.
2522	 *   The "Kepler"Syntax" does not send any HTTP header from the Lua Server
2523	 *   Page, but starts directly with <html> code - so it cannot influence
2524	 *   the HTTP response code, e.g., to send a 301 Moved Permanently.
2525	 *   Due to this difference, the same *.lp file cannot be used with the
2526	 *   same algorithm.
2527	 * - The "Kepler Syntax" used to allow mixtures of Lua and HTML inside an
2528	 *   incomplete Lua block, e.g.:
2529	 *   <lua? for i=1,10 do ?><li><%= key %></li><lua? end ?>
2530	 *   This was not provided in "classic" CivetWeb syntax, but you had to use
2531	 *   <? for i=1,10 do mg.write("<li>"..i.."</li>") end ?>
2532	 *   instead. The parsing algorithm for "Kepler syntax" is more complex
2533	 *   than for "classic" CivetWeb syntax - TODO: check timing/performance.
2534	 *
2535	 * CivetWeb now can use both parsing methods, but needs to know what
2536	 * parsing algorithm should be used.
2537	 * Idea: Files starting with '<' are HTML files in "Kepler Syntax", except
2538	 * "<?" which means "classic CivetWeb Syntax".
2539	 *
2540	 */
2541	run_lsp = run_lsp_civetweb;
2542	if ((addr[0] == '<') && (addr[1] != '?')) {
2543		run_lsp = run_lsp_kepler;
2544	}
2545
2546	/* We're not sending HTTP headers here, Lua page must do it. */
2547	error =
2548	    run_lsp(conn, path, addr, filep->stat.size, L, include_history->depth);
2549
2550cleanup_handle_lsp_request:
2551
2552	if (L != NULL && ls == NULL)
2553		lua_close(L);
2554	if (p != NULL)
2555		munmap(p, filep->stat.size);
2556	(void)mg_fclose(&filep->access);
2557
2558	return error;
2559}
2560
2561
2562#if defined(USE_WEBSOCKET)
2563struct mg_shared_lua_websocket_list {
2564	struct lua_websock_data ws;
2565	struct mg_shared_lua_websocket_list *next;
2566};
2567
2568
2569static void *
2570lua_websocket_new(const char *script, struct mg_connection *conn)
2571{
2572	struct mg_shared_lua_websocket_list **shared_websock_list =
2573	    &(conn->dom_ctx->shared_lua_websockets);
2574	struct lua_websock_data *ws;
2575	int err, ok = 0;
2576
2577	DEBUG_ASSERT(conn->lua_websocket_state == NULL);
2578
2579	/* lock list (mg_context global) */
2580	mg_lock_context(conn->phys_ctx);
2581	while (*shared_websock_list) {
2582		/* check if ws already in list */
2583		if (0 == strcmp(script, (*shared_websock_list)->ws.script)) {
2584			break;
2585		}
2586		shared_websock_list = &((*shared_websock_list)->next);
2587	}
2588
2589	if (*shared_websock_list == NULL) {
2590		/* add ws to list */
2591		*shared_websock_list =
2592		    (struct mg_shared_lua_websocket_list *)mg_calloc_ctx(
2593		        sizeof(struct mg_shared_lua_websocket_list), 1, conn->phys_ctx);
2594		if (*shared_websock_list == NULL) {
2595			conn->must_close = 1;
2596			mg_unlock_context(conn->phys_ctx);
2597			mg_cry_internal(conn,
2598			                "%s",
2599			                "Cannot create shared websocket struct, OOM");
2600			return NULL;
2601		}
2602		/* init ws list element */
2603		ws = &(*shared_websock_list)->ws;
2604		ws->script = mg_strdup_ctx(script, conn->phys_ctx);
2605		if (!ws->script) {
2606			conn->must_close = 1;
2607			mg_unlock_context(conn->phys_ctx);
2608			mg_cry_internal(conn,
2609			                "%s",
2610			                "Cannot create shared websocket script, OOM");
2611			return NULL;
2612		}
2613		pthread_mutex_init(&(ws->ws_mutex), &pthread_mutex_attr);
2614		(void)pthread_mutex_lock(&(ws->ws_mutex));
2615		ws->state = lua_newstate(lua_allocator, (void *)(conn->phys_ctx));
2616		ws->conn[0] = conn;
2617		ws->references = 1;
2618		prepare_lua_environment(conn->phys_ctx,
2619		                        conn,
2620		                        ws,
2621		                        ws->state,
2622		                        script,
2623		                        LUA_ENV_TYPE_LUA_WEBSOCKET);
2624		err = luaL_loadfile(ws->state, script);
2625		if (err != 0) {
2626			lua_cry(conn, err, ws->state, script, "load");
2627		}
2628		err = lua_pcall(ws->state, 0, 0, 0);
2629		if (err != 0) {
2630			lua_cry(conn, err, ws->state, script, "init");
2631		}
2632	} else {
2633		/* inc ref count */
2634		ws = &(*shared_websock_list)->ws;
2635		(void)pthread_mutex_lock(&(ws->ws_mutex));
2636		(*shared_websock_list)->ws.conn[(ws->references)++] = conn;
2637	}
2638	mg_unlock_context(conn->phys_ctx);
2639
2640	/* call add */
2641	lua_getglobal(ws->state, "open");
2642	lua_newtable(ws->state);
2643	prepare_lua_request_info(conn, ws->state);
2644	lua_pushstring(ws->state, "client");
2645	lua_pushlightuserdata(ws->state, (void *)conn);
2646	lua_rawset(ws->state, -3);
2647
2648	err = lua_pcall(ws->state, 1, 1, 0);
2649	if (err != 0) {
2650		lua_cry(conn, err, ws->state, script, "open handler");
2651	} else {
2652		if (lua_isboolean(ws->state, -1)) {
2653			ok = lua_toboolean(ws->state, -1);
2654		}
2655		lua_pop(ws->state, 1);
2656	}
2657	if (!ok) {
2658		/* Remove from ws connection list. */
2659		/* TODO (mid): Check if list entry and Lua state needs to be deleted
2660		 * (see websocket_close). */
2661		(*shared_websock_list)->ws.conn[--(ws->references)] = 0;
2662	}
2663
2664	(void)pthread_mutex_unlock(&(ws->ws_mutex));
2665
2666	return ok ? (void *)ws : NULL;
2667}
2668
2669
2670static int
2671lua_websocket_data(struct mg_connection *conn,
2672                   int bits,
2673                   char *data,
2674                   size_t data_len,
2675                   void *ws_arg)
2676{
2677	struct lua_websock_data *ws = (struct lua_websock_data *)(ws_arg);
2678	int err, ok = 0;
2679
2680	DEBUG_ASSERT(ws != NULL);
2681	DEBUG_ASSERT(ws->state != NULL);
2682
2683	(void)pthread_mutex_lock(&(ws->ws_mutex));
2684
2685	lua_getglobal(ws->state, "data");
2686	lua_newtable(ws->state);
2687	lua_pushstring(ws->state, "client");
2688	lua_pushlightuserdata(ws->state, (void *)conn);
2689	lua_rawset(ws->state, -3);
2690	lua_pushstring(ws->state, "bits"); /* TODO: dont use "bits" but fields with
2691	                                      a meaning according to
2692	                                      http://tools.ietf.org/html/rfc6455,
2693	                                      section 5.2 */
2694	lua_pushnumber(ws->state, bits);
2695	lua_rawset(ws->state, -3);
2696	lua_pushstring(ws->state, "data");
2697	lua_pushlstring(ws->state, data, data_len);
2698	lua_rawset(ws->state, -3);
2699
2700	err = lua_pcall(ws->state, 1, 1, 0);
2701	if (err != 0) {
2702		lua_cry(conn, err, ws->state, ws->script, "data handler");
2703	} else {
2704		if (lua_isboolean(ws->state, -1)) {
2705			ok = lua_toboolean(ws->state, -1);
2706		}
2707		lua_pop(ws->state, 1);
2708	}
2709	(void)pthread_mutex_unlock(&(ws->ws_mutex));
2710
2711	return ok;
2712}
2713
2714
2715static int
2716lua_websocket_ready(struct mg_connection *conn, void *ws_arg)
2717{
2718	struct lua_websock_data *ws = (struct lua_websock_data *)(ws_arg);
2719	int err, ok = 0;
2720
2721	DEBUG_ASSERT(ws != NULL);
2722	DEBUG_ASSERT(ws->state != NULL);
2723
2724	(void)pthread_mutex_lock(&(ws->ws_mutex));
2725
2726	lua_getglobal(ws->state, "ready");
2727	lua_newtable(ws->state);
2728	lua_pushstring(ws->state, "client");
2729	lua_pushlightuserdata(ws->state, (void *)conn);
2730	lua_rawset(ws->state, -3);
2731	err = lua_pcall(ws->state, 1, 1, 0);
2732	if (err != 0) {
2733		lua_cry(conn, err, ws->state, ws->script, "ready handler");
2734	} else {
2735		if (lua_isboolean(ws->state, -1)) {
2736			ok = lua_toboolean(ws->state, -1);
2737		}
2738		lua_pop(ws->state, 1);
2739	}
2740
2741	(void)pthread_mutex_unlock(&(ws->ws_mutex));
2742
2743	return ok;
2744}
2745
2746
2747static void
2748lua_websocket_close(struct mg_connection *conn, void *ws_arg)
2749{
2750	struct lua_websock_data *ws = (struct lua_websock_data *)(ws_arg);
2751	struct mg_shared_lua_websocket_list **shared_websock_list =
2752	    &(conn->dom_ctx->shared_lua_websockets);
2753	int err = 0;
2754	unsigned i;
2755
2756	DEBUG_ASSERT(ws != NULL);
2757	DEBUG_ASSERT(ws->state != NULL);
2758
2759	(void)pthread_mutex_lock(&(ws->ws_mutex));
2760
2761	lua_getglobal(ws->state, "close");
2762	lua_newtable(ws->state);
2763	lua_pushstring(ws->state, "client");
2764	lua_pushlightuserdata(ws->state, (void *)conn);
2765	lua_rawset(ws->state, -3);
2766
2767	err = lua_pcall(ws->state, 1, 0, 0);
2768	if (err != 0) {
2769		lua_cry(conn, err, ws->state, ws->script, "close handler");
2770	}
2771	for (i = 0; i < ws->references; i++) {
2772		if (ws->conn[i] == conn) {
2773			ws->references--;
2774			ws->conn[i] = ws->conn[ws->references];
2775		}
2776	}
2777	/* TODO: Delete lua_websock_data and remove it from the websocket list.
2778	   This must only be done, when all connections are closed, and all
2779	   asynchronous operations and timers are completed/expired. */
2780	(void)shared_websock_list; /* shared_websock_list unused (see open TODO) */
2781
2782	(void)pthread_mutex_unlock(&(ws->ws_mutex));
2783}
2784#endif
2785
2786
2787static lua_State *
2788mg_prepare_lua_context_script(const char *file_name,
2789                              struct mg_context *ctx,
2790                              char *ebuf,
2791                              size_t ebuf_len)
2792{
2793	struct lua_State *L;
2794	int lua_ret;
2795	const char *lua_err_txt;
2796
2797	(void)ctx;
2798
2799	L = luaL_newstate();
2800	if (L == NULL) {
2801		mg_snprintf(NULL,
2802		            NULL, /* No truncation check for ebuf */
2803		            ebuf,
2804		            ebuf_len,
2805		            "Error: %s",
2806		            "Cannot create Lua state");
2807		return 0;
2808	}
2809	civetweb_open_lua_libs(L);
2810
2811	lua_ret = luaL_loadfile(L, file_name);
2812	if (lua_ret != LUA_OK) {
2813		/* Error when loading the file (e.g. file not found,
2814		 * out of memory, ...)
2815		 */
2816		lua_err_txt = lua_tostring(L, -1);
2817		mg_snprintf(NULL,
2818		            NULL, /* No truncation check for ebuf */
2819		            ebuf,
2820		            ebuf_len,
2821		            "Error loading file %s: %s\n",
2822		            file_name,
2823		            lua_err_txt);
2824		return 0;
2825	}
2826
2827	/* The script file is loaded, now call it */
2828	lua_ret = lua_pcall(L,
2829	                    /* no arguments */ 0,
2830	                    /* zero or one return value */ 1,
2831	                    /* errors as strint return value */ 0);
2832
2833	if (lua_ret != LUA_OK) {
2834		/* Error when executing the script */
2835		lua_err_txt = lua_tostring(L, -1);
2836		mg_snprintf(NULL,
2837		            NULL, /* No truncation check for ebuf */
2838		            ebuf,
2839		            ebuf_len,
2840		            "Error running file %s: %s\n",
2841		            file_name,
2842		            lua_err_txt);
2843		return 0;
2844	}
2845	/*	lua_close(L); must be done somewhere else */
2846
2847	return L;
2848}
2849
2850
2851int
2852run_lua(const char *file_name)
2853{
2854	int func_ret = EXIT_FAILURE;
2855	char ebuf[512] = {0};
2856	lua_State *L =
2857	    mg_prepare_lua_context_script(file_name, NULL, ebuf, sizeof(ebuf));
2858	if (L) {
2859		/* Script executed */
2860		if (lua_type(L, -1) == LUA_TNUMBER) {
2861			func_ret = (int)lua_tonumber(L, -1);
2862		} else {
2863			func_ret = EXIT_SUCCESS;
2864		}
2865		lua_close(L);
2866	} else {
2867		fprintf(stderr, "%s\n", ebuf);
2868	}
2869	return func_ret;
2870}
2871
2872
2873static void *lib_handle_uuid = NULL;
2874
2875static void
2876lua_init_optional_libraries(void)
2877{
2878	/* shared Lua state */
2879	lua_shared_init();
2880
2881/* UUID library */
2882#if !defined(_WIN32)
2883	lib_handle_uuid = dlopen("libuuid.so", RTLD_LAZY);
2884	pf_uuid_generate.p =
2885	    (lib_handle_uuid ? dlsym(lib_handle_uuid, "uuid_generate") : 0);
2886#else
2887	pf_uuid_generate.p = 0;
2888#endif
2889}
2890
2891
2892static void
2893lua_exit_optional_libraries(void)
2894{
2895/* UUID library */
2896#if !defined(_WIN32)
2897	if (lib_handle_uuid) {
2898		dlclose(lib_handle_uuid);
2899	}
2900#endif
2901	pf_uuid_generate.p = 0;
2902	lib_handle_uuid = NULL;
2903
2904	/* shared Lua state */
2905	lua_shared_exit();
2906}
2907
2908
2909/* End of mod_lua.inl */
2910