From: Daniel Gruno Date: Sat, 29 Mar 2014 09:15:33 +0000 (+0000) Subject: mod_lua: Give me all the backports and eggs you have. (see CHANGES) X-Git-Tag: 2.4.10~399 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=707e187891393ac3c8ab61b390817e1c4ba800fa;p=apache mod_lua: Give me all the backports and eggs you have. (see CHANGES) git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1582968 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index e15c142da4..6136270c98 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,12 @@ Changes with Apache 2.4.10 + *) mod_lua: Redesign how request record table access behaves, + in order to utilize the request record from within these tables + [Daniel Gruno] + + *) mod_lua: Add r:wspeek for peeking at WebSocket frames. [Daniel Gruno] + *) mod_lua: Log an error when the initial parsing of a Lua file fails. [Daniel Gruno, Felipe Daragon ] diff --git a/modules/lua/lua_apr.c b/modules/lua/lua_apr.c index d8c59d0e16..94761ba4b2 100644 --- a/modules/lua/lua_apr.c +++ b/modules/lua/lua_apr.c @@ -17,17 +17,18 @@ #include "mod_lua.h" #include "lua_apr.h" +APLOG_USE_MODULE(lua); -apr_table_t *ap_lua_check_apr_table(lua_State *L, int index) +req_table_t *ap_lua_check_apr_table(lua_State *L, int index) { - apr_table_t *t; + req_table_t* t; luaL_checkudata(L, index, "Apr.Table"); t = lua_unboxpointer(L, index); return t; } -void ap_lua_push_apr_table(lua_State *L, apr_table_t *t) +void ap_lua_push_apr_table(lua_State *L, req_table_t *t) { lua_boxpointer(L, t); luaL_getmetatable(L, "Apr.Table"); @@ -36,26 +37,37 @@ void ap_lua_push_apr_table(lua_State *L, apr_table_t *t) static int lua_table_set(lua_State *L) { - apr_table_t *t = ap_lua_check_apr_table(L, 1); + req_table_t *t = ap_lua_check_apr_table(L, 1); const char *key = luaL_checkstring(L, 2); const char *val = luaL_checkstring(L, 3); - - /* Prevent response/header splitting by not allowing newlines in tables. - * At this stage, we don't have the request_rec handy, and we can't change - * a const char*, so we'll redirect to a standard error value instead. - */ - if (ap_strchr_c(val, '\n')) { - val = "[ERROR: Value contains newline, ignored.]"; + /* Unless it's the 'notes' table, check for newline chars */ + /* t->r will be NULL in case of the connection notes, but since + we aren't going to check anything called 'notes', we can safely + disregard checking whether t->r is defined. + */ + if (strcmp(t->n, "notes") && ap_strchr_c(val, '\n')) { + char *badchar; + char *replacement = apr_pstrdup(t->r->pool, val); + badchar = replacement; + while ( (badchar = ap_strchr(badchar, '\n')) ) { + *badchar = ' '; + } + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, t->r, + APLOGNO(02614) "mod_lua: Value for '%s' in table '%s' contains newline!", + key, t->n); + apr_table_set(t->t, key, replacement); + } + else { + apr_table_set(t->t, key, val); } - apr_table_set(t, key, val); return 0; } static int lua_table_get(lua_State *L) { - apr_table_t *t = ap_lua_check_apr_table(L, 1); + req_table_t *t = ap_lua_check_apr_table(L, 1); const char *key = luaL_checkstring(L, 2); - const char *val = apr_table_get(t, key); + const char *val = apr_table_get(t->t, key); lua_pushstring(L, val); return 1; } diff --git a/modules/lua/lua_apr.h b/modules/lua/lua_apr.h index 8a1428ffbb..c194f11cbb 100644 --- a/modules/lua/lua_apr.h +++ b/modules/lua/lua_apr.h @@ -30,7 +30,7 @@ int ap_lua_init(lua_State *L, apr_pool_t * p); -apr_table_t *ap_lua_check_apr_table(lua_State *L, int index); -void ap_lua_push_apr_table(lua_State *L, apr_table_t *t); +req_table_t *ap_lua_check_apr_table(lua_State *L, int index); +void ap_lua_push_apr_table(lua_State *L, req_table_t *t); #endif /* !_LUA_APR_H_ */ diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c index f3217f38d8..4201609eab 100644 --- a/modules/lua/lua_request.c +++ b/modules/lua/lua_request.c @@ -43,7 +43,7 @@ APLOG_USE_MODULE(lua); typedef char *(*req_field_string_f) (request_rec * r); typedef int (*req_field_int_f) (request_rec * r); -typedef apr_table_t *(*req_field_apr_table_f) (request_rec * r); +typedef req_table_t *(*req_field_apr_table_f) (request_rec * r); void ap_lua_rstack_dump(lua_State *L, request_rec *r, const char *msg) @@ -640,29 +640,49 @@ static int req_assbackwards_field(request_rec *r) return r->assbackwards; } -static apr_table_t* req_headers_in(request_rec *r) +static req_table_t* req_headers_in(request_rec *r) { - return r->headers_in; + req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t)); + t->r = r; + t->t = r->headers_in; + t->n = "headers_in"; + return t; } -static apr_table_t* req_headers_out(request_rec *r) +static req_table_t* req_headers_out(request_rec *r) { - return r->headers_out; + req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t)); + t->r = r; + t->t = r->headers_out; + t->n = "headers_out"; + return t; } -static apr_table_t* req_err_headers_out(request_rec *r) +static req_table_t* req_err_headers_out(request_rec *r) { - return r->err_headers_out; + req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t)); + t->r = r; + t->t = r->err_headers_out; + t->n = "err_headers_out"; + return t; } -static apr_table_t* req_subprocess_env(request_rec *r) +static req_table_t* req_subprocess_env(request_rec *r) { - return r->subprocess_env; + req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t)); + t->r = r; + t->t = r->subprocess_env; + t->n = "subprocess_env"; + return t; } -static apr_table_t* req_notes(request_rec *r) +static req_table_t* req_notes(request_rec *r) { - return r->notes; + req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t)); + t->r = r; + t->t = r->notes; + t->n = "notes"; + return t; } static int req_ssl_is_https_field(request_rec *r) @@ -1784,7 +1804,7 @@ static int req_dispatch(lua_State *L) if (rft) { switch (rft->type) { case APL_REQ_FUNTYPE_TABLE:{ - apr_table_t *rs; + req_table_t *rs; req_field_apr_table_f func = (req_field_apr_table_f)rft->fun; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01486) "request_rec->dispatching %s -> apr table", @@ -2152,6 +2172,27 @@ static apr_status_t lua_websocket_readbytes(conn_rec* c, char* buffer, return rv; } +static int lua_websocket_peek(lua_State *L) +{ + apr_status_t rv; + apr_bucket_brigade *brigade; + + request_rec *r = ap_lua_check_request_rec(L, 1); + + brigade = apr_brigade_create(r->connection->pool, + r->connection->bucket_alloc); + rv = ap_get_brigade(r->connection->input_filters, brigade, + AP_MODE_READBYTES, APR_NONBLOCK_READ, 1); + if (rv == APR_SUCCESS) { + lua_pushboolean(L, 1); + } + else { + lua_pushboolean(L, 0); + } + apr_brigade_cleanup(brigade); + return 1; +} + static int lua_websocket_read(lua_State *L) { apr_socket_t *sock; @@ -2791,12 +2832,15 @@ void ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p) makefun(&lua_websocket_greet, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "wsread", APR_HASH_KEY_STRING, makefun(&lua_websocket_read, APL_REQ_FUNTYPE_LUACFUN, p)); + apr_hash_set(dispatch, "wspeek", APR_HASH_KEY_STRING, + makefun(&lua_websocket_peek, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "wswrite", APR_HASH_KEY_STRING, makefun(&lua_websocket_write, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "wsclose", APR_HASH_KEY_STRING, makefun(&lua_websocket_close, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "wsping", APR_HASH_KEY_STRING, makefun(&lua_websocket_ping, APL_REQ_FUNTYPE_LUACFUN, p)); + lua_pushlightuserdata(L, dispatch); @@ -2830,12 +2874,17 @@ void ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p) void ap_lua_push_connection(lua_State *L, conn_rec *c) { + req_table_t *t; lua_boxpointer(L, c); luaL_getmetatable(L, "Apache2.Connection"); lua_setmetatable(L, -2); luaL_getmetatable(L, "Apache2.Connection"); - ap_lua_push_apr_table(L, c->notes); + t = apr_pcalloc(c->pool, sizeof(req_table_t)); + t->t = c->notes; + t->r = NULL; + t->n = "notes"; + ap_lua_push_apr_table(L, t); lua_setfield(L, -2, "notes"); lua_pushstring(L, c->client_ip); diff --git a/modules/lua/lua_request.h b/modules/lua/lua_request.h index b5ed3e5fc0..eee6a7a8aa 100644 --- a/modules/lua/lua_request.h +++ b/modules/lua/lua_request.h @@ -38,6 +38,15 @@ typedef struct int type; } req_fun_t; + +/* Struct to use as userdata for request_rec tables */ +typedef struct +{ + request_rec *r; /* Request_rec */ + apr_table_t *t; /* apr_table_t* */ + char *n; /* name of table */ +} req_table_t; + typedef struct { int type; size_t size;