1*76404edcSAsim Jamshed #include "mod_cml.h"
2*76404edcSAsim Jamshed #include "mod_cml_funcs.h"
3*76404edcSAsim Jamshed #include "log.h"
4*76404edcSAsim Jamshed #include "stream.h"
5*76404edcSAsim Jamshed 
6*76404edcSAsim Jamshed #include "stat_cache.h"
7*76404edcSAsim Jamshed 
8*76404edcSAsim Jamshed #include <assert.h>
9*76404edcSAsim Jamshed #include <stdio.h>
10*76404edcSAsim Jamshed #include <errno.h>
11*76404edcSAsim Jamshed #include <time.h>
12*76404edcSAsim Jamshed #include <string.h>
13*76404edcSAsim Jamshed 
14*76404edcSAsim Jamshed #define HASHLEN 16
15*76404edcSAsim Jamshed typedef unsigned char HASH[HASHLEN];
16*76404edcSAsim Jamshed #define HASHHEXLEN 32
17*76404edcSAsim Jamshed typedef char HASHHEX[HASHHEXLEN+1];
18*76404edcSAsim Jamshed #ifdef USE_OPENSSL
19*76404edcSAsim Jamshed #define IN const
20*76404edcSAsim Jamshed #else
21*76404edcSAsim Jamshed #define IN
22*76404edcSAsim Jamshed #endif
23*76404edcSAsim Jamshed #define OUT
24*76404edcSAsim Jamshed 
25*76404edcSAsim Jamshed #ifdef HAVE_LUA_H
26*76404edcSAsim Jamshed 
27*76404edcSAsim Jamshed #include <lua.h>
28*76404edcSAsim Jamshed #include <lualib.h>
29*76404edcSAsim Jamshed #include <lauxlib.h>
30*76404edcSAsim Jamshed 
31*76404edcSAsim Jamshed typedef struct {
32*76404edcSAsim Jamshed 	stream st;
33*76404edcSAsim Jamshed 	int done;
34*76404edcSAsim Jamshed } readme;
35*76404edcSAsim Jamshed 
load_file(lua_State * L,void * data,size_t * size)36*76404edcSAsim Jamshed static const char * load_file(lua_State *L, void *data, size_t *size) {
37*76404edcSAsim Jamshed 	readme *rm = data;
38*76404edcSAsim Jamshed 
39*76404edcSAsim Jamshed 	UNUSED(L);
40*76404edcSAsim Jamshed 
41*76404edcSAsim Jamshed 	if (rm->done) return 0;
42*76404edcSAsim Jamshed 
43*76404edcSAsim Jamshed 	*size = rm->st.size;
44*76404edcSAsim Jamshed 	rm->done = 1;
45*76404edcSAsim Jamshed 	return rm->st.start;
46*76404edcSAsim Jamshed }
47*76404edcSAsim Jamshed 
lua_to_c_get_string(lua_State * L,const char * varname,buffer * b)48*76404edcSAsim Jamshed static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
49*76404edcSAsim Jamshed 	int curelem;
50*76404edcSAsim Jamshed 
51*76404edcSAsim Jamshed 	lua_pushstring(L, varname);
52*76404edcSAsim Jamshed 
53*76404edcSAsim Jamshed 	curelem = lua_gettop(L);
54*76404edcSAsim Jamshed 	lua_gettable(L, LUA_GLOBALSINDEX);
55*76404edcSAsim Jamshed 
56*76404edcSAsim Jamshed 	/* it should be a table */
57*76404edcSAsim Jamshed 	if (!lua_isstring(L, curelem)) {
58*76404edcSAsim Jamshed 		lua_settop(L, curelem - 1);
59*76404edcSAsim Jamshed 
60*76404edcSAsim Jamshed 		return -1;
61*76404edcSAsim Jamshed 	}
62*76404edcSAsim Jamshed 
63*76404edcSAsim Jamshed 	buffer_copy_string(b, lua_tostring(L, curelem));
64*76404edcSAsim Jamshed 
65*76404edcSAsim Jamshed 	lua_pop(L, 1);
66*76404edcSAsim Jamshed 
67*76404edcSAsim Jamshed 	assert(curelem - 1 == lua_gettop(L));
68*76404edcSAsim Jamshed 
69*76404edcSAsim Jamshed 	return 0;
70*76404edcSAsim Jamshed }
71*76404edcSAsim Jamshed 
lua_to_c_is_table(lua_State * L,const char * varname)72*76404edcSAsim Jamshed static int lua_to_c_is_table(lua_State *L, const char *varname) {
73*76404edcSAsim Jamshed 	int curelem;
74*76404edcSAsim Jamshed 
75*76404edcSAsim Jamshed 	lua_pushstring(L, varname);
76*76404edcSAsim Jamshed 
77*76404edcSAsim Jamshed 	curelem = lua_gettop(L);
78*76404edcSAsim Jamshed 	lua_gettable(L, LUA_GLOBALSINDEX);
79*76404edcSAsim Jamshed 
80*76404edcSAsim Jamshed 	/* it should be a table */
81*76404edcSAsim Jamshed 	if (!lua_istable(L, curelem)) {
82*76404edcSAsim Jamshed 		lua_settop(L, curelem - 1);
83*76404edcSAsim Jamshed 
84*76404edcSAsim Jamshed 		return 0;
85*76404edcSAsim Jamshed 	}
86*76404edcSAsim Jamshed 
87*76404edcSAsim Jamshed 	lua_settop(L, curelem - 1);
88*76404edcSAsim Jamshed 
89*76404edcSAsim Jamshed 	assert(curelem - 1 == lua_gettop(L));
90*76404edcSAsim Jamshed 
91*76404edcSAsim Jamshed 	return 1;
92*76404edcSAsim Jamshed }
93*76404edcSAsim Jamshed 
c_to_lua_push(lua_State * L,int tbl,const char * key,size_t key_len,const char * val,size_t val_len)94*76404edcSAsim Jamshed static int c_to_lua_push(lua_State *L, int tbl, const char *key, size_t key_len, const char *val, size_t val_len) {
95*76404edcSAsim Jamshed 	lua_pushlstring(L, key, key_len);
96*76404edcSAsim Jamshed 	lua_pushlstring(L, val, val_len);
97*76404edcSAsim Jamshed 	lua_settable(L, tbl);
98*76404edcSAsim Jamshed 
99*76404edcSAsim Jamshed 	return 0;
100*76404edcSAsim Jamshed }
101*76404edcSAsim Jamshed 
102*76404edcSAsim Jamshed 
cache_export_get_params(lua_State * L,int tbl,buffer * qrystr)103*76404edcSAsim Jamshed static int cache_export_get_params(lua_State *L, int tbl, buffer *qrystr) {
104*76404edcSAsim Jamshed 	size_t is_key = 1;
105*76404edcSAsim Jamshed 	size_t i;
106*76404edcSAsim Jamshed 	char *key = NULL, *val = NULL;
107*76404edcSAsim Jamshed 
108*76404edcSAsim Jamshed 	key = qrystr->ptr;
109*76404edcSAsim Jamshed 
110*76404edcSAsim Jamshed 	/* we need the \0 */
111*76404edcSAsim Jamshed 	for (i = 0; i < qrystr->used; i++) {
112*76404edcSAsim Jamshed 		switch(qrystr->ptr[i]) {
113*76404edcSAsim Jamshed 		case '=':
114*76404edcSAsim Jamshed 			if (is_key) {
115*76404edcSAsim Jamshed 				val = qrystr->ptr + i + 1;
116*76404edcSAsim Jamshed 
117*76404edcSAsim Jamshed 				qrystr->ptr[i] = '\0';
118*76404edcSAsim Jamshed 
119*76404edcSAsim Jamshed 				is_key = 0;
120*76404edcSAsim Jamshed 			}
121*76404edcSAsim Jamshed 
122*76404edcSAsim Jamshed 			break;
123*76404edcSAsim Jamshed 		case '&':
124*76404edcSAsim Jamshed 		case '\0': /* fin symbol */
125*76404edcSAsim Jamshed 			if (!is_key) {
126*76404edcSAsim Jamshed 				/* we need at least a = since the last & */
127*76404edcSAsim Jamshed 
128*76404edcSAsim Jamshed 				/* terminate the value */
129*76404edcSAsim Jamshed 				qrystr->ptr[i] = '\0';
130*76404edcSAsim Jamshed 
131*76404edcSAsim Jamshed 				c_to_lua_push(L, tbl,
132*76404edcSAsim Jamshed 					      key, strlen(key),
133*76404edcSAsim Jamshed 					      val, strlen(val));
134*76404edcSAsim Jamshed 			}
135*76404edcSAsim Jamshed 
136*76404edcSAsim Jamshed 			key = qrystr->ptr + i + 1;
137*76404edcSAsim Jamshed 			val = NULL;
138*76404edcSAsim Jamshed 			is_key = 1;
139*76404edcSAsim Jamshed 			break;
140*76404edcSAsim Jamshed 		}
141*76404edcSAsim Jamshed 	}
142*76404edcSAsim Jamshed 
143*76404edcSAsim Jamshed 	return 0;
144*76404edcSAsim Jamshed }
145*76404edcSAsim Jamshed #if 0
146*76404edcSAsim Jamshed int cache_export_cookie_params(server *srv, connection *con, plugin_data *p) {
147*76404edcSAsim Jamshed 	data_unset *d;
148*76404edcSAsim Jamshed 
149*76404edcSAsim Jamshed 	UNUSED(srv);
150*76404edcSAsim Jamshed 
151*76404edcSAsim Jamshed 	if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
152*76404edcSAsim Jamshed 		data_string *ds = (data_string *)d;
153*76404edcSAsim Jamshed 		size_t key = 0, value = 0;
154*76404edcSAsim Jamshed 		size_t is_key = 1, is_sid = 0;
155*76404edcSAsim Jamshed 		size_t i;
156*76404edcSAsim Jamshed 
157*76404edcSAsim Jamshed 		/* found COOKIE */
158*76404edcSAsim Jamshed 		if (!DATA_IS_STRING(d)) return -1;
159*76404edcSAsim Jamshed 		if (ds->value->used == 0) return -1;
160*76404edcSAsim Jamshed 
161*76404edcSAsim Jamshed 		if (ds->value->ptr[0] == '\0' ||
162*76404edcSAsim Jamshed 		    ds->value->ptr[0] == '=' ||
163*76404edcSAsim Jamshed 		    ds->value->ptr[0] == ';') return -1;
164*76404edcSAsim Jamshed 
165*76404edcSAsim Jamshed 		buffer_reset(p->session_id);
166*76404edcSAsim Jamshed 		for (i = 0; i < ds->value->used; i++) {
167*76404edcSAsim Jamshed 			switch(ds->value->ptr[i]) {
168*76404edcSAsim Jamshed 			case '=':
169*76404edcSAsim Jamshed 				if (is_key) {
170*76404edcSAsim Jamshed 					if (0 == strncmp(ds->value->ptr + key, "PHPSESSID", i - key)) {
171*76404edcSAsim Jamshed 						/* found PHP-session-id-key */
172*76404edcSAsim Jamshed 						is_sid = 1;
173*76404edcSAsim Jamshed 					}
174*76404edcSAsim Jamshed 					value = i + 1;
175*76404edcSAsim Jamshed 
176*76404edcSAsim Jamshed 					is_key = 0;
177*76404edcSAsim Jamshed 				}
178*76404edcSAsim Jamshed 
179*76404edcSAsim Jamshed 				break;
180*76404edcSAsim Jamshed 			case ';':
181*76404edcSAsim Jamshed 				if (is_sid) {
182*76404edcSAsim Jamshed 					buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
183*76404edcSAsim Jamshed 				}
184*76404edcSAsim Jamshed 
185*76404edcSAsim Jamshed 				is_sid = 0;
186*76404edcSAsim Jamshed 				key = i + 1;
187*76404edcSAsim Jamshed 				value = 0;
188*76404edcSAsim Jamshed 				is_key = 1;
189*76404edcSAsim Jamshed 				break;
190*76404edcSAsim Jamshed 			case ' ':
191*76404edcSAsim Jamshed 				if (is_key == 1 && key == i) key = i + 1;
192*76404edcSAsim Jamshed 				if (is_key == 0 && value == i) value = i + 1;
193*76404edcSAsim Jamshed 				break;
194*76404edcSAsim Jamshed 			case '\0':
195*76404edcSAsim Jamshed 				if (is_sid) {
196*76404edcSAsim Jamshed 					buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
197*76404edcSAsim Jamshed 				}
198*76404edcSAsim Jamshed 				/* fin */
199*76404edcSAsim Jamshed 				break;
200*76404edcSAsim Jamshed 			}
201*76404edcSAsim Jamshed 		}
202*76404edcSAsim Jamshed 	}
203*76404edcSAsim Jamshed 
204*76404edcSAsim Jamshed 	return 0;
205*76404edcSAsim Jamshed }
206*76404edcSAsim Jamshed #endif
207*76404edcSAsim Jamshed 
cache_parse_lua(server * srv,connection * con,plugin_data * p,buffer * fn)208*76404edcSAsim Jamshed int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
209*76404edcSAsim Jamshed 	lua_State *L;
210*76404edcSAsim Jamshed 	readme rm;
211*76404edcSAsim Jamshed 	int ret = -1;
212*76404edcSAsim Jamshed 	buffer *b = buffer_init();
213*76404edcSAsim Jamshed 	int header_tbl = 0;
214*76404edcSAsim Jamshed 
215*76404edcSAsim Jamshed 	rm.done = 0;
216*76404edcSAsim Jamshed 	stream_open(&rm.st, fn);
217*76404edcSAsim Jamshed 
218*76404edcSAsim Jamshed 	/* push the lua file to the interpreter and see what happends */
219*76404edcSAsim Jamshed 	L = luaL_newstate();
220*76404edcSAsim Jamshed 	luaL_openlibs(L);
221*76404edcSAsim Jamshed 
222*76404edcSAsim Jamshed 	/* register functions */
223*76404edcSAsim Jamshed 	lua_register(L, "md5", f_crypto_md5);
224*76404edcSAsim Jamshed 	lua_register(L, "file_mtime", f_file_mtime);
225*76404edcSAsim Jamshed 	lua_register(L, "file_isreg", f_file_isreg);
226*76404edcSAsim Jamshed 	lua_register(L, "file_isdir", f_file_isreg);
227*76404edcSAsim Jamshed 	lua_register(L, "dir_files", f_dir_files);
228*76404edcSAsim Jamshed 
229*76404edcSAsim Jamshed #ifdef HAVE_MEMCACHE_H
230*76404edcSAsim Jamshed 	lua_pushliteral(L, "memcache_get_long");
231*76404edcSAsim Jamshed 	lua_pushlightuserdata(L, p->conf.mc);
232*76404edcSAsim Jamshed 	lua_pushcclosure(L, f_memcache_get_long, 1);
233*76404edcSAsim Jamshed 	lua_settable(L, LUA_GLOBALSINDEX);
234*76404edcSAsim Jamshed 
235*76404edcSAsim Jamshed 	lua_pushliteral(L, "memcache_get_string");
236*76404edcSAsim Jamshed 	lua_pushlightuserdata(L, p->conf.mc);
237*76404edcSAsim Jamshed 	lua_pushcclosure(L, f_memcache_get_string, 1);
238*76404edcSAsim Jamshed 	lua_settable(L, LUA_GLOBALSINDEX);
239*76404edcSAsim Jamshed 
240*76404edcSAsim Jamshed 	lua_pushliteral(L, "memcache_exists");
241*76404edcSAsim Jamshed 	lua_pushlightuserdata(L, p->conf.mc);
242*76404edcSAsim Jamshed 	lua_pushcclosure(L, f_memcache_exists, 1);
243*76404edcSAsim Jamshed 	lua_settable(L, LUA_GLOBALSINDEX);
244*76404edcSAsim Jamshed #endif
245*76404edcSAsim Jamshed 	/* register CGI environment */
246*76404edcSAsim Jamshed 	lua_pushliteral(L, "request");
247*76404edcSAsim Jamshed 	lua_newtable(L);
248*76404edcSAsim Jamshed 	lua_settable(L, LUA_GLOBALSINDEX);
249*76404edcSAsim Jamshed 
250*76404edcSAsim Jamshed 	lua_pushliteral(L, "request");
251*76404edcSAsim Jamshed 	header_tbl = lua_gettop(L);
252*76404edcSAsim Jamshed 	lua_gettable(L, LUA_GLOBALSINDEX);
253*76404edcSAsim Jamshed 
254*76404edcSAsim Jamshed 	c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
255*76404edcSAsim Jamshed 	c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
256*76404edcSAsim Jamshed 	c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
257*76404edcSAsim Jamshed 	c_to_lua_push(L, header_tbl, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
258*76404edcSAsim Jamshed 	if (!buffer_is_empty(con->request.pathinfo)) {
259*76404edcSAsim Jamshed 		c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
260*76404edcSAsim Jamshed 	}
261*76404edcSAsim Jamshed 
262*76404edcSAsim Jamshed 	c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
263*76404edcSAsim Jamshed 	c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
264*76404edcSAsim Jamshed 
265*76404edcSAsim Jamshed 	/* register GET parameter */
266*76404edcSAsim Jamshed 	lua_pushliteral(L, "get");
267*76404edcSAsim Jamshed 	lua_newtable(L);
268*76404edcSAsim Jamshed 	lua_settable(L, LUA_GLOBALSINDEX);
269*76404edcSAsim Jamshed 
270*76404edcSAsim Jamshed 	lua_pushliteral(L, "get");
271*76404edcSAsim Jamshed 	header_tbl = lua_gettop(L);
272*76404edcSAsim Jamshed 	lua_gettable(L, LUA_GLOBALSINDEX);
273*76404edcSAsim Jamshed 
274*76404edcSAsim Jamshed 	buffer_copy_string_buffer(b, con->uri.query);
275*76404edcSAsim Jamshed 	cache_export_get_params(L, header_tbl, b);
276*76404edcSAsim Jamshed 	buffer_reset(b);
277*76404edcSAsim Jamshed 
278*76404edcSAsim Jamshed 	/* 2 default constants */
279*76404edcSAsim Jamshed 	lua_pushliteral(L, "CACHE_HIT");
280*76404edcSAsim Jamshed 	lua_pushnumber(L, 0);
281*76404edcSAsim Jamshed 	lua_settable(L, LUA_GLOBALSINDEX);
282*76404edcSAsim Jamshed 
283*76404edcSAsim Jamshed 	lua_pushliteral(L, "CACHE_MISS");
284*76404edcSAsim Jamshed 	lua_pushnumber(L, 1);
285*76404edcSAsim Jamshed 	lua_settable(L, LUA_GLOBALSINDEX);
286*76404edcSAsim Jamshed 
287*76404edcSAsim Jamshed 	/* load lua program */
288*76404edcSAsim Jamshed 	if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {
289*76404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
290*76404edcSAsim Jamshed 				lua_tostring(L,-1));
291*76404edcSAsim Jamshed 
292*76404edcSAsim Jamshed 		goto error;
293*76404edcSAsim Jamshed 	}
294*76404edcSAsim Jamshed 
295*76404edcSAsim Jamshed 	/* get return value */
296*76404edcSAsim Jamshed 	ret = (int)lua_tonumber(L, -1);
297*76404edcSAsim Jamshed 	lua_pop(L, 1);
298*76404edcSAsim Jamshed 
299*76404edcSAsim Jamshed 	/* fetch the data from lua */
300*76404edcSAsim Jamshed 	lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
301*76404edcSAsim Jamshed 
302*76404edcSAsim Jamshed 	if (0 == lua_to_c_get_string(L, "output_contenttype", b)) {
303*76404edcSAsim Jamshed 		response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b));
304*76404edcSAsim Jamshed 	}
305*76404edcSAsim Jamshed 
306*76404edcSAsim Jamshed 	if (ret == 0) {
307*76404edcSAsim Jamshed 		/* up to now it is a cache-hit, check if all files exist */
308*76404edcSAsim Jamshed 
309*76404edcSAsim Jamshed 		int curelem;
310*76404edcSAsim Jamshed 		time_t mtime = 0;
311*76404edcSAsim Jamshed 
312*76404edcSAsim Jamshed 		if (!lua_to_c_is_table(L, "output_include")) {
313*76404edcSAsim Jamshed 			log_error_write(srv, __FILE__, __LINE__, "s",
314*76404edcSAsim Jamshed 				"output_include is missing or not a table");
315*76404edcSAsim Jamshed 			ret = -1;
316*76404edcSAsim Jamshed 
317*76404edcSAsim Jamshed 			goto error;
318*76404edcSAsim Jamshed 		}
319*76404edcSAsim Jamshed 
320*76404edcSAsim Jamshed 		lua_pushstring(L, "output_include");
321*76404edcSAsim Jamshed 
322*76404edcSAsim Jamshed 		curelem = lua_gettop(L);
323*76404edcSAsim Jamshed 		lua_gettable(L, LUA_GLOBALSINDEX);
324*76404edcSAsim Jamshed 
325*76404edcSAsim Jamshed 		/* HOW-TO build a etag ?
326*76404edcSAsim Jamshed 		 * as we don't just have one file we have to take the stat()
327*76404edcSAsim Jamshed 		 * from all base files, merge them and build the etag from
328*76404edcSAsim Jamshed 		 * it later.
329*76404edcSAsim Jamshed 		 *
330*76404edcSAsim Jamshed 		 * The mtime of the content is the mtime of the freshest base file
331*76404edcSAsim Jamshed 		 *
332*76404edcSAsim Jamshed 		 * */
333*76404edcSAsim Jamshed 
334*76404edcSAsim Jamshed 		lua_pushnil(L);  /* first key */
335*76404edcSAsim Jamshed 		while (lua_next(L, curelem) != 0) {
336*76404edcSAsim Jamshed 			stat_cache_entry *sce = NULL;
337*76404edcSAsim Jamshed 			/* key' is at index -2 and value' at index -1 */
338*76404edcSAsim Jamshed 
339*76404edcSAsim Jamshed 			if (lua_isstring(L, -1)) {
340*76404edcSAsim Jamshed 				const char *s = lua_tostring(L, -1);
341*76404edcSAsim Jamshed 
342*76404edcSAsim Jamshed 				/* the file is relative, make it absolute */
343*76404edcSAsim Jamshed 				if (s[0] != '/') {
344*76404edcSAsim Jamshed 					buffer_copy_string_buffer(b, p->basedir);
345*76404edcSAsim Jamshed 					buffer_append_string(b, lua_tostring(L, -1));
346*76404edcSAsim Jamshed 				} else {
347*76404edcSAsim Jamshed 					buffer_copy_string(b, lua_tostring(L, -1));
348*76404edcSAsim Jamshed 				}
349*76404edcSAsim Jamshed 
350*76404edcSAsim Jamshed 				if (HANDLER_ERROR == stat_cache_get_entry(srv, con, b, &sce)) {
351*76404edcSAsim Jamshed 					/* stat failed */
352*76404edcSAsim Jamshed 
353*76404edcSAsim Jamshed 					switch(errno) {
354*76404edcSAsim Jamshed 					case ENOENT:
355*76404edcSAsim Jamshed 						/* a file is missing, call the handler to generate it */
356*76404edcSAsim Jamshed 						if (!buffer_is_empty(p->trigger_handler)) {
357*76404edcSAsim Jamshed 							ret = 1; /* cache-miss */
358*76404edcSAsim Jamshed 
359*76404edcSAsim Jamshed 							log_error_write(srv, __FILE__, __LINE__, "s",
360*76404edcSAsim Jamshed 									"a file is missing, calling handler");
361*76404edcSAsim Jamshed 
362*76404edcSAsim Jamshed 							break;
363*76404edcSAsim Jamshed 						} else {
364*76404edcSAsim Jamshed 							/* handler not set -> 500 */
365*76404edcSAsim Jamshed 							ret = -1;
366*76404edcSAsim Jamshed 
367*76404edcSAsim Jamshed 							log_error_write(srv, __FILE__, __LINE__, "s",
368*76404edcSAsim Jamshed 									"a file missing and no handler set");
369*76404edcSAsim Jamshed 
370*76404edcSAsim Jamshed 							break;
371*76404edcSAsim Jamshed 						}
372*76404edcSAsim Jamshed 						break;
373*76404edcSAsim Jamshed 					default:
374*76404edcSAsim Jamshed 						break;
375*76404edcSAsim Jamshed 					}
376*76404edcSAsim Jamshed 				} else {
377*76404edcSAsim Jamshed 					chunkqueue_append_file(con->write_queue, b, 0, sce->st.st_size);
378*76404edcSAsim Jamshed 					if (sce->st.st_mtime > mtime) mtime = sce->st.st_mtime;
379*76404edcSAsim Jamshed 				}
380*76404edcSAsim Jamshed 			} else {
381*76404edcSAsim Jamshed 				/* not a string */
382*76404edcSAsim Jamshed 				ret = -1;
383*76404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "s",
384*76404edcSAsim Jamshed 						"not a string");
385*76404edcSAsim Jamshed 				break;
386*76404edcSAsim Jamshed 			}
387*76404edcSAsim Jamshed 
388*76404edcSAsim Jamshed 			lua_pop(L, 1);  /* removes value'; keeps key' for next iteration */
389*76404edcSAsim Jamshed 		}
390*76404edcSAsim Jamshed 
391*76404edcSAsim Jamshed 		lua_settop(L, curelem - 1);
392*76404edcSAsim Jamshed 
393*76404edcSAsim Jamshed 		if (ret == 0) {
394*76404edcSAsim Jamshed 			data_string *ds;
395*76404edcSAsim Jamshed 			char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
396*76404edcSAsim Jamshed 			buffer tbuf;
397*76404edcSAsim Jamshed 
398*76404edcSAsim Jamshed 			con->file_finished = 1;
399*76404edcSAsim Jamshed 
400*76404edcSAsim Jamshed 			ds = (data_string *)array_get_element(con->response.headers, "Last-Modified");
401*76404edcSAsim Jamshed 
402*76404edcSAsim Jamshed 			/* no Last-Modified specified */
403*76404edcSAsim Jamshed 			if ((mtime) && (NULL == ds)) {
404*76404edcSAsim Jamshed 
405*76404edcSAsim Jamshed 				strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
406*76404edcSAsim Jamshed 
407*76404edcSAsim Jamshed 				response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
408*76404edcSAsim Jamshed 
409*76404edcSAsim Jamshed 
410*76404edcSAsim Jamshed 				tbuf.ptr = timebuf;
411*76404edcSAsim Jamshed 				tbuf.used = sizeof(timebuf);
412*76404edcSAsim Jamshed 				tbuf.size = sizeof(timebuf);
413*76404edcSAsim Jamshed 			} else if (ds) {
414*76404edcSAsim Jamshed 				tbuf.ptr = ds->value->ptr;
415*76404edcSAsim Jamshed 				tbuf.used = ds->value->used;
416*76404edcSAsim Jamshed 				tbuf.size = ds->value->size;
417*76404edcSAsim Jamshed 			} else {
418*76404edcSAsim Jamshed 				tbuf.size = 0;
419*76404edcSAsim Jamshed 				tbuf.used = 0;
420*76404edcSAsim Jamshed 				tbuf.ptr = NULL;
421*76404edcSAsim Jamshed 			}
422*76404edcSAsim Jamshed 
423*76404edcSAsim Jamshed 			if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {
424*76404edcSAsim Jamshed 				/* ok, the client already has our content,
425*76404edcSAsim Jamshed 				 * no need to send it again */
426*76404edcSAsim Jamshed 
427*76404edcSAsim Jamshed 				chunkqueue_reset(con->write_queue);
428*76404edcSAsim Jamshed 				ret = 0; /* cache-hit */
429*76404edcSAsim Jamshed 			}
430*76404edcSAsim Jamshed 		} else {
431*76404edcSAsim Jamshed 			chunkqueue_reset(con->write_queue);
432*76404edcSAsim Jamshed 		}
433*76404edcSAsim Jamshed 	}
434*76404edcSAsim Jamshed 
435*76404edcSAsim Jamshed 	if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
436*76404edcSAsim Jamshed 		/* cache-miss */
437*76404edcSAsim Jamshed 		buffer_copy_string_buffer(con->uri.path, p->baseurl);
438*76404edcSAsim Jamshed 		buffer_append_string_buffer(con->uri.path, p->trigger_handler);
439*76404edcSAsim Jamshed 
440*76404edcSAsim Jamshed 		buffer_copy_string_buffer(con->physical.path, p->basedir);
441*76404edcSAsim Jamshed 		buffer_append_string_buffer(con->physical.path, p->trigger_handler);
442*76404edcSAsim Jamshed 
443*76404edcSAsim Jamshed 		chunkqueue_reset(con->write_queue);
444*76404edcSAsim Jamshed 	}
445*76404edcSAsim Jamshed 
446*76404edcSAsim Jamshed error:
447*76404edcSAsim Jamshed 	lua_close(L);
448*76404edcSAsim Jamshed 
449*76404edcSAsim Jamshed 	stream_close(&rm.st);
450*76404edcSAsim Jamshed 	buffer_free(b);
451*76404edcSAsim Jamshed 
452*76404edcSAsim Jamshed 	return ret /* cache-error */;
453*76404edcSAsim Jamshed }
454*76404edcSAsim Jamshed #else
cache_parse_lua(server * srv,connection * con,plugin_data * p,buffer * fn)455*76404edcSAsim Jamshed int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
456*76404edcSAsim Jamshed 	UNUSED(srv);
457*76404edcSAsim Jamshed 	UNUSED(con);
458*76404edcSAsim Jamshed 	UNUSED(p);
459*76404edcSAsim Jamshed 	UNUSED(fn);
460*76404edcSAsim Jamshed 	/* error */
461*76404edcSAsim Jamshed 	return -1;
462*76404edcSAsim Jamshed }
463*76404edcSAsim Jamshed #endif
464