Diff for /embedaddon/lighttpd/src/mod_cml_lua.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2014/06/15 20:20:06 version 1.1.1.3, 2016/11/02 10:35:00
Line 1 Line 1
   #include "first.h"
   
 #include "mod_cml.h"  #include "mod_cml.h"
 #include "mod_cml_funcs.h"  #include "mod_cml_funcs.h"
 #include "log.h"  #include "log.h"
Line 28  typedef char HASHHEX[HASHHEXLEN+1]; Line 30  typedef char HASHHEX[HASHHEXLEN+1];
 #include <lualib.h>  #include <lualib.h>
 #include <lauxlib.h>  #include <lauxlib.h>
   
 typedef struct {  
         stream st;  
         int done;  
 } readme;  
   
 static const char * load_file(lua_State *L, void *data, size_t *size) {  
         readme *rm = data;  
   
         UNUSED(L);  
   
         if (rm->done) return 0;  
   
         *size = rm->st.size;  
         rm->done = 1;  
         return rm->st.start;  
 }  
   
 static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {  static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
        int curelem;        int curelem = lua_gettop(L);
         int result;
   
        lua_pushstring(L, varname);        lua_getglobal(L, varname);
   
        curelem = lua_gettop(L);        if (lua_isstring(L, curelem)) {
        lua_gettable(L, LUA_GLOBALSINDEX);                buffer_copy_string(b, lua_tostring(L, curelem));
                result = 0;
        /* it should be a table */        } else {
        if (!lua_isstring(L, curelem)) {                result = -1;
                lua_settop(L, curelem - 1); 
 
                return -1; 
         }          }
   
         buffer_copy_string(b, lua_tostring(L, curelem));  
   
         lua_pop(L, 1);          lua_pop(L, 1);
        force_assert(curelem == lua_gettop(L));
        force_assert(curelem - 1 == lua_gettop(L));        return result;
 
        return 0; 
 }  }
   
 static int lua_to_c_is_table(lua_State *L, const char *varname) {  static int lua_to_c_is_table(lua_State *L, const char *varname) {
        int curelem;        int curelem = lua_gettop(L);
         int result;
   
        lua_pushstring(L, varname);        lua_getglobal(L, varname);
   
        curelem = lua_gettop(L);        result = lua_istable(L, curelem) ? 1 : 0;
        lua_gettable(L, LUA_GLOBALSINDEX); 
   
        /* it should be a table */        lua_pop(L, 1);
        if (!lua_istable(L, curelem)) {        force_assert(curelem == lua_gettop(L));
                lua_settop(L, curelem - 1);        return result;
 
                return 0; 
        } 
 
        lua_settop(L, curelem - 1); 
 
        force_assert(curelem - 1 == lua_gettop(L)); 
 
        return 1; 
 }  }
   
 static int c_to_lua_push(lua_State *L, int tbl, const char *key, size_t key_len, const char *val, size_t val_len) {  static int c_to_lua_push(lua_State *L, int tbl, const char *key, size_t key_len, const char *val, size_t val_len) {
Line 99  static int c_to_lua_push(lua_State *L, int tbl, const  Line 69  static int c_to_lua_push(lua_State *L, int tbl, const 
         return 0;          return 0;
 }  }
   
   
 static int cache_export_get_params(lua_State *L, int tbl, buffer *qrystr) {  static int cache_export_get_params(lua_State *L, int tbl, buffer *qrystr) {
         size_t is_key = 1;          size_t is_key = 1;
        size_t i;        size_t i, len;
         char *key = NULL, *val = NULL;          char *key = NULL, *val = NULL;
   
         key = qrystr->ptr;          key = qrystr->ptr;
   
         /* we need the \0 */          /* we need the \0 */
        for (i = 0; i < qrystr->used; i++) {        len = buffer_string_length(qrystr);
         for (i = 0; i <= len; i++) {
                 switch(qrystr->ptr[i]) {                  switch(qrystr->ptr[i]) {
                 case '=':                  case '=':
                         if (is_key) {                          if (is_key) {
Line 129  static int cache_export_get_params(lua_State *L, int t Line 99  static int cache_export_get_params(lua_State *L, int t
                                 qrystr->ptr[i] = '\0';                                  qrystr->ptr[i] = '\0';
   
                                 c_to_lua_push(L, tbl,                                  c_to_lua_push(L, tbl,
                                              key, strlen(key),                                        key, strlen(key),
                                              val, strlen(val));                                        val, strlen(val));
                         }                          }
   
                         key = qrystr->ptr + i + 1;                          key = qrystr->ptr + i + 1;
Line 142  static int cache_export_get_params(lua_State *L, int t Line 112  static int cache_export_get_params(lua_State *L, int t
   
         return 0;          return 0;
 }  }
 #if 0  
 int cache_export_cookie_params(server *srv, connection *con, plugin_data *p) {  
         data_unset *d;  
   
         UNUSED(srv);  
   
         if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {  
                 data_string *ds = (data_string *)d;  
                 size_t key = 0, value = 0;  
                 size_t is_key = 1, is_sid = 0;  
                 size_t i;  
   
                 /* found COOKIE */  
                 if (!DATA_IS_STRING(d)) return -1;  
                 if (ds->value->used == 0) return -1;  
   
                 if (ds->value->ptr[0] == '\0' ||  
                     ds->value->ptr[0] == '=' ||  
                     ds->value->ptr[0] == ';') return -1;  
   
                 buffer_reset(p->session_id);  
                 for (i = 0; i < ds->value->used; i++) {  
                         switch(ds->value->ptr[i]) {  
                         case '=':  
                                 if (is_key) {  
                                         if (0 == strncmp(ds->value->ptr + key, "PHPSESSID", i - key)) {  
                                                 /* found PHP-session-id-key */  
                                                 is_sid = 1;  
                                         }  
                                         value = i + 1;  
   
                                         is_key = 0;  
                                 }  
   
                                 break;  
                         case ';':  
                                 if (is_sid) {  
                                         buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);  
                                 }  
   
                                 is_sid = 0;  
                                 key = i + 1;  
                                 value = 0;  
                                 is_key = 1;  
                                 break;  
                         case ' ':  
                                 if (is_key == 1 && key == i) key = i + 1;  
                                 if (is_key == 0 && value == i) value = i + 1;  
                                 break;  
                         case '\0':  
                                 if (is_sid) {  
                                         buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);  
                                 }  
                                 /* fin */  
                                 break;  
                         }  
                 }  
         }  
   
         return 0;  
 }  
 #endif  
   
 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {  int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
         lua_State *L;          lua_State *L;
         readme rm;  
         int ret = -1;          int ret = -1;
         buffer *b;          buffer *b;
         int header_tbl = 0;  
   
         rm.done = 0;  
         if (-1 == stream_open(&rm.st, fn)) {  
                 log_error_write(srv, __FILE__, __LINE__, "sbss",  
                                 "opening lua cml file ", fn, "failed:", strerror(errno));  
                 return -1;  
         }  
   
         b = buffer_init();          b = buffer_init();
         /* push the lua file to the interpreter and see what happends */          /* push the lua file to the interpreter and see what happends */
         L = luaL_newstate();          L = luaL_newstate();
Line 231  int cache_parse_lua(server *srv, connection *con, plug Line 130  int cache_parse_lua(server *srv, connection *con, plug
         lua_register(L, "file_isdir", f_file_isreg);          lua_register(L, "file_isdir", f_file_isreg);
         lua_register(L, "dir_files", f_dir_files);          lua_register(L, "dir_files", f_dir_files);
   
#ifdef HAVE_MEMCACHE_H#ifdef USE_MEMCACHED
        lua_pushliteral(L, "memcache_get_long");        lua_pushlightuserdata(L, p->conf.memc);
        lua_pushlightuserdata(L, p->conf.mc); 
         lua_pushcclosure(L, f_memcache_get_long, 1);          lua_pushcclosure(L, f_memcache_get_long, 1);
        lua_settable(L, LUA_GLOBALSINDEX);        lua_setglobal(L, "memcache_get_long");
   
        lua_pushliteral(L, "memcache_get_string");        lua_pushlightuserdata(L, p->conf.memc);
        lua_pushlightuserdata(L, p->conf.mc); 
         lua_pushcclosure(L, f_memcache_get_string, 1);          lua_pushcclosure(L, f_memcache_get_string, 1);
        lua_settable(L, LUA_GLOBALSINDEX);        lua_setglobal(L, "memcache_get_string");
   
        lua_pushliteral(L, "memcache_exists");        lua_pushlightuserdata(L, p->conf.memc);
        lua_pushlightuserdata(L, p->conf.mc); 
         lua_pushcclosure(L, f_memcache_exists, 1);          lua_pushcclosure(L, f_memcache_exists, 1);
        lua_settable(L, LUA_GLOBALSINDEX);        lua_setglobal(L, "memcache_exists");
 #endif  #endif
   
         /* register CGI environment */          /* register CGI environment */
         lua_pushliteral(L, "request");  
         lua_newtable(L);          lua_newtable(L);
        lua_settable(L, LUA_GLOBALSINDEX);        {
                 int header_tbl = lua_gettop(L);
   
        lua_pushliteral(L, "request");                c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
        header_tbl = lua_gettop(L);                c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
        lua_gettable(L, LUA_GLOBALSINDEX);                c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
                 c_to_lua_push(L, header_tbl, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.basedir));
                 if (!buffer_string_is_empty(con->request.pathinfo)) {
                         c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
                 }
   
        c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));                c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
        c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));                c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
        c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path)); 
        c_to_lua_push(L, header_tbl, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root)); 
        if (!buffer_is_empty(con->request.pathinfo)) { 
                c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo)); 
         }          }
           lua_setglobal(L, "request");
   
         c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));  
         c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));  
   
         /* register GET parameter */          /* register GET parameter */
         lua_pushliteral(L, "get");  
         lua_newtable(L);          lua_newtable(L);
        lua_settable(L, LUA_GLOBALSINDEX);        {
                 int get_tbl = lua_gettop(L);
   
        lua_pushliteral(L, "get");                buffer_copy_buffer(b, con->uri.query);
        header_tbl = lua_gettop(L);                cache_export_get_params(L, get_tbl, b);
        lua_gettable(L, LUA_GLOBALSINDEX);                buffer_reset(b);
         }
         lua_setglobal(L, "get");
   
         buffer_copy_string_buffer(b, con->uri.query);  
         cache_export_get_params(L, header_tbl, b);  
         buffer_reset(b);  
   
         /* 2 default constants */          /* 2 default constants */
        lua_pushliteral(L, "CACHE_HIT");        lua_pushinteger(L, 0);
        lua_pushnumber(L, 0);        lua_setglobal(L, "CACHE_HIT");
        lua_settable(L, LUA_GLOBALSINDEX); 
   
        lua_pushliteral(L, "CACHE_MISS");        lua_pushinteger(L, 1);
        lua_pushnumber(L, 1);        lua_setglobal(L, "CACHE_MISS");
        lua_settable(L, LUA_GLOBALSINDEX); 
   
         /* load lua program */          /* load lua program */
        if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {        ret = luaL_loadfile(L, fn->ptr);
                log_error_write(srv, __FILE__, __LINE__, "s",        if (0 != ret) {
                                lua_tostring(L,-1));                log_error_write(srv, __FILE__, __LINE__, "sbsS",
                         "failed loading cml_lua script",
                         fn,
                         ":",
                         lua_tostring(L, -1));
                 goto error;
         }
   
           if (lua_pcall(L, 0, 1, 0)) {
                   log_error_write(srv, __FILE__, __LINE__, "sbsS",
                           "failed running cml_lua script",
                           fn,
                           ":",
                           lua_tostring(L, -1));
                 goto error;                  goto error;
         }          }
   
         /* get return value */          /* get return value */
        ret = (int)lua_tonumber(L, -1);        ret = (int)lua_tointeger(L, -1);
         lua_pop(L, 1);          lua_pop(L, 1);
   
         /* fetch the data from lua */          /* fetch the data from lua */
Line 322  int cache_parse_lua(server *srv, connection *con, plug Line 225  int cache_parse_lua(server *srv, connection *con, plug
                         goto error;                          goto error;
                 }                  }
   
                lua_pushstring(L, "output_include");                lua_getglobal(L, "output_include");
 
                 curelem = lua_gettop(L);                  curelem = lua_gettop(L);
                 lua_gettable(L, LUA_GLOBALSINDEX);  
   
                 /* HOW-TO build a etag ?                  /* HOW-TO build a etag ?
                  * as we don't just have one file we have to take the stat()                   * as we don't just have one file we have to take the stat()
Line 338  int cache_parse_lua(server *srv, connection *con, plug Line 239  int cache_parse_lua(server *srv, connection *con, plug
   
                 lua_pushnil(L);  /* first key */                  lua_pushnil(L);  /* first key */
                 while (lua_next(L, curelem) != 0) {                  while (lua_next(L, curelem) != 0) {
                         stat_cache_entry *sce = NULL;  
                         /* key' is at index -2 and value' at index -1 */                          /* key' is at index -2 and value' at index -1 */
   
                         if (lua_isstring(L, -1)) {                          if (lua_isstring(L, -1)) {
                                 const char *s = lua_tostring(L, -1);                                  const char *s = lua_tostring(L, -1);
                                   struct stat st;
                                   int fd;
   
                                 /* the file is relative, make it absolute */                                  /* the file is relative, make it absolute */
                                 if (s[0] != '/') {                                  if (s[0] != '/') {
                                        buffer_copy_string_buffer(b, p->basedir);                                        buffer_copy_buffer(b, p->basedir);
                                         buffer_append_string(b, lua_tostring(L, -1));                                          buffer_append_string(b, lua_tostring(L, -1));
                                 } else {                                  } else {
                                         buffer_copy_string(b, lua_tostring(L, -1));                                          buffer_copy_string(b, lua_tostring(L, -1));
                                 }                                  }
   
                                if (HANDLER_ERROR == stat_cache_get_entry(srv, con, b, &sce)) {                                fd = stat_cache_open_rdonly_fstat(srv, con, b, &st);
                                 if (fd < 0) {
                                         /* stat failed */                                          /* stat failed */
   
                                         switch(errno) {                                          switch(errno) {
                                         case ENOENT:                                          case ENOENT:
                                                 /* a file is missing, call the handler to generate it */                                                  /* a file is missing, call the handler to generate it */
                                                if (!buffer_is_empty(p->trigger_handler)) {                                                if (!buffer_string_is_empty(p->trigger_handler)) {
                                                         ret = 1; /* cache-miss */                                                          ret = 1; /* cache-miss */
   
                                                         log_error_write(srv, __FILE__, __LINE__, "s",                                                          log_error_write(srv, __FILE__, __LINE__, "s",
Line 379  int cache_parse_lua(server *srv, connection *con, plug Line 282  int cache_parse_lua(server *srv, connection *con, plug
                                                 break;                                                  break;
                                         }                                          }
                                 } else {                                  } else {
                                        chunkqueue_append_file(con->write_queue, b, 0, sce->st.st_size);                                        chunkqueue_append_file_fd(con->write_queue, b, fd, 0, st.st_size);
                                        if (sce->st.st_mtime > mtime) mtime = sce->st.st_mtime;                                        if (st.st_mtime > mtime) mtime = st.st_mtime;
                                 }                                  }
                         } else {                          } else {
                                 /* not a string */                                  /* not a string */
Line 398  int cache_parse_lua(server *srv, connection *con, plug Line 301  int cache_parse_lua(server *srv, connection *con, plug
                 if (ret == 0) {                  if (ret == 0) {
                         data_string *ds;                          data_string *ds;
                         char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];                          char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
                         buffer tbuf;  
   
                         con->file_finished = 1;                          con->file_finished = 1;
   
Line 411  int cache_parse_lua(server *srv, connection *con, plug Line 313  int cache_parse_lua(server *srv, connection *con, plug
                                 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));                                  strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
   
                                 response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);                                  response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
                                ds = (data_string *)array_get_element(con->response.headers, "Last-Modified");
                                tbuf.ptr = timebuf;                                force_assert(NULL != ds);
                                tbuf.used = sizeof(timebuf); 
                                tbuf.size = sizeof(timebuf); 
                        } else { 
                                tbuf.ptr = ds->value->ptr; 
                                tbuf.used = ds->value->used; 
                                tbuf.size = ds->value->size; 
                         }                          }
   
                        if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {                        if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, ds->value)) {
                                 /* ok, the client already has our content,                                  /* ok, the client already has our content,
                                  * no need to send it again */                                   * no need to send it again */
   
Line 433  int cache_parse_lua(server *srv, connection *con, plug Line 329  int cache_parse_lua(server *srv, connection *con, plug
                 }                  }
         }          }
   
        if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {        if (ret == 1 && !buffer_string_is_empty(p->trigger_handler)) {
                 /* cache-miss */                  /* cache-miss */
                buffer_copy_string_buffer(con->uri.path, p->baseurl);                buffer_copy_buffer(con->uri.path, p->baseurl);
                 buffer_append_string_buffer(con->uri.path, p->trigger_handler);                  buffer_append_string_buffer(con->uri.path, p->trigger_handler);
   
                buffer_copy_string_buffer(con->physical.path, p->basedir);                buffer_copy_buffer(con->physical.path, p->basedir);
                 buffer_append_string_buffer(con->physical.path, p->trigger_handler);                  buffer_append_string_buffer(con->physical.path, p->trigger_handler);
   
                 chunkqueue_reset(con->write_queue);                  chunkqueue_reset(con->write_queue);
Line 447  int cache_parse_lua(server *srv, connection *con, plug Line 343  int cache_parse_lua(server *srv, connection *con, plug
 error:  error:
         lua_close(L);          lua_close(L);
   
         stream_close(&rm.st);  
         buffer_free(b);          buffer_free(b);
   
         return ret /* cache-error */;          return ret /* cache-error */;

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>