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
30 #include <lua.h>
31
32 extern apr_thread_mutex_t* lua_ivm_mutex;
33
34 APLOG_USE_MODULE(lua);
35 #define POST_MAX_VARS 500
36
37 #ifndef MODLUA_MAX_REG_MATCH
38 #define MODLUA_MAX_REG_MATCH 25
39 #endif
40
41 typedef char *(*req_field_string_f) (request_rec * r);
42 typedef int (*req_field_int_f) (request_rec * r);
43 typedef apr_table_t *(*req_field_apr_table_f) (request_rec * r);
44
45
ap_lua_rstack_dump(lua_State * L,request_rec * r,const char * msg)46 void ap_lua_rstack_dump(lua_State *L, request_rec *r, const char *msg)
47 {
48 int i;
49 int top = lua_gettop(L);
50 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01484) "Lua Stack Dump: [%s]", msg);
51 for (i = 1; i <= top; i++) {
52 int t = lua_type(L, i);
53 switch (t) {
54 case LUA_TSTRING:{
55 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
56 "%d: '%s'", i, lua_tostring(L, i));
57 break;
58 }
59 case LUA_TUSERDATA:{
60 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "%d: userdata",
61 i);
62 break;
63 }
64 case LUA_TLIGHTUSERDATA:{
65 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
66 "%d: lightuserdata", i);
67 break;
68 }
69 case LUA_TNIL:{
70 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "%d: NIL", i);
71 break;
72 }
73 case LUA_TNONE:{
74 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "%d: None", i);
75 break;
76 }
77 case LUA_TBOOLEAN:{
78 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
79 "%d: %s", i, lua_toboolean(L,
80 i) ? "true" :
81 "false");
82 break;
83 }
84 case LUA_TNUMBER:{
85 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
86 "%d: %g", i, lua_tonumber(L, i));
87 break;
88 }
89 case LUA_TTABLE:{
90 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
91 "%d: <table>", i);
92 break;
93 }
94 case LUA_TFUNCTION:{
95 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
96 "%d: <function>", i);
97 break;
98 }
99 default:{
100 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
101 "%d: unknown: -[%s]-", i, lua_typename(L, i));
102 break;
103 }
104 }
105 }
106 }
107
108 /**
109 * Verify that the thing at index is a request_rec wrapping
110 * userdata thingamajig and return it if it is. if it is not
111 * lua will enter its error handling routine.
112 */
ap_lua_check_request_rec(lua_State * L,int index)113 static request_rec *ap_lua_check_request_rec(lua_State *L, int index)
114 {
115 request_rec *r;
116 luaL_checkudata(L, index, "Apache2.Request");
117 r = (request_rec *) lua_unboxpointer(L, index);
118 return r;
119 }
120
121 /* ------------------ request methods -------------------- */
122 /* helper callback for req_parseargs */
req_aprtable2luatable_cb(void * l,const char * key,const char * value)123 static int req_aprtable2luatable_cb(void *l, const char *key,
124 const char *value)
125 {
126 int t;
127 lua_State *L = (lua_State *) l; /* [table<s,t>, table<s,s>] */
128 /* rstack_dump(L, RRR, "start of cb"); */
129 /* L is [table<s,t>, table<s,s>] */
130 /* build complex */
131
132 lua_getfield(L, -1, key); /* [VALUE, table<s,t>, table<s,s>] */
133 /* rstack_dump(L, RRR, "after getfield"); */
134 t = lua_type(L, -1);
135 switch (t) {
136 case LUA_TNIL:
137 case LUA_TNONE:{
138 lua_pop(L, 1); /* [table<s,t>, table<s,s>] */
139 lua_newtable(L); /* [array, table<s,t>, table<s,s>] */
140 lua_pushnumber(L, 1); /* [1, array, table<s,t>, table<s,s>] */
141 lua_pushstring(L, value); /* [string, 1, array, table<s,t>, table<s,s>] */
142 lua_settable(L, -3); /* [array, table<s,t>, table<s,s>] */
143 lua_setfield(L, -2, key); /* [table<s,t>, table<s,s>] */
144 break;
145 }
146 case LUA_TTABLE:{
147 /* [array, table<s,t>, table<s,s>] */
148 int size = lua_objlen(L, -1);
149 lua_pushnumber(L, size + 1); /* [#, array, table<s,t>, table<s,s>] */
150 lua_pushstring(L, value); /* [string, #, array, table<s,t>, table<s,s>] */
151 lua_settable(L, -3); /* [array, table<s,t>, table<s,s>] */
152 lua_setfield(L, -2, key); /* [table<s,t>, table<s,s>] */
153 break;
154 }
155 }
156
157 /* L is [table<s,t>, table<s,s>] */
158 /* build simple */
159 lua_getfield(L, -2, key); /* [VALUE, table<s,s>, table<s,t>] */
160 if (lua_isnoneornil(L, -1)) { /* only set if not already set */
161 lua_pop(L, 1); /* [table<s,s>, table<s,t>]] */
162 lua_pushstring(L, value); /* [string, table<s,s>, table<s,t>] */
163 lua_setfield(L, -3, key); /* [table<s,s>, table<s,t>] */
164 }
165 else {
166 lua_pop(L, 1);
167 }
168 return 1;
169 }
170
171
172 /*
173 =======================================================================================================================
174 lua_read_body(request_rec *r, const char **rbuf, apr_off_t *size): Reads any additional form data sent in POST/PUT
175 requests. Used for multipart POST data.
176 =======================================================================================================================
177 */
lua_read_body(request_rec * r,const char ** rbuf,apr_off_t * size)178 static int lua_read_body(request_rec *r, const char **rbuf, apr_off_t *size)
179 {
180 int rc = OK;
181
182 if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
183 return (rc);
184 }
185 if (ap_should_client_block(r)) {
186
187 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
188 char argsbuffer[HUGE_STRING_LEN];
189 apr_off_t rsize, len_read, rpos = 0;
190 apr_off_t length = r->remaining;
191 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
192
193 *rbuf = (const char *) apr_pcalloc(r->pool, (apr_size_t) (length + 1));
194 *size = length;
195 while ((len_read = ap_get_client_block(r, argsbuffer, sizeof(argsbuffer))) > 0) {
196 if ((rpos + len_read) > length) {
197 rsize = length - rpos;
198 }
199 else {
200 rsize = len_read;
201 }
202
203 memcpy((char *) *rbuf + rpos, argsbuffer, (size_t) rsize);
204 rpos += rsize;
205 }
206 }
207
208 return (rc);
209 }
210
211
212 /*
213 * =======================================================================================================================
214 * lua_write_body: Reads any additional form data sent in POST/PUT requests
215 * and writes to a file.
216 * =======================================================================================================================
217 */
lua_write_body(request_rec * r,apr_file_t * file,apr_off_t * size)218 static apr_status_t lua_write_body(request_rec *r, apr_file_t *file, apr_off_t *size)
219 {
220 apr_status_t rc = OK;
221
222 if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
223 return rc;
224 if (ap_should_client_block(r)) {
225 char argsbuffer[HUGE_STRING_LEN];
226 apr_off_t rsize,
227 len_read,
228 rpos = 0;
229 apr_off_t length = r->remaining;
230 apr_size_t written;
231
232 *size = length;
233 while ((len_read =
234 ap_get_client_block(r, argsbuffer,
235 sizeof(argsbuffer))) > 0) {
236 if ((rpos + len_read) > length)
237 rsize = (apr_size_t) length - rpos;
238 else
239 rsize = len_read;
240
241 rc = apr_file_write_full(file, argsbuffer, (apr_size_t) rsize,
242 &written);
243 if (written != rsize || rc != OK)
244 return APR_ENOSPC;
245 rpos += rsize;
246 }
247 }
248
249 return rc;
250 }
251
252 /* r:parseargs() returning a lua table */
req_parseargs(lua_State * L)253 static int req_parseargs(lua_State *L)
254 {
255 apr_table_t *form_table;
256 request_rec *r = ap_lua_check_request_rec(L, 1);
257 lua_newtable(L);
258 lua_newtable(L); /* [table, table] */
259 ap_args_to_table(r, &form_table);
260 apr_table_do(req_aprtable2luatable_cb, L, form_table, NULL);
261 return 2; /* [table<string, string>, table<string, array<string>>] */
262 }
263
264 /* r:parsebody(): Parses regular (url-enocded) or multipart POST data and returns two tables*/
req_parsebody(lua_State * L)265 static int req_parsebody(lua_State *L)
266 {
267 apr_array_header_t *pairs;
268 apr_off_t len;
269 int res;
270 apr_size_t size;
271 apr_size_t max_post_size;
272 char *multipart;
273 const char *contentType;
274 request_rec *r = ap_lua_check_request_rec(L, 1);
275 max_post_size = (apr_size_t) luaL_optint(L, 2, MAX_STRING_LEN);
276 multipart = apr_pcalloc(r->pool, 256);
277 contentType = apr_table_get(r->headers_in, "Content-Type");
278 lua_newtable(L);
279 lua_newtable(L); /* [table, table] */
280 if (contentType != NULL && (sscanf(contentType, "multipart/form-data; boundary=%250c", multipart) == 1)) {
281 char *buffer, *key, *filename;
282 char *start = 0, *end = 0, *crlf = 0;
283 const char *data;
284 int i;
285 size_t vlen = 0;
286 size_t len = 0;
287 if (lua_read_body(r, &data, (apr_off_t*) &size) != OK) {
288 return 2;
289 }
290 len = strlen(multipart);
291 i = 0;
292 for
293 (
294 start = strstr((char *) data, multipart);
295 start != start + size;
296 start = end
297 ) {
298 i++;
299 if (i == POST_MAX_VARS) break;
300 end = strstr((char *) (start + 1), multipart);
301 if (!end) end = start + size;
302 crlf = strstr((char *) start, "\r\n\r\n");
303 if (!crlf) break;
304 key = (char *) apr_pcalloc(r->pool, 256);
305 filename = (char *) apr_pcalloc(r->pool, 256);
306 vlen = end - crlf - 8;
307 buffer = (char *) apr_pcalloc(r->pool, vlen+1);
308 memcpy(buffer, crlf + 4, vlen);
309 sscanf(start + len + 2,
310 "Content-Disposition: form-data; name=\"%255[^\"]\"; filename=\"%255[^\"]\"",
311 key, filename);
312 if (strlen(key)) {
313 req_aprtable2luatable_cb(L, key, buffer);
314 }
315 }
316 }
317 else {
318 char *buffer;
319 res = ap_parse_form_data(r, NULL, &pairs, -1, max_post_size);
320 if (res == OK) {
321 while(pairs && !apr_is_empty_array(pairs)) {
322 ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs);
323 apr_brigade_length(pair->value, 1, &len);
324 size = (apr_size_t) len;
325 buffer = apr_palloc(r->pool, size + 1);
326 apr_brigade_flatten(pair->value, buffer, &size);
327 buffer[len] = 0;
328 req_aprtable2luatable_cb(L, pair->name, buffer);
329 }
330 }
331 }
332 return 2; /* [table<string, string>, table<string, array<string>>] */
333 }
334
335
336 /*
337 * lua_ap_requestbody; r:requestbody([filename]) - Reads or stores the request
338 * body
339 */
lua_ap_requestbody(lua_State * L)340 static int lua_ap_requestbody(lua_State *L)
341 {
342 const char *filename;
343 request_rec *r;
344 apr_off_t maxSize;
345
346 r = ap_lua_check_request_rec(L, 1);
347 filename = luaL_optstring(L, 2, 0);
348 maxSize = luaL_optint(L, 3, 0);
349
350 if (r) {
351 apr_off_t size;
352 if (maxSize > 0 && r->remaining > maxSize) {
353 lua_pushnil(L);
354 lua_pushliteral(L, "Request body was larger than the permitted size.");
355 return 2;
356 }
357 if (r->method_number != M_POST && r->method_number != M_PUT)
358 return (0);
359 if (!filename) {
360 const char *data;
361
362 if (lua_read_body(r, &data, &size) != OK)
363 return (0);
364
365 lua_pushlstring(L, data, (size_t) size);
366 lua_pushinteger(L, (lua_Integer) size);
367 return (2);
368 } else {
369 apr_status_t rc;
370 apr_file_t *file;
371
372 rc = apr_file_open(&file, filename, APR_CREATE | APR_FOPEN_WRITE,
373 APR_FPROT_OS_DEFAULT, r->pool);
374 lua_settop(L, 0);
375 if (rc == APR_SUCCESS) {
376 rc = lua_write_body(r, file, &size);
377 apr_file_close(file);
378 if (rc != OK) {
379 lua_pushboolean(L, 0);
380 return 1;
381 }
382 lua_pushinteger(L, (lua_Integer) size);
383 return (1);
384 } else
385 lua_pushboolean(L, 0);
386 return (1);
387 }
388 }
389
390 return (0);
391 }
392
393 /* wrap ap_rputs as r:puts(String) */
req_puts(lua_State * L)394 static int req_puts(lua_State *L)
395 {
396 request_rec *r = ap_lua_check_request_rec(L, 1);
397
398 int argc = lua_gettop(L);
399 int i;
400
401 for (i = 2; i <= argc; i++) {
402 ap_rputs(luaL_checkstring(L, i), r);
403 }
404 return 0;
405 }
406
407 /* wrap ap_rwrite as r:write(String) */
req_write(lua_State * L)408 static int req_write(lua_State *L)
409 {
410 request_rec *r = ap_lua_check_request_rec(L, 1);
411 size_t n;
412 int rv;
413 const char *buf = luaL_checklstring(L, 2, &n);
414
415 rv = ap_rwrite((void *) buf, n, r);
416 lua_pushinteger(L, rv);
417 return 1;
418 }
419
420 /* r:addoutputfilter(name|function) */
req_add_output_filter(lua_State * L)421 static int req_add_output_filter(lua_State *L)
422 {
423 request_rec *r = ap_lua_check_request_rec(L, 1);
424 const char *name = luaL_checkstring(L, 2);
425 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01485) "adding output filter %s",
426 name);
427 ap_add_output_filter(name, L, r, r->connection);
428 return 0;
429 }
430
431 /* wrap ap_construct_url as r:construct_url(String) */
req_construct_url(lua_State * L)432 static int req_construct_url(lua_State *L)
433 {
434 request_rec *r = ap_lua_check_request_rec(L, 1);
435 const char *name = luaL_checkstring(L, 2);
436 lua_pushstring(L, ap_construct_url(r->pool, name, r));
437 return 1;
438 }
439
440 /* wrap ap_escape_html r:escape_html(String) */
req_escape_html(lua_State * L)441 static int req_escape_html(lua_State *L)
442 {
443 request_rec *r = ap_lua_check_request_rec(L, 1);
444 const char *s = luaL_checkstring(L, 2);
445 lua_pushstring(L, ap_escape_html(r->pool, s));
446 return 1;
447 }
448
449 /* wrap optional ssl_var_lookup as r:ssl_var_lookup(String) */
req_ssl_var_lookup(lua_State * L)450 static int req_ssl_var_lookup(lua_State *L)
451 {
452 request_rec *r = ap_lua_check_request_rec(L, 1);
453 const char *s = luaL_checkstring(L, 2);
454 const char *res = ap_lua_ssl_val(r->pool, r->server, r->connection, r,
455 (char *)s);
456 lua_pushstring(L, res);
457 return 1;
458 }
459
460 /* BEGIN dispatch mathods for request_rec fields */
461
462 /* not really a field, but we treat it like one */
req_document_root(request_rec * r)463 static const char *req_document_root(request_rec *r)
464 {
465 return ap_document_root(r);
466 }
467
req_context_prefix(request_rec * r)468 static const char *req_context_prefix(request_rec *r)
469 {
470 return ap_context_prefix(r);
471 }
472
req_context_document_root(request_rec * r)473 static const char *req_context_document_root(request_rec *r)
474 {
475 return ap_context_document_root(r);
476 }
477
req_uri_field(request_rec * r)478 static char *req_uri_field(request_rec *r)
479 {
480 return r->uri;
481 }
482
req_method_field(request_rec * r)483 static const char *req_method_field(request_rec *r)
484 {
485 return r->method;
486 }
req_handler_field(request_rec * r)487 static const char *req_handler_field(request_rec *r)
488 {
489 return r->handler;
490 }
req_proxyreq_field(request_rec * r)491 static const char *req_proxyreq_field(request_rec *r)
492 {
493 switch (r->proxyreq) {
494 case PROXYREQ_NONE: return "PROXYREQ_NONE";
495 case PROXYREQ_PROXY: return "PROXYREQ_PROXY";
496 case PROXYREQ_REVERSE: return "PROXYREQ_REVERSE";
497 case PROXYREQ_RESPONSE: return "PROXYREQ_RESPONSE";
498 default: return NULL;
499 }
500 }
req_hostname_field(request_rec * r)501 static const char *req_hostname_field(request_rec *r)
502 {
503 return r->hostname;
504 }
505
req_args_field(request_rec * r)506 static const char *req_args_field(request_rec *r)
507 {
508 return r->args;
509 }
510
req_path_info_field(request_rec * r)511 static const char *req_path_info_field(request_rec *r)
512 {
513 return r->path_info;
514 }
515
req_canonical_filename_field(request_rec * r)516 static const char *req_canonical_filename_field(request_rec *r)
517 {
518 return r->canonical_filename;
519 }
520
req_filename_field(request_rec * r)521 static const char *req_filename_field(request_rec *r)
522 {
523 return r->filename;
524 }
525
req_user_field(request_rec * r)526 static const char *req_user_field(request_rec *r)
527 {
528 return r->user;
529 }
530
req_unparsed_uri_field(request_rec * r)531 static const char *req_unparsed_uri_field(request_rec *r)
532 {
533 return r->unparsed_uri;
534 }
535
req_ap_auth_type_field(request_rec * r)536 static const char *req_ap_auth_type_field(request_rec *r)
537 {
538 return r->ap_auth_type;
539 }
540
req_content_encoding_field(request_rec * r)541 static const char *req_content_encoding_field(request_rec *r)
542 {
543 return r->content_encoding;
544 }
545
req_content_type_field(request_rec * r)546 static const char *req_content_type_field(request_rec *r)
547 {
548 return r->content_type;
549 }
550
req_range_field(request_rec * r)551 static const char *req_range_field(request_rec *r)
552 {
553 return r->range;
554 }
555
req_protocol_field(request_rec * r)556 static const char *req_protocol_field(request_rec *r)
557 {
558 return r->protocol;
559 }
560
req_the_request_field(request_rec * r)561 static const char *req_the_request_field(request_rec *r)
562 {
563 return r->the_request;
564 }
565
req_log_id_field(request_rec * r)566 static const char *req_log_id_field(request_rec *r)
567 {
568 return r->log_id;
569 }
570
req_useragent_ip_field(request_rec * r)571 static const char *req_useragent_ip_field(request_rec *r)
572 {
573 return r->useragent_ip;
574 }
575
req_remaining_field(request_rec * r)576 static int req_remaining_field(request_rec *r)
577 {
578 return r->remaining;
579 }
580
req_status_field(request_rec * r)581 static int req_status_field(request_rec *r)
582 {
583 return r->status;
584 }
585
req_assbackwards_field(request_rec * r)586 static int req_assbackwards_field(request_rec *r)
587 {
588 return r->assbackwards;
589 }
590
req_headers_in(request_rec * r)591 static apr_table_t* req_headers_in(request_rec *r)
592 {
593 return r->headers_in;
594 }
595
req_headers_out(request_rec * r)596 static apr_table_t* req_headers_out(request_rec *r)
597 {
598 return r->headers_out;
599 }
600
req_err_headers_out(request_rec * r)601 static apr_table_t* req_err_headers_out(request_rec *r)
602 {
603 return r->err_headers_out;
604 }
605
req_subprocess_env(request_rec * r)606 static apr_table_t* req_subprocess_env(request_rec *r)
607 {
608 return r->subprocess_env;
609 }
610
req_notes(request_rec * r)611 static apr_table_t* req_notes(request_rec *r)
612 {
613 return r->notes;
614 }
615
req_ssl_is_https_field(request_rec * r)616 static int req_ssl_is_https_field(request_rec *r)
617 {
618 return ap_lua_ssl_is_https(r->connection);
619 }
620
req_ap_get_server_port(request_rec * r)621 static int req_ap_get_server_port(request_rec *r)
622 {
623 return (int) ap_get_server_port(r);
624 }
625
lua_ap_rflush(lua_State * L)626 static int lua_ap_rflush (lua_State *L) {
627
628 int returnValue;
629 request_rec *r;
630 luaL_checktype(L, 1, LUA_TUSERDATA);
631 r = ap_lua_check_request_rec(L, 1);
632 returnValue = ap_rflush(r);
633 lua_pushboolean(L, (returnValue == 0));
634 return 1;
635 }
636
637
lua_ap_options(request_rec * r)638 static const char* lua_ap_options(request_rec* r)
639 {
640 int opts;
641 opts = ap_allow_options(r);
642 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" : "" );
643 }
644
lua_ap_allowoverrides(request_rec * r)645 static const char* lua_ap_allowoverrides(request_rec* r)
646 {
647 int opts;
648 opts = ap_allow_overrides(r);
649 return apr_psprintf(r->pool, "%s %s %s %s %s %s", (opts&OR_NONE) ? "None" : "", (opts&OR_LIMIT) ? "Limit" : "", (opts&OR_OPTIONS) ? "Options" : "", (opts&OR_FILEINFO) ? "FileInfo" : "", (opts&OR_AUTHCFG) ? "AuthCfg" : "", (opts&OR_INDEXES) ? "Indexes" : "" );
650 }
651
lua_ap_started(request_rec * r)652 static int lua_ap_started(request_rec* r)
653 {
654 return (int)(ap_scoreboard_image->global->restart_time / 1000000);
655 }
656
lua_ap_basic_auth_pw(request_rec * r)657 static const char* lua_ap_basic_auth_pw(request_rec* r)
658 {
659 const char* pw = NULL;
660 ap_get_basic_auth_pw(r, &pw);
661 return pw ? pw : "";
662 }
663
lua_ap_limit_req_body(request_rec * r)664 static int lua_ap_limit_req_body(request_rec* r)
665 {
666 return (int) ap_get_limit_req_body(r);
667 }
668
lua_ap_is_initial_req(request_rec * r)669 static int lua_ap_is_initial_req(request_rec *r)
670 {
671 return ap_is_initial_req(r);
672 }
673
lua_ap_some_auth_required(request_rec * r)674 static int lua_ap_some_auth_required(request_rec *r)
675 {
676 return ap_some_auth_required(r);
677 }
678
lua_ap_sendfile(lua_State * L)679 static int lua_ap_sendfile(lua_State *L)
680 {
681
682 apr_finfo_t file_info;
683 const char *filename;
684 request_rec *r;
685
686 luaL_checktype(L, 1, LUA_TUSERDATA);
687 luaL_checktype(L, 2, LUA_TSTRING);
688 r = ap_lua_check_request_rec(L, 1);
689 filename = lua_tostring(L, 2);
690 apr_stat(&file_info, filename, APR_FINFO_MIN, r->pool);
691 if (file_info.filetype == APR_NOFILE || file_info.filetype == APR_DIR) {
692 lua_pushboolean(L, 0);
693 }
694 else {
695 apr_size_t sent;
696 apr_status_t rc;
697 apr_file_t *file;
698
699 rc = apr_file_open(&file, filename, APR_READ, APR_OS_DEFAULT,
700 r->pool);
701 if (rc == APR_SUCCESS) {
702 ap_send_fd(file, r, 0, (apr_size_t)file_info.size, &sent);
703 apr_file_close(file);
704 lua_pushinteger(L, sent);
705 }
706 else {
707 lua_pushboolean(L, 0);
708 }
709 }
710
711 return (1);
712 }
713
714
715 /*
716 * lua_apr_b64encode; r:encode_base64(string) - encodes a string to Base64
717 * format
718 */
lua_apr_b64encode(lua_State * L)719 static int lua_apr_b64encode(lua_State *L)
720 {
721 const char *plain;
722 char *encoded;
723 size_t plain_len, encoded_len;
724 request_rec *r;
725
726 r = ap_lua_check_request_rec(L, 1);
727 luaL_checktype(L, 2, LUA_TSTRING);
728 plain = lua_tolstring(L, 2, &plain_len);
729 encoded_len = apr_base64_encode_len(plain_len);
730 if (encoded_len) {
731 encoded = apr_palloc(r->pool, encoded_len);
732 encoded_len = apr_base64_encode(encoded, plain, plain_len);
733 if (encoded_len > 0 && encoded[encoded_len - 1] == '\0')
734 encoded_len--;
735 lua_pushlstring(L, encoded, encoded_len);
736 return 1;
737 }
738 return 0;
739 }
740
741 /*
742 * lua_apr_b64decode; r:decode_base64(string) - decodes a Base64 string
743 */
lua_apr_b64decode(lua_State * L)744 static int lua_apr_b64decode(lua_State *L)
745 {
746 const char *encoded;
747 char *plain;
748 size_t encoded_len, decoded_len;
749 request_rec *r;
750
751 r = ap_lua_check_request_rec(L, 1);
752 luaL_checktype(L, 2, LUA_TSTRING);
753 encoded = lua_tolstring(L, 2, &encoded_len);
754 decoded_len = apr_base64_decode_len(encoded);
755 if (decoded_len) {
756 plain = apr_palloc(r->pool, decoded_len);
757 decoded_len = apr_base64_decode(plain, encoded);
758 if (decoded_len > 0 && plain[decoded_len - 1] == '\0')
759 decoded_len--;
760 lua_pushlstring(L, plain, decoded_len);
761 return 1;
762 }
763 return 0;
764 }
765
766 /*
767 * lua_ap_unescape; r:unescape(string) - Unescapes an URL-encoded string
768 */
lua_ap_unescape(lua_State * L)769 static int lua_ap_unescape(lua_State *L)
770 {
771 const char *escaped;
772 char *plain;
773 size_t x,
774 y;
775 request_rec *r;
776 r = ap_lua_check_request_rec(L, 1);
777 luaL_checktype(L, 2, LUA_TSTRING);
778 escaped = lua_tolstring(L, 2, &x);
779 plain = apr_pstrdup(r->pool, escaped);
780 y = ap_unescape_urlencoded(plain);
781 if (!y) {
782 lua_pushstring(L, plain);
783 return 1;
784 }
785 return 0;
786 }
787
788 /*
789 * lua_ap_escape; r:escape(string) - URL-escapes a string
790 */
lua_ap_escape(lua_State * L)791 static int lua_ap_escape(lua_State *L)
792 {
793 const char *plain;
794 char *escaped;
795 size_t x;
796 request_rec *r;
797 r = ap_lua_check_request_rec(L, 1);
798 luaL_checktype(L, 2, LUA_TSTRING);
799 plain = lua_tolstring(L, 2, &x);
800 escaped = ap_escape_urlencoded(r->pool, plain);
801 lua_pushstring(L, escaped);
802 return 1;
803 }
804
805 /*
806 * lua_apr_md5; r:md5(string) - Calculates an MD5 digest of a string
807 */
lua_apr_md5(lua_State * L)808 static int lua_apr_md5(lua_State *L)
809 {
810 const char *buffer;
811 char *result;
812 size_t len;
813 request_rec *r;
814
815 r = ap_lua_check_request_rec(L, 1);
816 luaL_checktype(L, 2, LUA_TSTRING);
817 buffer = lua_tolstring(L, 2, &len);
818 result = ap_md5_binary(r->pool, (const unsigned char *)buffer, len);
819 lua_pushstring(L, result);
820 return 1;
821 }
822
823 /*
824 * lua_apr_sha1; r:sha1(string) - Calculates the SHA1 digest of a string
825 */
lua_apr_sha1(lua_State * L)826 static int lua_apr_sha1(lua_State *L)
827 {
828 unsigned char digest[APR_SHA1_DIGESTSIZE];
829 apr_sha1_ctx_t sha1;
830 const char *buffer;
831 char *result;
832 size_t len;
833 request_rec *r;
834
835 r = ap_lua_check_request_rec(L, 1);
836 luaL_checktype(L, 2, LUA_TSTRING);
837 result = apr_pcalloc(r->pool, sizeof(digest) * 2 + 1);
838 buffer = lua_tolstring(L, 2, &len);
839 apr_sha1_init(&sha1);
840 apr_sha1_update(&sha1, buffer, len);
841 apr_sha1_final(digest, &sha1);
842 ap_bin2hex(digest, sizeof(digest), result);
843 lua_pushstring(L, result);
844 return 1;
845 }
846
847 /*
848 * lua_apr_htpassword; r:htpassword(string [, algorithm [, cost]]) - Creates
849 * a htpassword hash from a string
850 */
lua_apr_htpassword(lua_State * L)851 static int lua_apr_htpassword(lua_State *L)
852 {
853 passwd_ctx ctx = { 0 };
854 request_rec *r;
855
856 r = ap_lua_check_request_rec(L, 1);
857 luaL_checktype(L, 2, LUA_TSTRING);
858 ctx.passwd = apr_pstrdup(r->pool, lua_tostring(L, 2));
859 ctx.alg = luaL_optinteger(L, 3, ALG_APMD5);
860 ctx.cost = luaL_optinteger(L, 4, 0);
861 ctx.pool = r->pool;
862 ctx.out = apr_pcalloc(r->pool, MAX_PASSWD_LEN);
863 ctx.out_len = MAX_PASSWD_LEN;
864 if (mk_password_hash(&ctx)) {
865 lua_pushboolean(L, 0);
866 lua_pushstring(L, ctx.errstr);
867 return 2;
868 } else {
869 lua_pushstring(L, ctx.out);
870 }
871 return 1;
872 }
873
874 /*
875 * lua_apr_touch; r:touch(string [, time]) - Sets mtime of a file
876 */
lua_apr_touch(lua_State * L)877 static int lua_apr_touch(lua_State *L)
878 {
879 request_rec *r;
880 const char *path;
881 apr_status_t status;
882 apr_time_t mtime;
883
884 r = ap_lua_check_request_rec(L, 1);
885 luaL_checktype(L, 2, LUA_TSTRING);
886 path = lua_tostring(L, 2);
887 mtime = luaL_optnumber(L, 3, apr_time_now());
888 status = apr_file_mtime_set(path, mtime, r->pool);
889 lua_pushboolean(L, (status == 0));
890 return 1;
891 }
892
893 /*
894 * lua_apr_mkdir; r:mkdir(string [, permissions]) - Creates a directory
895 */
lua_apr_mkdir(lua_State * L)896 static int lua_apr_mkdir(lua_State *L)
897 {
898 request_rec *r;
899 const char *path;
900 apr_status_t status;
901 apr_fileperms_t perms;
902
903 r = ap_lua_check_request_rec(L, 1);
904 luaL_checktype(L, 2, LUA_TSTRING);
905 path = lua_tostring(L, 2);
906 perms = luaL_optinteger(L, 3, APR_OS_DEFAULT);
907 status = apr_dir_make(path, perms, r->pool);
908 lua_pushboolean(L, (status == 0));
909 return 1;
910 }
911
912 /*
913 * lua_apr_mkrdir; r:mkrdir(string [, permissions]) - Creates directories
914 * recursive
915 */
lua_apr_mkrdir(lua_State * L)916 static int lua_apr_mkrdir(lua_State *L)
917 {
918 request_rec *r;
919 const char *path;
920 apr_status_t status;
921 apr_fileperms_t perms;
922
923 r = ap_lua_check_request_rec(L, 1);
924 luaL_checktype(L, 2, LUA_TSTRING);
925 path = lua_tostring(L, 2);
926 perms = luaL_optinteger(L, 3, APR_OS_DEFAULT);
927 status = apr_dir_make_recursive(path, perms, r->pool);
928 lua_pushboolean(L, (status == 0));
929 return 1;
930 }
931
932 /*
933 * lua_apr_rmdir; r:rmdir(string) - Removes a directory
934 */
lua_apr_rmdir(lua_State * L)935 static int lua_apr_rmdir(lua_State *L)
936 {
937 request_rec *r;
938 const char *path;
939 apr_status_t status;
940
941 r = ap_lua_check_request_rec(L, 1);
942 luaL_checktype(L, 2, LUA_TSTRING);
943 path = lua_tostring(L, 2);
944 status = apr_dir_remove(path, r->pool);
945 lua_pushboolean(L, (status == 0));
946 return 1;
947 }
948
949 /*
950 * lua_apr_date_parse_rfc; r.date_parse_rfc(string) - Parses a DateTime string
951 */
lua_apr_date_parse_rfc(lua_State * L)952 static int lua_apr_date_parse_rfc(lua_State *L)
953 {
954 const char *input;
955 apr_time_t result;
956
957 luaL_checktype(L, 1, LUA_TSTRING);
958 input = lua_tostring(L, 1);
959 result = apr_date_parse_rfc(input);
960 if (result == 0)
961 return 0;
962 lua_pushnumber(L, (lua_Number)(result / APR_USEC_PER_SEC));
963 return 1;
964 }
965
966 /*
967 * lua_ap_mpm_query; r:mpm_query(info) - Queries for MPM info
968 */
lua_ap_mpm_query(lua_State * L)969 static int lua_ap_mpm_query(lua_State *L)
970 {
971 int x,
972 y;
973
974 x = lua_tointeger(L, 1);
975 ap_mpm_query(x, &y);
976 lua_pushinteger(L, y);
977 return 1;
978 }
979
980 /*
981 * lua_ap_expr; r:expr(string) - Evaluates an expr statement.
982 */
lua_ap_expr(lua_State * L)983 static int lua_ap_expr(lua_State *L)
984 {
985 request_rec *r;
986 int x = 0;
987 const char *expr,
988 *err;
989 ap_expr_info_t res;
990
991 luaL_checktype(L, 1, LUA_TUSERDATA);
992 luaL_checktype(L, 2, LUA_TSTRING);
993 r = ap_lua_check_request_rec(L, 1);
994 expr = lua_tostring(L, 2);
995
996
997 res.filename = NULL;
998 res.flags = 0;
999 res.line_number = 0;
1000 res.module_index = APLOG_MODULE_INDEX;
1001
1002 err = ap_expr_parse(r->pool, r->pool, &res, expr, NULL);
1003 if (!err) {
1004 x = ap_expr_exec(r, &res, &err);
1005 lua_pushboolean(L, x);
1006 if (x < 0) {
1007 lua_pushstring(L, err);
1008 return 2;
1009 }
1010 return 1;
1011 } else {
1012 lua_pushboolean(L, 0);
1013 lua_pushstring(L, err);
1014 return 2;
1015 }
1016 lua_pushboolean(L, 0);
1017 return 1;
1018 }
1019
1020
1021 /*
1022 * lua_ap_regex; r:regex(string, pattern [, flags])
1023 * - Evaluates a regex and returns captures if matched
1024 */
lua_ap_regex(lua_State * L)1025 static int lua_ap_regex(lua_State *L)
1026 {
1027 request_rec *r;
1028 int i,
1029 rv,
1030 flags;
1031 const char *pattern,
1032 *source;
1033 char *err;
1034 ap_regex_t regex;
1035 ap_regmatch_t matches[MODLUA_MAX_REG_MATCH+1];
1036
1037 luaL_checktype(L, 1, LUA_TUSERDATA);
1038 luaL_checktype(L, 2, LUA_TSTRING);
1039 luaL_checktype(L, 3, LUA_TSTRING);
1040 r = ap_lua_check_request_rec(L, 1);
1041 source = lua_tostring(L, 2);
1042 pattern = lua_tostring(L, 3);
1043 flags = luaL_optinteger(L, 4, 0);
1044
1045 rv = ap_regcomp(®ex, pattern, flags);
1046 if (rv) {
1047 lua_pushboolean(L, 0);
1048 err = apr_palloc(r->pool, 256);
1049 ap_regerror(rv, ®ex, err, 256);
1050 lua_pushstring(L, err);
1051 return 2;
1052 }
1053
1054 if (regex.re_nsub > MODLUA_MAX_REG_MATCH) {
1055 lua_pushboolean(L, 0);
1056 err = apr_palloc(r->pool, 64);
1057 apr_snprintf(err, 64,
1058 "regcomp found %d matches; only %d allowed.",
1059 regex.re_nsub, MODLUA_MAX_REG_MATCH);
1060 lua_pushstring(L, err);
1061 return 2;
1062 }
1063
1064 rv = ap_regexec(®ex, source, MODLUA_MAX_REG_MATCH, matches, 0);
1065 if (rv == AP_REG_NOMATCH) {
1066 lua_pushboolean(L, 0);
1067 return 1;
1068 }
1069
1070 lua_newtable(L);
1071 for (i = 0; i <= regex.re_nsub; i++) {
1072 lua_pushinteger(L, i);
1073 if (matches[i].rm_so >= 0 && matches[i].rm_eo >= 0)
1074 lua_pushstring(L,
1075 apr_pstrndup(r->pool, source + matches[i].rm_so,
1076 matches[i].rm_eo - matches[i].rm_so));
1077 else
1078 lua_pushnil(L);
1079 lua_settable(L, -3);
1080
1081 }
1082 return 1;
1083 }
1084
1085
1086
1087
1088 /*
1089 * lua_ap_scoreboard_process; r:scoreboard_process(a) - returns scoreboard info
1090 */
lua_ap_scoreboard_process(lua_State * L)1091 static int lua_ap_scoreboard_process(lua_State *L)
1092 {
1093 int i;
1094 process_score *ps_record;
1095
1096 luaL_checktype(L, 1, LUA_TUSERDATA);
1097 luaL_checktype(L, 2, LUA_TNUMBER);
1098 i = lua_tointeger(L, 2);
1099 ps_record = ap_get_scoreboard_process(i);
1100 if (ps_record) {
1101 lua_newtable(L);
1102
1103 lua_pushstring(L, "connections");
1104 lua_pushnumber(L, ps_record->connections);
1105 lua_settable(L, -3);
1106
1107 lua_pushstring(L, "keepalive");
1108 lua_pushnumber(L, ps_record->keep_alive);
1109 lua_settable(L, -3);
1110
1111 lua_pushstring(L, "lingering_close");
1112 lua_pushnumber(L, ps_record->lingering_close);
1113 lua_settable(L, -3);
1114
1115 lua_pushstring(L, "pid");
1116 lua_pushnumber(L, ps_record->pid);
1117 lua_settable(L, -3);
1118
1119 lua_pushstring(L, "suspended");
1120 lua_pushnumber(L, ps_record->suspended);
1121 lua_settable(L, -3);
1122
1123 lua_pushstring(L, "write_completion");
1124 lua_pushnumber(L, ps_record->write_completion);
1125 lua_settable(L, -3);
1126
1127 lua_pushstring(L, "not_accepting");
1128 lua_pushnumber(L, ps_record->not_accepting);
1129 lua_settable(L, -3);
1130
1131 lua_pushstring(L, "quiescing");
1132 lua_pushnumber(L, ps_record->quiescing);
1133 lua_settable(L, -3);
1134
1135 return 1;
1136 }
1137 return 0;
1138 }
1139
1140 /*
1141 * lua_ap_scoreboard_worker; r:scoreboard_worker(proc, thread) - Returns thread
1142 * info
1143 */
lua_ap_scoreboard_worker(lua_State * L)1144 static int lua_ap_scoreboard_worker(lua_State *L)
1145 {
1146 int i,
1147 j;
1148 worker_score *ws_record;
1149
1150 luaL_checktype(L, 1, LUA_TUSERDATA);
1151 luaL_checktype(L, 2, LUA_TNUMBER);
1152 luaL_checktype(L, 3, LUA_TNUMBER);
1153 i = lua_tointeger(L, 2);
1154 j = lua_tointeger(L, 3);
1155 ws_record = ap_get_scoreboard_worker_from_indexes(i, j);
1156 if (ws_record) {
1157 lua_newtable(L);
1158
1159 lua_pushstring(L, "access_count");
1160 lua_pushnumber(L, ws_record->access_count);
1161 lua_settable(L, -3);
1162
1163 lua_pushstring(L, "bytes_served");
1164 lua_pushnumber(L, (lua_Number) ws_record->bytes_served);
1165 lua_settable(L, -3);
1166
1167 lua_pushstring(L, "client");
1168 lua_pushstring(L, ws_record->client);
1169 lua_settable(L, -3);
1170
1171 lua_pushstring(L, "conn_bytes");
1172 lua_pushnumber(L, (lua_Number) ws_record->conn_bytes);
1173 lua_settable(L, -3);
1174
1175 lua_pushstring(L, "conn_count");
1176 lua_pushnumber(L, ws_record->conn_count);
1177 lua_settable(L, -3);
1178
1179 lua_pushstring(L, "generation");
1180 lua_pushnumber(L, ws_record->generation);
1181 lua_settable(L, -3);
1182
1183 lua_pushstring(L, "last_used");
1184 lua_pushnumber(L, (lua_Number) ws_record->last_used);
1185 lua_settable(L, -3);
1186
1187 lua_pushstring(L, "pid");
1188 lua_pushnumber(L, ws_record->pid);
1189 lua_settable(L, -3);
1190
1191 lua_pushstring(L, "request");
1192 lua_pushstring(L, ws_record->request);
1193 lua_settable(L, -3);
1194
1195 lua_pushstring(L, "start_time");
1196 lua_pushnumber(L, (lua_Number) ws_record->start_time);
1197 lua_settable(L, -3);
1198
1199 lua_pushstring(L, "status");
1200 lua_pushnumber(L, ws_record->status);
1201 lua_settable(L, -3);
1202
1203 lua_pushstring(L, "stop_time");
1204 lua_pushnumber(L, (lua_Number) ws_record->stop_time);
1205 lua_settable(L, -3);
1206
1207 lua_pushstring(L, "tid");
1208
1209 lua_pushinteger(L, (lua_Integer) ws_record->tid);
1210 lua_settable(L, -3);
1211
1212 lua_pushstring(L, "vhost");
1213 lua_pushstring(L, ws_record->vhost);
1214 lua_settable(L, -3);
1215 #ifdef HAVE_TIMES
1216 lua_pushstring(L, "stimes");
1217 lua_pushnumber(L, ws_record->times.tms_stime);
1218 lua_settable(L, -3);
1219
1220 lua_pushstring(L, "utimes");
1221 lua_pushnumber(L, ws_record->times.tms_utime);
1222 lua_settable(L, -3);
1223 #endif
1224 return 1;
1225 }
1226 return 0;
1227 }
1228
1229 /*
1230 * lua_ap_clock; r:clock() - Returns timestamp with microsecond precision
1231 */
lua_ap_clock(lua_State * L)1232 static int lua_ap_clock(lua_State *L)
1233 {
1234 apr_time_t now;
1235 now = apr_time_now();
1236 lua_pushnumber(L, (lua_Number) now);
1237 return 1;
1238 }
1239
1240 /*
1241 * lua_ap_add_input_filter; r:add_input_filter(name) - Adds an input filter to
1242 * the chain
1243 */
lua_ap_add_input_filter(lua_State * L)1244 static int lua_ap_add_input_filter(lua_State *L)
1245 {
1246 request_rec *r;
1247 const char *filterName;
1248 ap_filter_rec_t *filter;
1249
1250 luaL_checktype(L, 1, LUA_TUSERDATA);
1251 luaL_checktype(L, 2, LUA_TSTRING);
1252 r = ap_lua_check_request_rec(L, 1);
1253 filterName = lua_tostring(L, 2);
1254 filter = ap_get_input_filter_handle(filterName);
1255 if (filter) {
1256 ap_add_input_filter_handle(filter, NULL, r, r->connection);
1257 lua_pushboolean(L, 1);
1258 } else
1259 lua_pushboolean(L, 0);
1260 return 1;
1261 }
1262
1263
1264 /*
1265 * lua_ap_module_info; r:module_info(mod_name) - Returns information about a
1266 * loaded module
1267 */
lua_ap_module_info(lua_State * L)1268 static int lua_ap_module_info(lua_State *L)
1269 {
1270 const char *moduleName;
1271 module *mod;
1272
1273 luaL_checktype(L, 1, LUA_TSTRING);
1274 moduleName = lua_tostring(L, 1);
1275 mod = ap_find_linked_module(moduleName);
1276 if (mod && mod->cmds) {
1277 const command_rec *cmd;
1278 lua_newtable(L);
1279 lua_pushstring(L, "commands");
1280 lua_newtable(L);
1281 for (cmd = mod->cmds; cmd->name; ++cmd) {
1282 lua_pushstring(L, cmd->name);
1283 lua_pushstring(L, cmd->errmsg);
1284 lua_settable(L, -3);
1285 }
1286 lua_settable(L, -3);
1287 return 1;
1288 }
1289 return 0;
1290 }
1291
1292 /*
1293 * lua_ap_runtime_dir_relative: r:runtime_dir_relative(file): Returns the
1294 * filename as relative to the runtime dir
1295 */
lua_ap_runtime_dir_relative(lua_State * L)1296 static int lua_ap_runtime_dir_relative(lua_State *L)
1297 {
1298 request_rec *r;
1299 const char *file;
1300
1301 luaL_checktype(L, 1, LUA_TUSERDATA);
1302 r = ap_lua_check_request_rec(L, 1);
1303 file = luaL_optstring(L, 2, ".");
1304 lua_pushstring(L, ap_runtime_dir_relative(r->pool, file));
1305 return 1;
1306 }
1307
1308 /*
1309 * lua_ap_set_document_root; r:set_document_root(path) - sets the current doc
1310 * root for the request
1311 */
lua_ap_set_document_root(lua_State * L)1312 static int lua_ap_set_document_root(lua_State *L)
1313 {
1314 request_rec *r;
1315 const char *root;
1316
1317 luaL_checktype(L, 1, LUA_TUSERDATA);
1318 luaL_checktype(L, 2, LUA_TSTRING);
1319 r = ap_lua_check_request_rec(L, 1);
1320 root = lua_tostring(L, 2);
1321 ap_set_document_root(r, root);
1322 return 0;
1323 }
1324
1325 /*
1326 * lua_ap_getdir; r:get_direntries(directory) - Gets all entries of a
1327 * directory and returns the directory info as a table
1328 */
lua_ap_getdir(lua_State * L)1329 static int lua_ap_getdir(lua_State *L)
1330 {
1331 request_rec *r;
1332 apr_dir_t *thedir;
1333 apr_finfo_t file_info;
1334 apr_status_t status;
1335 const char *directory;
1336
1337 luaL_checktype(L, 1, LUA_TUSERDATA);
1338 luaL_checktype(L, 2, LUA_TSTRING);
1339 r = ap_lua_check_request_rec(L, 1);
1340 directory = lua_tostring(L, 2);
1341 if (apr_dir_open(&thedir, directory, r->pool) == APR_SUCCESS) {
1342 int i = 0;
1343 lua_newtable(L);
1344 do {
1345 status = apr_dir_read(&file_info, APR_FINFO_NAME, thedir);
1346 if (APR_STATUS_IS_INCOMPLETE(status)) {
1347 continue; /* ignore un-stat()able files */
1348 }
1349 else if (status != APR_SUCCESS) {
1350 break;
1351 }
1352 lua_pushinteger(L, ++i);
1353 lua_pushstring(L, file_info.name);
1354 lua_settable(L, -3);
1355
1356 } while (1);
1357 apr_dir_close(thedir);
1358 return 1;
1359 }
1360 else {
1361 return 0;
1362 }
1363 }
1364
1365 /*
1366 * lua_ap_stat; r:stat(filename [, wanted]) - Runs stat on a file and
1367 * returns the file info as a table
1368 */
lua_ap_stat(lua_State * L)1369 static int lua_ap_stat(lua_State *L)
1370 {
1371 request_rec *r;
1372 const char *filename;
1373 apr_finfo_t file_info;
1374 apr_int32_t wanted;
1375
1376 luaL_checktype(L, 1, LUA_TUSERDATA);
1377 luaL_checktype(L, 2, LUA_TSTRING);
1378 r = ap_lua_check_request_rec(L, 1);
1379 filename = lua_tostring(L, 2);
1380 wanted = luaL_optinteger(L, 3, APR_FINFO_MIN);
1381 if (apr_stat(&file_info, filename, wanted, r->pool) == OK) {
1382 lua_newtable(L);
1383 if (wanted & APR_FINFO_MTIME) {
1384 lua_pushstring(L, "mtime");
1385 lua_pushnumber(L, (lua_Number) file_info.mtime);
1386 lua_settable(L, -3);
1387 }
1388 if (wanted & APR_FINFO_ATIME) {
1389 lua_pushstring(L, "atime");
1390 lua_pushnumber(L, (lua_Number) file_info.atime);
1391 lua_settable(L, -3);
1392 }
1393 if (wanted & APR_FINFO_CTIME) {
1394 lua_pushstring(L, "ctime");
1395 lua_pushnumber(L, (lua_Number) file_info.ctime);
1396 lua_settable(L, -3);
1397 }
1398 if (wanted & APR_FINFO_SIZE) {
1399 lua_pushstring(L, "size");
1400 lua_pushnumber(L, (lua_Number) file_info.size);
1401 lua_settable(L, -3);
1402 }
1403 if (wanted & APR_FINFO_TYPE) {
1404 lua_pushstring(L, "filetype");
1405 lua_pushinteger(L, file_info.filetype);
1406 lua_settable(L, -3);
1407 }
1408 if (wanted & APR_FINFO_PROT) {
1409 lua_pushstring(L, "protection");
1410 lua_pushinteger(L, file_info.protection);
1411 lua_settable(L, -3);
1412 }
1413 return 1;
1414 }
1415 else {
1416 return 0;
1417 }
1418 }
1419
1420 /*
1421 * lua_ap_loaded_modules; r:loaded_modules() - Returns a list of loaded modules
1422 */
lua_ap_loaded_modules(lua_State * L)1423 static int lua_ap_loaded_modules(lua_State *L)
1424 {
1425 int i;
1426 lua_newtable(L);
1427 for (i = 0; ap_loaded_modules[i] && ap_loaded_modules[i]->name; i++) {
1428 lua_pushinteger(L, i + 1);
1429 lua_pushstring(L, ap_loaded_modules[i]->name);
1430 lua_settable(L, -3);
1431 }
1432 return 1;
1433 }
1434
1435 /*
1436 * lua_ap_server_info; r:server_info() - Returns server info, such as the
1437 * executable filename, server root, mpm etc
1438 */
lua_ap_server_info(lua_State * L)1439 static int lua_ap_server_info(lua_State *L)
1440 {
1441 lua_newtable(L);
1442
1443 lua_pushstring(L, "server_executable");
1444 lua_pushstring(L, ap_server_argv0);
1445 lua_settable(L, -3);
1446
1447 lua_pushstring(L, "server_root");
1448 lua_pushstring(L, ap_server_root);
1449 lua_settable(L, -3);
1450
1451 lua_pushstring(L, "scoreboard_fname");
1452 lua_pushstring(L, ap_scoreboard_fname);
1453 lua_settable(L, -3);
1454
1455 lua_pushstring(L, "server_mpm");
1456 lua_pushstring(L, ap_show_mpm());
1457 lua_settable(L, -3);
1458
1459 return 1;
1460 }
1461
1462
1463 /*
1464 * === Auto-scraped functions ===
1465 */
1466
1467
1468 /**
1469 * ap_set_context_info: Set context_prefix and context_document_root.
1470 * @param r The request
1471 * @param prefix the URI prefix, without trailing slash
1472 * @param document_root the corresponding directory on disk, without trailing
1473 * slash
1474 * @note If one of prefix of document_root is NULL, the corrsponding
1475 * property will not be changed.
1476 */
lua_ap_set_context_info(lua_State * L)1477 static int lua_ap_set_context_info(lua_State *L)
1478 {
1479 request_rec *r;
1480 const char *prefix;
1481 const char *document_root;
1482 luaL_checktype(L, 1, LUA_TUSERDATA);
1483 r = ap_lua_check_request_rec(L, 1);
1484 luaL_checktype(L, 2, LUA_TSTRING);
1485 prefix = lua_tostring(L, 2);
1486 luaL_checktype(L, 3, LUA_TSTRING);
1487 document_root = lua_tostring(L, 3);
1488 ap_set_context_info(r, prefix, document_root);
1489 return 0;
1490 }
1491
1492
1493 /**
1494 * ap_os_escape_path (apr_pool_t *p, const char *path, int partial)
1495 * convert an OS path to a URL in an OS dependant way.
1496 * @param p The pool to allocate from
1497 * @param path The path to convert
1498 * @param partial if set, assume that the path will be appended to something
1499 * with a '/' in it (and thus does not prefix "./")
1500 * @return The converted URL
1501 */
lua_ap_os_escape_path(lua_State * L)1502 static int lua_ap_os_escape_path(lua_State *L)
1503 {
1504 char *returnValue;
1505 request_rec *r;
1506 const char *path;
1507 int partial = 0;
1508 luaL_checktype(L, 1, LUA_TUSERDATA);
1509 r = ap_lua_check_request_rec(L, 1);
1510 luaL_checktype(L, 2, LUA_TSTRING);
1511 path = lua_tostring(L, 2);
1512 if (lua_isboolean(L, 3))
1513 partial = lua_toboolean(L, 3);
1514 returnValue = ap_os_escape_path(r->pool, path, partial);
1515 lua_pushstring(L, returnValue);
1516 return 1;
1517 }
1518
1519
1520 /**
1521 * ap_escape_logitem (apr_pool_t *p, const char *str)
1522 * Escape a string for logging
1523 * @param p The pool to allocate from
1524 * @param str The string to escape
1525 * @return The escaped string
1526 */
lua_ap_escape_logitem(lua_State * L)1527 static int lua_ap_escape_logitem(lua_State *L)
1528 {
1529 char *returnValue;
1530 request_rec *r;
1531 const char *str;
1532 luaL_checktype(L, 1, LUA_TUSERDATA);
1533 r = ap_lua_check_request_rec(L, 1);
1534 luaL_checktype(L, 2, LUA_TSTRING);
1535 str = lua_tostring(L, 2);
1536 returnValue = ap_escape_logitem(r->pool, str);
1537 lua_pushstring(L, returnValue);
1538 return 1;
1539 }
1540
1541 /**
1542 * ap_strcmp_match (const char *str, const char *expected)
1543 * Determine if a string matches a patterm containing the wildcards '?' or '*'
1544 * @param str The string to check
1545 * @param expected The pattern to match against
1546 * @param ignoreCase Whether to ignore case when matching
1547 * @return 1 if the two strings match, 0 otherwise
1548 */
lua_ap_strcmp_match(lua_State * L)1549 static int lua_ap_strcmp_match(lua_State *L)
1550 {
1551 int returnValue;
1552 const char *str;
1553 const char *expected;
1554 int ignoreCase = 0;
1555 luaL_checktype(L, 1, LUA_TSTRING);
1556 str = lua_tostring(L, 1);
1557 luaL_checktype(L, 2, LUA_TSTRING);
1558 expected = lua_tostring(L, 2);
1559 if (lua_isboolean(L, 3))
1560 ignoreCase = lua_toboolean(L, 3);
1561 if (!ignoreCase)
1562 returnValue = ap_strcmp_match(str, expected);
1563 else
1564 returnValue = ap_strcasecmp_match(str, expected);
1565 lua_pushboolean(L, (!returnValue));
1566 return 1;
1567 }
1568
1569
1570 /**
1571 * ap_set_keepalive (request_rec *r)
1572 * Set the keepalive status for this request
1573 * @param r The current request
1574 * @return 1 if keepalive can be set, 0 otherwise
1575 */
lua_ap_set_keepalive(lua_State * L)1576 static int lua_ap_set_keepalive(lua_State *L)
1577 {
1578 int returnValue;
1579 request_rec *r;
1580 luaL_checktype(L, 1, LUA_TUSERDATA);
1581 r = ap_lua_check_request_rec(L, 1);
1582 returnValue = ap_set_keepalive(r);
1583 lua_pushboolean(L, returnValue);
1584 return 1;
1585 }
1586
1587 /**
1588 * ap_make_etag (request_rec *r, int force_weak)
1589 * Construct an entity tag from the resource information. If it's a real
1590 * file, build in some of the file characteristics.
1591 * @param r The current request
1592 * @param force_weak Force the entity tag to be weak - it could be modified
1593 * again in as short an interval.
1594 * @return The entity tag
1595 */
lua_ap_make_etag(lua_State * L)1596 static int lua_ap_make_etag(lua_State *L)
1597 {
1598 char *returnValue;
1599 request_rec *r;
1600 int force_weak;
1601 luaL_checktype(L, 1, LUA_TUSERDATA);
1602 r = ap_lua_check_request_rec(L, 1);
1603 luaL_checktype(L, 2, LUA_TBOOLEAN);
1604 force_weak = luaL_optint(L, 2, 0);
1605 returnValue = ap_make_etag(r, force_weak);
1606 lua_pushstring(L, returnValue);
1607 return 1;
1608 }
1609
1610
1611
1612 /**
1613 * ap_send_interim_response (request_rec *r, int send_headers)
1614 * Send an interim (HTTP 1xx) response immediately.
1615 * @param r The request
1616 * @param send_headers Whether to send&clear headers in r->headers_out
1617 */
lua_ap_send_interim_response(lua_State * L)1618 static int lua_ap_send_interim_response(lua_State *L)
1619 {
1620 request_rec *r;
1621 int send_headers = 0;
1622 luaL_checktype(L, 1, LUA_TUSERDATA);
1623 r = ap_lua_check_request_rec(L, 1);
1624 if (lua_isboolean(L, 2))
1625 send_headers = lua_toboolean(L, 2);
1626 ap_send_interim_response(r, send_headers);
1627 return 0;
1628 }
1629
1630
1631 /**
1632 * ap_custom_response (request_rec *r, int status, const char *string)
1633 * Install a custom response handler for a given status
1634 * @param r The current request
1635 * @param status The status for which the custom response should be used
1636 * @param string The custom response. This can be a static string, a file
1637 * or a URL
1638 */
lua_ap_custom_response(lua_State * L)1639 static int lua_ap_custom_response(lua_State *L)
1640 {
1641 request_rec *r;
1642 int status;
1643 const char *string;
1644 luaL_checktype(L, 1, LUA_TUSERDATA);
1645 r = ap_lua_check_request_rec(L, 1);
1646 luaL_checktype(L, 2, LUA_TNUMBER);
1647 status = lua_tointeger(L, 2);
1648 luaL_checktype(L, 3, LUA_TSTRING);
1649 string = lua_tostring(L, 3);
1650 ap_custom_response(r, status, string);
1651 return 0;
1652 }
1653
1654
1655 /**
1656 * ap_exists_config_define (const char *name)
1657 * Check for a definition from the server command line
1658 * @param name The define to check for
1659 * @return 1 if defined, 0 otherwise
1660 */
lua_ap_exists_config_define(lua_State * L)1661 static int lua_ap_exists_config_define(lua_State *L)
1662 {
1663 int returnValue;
1664 const char *name;
1665 luaL_checktype(L, 1, LUA_TSTRING);
1666 name = lua_tostring(L, 1);
1667 returnValue = ap_exists_config_define(name);
1668 lua_pushboolean(L, returnValue);
1669 return 1;
1670 }
1671
lua_ap_get_server_name_for_url(lua_State * L)1672 static int lua_ap_get_server_name_for_url(lua_State *L)
1673 {
1674 const char *servername;
1675 request_rec *r;
1676 luaL_checktype(L, 1, LUA_TUSERDATA);
1677 r = ap_lua_check_request_rec(L, 1);
1678 servername = ap_get_server_name_for_url(r);
1679 lua_pushstring(L, servername);
1680 return 1;
1681 }
1682
1683 /* ap_state_query (int query_code) item starts a new field */
lua_ap_state_query(lua_State * L)1684 static int lua_ap_state_query(lua_State *L)
1685 {
1686
1687 int returnValue;
1688 int query_code;
1689 luaL_checktype(L, 1, LUA_TNUMBER);
1690 query_code = lua_tointeger(L, 1);
1691 returnValue = ap_state_query(query_code);
1692 lua_pushinteger(L, returnValue);
1693 return 1;
1694 }
1695
1696 /*
1697 * lua_ap_usleep; r:usleep(microseconds)
1698 * - Sleep for the specified number of microseconds.
1699 */
lua_ap_usleep(lua_State * L)1700 static int lua_ap_usleep(lua_State *L)
1701 {
1702 apr_interval_time_t msec;
1703 luaL_checktype(L, 1, LUA_TNUMBER);
1704 msec = (apr_interval_time_t)lua_tonumber(L, 1);
1705 apr_sleep(msec);
1706 return 0;
1707 }
1708
1709 /* END dispatch methods for request_rec fields */
1710
req_dispatch(lua_State * L)1711 static int req_dispatch(lua_State *L)
1712 {
1713 apr_hash_t *dispatch;
1714 req_fun_t *rft;
1715 request_rec *r = ap_lua_check_request_rec(L, 1);
1716 const char *name = luaL_checkstring(L, 2);
1717 lua_pop(L, 2);
1718
1719 lua_getfield(L, LUA_REGISTRYINDEX, "Apache2.Request.dispatch");
1720 dispatch = lua_touserdata(L, 1);
1721 lua_pop(L, 1);
1722
1723 rft = apr_hash_get(dispatch, name, APR_HASH_KEY_STRING);
1724 if (rft) {
1725 switch (rft->type) {
1726 case APL_REQ_FUNTYPE_TABLE:{
1727 apr_table_t *rs;
1728 req_field_apr_table_f func = (req_field_apr_table_f)rft->fun;
1729 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01486)
1730 "request_rec->dispatching %s -> apr table",
1731 name);
1732 rs = (*func)(r);
1733 ap_lua_push_apr_table(L, rs);
1734 return 1;
1735 }
1736
1737 case APL_REQ_FUNTYPE_LUACFUN:{
1738 lua_CFunction func = (lua_CFunction)rft->fun;
1739 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01487)
1740 "request_rec->dispatching %s -> lua_CFunction",
1741 name);
1742 lua_pushcfunction(L, func);
1743 return 1;
1744 }
1745 case APL_REQ_FUNTYPE_STRING:{
1746 req_field_string_f func = (req_field_string_f)rft->fun;
1747 char *rs;
1748 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01488)
1749 "request_rec->dispatching %s -> string", name);
1750 rs = (*func) (r);
1751 lua_pushstring(L, rs);
1752 return 1;
1753 }
1754 case APL_REQ_FUNTYPE_INT:{
1755 req_field_int_f func = (req_field_int_f)rft->fun;
1756 int rs;
1757 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01489)
1758 "request_rec->dispatching %s -> int", name);
1759 rs = (*func) (r);
1760 lua_pushinteger(L, rs);
1761 return 1;
1762 }
1763 case APL_REQ_FUNTYPE_BOOLEAN:{
1764 req_field_int_f func = (req_field_int_f)rft->fun;
1765 int rs;
1766 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01490)
1767 "request_rec->dispatching %s -> boolean", name);
1768 rs = (*func) (r);
1769 lua_pushboolean(L, rs);
1770 return 1;
1771 }
1772 }
1773 }
1774
1775 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01491) "nothing for %s", name);
1776 return 0;
1777 }
1778
1779 /* helper function for the logging functions below */
req_log_at(lua_State * L,int level)1780 static int req_log_at(lua_State *L, int level)
1781 {
1782 const char *msg;
1783 request_rec *r = ap_lua_check_request_rec(L, 1);
1784 lua_Debug dbg;
1785
1786 lua_getstack(L, 1, &dbg);
1787 lua_getinfo(L, "Sl", &dbg);
1788
1789 msg = luaL_checkstring(L, 2);
1790 ap_log_rerror(dbg.source, dbg.currentline, APLOG_MODULE_INDEX, level, 0,
1791 r, "%s", msg);
1792 return 0;
1793 }
1794
1795 /* r:debug(String) and friends which use apache logging */
req_emerg(lua_State * L)1796 static int req_emerg(lua_State *L)
1797 {
1798 return req_log_at(L, APLOG_EMERG);
1799 }
req_alert(lua_State * L)1800 static int req_alert(lua_State *L)
1801 {
1802 return req_log_at(L, APLOG_ALERT);
1803 }
req_crit(lua_State * L)1804 static int req_crit(lua_State *L)
1805 {
1806 return req_log_at(L, APLOG_CRIT);
1807 }
req_err(lua_State * L)1808 static int req_err(lua_State *L)
1809 {
1810 return req_log_at(L, APLOG_ERR);
1811 }
req_warn(lua_State * L)1812 static int req_warn(lua_State *L)
1813 {
1814 return req_log_at(L, APLOG_WARNING);
1815 }
req_notice(lua_State * L)1816 static int req_notice(lua_State *L)
1817 {
1818 return req_log_at(L, APLOG_NOTICE);
1819 }
req_info(lua_State * L)1820 static int req_info(lua_State *L)
1821 {
1822 return req_log_at(L, APLOG_INFO);
1823 }
req_debug(lua_State * L)1824 static int req_debug(lua_State *L)
1825 {
1826 return req_log_at(L, APLOG_DEBUG);
1827 }
1828
lua_ivm_get(lua_State * L)1829 static int lua_ivm_get(lua_State *L)
1830 {
1831 const char *key, *raw_key;
1832 lua_ivm_object *object = NULL;
1833 request_rec *r = ap_lua_check_request_rec(L, 1);
1834 key = luaL_checkstring(L, 2);
1835 raw_key = apr_pstrcat(r->pool, "lua_ivm_", key, NULL);
1836 apr_thread_mutex_lock(lua_ivm_mutex);
1837 apr_pool_userdata_get((void **)&object, raw_key, r->server->process->pool);
1838 if (object) {
1839 if (object->type == LUA_TBOOLEAN) lua_pushboolean(L, (int) object->number);
1840 else if (object->type == LUA_TNUMBER) lua_pushnumber(L, object->number);
1841 else if (object->type == LUA_TSTRING) lua_pushlstring(L, object->vb.buf, object->size);
1842 apr_thread_mutex_unlock(lua_ivm_mutex);
1843 return 1;
1844 }
1845 else {
1846 apr_thread_mutex_unlock(lua_ivm_mutex);
1847 return 0;
1848 }
1849 }
1850
1851
lua_ivm_set(lua_State * L)1852 static int lua_ivm_set(lua_State *L)
1853 {
1854 const char *key, *raw_key;
1855 const char *value = NULL;
1856 size_t str_len;
1857 lua_ivm_object *object = NULL;
1858 request_rec *r = ap_lua_check_request_rec(L, 1);
1859 key = luaL_checkstring(L, 2);
1860 luaL_checkany(L, 3);
1861 raw_key = apr_pstrcat(r->pool, "lua_ivm_", key, NULL);
1862
1863 apr_thread_mutex_lock(lua_ivm_mutex);
1864 apr_pool_userdata_get((void **)&object, raw_key, r->server->process->pool);
1865 if (!object) {
1866 object = apr_pcalloc(r->server->process->pool, sizeof(lua_ivm_object));
1867 ap_varbuf_init(r->server->process->pool, &object->vb, 2);
1868 object->size = 1;
1869 object->vb_size = 1;
1870 }
1871 object->type = lua_type(L, 3);
1872 if (object->type == LUA_TNUMBER) object->number = lua_tonumber(L, 3);
1873 else if (object->type == LUA_TBOOLEAN) object->number = lua_tonumber(L, 3);
1874 else if (object->type == LUA_TSTRING) {
1875 value = lua_tolstring(L, 3, &str_len);
1876 str_len++; /* add trailing \0 */
1877 if ( str_len > object->vb_size) {
1878 ap_varbuf_grow(&object->vb, str_len);
1879 object->vb_size = str_len;
1880 }
1881 object->size = str_len-1;
1882 memset(object->vb.buf, 0, str_len);
1883 memcpy(object->vb.buf, value, str_len-1);
1884 }
1885 apr_pool_userdata_set(object, raw_key, NULL, r->server->process->pool);
1886 apr_thread_mutex_unlock(lua_ivm_mutex);
1887 return 0;
1888 }
1889
1890 #define APLUA_REQ_TRACE(lev) static int req_trace##lev(lua_State *L) \
1891 { \
1892 return req_log_at(L, APLOG_TRACE##lev); \
1893 }
1894
1895 APLUA_REQ_TRACE(1)
1896 APLUA_REQ_TRACE(2)
1897 APLUA_REQ_TRACE(3)
1898 APLUA_REQ_TRACE(4)
1899 APLUA_REQ_TRACE(5)
1900 APLUA_REQ_TRACE(6)
1901 APLUA_REQ_TRACE(7)
1902 APLUA_REQ_TRACE(8)
1903
1904 /* handle r.status = 201 */
req_newindex(lua_State * L)1905 static int req_newindex(lua_State *L)
1906 {
1907 const char *key;
1908 /* request_rec* r = lua_touserdata(L, lua_upvalueindex(1)); */
1909 /* const char* key = luaL_checkstring(L, -2); */
1910 request_rec *r = ap_lua_check_request_rec(L, 1);
1911 key = luaL_checkstring(L, 2);
1912
1913 if (0 == strcmp("args", key)) {
1914 const char *value = luaL_checkstring(L, 3);
1915 r->args = apr_pstrdup(r->pool, value);
1916 return 0;
1917 }
1918
1919 if (0 == strcmp("content_type", key)) {
1920 const char *value = luaL_checkstring(L, 3);
1921 ap_set_content_type(r, apr_pstrdup(r->pool, value));
1922 return 0;
1923 }
1924
1925 if (0 == strcmp("filename", key)) {
1926 const char *value = luaL_checkstring(L, 3);
1927 r->filename = apr_pstrdup(r->pool, value);
1928 return 0;
1929 }
1930
1931 if (0 == strcmp("handler", key)) {
1932 const char *value = luaL_checkstring(L, 3);
1933 r->handler = apr_pstrdup(r->pool, value);
1934 return 0;
1935 }
1936
1937 if (0 == strcmp("proxyreq", key)) {
1938 int value = luaL_checkinteger(L, 3);
1939 r->proxyreq = value;
1940 return 0;
1941 }
1942
1943 if (0 == strcmp("status", key)) {
1944 int code = luaL_checkinteger(L, 3);
1945 r->status = code;
1946 return 0;
1947 }
1948
1949 if (0 == strcmp("uri", key)) {
1950 const char *value = luaL_checkstring(L, 3);
1951 r->uri = apr_pstrdup(r->pool, value);
1952 return 0;
1953 }
1954
1955 if (0 == strcmp("user", key)) {
1956 const char *value = luaL_checkstring(L, 3);
1957 r->user = apr_pstrdup(r->pool, value);
1958 return 0;
1959 }
1960
1961 lua_pushstring(L,
1962 apr_psprintf(r->pool,
1963 "Property [%s] may not be set on a request_rec",
1964 key));
1965 lua_error(L);
1966 return 0;
1967 }
1968
1969 static const struct luaL_Reg request_methods[] = {
1970 {"__index", req_dispatch},
1971 {"__newindex", req_newindex},
1972 /* {"__newindex", req_set_field}, */
1973 {NULL, NULL}
1974 };
1975
1976
1977 static const struct luaL_Reg connection_methods[] = {
1978 {NULL, NULL}
1979 };
1980
lua_ap_auth_name(request_rec * r)1981 static const char* lua_ap_auth_name(request_rec* r)
1982 {
1983 const char *name;
1984 name = ap_auth_name(r);
1985 return name ? name : "";
1986 }
1987
lua_ap_get_server_name(request_rec * r)1988 static const char* lua_ap_get_server_name(request_rec* r)
1989 {
1990 const char *name;
1991 name = ap_get_server_name(r);
1992 return name ? name : "localhost";
1993 }
1994
1995
1996
1997 static const struct luaL_Reg server_methods[] = {
1998 {NULL, NULL}
1999 };
2000
2001
makefun(const void * fun,int type,apr_pool_t * pool)2002 static req_fun_t *makefun(const void *fun, int type, apr_pool_t *pool)
2003 {
2004 req_fun_t *rft = apr_palloc(pool, sizeof(req_fun_t));
2005 rft->fun = fun;
2006 rft->type = type;
2007 return rft;
2008 }
2009
ap_lua_load_request_lmodule(lua_State * L,apr_pool_t * p)2010 void ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p)
2011 {
2012
2013 apr_hash_t *dispatch = apr_hash_make(p);
2014
2015 apr_hash_set(dispatch, "puts", APR_HASH_KEY_STRING,
2016 makefun(&req_puts, APL_REQ_FUNTYPE_LUACFUN, p));
2017 apr_hash_set(dispatch, "write", APR_HASH_KEY_STRING,
2018 makefun(&req_write, APL_REQ_FUNTYPE_LUACFUN, p));
2019 apr_hash_set(dispatch, "document_root", APR_HASH_KEY_STRING,
2020 makefun(&req_document_root, APL_REQ_FUNTYPE_STRING, p));
2021 apr_hash_set(dispatch, "context_prefix", APR_HASH_KEY_STRING,
2022 makefun(&req_context_prefix, APL_REQ_FUNTYPE_STRING, p));
2023 apr_hash_set(dispatch, "context_document_root", APR_HASH_KEY_STRING,
2024 makefun(&req_context_document_root, APL_REQ_FUNTYPE_STRING, p));
2025 apr_hash_set(dispatch, "parseargs", APR_HASH_KEY_STRING,
2026 makefun(&req_parseargs, APL_REQ_FUNTYPE_LUACFUN, p));
2027 apr_hash_set(dispatch, "parsebody", APR_HASH_KEY_STRING,
2028 makefun(&req_parsebody, APL_REQ_FUNTYPE_LUACFUN, p));
2029 apr_hash_set(dispatch, "debug", APR_HASH_KEY_STRING,
2030 makefun(&req_debug, APL_REQ_FUNTYPE_LUACFUN, p));
2031 apr_hash_set(dispatch, "info", APR_HASH_KEY_STRING,
2032 makefun(&req_info, APL_REQ_FUNTYPE_LUACFUN, p));
2033 apr_hash_set(dispatch, "notice", APR_HASH_KEY_STRING,
2034 makefun(&req_notice, APL_REQ_FUNTYPE_LUACFUN, p));
2035 apr_hash_set(dispatch, "warn", APR_HASH_KEY_STRING,
2036 makefun(&req_warn, APL_REQ_FUNTYPE_LUACFUN, p));
2037 apr_hash_set(dispatch, "err", APR_HASH_KEY_STRING,
2038 makefun(&req_err, APL_REQ_FUNTYPE_LUACFUN, p));
2039 apr_hash_set(dispatch, "crit", APR_HASH_KEY_STRING,
2040 makefun(&req_crit, APL_REQ_FUNTYPE_LUACFUN, p));
2041 apr_hash_set(dispatch, "alert", APR_HASH_KEY_STRING,
2042 makefun(&req_alert, APL_REQ_FUNTYPE_LUACFUN, p));
2043 apr_hash_set(dispatch, "emerg", APR_HASH_KEY_STRING,
2044 makefun(&req_emerg, APL_REQ_FUNTYPE_LUACFUN, p));
2045 apr_hash_set(dispatch, "trace1", APR_HASH_KEY_STRING,
2046 makefun(&req_trace1, APL_REQ_FUNTYPE_LUACFUN, p));
2047 apr_hash_set(dispatch, "trace2", APR_HASH_KEY_STRING,
2048 makefun(&req_trace2, APL_REQ_FUNTYPE_LUACFUN, p));
2049 apr_hash_set(dispatch, "trace3", APR_HASH_KEY_STRING,
2050 makefun(&req_trace3, APL_REQ_FUNTYPE_LUACFUN, p));
2051 apr_hash_set(dispatch, "trace4", APR_HASH_KEY_STRING,
2052 makefun(&req_trace4, APL_REQ_FUNTYPE_LUACFUN, p));
2053 apr_hash_set(dispatch, "trace5", APR_HASH_KEY_STRING,
2054 makefun(&req_trace5, APL_REQ_FUNTYPE_LUACFUN, p));
2055 apr_hash_set(dispatch, "trace6", APR_HASH_KEY_STRING,
2056 makefun(&req_trace6, APL_REQ_FUNTYPE_LUACFUN, p));
2057 apr_hash_set(dispatch, "trace7", APR_HASH_KEY_STRING,
2058 makefun(&req_trace7, APL_REQ_FUNTYPE_LUACFUN, p));
2059 apr_hash_set(dispatch, "trace8", APR_HASH_KEY_STRING,
2060 makefun(&req_trace8, APL_REQ_FUNTYPE_LUACFUN, p));
2061 apr_hash_set(dispatch, "add_output_filter", APR_HASH_KEY_STRING,
2062 makefun(&req_add_output_filter, APL_REQ_FUNTYPE_LUACFUN, p));
2063 apr_hash_set(dispatch, "construct_url", APR_HASH_KEY_STRING,
2064 makefun(&req_construct_url, APL_REQ_FUNTYPE_LUACFUN, p));
2065 apr_hash_set(dispatch, "escape_html", APR_HASH_KEY_STRING,
2066 makefun(&req_escape_html, APL_REQ_FUNTYPE_LUACFUN, p));
2067 apr_hash_set(dispatch, "ssl_var_lookup", APR_HASH_KEY_STRING,
2068 makefun(&req_ssl_var_lookup, APL_REQ_FUNTYPE_LUACFUN, p));
2069 apr_hash_set(dispatch, "is_https", APR_HASH_KEY_STRING,
2070 makefun(&req_ssl_is_https_field, APL_REQ_FUNTYPE_BOOLEAN, p));
2071 apr_hash_set(dispatch, "assbackwards", APR_HASH_KEY_STRING,
2072 makefun(&req_assbackwards_field, APL_REQ_FUNTYPE_BOOLEAN, p));
2073 apr_hash_set(dispatch, "status", APR_HASH_KEY_STRING,
2074 makefun(&req_status_field, APL_REQ_FUNTYPE_INT, p));
2075 apr_hash_set(dispatch, "protocol", APR_HASH_KEY_STRING,
2076 makefun(&req_protocol_field, APL_REQ_FUNTYPE_STRING, p));
2077 apr_hash_set(dispatch, "range", APR_HASH_KEY_STRING,
2078 makefun(&req_range_field, APL_REQ_FUNTYPE_STRING, p));
2079 apr_hash_set(dispatch, "content_type", APR_HASH_KEY_STRING,
2080 makefun(&req_content_type_field, APL_REQ_FUNTYPE_STRING, p));
2081 apr_hash_set(dispatch, "content_encoding", APR_HASH_KEY_STRING,
2082 makefun(&req_content_encoding_field, APL_REQ_FUNTYPE_STRING,
2083 p));
2084 apr_hash_set(dispatch, "ap_auth_type", APR_HASH_KEY_STRING,
2085 makefun(&req_ap_auth_type_field, APL_REQ_FUNTYPE_STRING, p));
2086 apr_hash_set(dispatch, "unparsed_uri", APR_HASH_KEY_STRING,
2087 makefun(&req_unparsed_uri_field, APL_REQ_FUNTYPE_STRING, p));
2088 apr_hash_set(dispatch, "user", APR_HASH_KEY_STRING,
2089 makefun(&req_user_field, APL_REQ_FUNTYPE_STRING, p));
2090 apr_hash_set(dispatch, "filename", APR_HASH_KEY_STRING,
2091 makefun(&req_filename_field, APL_REQ_FUNTYPE_STRING, p));
2092 apr_hash_set(dispatch, "canonical_filename", APR_HASH_KEY_STRING,
2093 makefun(&req_canonical_filename_field,
2094 APL_REQ_FUNTYPE_STRING, p));
2095 apr_hash_set(dispatch, "path_info", APR_HASH_KEY_STRING,
2096 makefun(&req_path_info_field, APL_REQ_FUNTYPE_STRING, p));
2097 apr_hash_set(dispatch, "args", APR_HASH_KEY_STRING,
2098 makefun(&req_args_field, APL_REQ_FUNTYPE_STRING, p));
2099 apr_hash_set(dispatch, "handler", APR_HASH_KEY_STRING,
2100 makefun(&req_handler_field, APL_REQ_FUNTYPE_STRING, p));
2101 apr_hash_set(dispatch, "hostname", APR_HASH_KEY_STRING,
2102 makefun(&req_hostname_field, APL_REQ_FUNTYPE_STRING, p));
2103 apr_hash_set(dispatch, "uri", APR_HASH_KEY_STRING,
2104 makefun(&req_uri_field, APL_REQ_FUNTYPE_STRING, p));
2105 apr_hash_set(dispatch, "the_request", APR_HASH_KEY_STRING,
2106 makefun(&req_the_request_field, APL_REQ_FUNTYPE_STRING, p));
2107 apr_hash_set(dispatch, "log_id", APR_HASH_KEY_STRING,
2108 makefun(&req_log_id_field, APL_REQ_FUNTYPE_STRING, p));
2109 apr_hash_set(dispatch, "useragent_ip", APR_HASH_KEY_STRING,
2110 makefun(&req_useragent_ip_field, APL_REQ_FUNTYPE_STRING, p));
2111 apr_hash_set(dispatch, "method", APR_HASH_KEY_STRING,
2112 makefun(&req_method_field, APL_REQ_FUNTYPE_STRING, p));
2113 apr_hash_set(dispatch, "proxyreq", APR_HASH_KEY_STRING,
2114 makefun(&req_proxyreq_field, APL_REQ_FUNTYPE_STRING, p));
2115 apr_hash_set(dispatch, "headers_in", APR_HASH_KEY_STRING,
2116 makefun(&req_headers_in, APL_REQ_FUNTYPE_TABLE, p));
2117 apr_hash_set(dispatch, "headers_out", APR_HASH_KEY_STRING,
2118 makefun(&req_headers_out, APL_REQ_FUNTYPE_TABLE, p));
2119 apr_hash_set(dispatch, "err_headers_out", APR_HASH_KEY_STRING,
2120 makefun(&req_err_headers_out, APL_REQ_FUNTYPE_TABLE, p));
2121 apr_hash_set(dispatch, "notes", APR_HASH_KEY_STRING,
2122 makefun(&req_notes, APL_REQ_FUNTYPE_TABLE, p));
2123 apr_hash_set(dispatch, "subprocess_env", APR_HASH_KEY_STRING,
2124 makefun(&req_subprocess_env, APL_REQ_FUNTYPE_TABLE, p));
2125 apr_hash_set(dispatch, "flush", APR_HASH_KEY_STRING,
2126 makefun(&lua_ap_rflush, APL_REQ_FUNTYPE_LUACFUN, p));
2127 apr_hash_set(dispatch, "port", APR_HASH_KEY_STRING,
2128 makefun(&req_ap_get_server_port, APL_REQ_FUNTYPE_INT, p));
2129 apr_hash_set(dispatch, "banner", APR_HASH_KEY_STRING,
2130 makefun(&ap_get_server_banner, APL_REQ_FUNTYPE_STRING, p));
2131 apr_hash_set(dispatch, "options", APR_HASH_KEY_STRING,
2132 makefun(&lua_ap_options, APL_REQ_FUNTYPE_STRING, p));
2133 apr_hash_set(dispatch, "allowoverrides", APR_HASH_KEY_STRING,
2134 makefun(&lua_ap_allowoverrides, APL_REQ_FUNTYPE_STRING, p));
2135 apr_hash_set(dispatch, "started", APR_HASH_KEY_STRING,
2136 makefun(&lua_ap_started, APL_REQ_FUNTYPE_INT, p));
2137 apr_hash_set(dispatch, "basic_auth_pw", APR_HASH_KEY_STRING,
2138 makefun(&lua_ap_basic_auth_pw, APL_REQ_FUNTYPE_STRING, p));
2139 apr_hash_set(dispatch, "limit_req_body", APR_HASH_KEY_STRING,
2140 makefun(&lua_ap_limit_req_body, APL_REQ_FUNTYPE_INT, p));
2141 apr_hash_set(dispatch, "server_built", APR_HASH_KEY_STRING,
2142 makefun(&ap_get_server_built, APL_REQ_FUNTYPE_STRING, p));
2143 apr_hash_set(dispatch, "is_initial_req", APR_HASH_KEY_STRING,
2144 makefun(&lua_ap_is_initial_req, APL_REQ_FUNTYPE_BOOLEAN, p));
2145 apr_hash_set(dispatch, "remaining", APR_HASH_KEY_STRING,
2146 makefun(&req_remaining_field, APL_REQ_FUNTYPE_INT, p));
2147 apr_hash_set(dispatch, "some_auth_required", APR_HASH_KEY_STRING,
2148 makefun(&lua_ap_some_auth_required, APL_REQ_FUNTYPE_BOOLEAN, p));
2149 apr_hash_set(dispatch, "server_name", APR_HASH_KEY_STRING,
2150 makefun(&lua_ap_get_server_name, APL_REQ_FUNTYPE_STRING, p));
2151 apr_hash_set(dispatch, "auth_name", APR_HASH_KEY_STRING,
2152 makefun(&lua_ap_auth_name, APL_REQ_FUNTYPE_STRING, p));
2153 apr_hash_set(dispatch, "sendfile", APR_HASH_KEY_STRING,
2154 makefun(&lua_ap_sendfile, APL_REQ_FUNTYPE_LUACFUN, p));
2155 apr_hash_set(dispatch, "dbacquire", APR_HASH_KEY_STRING,
2156 makefun(&lua_db_acquire, APL_REQ_FUNTYPE_LUACFUN, p));
2157 apr_hash_set(dispatch, "stat", APR_HASH_KEY_STRING,
2158 makefun(&lua_ap_stat, APL_REQ_FUNTYPE_LUACFUN, p));
2159 apr_hash_set(dispatch, "get_direntries", APR_HASH_KEY_STRING,
2160 makefun(&lua_ap_getdir, APL_REQ_FUNTYPE_LUACFUN, p));
2161 apr_hash_set(dispatch, "regex", APR_HASH_KEY_STRING,
2162 makefun(&lua_ap_regex, APL_REQ_FUNTYPE_LUACFUN, p));
2163 apr_hash_set(dispatch, "usleep", APR_HASH_KEY_STRING,
2164 makefun(&lua_ap_usleep, APL_REQ_FUNTYPE_LUACFUN, p));
2165 apr_hash_set(dispatch, "base64_encode", APR_HASH_KEY_STRING,
2166 makefun(&lua_apr_b64encode, APL_REQ_FUNTYPE_LUACFUN, p));
2167 apr_hash_set(dispatch, "base64_decode", APR_HASH_KEY_STRING,
2168 makefun(&lua_apr_b64decode, APL_REQ_FUNTYPE_LUACFUN, p));
2169 apr_hash_set(dispatch, "md5", APR_HASH_KEY_STRING,
2170 makefun(&lua_apr_md5, APL_REQ_FUNTYPE_LUACFUN, p));
2171 apr_hash_set(dispatch, "sha1", APR_HASH_KEY_STRING,
2172 makefun(&lua_apr_sha1, APL_REQ_FUNTYPE_LUACFUN, p));
2173 apr_hash_set(dispatch, "htpassword", APR_HASH_KEY_STRING,
2174 makefun(&lua_apr_htpassword, APL_REQ_FUNTYPE_LUACFUN, p));
2175 apr_hash_set(dispatch, "touch", APR_HASH_KEY_STRING,
2176 makefun(&lua_apr_touch, APL_REQ_FUNTYPE_LUACFUN, p));
2177 apr_hash_set(dispatch, "mkdir", APR_HASH_KEY_STRING,
2178 makefun(&lua_apr_mkdir, APL_REQ_FUNTYPE_LUACFUN, p));
2179 apr_hash_set(dispatch, "mkrdir", APR_HASH_KEY_STRING,
2180 makefun(&lua_apr_mkrdir, APL_REQ_FUNTYPE_LUACFUN, p));
2181 apr_hash_set(dispatch, "rmdir", APR_HASH_KEY_STRING,
2182 makefun(&lua_apr_rmdir, APL_REQ_FUNTYPE_LUACFUN, p));
2183 apr_hash_set(dispatch, "date_parse_rfc", APR_HASH_KEY_STRING,
2184 makefun(&lua_apr_date_parse_rfc, APL_REQ_FUNTYPE_LUACFUN, p));
2185 apr_hash_set(dispatch, "escape", APR_HASH_KEY_STRING,
2186 makefun(&lua_ap_escape, APL_REQ_FUNTYPE_LUACFUN, p));
2187 apr_hash_set(dispatch, "unescape", APR_HASH_KEY_STRING,
2188 makefun(&lua_ap_unescape, APL_REQ_FUNTYPE_LUACFUN, p));
2189 apr_hash_set(dispatch, "mpm_query", APR_HASH_KEY_STRING,
2190 makefun(&lua_ap_mpm_query, APL_REQ_FUNTYPE_LUACFUN, p));
2191 apr_hash_set(dispatch, "expr", APR_HASH_KEY_STRING,
2192 makefun(&lua_ap_expr, APL_REQ_FUNTYPE_LUACFUN, p));
2193 apr_hash_set(dispatch, "scoreboard_process", APR_HASH_KEY_STRING,
2194 makefun(&lua_ap_scoreboard_process, APL_REQ_FUNTYPE_LUACFUN, p));
2195 apr_hash_set(dispatch, "scoreboard_worker", APR_HASH_KEY_STRING,
2196 makefun(&lua_ap_scoreboard_worker, APL_REQ_FUNTYPE_LUACFUN, p));
2197 apr_hash_set(dispatch, "clock", APR_HASH_KEY_STRING,
2198 makefun(&lua_ap_clock, APL_REQ_FUNTYPE_LUACFUN, p));
2199 apr_hash_set(dispatch, "requestbody", APR_HASH_KEY_STRING,
2200 makefun(&lua_ap_requestbody, APL_REQ_FUNTYPE_LUACFUN, p));
2201 apr_hash_set(dispatch, "add_input_filter", APR_HASH_KEY_STRING,
2202 makefun(&lua_ap_add_input_filter, APL_REQ_FUNTYPE_LUACFUN, p));
2203 apr_hash_set(dispatch, "module_info", APR_HASH_KEY_STRING,
2204 makefun(&lua_ap_module_info, APL_REQ_FUNTYPE_LUACFUN, p));
2205 apr_hash_set(dispatch, "loaded_modules", APR_HASH_KEY_STRING,
2206 makefun(&lua_ap_loaded_modules, APL_REQ_FUNTYPE_LUACFUN, p));
2207 apr_hash_set(dispatch, "runtime_dir_relative", APR_HASH_KEY_STRING,
2208 makefun(&lua_ap_runtime_dir_relative, APL_REQ_FUNTYPE_LUACFUN, p));
2209 apr_hash_set(dispatch, "server_info", APR_HASH_KEY_STRING,
2210 makefun(&lua_ap_server_info, APL_REQ_FUNTYPE_LUACFUN, p));
2211 apr_hash_set(dispatch, "set_document_root", APR_HASH_KEY_STRING,
2212 makefun(&lua_ap_set_document_root, APL_REQ_FUNTYPE_LUACFUN, p));
2213 apr_hash_set(dispatch, "set_context_info", APR_HASH_KEY_STRING,
2214 makefun(&lua_ap_set_context_info, APL_REQ_FUNTYPE_LUACFUN, p));
2215 apr_hash_set(dispatch, "os_escape_path", APR_HASH_KEY_STRING,
2216 makefun(&lua_ap_os_escape_path, APL_REQ_FUNTYPE_LUACFUN, p));
2217 apr_hash_set(dispatch, "escape_logitem", APR_HASH_KEY_STRING,
2218 makefun(&lua_ap_escape_logitem, APL_REQ_FUNTYPE_LUACFUN, p));
2219 apr_hash_set(dispatch, "strcmp_match", APR_HASH_KEY_STRING,
2220 makefun(&lua_ap_strcmp_match, APL_REQ_FUNTYPE_LUACFUN, p));
2221 apr_hash_set(dispatch, "set_keepalive", APR_HASH_KEY_STRING,
2222 makefun(&lua_ap_set_keepalive, APL_REQ_FUNTYPE_LUACFUN, p));
2223 apr_hash_set(dispatch, "make_etag", APR_HASH_KEY_STRING,
2224 makefun(&lua_ap_make_etag, APL_REQ_FUNTYPE_LUACFUN, p));
2225 apr_hash_set(dispatch, "send_interim_response", APR_HASH_KEY_STRING,
2226 makefun(&lua_ap_send_interim_response, APL_REQ_FUNTYPE_LUACFUN, p));
2227 apr_hash_set(dispatch, "custom_response", APR_HASH_KEY_STRING,
2228 makefun(&lua_ap_custom_response, APL_REQ_FUNTYPE_LUACFUN, p));
2229 apr_hash_set(dispatch, "exists_config_define", APR_HASH_KEY_STRING,
2230 makefun(&lua_ap_exists_config_define, APL_REQ_FUNTYPE_LUACFUN, p));
2231 apr_hash_set(dispatch, "state_query", APR_HASH_KEY_STRING,
2232 makefun(&lua_ap_state_query, APL_REQ_FUNTYPE_LUACFUN, p));
2233 apr_hash_set(dispatch, "get_server_name_for_url", APR_HASH_KEY_STRING,
2234 makefun(&lua_ap_get_server_name_for_url, APL_REQ_FUNTYPE_LUACFUN, p));
2235 apr_hash_set(dispatch, "ivm_get", APR_HASH_KEY_STRING,
2236 makefun(&lua_ivm_get, APL_REQ_FUNTYPE_LUACFUN, p));
2237 apr_hash_set(dispatch, "ivm_set", APR_HASH_KEY_STRING,
2238 makefun(&lua_ivm_set, APL_REQ_FUNTYPE_LUACFUN, p));
2239
2240 lua_pushlightuserdata(L, dispatch);
2241 lua_setfield(L, LUA_REGISTRYINDEX, "Apache2.Request.dispatch");
2242
2243 luaL_newmetatable(L, "Apache2.Request"); /* [metatable] */
2244 lua_pushvalue(L, -1);
2245
2246 lua_setfield(L, -2, "__index");
2247 luaL_register(L, NULL, request_methods); /* [metatable] */
2248
2249 lua_pop(L, 2);
2250
2251 luaL_newmetatable(L, "Apache2.Connection"); /* [metatable] */
2252 lua_pushvalue(L, -1);
2253
2254 lua_setfield(L, -2, "__index");
2255 luaL_register(L, NULL, connection_methods); /* [metatable] */
2256
2257 lua_pop(L, 2);
2258
2259 luaL_newmetatable(L, "Apache2.Server"); /* [metatable] */
2260 lua_pushvalue(L, -1);
2261
2262 lua_setfield(L, -2, "__index");
2263 luaL_register(L, NULL, server_methods); /* [metatable] */
2264
2265 lua_pop(L, 2);
2266
2267 }
2268
ap_lua_push_connection(lua_State * L,conn_rec * c)2269 void ap_lua_push_connection(lua_State *L, conn_rec *c)
2270 {
2271 lua_boxpointer(L, c);
2272 luaL_getmetatable(L, "Apache2.Connection");
2273 lua_setmetatable(L, -2);
2274 luaL_getmetatable(L, "Apache2.Connection");
2275
2276 ap_lua_push_apr_table(L, c->notes);
2277 lua_setfield(L, -2, "notes");
2278
2279 lua_pushstring(L, c->client_ip);
2280 lua_setfield(L, -2, "client_ip");
2281
2282 lua_pop(L, 1);
2283 }
2284
2285
ap_lua_push_server(lua_State * L,server_rec * s)2286 void ap_lua_push_server(lua_State *L, server_rec *s)
2287 {
2288 lua_boxpointer(L, s);
2289 luaL_getmetatable(L, "Apache2.Server");
2290 lua_setmetatable(L, -2);
2291 luaL_getmetatable(L, "Apache2.Server");
2292
2293 lua_pushstring(L, s->server_hostname);
2294 lua_setfield(L, -2, "server_hostname");
2295
2296 lua_pop(L, 1);
2297 }
2298
ap_lua_push_request(lua_State * L,request_rec * r)2299 void ap_lua_push_request(lua_State *L, request_rec *r)
2300 {
2301 lua_boxpointer(L, r);
2302 luaL_getmetatable(L, "Apache2.Request");
2303 lua_setmetatable(L, -2);
2304 }
2305