packages: sort network related packages into package/network/
[openwrt/staging/yousong.git] / package / uhttpd / src / uhttpd-lua.c
diff --git a/package/uhttpd/src/uhttpd-lua.c b/package/uhttpd/src/uhttpd-lua.c
deleted file mode 100644 (file)
index e113937..0000000
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * uhttpd - Tiny single-threaded httpd - Lua handler
- *
- *   Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#include "uhttpd.h"
-#include "uhttpd-utils.h"
-#include "uhttpd-lua.h"
-
-
-static int uh_lua_recv(lua_State *L)
-{
-       size_t length;
-
-       char buffer[UH_LIMIT_MSGHEAD];
-
-       int to = 1;
-       int fd = fileno(stdin);
-       int rlen = 0;
-
-       length = luaL_checknumber(L, 1);
-
-       if ((length > 0) && (length <= sizeof(buffer)))
-       {
-               /* receive data */
-               rlen = uh_raw_recv(fd, buffer, length, to);
-
-               /* data read */
-               if (rlen > 0)
-               {
-                       lua_pushnumber(L, rlen);
-                       lua_pushlstring(L, buffer, rlen);
-                       return 2;
-               }
-
-               /* eof */
-               else if (rlen == 0)
-               {
-                       lua_pushnumber(L, 0);
-                       return 1;
-               }
-
-               /* no, timeout and actually no data */
-               else
-               {
-                       lua_pushnumber(L, -1);
-                       return 1;
-               }
-       }
-
-       /* parameter error */
-       lua_pushnumber(L, -2);
-       return 1;
-}
-
-static int uh_lua_send_common(lua_State *L, bool chunked)
-{
-       size_t length;
-
-       char chunk[16];
-       const char *buffer;
-
-       int rv;
-       int to = 1;
-       int fd = fileno(stdout);
-       int slen = 0;
-
-       buffer = luaL_checklstring(L, 1, &length);
-
-       if (chunked)
-       {
-               if (length > 0)
-               {
-                       snprintf(chunk, sizeof(chunk), "%X\r\n", length);
-
-                       ensure_out(rv = uh_raw_send(fd, chunk, strlen(chunk), to));
-                       slen += rv;
-
-                       ensure_out(rv = uh_raw_send(fd, buffer, length, to));
-                       slen += rv;
-
-                       ensure_out(rv = uh_raw_send(fd, "\r\n", 2, to));
-                       slen += rv;
-               }
-               else
-               {
-                       slen = uh_raw_send(fd, "0\r\n\r\n", 5, to);
-               }
-       }
-       else
-       {
-               slen = uh_raw_send(fd, buffer, length, to);
-       }
-
-out:
-       lua_pushnumber(L, slen);
-       return 1;
-}
-
-static int uh_lua_send(lua_State *L)
-{
-       return uh_lua_send_common(L, false);
-}
-
-static int uh_lua_sendc(lua_State *L)
-{
-       return uh_lua_send_common(L, true);
-}
-
-static int uh_lua_str2str(lua_State *L, int (*xlate_func) (char *, int, const char *, int))
-{
-       size_t inlen;
-       int outlen;
-       const char *inbuf;
-       char outbuf[UH_LIMIT_MSGHEAD];
-
-       inbuf = luaL_checklstring(L, 1, &inlen);
-       outlen = (* xlate_func)(outbuf, sizeof(outbuf), inbuf, inlen);
-       if (outlen < 0)
-               luaL_error(L, "%s on URL-encode codec",
-                                  (outlen==-1) ? "buffer overflow" : "malformed string");
-
-       lua_pushlstring(L, outbuf, outlen);
-       return 1;
-}
-
-static int uh_lua_urldecode(lua_State *L)
-{
-       return uh_lua_str2str( L, uh_urldecode );
-}
-
-
-static int uh_lua_urlencode(lua_State *L)
-{
-       return uh_lua_str2str( L, uh_urlencode );
-}
-
-
-lua_State * uh_lua_init(const struct config *conf)
-{
-       lua_State *L = lua_open();
-       const char *err_str = NULL;
-
-       /* Load standard libaries */
-       luaL_openlibs(L);
-
-       /* build uhttpd api table */
-       lua_newtable(L);
-
-       /* register global send and receive functions */
-       lua_pushcfunction(L, uh_lua_recv);
-       lua_setfield(L, -2, "recv");
-
-       lua_pushcfunction(L, uh_lua_send);
-       lua_setfield(L, -2, "send");
-
-       lua_pushcfunction(L, uh_lua_sendc);
-       lua_setfield(L, -2, "sendc");
-
-       lua_pushcfunction(L, uh_lua_urldecode);
-       lua_setfield(L, -2, "urldecode");
-
-       lua_pushcfunction(L, uh_lua_urlencode);
-       lua_setfield(L, -2, "urlencode");
-
-       /* Pass the document-root to the Lua handler by placing it in
-       ** uhttpd.docroot.  It could alternatively be placed in env.DOCUMENT_ROOT
-       ** which would more closely resemble the CGI protocol; but would mean that
-       ** it is not available at the time when the handler-chunk is loaded but
-       ** rather not until the handler is called, without any code savings. */
-       lua_pushstring(L, conf->docroot);
-       lua_setfield(L, -2, "docroot");
-
-       /* _G.uhttpd = { ... } */
-       lua_setfield(L, LUA_GLOBALSINDEX, "uhttpd");
-
-
-       /* load Lua handler */
-       switch (luaL_loadfile(L, conf->lua_handler))
-       {
-               case LUA_ERRSYNTAX:
-                       fprintf(stderr,
-                                       "Lua handler contains syntax errors, unable to continue\n");
-                       exit(1);
-
-               case LUA_ERRMEM:
-                       fprintf(stderr,
-                                       "Lua handler ran out of memory, unable to continue\n");
-                       exit(1);
-
-               case LUA_ERRFILE:
-                       fprintf(stderr,
-                                       "Lua cannot open the handler script, unable to continue\n");
-                       exit(1);
-
-               default:
-                       /* compile Lua handler */
-                       switch (lua_pcall(L, 0, 0, 0))
-                       {
-                               case LUA_ERRRUN:
-                                       err_str = luaL_checkstring(L, -1);
-                                       fprintf(stderr,
-                                                       "Lua handler had runtime error, "
-                                                       "unable to continue\n"
-                                                       "Error: %s\n", err_str);
-                                       exit(1);
-
-                               case LUA_ERRMEM:
-                                       err_str = luaL_checkstring(L, -1);
-                                       fprintf(stderr,
-                                                       "Lua handler ran out of memory, "
-                                                       "unable to continue\n"
-                                                       "Error: %s\n", err_str);
-                                       exit(1);
-
-                               default:
-                                       /* test handler function */
-                                       lua_getglobal(L, UH_LUA_CALLBACK);
-
-                                       if (! lua_isfunction(L, -1))
-                                       {
-                                               fprintf(stderr,
-                                                               "Lua handler provides no "UH_LUA_CALLBACK"(), "
-                                                               "unable to continue\n");
-                                               exit(1);
-                                       }
-
-                                       lua_pop(L, 1);
-                                       break;
-                       }
-
-                       break;
-       }
-
-       return L;
-}
-
-static void uh_lua_shutdown(struct uh_lua_state *state)
-{
-       free(state);
-}
-
-static bool uh_lua_socket_cb(struct client *cl)
-{
-       int len;
-       char buf[UH_LIMIT_MSGHEAD];
-
-       struct uh_lua_state *state = (struct uh_lua_state *)cl->priv;
-
-       /* there is unread post data waiting */
-       while (state->content_length > 0)
-       {
-               /* remaining data in http head buffer ... */
-               if (cl->httpbuf.len > 0)
-               {
-                       len = min(state->content_length, cl->httpbuf.len);
-
-                       D("Lua: Child(%d) feed %d HTTP buffer bytes\n", cl->proc.pid, len);
-
-                       memcpy(buf, cl->httpbuf.ptr, len);
-
-                       cl->httpbuf.len -= len;
-                       cl->httpbuf.ptr += len;
-               }
-
-               /* read it from socket ... */
-               else
-               {
-                       len = uh_tcp_recv(cl, buf, min(state->content_length, sizeof(buf)));
-
-                       if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
-                               break;
-
-                       D("Lua: Child(%d) feed %d/%d TCP socket bytes\n",
-                         cl->proc.pid, len, min(state->content_length, sizeof(buf)));
-               }
-
-               if (len)
-                       state->content_length -= len;
-               else
-                       state->content_length = 0;
-
-               /* ... write to Lua process */
-               len = uh_raw_send(cl->wpipe.fd, buf, len,
-                                                 cl->server->conf->script_timeout);
-
-               /* explicit EOF notification for the child */
-               if (state->content_length <= 0)
-                       uh_ufd_remove(&cl->wpipe);
-       }
-
-       /* try to read data from child */
-       while ((len = uh_raw_recv(cl->rpipe.fd, buf, sizeof(buf), -1)) > 0)
-       {
-               /* pass through buffer to socket */
-               D("Lua: Child(%d) relaying %d normal bytes\n", cl->proc.pid, len);
-               ensure_out(uh_tcp_send(cl, buf, len));
-               state->data_sent = true;
-       }
-
-       /* got EOF or read error from child */
-       if ((len == 0) ||
-               ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (len == -1)))
-       {
-               D("Lua: Child(%d) presumed dead [%s]\n",
-                 cl->proc.pid, strerror(errno));
-
-               goto out;
-       }
-
-       return true;
-
-out:
-       if (!state->data_sent)
-       {
-               if (cl->timeout.pending)
-                       uh_http_sendhf(cl, 502, "Bad Gateway",
-                                                  "The Lua process did not produce any response\n");
-               else
-                       uh_http_sendhf(cl, 504, "Gateway Timeout",
-                                                  "The Lua process took too long to produce a "
-                                                  "response\n");
-       }
-
-       uh_lua_shutdown(state);
-       return false;
-}
-
-bool uh_lua_request(struct client *cl, lua_State *L)
-{
-       int i;
-       char *query_string;
-       const char *prefix = cl->server->conf->lua_prefix;
-       const char *err_str = NULL;
-
-       int rfd[2] = { 0, 0 };
-       int wfd[2] = { 0, 0 };
-
-       pid_t child;
-
-       struct uh_lua_state *state;
-       struct http_request *req = &cl->request;
-
-       int content_length = cl->httpbuf.len;
-
-
-       /* allocate state */
-       if (!(state = malloc(sizeof(*state))))
-       {
-               uh_client_error(cl, 500, "Internal Server Error", "Out of memory");
-               return false;
-       }
-
-       /* spawn pipes for me->child, child->me */
-       if ((pipe(rfd) < 0) || (pipe(wfd) < 0))
-       {
-               if (rfd[0] > 0) close(rfd[0]);
-               if (rfd[1] > 0) close(rfd[1]);
-               if (wfd[0] > 0) close(wfd[0]);
-               if (wfd[1] > 0) close(wfd[1]);
-
-               uh_client_error(cl, 500, "Internal Server Error",
-                                               "Failed to create pipe: %s", strerror(errno));
-
-               return false;
-       }
-
-
-       switch ((child = fork()))
-       {
-       case -1:
-               uh_client_error(cl, 500, "Internal Server Error",
-                                               "Failed to fork child: %s", strerror(errno));
-
-               return false;
-
-       case 0:
-#ifdef DEBUG
-               sleep(atoi(getenv("UHTTPD_SLEEP_ON_FORK") ?: "0"));
-#endif
-
-               /* do not leak parent epoll descriptor */
-               uloop_done();
-
-               /* close loose pipe ends */
-               close(rfd[0]);
-               close(wfd[1]);
-
-               /* patch stdout and stdin to pipes */
-               dup2(rfd[1], 1);
-               dup2(wfd[0], 0);
-
-               /* avoid leaking our pipe into child-child processes */
-               fd_cloexec(rfd[1]);
-               fd_cloexec(wfd[0]);
-
-               /* put handler callback on stack */
-               lua_getglobal(L, UH_LUA_CALLBACK);
-
-               /* build env table */
-               lua_newtable(L);
-
-               /* request method */
-               lua_pushstring(L, http_methods[req->method]);
-               lua_setfield(L, -2, "REQUEST_METHOD");
-
-               /* request url */
-               lua_pushstring(L, req->url);
-               lua_setfield(L, -2, "REQUEST_URI");
-
-               /* script name */
-               lua_pushstring(L, cl->server->conf->lua_prefix);
-               lua_setfield(L, -2, "SCRIPT_NAME");
-
-               /* query string, path info */
-               if ((query_string = strchr(req->url, '?')) != NULL)
-               {
-                       lua_pushstring(L, query_string + 1);
-                       lua_setfield(L, -2, "QUERY_STRING");
-
-                       if ((int)(query_string - req->url) > strlen(prefix))
-                       {
-                               lua_pushlstring(L,
-                                       &req->url[strlen(prefix)],
-                                       (int)(query_string - req->url) - strlen(prefix)
-                               );
-
-                               lua_setfield(L, -2, "PATH_INFO");
-                       }
-               }
-               else if (strlen(req->url) > strlen(prefix))
-               {
-                       lua_pushstring(L, &req->url[strlen(prefix)]);
-                       lua_setfield(L, -2, "PATH_INFO");
-               }
-
-               /* http protcol version */
-               lua_pushnumber(L, 0.9 + (req->version / 10.0));
-               lua_setfield(L, -2, "HTTP_VERSION");
-
-               lua_pushstring(L, http_versions[req->version]);
-               lua_setfield(L, -2, "SERVER_PROTOCOL");
-
-
-               /* address information */
-               lua_pushstring(L, sa_straddr(&cl->peeraddr));
-               lua_setfield(L, -2, "REMOTE_ADDR");
-
-               lua_pushinteger(L, sa_port(&cl->peeraddr));
-               lua_setfield(L, -2, "REMOTE_PORT");
-
-               lua_pushstring(L, sa_straddr(&cl->servaddr));
-               lua_setfield(L, -2, "SERVER_ADDR");
-
-               lua_pushinteger(L, sa_port(&cl->servaddr));
-               lua_setfield(L, -2, "SERVER_PORT");
-
-               /* essential env vars */
-               foreach_header(i, req->headers)
-               {
-                       if (!strcasecmp(req->headers[i], "Content-Length"))
-                       {
-                               content_length = atoi(req->headers[i+1]);
-                       }
-                       else if (!strcasecmp(req->headers[i], "Content-Type"))
-                       {
-                               lua_pushstring(L, req->headers[i+1]);
-                               lua_setfield(L, -2, "CONTENT_TYPE");
-                       }
-               }
-
-               lua_pushnumber(L, content_length);
-               lua_setfield(L, -2, "CONTENT_LENGTH");
-
-               /* misc. headers */
-               lua_newtable(L);
-
-               foreach_header(i, req->headers)
-               {
-                       if( strcasecmp(req->headers[i], "Content-Length") &&
-                               strcasecmp(req->headers[i], "Content-Type"))
-                       {
-                               lua_pushstring(L, req->headers[i+1]);
-                               lua_setfield(L, -2, req->headers[i]);
-                       }
-               }
-
-               lua_setfield(L, -2, "headers");
-
-
-               /* call */
-               switch (lua_pcall(L, 1, 0, 0))
-               {
-                       case LUA_ERRMEM:
-                       case LUA_ERRRUN:
-                               err_str = luaL_checkstring(L, -1);
-
-                               if (! err_str)
-                                       err_str = "Unknown error";
-
-                               printf("%s 500 Internal Server Error\r\n"
-                                          "Connection: close\r\n"
-                                          "Content-Type: text/plain\r\n"
-                                          "Content-Length: %i\r\n\r\n"
-                                          "Lua raised a runtime error:\n  %s\n",
-                                          http_versions[req->version],
-                                          31 + strlen(err_str), err_str);
-
-                               break;
-
-                       default:
-                               break;
-               }
-
-               close(wfd[0]);
-               close(rfd[1]);
-               exit(0);
-
-               break;
-
-       /* parent; handle I/O relaying */
-       default:
-               memset(state, 0, sizeof(*state));
-
-               cl->rpipe.fd = rfd[0];
-               cl->wpipe.fd = wfd[1];
-               cl->proc.pid = child;
-
-               /* make pipe non-blocking */
-               fd_nonblock(cl->rpipe.fd);
-               fd_nonblock(cl->wpipe.fd);
-
-               /* close unneeded pipe ends */
-               close(rfd[1]);
-               close(wfd[0]);
-
-               D("Lua: Child(%d) created: rfd(%d) wfd(%d)\n", child, rfd[0], wfd[1]);
-
-               state->content_length = cl->httpbuf.len;
-
-               /* find content length */
-               if (req->method == UH_HTTP_MSG_POST)
-               {
-                       foreach_header(i, req->headers)
-                       {
-                               if (!strcasecmp(req->headers[i], "Content-Length"))
-                               {
-                                       state->content_length = atoi(req->headers[i+1]);
-                                       break;
-                               }
-                       }
-               }
-
-               cl->cb = uh_lua_socket_cb;
-               cl->priv = state;
-
-               break;
-       }
-
-       return true;
-}
-
-void uh_lua_close(lua_State *L)
-{
-       lua_close(L);
-}