}
case LUA_TTABLE:{
/* [array, table<s,t>, table<s,s>] */
- int size = lua_objlen(L, -1);
+ int size = lua_rawlen(L, -1);
lua_pushnumber(L, size + 1); /* [#, array, table<s,t>, table<s,s>] */
lua_pushstring(L, value); /* [string, #, array, table<s,t>, table<s,s>] */
lua_settable(L, -3); /* [array, table<s,t>, table<s,s>] */
lua_setfield(L, -2, key); /* [table<s,t>, table<s,s>] */
break;
}
+
case LUA_TTABLE:{
/* [array, table<s,t>, table<s,s>] */
- int size = lua_objlen(L, -1);
+ int size = lua_rawlen(L, -1);
lua_pushnumber(L, size + 1); /* [#, array, table<s,t>, table<s,s>] */
lua_pushlstring(L, value, len); /* [string, #, array, table<s,t>, table<s,s>] */
lua_settable(L, -3); /* [array, table<s,t>, table<s,s>] */
len_read,
rpos = 0;
apr_off_t length = r->remaining;
- apr_size_t written;
*size = length;
while ((len_read =
rsize = len_read;
rc = apr_file_write_full(file, argsbuffer, (apr_size_t) rsize,
- &written);
- if (written != rsize || rc != OK)
- return APR_ENOSPC;
+ NULL);
if (rc != APR_SUCCESS)
return rc;
rpos += rsize;
sscanf(start + len + 2,
"Content-Disposition: form-data; name=\"%255[^\"]\"; filename=\"%255[^\"]\"",
key, filename);
- if (strlen(key)) {
+ if (*key) {
req_aprtable2luatable_cb_len(L, key, buffer, vlen);
}
}
return r->assbackwards;
}
-static req_table_t *req_headers_in(request_rec *r)
+static req_table_t* req_headers_in(request_rec *r)
{
- req_table_t *t = apr_palloc(r->pool, sizeof(req_table_t));
+ 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 req_table_t *req_headers_out(request_rec *r)
+static req_table_t* req_headers_out(request_rec *r)
{
- req_table_t *t = apr_palloc(r->pool, sizeof(req_table_t));
+ 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 req_table_t *req_err_headers_out(request_rec *r)
+static req_table_t* req_err_headers_out(request_rec *r)
{
- req_table_t *t = apr_palloc(r->pool, sizeof(req_table_t));
+ 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 req_table_t *req_subprocess_env(request_rec *r)
+static req_table_t* req_subprocess_env(request_rec *r)
{
- req_table_t *t = apr_palloc(r->pool, sizeof(req_table_t));
+ 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 req_table_t *req_notes(request_rec *r)
+static req_table_t* req_notes(request_rec *r)
{
- req_table_t *t = apr_palloc(r->pool, sizeof(req_table_t));
+ req_table_t* t = apr_palloc(r->pool, sizeof(req_table_t));
t->r = r;
t->t = r->notes;
t->n = "notes";
lua_getinfo(L, "Sl", &dbg);
msg = luaL_checkstring(L, 2);
+ /* Intentional no APLOGNO */
ap_log_rerror(dbg.source, dbg.currentline, APLOG_MODULE_INDEX, level, 0,
r, "%s", msg);
return 0;
secure ? "Secure;" : "",
expires ? strexpires : "",
httponly ? "HttpOnly;" : "",
- strlen(strdomain) ? strdomain : "",
- strlen(strpath) ? strpath : "");
+ *strdomain ? strdomain : "",
+ *strpath ? strpath : "");
apr_table_add(r->err_headers_out, "Set-Cookie", out);
return 0;
encoded = apr_palloc(r->pool, encoded_len);
encoded_len = apr_base64_encode(encoded, (char*) digest, APR_SHA1_DIGESTSIZE);
r->status = 101;
- apr_table_set(r->headers_out, "Upgrade", "websocket");
- apr_table_set(r->headers_out, "Connection", "Upgrade");
- apr_table_set(r->headers_out, "Sec-WebSocket-Accept", encoded);
+ apr_table_setn(r->headers_out, "Upgrade", "websocket");
+ apr_table_setn(r->headers_out, "Connection", "Upgrade");
+ apr_table_setn(r->headers_out, "Sec-WebSocket-Accept", encoded);
/* Trick httpd into NOT using the chunked filter, IMPORTANT!!!111*/
- apr_table_set(r->headers_out, "Transfer-Encoding", "chunked");
+ apr_table_setn(r->headers_out, "Transfer-Encoding", "chunked");
r->clength = 0;
r->bytes_sent = 0;
mask_bytes = apr_pcalloc(r->pool, 4);
sock = ap_get_conn_socket(r->connection);
- while (do_read) {
- do_read = 0;
- /* Get opcode and FIN bit */
- if (plaintext) {
- rv = apr_socket_recv(sock, &byte, &len);
- }
- else {
- rv = lua_websocket_readbytes(r->connection, &byte, 1);
- }
- if (rv == APR_SUCCESS) {
- unsigned char ubyte, fin, opcode, mask, payload;
- ubyte = (unsigned char)byte;
- /* fin bit is the first bit */
- fin = ubyte >> (CHAR_BIT - 1);
- /* opcode is the last four bits (there's 3 reserved bits we don't care about) */
- opcode = ubyte & 0xf;
-
- /* Get the payload length and mask bit */
+ while (do_read) {
+ do_read = 0;
+ /* Get opcode and FIN bit */
if (plaintext) {
rv = apr_socket_recv(sock, &byte, &len);
}
rv = lua_websocket_readbytes(r->connection, &byte, 1);
}
if (rv == APR_SUCCESS) {
+ unsigned char ubyte, fin, opcode, mask, payload;
ubyte = (unsigned char)byte;
- /* Mask is the first bit */
- mask = ubyte >> (CHAR_BIT - 1);
- /* Payload is the last 7 bits */
- payload = ubyte & 0x7f;
- plen = payload;
-
- /* Extended payload? */
- if (payload == 126) {
- len = 2;
- if (plaintext) {
- /* XXX: apr_socket_recv does not receive len bits, only up to len bits! */
- rv = apr_socket_recv(sock, (char*) &payload_short, &len);
- }
- else {
- rv = lua_websocket_readbytes(r->connection,
- (char*) &payload_short, 2);
- }
- payload_short = ntohs(payload_short);
-
- if (rv == APR_SUCCESS) {
- plen = payload_short;
- }
- else {
- return 0;
- }
+ /* fin bit is the first bit */
+ fin = ubyte >> (CHAR_BIT - 1);
+ /* opcode is the last four bits (there's 3 reserved bits we don't care about) */
+ opcode = ubyte & 0xf;
+
+ /* Get the payload length and mask bit */
+ if (plaintext) {
+ rv = apr_socket_recv(sock, &byte, &len);
}
- /* Super duper extended payload? */
- if (payload == 127) {
- len = 8;
- if (plaintext) {
- rv = apr_socket_recv(sock, (char*) &payload_long, &len);
- }
- else {
- rv = lua_websocket_readbytes(r->connection,
- (char*) &payload_long, 8);
- }
- if (rv == APR_SUCCESS) {
- plen = ap_ntoh64(&payload_long);
- }
- else {
- return 0;
- }
+ else {
+ rv = lua_websocket_readbytes(r->connection, &byte, 1);
}
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03210)
- "Websocket: Reading %" APR_SIZE_T_FMT " (%s) bytes, masking is %s. %s",
- plen,
- (payload >= 126) ? "extra payload" : "no extra payload",
- mask ? "on" : "off",
- fin ? "This is a final frame" : "more to follow");
- if (mask) {
- len = 4;
- if (plaintext) {
- rv = apr_socket_recv(sock, (char*) mask_bytes, &len);
+ if (rv == APR_SUCCESS) {
+ ubyte = (unsigned char)byte;
+ /* Mask is the first bit */
+ mask = ubyte >> (CHAR_BIT - 1);
+ /* Payload is the last 7 bits */
+ payload = ubyte & 0x7f;
+ plen = payload;
+
+ /* Extended payload? */
+ if (payload == 126) {
+ len = 2;
+ if (plaintext) {
+ /* XXX: apr_socket_recv does not receive len bits, only up to len bits! */
+ rv = apr_socket_recv(sock, (char*) &payload_short, &len);
+ }
+ else {
+ rv = lua_websocket_readbytes(r->connection,
+ (char*) &payload_short, 2);
+ }
+ payload_short = ntohs(payload_short);
+
+ if (rv == APR_SUCCESS) {
+ plen = payload_short;
+ }
+ else {
+ return 0;
+ }
}
- else {
- rv = lua_websocket_readbytes(r->connection,
- (char*) mask_bytes, 4);
+ /* Super duper extended payload? */
+ if (payload == 127) {
+ len = 8;
+ if (plaintext) {
+ rv = apr_socket_recv(sock, (char*) &payload_long, &len);
+ }
+ else {
+ rv = lua_websocket_readbytes(r->connection,
+ (char*) &payload_long, 8);
+ }
+ if (rv == APR_SUCCESS) {
+ plen = ap_ntoh64(&payload_long);
+ }
+ else {
+ return 0;
+ }
}
- if (rv != APR_SUCCESS) {
- return 0;
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03210)
+ "Websocket: Reading %" APR_SIZE_T_FMT " (%s) bytes, masking is %s. %s",
+ plen,
+ (payload >= 126) ? "extra payload" : "no extra payload",
+ mask ? "on" : "off",
+ fin ? "This is a final frame" : "more to follow");
+ if (mask) {
+ len = 4;
+ if (plaintext) {
+ rv = apr_socket_recv(sock, (char*) mask_bytes, &len);
+ }
+ else {
+ rv = lua_websocket_readbytes(r->connection,
+ (char*) mask_bytes, 4);
+ }
+ if (rv != APR_SUCCESS) {
+ return 0;
+ }
}
- }
- if (plen < (HUGE_STRING_LEN*1024) && plen > 0) {
- apr_size_t remaining = plen;
- apr_size_t received;
- apr_off_t at = 0;
- char *buffer = apr_palloc(r->pool, plen+1);
- buffer[plen] = 0;
-
- if (plaintext) {
- while (remaining > 0) {
- received = remaining;
- rv = apr_socket_recv(sock, buffer+at, &received);
- if (received > 0 ) {
- remaining -= received;
- at += received;
+ if (plen < (HUGE_STRING_LEN*1024) && plen > 0) {
+ apr_size_t remaining = plen;
+ apr_size_t received;
+ apr_off_t at = 0;
+ char *buffer = apr_palloc(r->pool, plen+1);
+ buffer[plen] = 0;
+
+ if (plaintext) {
+ while (remaining > 0) {
+ received = remaining;
+ rv = apr_socket_recv(sock, buffer+at, &received);
+ if (received > 0 ) {
+ remaining -= received;
+ at += received;
+ }
}
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "Websocket: Frame contained %" APR_OFF_T_FMT " bytes, pushed to Lua stack",
+ at);
}
- ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
- "Websocket: Frame contained %" APR_OFF_T_FMT " bytes, pushed to Lua stack",
- at);
- }
- else {
- rv = lua_websocket_readbytes(r->connection, buffer,
- remaining);
- ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
- "Websocket: SSL Frame contained %" APR_SIZE_T_FMT " bytes, "\
- "pushed to Lua stack",
- remaining);
- }
- if (mask) {
- for (n = 0; n < plen; n++) {
- buffer[n] ^= mask_bytes[n%4];
+ else {
+ rv = lua_websocket_readbytes(r->connection, buffer,
+ remaining);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "Websocket: SSL Frame contained %" APR_SIZE_T_FMT " bytes, "\
+ "pushed to Lua stack",
+ remaining);
}
+ if (mask) {
+ for (n = 0; n < plen; n++) {
+ buffer[n] ^= mask_bytes[n%4];
+ }
+ }
+
+ lua_pushlstring(L, buffer, (size_t) plen); /* push to stack */
+ lua_pushboolean(L, fin); /* push FIN bit to stack as boolean */
+ return 2;
+ }
+
+
+ /* Decide if we need to react to the opcode or not */
+ if (opcode == 0x09) { /* ping */
+ char frame[2];
+ plen = 2;
+ frame[0] = 0x8A;
+ frame[1] = 0;
+ apr_socket_send(sock, frame, &plen); /* Pong! */
+ do_read = 1;
}
-
- lua_pushlstring(L, buffer, (size_t) plen); /* push to stack */
- lua_pushboolean(L, fin); /* push FIN bit to stack as boolean */
- return 2;
- }
-
-
- /* Decide if we need to react to the opcode or not */
- if (opcode == 0x09) { /* ping */
- char frame[2];
- plen = 2;
- frame[0] = 0x8A;
- frame[1] = 0;
- apr_socket_send(sock, frame, &plen); /* Pong! */
- do_read = 1;
}
}
}
- }
return 0;
}
return 0;
}
+
+
+/* helper function for walking config trees */
+static void read_cfg_tree(lua_State *L, request_rec *r, ap_directive_t *rcfg) {
+ int x = 0;
+ const char* value;
+ ap_directive_t *cfg;
+ lua_newtable(L);
+
+ for (cfg = rcfg; cfg; cfg = cfg->next) {
+ x++;
+ lua_pushnumber(L, x);
+ lua_newtable(L);
+ value = apr_psprintf(r->pool, "%s %s", cfg->directive, cfg->args);
+ lua_pushstring(L, "directive");
+ lua_pushstring(L, value);
+ lua_settable(L, -3);
+ lua_pushstring(L, "file");
+ lua_pushstring(L, cfg->filename);
+ lua_settable(L, -3);
+ lua_pushstring(L, "line");
+ lua_pushnumber(L, cfg->line_num);
+ lua_settable(L, -3);
+ if (cfg->first_child) {
+ lua_pushstring(L, "children");
+ read_cfg_tree(L, r, cfg->first_child);
+ lua_settable(L, -3);
+ }
+ lua_settable(L, -3);
+ }
+}
+
+static int lua_ap_get_config(lua_State *L) {
+ request_rec *r = ap_lua_check_request_rec(L, 1);
+ read_cfg_tree(L, r, ap_conftree);
+
+ return 1;
+}
+
+
+/* Hack, hack, hack...! TODO: Make this actually work properly */
+static int lua_ap_get_active_config(lua_State *L) {
+ ap_directive_t *subdir;
+ ap_directive_t *dir = ap_conftree;
+ request_rec *r = ap_lua_check_request_rec(L, 1);
+
+ for (dir = ap_conftree; dir; dir = dir->next) {
+ if (ap_strcasestr(dir->directive, "<virtualhost") && dir->first_child) {
+ for (subdir = dir->first_child; subdir; subdir = subdir->next) {
+ if (ap_strcasecmp_match(subdir->directive, "servername") &&
+ !ap_strcasecmp_match(r->hostname, subdir->args)) {
+ read_cfg_tree(L, r, dir->first_child);
+ return 1;
+ }
+ if (ap_strcasecmp_match(subdir->directive, "serveralias") &&
+ !ap_strcasecmp_match(r->hostname, subdir->args)) {
+ read_cfg_tree(L, r, dir->first_child);
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+
static const struct luaL_Reg request_methods[] = {
{"__index", req_dispatch},
{"__newindex", req_newindex},
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));
-
+ apr_hash_set(dispatch, "config", APR_HASH_KEY_STRING,
+ makefun(&lua_ap_get_config, APL_REQ_FUNTYPE_LUACFUN, p));
+ apr_hash_set(dispatch, "activeconfig", APR_HASH_KEY_STRING,
+ makefun(&lua_ap_get_active_config, APL_REQ_FUNTYPE_LUACFUN, p));
lua_pushlightuserdata(L, dispatch);
lua_setfield(L, LUA_REGISTRYINDEX, "Apache2.Request.dispatch");
void ap_lua_push_connection(lua_State *L, conn_rec *c)
{
- req_table_t *t;
+ req_table_t* t;
lua_boxpointer(L, c);
luaL_getmetatable(L, "Apache2.Connection");
lua_setmetatable(L, -2);