1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include "mod_lua.h"
19 #include "lua_apr.h"
20 #include "lua_dbd.h"
21 #include "lua_passwd.h"
22 #include "scoreboard.h"
23 #include "util_md5.h"
24 #include "util_script.h"
25 #include "util_varbuf.h"
26 #include "apr_date.h"
27 #include "apr_pools.h"
28 #include "apr_thread_mutex.h"
29 #include "apr_tables.h"
30 #include "util_cookies.h"
31
32 #define APR_WANT_BYTEFUNC
33 #include "apr_want.h"
34
35 extern apr_global_mutex_t* lua_ivm_mutex;
36 extern apr_shm_t *lua_ivm_shm;
37
38 APLOG_USE_MODULE(lua);
39 #define POST_MAX_VARS 500
40
41 #ifndef MODLUA_MAX_REG_MATCH
42 #define MODLUA_MAX_REG_MATCH 25
43 #endif
44
45 typedef char *(*req_field_string_f) (request_rec * r);
46 typedef int (*req_field_int_f) (request_rec * r);
47 typedef req_table_t *(*req_field_apr_table_f) (request_rec * r);
48
49
ap_lua_rstack_dump(lua_State * L,request_rec * r,const char * msg)50 void ap_lua_rstack_dump(lua_State *L, request_rec *r, const char *msg)
51 {
52 int i;
53 int top = lua_gettop(L);
54 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01484) "Lua Stack Dump: [%s]", msg);
55 for (i = 1; i <= top; i++) {
56 int t = lua_type(L, i);
57 switch (t) {
58 case LUA_TSTRING:{
59 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03001)
60 "%d: '%s'", i, lua_tostring(L, i));
61 break;
62 }
63 case LUA_TUSERDATA:{
64 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03002)
65 "%d: userdata", i);
66 break;
67 }
68 case LUA_TLIGHTUSERDATA:{
69 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03003)
70 "%d: lightuserdata", i);
71 break;
72 }
73 case LUA_TNIL:{
74 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03004)
75 "%d: NIL", i);
76 break;
77 }
78 case LUA_TNONE:{
79 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03005)
80 "%d: None", i);
81 break;
82 }
83 case LUA_TBOOLEAN:{
84 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03006)
85 "%d: %s", i,
86 lua_toboolean(L, i) ? "true" : "false");
87 break;
88 }
89 case LUA_TNUMBER:{
90 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03007)
91 "%d: %g", i, lua_tonumber(L, i));
92 break;
93 }
94 case LUA_TTABLE:{
95 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03008)
96 "%d: <table>", i);
97 break;
98 }
99 case LUA_TFUNCTION:{
100 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03009)
101 "%d: <function>", i);
102 break;
103 }
104 default:{
105 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03010)
106 "%d: unknown: -[%s]-", i, lua_typename(L, i));
107 break;
108 }
109 }
110 }
111 }
112
113 /**
114 * Verify that the thing at index is a request_rec wrapping
115 * userdata thingamajig and return it if it is. if it is not
116 * lua will enter its error handling routine.
117 */
ap_lua_check_request_rec(lua_State * L,int index)118 static request_rec *ap_lua_check_request_rec(lua_State *L, int index)
119 {
120 request_rec *r;
121 luaL_checkudata(L, index, "Apache2.Request");
122 r = (request_rec *) lua_unboxpointer(L, index);
123 return r;
124 }
125
126 /* ------------------ request methods -------------------- */
127 /* helper callback for req_parseargs */
req_aprtable2luatable_cb(void * l,const char * key,const char * value)128 static int req_aprtable2luatable_cb(void *l, const char *key,
129 const char *value)
130 {
131 int t;
132 lua_State *L = (lua_State *) l; /* [table<s,t>, table<s,s>] */
133 /* rstack_dump(L, RRR, "start of cb"); */
134 /* L is [table<s,t>, table<s,s>] */
135 /* build complex */
136
137 lua_getfield(L, -1, key); /* [VALUE, table<s,t>, table<s,s>] */
138 /* rstack_dump(L, RRR, "after getfield"); */
139 t = lua_type(L, -1);
140 switch (t) {
141 case LUA_TNIL:
142 case LUA_TNONE:{
143 lua_pop(L, 1); /* [table<s,t>, table<s,s>] */
144 lua_newtable(L); /* [array, table<s,t>, table<s,s>] */
145 lua_pushnumber(L, 1); /* [1, array, table<s,t>, table<s,s>] */
146 lua_pushstring(L, value); /* [string, 1, array, table<s,t>, table<s,s>] */
147 lua_settable(L, -3); /* [array, table<s,t>, table<s,s>] */
148 lua_setfield(L, -2, key); /* [table<s,t>, table<s,s>] */
149 break;
150 }
151 case LUA_TTABLE:{
152 /* [array, table<s,t>, table<s,s>] */
153 int size = lua_rawlen(L, -1);
154 lua_pushnumber(L, size + 1); /* [#, array, table<s,t>, table<s,s>] */
155 lua_pushstring(L, value); /* [string, #, array, table<s,t>, table<s,s>] */
156 lua_settable(L, -3); /* [array, table<s,t>, table<s,s>] */
157 lua_setfield(L, -2, key); /* [table<s,t>, table<s,s>] */
158 break;
159 }
160 }
161
162 /* L is [table<s,t>, table<s,s>] */
163 /* build simple */
164 lua_getfield(L, -2, key); /* [VALUE, table<s,s>, table<s,t>] */
165 if (lua_isnoneornil(L, -1)) { /* only set if not already set */
166 lua_pop(L, 1); /* [table<s,s>, table<s,t>]] */
167 lua_pushstring(L, value); /* [string, table<s,s>, table<s,t>] */
168 lua_setfield(L, -3, key); /* [table<s,s>, table<s,t>] */
169 }
170 else {
171 lua_pop(L, 1);
172 }
173 return 1;
174 }
175
176 /* helper callback for req_parseargs */
req_aprtable2luatable_cb_len(void * l,const char * key,const char * value,size_t len)177 static int req_aprtable2luatable_cb_len(void *l, const char *key,
178 const char *value, size_t len)
179 {
180 int t;
181 lua_State *L = (lua_State *) l; /* [table<s,t>, table<s,s>] */
182 /* rstack_dump(L, RRR, "start of cb"); */
183 /* L is [table<s,t>, table<s,s>] */
184 /* build complex */
185
186 lua_getfield(L, -1, key); /* [VALUE, table<s,t>, table<s,s>] */
187 /* rstack_dump(L, RRR, "after getfield"); */
188 t = lua_type(L, -1);
189 switch (t) {
190 case LUA_TNIL:
191 case LUA_TNONE:{
192 lua_pop(L, 1); /* [table<s,t>, table<s,s>] */
193 lua_newtable(L); /* [array, table<s,t>, table<s,s>] */
194 lua_pushnumber(L, 1); /* [1, array, table<s,t>, table<s,s>] */
195 lua_pushlstring(L, value, len); /* [string, 1, array, table<s,t>, table<s,s>] */
196 lua_settable(L, -3); /* [array, table<s,t>, table<s,s>] */
197 lua_setfield(L, -2, key); /* [table<s,t>, table<s,s>] */
198 break;
199 }
200
201 case LUA_TTABLE:{
202 /* [array, table<s,t>, table<s,s>] */
203 int size = lua_rawlen(L, -1);
204 lua_pushnumber(L, size + 1); /* [#, array, table<s,t>, table<s,s>] */
205 lua_pushlstring(L, value, len); /* [string, #, array, table<s,t>, table<s,s>] */
206 lua_settable(L, -3); /* [array, table<s,t>, table<s,s>] */
207 lua_setfield(L, -2, key); /* [table<s,t>, table<s,s>] */
208 break;
209 }
210 }
211
212 /* L is [table<s,t>, table<s,s>] */
213 /* build simple */
214 lua_getfield(L, -2, key); /* [VALUE, table<s,s>, table<s,t>] */
215 if (lua_isnoneornil(L, -1)) { /* only set if not already set */
216 lua_pop(L, 1); /* [table<s,s>, table<s,t>]] */
217 lua_pushlstring(L, value, len); /* [string, table<s,s>, table<s,t>] */
218 lua_setfield(L, -3, key); /* [table<s,s>, table<s,t>] */
219 }
220 else {
221 lua_pop(L, 1);
222 }
223 return 1;
224 }
225
226
227 /*
228 =======================================================================================================================
229 lua_read_body(request_rec *r, const char **rbuf, apr_off_t *size): Reads any additional form data sent in POST/PUT
230 requests. Used for multipart POST data.
231 =======================================================================================================================
232 */
lua_read_body(request_rec * r,const char ** rbuf,apr_off_t * size,apr_off_t maxsize)233 static int lua_read_body(request_rec *r, const char **rbuf, apr_off_t *size,
234 apr_off_t maxsize)
235 {
236 int rc = OK;
237
238 *rbuf = NULL;
239 *size = 0;
240
241 if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
242 return (rc);
243 }
244 if (ap_should_client_block(r)) {
245
246 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
247 apr_off_t len_read, rpos = 0;
248 apr_off_t length = r->remaining;
249 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
250
251 if (maxsize != 0 && length > maxsize) {
252 return APR_EINCOMPLETE; /* Only room for incomplete data chunk :( */
253 }
254 *rbuf = (const char *) apr_pcalloc(r->pool, (apr_size_t) (length + 1));
255 while ((rpos < length)
256 && (len_read = ap_get_client_block(r, (char *) *rbuf + rpos,
257 length - rpos)) > 0) {
258 rpos += len_read;
259 }
260 if (len_read < 0) {
261 return APR_EINCOMPLETE;
262 }
263 *size = rpos;
264 }
265 else {
266 rc = DONE;
267 }
268
269 return (rc);
270 }
271
272
273 /*
274 * =======================================================================================================================
275 * lua_write_body: Reads any additional form data sent in POST/PUT requests
276 * and writes to a file.
277 * =======================================================================================================================
278 */
lua_write_body(request_rec * r,apr_file_t * file,apr_off_t * size)279 static apr_status_t lua_write_body(request_rec *r, apr_file_t *file, apr_off_t *size)
280 {
281 apr_status_t rc = OK;
282
283 *size = 0;
284
285 if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
286 return rc;
287 if (ap_should_client_block(r)) {
288 char argsbuffer[HUGE_STRING_LEN];
289 apr_off_t rsize,
290 len_read,
291 rpos = 0;
292 apr_off_t length = r->remaining;
293
294 *size = length;
295 while ((len_read =
296 ap_get_client_block(r, argsbuffer,
297 sizeof(argsbuffer))) > 0) {
298 if ((rpos + len_read) > length)
299 rsize = (apr_size_t) length - rpos;
300 else
301 rsize = len_read;
302
303 rc = apr_file_write_full(file, argsbuffer, (apr_size_t) rsize,
304 NULL);
305 if (rc != APR_SUCCESS)
306 return rc;
307 rpos += rsize;
308 }
309 }
310 else {
311 rc = DONE;
312 }
313
314 return rc;
315 }
316
317 /* expose apr_table as (r/o) lua table */
req_aprtable2luatable(lua_State * L,apr_table_t * t)318 static int req_aprtable2luatable(lua_State *L, apr_table_t *t)
319 {
320 lua_newtable(L);
321 lua_newtable(L); /* [table, table] */
322 apr_table_do(req_aprtable2luatable_cb, L, t, NULL);
323 return 2; /* [table<string, string>, table<string, array<string>>] */
324 }
325
req_headers_in_table(lua_State * L)326 static int req_headers_in_table(lua_State *L)
327 {
328 request_rec *r = ap_lua_check_request_rec(L, 1);
329 return req_aprtable2luatable(L, r->headers_in);
330 }
req_headers_out_table(lua_State * L)331 static int req_headers_out_table(lua_State *L)
332 {
333 request_rec *r = ap_lua_check_request_rec(L, 1);
334 return req_aprtable2luatable(L, r->headers_out);
335 }
req_err_headers_out_table(lua_State * L)336 static int req_err_headers_out_table(lua_State *L)
337 {
338 request_rec *r = ap_lua_check_request_rec(L, 1);
339 return req_aprtable2luatable(L, r->err_headers_out);
340 }
req_notes_table(lua_State * L)341 static int req_notes_table(lua_State *L)
342 {
343 request_rec *r = ap_lua_check_request_rec(L, 1);
344 return req_aprtable2luatable(L, r->notes);
345 }
req_subprocess_env_table(lua_State * L)346 static int req_subprocess_env_table(lua_State *L)
347 {
348 request_rec *r = ap_lua_check_request_rec(L, 1);
349 return req_aprtable2luatable(L, r->subprocess_env);
350 }
351 /* r:parseargs() returning a lua table */
req_parseargs(lua_State * L)352 static int req_parseargs(lua_State *L)
353 {
354 apr_table_t *form_table;
355 request_rec *r = ap_lua_check_request_rec(L, 1);
356 lua_newtable(L);
357 lua_newtable(L); /* [table, table] */
358 ap_args_to_table(r, &form_table);
359 apr_table_do(req_aprtable2luatable_cb, L, form_table, NULL);
360 return 2; /* [table<string, string>, table<string, array<string>>] */
361 }
362
363 /* ap_lua_binstrstr: Binary strstr function for uploaded data with NULL bytes */
ap_lua_binstrstr(const char * haystack,size_t hsize,const char * needle,size_t nsize)364 static char* ap_lua_binstrstr (const char * haystack, size_t hsize, const char* needle, size_t nsize)
365 {
366 size_t p;
367 if (haystack == NULL) return NULL;
368 if (needle == NULL) return NULL;
369 if (hsize < nsize) return NULL;
370 for (p = 0; p <= (hsize - nsize); ++p) {
371 if (memcmp(haystack + p, needle, nsize) == 0) {
372 return (char*) (haystack + p);
373 }
374 }
375 return NULL;
376 }
377
378 /* r:parsebody(): Parses regular (url-enocded) or multipart POST data and returns two tables*/
req_parsebody(lua_State * L)379 static int req_parsebody(lua_State *L)
380 {
381 apr_array_header_t *pairs;
382 apr_off_t len;
383 int res;
384 apr_size_t size;
385 apr_size_t max_post_size;
386 char *multipart;
387 const char *contentType;
388 request_rec *r = ap_lua_check_request_rec(L, 1);
389 max_post_size = (apr_size_t) luaL_optinteger(L, 2, MAX_STRING_LEN);
390 multipart = apr_pcalloc(r->pool, 256);
391 contentType = apr_table_get(r->headers_in, "Content-Type");
392 lua_newtable(L);
393 lua_newtable(L); /* [table, table] */
394 if (contentType != NULL && (sscanf(contentType, "multipart/form-data; boundary=%250c", multipart) == 1)) {
395 char *buffer, *key, *filename;
396 char *start = 0, *end = 0, *crlf = 0;
397 const char *data;
398 int i;
399 size_t vlen = 0;
400 size_t len = 0;
401 if (lua_read_body(r, &data, (apr_off_t*) &size, max_post_size) != OK) {
402 return 2;
403 }
404 len = strlen(multipart);
405 i = 0;
406 for
407 (
408 start = strstr((char *) data, multipart);
409 start != NULL;
410 start = end
411 ) {
412 i++;
413 if (i == POST_MAX_VARS) break;
414 crlf = strstr((char *) start, "\r\n\r\n");
415 if (!crlf) break;
416 end = ap_lua_binstrstr(crlf, (size - (crlf - data)), multipart, len);
417 if (end == NULL) break;
418 key = (char *) apr_pcalloc(r->pool, 256);
419 filename = (char *) apr_pcalloc(r->pool, 256);
420 if (end - crlf <= 8) break;
421 vlen = end - crlf - 8;
422 buffer = (char *) apr_pcalloc(r->pool, vlen+1);
423 memcpy(buffer, crlf + 4, vlen);
424 sscanf(start + len + 2,
425 "Content-Disposition: form-data; name=\"%255[^\"]\"; filename=\"%255[^\"]\"",
426 key, filename);
427 if (*key) {
428 req_aprtable2luatable_cb_len(L, key, buffer, vlen);
429 }
430 }
431 }
432 else {
433 char *buffer;
434 res = ap_parse_form_data(r, NULL, &pairs, -1, max_post_size);
435 if (res == OK) {
436 while(pairs && !apr_is_empty_array(pairs)) {
437 ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs);
438 apr_brigade_length(pair->value, 1, &len);
439 size = (apr_size_t) len;
440 buffer = apr_palloc(r->pool, size + 1);
441 apr_brigade_flatten(pair->value, buffer, &size);
442 buffer[len] = 0;
443 req_aprtable2luatable_cb(L, pair->name, buffer);
444 }
445 }
446 }
447 return 2; /* [table<string, string>, table<string, array<string>>] */
448 }
449
450
451 /*
452 * lua_ap_requestbody; r:requestbody([filename]) - Reads or stores the request
453 * body
454 */
lua_ap_requestbody(lua_State * L)455 static int lua_ap_requestbody(lua_State *L)
456 {
457 const char *filename;
458 request_rec *r;
459 apr_off_t maxSize;
460
461 r = ap_lua_check_request_rec(L, 1);
462 filename = luaL_optstring(L, 2, 0);
463 maxSize = (apr_off_t)luaL_optinteger(L, 3, 0);
464
465 if (r) {
466 apr_off_t size;
467 if (maxSize > 0 && r->remaining > maxSize) {
468 lua_pushnil(L);
469 lua_pushliteral(L, "Request body was larger than the permitted size.");
470 return 2;
471 }
472 if (r->method_number != M_POST && r->method_number != M_PUT)
473 return (0);
474 if (!filename) {
475 const char *data;
476
477 if (lua_read_body(r, &data, &size, maxSize) != OK)
478 return (0);
479
480 lua_pushlstring(L, data, (size_t) size);
481 lua_pushinteger(L, (lua_Integer) size);
482 return (2);
483 } else {
484 apr_status_t rc;
485 apr_file_t *file;
486
487 rc = apr_file_open(&file, filename, APR_CREATE | APR_FOPEN_WRITE,
488 APR_FPROT_OS_DEFAULT, r->pool);
489 lua_settop(L, 0);
490 if (rc == APR_SUCCESS) {
491 rc = lua_write_body(r, file, &size);
492 apr_file_close(file);
493 if (rc != OK) {
494 lua_pushboolean(L, 0);
495 return 1;
496 }
497 lua_pushinteger(L, (lua_Integer) size);
498 return (1);
499 } else
500 lua_pushboolean(L, 0);
501 return (1);
502 }
503 }
504
505 return (0);
506 }
507
508 /* wrap ap_rputs as r:puts(String) */
req_puts(lua_State * L)509 static int req_puts(lua_State *L)
510 {
511 request_rec *r = ap_lua_check_request_rec(L, 1);
512
513 int argc = lua_gettop(L);
514 int i;
515
516 for (i = 2; i <= argc; i++) {
517 ap_rputs(luaL_checkstring(L, i), r);
518 }
519 return 0;
520 }
521
522 /* wrap ap_rwrite as r:write(String) */
req_write(lua_State * L)523 static int req_write(lua_State *L)
524 {
525 request_rec *r = ap_lua_check_request_rec(L, 1);
526 size_t n;
527 int rv;
528 const char *buf = luaL_checklstring(L, 2, &n);
529
530 rv = ap_rwrite((void *) buf, n, r);
531 lua_pushinteger(L, rv);
532 return 1;
533 }
534
535 /* r:add_output_filter(name) */
req_add_output_filter(lua_State * L)536 static int req_add_output_filter(lua_State *L)
537 {
538 request_rec *r = ap_lua_check_request_rec(L, 1);
539 const char *name = luaL_checkstring(L, 2);
540 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01485) "adding output filter %s",
541 name);
542 ap_add_output_filter(name, L, r, r->connection);
543 return 0;
544 }
545
546 /* wrap ap_construct_url as r:construct_url(String) */
req_construct_url(lua_State * L)547 static int req_construct_url(lua_State *L)
548 {
549 request_rec *r = ap_lua_check_request_rec(L, 1);
550 const char *name = luaL_checkstring(L, 2);
551 lua_pushstring(L, ap_construct_url(r->pool, name, r));
552 return 1;
553 }
554
555 /* wrap ap_escape_html r:escape_html(String) */
req_escape_html(lua_State * L)556 static int req_escape_html(lua_State *L)
557 {
558 request_rec *r = ap_lua_check_request_rec(L, 1);
559 const char *s = luaL_checkstring(L, 2);
560 lua_pushstring(L, ap_escape_html(r->pool, s));
561 return 1;
562 }
563
564 /* wrap optional ssl_var_lookup as r:ssl_var_lookup(String) */
req_ssl_var_lookup(lua_State * L)565 static int req_ssl_var_lookup(lua_State *L)
566 {
567 request_rec *r = ap_lua_check_request_rec(L, 1);
568 const char *s = luaL_checkstring(L, 2);
569 const char *res = ap_lua_ssl_val(r->pool, r->server, r->connection, r,
570 (char *)s);
571 lua_pushstring(L, res);
572 return 1;
573 }
574
575 /* BEGIN dispatch mathods for request_rec fields */
576
577 /* not really a field, but we treat it like one */
req_document_root(request_rec * r)578 static const char *req_document_root(request_rec *r)
579 {
580 return ap_document_root(r);
581 }
582
req_context_prefix(request_rec * r)583 static const char *req_context_prefix(request_rec *r)
584 {
585 return ap_context_prefix(r);
586 }
587
req_context_document_root(request_rec * r)588 static const char *req_context_document_root(request_rec *r)
589 {
590 return ap_context_document_root(r);
591 }
592
req_uri_field(request_rec * r)593 static char *req_uri_field(request_rec *r)
594 {
595 return r->uri;
596 }
597
req_method_field(request_rec * r)598 static const char *req_method_field(request_rec *r)
599 {
600 return r->method;
601 }
req_handler_field(request_rec * r)602 static const char *req_handler_field(request_rec *r)
603 {
604 return r->handler;
605 }
req_proxyreq_field(request_rec * r)606 static const char *req_proxyreq_field(request_rec *r)
607 {
608 switch (r->proxyreq) {
609 case PROXYREQ_NONE: return "PROXYREQ_NONE";
610 case PROXYREQ_PROXY: return "PROXYREQ_PROXY";
611 case PROXYREQ_REVERSE: return "PROXYREQ_REVERSE";
612 case PROXYREQ_RESPONSE: return "PROXYREQ_RESPONSE";
613 default: return NULL;
614 }
615 }
req_hostname_field(request_rec * r)616 static const char *req_hostname_field(request_rec *r)
617 {
618 return r->hostname;
619 }
620
req_args_field(request_rec * r)621 static const char *req_args_field(request_rec *r)
622 {
623 return r->args;
624 }
625
req_path_info_field(request_rec * r)626 static const char *req_path_info_field(request_rec *r)
627 {
628 return r->path_info;
629 }
630
req_canonical_filename_field(request_rec * r)631 static const char *req_canonical_filename_field(request_rec *r)
632 {
633 return r->canonical_filename;
634 }
635
req_filename_field(request_rec * r)636 static const char *req_filename_field(request_rec *r)
637 {
638 return r->filename;
639 }
640
req_user_field(request_rec * r)641 static const char *req_user_field(request_rec *r)
642 {
643 return r->user;
644 }
645
req_unparsed_uri_field(request_rec * r)646 static const char *req_unparsed_uri_field(request_rec *r)
647 {
648 return r->unparsed_uri;
649 }
650
req_ap_auth_type_field(request_rec * r)651 static const char *req_ap_auth_type_field(request_rec *r)
652 {
653 return r->ap_auth_type;
654 }
655
req_content_encoding_field(request_rec * r)656 static const char *req_content_encoding_field(request_rec *r)
657 {
658 return r->content_encoding;
659 }
660
req_content_type_field(request_rec * r)661 static const char *req_content_type_field(request_rec *r)
662 {
663 return r->content_type;
664 }
665
req_range_field(request_rec * r)666 static const char *req_range_field(request_rec *r)
667 {
668 return r->range;
669 }
670
req_protocol_field(request_rec * r)671 static const char *req_protocol_field(request_rec *r)
672 {
673 return r->protocol;
674 }
675
req_the_request_field(request_rec * r)676 static const char *req_the_request_field(request_rec *r)
677 {
678 return r->the_request;
679 }
680
req_log_id_field(request_rec * r)681 static const char *req_log_id_field(request_rec *r)
682 {
683 return r->log_id;
684 }
685
req_useragent_ip_field(request_rec * r)686 static const char *req_useragent_ip_field(request_rec *r)
687 {
688 return r->useragent_ip;
689 }
690
req_remaining_field(request_rec * r)691 static int req_remaining_field(request_rec *r)
692 {
693 return r->remaining;
694 }
695
req_status_field(request_rec * r)696 static int req_status_field(request_rec *r)
697 {
698 return r->status;
699 }
700
req_assbackwards_field(request_rec * r)701 static int req_assbackwards_field(request_rec *r)
702 {
703 return r->assbackwards;
704 }
705
req_headers_in(request_rec * r)706 static req_table_t* req_headers_in(request_rec *r)
707 {
708 req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t));
709 t->r = r;
710 t->t = r->headers_in;
711 t->n = "headers_in";
712 return t;
713 }
714
req_headers_out(request_rec * r)715 static req_table_t* req_headers_out(request_rec *r)
716 {
717 req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t));
718 t->r = r;
719 t->t = r->headers_out;
720 t->n = "headers_out";
721 return t;
722 }
723
req_err_headers_out(request_rec * r)724 static req_table_t* req_err_headers_out(request_rec *r)
725 {
726 req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t));
727 t->r = r;
728 t->t = r->err_headers_out;
729 t->n = "err_headers_out";
730 return t;
731 }
732
req_subprocess_env(request_rec * r)733 static req_table_t* req_subprocess_env(request_rec *r)
734 {
735 req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t));
736 t->r = r;
737 t->t = r->subprocess_env;
738 t->n = "subprocess_env";
739 return t;
740 }
741
req_notes(request_rec * r)742 static req_table_t* req_notes(request_rec *r)
743 {
744 req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t));
745 t->r = r;
746 t->t = r->notes;
747 t->n = "notes";
748 return t;
749 }
750
req_ssl_is_https_field(request_rec * r)751 static int req_ssl_is_https_field(request_rec *r)
752 {
753 return ap_lua_ssl_is_https(r->connection);
754 }
755
req_ap_get_server_port(request_rec * r)756 static int req_ap_get_server_port(request_rec *r)
757 {
758 return (int) ap_get_server_port(r);
759 }
760
lua_ap_rflush(lua_State * L)761 static int lua_ap_rflush (lua_State *L) {
762
763 int returnValue;
764 request_rec *r;
765 luaL_checktype(L, 1, LUA_TUSERDATA);
766 r = ap_lua_check_request_rec(L, 1);
767 returnValue = ap_rflush(r);
768 lua_pushboolean(L, (returnValue == 0));
769 return 1;
770 }
771
772
lua_ap_options(request_rec * r)773 static const char* lua_ap_options(request_rec* r)
774 {
775 int opts;
776 opts = ap_allow_options(r);
777 return apr_psprintf(r->pool, "%s %s %s %s %s %s", (opts&OPT_INDEXES) ? "Indexes" : "", (opts&OPT_INCLUDES) ? "Includes" : "", (opts&OPT_SYM_LINKS) ? "FollowSymLinks" : "", (opts&OPT_EXECCGI) ? "ExecCGI" : "", (opts&OPT_MULTI) ? "MultiViews" : "", (opts&OPT_ALL) == OPT_ALL ? "All" : "" );
778 }
779
lua_ap_allowoverrides(request_rec * r)780 static const char* lua_ap_allowoverrides(request_rec* r)
781 {
782 int opts;
783 opts = ap_allow_overrides(r);
784 if ( (opts & OR_ALL) == OR_ALL) {
785 return "All";
786 }
787 else if (opts == OR_NONE) {
788 return "None";
789 }
790 return apr_psprintf(r->pool, "%s %s %s %s %s", (opts & OR_LIMIT) ? "Limit" : "", (opts & OR_OPTIONS) ? "Options" : "", (opts & OR_FILEINFO) ? "FileInfo" : "", (opts & OR_AUTHCFG) ? "AuthCfg" : "", (opts & OR_INDEXES) ? "Indexes" : "" );
791
792 }
793
lua_ap_started(request_rec * r)794 static int lua_ap_started(request_rec* r)
795 {
796 return (int)(ap_scoreboard_image->global->restart_time / 1000000);
797 }
798
lua_ap_basic_auth_pw(request_rec * r)799 static const char* lua_ap_basic_auth_pw(request_rec* r)
800 {
801 const char* pw = NULL;
802 ap_get_basic_auth_pw(r, &pw);
803 return pw ? pw : "";
804 }
805
lua_ap_limit_req_body(request_rec * r)806 static int lua_ap_limit_req_body(request_rec* r)
807 {
808 return (int) ap_get_limit_req_body(r);
809 }
810
lua_ap_is_initial_req(request_rec * r)811 static int lua_ap_is_initial_req(request_rec *r)
812 {
813 return ap_is_initial_req(r);
814 }
815
lua_ap_some_auth_required(request_rec * r)816 static int lua_ap_some_auth_required(request_rec *r)
817 {
818 return ap_some_auth_required(r);
819 }
820
lua_ap_sendfile(lua_State * L)821 static int lua_ap_sendfile(lua_State *L)
822 {
823
824 apr_finfo_t file_info;
825 const char *filename;
826 request_rec *r;
827
828 luaL_checktype(L, 1, LUA_TUSERDATA);
829 luaL_checktype(L, 2, LUA_TSTRING);
830 r = ap_lua_check_request_rec(L, 1);
831 filename = lua_tostring(L, 2);
832 apr_stat(&file_info, filename, APR_FINFO_MIN, r->pool);
833 if (file_info.filetype == APR_NOFILE || file_info.filetype == APR_DIR) {
834 lua_pushboolean(L, 0);
835 }
836 else {
837 apr_size_t sent;
838 apr_status_t rc;
839 apr_file_t *file;
840
841 rc = apr_file_open(&file, filename, APR_READ, APR_OS_DEFAULT,
842 r->pool);
843 if (rc == APR_SUCCESS) {
844 ap_send_fd(file, r, 0, (apr_size_t)file_info.size, &sent);
845 apr_file_close(file);
846 lua_pushinteger(L, sent);
847 }
848 else {
849 lua_pushboolean(L, 0);
850 }
851 }
852
853 return (1);
854 }
855
856
857 /*
858 * lua_apr_b64encode; r:encode_base64(string) - encodes a string to Base64
859 * format
860 */
lua_apr_b64encode(lua_State * L)861 static int lua_apr_b64encode(lua_State *L)
862 {
863 const char *plain;
864 char *encoded;
865 size_t plain_len, encoded_len;
866 request_rec *r;
867
868 r = ap_lua_check_request_rec(L, 1);
869 luaL_checktype(L, 2, LUA_TSTRING);
870 plain = lua_tolstring(L, 2, &plain_len);
871 encoded_len = apr_base64_encode_len(plain_len);
872 if (encoded_len) {
873 encoded = apr_palloc(r->pool, encoded_len);
874 encoded_len = apr_base64_encode(encoded, plain, plain_len);
875 if (encoded_len > 0 && encoded[encoded_len - 1] == '\0')
876 encoded_len--;
877 lua_pushlstring(L, encoded, encoded_len);
878 return 1;
879 }
880 return 0;
881 }
882
883 /*
884 * lua_apr_b64decode; r:decode_base64(string) - decodes a Base64 string
885 */
lua_apr_b64decode(lua_State * L)886 static int lua_apr_b64decode(lua_State *L)
887 {
888 const char *encoded;
889 char *plain;
890 size_t encoded_len, decoded_len;
891 request_rec *r;
892
893 r = ap_lua_check_request_rec(L, 1);
894 luaL_checktype(L, 2, LUA_TSTRING);
895 encoded = lua_tolstring(L, 2, &encoded_len);
896 decoded_len = apr_base64_decode_len(encoded);
897 if (decoded_len) {
898 plain = apr_palloc(r->pool, decoded_len);
899 decoded_len = apr_base64_decode(plain, encoded);
900 if (decoded_len > 0 && plain[decoded_len - 1] == '\0')
901 decoded_len--;
902 lua_pushlstring(L, plain, decoded_len);
903 return 1;
904 }
905 return 0;
906 }
907
908 /*
909 * lua_ap_unescape; r:unescape(string) - Unescapes an URL-encoded string
910 */
lua_ap_unescape(lua_State * L)911 static int lua_ap_unescape(lua_State *L)
912 {
913 const char *escaped;
914 char *plain;
915 size_t x,
916 y;
917 request_rec *r;
918 r = ap_lua_check_request_rec(L, 1);
919 luaL_checktype(L, 2, LUA_TSTRING);
920 escaped = lua_tolstring(L, 2, &x);
921 plain = apr_pstrdup(r->pool, escaped);
922 y = ap_unescape_urlencoded(plain);
923 if (!y) {
924 lua_pushstring(L, plain);
925 return 1;
926 }
927 return 0;
928 }
929
930 /*
931 * lua_ap_escape; r:escape(string) - URL-escapes a string
932 */
lua_ap_escape(lua_State * L)933 static int lua_ap_escape(lua_State *L)
934 {
935 const char *plain;
936 char *escaped;
937 size_t x;
938 request_rec *r;
939 r = ap_lua_check_request_rec(L, 1);
940 luaL_checktype(L, 2, LUA_TSTRING);
941 plain = lua_tolstring(L, 2, &x);
942 escaped = ap_escape_urlencoded(r->pool, plain);
943 lua_pushstring(L, escaped);
944 return 1;
945 }
946
947 /*
948 * lua_apr_md5; r:md5(string) - Calculates an MD5 digest of a string
949 */
lua_apr_md5(lua_State * L)950 static int lua_apr_md5(lua_State *L)
951 {
952 const char *buffer;
953 char *result;
954 size_t len;
955 request_rec *r;
956
957 r = ap_lua_check_request_rec(L, 1);
958 luaL_checktype(L, 2, LUA_TSTRING);
959 buffer = lua_tolstring(L, 2, &len);
960 result = ap_md5_binary(r->pool, (const unsigned char *)buffer, len);
961 lua_pushstring(L, result);
962 return 1;
963 }
964
965 /*
966 * lua_apr_sha1; r:sha1(string) - Calculates the SHA1 digest of a string
967 */
lua_apr_sha1(lua_State * L)968 static int lua_apr_sha1(lua_State *L)
969 {
970 unsigned char digest[APR_SHA1_DIGESTSIZE];
971 apr_sha1_ctx_t sha1;
972 const char *buffer;
973 char *result;
974 size_t len;
975 request_rec *r;
976
977 r = ap_lua_check_request_rec(L, 1);
978 luaL_checktype(L, 2, LUA_TSTRING);
979 result = apr_pcalloc(r->pool, sizeof(digest) * 2 + 1);
980 buffer = lua_tolstring(L, 2, &len);
981 apr_sha1_init(&sha1);
982 apr_sha1_update(&sha1, buffer, len);
983 apr_sha1_final(digest, &sha1);
984
985 ap_bin2hex(digest, sizeof(digest), result);
986 lua_pushstring(L, result);
987 return 1;
988 }
989
990 /*
991 * lua_apr_htpassword; r:htpassword(string [, algorithm [, cost]]) - Creates
992 * a htpassword hash from a string
993 */
lua_apr_htpassword(lua_State * L)994 static int lua_apr_htpassword(lua_State *L)
995 {
996 passwd_ctx ctx = { 0 };
997 request_rec *r;
998
999 r = ap_lua_check_request_rec(L, 1);
1000 luaL_checktype(L, 2, LUA_TSTRING);
1001 ctx.passwd = apr_pstrdup(r->pool, lua_tostring(L, 2));
1002 ctx.alg = luaL_optinteger(L, 3, ALG_APMD5);
1003 ctx.cost = luaL_optinteger(L, 4, 0);
1004 ctx.pool = r->pool;
1005 ctx.out = apr_pcalloc(r->pool, MAX_PASSWD_LEN);
1006 ctx.out_len = MAX_PASSWD_LEN;
1007 if (mk_password_hash(&ctx)) {
1008 lua_pushboolean(L, 0);
1009 lua_pushstring(L, ctx.errstr);
1010 return 2;
1011 } else {
1012 lua_pushstring(L, ctx.out);
1013 }
1014 return 1;
1015 }
1016
1017 /*
1018 * lua_apr_touch; r:touch(string [, time]) - Sets mtime of a file
1019 */
lua_apr_touch(lua_State * L)1020 static int lua_apr_touch(lua_State *L)
1021 {
1022 request_rec *r;
1023 const char *path;
1024 apr_status_t status;
1025 apr_time_t mtime;
1026
1027 r = ap_lua_check_request_rec(L, 1);
1028 luaL_checktype(L, 2, LUA_TSTRING);
1029 path = lua_tostring(L, 2);
1030 mtime = (apr_time_t)luaL_optnumber(L, 3, (lua_Number)apr_time_now());
1031 status = apr_file_mtime_set(path, mtime, r->pool);
1032 lua_pushboolean(L, (status == 0));
1033 return 1;
1034 }
1035
1036 /*
1037 * lua_apr_mkdir; r:mkdir(string [, permissions]) - Creates a directory
1038 */
lua_apr_mkdir(lua_State * L)1039 static int lua_apr_mkdir(lua_State *L)
1040 {
1041 request_rec *r;
1042 const char *path;
1043 apr_status_t status;
1044 apr_fileperms_t perms;
1045
1046 r = ap_lua_check_request_rec(L, 1);
1047 luaL_checktype(L, 2, LUA_TSTRING);
1048 path = lua_tostring(L, 2);
1049 perms = luaL_optinteger(L, 3, APR_OS_DEFAULT);
1050 status = apr_dir_make(path, perms, r->pool);
1051 lua_pushboolean(L, (status == 0));
1052 return 1;
1053 }
1054
1055 /*
1056 * lua_apr_mkrdir; r:mkrdir(string [, permissions]) - Creates directories
1057 * recursive
1058 */
lua_apr_mkrdir(lua_State * L)1059 static int lua_apr_mkrdir(lua_State *L)
1060 {
1061 request_rec *r;
1062 const char *path;
1063 apr_status_t status;
1064 apr_fileperms_t perms;
1065
1066 r = ap_lua_check_request_rec(L, 1);
1067 luaL_checktype(L, 2, LUA_TSTRING);
1068 path = lua_tostring(L, 2);
1069 perms = luaL_optinteger(L, 3, APR_OS_DEFAULT);
1070 status = apr_dir_make_recursive(path, perms, r->pool);
1071 lua_pushboolean(L, (status == 0));
1072 return 1;
1073 }
1074
1075 /*
1076 * lua_apr_rmdir; r:rmdir(string) - Removes a directory
1077 */
lua_apr_rmdir(lua_State * L)1078 static int lua_apr_rmdir(lua_State *L)
1079 {
1080 request_rec *r;
1081 const char *path;
1082 apr_status_t status;
1083
1084 r = ap_lua_check_request_rec(L, 1);
1085 luaL_checktype(L, 2, LUA_TSTRING);
1086 path = lua_tostring(L, 2);
1087 status = apr_dir_remove(path, r->pool);
1088 lua_pushboolean(L, (status == 0));
1089 return 1;
1090 }
1091
1092 /*
1093 * lua_apr_date_parse_rfc; r.date_parse_rfc(string) - Parses a DateTime string
1094 */
lua_apr_date_parse_rfc(lua_State * L)1095 static int lua_apr_date_parse_rfc(lua_State *L)
1096 {
1097 const char *input;
1098 apr_time_t result;
1099
1100 luaL_checktype(L, 1, LUA_TSTRING);
1101 input = lua_tostring(L, 1);
1102 result = apr_date_parse_rfc(input);
1103 if (result == 0)
1104 return 0;
1105 lua_pushnumber(L, (lua_Number)(result / APR_USEC_PER_SEC));
1106 return 1;
1107 }
1108
1109 /*
1110 * lua_ap_mpm_query; r:mpm_query(info) - Queries for MPM info
1111 */
lua_ap_mpm_query(lua_State * L)1112 static int lua_ap_mpm_query(lua_State *L)
1113 {
1114 int x,
1115 y;
1116
1117 x = lua_tointeger(L, 1);
1118 ap_mpm_query(x, &y);
1119 lua_pushinteger(L, y);
1120 return 1;
1121 }
1122
1123 /*
1124 * lua_ap_expr; r:expr(string) - Evaluates an expr statement.
1125 */
lua_ap_expr(lua_State * L)1126 static int lua_ap_expr(lua_State *L)
1127 {
1128 request_rec *r;
1129 int x = 0;
1130 const char *expr,
1131 *err;
1132 ap_expr_info_t res;
1133
1134 luaL_checktype(L, 1, LUA_TUSERDATA);
1135 luaL_checktype(L, 2, LUA_TSTRING);
1136 r = ap_lua_check_request_rec(L, 1);
1137 expr = lua_tostring(L, 2);
1138
1139
1140 res.filename = NULL;
1141 res.flags = 0;
1142 res.line_number = 0;
1143 res.module_index = APLOG_MODULE_INDEX;
1144
1145 err = ap_expr_parse(r->pool, r->pool, &res, expr, NULL);
1146 if (!err) {
1147 x = ap_expr_exec(r, &res, &err);
1148 lua_pushboolean(L, x);
1149 if (x < 0) {
1150 lua_pushstring(L, err);
1151 return 2;
1152 }
1153 return 1;
1154 } else {
1155 lua_pushboolean(L, 0);
1156 lua_pushstring(L, err);
1157 return 2;
1158 }
1159 lua_pushboolean(L, 0);
1160 return 1;
1161 }
1162
1163
1164 /*
1165 * lua_ap_regex; r:regex(string, pattern [, flags])
1166 * - Evaluates a regex and returns captures if matched
1167 */
lua_ap_regex(lua_State * L)1168 static int lua_ap_regex(lua_State *L)
1169 {
1170 request_rec *r;
1171 int i,
1172 rv,
1173 flags;
1174 const char *pattern,
1175 *source;
1176 char *err;
1177 ap_regex_t regex;
1178 ap_regmatch_t matches[MODLUA_MAX_REG_MATCH+1];
1179
1180 luaL_checktype(L, 1, LUA_TUSERDATA);
1181 luaL_checktype(L, 2, LUA_TSTRING);
1182 luaL_checktype(L, 3, LUA_TSTRING);
1183 r = ap_lua_check_request_rec(L, 1);
1184 source = lua_tostring(L, 2);
1185 pattern = lua_tostring(L, 3);
1186 flags = luaL_optinteger(L, 4, 0);
1187
1188 rv = ap_regcomp(®ex, pattern, flags);
1189 if (rv) {
1190 lua_pushboolean(L, 0);
1191 err = apr_palloc(r->pool, 256);
1192 ap_regerror(rv, ®ex, err, 256);
1193 lua_pushstring(L, err);
1194 return 2;
1195 }
1196
1197 if (regex.re_nsub > MODLUA_MAX_REG_MATCH) {
1198 lua_pushboolean(L, 0);
1199 err = apr_palloc(r->pool, 64);
1200 apr_snprintf(err, 64,
1201 "regcomp found %d matches; only %d allowed.",
1202 regex.re_nsub, MODLUA_MAX_REG_MATCH);
1203 lua_pushstring(L, err);
1204 return 2;
1205 }
1206
1207 rv = ap_regexec(®ex, source, MODLUA_MAX_REG_MATCH, matches, 0);
1208 if (rv == AP_REG_NOMATCH) {
1209 lua_pushboolean(L, 0);
1210 return 1;
1211 }
1212
1213 lua_newtable(L);
1214 for (i = 0; i <= regex.re_nsub; i++) {
1215 lua_pushinteger(L, i);
1216 if (matches[i].rm_so >= 0 && matches[i].rm_eo >= 0)
1217 lua_pushstring(L,
1218 apr_pstrndup(r->pool, source + matches[i].rm_so,
1219 matches[i].rm_eo - matches[i].rm_so));
1220 else
1221 lua_pushnil(L);
1222 lua_settable(L, -3);
1223
1224 }
1225 return 1;
1226 }
1227
1228
1229
1230
1231 /*
1232 * lua_ap_scoreboard_process; r:scoreboard_process(a) - returns scoreboard info
1233 */
lua_ap_scoreboard_process(lua_State * L)1234 static int lua_ap_scoreboard_process(lua_State *L)
1235 {
1236 int i;
1237 process_score *ps_record;
1238
1239 luaL_checktype(L, 1, LUA_TUSERDATA);
1240 luaL_checktype(L, 2, LUA_TNUMBER);
1241 i = lua_tointeger(L, 2);
1242 ps_record = ap_get_scoreboard_process(i);
1243 if (ps_record) {
1244 lua_newtable(L);
1245
1246 lua_pushstring(L, "connections");
1247 lua_pushnumber(L, ps_record->connections);
1248 lua_settable(L, -3);
1249
1250 lua_pushstring(L, "keepalive");
1251 lua_pushnumber(L, ps_record->keep_alive);
1252 lua_settable(L, -3);
1253
1254 lua_pushstring(L, "lingering_close");
1255 lua_pushnumber(L, ps_record->lingering_close);
1256 lua_settable(L, -3);
1257
1258 lua_pushstring(L, "pid");
1259 lua_pushnumber(L, ps_record->pid);
1260 lua_settable(L, -3);
1261
1262 lua_pushstring(L, "suspended");
1263 lua_pushnumber(L, ps_record->suspended);
1264 lua_settable(L, -3);
1265
1266 lua_pushstring(L, "write_completion");
1267 lua_pushnumber(L, ps_record->write_completion);
1268 lua_settable(L, -3);
1269
1270 lua_pushstring(L, "not_accepting");
1271 lua_pushnumber(L, ps_record->not_accepting);
1272 lua_settable(L, -3);
1273
1274 lua_pushstring(L, "quiescing");
1275 lua_pushnumber(L, ps_record->quiescing);
1276 lua_settable(L, -3);
1277
1278 return 1;
1279 }
1280 return 0;
1281 }
1282
1283 /*
1284 * lua_ap_scoreboard_worker; r:scoreboard_worker(proc, thread) - Returns thread
1285 * info
1286 */
lua_ap_scoreboard_worker(lua_State * L)1287 static int lua_ap_scoreboard_worker(lua_State *L)
1288 {
1289 int i, j;
1290 worker_score *ws_record = NULL;
1291 request_rec *r = NULL;
1292
1293 luaL_checktype(L, 1, LUA_TUSERDATA);
1294 luaL_checktype(L, 2, LUA_TNUMBER);
1295 luaL_checktype(L, 3, LUA_TNUMBER);
1296
1297 r = ap_lua_check_request_rec(L, 1);
1298 if (!r) return 0;
1299
1300 i = lua_tointeger(L, 2);
1301 j = lua_tointeger(L, 3);
1302 ws_record = apr_palloc(r->pool, sizeof *ws_record);
1303
1304 ap_copy_scoreboard_worker(ws_record, i, j);
1305 if (ws_record) {
1306 lua_newtable(L);
1307
1308 lua_pushstring(L, "access_count");
1309 lua_pushnumber(L, ws_record->access_count);
1310 lua_settable(L, -3);
1311
1312 lua_pushstring(L, "bytes_served");
1313 lua_pushnumber(L, (lua_Number) ws_record->bytes_served);
1314 lua_settable(L, -3);
1315
1316 lua_pushstring(L, "client");
1317 lua_pushstring(L, ws_record->client);
1318 lua_settable(L, -3);
1319
1320 lua_pushstring(L, "client64");
1321 lua_pushstring(L, ws_record->client64);
1322 lua_settable(L, -3);
1323
1324 lua_pushstring(L, "conn_bytes");
1325 lua_pushnumber(L, (lua_Number) ws_record->conn_bytes);
1326 lua_settable(L, -3);
1327
1328 lua_pushstring(L, "conn_count");
1329 lua_pushnumber(L, ws_record->conn_count);
1330 lua_settable(L, -3);
1331
1332 lua_pushstring(L, "generation");
1333 lua_pushnumber(L, ws_record->generation);
1334 lua_settable(L, -3);
1335
1336 lua_pushstring(L, "last_used");
1337 lua_pushnumber(L, (lua_Number) ws_record->last_used);
1338 lua_settable(L, -3);
1339
1340 lua_pushstring(L, "pid");
1341 lua_pushnumber(L, ws_record->pid);
1342 lua_settable(L, -3);
1343
1344 lua_pushstring(L, "request");
1345 lua_pushstring(L, ws_record->request);
1346 lua_settable(L, -3);
1347
1348 lua_pushstring(L, "start_time");
1349 lua_pushnumber(L, (lua_Number) ws_record->start_time);
1350 lua_settable(L, -3);
1351
1352 lua_pushstring(L, "status");
1353 lua_pushnumber(L, ws_record->status);
1354 lua_settable(L, -3);
1355
1356 lua_pushstring(L, "stop_time");
1357 lua_pushnumber(L, (lua_Number) ws_record->stop_time);
1358 lua_settable(L, -3);
1359
1360 lua_pushstring(L, "tid");
1361
1362 lua_pushinteger(L, (lua_Integer) ws_record->tid);
1363 lua_settable(L, -3);
1364
1365 lua_pushstring(L, "vhost");
1366 lua_pushstring(L, ws_record->vhost);
1367 lua_settable(L, -3);
1368 #ifdef HAVE_TIMES
1369 lua_pushstring(L, "stimes");
1370 lua_pushnumber(L, ws_record->times.tms_stime);
1371 lua_settable(L, -3);
1372
1373 lua_pushstring(L, "utimes");
1374 lua_pushnumber(L, ws_record->times.tms_utime);
1375 lua_settable(L, -3);
1376 #endif
1377 return 1;
1378 }
1379 return 0;
1380 }
1381
1382 /*
1383 * lua_ap_clock; r:clock() - Returns timestamp with microsecond precision
1384 */
lua_ap_clock(lua_State * L)1385 static int lua_ap_clock(lua_State *L)
1386 {
1387 apr_time_t now;
1388 now = apr_time_now();
1389 lua_pushnumber(L, (lua_Number) now);
1390 return 1;
1391 }
1392
1393 /*
1394 * lua_ap_add_input_filter; r:add_input_filter(name) - Adds an input filter to
1395 * the chain
1396 */
lua_ap_add_input_filter(lua_State * L)1397 static int lua_ap_add_input_filter(lua_State *L)
1398 {
1399 request_rec *r;
1400 const char *filterName;
1401 ap_filter_rec_t *filter;
1402
1403 luaL_checktype(L, 1, LUA_TUSERDATA);
1404 luaL_checktype(L, 2, LUA_TSTRING);
1405 r = ap_lua_check_request_rec(L, 1);
1406 filterName = lua_tostring(L, 2);
1407 filter = ap_get_input_filter_handle(filterName);
1408 if (filter) {
1409 ap_add_input_filter_handle(filter, NULL, r, r->connection);
1410 lua_pushboolean(L, 1);
1411 } else
1412 lua_pushboolean(L, 0);
1413 return 1;
1414 }
1415
1416
1417 /*
1418 * lua_ap_module_info; r:module_info(mod_name) - Returns information about a
1419 * loaded module
1420 */
lua_ap_module_info(lua_State * L)1421 static int lua_ap_module_info(lua_State *L)
1422 {
1423 const char *moduleName;
1424 module *mod;
1425
1426 luaL_checktype(L, 1, LUA_TSTRING);
1427 moduleName = lua_tostring(L, 1);
1428 mod = ap_find_linked_module(moduleName);
1429 if (mod && mod->cmds) {
1430 const command_rec *cmd;
1431 lua_newtable(L);
1432 lua_pushstring(L, "commands");
1433 lua_newtable(L);
1434 for (cmd = mod->cmds; cmd->name; ++cmd) {
1435 lua_pushstring(L, cmd->name);
1436 lua_pushstring(L, cmd->errmsg);
1437 lua_settable(L, -3);
1438 }
1439 lua_settable(L, -3);
1440 return 1;
1441 }
1442 return 0;
1443 }
1444
1445 /*
1446 * lua_ap_runtime_dir_relative: r:runtime_dir_relative(file): Returns the
1447 * filename as relative to the runtime dir
1448 */
lua_ap_runtime_dir_relative(lua_State * L)1449 static int lua_ap_runtime_dir_relative(lua_State *L)
1450 {
1451 request_rec *r;
1452 const char *file;
1453
1454 luaL_checktype(L, 1, LUA_TUSERDATA);
1455 r = ap_lua_check_request_rec(L, 1);
1456 file = luaL_optstring(L, 2, ".");
1457 lua_pushstring(L, ap_runtime_dir_relative(r->pool, file));
1458 return 1;
1459 }
1460
1461 /*
1462 * lua_ap_set_document_root; r:set_document_root(path) - sets the current doc
1463 * root for the request
1464 */
lua_ap_set_document_root(lua_State * L)1465 static int lua_ap_set_document_root(lua_State *L)
1466 {
1467 request_rec *r;
1468 const char *root;
1469
1470 luaL_checktype(L, 1, LUA_TUSERDATA);
1471 luaL_checktype(L, 2, LUA_TSTRING);
1472 r = ap_lua_check_request_rec(L, 1);
1473 root = lua_tostring(L, 2);
1474 ap_set_document_root(r, root);
1475 return 0;
1476 }
1477
1478 /*
1479 * lua_ap_getdir; r:get_direntries(directory) - Gets all entries of a
1480 * directory and returns the directory info as a table
1481 */
lua_ap_getdir(lua_State * L)1482 static int lua_ap_getdir(lua_State *L)
1483 {
1484 request_rec *r;
1485 apr_dir_t *thedir;
1486 apr_finfo_t file_info;
1487 apr_status_t status;
1488 const char *directory;
1489
1490 luaL_checktype(L, 1, LUA_TUSERDATA);
1491 luaL_checktype(L, 2, LUA_TSTRING);
1492 r = ap_lua_check_request_rec(L, 1);
1493 directory = lua_tostring(L, 2);
1494 if (apr_dir_open(&thedir, directory, r->pool) == APR_SUCCESS) {
1495 int i = 0;
1496 lua_newtable(L);
1497 do {
1498 status = apr_dir_read(&file_info, APR_FINFO_NAME, thedir);
1499 if (APR_STATUS_IS_INCOMPLETE(status)) {
1500 continue; /* ignore un-stat()able files */
1501 }
1502 else if (status != APR_SUCCESS) {
1503 break;
1504 }
1505 lua_pushinteger(L, ++i);
1506 lua_pushstring(L, file_info.name);
1507 lua_settable(L, -3);
1508
1509 } while (1);
1510 apr_dir_close(thedir);
1511 return 1;
1512 }
1513 else {
1514 return 0;
1515 }
1516 }
1517
1518 /*
1519 * lua_ap_stat; r:stat(filename [, wanted]) - Runs stat on a file and
1520 * returns the file info as a table
1521 */
lua_ap_stat(lua_State * L)1522 static int lua_ap_stat(lua_State *L)
1523 {
1524 request_rec *r;
1525 const char *filename;
1526 apr_finfo_t file_info;
1527 apr_int32_t wanted;
1528
1529 luaL_checktype(L, 1, LUA_TUSERDATA);
1530 luaL_checktype(L, 2, LUA_TSTRING);
1531 r = ap_lua_check_request_rec(L, 1);
1532 filename = lua_tostring(L, 2);
1533 wanted = luaL_optinteger(L, 3, APR_FINFO_MIN);
1534 if (apr_stat(&file_info, filename, wanted, r->pool) == OK) {
1535 lua_newtable(L);
1536 if (wanted & APR_FINFO_MTIME) {
1537 lua_pushstring(L, "mtime");
1538 lua_pushnumber(L, (lua_Number) file_info.mtime);
1539 lua_settable(L, -3);
1540 }
1541 if (wanted & APR_FINFO_ATIME) {
1542 lua_pushstring(L, "atime");
1543 lua_pushnumber(L, (lua_Number) file_info.atime);
1544 lua_settable(L, -3);
1545 }
1546 if (wanted & APR_FINFO_CTIME) {
1547 lua_pushstring(L, "ctime");
1548 lua_pushnumber(L, (lua_Number) file_info.ctime);
1549 lua_settable(L, -3);
1550 }
1551 if (wanted & APR_FINFO_SIZE) {
1552 lua_pushstring(L, "size");
1553 lua_pushnumber(L, (lua_Number) file_info.size);
1554 lua_settable(L, -3);
1555 }
1556 if (wanted & APR_FINFO_TYPE) {
1557 lua_pushstring(L, "filetype");
1558 lua_pushinteger(L, file_info.filetype);
1559 lua_settable(L, -3);
1560 }
1561 if (wanted & APR_FINFO_PROT) {
1562 lua_pushstring(L, "protection");
1563 lua_pushinteger(L, file_info.protection);
1564 lua_settable(L, -3);
1565 }
1566 return 1;
1567 }
1568 else {
1569 return 0;
1570 }
1571 }
1572
1573 /*
1574 * lua_ap_loaded_modules; r:loaded_modules() - Returns a list of loaded modules
1575 */
lua_ap_loaded_modules(lua_State * L)1576 static int lua_ap_loaded_modules(lua_State *L)
1577 {
1578 int i;
1579 lua_newtable(L);
1580 for (i = 0; ap_loaded_modules[i] && ap_loaded_modules[i]->name; i++) {
1581 lua_pushinteger(L, i + 1);
1582 lua_pushstring(L, ap_loaded_modules[i]->name);
1583 lua_settable(L, -3);
1584 }
1585 return 1;
1586 }
1587
1588 /*
1589 * lua_ap_server_info; r:server_info() - Returns server info, such as the
1590 * executable filename, server root, mpm etc
1591 */
lua_ap_server_info(lua_State * L)1592 static int lua_ap_server_info(lua_State *L)
1593 {
1594 lua_newtable(L);
1595
1596 lua_pushstring(L, "server_executable");
1597 lua_pushstring(L, ap_server_argv0);
1598 lua_settable(L, -3);
1599
1600 lua_pushstring(L, "server_root");
1601 lua_pushstring(L, ap_server_root);
1602 lua_settable(L, -3);
1603
1604 lua_pushstring(L, "scoreboard_fname");
1605 lua_pushstring(L, ap_scoreboard_fname);
1606 lua_settable(L, -3);
1607
1608 lua_pushstring(L, "server_mpm");
1609 lua_pushstring(L, ap_show_mpm());
1610 lua_settable(L, -3);
1611
1612 return 1;
1613 }
1614
1615
1616 /*
1617 * === Auto-scraped functions ===
1618 */
1619
1620
1621 /**
1622 * ap_set_context_info: Set context_prefix and context_document_root.
1623 * @param r The request
1624 * @param prefix the URI prefix, without trailing slash
1625 * @param document_root the corresponding directory on disk, without trailing
1626 * slash
1627 * @note If one of prefix of document_root is NULL, the corrsponding
1628 * property will not be changed.
1629 */
lua_ap_set_context_info(lua_State * L)1630 static int lua_ap_set_context_info(lua_State *L)
1631 {
1632 request_rec *r;
1633 const char *prefix;
1634 const char *document_root;
1635 luaL_checktype(L, 1, LUA_TUSERDATA);
1636 r = ap_lua_check_request_rec(L, 1);
1637 luaL_checktype(L, 2, LUA_TSTRING);
1638 prefix = lua_tostring(L, 2);
1639 luaL_checktype(L, 3, LUA_TSTRING);
1640 document_root = lua_tostring(L, 3);
1641 ap_set_context_info(r, prefix, document_root);
1642 return 0;
1643 }
1644
1645
1646 /**
1647 * ap_os_escape_path (apr_pool_t *p, const char *path, int partial)
1648 * convert an OS path to a URL in an OS dependant way.
1649 * @param p The pool to allocate from
1650 * @param path The path to convert
1651 * @param partial if set, assume that the path will be appended to something
1652 * with a '/' in it (and thus does not prefix "./")
1653 * @return The converted URL
1654 */
lua_ap_os_escape_path(lua_State * L)1655 static int lua_ap_os_escape_path(lua_State *L)
1656 {
1657 char *returnValue;
1658 request_rec *r;
1659 const char *path;
1660 int partial = 0;
1661 luaL_checktype(L, 1, LUA_TUSERDATA);
1662 r = ap_lua_check_request_rec(L, 1);
1663 luaL_checktype(L, 2, LUA_TSTRING);
1664 path = lua_tostring(L, 2);
1665 if (lua_isboolean(L, 3))
1666 partial = lua_toboolean(L, 3);
1667 returnValue = ap_os_escape_path(r->pool, path, partial);
1668 lua_pushstring(L, returnValue);
1669 return 1;
1670 }
1671
1672
1673 /**
1674 * ap_escape_logitem (apr_pool_t *p, const char *str)
1675 * Escape a string for logging
1676 * @param p The pool to allocate from
1677 * @param str The string to escape
1678 * @return The escaped string
1679 */
lua_ap_escape_logitem(lua_State * L)1680 static int lua_ap_escape_logitem(lua_State *L)
1681 {
1682 char *returnValue;
1683 request_rec *r;
1684 const char *str;
1685 luaL_checktype(L, 1, LUA_TUSERDATA);
1686 r = ap_lua_check_request_rec(L, 1);
1687 luaL_checktype(L, 2, LUA_TSTRING);
1688 str = lua_tostring(L, 2);
1689 returnValue = ap_escape_logitem(r->pool, str);
1690 lua_pushstring(L, returnValue);
1691 return 1;
1692 }
1693
1694 /**
1695 * ap_strcmp_match (const char *str, const char *expected)
1696 * Determine if a string matches a pattern containing the wildcards '?' or '*'
1697 * @param str The string to check
1698 * @param expected The pattern to match against
1699 * @param ignoreCase Whether to ignore case when matching
1700 * @return 1 if the two strings match, 0 otherwise
1701 */
lua_ap_strcmp_match(lua_State * L)1702 static int lua_ap_strcmp_match(lua_State *L)
1703 {
1704 int returnValue;
1705 const char *str;
1706 const char *expected;
1707 int ignoreCase = 0;
1708 luaL_checktype(L, 1, LUA_TSTRING);
1709 str = lua_tostring(L, 1);
1710 luaL_checktype(L, 2, LUA_TSTRING);
1711 expected = lua_tostring(L, 2);
1712 if (lua_isboolean(L, 3))
1713 ignoreCase = lua_toboolean(L, 3);
1714 if (!ignoreCase)
1715 returnValue = ap_strcmp_match(str, expected);
1716 else
1717 returnValue = ap_strcasecmp_match(str, expected);
1718 lua_pushboolean(L, (!returnValue));
1719 return 1;
1720 }
1721
1722
1723 /**
1724 * ap_set_keepalive (request_rec *r)
1725 * Set the keepalive status for this request
1726 * @param r The current request
1727 * @return 1 if keepalive can be set, 0 otherwise
1728 */
lua_ap_set_keepalive(lua_State * L)1729 static int lua_ap_set_keepalive(lua_State *L)
1730 {
1731 int returnValue;
1732 request_rec *r;
1733 luaL_checktype(L, 1, LUA_TUSERDATA);
1734 r = ap_lua_check_request_rec(L, 1);
1735 returnValue = ap_set_keepalive(r);
1736 lua_pushboolean(L, returnValue);
1737 return 1;
1738 }
1739
1740 /**
1741 * ap_make_etag (request_rec *r, int force_weak)
1742 * Construct an entity tag from the resource information. If it's a real
1743 * file, build in some of the file characteristics.
1744 * @param r The current request
1745 * @param force_weak Force the entity tag to be weak - it could be modified
1746 * again in as short an interval.
1747 * @return The entity tag
1748 */
lua_ap_make_etag(lua_State * L)1749 static int lua_ap_make_etag(lua_State *L)
1750 {
1751 char *returnValue;
1752 request_rec *r;
1753 int force_weak;
1754 luaL_checktype(L, 1, LUA_TUSERDATA);
1755 r = ap_lua_check_request_rec(L, 1);
1756 luaL_checktype(L, 2, LUA_TBOOLEAN);
1757 force_weak = (int)luaL_optinteger(L, 2, 0);
1758 returnValue = ap_make_etag(r, force_weak);
1759 lua_pushstring(L, returnValue);
1760 return 1;
1761 }
1762
1763
1764
1765 /**
1766 * ap_send_interim_response (request_rec *r, int send_headers)
1767 * Send an interim (HTTP 1xx) response immediately.
1768 * @param r The request
1769 * @param send_headers Whether to send&clear headers in r->headers_out
1770 */
lua_ap_send_interim_response(lua_State * L)1771 static int lua_ap_send_interim_response(lua_State *L)
1772 {
1773 request_rec *r;
1774 int send_headers = 0;
1775 luaL_checktype(L, 1, LUA_TUSERDATA);
1776 r = ap_lua_check_request_rec(L, 1);
1777 if (lua_isboolean(L, 2))
1778 send_headers = lua_toboolean(L, 2);
1779 ap_send_interim_response(r, send_headers);
1780 return 0;
1781 }
1782
1783
1784 /**
1785 * ap_custom_response (request_rec *r, int status, const char *string)
1786 * Install a custom response handler for a given status
1787 * @param r The current request
1788 * @param status The status for which the custom response should be used
1789 * @param string The custom response. This can be a static string, a file
1790 * or a URL
1791 */
lua_ap_custom_response(lua_State * L)1792 static int lua_ap_custom_response(lua_State *L)
1793 {
1794 request_rec *r;
1795 int status;
1796 const char *string;
1797 luaL_checktype(L, 1, LUA_TUSERDATA);
1798 r = ap_lua_check_request_rec(L, 1);
1799 luaL_checktype(L, 2, LUA_TNUMBER);
1800 status = lua_tointeger(L, 2);
1801 luaL_checktype(L, 3, LUA_TSTRING);
1802 string = lua_tostring(L, 3);
1803 ap_custom_response(r, status, string);
1804 return 0;
1805 }
1806
1807
1808 /**
1809 * ap_exists_config_define (const char *name)
1810 * Check for a definition from the server command line
1811 * @param name The define to check for
1812 * @return 1 if defined, 0 otherwise
1813 */
lua_ap_exists_config_define(lua_State * L)1814 static int lua_ap_exists_config_define(lua_State *L)
1815 {
1816 int returnValue;
1817 const char *name;
1818 luaL_checktype(L, 1, LUA_TSTRING);
1819 name = lua_tostring(L, 1);
1820 returnValue = ap_exists_config_define(name);
1821 lua_pushboolean(L, returnValue);
1822 return 1;
1823 }
1824
lua_ap_get_server_name_for_url(lua_State * L)1825 static int lua_ap_get_server_name_for_url(lua_State *L)
1826 {
1827 const char *servername;
1828 request_rec *r;
1829 luaL_checktype(L, 1, LUA_TUSERDATA);
1830 r = ap_lua_check_request_rec(L, 1);
1831 servername = ap_get_server_name_for_url(r);
1832 lua_pushstring(L, servername);
1833 return 1;
1834 }
1835
1836 /* ap_state_query (int query_code) item starts a new field */
lua_ap_state_query(lua_State * L)1837 static int lua_ap_state_query(lua_State *L)
1838 {
1839
1840 int returnValue;
1841 int query_code;
1842 luaL_checktype(L, 1, LUA_TNUMBER);
1843 query_code = lua_tointeger(L, 1);
1844 returnValue = ap_state_query(query_code);
1845 lua_pushinteger(L, returnValue);
1846 return 1;
1847 }
1848
1849 /*
1850 * lua_ap_usleep; r:usleep(microseconds)
1851 * - Sleep for the specified number of microseconds.
1852 */
lua_ap_usleep(lua_State * L)1853 static int lua_ap_usleep(lua_State *L)
1854 {
1855 apr_interval_time_t msec;
1856 luaL_checktype(L, 1, LUA_TNUMBER);
1857 msec = (apr_interval_time_t)lua_tonumber(L, 1);
1858 apr_sleep(msec);
1859 return 0;
1860 }
1861
1862 /* END dispatch methods for request_rec fields */
1863
req_dispatch(lua_State * L)1864 static int req_dispatch(lua_State *L)
1865 {
1866 apr_hash_t *dispatch;
1867 req_fun_t *rft;
1868 request_rec *r = ap_lua_check_request_rec(L, 1);
1869 const char *name = luaL_checkstring(L, 2);
1870 lua_pop(L, 2);
1871
1872 lua_getfield(L, LUA_REGISTRYINDEX, "Apache2.Request.dispatch");
1873 dispatch = lua_touserdata(L, 1);
1874 lua_pop(L, 1);
1875
1876 rft = apr_hash_get(dispatch, name, APR_HASH_KEY_STRING);
1877 if (rft) {
1878 switch (rft->type) {
1879 case APL_REQ_FUNTYPE_TABLE:{
1880 req_table_t *rs;
1881 req_field_apr_table_f func = (req_field_apr_table_f)rft->fun;
1882 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01486)
1883 "request_rec->dispatching %s -> apr table",
1884 name);
1885 rs = (*func)(r);
1886 ap_lua_push_apr_table(L, rs);
1887 return 1;
1888 }
1889
1890 case APL_REQ_FUNTYPE_LUACFUN:{
1891 lua_CFunction func = (lua_CFunction)rft->fun;
1892 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01487)
1893 "request_rec->dispatching %s -> lua_CFunction",
1894 name);
1895 lua_pushcfunction(L, func);
1896 return 1;
1897 }
1898 case APL_REQ_FUNTYPE_STRING:{
1899 req_field_string_f func = (req_field_string_f)rft->fun;
1900 char *rs;
1901 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01488)
1902 "request_rec->dispatching %s -> string", name);
1903 rs = (*func) (r);
1904 lua_pushstring(L, rs);
1905 return 1;
1906 }
1907 case APL_REQ_FUNTYPE_INT:{
1908 req_field_int_f func = (req_field_int_f)rft->fun;
1909 int rs;
1910 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01489)
1911 "request_rec->dispatching %s -> int", name);
1912 rs = (*func) (r);
1913 lua_pushinteger(L, rs);
1914 return 1;
1915 }
1916 case APL_REQ_FUNTYPE_BOOLEAN:{
1917 req_field_int_f func = (req_field_int_f)rft->fun;
1918 int rs;
1919 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01490)
1920 "request_rec->dispatching %s -> boolean", name);
1921 rs = (*func) (r);
1922 lua_pushboolean(L, rs);
1923 return 1;
1924 }
1925 }
1926 }
1927
1928 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01491) "nothing for %s", name);
1929 return 0;
1930 }
1931
1932 /* helper function for the logging functions below */
req_log_at(lua_State * L,int level)1933 static int req_log_at(lua_State *L, int level)
1934 {
1935 const char *msg;
1936 request_rec *r = ap_lua_check_request_rec(L, 1);
1937 lua_Debug dbg;
1938
1939 lua_getstack(L, 1, &dbg);
1940 lua_getinfo(L, "Sl", &dbg);
1941
1942 msg = luaL_checkstring(L, 2);
1943 /* Intentional no APLOGNO */
1944 ap_log_rerror(dbg.source, dbg.currentline, APLOG_MODULE_INDEX, level, 0,
1945 r, "%s", msg);
1946 return 0;
1947 }
1948
1949 /* r:debug(String) and friends which use apache logging */
req_emerg(lua_State * L)1950 static int req_emerg(lua_State *L)
1951 {
1952 return req_log_at(L, APLOG_EMERG);
1953 }
req_alert(lua_State * L)1954 static int req_alert(lua_State *L)
1955 {
1956 return req_log_at(L, APLOG_ALERT);
1957 }
req_crit(lua_State * L)1958 static int req_crit(lua_State *L)
1959 {
1960 return req_log_at(L, APLOG_CRIT);
1961 }
req_err(lua_State * L)1962 static int req_err(lua_State *L)
1963 {
1964 return req_log_at(L, APLOG_ERR);
1965 }
req_warn(lua_State * L)1966 static int req_warn(lua_State *L)
1967 {
1968 return req_log_at(L, APLOG_WARNING);
1969 }
req_notice(lua_State * L)1970 static int req_notice(lua_State *L)
1971 {
1972 return req_log_at(L, APLOG_NOTICE);
1973 }
req_info(lua_State * L)1974 static int req_info(lua_State *L)
1975 {
1976 return req_log_at(L, APLOG_INFO);
1977 }
req_debug(lua_State * L)1978 static int req_debug(lua_State *L)
1979 {
1980 return req_log_at(L, APLOG_DEBUG);
1981 }
1982
lua_ivm_get(lua_State * L)1983 static int lua_ivm_get(lua_State *L)
1984 {
1985 const char *key, *raw_key;
1986 apr_pool_t *pool;
1987 lua_ivm_object *object = NULL;
1988 request_rec *r = ap_lua_check_request_rec(L, 1);
1989 key = luaL_checkstring(L, 2);
1990 raw_key = apr_pstrcat(r->pool, "lua_ivm_", key, NULL);
1991 apr_global_mutex_lock(lua_ivm_mutex);
1992 pool = *((apr_pool_t**) apr_shm_baseaddr_get(lua_ivm_shm));
1993 apr_pool_userdata_get((void **)&object, raw_key, pool);
1994 if (object) {
1995 if (object->type == LUA_TBOOLEAN) lua_pushboolean(L, (int) object->number);
1996 else if (object->type == LUA_TNUMBER) lua_pushnumber(L, object->number);
1997 else if (object->type == LUA_TSTRING) lua_pushlstring(L, object->vb.buf, object->size);
1998 apr_global_mutex_unlock(lua_ivm_mutex);
1999 return 1;
2000 }
2001 else {
2002 apr_global_mutex_unlock(lua_ivm_mutex);
2003 return 0;
2004 }
2005 }
2006
2007
lua_ivm_set(lua_State * L)2008 static int lua_ivm_set(lua_State *L)
2009 {
2010 const char *key, *raw_key;
2011 const char *value = NULL;
2012 apr_pool_t *pool;
2013 size_t str_len;
2014 lua_ivm_object *object = NULL;
2015 request_rec *r = ap_lua_check_request_rec(L, 1);
2016 key = luaL_checkstring(L, 2);
2017 luaL_checkany(L, 3);
2018 raw_key = apr_pstrcat(r->pool, "lua_ivm_", key, NULL);
2019
2020 apr_global_mutex_lock(lua_ivm_mutex);
2021 pool = *((apr_pool_t**) apr_shm_baseaddr_get(lua_ivm_shm));
2022 apr_pool_userdata_get((void **)&object, raw_key, pool);
2023 if (!object) {
2024 object = apr_pcalloc(pool, sizeof(lua_ivm_object));
2025 ap_varbuf_init(pool, &object->vb, 2);
2026 object->size = 1;
2027 object->vb_size = 1;
2028 }
2029 object->type = lua_type(L, 3);
2030 if (object->type == LUA_TNUMBER) object->number = lua_tonumber(L, 3);
2031 else if (object->type == LUA_TBOOLEAN) object->number = lua_tonumber(L, 3);
2032 else if (object->type == LUA_TSTRING) {
2033 value = lua_tolstring(L, 3, &str_len);
2034 str_len++; /* add trailing \0 */
2035 if ( str_len > object->vb_size) {
2036 ap_varbuf_grow(&object->vb, str_len);
2037 object->vb_size = str_len;
2038 }
2039 object->size = str_len-1;
2040 memset(object->vb.buf, 0, str_len);
2041 memcpy(object->vb.buf, value, str_len-1);
2042 }
2043 apr_pool_userdata_set(object, raw_key, NULL, pool);
2044 apr_global_mutex_unlock(lua_ivm_mutex);
2045 return 0;
2046 }
2047
lua_get_cookie(lua_State * L)2048 static int lua_get_cookie(lua_State *L)
2049 {
2050 const char *key, *cookie;
2051 request_rec *r = ap_lua_check_request_rec(L, 1);
2052 key = luaL_checkstring(L, 2);
2053 cookie = NULL;
2054 ap_cookie_read(r, key, &cookie, 0);
2055 if (cookie != NULL) {
2056 lua_pushstring(L, cookie);
2057 return 1;
2058 }
2059 return 0;
2060 }
2061
lua_set_cookie(lua_State * L)2062 static int lua_set_cookie(lua_State *L)
2063 {
2064 const char *key, *value, *out, *path = "", *domain = "";
2065 const char *strexpires = "", *strdomain = "", *strpath = "";
2066 int secure = 0, expires = 0, httponly = 0;
2067 char cdate[APR_RFC822_DATE_LEN+1];
2068 apr_status_t rv;
2069 request_rec *r = ap_lua_check_request_rec(L, 1);
2070
2071 /* New >= 2.4.8 method: */
2072 if (lua_istable(L, 2)) {
2073
2074 /* key */
2075 lua_pushstring(L, "key");
2076 lua_gettable(L, -2);
2077 key = luaL_checkstring(L, -1);
2078 lua_pop(L, 1);
2079
2080 /* value */
2081 lua_pushstring(L, "value");
2082 lua_gettable(L, -2);
2083 value = luaL_checkstring(L, -1);
2084 lua_pop(L, 1);
2085
2086 /* expiry */
2087 lua_pushstring(L, "expires");
2088 lua_gettable(L, -2);
2089 expires = (int)luaL_optinteger(L, -1, 0);
2090 lua_pop(L, 1);
2091
2092 /* secure */
2093 lua_pushstring(L, "secure");
2094 lua_gettable(L, -2);
2095 if (lua_isboolean(L, -1)) {
2096 secure = lua_toboolean(L, -1);
2097 }
2098 lua_pop(L, 1);
2099
2100 /* httponly */
2101 lua_pushstring(L, "httponly");
2102 lua_gettable(L, -2);
2103 if (lua_isboolean(L, -1)) {
2104 httponly = lua_toboolean(L, -1);
2105 }
2106 lua_pop(L, 1);
2107
2108 /* path */
2109 lua_pushstring(L, "path");
2110 lua_gettable(L, -2);
2111 path = luaL_optstring(L, -1, "/");
2112 lua_pop(L, 1);
2113
2114 /* domain */
2115 lua_pushstring(L, "domain");
2116 lua_gettable(L, -2);
2117 domain = luaL_optstring(L, -1, "");
2118 lua_pop(L, 1);
2119 }
2120 /* Old <= 2.4.7 method: */
2121 else {
2122 key = luaL_checkstring(L, 2);
2123 value = luaL_checkstring(L, 3);
2124 secure = 0;
2125 if (lua_isboolean(L, 4)) {
2126 secure = lua_toboolean(L, 4);
2127 }
2128 expires = luaL_optinteger(L, 5, 0);
2129 }
2130
2131 /* Calculate expiry if set */
2132 if (expires > 0) {
2133 rv = apr_rfc822_date(cdate, apr_time_from_sec(expires));
2134 if (rv == APR_SUCCESS) {
2135 strexpires = apr_psprintf(r->pool, "Expires=%s;", cdate);
2136 }
2137 }
2138
2139 /* Create path segment */
2140 if (path != NULL && strlen(path) > 0) {
2141 strpath = apr_psprintf(r->pool, "Path=%s;", path);
2142 }
2143
2144 /* Create domain segment */
2145 if (domain != NULL && strlen(domain) > 0) {
2146 /* Domain does NOT like quotes in most browsers, so let's avoid that */
2147 strdomain = apr_psprintf(r->pool, "Domain=%s;", domain);
2148 }
2149
2150 /* URL-encode key/value */
2151 value = ap_escape_urlencoded(r->pool, value);
2152 key = ap_escape_urlencoded(r->pool, key);
2153
2154 /* Create the header */
2155 out = apr_psprintf(r->pool, "%s=%s; %s %s %s %s %s", key, value,
2156 secure ? "Secure;" : "",
2157 expires ? strexpires : "",
2158 httponly ? "HttpOnly;" : "",
2159 *strdomain ? strdomain : "",
2160 *strpath ? strpath : "");
2161
2162 apr_table_add(r->err_headers_out, "Set-Cookie", out);
2163 return 0;
2164 }
2165
ap_ntoh64(const apr_uint64_t * input)2166 static apr_uint64_t ap_ntoh64(const apr_uint64_t *input)
2167 {
2168 apr_uint64_t rval;
2169 unsigned char *data = (unsigned char *)&rval;
2170 if (APR_IS_BIGENDIAN) {
2171 return *input;
2172 }
2173
2174 data[0] = *input >> 56;
2175 data[1] = *input >> 48;
2176 data[2] = *input >> 40;
2177 data[3] = *input >> 32;
2178 data[4] = *input >> 24;
2179 data[5] = *input >> 16;
2180 data[6] = *input >> 8;
2181 data[7] = *input >> 0;
2182
2183 return rval;
2184 }
2185
lua_websocket_greet(lua_State * L)2186 static int lua_websocket_greet(lua_State *L)
2187 {
2188 const char *key = NULL;
2189 unsigned char digest[APR_SHA1_DIGESTSIZE];
2190 apr_sha1_ctx_t sha1;
2191 char *encoded;
2192 int encoded_len;
2193 request_rec *r = ap_lua_check_request_rec(L, 1);
2194 key = apr_table_get(r->headers_in, "Sec-WebSocket-Key");
2195 if (key != NULL) {
2196 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03011)
2197 "Websocket: Got websocket key: %s", key);
2198 key = apr_pstrcat(r->pool, key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
2199 NULL);
2200 apr_sha1_init(&sha1);
2201 apr_sha1_update(&sha1, key, strlen(key));
2202 apr_sha1_final(digest, &sha1);
2203 encoded_len = apr_base64_encode_len(APR_SHA1_DIGESTSIZE);
2204 if (encoded_len) {
2205 encoded = apr_palloc(r->pool, encoded_len);
2206 encoded_len = apr_base64_encode(encoded, (char*) digest, APR_SHA1_DIGESTSIZE);
2207 r->status = 101;
2208 apr_table_setn(r->headers_out, "Upgrade", "websocket");
2209 apr_table_setn(r->headers_out, "Connection", "Upgrade");
2210 apr_table_setn(r->headers_out, "Sec-WebSocket-Accept", encoded);
2211
2212 /* Trick httpd into NOT using the chunked filter, IMPORTANT!!!111*/
2213 apr_table_setn(r->headers_out, "Transfer-Encoding", "chunked");
2214
2215 r->clength = 0;
2216 r->bytes_sent = 0;
2217 r->read_chunked = 0;
2218 ap_rflush(r);
2219 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03012)
2220 "Websocket: Upgraded from HTTP to Websocket");
2221 lua_pushboolean(L, 1);
2222 return 1;
2223 }
2224 }
2225 ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02666)
2226 "Websocket: Upgrade from HTTP to Websocket failed");
2227 return 0;
2228 }
2229
lua_websocket_readbytes(conn_rec * c,char * buffer,apr_off_t len)2230 static apr_status_t lua_websocket_readbytes(conn_rec* c, char* buffer,
2231 apr_off_t len)
2232 {
2233 apr_bucket_brigade *brigade = apr_brigade_create(c->pool, c->bucket_alloc);
2234 apr_status_t rv;
2235 rv = ap_get_brigade(c->input_filters, brigade, AP_MODE_READBYTES,
2236 APR_BLOCK_READ, len);
2237 if (rv == APR_SUCCESS) {
2238 if (!APR_BRIGADE_EMPTY(brigade)) {
2239 apr_bucket* bucket = APR_BRIGADE_FIRST(brigade);
2240 const char* data = NULL;
2241 apr_size_t data_length = 0;
2242 rv = apr_bucket_read(bucket, &data, &data_length, APR_BLOCK_READ);
2243 if (rv == APR_SUCCESS) {
2244 memcpy(buffer, data, len);
2245 }
2246 apr_bucket_delete(bucket);
2247 }
2248 }
2249 apr_brigade_cleanup(brigade);
2250 return rv;
2251 }
2252
lua_websocket_peek(lua_State * L)2253 static int lua_websocket_peek(lua_State *L)
2254 {
2255 apr_status_t rv;
2256 apr_bucket_brigade *brigade;
2257
2258 request_rec *r = ap_lua_check_request_rec(L, 1);
2259
2260 brigade = apr_brigade_create(r->connection->pool,
2261 r->connection->bucket_alloc);
2262 rv = ap_get_brigade(r->connection->input_filters, brigade,
2263 AP_MODE_READBYTES, APR_NONBLOCK_READ, 1);
2264 if (rv == APR_SUCCESS) {
2265 lua_pushboolean(L, 1);
2266 }
2267 else {
2268 lua_pushboolean(L, 0);
2269 }
2270 apr_brigade_cleanup(brigade);
2271 return 1;
2272 }
2273
lua_websocket_read(lua_State * L)2274 static int lua_websocket_read(lua_State *L)
2275 {
2276 apr_socket_t *sock;
2277 apr_status_t rv;
2278 int do_read = 1;
2279 int n = 0;
2280 apr_size_t len = 1;
2281 apr_size_t plen = 0;
2282 unsigned short payload_short = 0;
2283 apr_uint64_t payload_long = 0;
2284 unsigned char *mask_bytes;
2285 char byte;
2286 int plaintext;
2287
2288
2289 request_rec *r = ap_lua_check_request_rec(L, 1);
2290 plaintext = ap_lua_ssl_is_https(r->connection) ? 0 : 1;
2291
2292
2293 mask_bytes = apr_pcalloc(r->pool, 4);
2294 sock = ap_get_conn_socket(r->connection);
2295
2296 while (do_read) {
2297 do_read = 0;
2298 /* Get opcode and FIN bit */
2299 if (plaintext) {
2300 rv = apr_socket_recv(sock, &byte, &len);
2301 }
2302 else {
2303 rv = lua_websocket_readbytes(r->connection, &byte, 1);
2304 }
2305 if (rv == APR_SUCCESS) {
2306 unsigned char ubyte, fin, opcode, mask, payload;
2307 ubyte = (unsigned char)byte;
2308 /* fin bit is the first bit */
2309 fin = ubyte >> (CHAR_BIT - 1);
2310 /* opcode is the last four bits (there's 3 reserved bits we don't care about) */
2311 opcode = ubyte & 0xf;
2312
2313 /* Get the payload length and mask bit */
2314 if (plaintext) {
2315 rv = apr_socket_recv(sock, &byte, &len);
2316 }
2317 else {
2318 rv = lua_websocket_readbytes(r->connection, &byte, 1);
2319 }
2320 if (rv == APR_SUCCESS) {
2321 ubyte = (unsigned char)byte;
2322 /* Mask is the first bit */
2323 mask = ubyte >> (CHAR_BIT - 1);
2324 /* Payload is the last 7 bits */
2325 payload = ubyte & 0x7f;
2326 plen = payload;
2327
2328 /* Extended payload? */
2329 if (payload == 126) {
2330 len = 2;
2331 if (plaintext) {
2332 /* XXX: apr_socket_recv does not receive len bits, only up to len bits! */
2333 rv = apr_socket_recv(sock, (char*) &payload_short, &len);
2334 }
2335 else {
2336 rv = lua_websocket_readbytes(r->connection,
2337 (char*) &payload_short, 2);
2338 }
2339 payload_short = ntohs(payload_short);
2340
2341 if (rv == APR_SUCCESS) {
2342 plen = payload_short;
2343 }
2344 else {
2345 return 0;
2346 }
2347 }
2348 /* Super duper extended payload? */
2349 if (payload == 127) {
2350 len = 8;
2351 if (plaintext) {
2352 rv = apr_socket_recv(sock, (char*) &payload_long, &len);
2353 }
2354 else {
2355 rv = lua_websocket_readbytes(r->connection,
2356 (char*) &payload_long, 8);
2357 }
2358 if (rv == APR_SUCCESS) {
2359 plen = ap_ntoh64(&payload_long);
2360 }
2361 else {
2362 return 0;
2363 }
2364 }
2365 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03210)
2366 "Websocket: Reading %" APR_SIZE_T_FMT " (%s) bytes, masking is %s. %s",
2367 plen,
2368 (payload >= 126) ? "extra payload" : "no extra payload",
2369 mask ? "on" : "off",
2370 fin ? "This is a final frame" : "more to follow");
2371 if (mask) {
2372 len = 4;
2373 if (plaintext) {
2374 rv = apr_socket_recv(sock, (char*) mask_bytes, &len);
2375 }
2376 else {
2377 rv = lua_websocket_readbytes(r->connection,
2378 (char*) mask_bytes, 4);
2379 }
2380 if (rv != APR_SUCCESS) {
2381 return 0;
2382 }
2383 }
2384 if (plen < (HUGE_STRING_LEN*1024) && plen > 0) {
2385 apr_size_t remaining = plen;
2386 apr_size_t received;
2387 apr_off_t at = 0;
2388 char *buffer = apr_palloc(r->pool, plen+1);
2389 buffer[plen] = 0;
2390
2391 if (plaintext) {
2392 while (remaining > 0) {
2393 received = remaining;
2394 rv = apr_socket_recv(sock, buffer+at, &received);
2395 if (received > 0 ) {
2396 remaining -= received;
2397 at += received;
2398 }
2399 }
2400 ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
2401 "Websocket: Frame contained %" APR_OFF_T_FMT " bytes, pushed to Lua stack",
2402 at);
2403 }
2404 else {
2405 rv = lua_websocket_readbytes(r->connection, buffer,
2406 remaining);
2407 ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
2408 "Websocket: SSL Frame contained %" APR_SIZE_T_FMT " bytes, "\
2409 "pushed to Lua stack",
2410 remaining);
2411 }
2412 if (mask) {
2413 for (n = 0; n < plen; n++) {
2414 buffer[n] ^= mask_bytes[n%4];
2415 }
2416 }
2417
2418 lua_pushlstring(L, buffer, (size_t) plen); /* push to stack */
2419 lua_pushboolean(L, fin); /* push FIN bit to stack as boolean */
2420 return 2;
2421 }
2422
2423
2424 /* Decide if we need to react to the opcode or not */
2425 if (opcode == 0x09) { /* ping */
2426 char frame[2];
2427 plen = 2;
2428 frame[0] = 0x8A;
2429 frame[1] = 0;
2430 apr_socket_send(sock, frame, &plen); /* Pong! */
2431 do_read = 1;
2432 }
2433 }
2434 }
2435 }
2436 return 0;
2437 }
2438
2439
lua_websocket_write(lua_State * L)2440 static int lua_websocket_write(lua_State *L)
2441 {
2442 const char *string;
2443 apr_status_t rv;
2444 size_t len;
2445 int raw = 0;
2446 char prelude;
2447 request_rec *r = ap_lua_check_request_rec(L, 1);
2448
2449 if (lua_isboolean(L, 3)) {
2450 raw = lua_toboolean(L, 3);
2451 }
2452 string = lua_tolstring(L, 2, &len);
2453
2454 if (raw != 1) {
2455 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03013)
2456 "Websocket: Writing framed message to client");
2457
2458 prelude = 0x81; /* text frame, FIN */
2459 ap_rputc(prelude, r);
2460 if (len < 126) {
2461 ap_rputc(len, r);
2462 }
2463 else if (len < 65535) {
2464 apr_uint16_t slen = len;
2465 ap_rputc(126, r);
2466 slen = htons(slen);
2467 ap_rwrite((char*) &slen, 2, r);
2468 }
2469 else {
2470 apr_uint64_t llen = len;
2471 ap_rputc(127, r);
2472 llen = ap_ntoh64(&llen); /* ntoh doubles as hton */
2473 ap_rwrite((char*) &llen, 8, r);
2474 }
2475 }
2476 else {
2477 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03014)
2478 "Websocket: Writing raw message to client");
2479 }
2480 ap_rwrite(string, len, r);
2481 rv = ap_rflush(r);
2482 if (rv == APR_SUCCESS) {
2483 lua_pushboolean(L, 1);
2484 }
2485 else {
2486 lua_pushboolean(L, 0);
2487 }
2488 return 1;
2489 }
2490
2491
lua_websocket_close(lua_State * L)2492 static int lua_websocket_close(lua_State *L)
2493 {
2494 apr_socket_t *sock;
2495 char prelude[2];
2496 request_rec *r = ap_lua_check_request_rec(L, 1);
2497
2498 sock = ap_get_conn_socket(r->connection);
2499
2500 /* Send a header that says: socket is closing. */
2501 prelude[0] = 0x88; /* closing socket opcode */
2502 prelude[1] = 0; /* zero length frame */
2503 ap_rwrite(prelude, 2, r);
2504
2505 /* Close up tell the MPM and filters to back off */
2506 apr_socket_close(sock);
2507 r->output_filters = NULL;
2508 r->connection->keepalive = AP_CONN_CLOSE;
2509 return 0;
2510 }
2511
lua_websocket_ping(lua_State * L)2512 static int lua_websocket_ping(lua_State *L)
2513 {
2514 apr_socket_t *sock;
2515 apr_size_t plen;
2516 char prelude[2];
2517 apr_status_t rv;
2518 request_rec *r = ap_lua_check_request_rec(L, 1);
2519 sock = ap_get_conn_socket(r->connection);
2520
2521 /* Send a header that says: PING. */
2522 prelude[0] = 0x89; /* ping opcode */
2523 prelude[1] = 0;
2524 plen = 2;
2525 apr_socket_send(sock, prelude, &plen);
2526
2527
2528 /* Get opcode and FIN bit from pong */
2529 plen = 2;
2530 rv = apr_socket_recv(sock, prelude, &plen);
2531 if (rv == APR_SUCCESS) {
2532 unsigned char opcode = prelude[0];
2533 unsigned char len = prelude[1];
2534 unsigned char mask = len >> 7;
2535 if (mask) len -= 128;
2536 plen = len;
2537 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03015)
2538 "Websocket: Got PONG opcode: %x", opcode);
2539 if (opcode == 0x8A) {
2540 lua_pushboolean(L, 1);
2541 }
2542 else {
2543 lua_pushboolean(L, 0);
2544 }
2545 if (plen > 0) {
2546 ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
2547 "Websocket: Reading %" APR_SIZE_T_FMT " bytes of PONG", plen);
2548 return 1;
2549 }
2550 if (mask) {
2551 plen = 2;
2552 apr_socket_recv(sock, prelude, &plen);
2553 plen = 2;
2554 apr_socket_recv(sock, prelude, &plen);
2555 }
2556 }
2557 else {
2558 lua_pushboolean(L, 0);
2559 }
2560 return 1;
2561 }
2562
2563
2564 #define APLUA_REQ_TRACE(lev) static int req_trace##lev(lua_State *L) \
2565 { \
2566 return req_log_at(L, APLOG_TRACE##lev); \
2567 }
2568
2569 APLUA_REQ_TRACE(1)
2570 APLUA_REQ_TRACE(2)
2571 APLUA_REQ_TRACE(3)
2572 APLUA_REQ_TRACE(4)
2573 APLUA_REQ_TRACE(5)
2574 APLUA_REQ_TRACE(6)
2575 APLUA_REQ_TRACE(7)
2576 APLUA_REQ_TRACE(8)
2577
2578 /* handle r.status = 201 */
req_newindex(lua_State * L)2579 static int req_newindex(lua_State *L)
2580 {
2581 const char *key;
2582 /* request_rec* r = lua_touserdata(L, lua_upvalueindex(1)); */
2583 /* const char* key = luaL_checkstring(L, -2); */
2584 request_rec *r = ap_lua_check_request_rec(L, 1);
2585 key = luaL_checkstring(L, 2);
2586
2587 if (0 == strcmp("args", key)) {
2588 const char *value = luaL_checkstring(L, 3);
2589 r->args = apr_pstrdup(r->pool, value);
2590 return 0;
2591 }
2592
2593 if (0 == strcmp("content_type", key)) {
2594 const char *value = luaL_checkstring(L, 3);
2595 ap_set_content_type(r, apr_pstrdup(r->pool, value));
2596 return 0;
2597 }
2598
2599 if (0 == strcmp("filename", key)) {
2600 const char *value = luaL_checkstring(L, 3);
2601 r->filename = apr_pstrdup(r->pool, value);
2602 return 0;
2603 }
2604
2605 if (0 == strcmp("handler", key)) {
2606 const char *value = luaL_checkstring(L, 3);
2607 r->handler = apr_pstrdup(r->pool, value);
2608 return 0;
2609 }
2610
2611 if (0 == strcmp("proxyreq", key)) {
2612 int value = luaL_checkinteger(L, 3);
2613 r->proxyreq = value;
2614 return 0;
2615 }
2616
2617 if (0 == strcmp("status", key)) {
2618 int code = luaL_checkinteger(L, 3);
2619 r->status = code;
2620 return 0;
2621 }
2622
2623 if (0 == strcmp("uri", key)) {
2624 const char *value = luaL_checkstring(L, 3);
2625 r->uri = apr_pstrdup(r->pool, value);
2626 return 0;
2627 }
2628
2629 if (0 == strcmp("user", key)) {
2630 const char *value = luaL_checkstring(L, 3);
2631 r->user = apr_pstrdup(r->pool, value);
2632 return 0;
2633 }
2634
2635 lua_pushstring(L,
2636 apr_psprintf(r->pool,
2637 "Property [%s] may not be set on a request_rec",
2638 key));
2639 lua_error(L);
2640 return 0;
2641 }
2642
2643
2644
2645 /* helper function for walking config trees */
read_cfg_tree(lua_State * L,request_rec * r,ap_directive_t * rcfg)2646 static void read_cfg_tree(lua_State *L, request_rec *r, ap_directive_t *rcfg) {
2647 int x = 0;
2648 const char* value;
2649 ap_directive_t *cfg;
2650 lua_newtable(L);
2651
2652 for (cfg = rcfg; cfg; cfg = cfg->next) {
2653 x++;
2654 lua_pushnumber(L, x);
2655 lua_newtable(L);
2656 value = apr_psprintf(r->pool, "%s %s", cfg->directive, cfg->args);
2657 lua_pushstring(L, "directive");
2658 lua_pushstring(L, value);
2659 lua_settable(L, -3);
2660 lua_pushstring(L, "file");
2661 lua_pushstring(L, cfg->filename);
2662 lua_settable(L, -3);
2663 lua_pushstring(L, "line");
2664 lua_pushnumber(L, cfg->line_num);
2665 lua_settable(L, -3);
2666 if (cfg->first_child) {
2667 lua_pushstring(L, "children");
2668 read_cfg_tree(L, r, cfg->first_child);
2669 lua_settable(L, -3);
2670 }
2671 lua_settable(L, -3);
2672 }
2673 }
2674
lua_ap_get_config(lua_State * L)2675 static int lua_ap_get_config(lua_State *L) {
2676 request_rec *r = ap_lua_check_request_rec(L, 1);
2677 read_cfg_tree(L, r, ap_conftree);
2678
2679 return 1;
2680 }
2681
2682
2683 /* Hack, hack, hack...! TODO: Make this actually work properly */
lua_ap_get_active_config(lua_State * L)2684 static int lua_ap_get_active_config(lua_State *L) {
2685 ap_directive_t *subdir;
2686 ap_directive_t *dir = ap_conftree;
2687 request_rec *r = ap_lua_check_request_rec(L, 1);
2688
2689 for (dir = ap_conftree; dir; dir = dir->next) {
2690 if (ap_strcasestr(dir->directive, "<virtualhost") && dir->first_child) {
2691 for (subdir = dir->first_child; subdir; subdir = subdir->next) {
2692 if (ap_strcasecmp_match(subdir->directive, "servername") &&
2693 !ap_strcasecmp_match(r->hostname, subdir->args)) {
2694 read_cfg_tree(L, r, dir->first_child);
2695 return 1;
2696 }
2697 if (ap_strcasecmp_match(subdir->directive, "serveralias") &&
2698 !ap_strcasecmp_match(r->hostname, subdir->args)) {
2699 read_cfg_tree(L, r, dir->first_child);
2700 return 1;
2701 }
2702 }
2703 }
2704 }
2705 return 0;
2706 }
2707
2708
2709
2710 static const struct luaL_Reg request_methods[] = {
2711 {"__index", req_dispatch},
2712 {"__newindex", req_newindex},
2713 /* {"__newindex", req_set_field}, */
2714 {NULL, NULL}
2715 };
2716
2717
2718 static const struct luaL_Reg connection_methods[] = {
2719 {NULL, NULL}
2720 };
2721
lua_ap_auth_name(request_rec * r)2722 static const char* lua_ap_auth_name(request_rec* r)
2723 {
2724 const char *name;
2725 name = ap_auth_name(r);
2726 return name ? name : "";
2727 }
2728
lua_ap_get_server_name(request_rec * r)2729 static const char* lua_ap_get_server_name(request_rec* r)
2730 {
2731 const char *name;
2732 name = ap_get_server_name(r);
2733 return name ? name : "localhost";
2734 }
2735
2736
2737
2738
2739 static const struct luaL_Reg server_methods[] = {
2740 {NULL, NULL}
2741 };
2742
2743
makefun(const void * fun,int type,apr_pool_t * pool)2744 static req_fun_t *makefun(const void *fun, int type, apr_pool_t *pool)
2745 {
2746 req_fun_t *rft = apr_palloc(pool, sizeof(req_fun_t));
2747 rft->fun = fun;
2748 rft->type = type;
2749 return rft;
2750 }
2751
ap_lua_load_request_lmodule(lua_State * L,apr_pool_t * p)2752 void ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p)
2753 {
2754
2755 apr_hash_t *dispatch = apr_hash_make(p);
2756
2757 apr_hash_set(dispatch, "puts", APR_HASH_KEY_STRING,
2758 makefun(&req_puts, APL_REQ_FUNTYPE_LUACFUN, p));
2759 apr_hash_set(dispatch, "write", APR_HASH_KEY_STRING,
2760 makefun(&req_write, APL_REQ_FUNTYPE_LUACFUN, p));
2761 apr_hash_set(dispatch, "document_root", APR_HASH_KEY_STRING,
2762 makefun(&req_document_root, APL_REQ_FUNTYPE_STRING, p));
2763 apr_hash_set(dispatch, "context_prefix", APR_HASH_KEY_STRING,
2764 makefun(&req_context_prefix, APL_REQ_FUNTYPE_STRING, p));
2765 apr_hash_set(dispatch, "context_document_root", APR_HASH_KEY_STRING,
2766 makefun(&req_context_document_root, APL_REQ_FUNTYPE_STRING, p));
2767 apr_hash_set(dispatch, "parseargs", APR_HASH_KEY_STRING,
2768 makefun(&req_parseargs, APL_REQ_FUNTYPE_LUACFUN, p));
2769 apr_hash_set(dispatch, "parsebody", APR_HASH_KEY_STRING,
2770 makefun(&req_parsebody, APL_REQ_FUNTYPE_LUACFUN, p));
2771 apr_hash_set(dispatch, "debug", APR_HASH_KEY_STRING,
2772 makefun(&req_debug, APL_REQ_FUNTYPE_LUACFUN, p));
2773 apr_hash_set(dispatch, "info", APR_HASH_KEY_STRING,
2774 makefun(&req_info, APL_REQ_FUNTYPE_LUACFUN, p));
2775 apr_hash_set(dispatch, "notice", APR_HASH_KEY_STRING,
2776 makefun(&req_notice, APL_REQ_FUNTYPE_LUACFUN, p));
2777 apr_hash_set(dispatch, "warn", APR_HASH_KEY_STRING,
2778 makefun(&req_warn, APL_REQ_FUNTYPE_LUACFUN, p));
2779 apr_hash_set(dispatch, "err", APR_HASH_KEY_STRING,
2780 makefun(&req_err, APL_REQ_FUNTYPE_LUACFUN, p));
2781 apr_hash_set(dispatch, "crit", APR_HASH_KEY_STRING,
2782 makefun(&req_crit, APL_REQ_FUNTYPE_LUACFUN, p));
2783 apr_hash_set(dispatch, "alert", APR_HASH_KEY_STRING,
2784 makefun(&req_alert, APL_REQ_FUNTYPE_LUACFUN, p));
2785 apr_hash_set(dispatch, "emerg", APR_HASH_KEY_STRING,
2786 makefun(&req_emerg, APL_REQ_FUNTYPE_LUACFUN, p));
2787 apr_hash_set(dispatch, "trace1", APR_HASH_KEY_STRING,
2788 makefun(&req_trace1, APL_REQ_FUNTYPE_LUACFUN, p));
2789 apr_hash_set(dispatch, "trace2", APR_HASH_KEY_STRING,
2790 makefun(&req_trace2, APL_REQ_FUNTYPE_LUACFUN, p));
2791 apr_hash_set(dispatch, "trace3", APR_HASH_KEY_STRING,
2792 makefun(&req_trace3, APL_REQ_FUNTYPE_LUACFUN, p));
2793 apr_hash_set(dispatch, "trace4", APR_HASH_KEY_STRING,
2794 makefun(&req_trace4, APL_REQ_FUNTYPE_LUACFUN, p));
2795 apr_hash_set(dispatch, "trace5", APR_HASH_KEY_STRING,
2796 makefun(&req_trace5, APL_REQ_FUNTYPE_LUACFUN, p));
2797 apr_hash_set(dispatch, "trace6", APR_HASH_KEY_STRING,
2798 makefun(&req_trace6, APL_REQ_FUNTYPE_LUACFUN, p));
2799 apr_hash_set(dispatch, "trace7", APR_HASH_KEY_STRING,
2800 makefun(&req_trace7, APL_REQ_FUNTYPE_LUACFUN, p));
2801 apr_hash_set(dispatch, "trace8", APR_HASH_KEY_STRING,
2802 makefun(&req_trace8, APL_REQ_FUNTYPE_LUACFUN, p));
2803 apr_hash_set(dispatch, "add_output_filter", APR_HASH_KEY_STRING,
2804 makefun(&req_add_output_filter, APL_REQ_FUNTYPE_LUACFUN, p));
2805 apr_hash_set(dispatch, "construct_url", APR_HASH_KEY_STRING,
2806 makefun(&req_construct_url, APL_REQ_FUNTYPE_LUACFUN, p));
2807 apr_hash_set(dispatch, "escape_html", APR_HASH_KEY_STRING,
2808 makefun(&req_escape_html, APL_REQ_FUNTYPE_LUACFUN, p));
2809 apr_hash_set(dispatch, "ssl_var_lookup", APR_HASH_KEY_STRING,
2810 makefun(&req_ssl_var_lookup, APL_REQ_FUNTYPE_LUACFUN, p));
2811 apr_hash_set(dispatch, "is_https", APR_HASH_KEY_STRING,
2812 makefun(&req_ssl_is_https_field, APL_REQ_FUNTYPE_BOOLEAN, p));
2813 apr_hash_set(dispatch, "assbackwards", APR_HASH_KEY_STRING,
2814 makefun(&req_assbackwards_field, APL_REQ_FUNTYPE_BOOLEAN, p));
2815 apr_hash_set(dispatch, "status", APR_HASH_KEY_STRING,
2816 makefun(&req_status_field, APL_REQ_FUNTYPE_INT, p));
2817 apr_hash_set(dispatch, "protocol", APR_HASH_KEY_STRING,
2818 makefun(&req_protocol_field, APL_REQ_FUNTYPE_STRING, p));
2819 apr_hash_set(dispatch, "range", APR_HASH_KEY_STRING,
2820 makefun(&req_range_field, APL_REQ_FUNTYPE_STRING, p));
2821 apr_hash_set(dispatch, "content_type", APR_HASH_KEY_STRING,
2822 makefun(&req_content_type_field, APL_REQ_FUNTYPE_STRING, p));
2823 apr_hash_set(dispatch, "content_encoding", APR_HASH_KEY_STRING,
2824 makefun(&req_content_encoding_field, APL_REQ_FUNTYPE_STRING,
2825 p));
2826 apr_hash_set(dispatch, "ap_auth_type", APR_HASH_KEY_STRING,
2827 makefun(&req_ap_auth_type_field, APL_REQ_FUNTYPE_STRING, p));
2828 apr_hash_set(dispatch, "unparsed_uri", APR_HASH_KEY_STRING,
2829 makefun(&req_unparsed_uri_field, APL_REQ_FUNTYPE_STRING, p));
2830 apr_hash_set(dispatch, "user", APR_HASH_KEY_STRING,
2831 makefun(&req_user_field, APL_REQ_FUNTYPE_STRING, p));
2832 apr_hash_set(dispatch, "filename", APR_HASH_KEY_STRING,
2833 makefun(&req_filename_field, APL_REQ_FUNTYPE_STRING, p));
2834 apr_hash_set(dispatch, "canonical_filename", APR_HASH_KEY_STRING,
2835 makefun(&req_canonical_filename_field,
2836 APL_REQ_FUNTYPE_STRING, p));
2837 apr_hash_set(dispatch, "path_info", APR_HASH_KEY_STRING,
2838 makefun(&req_path_info_field, APL_REQ_FUNTYPE_STRING, p));
2839 apr_hash_set(dispatch, "args", APR_HASH_KEY_STRING,
2840 makefun(&req_args_field, APL_REQ_FUNTYPE_STRING, p));
2841 apr_hash_set(dispatch, "handler", APR_HASH_KEY_STRING,
2842 makefun(&req_handler_field, APL_REQ_FUNTYPE_STRING, p));
2843 apr_hash_set(dispatch, "hostname", APR_HASH_KEY_STRING,
2844 makefun(&req_hostname_field, APL_REQ_FUNTYPE_STRING, p));
2845 apr_hash_set(dispatch, "uri", APR_HASH_KEY_STRING,
2846 makefun(&req_uri_field, APL_REQ_FUNTYPE_STRING, p));
2847 apr_hash_set(dispatch, "the_request", APR_HASH_KEY_STRING,
2848 makefun(&req_the_request_field, APL_REQ_FUNTYPE_STRING, p));
2849 apr_hash_set(dispatch, "log_id", APR_HASH_KEY_STRING,
2850 makefun(&req_log_id_field, APL_REQ_FUNTYPE_STRING, p));
2851 apr_hash_set(dispatch, "useragent_ip", APR_HASH_KEY_STRING,
2852 makefun(&req_useragent_ip_field, APL_REQ_FUNTYPE_STRING, p));
2853 apr_hash_set(dispatch, "method", APR_HASH_KEY_STRING,
2854 makefun(&req_method_field, APL_REQ_FUNTYPE_STRING, p));
2855 apr_hash_set(dispatch, "proxyreq", APR_HASH_KEY_STRING,
2856 makefun(&req_proxyreq_field, APL_REQ_FUNTYPE_STRING, p));
2857 apr_hash_set(dispatch, "headers_in", APR_HASH_KEY_STRING,
2858 makefun(&req_headers_in, APL_REQ_FUNTYPE_TABLE, p));
2859 apr_hash_set(dispatch, "headers_in_table", APR_HASH_KEY_STRING,
2860 makefun(&req_headers_in_table, APL_REQ_FUNTYPE_LUACFUN, p));
2861 apr_hash_set(dispatch, "headers_out", APR_HASH_KEY_STRING,
2862 makefun(&req_headers_out, APL_REQ_FUNTYPE_TABLE, p));
2863 apr_hash_set(dispatch, "headers_out_table", APR_HASH_KEY_STRING,
2864 makefun(&req_headers_out_table, APL_REQ_FUNTYPE_LUACFUN, p));
2865 apr_hash_set(dispatch, "err_headers_out", APR_HASH_KEY_STRING,
2866 makefun(&req_err_headers_out, APL_REQ_FUNTYPE_TABLE, p));
2867 apr_hash_set(dispatch, "err_headers_out_table", APR_HASH_KEY_STRING,
2868 makefun(&req_err_headers_out_table, APL_REQ_FUNTYPE_LUACFUN, p));
2869 apr_hash_set(dispatch, "notes", APR_HASH_KEY_STRING,
2870 makefun(&req_notes, APL_REQ_FUNTYPE_TABLE, p));
2871 apr_hash_set(dispatch, "notes_table", APR_HASH_KEY_STRING,
2872 makefun(&req_notes_table, APL_REQ_FUNTYPE_LUACFUN, p));
2873 apr_hash_set(dispatch, "subprocess_env", APR_HASH_KEY_STRING,
2874 makefun(&req_subprocess_env, APL_REQ_FUNTYPE_TABLE, p));
2875 apr_hash_set(dispatch, "subprocess_env_table", APR_HASH_KEY_STRING,
2876 makefun(&req_subprocess_env_table, APL_REQ_FUNTYPE_LUACFUN, p));
2877 apr_hash_set(dispatch, "flush", APR_HASH_KEY_STRING,
2878 makefun(&lua_ap_rflush, APL_REQ_FUNTYPE_LUACFUN, p));
2879 apr_hash_set(dispatch, "port", APR_HASH_KEY_STRING,
2880 makefun(&req_ap_get_server_port, APL_REQ_FUNTYPE_INT, p));
2881 apr_hash_set(dispatch, "banner", APR_HASH_KEY_STRING,
2882 makefun(&ap_get_server_banner, APL_REQ_FUNTYPE_STRING, p));
2883 apr_hash_set(dispatch, "options", APR_HASH_KEY_STRING,
2884 makefun(&lua_ap_options, APL_REQ_FUNTYPE_STRING, p));
2885 apr_hash_set(dispatch, "allowoverrides", APR_HASH_KEY_STRING,
2886 makefun(&lua_ap_allowoverrides, APL_REQ_FUNTYPE_STRING, p));
2887 apr_hash_set(dispatch, "started", APR_HASH_KEY_STRING,
2888 makefun(&lua_ap_started, APL_REQ_FUNTYPE_INT, p));
2889 apr_hash_set(dispatch, "basic_auth_pw", APR_HASH_KEY_STRING,
2890 makefun(&lua_ap_basic_auth_pw, APL_REQ_FUNTYPE_STRING, p));
2891 apr_hash_set(dispatch, "limit_req_body", APR_HASH_KEY_STRING,
2892 makefun(&lua_ap_limit_req_body, APL_REQ_FUNTYPE_INT, p));
2893 apr_hash_set(dispatch, "server_built", APR_HASH_KEY_STRING,
2894 makefun(&ap_get_server_built, APL_REQ_FUNTYPE_STRING, p));
2895 apr_hash_set(dispatch, "is_initial_req", APR_HASH_KEY_STRING,
2896 makefun(&lua_ap_is_initial_req, APL_REQ_FUNTYPE_BOOLEAN, p));
2897 apr_hash_set(dispatch, "remaining", APR_HASH_KEY_STRING,
2898 makefun(&req_remaining_field, APL_REQ_FUNTYPE_INT, p));
2899 apr_hash_set(dispatch, "some_auth_required", APR_HASH_KEY_STRING,
2900 makefun(&lua_ap_some_auth_required, APL_REQ_FUNTYPE_BOOLEAN, p));
2901 apr_hash_set(dispatch, "server_name", APR_HASH_KEY_STRING,
2902 makefun(&lua_ap_get_server_name, APL_REQ_FUNTYPE_STRING, p));
2903 apr_hash_set(dispatch, "auth_name", APR_HASH_KEY_STRING,
2904 makefun(&lua_ap_auth_name, APL_REQ_FUNTYPE_STRING, p));
2905 apr_hash_set(dispatch, "sendfile", APR_HASH_KEY_STRING,
2906 makefun(&lua_ap_sendfile, APL_REQ_FUNTYPE_LUACFUN, p));
2907 apr_hash_set(dispatch, "dbacquire", APR_HASH_KEY_STRING,
2908 makefun(&lua_db_acquire, APL_REQ_FUNTYPE_LUACFUN, p));
2909 apr_hash_set(dispatch, "stat", APR_HASH_KEY_STRING,
2910 makefun(&lua_ap_stat, APL_REQ_FUNTYPE_LUACFUN, p));
2911 apr_hash_set(dispatch, "get_direntries", APR_HASH_KEY_STRING,
2912 makefun(&lua_ap_getdir, APL_REQ_FUNTYPE_LUACFUN, p));
2913 apr_hash_set(dispatch, "regex", APR_HASH_KEY_STRING,
2914 makefun(&lua_ap_regex, APL_REQ_FUNTYPE_LUACFUN, p));
2915 apr_hash_set(dispatch, "usleep", APR_HASH_KEY_STRING,
2916 makefun(&lua_ap_usleep, APL_REQ_FUNTYPE_LUACFUN, p));
2917 apr_hash_set(dispatch, "base64_encode", APR_HASH_KEY_STRING,
2918 makefun(&lua_apr_b64encode, APL_REQ_FUNTYPE_LUACFUN, p));
2919 apr_hash_set(dispatch, "base64_decode", APR_HASH_KEY_STRING,
2920 makefun(&lua_apr_b64decode, APL_REQ_FUNTYPE_LUACFUN, p));
2921 apr_hash_set(dispatch, "md5", APR_HASH_KEY_STRING,
2922 makefun(&lua_apr_md5, APL_REQ_FUNTYPE_LUACFUN, p));
2923 apr_hash_set(dispatch, "sha1", APR_HASH_KEY_STRING,
2924 makefun(&lua_apr_sha1, APL_REQ_FUNTYPE_LUACFUN, p));
2925 apr_hash_set(dispatch, "htpassword", APR_HASH_KEY_STRING,
2926 makefun(&lua_apr_htpassword, APL_REQ_FUNTYPE_LUACFUN, p));
2927 apr_hash_set(dispatch, "touch", APR_HASH_KEY_STRING,
2928 makefun(&lua_apr_touch, APL_REQ_FUNTYPE_LUACFUN, p));
2929 apr_hash_set(dispatch, "mkdir", APR_HASH_KEY_STRING,
2930 makefun(&lua_apr_mkdir, APL_REQ_FUNTYPE_LUACFUN, p));
2931 apr_hash_set(dispatch, "mkrdir", APR_HASH_KEY_STRING,
2932 makefun(&lua_apr_mkrdir, APL_REQ_FUNTYPE_LUACFUN, p));
2933 apr_hash_set(dispatch, "rmdir", APR_HASH_KEY_STRING,
2934 makefun(&lua_apr_rmdir, APL_REQ_FUNTYPE_LUACFUN, p));
2935 apr_hash_set(dispatch, "date_parse_rfc", APR_HASH_KEY_STRING,
2936 makefun(&lua_apr_date_parse_rfc, APL_REQ_FUNTYPE_LUACFUN, p));
2937 apr_hash_set(dispatch, "escape", APR_HASH_KEY_STRING,
2938 makefun(&lua_ap_escape, APL_REQ_FUNTYPE_LUACFUN, p));
2939 apr_hash_set(dispatch, "unescape", APR_HASH_KEY_STRING,
2940 makefun(&lua_ap_unescape, APL_REQ_FUNTYPE_LUACFUN, p));
2941 apr_hash_set(dispatch, "mpm_query", APR_HASH_KEY_STRING,
2942 makefun(&lua_ap_mpm_query, APL_REQ_FUNTYPE_LUACFUN, p));
2943 apr_hash_set(dispatch, "expr", APR_HASH_KEY_STRING,
2944 makefun(&lua_ap_expr, APL_REQ_FUNTYPE_LUACFUN, p));
2945 apr_hash_set(dispatch, "scoreboard_process", APR_HASH_KEY_STRING,
2946 makefun(&lua_ap_scoreboard_process, APL_REQ_FUNTYPE_LUACFUN, p));
2947 apr_hash_set(dispatch, "scoreboard_worker", APR_HASH_KEY_STRING,
2948 makefun(&lua_ap_scoreboard_worker, APL_REQ_FUNTYPE_LUACFUN, p));
2949 apr_hash_set(dispatch, "clock", APR_HASH_KEY_STRING,
2950 makefun(&lua_ap_clock, APL_REQ_FUNTYPE_LUACFUN, p));
2951 apr_hash_set(dispatch, "requestbody", APR_HASH_KEY_STRING,
2952 makefun(&lua_ap_requestbody, APL_REQ_FUNTYPE_LUACFUN, p));
2953 apr_hash_set(dispatch, "add_input_filter", APR_HASH_KEY_STRING,
2954 makefun(&lua_ap_add_input_filter, APL_REQ_FUNTYPE_LUACFUN, p));
2955 apr_hash_set(dispatch, "module_info", APR_HASH_KEY_STRING,
2956 makefun(&lua_ap_module_info, APL_REQ_FUNTYPE_LUACFUN, p));
2957 apr_hash_set(dispatch, "loaded_modules", APR_HASH_KEY_STRING,
2958 makefun(&lua_ap_loaded_modules, APL_REQ_FUNTYPE_LUACFUN, p));
2959 apr_hash_set(dispatch, "runtime_dir_relative", APR_HASH_KEY_STRING,
2960 makefun(&lua_ap_runtime_dir_relative, APL_REQ_FUNTYPE_LUACFUN, p));
2961 apr_hash_set(dispatch, "server_info", APR_HASH_KEY_STRING,
2962 makefun(&lua_ap_server_info, APL_REQ_FUNTYPE_LUACFUN, p));
2963 apr_hash_set(dispatch, "set_document_root", APR_HASH_KEY_STRING,
2964 makefun(&lua_ap_set_document_root, APL_REQ_FUNTYPE_LUACFUN, p));
2965 apr_hash_set(dispatch, "set_context_info", APR_HASH_KEY_STRING,
2966 makefun(&lua_ap_set_context_info, APL_REQ_FUNTYPE_LUACFUN, p));
2967 apr_hash_set(dispatch, "os_escape_path", APR_HASH_KEY_STRING,
2968 makefun(&lua_ap_os_escape_path, APL_REQ_FUNTYPE_LUACFUN, p));
2969 apr_hash_set(dispatch, "escape_logitem", APR_HASH_KEY_STRING,
2970 makefun(&lua_ap_escape_logitem, APL_REQ_FUNTYPE_LUACFUN, p));
2971 apr_hash_set(dispatch, "strcmp_match", APR_HASH_KEY_STRING,
2972 makefun(&lua_ap_strcmp_match, APL_REQ_FUNTYPE_LUACFUN, p));
2973 apr_hash_set(dispatch, "set_keepalive", APR_HASH_KEY_STRING,
2974 makefun(&lua_ap_set_keepalive, APL_REQ_FUNTYPE_LUACFUN, p));
2975 apr_hash_set(dispatch, "make_etag", APR_HASH_KEY_STRING,
2976 makefun(&lua_ap_make_etag, APL_REQ_FUNTYPE_LUACFUN, p));
2977 apr_hash_set(dispatch, "send_interim_response", APR_HASH_KEY_STRING,
2978 makefun(&lua_ap_send_interim_response, APL_REQ_FUNTYPE_LUACFUN, p));
2979 apr_hash_set(dispatch, "custom_response", APR_HASH_KEY_STRING,
2980 makefun(&lua_ap_custom_response, APL_REQ_FUNTYPE_LUACFUN, p));
2981 apr_hash_set(dispatch, "exists_config_define", APR_HASH_KEY_STRING,
2982 makefun(&lua_ap_exists_config_define, APL_REQ_FUNTYPE_LUACFUN, p));
2983 apr_hash_set(dispatch, "state_query", APR_HASH_KEY_STRING,
2984 makefun(&lua_ap_state_query, APL_REQ_FUNTYPE_LUACFUN, p));
2985 apr_hash_set(dispatch, "get_server_name_for_url", APR_HASH_KEY_STRING,
2986 makefun(&lua_ap_get_server_name_for_url, APL_REQ_FUNTYPE_LUACFUN, p));
2987 apr_hash_set(dispatch, "ivm_get", APR_HASH_KEY_STRING,
2988 makefun(&lua_ivm_get, APL_REQ_FUNTYPE_LUACFUN, p));
2989 apr_hash_set(dispatch, "ivm_set", APR_HASH_KEY_STRING,
2990 makefun(&lua_ivm_set, APL_REQ_FUNTYPE_LUACFUN, p));
2991 apr_hash_set(dispatch, "getcookie", APR_HASH_KEY_STRING,
2992 makefun(&lua_get_cookie, APL_REQ_FUNTYPE_LUACFUN, p));
2993 apr_hash_set(dispatch, "setcookie", APR_HASH_KEY_STRING,
2994 makefun(&lua_set_cookie, APL_REQ_FUNTYPE_LUACFUN, p));
2995 apr_hash_set(dispatch, "wsupgrade", APR_HASH_KEY_STRING,
2996 makefun(&lua_websocket_greet, APL_REQ_FUNTYPE_LUACFUN, p));
2997 apr_hash_set(dispatch, "wsread", APR_HASH_KEY_STRING,
2998 makefun(&lua_websocket_read, APL_REQ_FUNTYPE_LUACFUN, p));
2999 apr_hash_set(dispatch, "wspeek", APR_HASH_KEY_STRING,
3000 makefun(&lua_websocket_peek, APL_REQ_FUNTYPE_LUACFUN, p));
3001 apr_hash_set(dispatch, "wswrite", APR_HASH_KEY_STRING,
3002 makefun(&lua_websocket_write, APL_REQ_FUNTYPE_LUACFUN, p));
3003 apr_hash_set(dispatch, "wsclose", APR_HASH_KEY_STRING,
3004 makefun(&lua_websocket_close, APL_REQ_FUNTYPE_LUACFUN, p));
3005 apr_hash_set(dispatch, "wsping", APR_HASH_KEY_STRING,
3006 makefun(&lua_websocket_ping, APL_REQ_FUNTYPE_LUACFUN, p));
3007 apr_hash_set(dispatch, "config", APR_HASH_KEY_STRING,
3008 makefun(&lua_ap_get_config, APL_REQ_FUNTYPE_LUACFUN, p));
3009 apr_hash_set(dispatch, "activeconfig", APR_HASH_KEY_STRING,
3010 makefun(&lua_ap_get_active_config, APL_REQ_FUNTYPE_LUACFUN, p));
3011 lua_pushlightuserdata(L, dispatch);
3012 lua_setfield(L, LUA_REGISTRYINDEX, "Apache2.Request.dispatch");
3013
3014 luaL_newmetatable(L, "Apache2.Request"); /* [metatable] */
3015 lua_pushvalue(L, -1);
3016
3017 lua_setfield(L, -2, "__index");
3018 luaL_setfuncs_compat(L, request_methods); /* [metatable] */
3019
3020 lua_pop(L, 2);
3021
3022 luaL_newmetatable(L, "Apache2.Connection"); /* [metatable] */
3023 lua_pushvalue(L, -1);
3024
3025 lua_setfield(L, -2, "__index");
3026 luaL_setfuncs_compat(L, connection_methods); /* [metatable] */
3027
3028 lua_pop(L, 2);
3029
3030 luaL_newmetatable(L, "Apache2.Server"); /* [metatable] */
3031 lua_pushvalue(L, -1);
3032
3033 lua_setfield(L, -2, "__index");
3034 luaL_setfuncs_compat(L, server_methods); /* [metatable] */
3035
3036 lua_pop(L, 2);
3037
3038 }
3039
ap_lua_push_connection(lua_State * L,conn_rec * c)3040 void ap_lua_push_connection(lua_State *L, conn_rec *c)
3041 {
3042 req_table_t* t;
3043 lua_boxpointer(L, c);
3044 luaL_getmetatable(L, "Apache2.Connection");
3045 lua_setmetatable(L, -2);
3046 luaL_getmetatable(L, "Apache2.Connection");
3047
3048 t = apr_pcalloc(c->pool, sizeof(req_table_t));
3049 t->t = c->notes;
3050 t->r = NULL;
3051 t->n = "notes";
3052 ap_lua_push_apr_table(L, t);
3053 lua_setfield(L, -2, "notes");
3054
3055 lua_pushstring(L, c->client_ip);
3056 lua_setfield(L, -2, "client_ip");
3057
3058 lua_pop(L, 1);
3059 }
3060
3061
ap_lua_push_server(lua_State * L,server_rec * s)3062 void ap_lua_push_server(lua_State *L, server_rec *s)
3063 {
3064 lua_boxpointer(L, s);
3065 luaL_getmetatable(L, "Apache2.Server");
3066 lua_setmetatable(L, -2);
3067 luaL_getmetatable(L, "Apache2.Server");
3068
3069 lua_pushstring(L, s->server_hostname);
3070 lua_setfield(L, -2, "server_hostname");
3071
3072 lua_pop(L, 1);
3073 }
3074
ap_lua_push_request(lua_State * L,request_rec * r)3075 void ap_lua_push_request(lua_State *L, request_rec *r)
3076 {
3077 lua_boxpointer(L, r);
3078 luaL_getmetatable(L, "Apache2.Request");
3079 lua_setmetatable(L, -2);
3080 }
3081