Ejemplo n.º 1
0
/**
 * walk through the content array
 *
 * content = { "<pre>", { file = "/content" } , "</pre>" }
 *
 * header["Content-Type"] = "text/html"
 *
 * return 200
 */
static int magnet_attach_content(server *srv, connection *con, plugin_data *p, lua_State *L) {
	UNUSED(p);
	/**
	 * get the environment of the function
	 */

	assert(lua_isfunction(L, -1));
	lua_getfenv(L, -1); /* -1 is the function */

	lua_getfield(L, -1, "lighty"); /* lighty.* from the env  */
	assert(lua_istable(L, -1));

	lua_getfield(L, -1, "content"); /* lighty.content */
	if (lua_istable(L, -1)) {
		int i;
		/* header is found, and is a table */

		for (i = 1; ; i++) {
			lua_rawgeti(L, -1, i);

			/* -1 is the value and should be the value ... aka a table */
			if (lua_isstring(L, -1)) {
				size_t s_len = 0;
				const char *s = lua_tolstring(L, -1, &s_len);

				chunkqueue_append_mem(con->send, s, s_len);
			} else if (lua_istable(L, -1)) {
				lua_getfield(L, -1, "filename");
				lua_getfield(L, -2, "length");
				lua_getfield(L, -3, "offset");

				if (lua_isstring(L, -3)) { /* filename has to be a string */
					buffer *fn = buffer_init();
					stat_cache_entry *sce;

					buffer_copy_string(fn, lua_tostring(L, -3));

					if (HANDLER_GO_ON == stat_cache_get_entry(srv, con, fn, &sce)) {
						off_t off = 0;
						off_t len = 0;

						if (lua_isnumber(L, -1)) {
							off = lua_tonumber(L, -1);
						}

						if (lua_isnumber(L, -2)) {
							len = lua_tonumber(L, -2);
						} else {
							len = sce->st.st_size;
						}

						if (off < 0) {
							return luaL_error(L, "offset for '%s' is negative", fn->ptr);
						}

						if (len < off) {
							return luaL_error(L, "offset > length for '%s'", fn->ptr);
						}

						chunkqueue_append_file(con->send, fn, off, len - off);
					}

					buffer_free(fn);
				} else {
					lua_pop(L, 3 + 2); /* correct the stack */

					return luaL_error(L, "content[%d] is a table and requires the field \"filename\"", i);
				}

				lua_pop(L, 3);
			} else if (lua_isnil(L, -1)) {
				/* oops, end of list */

				lua_pop(L, 1);

				break;
			} else {
				lua_pop(L, 4);

				return luaL_error(L, "content[%d] is neither a string nor a table: ", i);
			}

			lua_pop(L, 1); /* pop the content[...] table */
		}
	} else {
		return luaL_error(L, "lighty.content has to be a table");
	}
	lua_pop(L, 1); /* pop the header-table */
	lua_pop(L, 1); /* pop the lighty-table */
	lua_pop(L, 1); /* php the function env */

	return 0;
}
static int
log_wrapper(ngx_tcp_session_t *s, const char *ident, ngx_uint_t level,
        lua_State *L)
{
    u_char              *buf;
    u_char              *p, *q;
    ngx_str_t            name;
    int                  nargs, i;
    size_t               size, len;
    size_t               src_len = 0;
    int                  type;
    const char          *msg;
    lua_Debug            ar;
    ngx_buf_t           *b;

    if (level > s->connection->log->log_level) {
        return 0;
    }

    dd("log level: %d", (int)level);
#if 1
    /* add debug info */

    lua_getstack(L, 1, &ar);
    lua_getinfo(L, "Snl", &ar);

    /* get the basename of the Lua source file path, stored in q */
    name.data = (u_char *) ar.short_src;
    if (name.data == NULL) {
        name.len = 0;

    } else {
        p = name.data;
        while (*p != '\0') {
            if (*p == '/' || *p == '\\') {
                name.data = p + 1;
            }
            p++;
        }

        name.len = p - name.data;
    }

#endif

    nargs = lua_gettop(L);

    size = name.len + NGX_INT_T_LEN + sizeof(":: ") - 1;

    if (*ar.namewhat != '\0' && *ar.what == 'L') {
        src_len = ngx_strlen(ar.name);
        size += src_len + sizeof("(): ") - 1;
    }

    for (i = 1; i <= nargs; i++) {
        type = lua_type(L, i);
        switch (type) {
            case LUA_TNUMBER:
            case LUA_TSTRING:
                lua_tolstring(L, i, &len);
                size += len;
                break;

            case LUA_TNIL:
                size += sizeof("nil") - 1;
                break;

            case LUA_TBOOLEAN:
                if (lua_toboolean(L, i)) {
                    size += sizeof("true") - 1;

                } else {
                    size += sizeof("false") - 1;
                }

                break;

            case LUA_TLIGHTUSERDATA:
                if (lua_touserdata(L, i) == NULL) {
                    size += sizeof("null") - 1;
                    break;
                }

                continue;

            default:
                msg = lua_pushfstring(L, "string, number, boolean, or nil "
                         "expected, got %s", lua_typename(L, type));
                return luaL_argerror(L, i, msg);
        }
    }

    //buf = lua_newuserdata(L, size + 1);
    b = ngx_create_temp_buf(s->pool, size + 1);
    buf = (u_char*)b->pos;

    p = ngx_copy(buf, name.data, name.len);

    *p++ = ':';

    p = ngx_snprintf(p, NGX_INT_T_LEN, "%d",
                     ar.currentline ? ar.currentline : ar.linedefined);

    *p++ = ':'; *p++ = ' ';

    if (*ar.namewhat != '\0' && *ar.what == 'L') {
        p = ngx_copy(p, ar.name, src_len);
        *p++ = '(';
        *p++ = ')';
        *p++ = ':';
        *p++ = ' ';
    }

    for (i = 1; i <= nargs; i++) {
        type = lua_type(L, i);
        switch (type) {
            case LUA_TNUMBER:
            case LUA_TSTRING:
                q = (u_char *) lua_tolstring(L, i, &len);
                p = ngx_copy(p, q, len);
                break;

            case LUA_TNIL:
                *p++ = 'n';
                *p++ = 'i';
                *p++ = 'l';
                break;

            case LUA_TBOOLEAN:
                if (lua_toboolean(L, i)) {
                    *p++ = 't';
                    *p++ = 'r';
                    *p++ = 'u';
                    *p++ = 'e';

                } else {
                    *p++ = 'f';
                    *p++ = 'a';
                    *p++ = 'l';
                    *p++ = 's';
                    *p++ = 'e';
                }

                break;

            case LUA_TLIGHTUSERDATA:
                *p++ = 'n';
                *p++ = 'u';
                *p++ = 'l';
                *p++ = 'l';

                break;

            default:
                return luaL_error(L, "impossible to reach here");
        }
    }

    *p++ = '\0';

    if (p - buf > (off_t) (size + 1)) {
        return luaL_error(L, "buffer error: %d > %d", (int) (p - buf),
                          (int) (size + 1));
    }

    ngx_log_error(level, s->connection->log, 0, "%s%s", ident, buf);

    return 0;
}
Ejemplo n.º 3
0
/*
	unsigned address
	 string address
	integer type
	integer session
	string message
	 lightuserdata message_ptr
	 integer len
 */
static int
_send(lua_State *L) {
    struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
    int addr_type = lua_type(L,1);
    uint32_t dest = 0;
    switch(addr_type) {
    case LUA_TNUMBER:
        dest = lua_tounsigned(L,1);
        break;
    case LUA_TSTRING: {
        const char * addrname = lua_tostring(L,1);
        if (addrname[0] == '.' || addrname[0] == ':') {
            dest = skynet_queryname(context, addrname);
            if (dest == 0) {
                luaL_error(L, "Invalid name %s", addrname);
            }
        } else if ('0' <= addrname[0] && addrname[0] <= '9') {
            luaL_error(L, "Invalid name %s: must not start with a digit", addrname);
        } else {
            return _sendname(L, context, addrname);
        }
        break;
    }
    default:
        return luaL_error(L, "address must be number or string, got %s",lua_typename(L,addr_type));
    }

    int type = luaL_checkinteger(L, 2);
    int session = 0;
    if (lua_isnil(L,3)) {
        type |= PTYPE_TAG_ALLOCSESSION;
    } else {
        session = luaL_checkinteger(L,3);
    }

    int mtype = lua_type(L,4);
    switch (mtype) {
    case LUA_TSTRING: {
        size_t len = 0;
        void * msg = (void *)lua_tolstring(L,4,&len);
        if (len == 0) {
            msg = NULL;
        }
        session = skynet_send(context, 0, dest, type, session , msg, len);
        break;
    }
    case LUA_TLIGHTUSERDATA: {
        void * msg = lua_touserdata(L,4);
        int size = luaL_checkinteger(L,5);
        session = skynet_send(context, 0, dest, type | PTYPE_TAG_DONTCOPY, session, msg, size);
        break;
    }
    default:
        luaL_error(L, "skynet.send invalid param %s", lua_type(L,4));
    }
    if (session < 0) {
        luaL_error(L, "skynet.send session (%d) < 0", session);
    }
    lua_pushinteger(L,session);
    return 1;
}
Ejemplo n.º 4
0
static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) {

    lua_CFunction cfunc= lua_tocfunction( L,i );
    unsigned n;

    ASSERT_L( L2_cache_i != 0 );

  STACK_GROW(L,2);

  STACK_CHECK(L)
    if (!cfunc) {   // Lua function
        luaL_Buffer b;
        const char *s;
        size_t sz;
        int tmp;
        const char *name= NULL;

#if 0
        // "To get information about a function you push it onto the 
        // stack and start the what string with the character '>'."
        //
        { lua_Debug ar;
        lua_pushvalue( L, i );
        lua_getinfo(L, ">n", &ar);      // fills 'name' and 'namewhat', pops function
        name= ar.namewhat;
        
        fprintf( stderr, "NAME: %s\n", name );  // just gives NULL
        }
#endif 
        // 'lua_dump()' needs the function at top of stack
        //
        if (i!=-1) lua_pushvalue( L, i );

        luaL_buffinit(L,&b);
        tmp= lua_dump(L, buf_writer, &b);
        ASSERT_L(tmp==0);
            //
            // "value returned is the error code returned by the last call 
            // to the writer" (and we only return 0)

        luaL_pushresult(&b);    // pushes dumped string on 'L'
        s= lua_tolstring(L,-1,&sz);
        ASSERT_L( s && sz );

        if (i!=-1) lua_remove( L, -2 );

        // Note: Line numbers seem to be taken precisely from the 
        //       original function. 'name' is not used since the chunk
        //       is precompiled (it seems...). 
        //
        // TBD: Can we get the function's original name through, as well?
        //
        if (luaL_loadbuffer(L2, s, sz, name) != 0) {
            // chunk is precompiled so only LUA_ERRMEM can happen
            // "Otherwise, it pushes an error message"
            //
            STACK_GROW( L,1 );
            luaL_error( L, "%s", lua_tostring(L2,-1) );
        }
        lua_pop(L,1);   // remove the dumped string
  STACK_MID(L,0)
    }
Ejemplo n.º 5
0
ItemStack read_item(lua_State* L, int index,Server* srv)
{
	if(index < 0)
		index = lua_gettop(L) + 1 + index;

	if(lua_isnil(L, index))
	{
		return ItemStack();
	}
	else if(lua_isuserdata(L, index))
	{
		// Convert from LuaItemStack
		LuaItemStack *o = LuaItemStack::checkobject(L, index);
		return o->getItem();
	}
	else if(lua_isstring(L, index))
	{
		// Convert from itemstring
		std::string itemstring = lua_tostring(L, index);
		IItemDefManager *idef = srv->idef();
		try
		{
			ItemStack item;
			item.deSerialize(itemstring, idef);
			return item;
		}
		catch(SerializationError &e)
		{
			warningstream<<"unable to create item from itemstring"
					<<": "<<itemstring<<std::endl;
			return ItemStack();
		}
	}
	else if(lua_istable(L, index))
	{
		// Convert from table
		IItemDefManager *idef = srv->idef();
		std::string name = getstringfield_default(L, index, "name", "");
		int count = getintfield_default(L, index, "count", 1);
		int wear = getintfield_default(L, index, "wear", 0);

		ItemStack istack(name, count, wear, idef);

		lua_getfield(L, index, "metadata");

		// Support old metadata format by checking type
		int fieldstable = lua_gettop(L);
		if (lua_istable(L, fieldstable)) {
			lua_pushnil(L);
			while (lua_next(L, fieldstable) != 0) {
				// key at index -2 and value at index -1
				std::string key = lua_tostring(L, -2);
				size_t value_len;
				const char *value_cs = lua_tolstring(L, -1, &value_len);
				std::string value(value_cs, value_len);
				istack.metadata.setString(name, value);
				lua_pop(L, 1); // removes value, keeps key for next iteration
			}
		} else {
			// BACKWARDS COMPATIBLITY
			std::string value = getstringfield_default(L, index, "metadata", "");
			istack.metadata.setString("", value);
		}

		lua_getfield(L, index, "meta");
		fieldstable = lua_gettop(L);
		if (lua_istable(L, fieldstable)) {
			lua_pushnil(L);
			while (lua_next(L, fieldstable) != 0) {
				// key at index -2 and value at index -1
				std::string key = lua_tostring(L, -2);
				size_t value_len;
				const char *value_cs = lua_tolstring(L, -1, &value_len);
				std::string value(value_cs, value_len);
				istack.metadata.setString(name, value);
				lua_pop(L, 1); // removes value, keeps key for next iteration
			}
		}

		return istack;
	} else {
		throw LuaError("Expecting itemstack, itemstring, table or nil");
	}
}
Ejemplo n.º 6
0
/*
 * Arguments: membuf_udata, offset (number), value
 */
static int
mem_newindex (lua_State *L)
{
  struct membuf *mb = checkudata(L, 1, MEM_TYPENAME);
  const int off = lua_tointeger(L, 2);
  const int type = memtype(mb);
  char *ptr = mb->data + memlen(type, off);

  switch (lua_type(L, 3)) {
  case LUA_TNUMBER: {
      lua_Number num = lua_tonumber(L, 3);

      switch (type) {
      case MEM_TCHAR:
        *((char *) ptr) = (char) num;
        break;
      case MEM_TUCHAR:
        *((unsigned char *) ptr) = (unsigned char) num;
        break;
      case MEM_TSHORT:
        *((short *) ptr) = (short) num;
        break;
      case MEM_TUSHORT:
        *((unsigned short *) ptr) = (unsigned short) num;
        break;
      case MEM_TINT:
        *((int *) ptr) = (int) num;
        break;
      case MEM_TUINT:
        *((unsigned int *) ptr) = (unsigned int) num;
        break;
      case MEM_TLONG:
        *((long *) ptr) = (long) num;
        break;
      case MEM_TULONG:
        *((unsigned long *) ptr) = (unsigned long) num;
        break;
      case MEM_TFLOAT:
        *((float *) ptr) = (float) num;
        break;
      case MEM_TDOUBLE:
        *((double *) ptr) = (double) num;
        break;
      case MEM_TNUMBER:
        *((lua_Number *) ptr) = num;
        break;
      case MEM_TBITSTRING:
        luaL_argerror(L, 3, "boolean expected");
        break;
      }
    }
    break;
  case LUA_TBOOLEAN:
    if (type != MEM_TBITSTRING)
      luaL_argerror(L, 1, "bitstring expected");
    else {
      const int bit = 1 << (off & 7);

      --ptr;  /* correct address */
      if (lua_toboolean(L, 3)) *ptr |= bit;  /* set */
      else *ptr &= ~bit;  /* clear */
    }
    break;
  case LUA_TSTRING:
    {
      size_t len;
      const char *s = lua_tolstring(L, 3, &len);

      memcpy(ptr, s, len);
    }
    break;
  default:
    luaL_argerror(L, 3, "membuf value expected");
  }
  return 0;
}
ngx_int_t
ngx_http_lua_log_by_chunk(lua_State *L, ngx_http_request_t *r)
{
    ngx_int_t        rc;
    u_char          *err_msg;
    size_t           len;
#if (NGX_PCRE)
    ngx_pool_t      *old_pool;
#endif

    /*  set Lua VM panic handler */
    lua_atpanic(L, ngx_http_lua_atpanic);

    NGX_LUA_EXCEPTION_TRY {

        /* initialize nginx context in Lua VM, code chunk at stack top sp = 1 */
        ngx_http_lua_log_by_lua_env(L, r);

#if (NGX_PCRE)
        /* XXX: work-around to nginx regex subsystem */
        old_pool = ngx_http_lua_pcre_malloc_init(r->pool);
#endif

        lua_pushcfunction(L, ngx_http_lua_traceback);
        lua_insert(L, 1);  /* put it under chunk and args */

        /*  protected call user code */
        rc = lua_pcall(L, 0, 1, 1);

        lua_remove(L, 1);  /* remove traceback function */

#if (NGX_PCRE)
        /* XXX: work-around to nginx regex subsystem */
        ngx_http_lua_pcre_malloc_done(old_pool);
#endif

        if (rc != 0) {
            /*  error occured when running loaded code */
            err_msg = (u_char *) lua_tolstring(L, -1, &len);

            if (err_msg == NULL) {
                err_msg = (u_char *) "unknown reason";
                len = sizeof("unknown reason") - 1;
            }

            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                          "failed to run log_by_lua*: %*s", len, err_msg);

            lua_settop(L, 0);    /*  clear remaining elems on stack */

            return NGX_ERROR;
        }

    } NGX_LUA_EXCEPTION_CATCH {

        dd("nginx execution restored");
        return NGX_ERROR;
    }

    /*  clear Lua stack */
    lua_settop(L, 0);

    return NGX_OK;
}
int
ngx_http_lua_parse_args(ngx_http_request_t *r, lua_State *L, u_char *buf,
        u_char *last, int max)
{
    u_char                      *p, *q;
    u_char                      *src, *dst;
    unsigned                     parsing_value;
    size_t                       len;
    int                          count = 0;
    int                          top;

    top = lua_gettop(L);

    p = buf;

    parsing_value = 0;
    q = p;

    while (p != last) {
        if (*p == '=' && ! parsing_value) {
            /* key data is between p and q */

            src = q; dst = q;

            ngx_http_lua_unescape_uri(&dst, &src, p - q,
                                      NGX_UNESCAPE_URI_COMPONENT);

            dd("pushing key %.*s", (int) (dst - q), q);

            /* push the key */
            lua_pushlstring(L, (char *) q, dst - q);

            /* skip the current '=' char */
            p++;

            q = p;
            parsing_value = 1;

        } else if (*p == '&') {
            /* reached the end of a key or a value, just save it */
            src = q; dst = q;

            ngx_http_lua_unescape_uri(&dst, &src, p - q,
                                      NGX_UNESCAPE_URI_COMPONENT);

            dd("pushing key or value %.*s", (int) (dst - q), q);

            /* push the value or key */
            lua_pushlstring(L, (char *) q, dst - q);

            /* skip the current '&' char */
            p++;

            q = p;

            if (parsing_value) {
                /* end of the current pair's value */
                parsing_value = 0;

            } else {
                /* the current parsing pair takes no value,
                 * just push the value "true" */
                dd("pushing boolean true");

                lua_pushboolean(L, 1);
            }

            (void) lua_tolstring(L, -2, &len);

            if (len == 0) {
                /* ignore empty string key pairs */
                dd("popping key and value...");
                lua_pop(L, 2);

            } else {
                dd("setting table...");
                ngx_http_lua_set_multi_value_table(L, top);
            }

            if (max > 0 && ++count == max) {
                ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                               "lua hit query args limit %d", max);

                return 1;
            }

        } else {
            p++;
        }
    }

    if (p != q || parsing_value) {
        src = q; dst = q;

        ngx_http_lua_unescape_uri(&dst, &src, p - q,
                                  NGX_UNESCAPE_URI_COMPONENT);

        dd("pushing key or value %.*s", (int) (dst - q), q);

        lua_pushlstring(L, (char *) q, dst - q);

        if (!parsing_value) {
            dd("pushing boolean true...");
            lua_pushboolean(L, 1);
        }

        (void) lua_tolstring(L, -2, &len);

        if (len == 0) {
            /* ignore empty string key pairs */
            dd("popping key and value...");
            lua_pop(L, 2);

        } else {
            dd("setting table...");
            ngx_http_lua_set_multi_value_table(L, top);
        }
    }

    dd("gettop: %d", lua_gettop(L));
    dd("type: %s", lua_typename(L, lua_type(L, 1)));

    if (lua_gettop(L) != top) {
        return luaL_error(L, "internal error: stack in bad state");
    }

    return 1;
}
Ejemplo n.º 9
0
Archivo: script.c Proyecto: tdihp/wrk
void script_request(lua_State *L, char **buf, size_t *len) {
    lua_getglobal(L, "request");
    lua_call(L, 0, 1);
    *buf = (char *) lua_tolstring(L, 1, len);
    lua_pop(L, 1);
}
Ejemplo n.º 10
0
bool LuaState::ExecuteLoadString(string const &s, LoadStringResult &result)
{
    if (!this->have_load_string) return false;

    int stack_size = lua_gettop(this->L);

    lua_getglobal(this->L, LOAD_STRING_FUNCTION);
    lua_pushlstring(this->L, s.c_str(), s.length());
    if (lua_pcall(this->L, 1, LUA_MULTRET, 0) != 0) {
        result.execution_success = false;
        size_t len = 0;
        const char *error = lua_tolstring(this->L, -1, &len);
        result.lua_error = string(error, len);
        lua_pop(this->L, 1);
        return true;
    }

    result.execution_success = true;

    int nresults = lua_gettop(L) - stack_size;
    if (nresults < 1) {
        result.return_type = result.INVALID;
        return true;
    }

    // as a refresher, the following type conventions are handled:
    //
    //  nil
    //  bool
    //  1 or more strings
    //  1 or more messages
    //  1 or more envelopes
    //  table, <any of above except nil>

    int stpos = -1 * nresults;
    int value_results = nresults;
    bool got_type = false;

    // handle the one off case for a single nil
    if (nresults == 1 && lua_isnil(this->L, -1)) {
        result.return_type = result.NIL;
        goto LOAD_STRING_POP_AND_RETURN;
    }

    // so we have a type that could be repeated
    // the first and only first one could be a table, so handle that
    if (lua_istable(this->L, stpos)) {
        value_results--;

        if (value_results < 1) {
            result.return_type = result.INVALID;
            goto LOAD_STRING_POP_AND_RETURN;
        }

        // @todo should we error if type is not a string?

        lua_getfield(this->L, stpos, "bucket");
        if (lua_isstring(this->L, -1)) {
            size_t len;
            const char *s = lua_tolstring(this->L, -1, &len);
            result.has_bucket = true;
            result.bucket = string(s, len);
        }
        lua_pop(this->L, 1);

        lua_getfield(this->L, stpos, "set");
        if (lua_isstring(this->L, -1)) {
            size_t len;
            const char *s = lua_tolstring(this->L, -1, &len);
            result.has_set = true;
            result.set = string(s, len);
        }
        lua_pop(this->L, 1);

        stpos++;
    }

    // ok, now iterate through the remaining values
    // make sure the types are consistent along the way
    for (int i = stpos; i < 0; i++) {
        if (lua_isboolean(this->L, i)) {
            // multiple booleans doesn't make any sense. catch it
            if (value_results > 1) {
                result.return_type = result.INVALID;
                goto LOAD_STRING_POP_AND_RETURN;
            }

            result.return_type = lua_toboolean(this->L, i) ? result.BOOLTRUE : result.BOOLFALSE;
            got_type = true;
            continue;
        }

        if (lua_isstring(this->L, i)) {
            // can't mix types
            if (got_type && result.return_type != result.STRING) {
                result.return_type = result.INVALID;
                goto LOAD_STRING_POP_AND_RETURN;
            }

            size_t len = 0;
            const char *s = lua_tolstring(this->L, i, &len);
            result.return_type = result.STRING;
            result.strings.push_back(string(s, len));
            got_type = true;
            continue;
        }

        void *ud = lua_touserdata(this->L, i);
        if (ud == NULL) {
            result.return_type = result.INVALID;
            break;
        }

        if (lua_getmetatable(this->L, i) == 0) {
            result.return_type = result.INVALID;
            break;
        }

        // is it an envelope type
        lua_getfield(this->L, LUA_REGISTRYINDEX, LUA_ENVELOPE_METHOD_TABLENAME);
        if (lua_rawequal(this->L, -2, -1)) {
            // don't need the metatables
            lua_pop(this->L, 2);

            if (got_type && result.return_type != result.ENVELOPE) {
                result.return_type = result.INVALID;
                goto LOAD_STRING_POP_AND_RETURN;
            }

            envelope_udata *ed = (envelope_udata *)ud;

            // we copy the envelope since poorly designed Lua scripts could
            // do evil things with the envelope in Lua land and we don't want
            // that to impact us here
            result.envelopes.push_back(Envelope(*ed->e));

            result.return_type = result.ENVELOPE;
            got_type = true;
            continue;
        }

        // remove metatables
        lua_pop(this->L, 2);

        // @todo handle message case

        result.return_type = result.INVALID;
        break;
    }

LOAD_STRING_POP_AND_RETURN:
    lua_pop(this->L, nresults);

    return true;
}
Ejemplo n.º 11
0
static int
ngx_http_lua_ngx_req_set_uri_args(lua_State *L) {
    ngx_http_request_t          *r;
    ngx_str_t                    args;
    const char                  *msg;
    size_t                       len;
    u_char                      *p;

    if (lua_gettop(L) != 1) {
        return luaL_error(L, "expecting 1 argument but seen %d",
                          lua_gettop(L));
    }

    lua_pushlightuserdata(L, &ngx_http_lua_request_key);
    lua_rawget(L, LUA_GLOBALSINDEX);
    r = lua_touserdata(L, -1);
    lua_pop(L, 1);

    if (r == NULL) {
        return luaL_error(L, "no request object found");
    }

    ngx_http_lua_check_fake_request(L, r);

    switch (lua_type(L, 1)) {
    case LUA_TNUMBER:
    case LUA_TSTRING:
        p = (u_char *) lua_tolstring(L, 1, &len);

        args.data = ngx_palloc(r->pool, len);
        if (args.data == NULL) {
            return luaL_error(L, "out of memory");
        }

        ngx_memcpy(args.data, p, len);

        args.len = len;
        break;

    case LUA_TTABLE:
        ngx_http_lua_process_args_option(r, L, 1, &args);

        dd("args: %.*s", (int) args.len, args.data);

        break;

    default:
        msg = lua_pushfstring(L, "string, number, or table expected, "
                              "but got %s", luaL_typename(L, 2));
        return luaL_argerror(L, 1, msg);
    }

    dd("args: %.*s", (int) args.len, args.data);

    r->args.data = args.data;
    r->args.len = args.len;

    r->valid_unparsed_uri = 0;

    return 0;
}
Ejemplo n.º 12
0
static int
ngx_http_lua_ngx_location_capture_multi(lua_State *L)
{
    ngx_http_request_t              *r;
    ngx_http_request_t              *sr; /* subrequest object */
    ngx_http_post_subrequest_t      *psr;
    ngx_http_lua_ctx_t              *sr_ctx;
    ngx_http_lua_ctx_t              *ctx;
    ngx_array_t                     *extra_vars;
    ngx_str_t                        uri;
    ngx_str_t                        args;
    ngx_str_t                        extra_args;
    ngx_uint_t                       flags;
    u_char                          *p;
    u_char                          *q;
    size_t                           len;
    size_t                           nargs;
    int                              rc;
    int                              n;
    int                              always_forward_body = 0;
    ngx_uint_t                       method;
    ngx_http_request_body_t         *body;
    int                              type;
    ngx_buf_t                       *b;
    unsigned                         vars_action;
    ngx_uint_t                       nsubreqs;
    ngx_uint_t                       index;
    size_t                           sr_statuses_len;
    size_t                           sr_headers_len;
    size_t                           sr_bodies_len;
    size_t                           sr_flags_len;
    unsigned                         custom_ctx;
    ngx_http_lua_co_ctx_t           *coctx;

    ngx_http_lua_post_subrequest_data_t      *psr_data;

    n = lua_gettop(L);
    if (n != 1) {
        return luaL_error(L, "only one argument is expected, but got %d", n);
    }

    luaL_checktype(L, 1, LUA_TTABLE);

    nsubreqs = lua_objlen(L, 1);
    if (nsubreqs == 0) {
        return luaL_error(L, "at least one subrequest should be specified");
    }

    r = ngx_http_lua_get_req(L);
    if (r == NULL) {
        return luaL_error(L, "no request object found");
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
    if (ctx == NULL) {
        return luaL_error(L, "no ctx found");
    }

    ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
                               | NGX_HTTP_LUA_CONTEXT_ACCESS
                               | NGX_HTTP_LUA_CONTEXT_CONTENT);

    coctx = ctx->cur_co_ctx;
    if (coctx == NULL) {
        return luaL_error(L, "no co ctx found");
    }

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "lua location capture, uri:\"%V\" c:%ud", &r->uri,
                   r->main->count);

    sr_statuses_len = nsubreqs * sizeof(ngx_int_t);
    sr_headers_len  = nsubreqs * sizeof(ngx_http_headers_out_t *);
    sr_bodies_len   = nsubreqs * sizeof(ngx_str_t);
    sr_flags_len    = nsubreqs * sizeof(uint8_t);

    p = ngx_pcalloc(r->pool, sr_statuses_len + sr_headers_len +
                    sr_bodies_len + sr_flags_len);

    if (p == NULL) {
        return luaL_error(L, "no memory");
    }

    coctx->sr_statuses = (void *) p;
    p += sr_statuses_len;

    coctx->sr_headers = (void *) p;
    p += sr_headers_len;

    coctx->sr_bodies = (void *) p;
    p += sr_bodies_len;

    coctx->sr_flags = (void *) p;

    coctx->nsubreqs = nsubreqs;

    coctx->pending_subreqs = 0;

    extra_vars = NULL;

    for (index = 0; index < nsubreqs; index++) {
        coctx->pending_subreqs++;

        lua_rawgeti(L, 1, index + 1);
        if (lua_isnil(L, -1)) {
            return luaL_error(L, "only array-like tables are allowed");
        }

        dd("queries query: top %d", lua_gettop(L));

        if (lua_type(L, -1) != LUA_TTABLE) {
            return luaL_error(L, "the query argument %d is not a table, "
                              "but a %s",
                              index, lua_typename(L, lua_type(L, -1)));
        }

        nargs = lua_objlen(L, -1);

        if (nargs != 1 && nargs != 2) {
            return luaL_error(L, "query argument %d expecting one or "
                              "two arguments", index);
        }

        lua_rawgeti(L, 2, 1); /* queries query uri */

        dd("queries query uri: %d", lua_gettop(L));

        dd("first arg in first query: %s", lua_typename(L, lua_type(L, -1)));

        body = NULL;

        ngx_str_null(&extra_args);

        if (extra_vars != NULL) {
            /* flush out existing elements in the array */
            extra_vars->nelts = 0;
        }

        vars_action = 0;

        custom_ctx = 0;

        if (nargs == 2) {
            /* check out the options table */

            lua_rawgeti(L, 2, 2); /* queries query uri opts */

            dd("queries query uri opts: %d", lua_gettop(L));

            if (lua_type(L, 4) != LUA_TTABLE) {
                return luaL_error(L, "expecting table as the 2nd argument for "
                                  "subrequest %d, but got %s", index,
                                  luaL_typename(L, 4));
            }

            dd("queries query uri opts: %d", lua_gettop(L));

            /* check the args option */

            lua_getfield(L, 4, "args");

            type = lua_type(L, -1);

            switch (type) {
            case LUA_TTABLE:
                ngx_http_lua_process_args_option(r, L, -1, &extra_args);
                break;

            case LUA_TNIL:
                /* do nothing */
                break;

            case LUA_TNUMBER:
            case LUA_TSTRING:
                extra_args.data = (u_char *) lua_tolstring(L, -1, &len);
                extra_args.len = len;

                break;

            default:
                return luaL_error(L, "Bad args option value");
            }

            lua_pop(L, 1);

            dd("queries query uri opts: %d", lua_gettop(L));

            /* check the vars option */

            lua_getfield(L, 4, "vars");

            switch (lua_type(L, -1)) {
            case LUA_TTABLE:
                ngx_http_lua_process_vars_option(r, L, -1, &extra_vars);

                dd("post process vars top: %d", lua_gettop(L));
                break;

            case LUA_TNIL:
                /* do nothing */
                break;

            default:
                return luaL_error(L, "Bad vars option value");
            }

            lua_pop(L, 1);

            dd("queries query uri opts: %d", lua_gettop(L));

            /* check the share_all_vars option */

            lua_getfield(L, 4, "share_all_vars");

            switch (lua_type(L, -1)) {
            case LUA_TNIL:
                /* do nothing */
                break;

            case LUA_TBOOLEAN:
                if (lua_toboolean(L, -1)) {
                    vars_action |= NGX_HTTP_LUA_SHARE_ALL_VARS;
                }
                break;

            default:
                return luaL_error(L, "Bad share_all_vars option value");
            }

            lua_pop(L, 1);

            dd("queries query uri opts: %d", lua_gettop(L));

            /* check the copy_all_vars option */

            lua_getfield(L, 4, "copy_all_vars");

            switch (lua_type(L, -1)) {
            case LUA_TNIL:
                /* do nothing */
                break;

            case LUA_TBOOLEAN:
                if (lua_toboolean(L, -1)) {
                    vars_action |= NGX_HTTP_LUA_COPY_ALL_VARS;
                }
                break;

            default:
                return luaL_error(L, "Bad copy_all_vars option value");
            }

            lua_pop(L, 1);

            dd("queries query uri opts: %d", lua_gettop(L));

            /* check the "forward_body" option */

            lua_getfield(L, 4, "always_forward_body");
            always_forward_body = lua_toboolean(L, -1);
            lua_pop(L, 1);

            dd("always foward body: %d", always_forward_body);

            /* check the "method" option */

            lua_getfield(L, 4, "method");

            type = lua_type(L, -1);

            if (type == LUA_TNIL) {
                method = NGX_HTTP_GET;

            } else {
                if (type != LUA_TNUMBER) {
                    return luaL_error(L, "Bad http request method");
                }

                method = (ngx_uint_t) lua_tonumber(L, -1);
            }

            lua_pop(L, 1);

            dd("queries query uri opts: %d", lua_gettop(L));

            /* check the "ctx" option */

            lua_getfield(L, 4, "ctx");

            type = lua_type(L, -1);

            if (type != LUA_TNIL) {
                if (type != LUA_TTABLE) {
                    return luaL_error(L, "Bad ctx option value type %s, "
                                      "expected a Lua table",
                                      lua_typename(L, type));
                }

                custom_ctx = 1;

            } else {
                lua_pop(L, 1);
            }

            dd("queries query uri opts ctx?: %d", lua_gettop(L));

            /* check the "body" option */

            lua_getfield(L, 4, "body");

            type = lua_type(L, -1);

            if (type != LUA_TNIL) {
                if (type != LUA_TSTRING && type != LUA_TNUMBER) {
                    return luaL_error(L, "Bad http request body");
                }

                body = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));

                if (body == NULL) {
                    return luaL_error(L, "no memory");
                }

                q = (u_char *) lua_tolstring(L, -1, &len);

                dd("request body: [%.*s]", (int) len, q);

                if (len) {
                    b = ngx_create_temp_buf(r->pool, len);
                    if (b == NULL) {
                        return luaL_error(L, "no memory");
                    }

                    b->last = ngx_copy(b->last, q, len);

                    body->bufs = ngx_alloc_chain_link(r->pool);
                    if (body->bufs == NULL) {
                        return luaL_error(L, "no memory");
                    }

                    body->bufs->buf = b;
                    body->bufs->next = NULL;

                    body->buf = b;
                }
            }

            lua_pop(L, 1); /* pop the body */

            /* stack: queries query uri opts ctx? */

            lua_remove(L, 4);

            /* stack: queries query uri ctx? */

            dd("queries query uri ctx?: %d", lua_gettop(L));

        } else {
            method = NGX_HTTP_GET;
        }

        /* stack: queries query uri ctx? */

        p = (u_char *) luaL_checklstring(L, 3, &len);

        uri.data = ngx_palloc(r->pool, len);
        if (uri.data == NULL) {
            return luaL_error(L, "memory allocation error");
        }

        ngx_memcpy(uri.data, p, len);

        uri.len = len;

        ngx_str_null(&args);

        flags = 0;

        rc = ngx_http_parse_unsafe_uri(r, &uri, &args, &flags);
        if (rc != NGX_OK) {
            dd("rc = %d", (int) rc);

            return luaL_error(L, "unsafe uri in argument #1: %s", p);
        }

        if (args.len == 0) {
            if (extra_args.len) {
                p = ngx_palloc(r->pool, extra_args.len);
                if (p == NULL) {
                    return luaL_error(L, "no memory");
                }

                ngx_memcpy(p, extra_args.data, extra_args.len);

                args.data = p;
                args.len = extra_args.len;
            }

        } else if (extra_args.len) {
            /* concatenate the two parts of args together */
            len = args.len + (sizeof("&") - 1) + extra_args.len;

            p = ngx_palloc(r->pool, len);
            if (p == NULL) {
                return luaL_error(L, "no memory");
            }

            q = ngx_copy(p, args.data, args.len);
            *q++ = '&';
            ngx_memcpy(q, extra_args.data, extra_args.len);

            args.data = p;
            args.len = len;
        }

        p = ngx_pnalloc(r->pool, sizeof(ngx_http_post_subrequest_t)
                        + sizeof(ngx_http_lua_ctx_t)
                        + sizeof(ngx_http_lua_post_subrequest_data_t));
        if (p == NULL) {
            return luaL_error(L, "no memory");
        }

        psr = (ngx_http_post_subrequest_t *) p;

        p += sizeof(ngx_http_post_subrequest_t);

        sr_ctx = (ngx_http_lua_ctx_t *) p;

        p += sizeof(ngx_http_lua_ctx_t);

        psr_data = (ngx_http_lua_post_subrequest_data_t *) p;

        ngx_memzero(sr_ctx, sizeof(ngx_http_lua_ctx_t));

        /* set by ngx_memzero:
         *      sr_ctx->run_post_subrequest = 0
         *      sr_ctx->free = NULL
         *      sr_ctx->body = NULL
         */

        psr_data->ctx = sr_ctx;
        psr_data->pr_co_ctx = coctx;

        psr->handler = ngx_http_lua_post_subrequest;
        psr->data = psr_data;

        rc = ngx_http_lua_subrequest(r, &uri, &args, &sr, psr, 0);

        if (rc != NGX_OK) {
            return luaL_error(L, "failed to issue subrequest: %d", (int) rc);
        }

        ngx_http_lua_init_ctx(sr, sr_ctx);

        sr_ctx->capture = 1;
        sr_ctx->index = index;
        sr_ctx->last_body = &sr_ctx->body;
        sr_ctx->vm_state = ctx->vm_state;

        ngx_http_set_ctx(sr, sr_ctx, ngx_http_lua_module);

        rc = ngx_http_lua_adjust_subrequest(sr, method, always_forward_body,
                                            body, vars_action, extra_vars);

        if (rc != NGX_OK) {
            ngx_http_lua_cancel_subreq(sr);
            return luaL_error(L, "failed to adjust the subrequest: %d",
                              (int) rc);
        }

        dd("queries query uri opts ctx? %d", lua_gettop(L));

        /* stack: queries query uri ctx? */

        if (custom_ctx) {
            ngx_http_lua_ngx_set_ctx_helper(L, sr, sr_ctx, -1);
            lua_pop(L, 3);

        } else {
            lua_pop(L, 2);
        }

        /* stack: queries */
    }

    if (extra_vars) {
        ngx_array_destroy(extra_vars);
    }

    ctx->no_abort = 1;

    return lua_yield(L, 0);
}
Ejemplo n.º 13
0
int KSystemScriptTable::LuaSaveDataToFile(Lua_State* L)
{
    int nRetCode = false;

    IFile *piFile = NULL;
    const char *pcszFile = NULL;
    const char *pcsBuff = NULL;
    unsigned uFilePathLength = 0;
    size_t uBuffSize = 0;
    int i = 0;
    char szFile[MAX_PATH];
    char szPath[MAX_PATH];

    KGLOG_PROCESS_ERROR(L);

    nRetCode = lua_gettop(L);
    KGLOG_PROCESS_ERROR(nRetCode == 2);

    pcsBuff = lua_tolstring(L, 1, &uBuffSize);
    KGLOG_PROCESS_ERROR(pcsBuff);
    KGLOG_PROCESS_ERROR(uBuffSize > 0);

    pcszFile = lua_tostring(L, 2);
    KGLOG_PROCESS_ERROR(pcszFile);
    KGLOG_PROCESS_ERROR(pcszFile[0]);

    uFilePathLength = snprintf(
                          szFile,
                          sizeof(szFile),
                          "%s\\%s",
                          F_UI_USER_DATA_FOLDER,
                          pcszFile
                      );
    KGLOG_PROCESS_ERROR(uFilePathLength > 0);
    szFile[sizeof(szFile) - 1] = '\0';
    FormatFilePath(szFile);

    szPath[0] = '\0';
    for (i = uFilePathLength; i >= 0; i--)
    {
        if (szFile[i] != '/' && szFile[i] != '\\')
            continue;

        ASSERT(i < sizeof(szPath));
        strncpy(szPath, szFile, i);
        szPath[i] = '\0';
        break;
    }

    nRetCode = KUiConfig::IsFilePathExist(szPath);
    if (!nRetCode)
    {
        nRetCode = KUiConfig::CreatePath(szPath);
        KGLOG_PROCESS_ERROR(nRetCode);
    }

    piFile = g_CreateFile(szFile);
    KGLOG_PROCESS_ERROR(piFile);

    nRetCode = piFile->Write(pcsBuff, (unsigned long)uBuffSize);
    KGLOG_PROCESS_ERROR(nRetCode == uBuffSize);

Exit0:
    SAFE_RELEASE(piFile);
    return 0;
}
Ejemplo n.º 14
0
static int
ts_lua_transform_handler(TSCont contp, ts_lua_transform_ctx *transform_ctx)
{
    TSVConn             output_conn;
    TSVIO               input_vio;
    TSIOBufferReader    input_reader;
    TSIOBufferBlock     blk;
    int64_t             towrite, blk_len, upstream_done, avail, left;
    const char          *start;
    const char          *res;
    size_t              res_len;
    int                 ret, eos;

    lua_State           *L;
    TSMutex             mtxp;

    L = transform_ctx->hctx->lua;
    mtxp = transform_ctx->hctx->mctx->mutexp;

    output_conn = TSTransformOutputVConnGet(contp);
    input_vio = TSVConnWriteVIOGet(contp);
    input_reader = TSVIOReaderGet(input_vio);

    if (!transform_ctx->output_buffer) {
        transform_ctx->output_buffer = TSIOBufferCreate();
        transform_ctx->output_reader = TSIOBufferReaderAlloc(transform_ctx->output_buffer);
        transform_ctx->output_vio = TSVConnWrite(output_conn, contp, transform_ctx->output_reader, INT64_MAX);
    }

    if (!TSVIOBufferGet(input_vio)) {
        TSVIONBytesSet(transform_ctx->output_vio, transform_ctx->total);
        TSVIOReenable(transform_ctx->output_vio);
        return 1;
    }

    if (transform_ctx->eos) {
        return 1;
    }

    left = towrite = TSVIONTodoGet(input_vio);
    upstream_done = TSVIONDoneGet(input_vio);
    avail = TSIOBufferReaderAvail(input_reader);
    eos = 0;

    if (left <= avail)
        eos = 1;

    if (towrite > avail)
        towrite = avail;

    TSMutexLock(mtxp);

    blk = TSIOBufferReaderStart(input_reader);

    do {
        start = TSIOBufferBlockReadStart(blk, input_reader, &blk_len);

        lua_pushlightuserdata(L, transform_ctx);
        lua_rawget(L, LUA_GLOBALSINDEX);                /* push function */

        if (towrite > blk_len) {
            lua_pushlstring(L, start, (size_t)blk_len);
            towrite -= blk_len;
        } else {
            lua_pushlstring(L, start, (size_t)towrite);
            towrite = 0;
        }

        if (!towrite && eos) {
            lua_pushinteger(L, 1);                          /* second param, not finish */ 
        } else {
            lua_pushinteger(L, 0);                          /* second param, not finish */ 
        }

        if (lua_pcall(L, 2, 2, 0)) {
            fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(L, -1));
        }

        ret = lua_tointeger(L, -1);                         /* 0 is not finished, 1 is finished */
        res = lua_tolstring(L, -2, &res_len);

        if (res && res_len) {
            TSIOBufferWrite(transform_ctx->output_buffer, res, res_len);
            transform_ctx->total += res_len;
        }

        lua_pop(L, 2);

        if (ret || (eos && !towrite)) {            // EOS
            eos = 1;
            break;
        }

        blk = TSIOBufferBlockNext(blk);

    } while (blk && towrite > 0);

    TSMutexUnlock(mtxp);

    TSIOBufferReaderConsume(input_reader, avail);
    TSVIONDoneSet(input_vio, upstream_done + avail);

    if (eos) {
        transform_ctx->eos = 1;
        TSVIONBytesSet(transform_ctx->output_vio, transform_ctx->total);
        TSVIOReenable(transform_ctx->output_vio);
        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, input_vio);
    } else {
        TSVIOReenable(transform_ctx->output_vio);
        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_READY, input_vio);
    }

    return 1;
}
Ejemplo n.º 15
0
void
amf0_encode(lua_State *L, amf_buf *buf, int avmplus, int idx, int ridx)
{
    int         array_len, old_top, ref;
    size_t      len;
    const char  *str;

    abs_idx(L, idx);
    abs_idx(L, ridx);

    old_top = lua_gettop(L);

    switch (lua_type(L, idx)) {
    case LUA_TNIL:
        amf_buf_append_char(buf, AMF0_NULL);
        break;

    case LUA_TBOOLEAN:
        amf_buf_append_char(buf, AMF0_BOOLEAN);
        amf_buf_append_char(buf, lua_toboolean(L, idx) ? 1 : 0);
        break;

    case LUA_TNUMBER:
        amf_buf_append_char(buf, AMF0_NUMBER);
        amf0_encode_number(buf, lua_tonumber(L, idx));
        break;

    case LUA_TSTRING:
        str = lua_tolstring(L, idx, &len);
        amf0_encode_string(buf, str, len);
        break;

    case LUA_TTABLE: {
        if (avmplus) {
            lua_newtable(L);
            lua_newtable(L);
            lua_newtable(L);

            int top = lua_gettop(L);

            amf3_encode(L, buf, idx, top-2, top-1, top);

            lua_pop(L, 3);

        } else {
            ref = amf0_encode_ref(buf, L, idx, ridx);
            if (ref >= 0) {
                break;
            }

            array_len = strict_array_length(L, idx);
            if (array_len == 0) {
                amf_buf_append_char(buf, AMF0_NULL);
            } else if (array_len > 0) {
                amf0_encode_table_as_array(buf, L, idx, ridx, array_len);
            } else {
                amf0_encode_table_as_object(buf, L, idx, ridx);
            }
        }
        break;
    }
    }

    assert(lua_gettop(L) == old_top);
}
Ejemplo n.º 16
0
static int _lua_echo(epdata_t *epd, lua_State *L, int nargs, int can_yield)
{
    size_t len = 0;
    int have = 0;
    epd->next_out = NULL;

    if(lua_istable(L, 1)) {
        len = lua_calc_strlen_in_table(L, 1, 2, 0 /* strict */);

        if(len < 1) {
            return 0;
        }

        char *buf = temp_buf;

        if(len > 8192) {
            buf = malloc(len);

            if(!buf) {
                return 0;
            }

            lua_copy_str_in_table(L, 1, buf);
            have = network_send(epd, buf, len);

            if(have > 0 && can_yield) {
                epd->next_out = malloc(have);
                memcpy(epd->next_out, buf + (len - have), have);
            }

            free(buf);

        } else {
            lua_copy_str_in_table(L, 1, buf);
            have = network_send(epd, buf, len);

            if(have > 0 && can_yield) {
                epd->next_out = malloc(have);
                memcpy(epd->next_out, buf + (len - have), have);
            }
        }

    } else {
        const char *data = NULL;
        int i = 0;

        for(i = 1; i <= nargs; i++) {
            if(lua_isboolean(L, i)) {
                char *buf = NULL;

                if(lua_toboolean(L, i)) {
                    buf = "true";
                    have = network_send(epd, buf, 4);

                } else {
                    buf = "false";
                    have = network_send(epd, buf, 5);
                }

                if(have > 0 && can_yield) {
                    epd->next_out = malloc(have);
                    memcpy(epd->next_out, buf + (len - have), have);
                }

            } else {
                data = lua_tolstring(L, i, &len);
                have = network_send(epd, data, len);

                if(have > 0 && can_yield) {
                    epd->next_out = malloc(have);
                    memcpy(epd->next_out, data + (len - have), have);
                }
            }
        }
    }

    if(epd->next_out) {
        if(network_flush(epd) == 1) {
            epd->next_proc = send_then_send;
            epd->next_out_len = have;
            return have;

        } else {
            LOGF(ERR, "flush error");
            free(epd->next_out);
            epd->next_out = NULL;
            return 0;
        }
    }

    return 0;
}
Ejemplo n.º 17
0
void
amf3_encode(lua_State *L, amf_buf *buf, int idx, int sidx, int oidx, int tidx)
{
    int          old_top, array_len;
    const char  *str;
    size_t       str_len;

    old_top = lua_gettop(L);

    switch (lua_type(L, idx)) {
    case LUA_TNIL: {
        amf_buf_append_char(buf, AMF3_NULL);
        break;
    }

    case LUA_TBOOLEAN: {
        if (lua_toboolean(L, idx)) {
            amf_buf_append_char(buf, AMF3_TRUE);
        } else {
            amf_buf_append_char(buf, AMF3_FALSE);
        }
        break;
    }

    case LUA_TNUMBER: {
        lua_Number n = lua_tonumber(L, idx);
        /* encode as double */
        if (floor(n) != n || n < AMF3_MIN_INT || n > AMF3_MAX_INT) {
            amf_buf_append_char(buf, AMF3_DOUBLE);
            amf_buf_append_double(buf, n);
        } else {
            amf_buf_append_char(buf, AMF3_INTEGER);
            amf_buf_append_u29(buf, (int)n);
        }
        break;
    }

    case LUA_TSTRING: {
        str = lua_tolstring(L, idx, &str_len);
        amf_buf_append_char(buf, AMF3_STRING);
        amf3_encode_string(L, buf, idx, sidx);
        break;
    }

    case LUA_TTABLE:
        array_len = strict_array_length(L, idx);

        if (array_len == 0) {
            amf_buf_append_char(buf, AMF3_NULL);

        } else if (array_len > 0) {
            amf3_encode_table_as_array(L, buf, idx, sidx, oidx, tidx, array_len);

        } else {
            amf3_encode_table_as_object(L, buf, idx, sidx, oidx, tidx);

        }

    }

    assert(lua_gettop(L) == old_top);
}
Ejemplo n.º 18
0
int lua_print_error(lua_State *L)
{
    epdata_t *epd = get_epd(L);

    if(!epd) {
        lua_pushnil(L);
        lua_pushstring(L, "miss epd!");
        return 2;
    }

    lua_Debug ar;
    lua_getstack(L, 1, &ar);
    lua_getinfo(L, "nSl", &ar);

    if(!ar.source) {
        return 0;
    }

    snprintf(temp_buf_1024, 1024, "%s:%d", ar.source + 1, ar.currentline);

    lua_getfield(L, LUA_GLOBALSINDEX, "debug");

    if(!lua_istable(L, -1)) {
        lua_pop(L, 1);
        return 1;
    }

    lua_getfield(L, -1, "traceback");

    if(!lua_isfunction(L, -1)) {
        lua_pop(L, 2);
        return 1;
    }

    lua_pushvalue(L, 1);  /* pass error message */
    lua_pushinteger(L, 2);  /* skip this function and traceback */
    lua_call(L, 2, 1);  /* call debug.traceback */

    size_t len = 0;
    char *msg = (char *)lua_tolstring(L, -1, &len);
    int i = 0;
    memcpy(temp_buf2, "<h3>Error: ", 11);
    int j = 11;
    int is_first_line = 1;

    for(i = 0; i < len; i++) {
        temp_buf[i] = (msg[i] != '\n' ? msg[i] : ' ');

        if(is_first_line && msg[i] == '\n') {
            memcpy(temp_buf2 + j, "</h3>\n<pre>", 11);
            j += 11;
        }

        temp_buf2[j++] = msg[i];
    }

    temp_buf[len] = '\0';
    memcpy(temp_buf2 + j, "\n</pre>", 7);
    j += 7;
    temp_buf2[j] = '\0';

    _LOGF(ERR, temp_buf_1024, "%s", temp_buf);
    network_send(epd, temp_buf2, j);

    return 1;
}
Ejemplo n.º 19
0
/**
 * @upvalue z_stream - Memory for the z_stream.
 * @upvalue remainder - Any remainder from the last deflate call.
 *
 * @param string - "print" to deflate stream.
 * @param int - flush output buffer? Z_SYNC_FLUSH, Z_FULL_FLUSH, or Z_FINISH.
 *
 * if no params, terminates the stream (as if we got empty string and Z_FINISH).
 */
static int lz_filter_impl(lua_State *L, int (*filter)(z_streamp, int), int (*end)(z_streamp), const char* name) {
    int flush = Z_NO_FLUSH, result;
    z_stream* stream;
    luaL_Buffer buff;
    size_t avail_in;

    if ( filter == deflate ) {
        const char *const opts[] = { "none", "sync", "full", "finish", NULL };
        flush = luaL_checkoption(L, 2, opts[0], opts);
        if ( flush ) flush++; 
        /* Z_NO_FLUSH(0) Z_SYNC_FLUSH(2), Z_FULL_FLUSH(3), Z_FINISH (4) */

        /* No arguments or nil, we are terminating the stream: */
        if ( lua_gettop(L) == 0 || lua_isnil(L, 1) ) {
            flush = Z_FINISH;
        }
    }

    stream = (z_stream*)lua_touserdata(L, lua_upvalueindex(1));
    if ( stream == NULL ) {
        if ( lua_gettop(L) >= 1 && lua_isstring(L, 1) ) {
            lua_pushfstring(L, "IllegalState: calling %s function when stream was previously closed", name);
            lua_error(L);
        }
        lua_pushstring(L, "");
        lua_pushboolean(L, 1);
        return 2; /* Ignore duplicate calls to "close". */
    }

    luaL_buffinit(L, &buff);

    if ( lua_gettop(L) > 1 ) lua_pushvalue(L, 1);

    if ( lua_isstring(L, lua_upvalueindex(2)) ) {
        lua_pushvalue(L, lua_upvalueindex(2));
        if ( lua_gettop(L) > 1 && lua_isstring(L, -2) ) {
            lua_concat(L, 2);
        }
    }

    /*  Do the actual deflate'ing: */
    if (lua_gettop(L) > 0) {
        stream->next_in = (unsigned char*)lua_tolstring(L, -1, &avail_in);
    } else {
        stream->next_in = NULL;
        avail_in = 0;
    }
    stream->avail_in = (uInt)avail_in;

    if ( ! stream->avail_in && ! flush ) {
        /*  Passed empty string, make it a noop instead of erroring out. */
        lua_pushstring(L, "");
        lua_pushboolean(L, 0);
        lua_pushinteger(L, stream->total_in);
        lua_pushinteger(L, stream->total_out);
        return 4;
    }

    do {
        stream->next_out  = (unsigned char*)luaL_prepbuffer(&buff);
        stream->avail_out = LUAL_BUFFERSIZE;
        result = filter(stream, flush);
        if ( Z_BUF_ERROR != result ) {
            /* Ignore Z_BUF_ERROR since that just indicates that we
             * need a larger buffer in order to proceed.  Thanks to
             * Tobias Markmann for finding this bug!
             */
            lz_assert(L, result, stream, __FILE__, __LINE__);
        }
        luaL_addsize(&buff, LUAL_BUFFERSIZE - stream->avail_out);
    } while ( stream->avail_out == 0 );

    /*  Need to do this before we alter the stack: */
    luaL_pushresult(&buff);

    /*  Save remainder in lua_upvalueindex(2): */
    if ( NULL != stream->next_in ) {
        lua_pushlstring(L, (char*)stream->next_in, stream->avail_in);
        lua_replace(L, lua_upvalueindex(2));
    }

    /*  "close" the stream/remove finalizer: */
    if ( result == Z_STREAM_END ) {
        /*  Clear-out the metatable so end is not called twice: */
        lua_pushnil(L);
        lua_setmetatable(L, lua_upvalueindex(1));

        /*  nil the upvalue: */
        lua_pushnil(L);
        lua_replace(L, lua_upvalueindex(1));

        /*  Close the stream: */
        lz_assert(L, end(stream), stream, __FILE__, __LINE__);

        lua_pushboolean(L, 1);
    } else {
        lua_pushboolean(L, 0);
    }
    lua_pushinteger(L, stream->total_in);
    lua_pushinteger(L, stream->total_out);
    return 4;
}
Ejemplo n.º 20
0
int lua_header(lua_State *L)
{
    epdata_t *epd = get_epd(L);

    if(!epd) {
        lua_pushnil(L);
        lua_pushstring(L, "miss epd!");
        return 2;
    }

    if(epd->websocket) {
        return 0;
    }

    if(lua_gettop(L) < 1) {
        return 0;
    }

    if(epd->header_sended != 0) {
        lua_pushnil(L);
        lua_pushstring(L, "respone header has been sended");
        return 2;
    }

    int t = lua_type(L, 1);
    size_t dlen = 0;
    const char *data = NULL;
    int ret = 0;

    if(t == LUA_TSTRING) {
        data = lua_tolstring(L, 1, &dlen);

        if(stristr(data, "content-length", dlen) != data) {
            ret = network_send_header(epd, data);
        }

    } else if(t == LUA_TTABLE) {
        int len = lua_objlen(L, 1), i = 0;

        for(i = 0; i < len; i++) {
            lua_pushinteger(L, i + 1);
            lua_gettable(L, -2);

            if(lua_isstring(L, -1)) {
                data = lua_tolstring(L, -1, &dlen);

                if(stristr(data, "content-length", dlen) != data) {
                    ret = network_send_header(epd, lua_tostring(L, -1));
                }
            }

            lua_pop(L, 1);
        }
    }

    if(ret == -1) {
        lua_pushnil(L);
        lua_pushstring(L, "respone header too big");
        return 2;

    } else if(ret == 0) {
        lua_pushnil(L);

    } else {
        lua_pushboolean(L, 1);
    }

    return 1;
}
Ejemplo n.º 21
0
static int decrypt(lua_State* pState)
{
    AESObject* aes = (AESObject*)lua_touserdata(pState, 1);

    unsigned char *buffer, *str;
    unsigned char temp[BLOCK_SIZE];
    int i, j, len;

    str = lua_tolstring(pState, 2, &len);
    if (len == 0)
    {
        lua_pushstring(pState, "");
        return 1;
    }

    if ( (len % BLOCK_SIZE) !=0 && (aes->mode!=MODE_CFB))
    {
        luaL_error(pState, 
                 "Input strings must be "
                 "a multiple of %d in length",
                 BLOCK_SIZE);
        return 0;
    }
    if (aes->mode == MODE_CFB && 
        (len % (aes->segment_size/8) !=0)) {
        luaL_error(pState, 
                 "aInput strings must be a multiple of "
                 "the segment size %d in length",
                 aes->segment_size/8);
        return 0;
    }

    buffer = (char*)malloc(len);
    if (!buffer)
    {
        luaL_error(pState, "alloc memory error");
        return 0;
    }

    switch(aes->mode)
    {
        case(MODE_ECB):      
            for(i=0; i<len; i+=BLOCK_SIZE) 
            {
                block_decrypt(&(aes->st), str+i, buffer+i);
            }
            break;

        case(MODE_CBC):      
            for(i=0; i<len; i+=BLOCK_SIZE) 
            {
                memcpy(aes->oldCipher, aes->IV, BLOCK_SIZE);
                block_decrypt(&(aes->st), str+i, temp);
                for(j=0; j<BLOCK_SIZE; j++) 
                {
                    buffer[i+j]=temp[j]^aes->IV[j];
                    aes->IV[j]=str[i+j];
                }
            }
            break;

        case(MODE_CFB):      
            for(i=0; i<len; i+=aes->segment_size/8) 
            {
                block_encrypt(&(aes->st), aes->IV, temp);
                for (j=0; j<aes->segment_size/8; j++) {
                    buffer[i+j] = str[i+j]^temp[j];
                }
                if (aes->segment_size == BLOCK_SIZE * 8) {
                    /* s == b: segment size is identical to 
                       the algorithm block size */
                    memcpy(aes->IV, str + i, BLOCK_SIZE);
                }
                else if ((aes->segment_size % 8) == 0) {
                    int sz = aes->segment_size/8;
                    memmove(aes->IV, aes->IV + sz, 
                        BLOCK_SIZE-sz);
                    memcpy(aes->IV + BLOCK_SIZE - sz, str + i, 
                           sz);
                }
                else {
                    /* segment_size is not a multiple of 8; 
                       currently this can't happen */
                }
            }
            break;

        case (MODE_OFB):
            for(i=0; i<len; i+=BLOCK_SIZE) 
            {
                block_encrypt(&(aes->st), aes->IV, temp);
                memcpy(aes->IV, temp, BLOCK_SIZE);
                for(j=0; j<BLOCK_SIZE; j++)
                {
                    buffer[i+j] = str[i+j] ^ aes->IV[j];
                }
            }      
            break;

        default:
            free(buffer);
            luaL_error(pState, "not support mode");
            return 0;
    }
    lua_pushlstring(pState, buffer, len);
    free(buffer);
    return 1;
}
Ejemplo n.º 22
0
LUA_API const char* luaS_tolstring32(lua_State *L, int index, int* len) {
	size_t l;
	const char* ret = lua_tolstring(L, index, &l);
	*len = (int)l;
	return ret;
}
Ejemplo n.º 23
0
LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
  const char *s = lua_tolstring(L, narg, len);
  if (!s) tag_error(L, narg, LUA_TSTRING);
  return s;
}
Ejemplo n.º 24
0
/**
 * @brief Handles the CLI input.
 *
 *    @param wid Window receiving the input.
 *    @param unused Unused.
 */
static void cli_input( unsigned int wid, char *unused )
{
   (void) unused;
   int status;
   char *str;
   lua_State *L;
   char buf[LINE_LENGTH];

   /* Get the input. */
   str = window_getInput( wid, "inpInput" );

   /* Ignore useless stuff. */
   if (str == NULL)
      return;

   /* Put the message in the console. */
   snprintf( buf, LINE_LENGTH, "%s %s",
         cli_firstline ? "> " : ">>", str );
   cli_addMessage( buf );

   /* Set up state. */
   L = cli_state;

   /* Set up for concat. */
   if (!cli_firstline)           /* o */
      lua_pushliteral(L, "\n");  /* o \n */

   /* Load the string. */
   lua_pushstring( L, str );     /* s */

   /* Concat. */
   if (!cli_firstline)           /* o \n s */
      lua_concat(L, 3);          /* s */

   status = luaL_loadbuffer( L, lua_tostring(L,-1), lua_strlen(L,-1), "=cli" );

   /* String isn't proper Lua yet. */
   if (status == LUA_ERRSYNTAX) {
      size_t lmsg;
      const char *msg = lua_tolstring(L, -1, &lmsg);
      const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
      if (strstr(msg, LUA_QL("<eof>")) == tp) {
         /* Pop the loaded buffer. */
         lua_pop(L, 1);
         cli_firstline = 0;
      }
      else {
         /* Real error, spew message and break. */
         cli_addMessage( lua_tostring(L, -1) );
         lua_settop(L, 0);
         cli_firstline = 1;
      }
   }
   /* Print results - all went well. */
   else if (status == 0) {
      lua_remove(L,1);
      if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
         cli_addMessage( lua_tostring(L, -1) );
         lua_pop(L,1);
      }
      if (lua_gettop(L) > 0) {
         lua_getglobal(L, "print");
         lua_insert(L, 1);
         if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
            cli_addMessage( "Error printing results." );
      }

      /* Clear stack. */
      lua_settop(L, 0);
      cli_firstline = 1;
   }

   /* Clear the box now. */
   window_setInput( wid, "inpInput", NULL );
}
static int
ngx_http_lua_ngx_exec(lua_State *L)
{
    int                          n;
    ngx_http_request_t          *r;
    ngx_http_lua_ctx_t          *ctx;
    ngx_str_t                    uri;
    ngx_str_t                    args, user_args;
    ngx_uint_t                   flags;
    u_char                      *p;
    u_char                      *q;
    size_t                       len;
    const char                  *msg;

    n = lua_gettop(L);
    if (n != 1 && n != 2) {
        return luaL_error(L, "expecting one or two arguments, but got %d",
                          n);
    }

    r = ngx_http_lua_get_req(L);
    if (r == NULL) {
        return luaL_error(L, "no request object found");
    }

    ngx_str_null(&args);

    /* read the 1st argument (uri) */

    p = (u_char *) luaL_checklstring(L, 1, &len);

    if (len == 0) {
        return luaL_error(L, "The uri argument is empty");
    }

    uri.data = ngx_palloc(r->pool, len);
    if (uri.data == NULL) {
        return luaL_error(L, "no memory");
    }

    ngx_memcpy(uri.data, p, len);

    uri.len = len;

    ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
    if (ctx == NULL) {
        return luaL_error(L, "no ctx found");
    }

    ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
                               | NGX_HTTP_LUA_CONTEXT_ACCESS
                               | NGX_HTTP_LUA_CONTEXT_CONTENT);

    ngx_http_lua_check_if_abortable(L, ctx);

    if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags)
        != NGX_OK)
    {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    if (n == 2) {
        /* read the 2nd argument (args) */
        dd("args type: %s", luaL_typename(L, 2));

        switch (lua_type(L, 2)) {
        case LUA_TNUMBER:
        case LUA_TSTRING:
            p = (u_char *) lua_tolstring(L, 2, &len);

            user_args.data = ngx_palloc(r->pool, len);
            if (user_args.data == NULL) {
                return luaL_error(L, "no memory");
            }

            ngx_memcpy(user_args.data, p, len);

            user_args.len = len;
            break;

        case LUA_TTABLE:
            ngx_http_lua_process_args_option(r, L, 2, &user_args);

            dd("user_args: %.*s", (int) user_args.len, user_args.data);

            break;

        case LUA_TNIL:
            ngx_str_null(&user_args);
            break;

        default:
            msg = lua_pushfstring(L, "string, number, or table expected, "
                                  "but got %s", luaL_typename(L, 2));
            return luaL_argerror(L, 2, msg);
        }

    } else {
        user_args.data = NULL;
        user_args.len = 0;
    }

    if (user_args.len) {
        if (args.len == 0) {
            args = user_args;

        } else {
            p = ngx_palloc(r->pool, args.len + user_args.len + 1);
            if (p == NULL) {
                return luaL_error(L, "no memory");
            }

            q = ngx_copy(p, args.data, args.len);
            *q++ = '&';
            ngx_memcpy(q, user_args.data, user_args.len);

            args.data = p;
            args.len += user_args.len + 1;
        }
    }

    if (r->header_sent || ctx->header_sent) {
        return luaL_error(L, "attempt to call ngx.exec after "
                          "sending out response headers");
    }

    ctx->exec_uri = uri;
    ctx->exec_args = args;

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "lua exec \"%V?%V\"",
                   &ctx->exec_uri, &ctx->exec_args);

    return lua_yield(L, 0);
}
Ejemplo n.º 26
0
static int
ngx_http_lua_shdict_set_helper(lua_State *L, int flags)
{
    int                          i, n;
    ngx_str_t                    key;
    uint32_t                     hash;
    ngx_int_t                    rc;
    ngx_http_lua_shdict_ctx_t   *ctx;
    ngx_http_lua_shdict_node_t  *sd;
    ngx_str_t                    value;
    int                          value_type;
    double                       num;
    u_char                       c;
    lua_Number                   exptime = 0;
    u_char                      *p;
    ngx_rbtree_node_t           *node;
    ngx_time_t                  *tp;
    ngx_shm_zone_t              *zone;
    int                          forcible = 0;
                         /* indicates whether to foricibly override other
                          * valid entries */
    int32_t                      user_flags = 0;

    n = lua_gettop(L);

    if (n != 3 && n != 4 && n != 5) {
        return luaL_error(L, "expecting 3, 4 or 5 arguments, "
                          "but only seen %d", n);
    }

    zone = lua_touserdata(L, 1);
    if (zone == NULL) {
        return luaL_error(L, "bad \"zone\" argument");
    }

    ctx = zone->data;

    if (lua_isnil(L, 2)) {
        lua_pushnil(L);
        lua_pushliteral(L, "nil key");
        return 2;
    }

    key.data = (u_char *) luaL_checklstring(L, 2, &key.len);

    if (key.len == 0) {
        lua_pushnil(L);
        lua_pushliteral(L, "empty key");
        return 2;
    }

    if (key.len > 65535) {
        lua_pushnil(L);
        lua_pushliteral(L, "key too long");
        return 2;
    }

    hash = ngx_crc32_short(key.data, key.len);

    value_type = lua_type(L, 3);

    switch (value_type) {
    case LUA_TSTRING:
        value.data = (u_char *) lua_tolstring(L, 3, &value.len);
        break;

    case LUA_TNUMBER:
        value.len = sizeof(double);
        num = lua_tonumber(L, 3);
        value.data = (u_char *) &num;
        break;

    case LUA_TBOOLEAN:
        value.len = sizeof(u_char);
        c = lua_toboolean(L, 3) ? 1 : 0;
        value.data = &c;
        break;

    case LUA_TNIL:
        if (flags & (NGX_HTTP_LUA_SHDICT_ADD|NGX_HTTP_LUA_SHDICT_REPLACE)) {
            lua_pushnil(L);
            lua_pushliteral(L, "attempt to add or replace nil values");
            return 2;
        }

        ngx_str_null(&value);
        break;

    default:
        lua_pushnil(L);
        lua_pushliteral(L, "bad value type");
        return 2;
    }

    if (n >= 4) {
        exptime = luaL_checknumber(L, 4);
        if (exptime < 0) {
            exptime = 0;
        }
    }

    if (n == 5) {
        user_flags = (uint32_t) luaL_checkinteger(L, 5);
    }

    ngx_shmtx_lock(&ctx->shpool->mutex);

#if 1
    ngx_http_lua_shdict_expire(ctx, 1);
#endif

    rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len, &sd);

    dd("shdict lookup returned %d", (int) rc);

    if (flags & NGX_HTTP_LUA_SHDICT_REPLACE) {

        if (rc == NGX_DECLINED || rc == NGX_DONE) {
            ngx_shmtx_unlock(&ctx->shpool->mutex);

            lua_pushboolean(L, 0);
            lua_pushliteral(L, "not found");
            lua_pushboolean(L, forcible);
            return 3;
        }

        /* rc == NGX_OK */

        goto replace;
    }

    if (flags & NGX_HTTP_LUA_SHDICT_ADD) {

        if (rc == NGX_OK) {
            ngx_shmtx_unlock(&ctx->shpool->mutex);

            lua_pushboolean(L, 0);
            lua_pushliteral(L, "exists");
            lua_pushboolean(L, forcible);
            return 3;
        }

        if (rc == NGX_DONE) {
            /* exists but expired */

            dd("go to replace");
            goto replace;
        }

        /* rc == NGX_DECLINED */

        dd("go to insert");
        goto insert;
    }

    if (rc == NGX_OK || rc == NGX_DONE) {

        if (value_type == LUA_TNIL) {
            goto remove;
        }

replace:

        if (value.data && value.len == (size_t) sd->value_len) {

            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
                           "lua shared dict set: found old entry and value "
                           "size matched, reusing it");

            ngx_queue_remove(&sd->queue);
            ngx_queue_insert_head(&ctx->sh->queue, &sd->queue);

            sd->key_len = (u_short) key.len;

            if (exptime > 0) {
                tp = ngx_timeofday();
                sd->expires = (uint64_t) tp->sec * 1000 + tp->msec
                              + (uint64_t) (exptime * 1000);

            } else {
                sd->expires = 0;
            }

            sd->user_flags = user_flags;

            sd->value_len = (uint32_t) value.len;

            dd("setting value type to %d", value_type);

            sd->value_type = (uint8_t) value_type;

            p = ngx_copy(sd->data, key.data, key.len);
            ngx_memcpy(p, value.data, value.len);

            ngx_shmtx_unlock(&ctx->shpool->mutex);

            lua_pushboolean(L, 1);
            lua_pushnil(L);
            lua_pushboolean(L, forcible);
            return 3;
        }

        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
                       "lua shared dict set: found old entry but value size "
                       "NOT matched, removing it first");

remove:

        ngx_queue_remove(&sd->queue);

        node = (ngx_rbtree_node_t *)
                   ((u_char *) sd - offsetof(ngx_rbtree_node_t, color));

        ngx_rbtree_delete(&ctx->sh->rbtree, node);

        ngx_slab_free_locked(ctx->shpool, node);

    }

insert:

    /* rc == NGX_DECLINED or value size unmatch */

    if (value.data == NULL) {
        ngx_shmtx_unlock(&ctx->shpool->mutex);

        lua_pushboolean(L, 1);
        lua_pushnil(L);
        lua_pushboolean(L, 0);
        return 3;
    }

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
                   "lua shared dict set: creating a new entry");

    n = offsetof(ngx_rbtree_node_t, color)
        + offsetof(ngx_http_lua_shdict_node_t, data)
        + key.len
        + value.len;

    node = ngx_slab_alloc_locked(ctx->shpool, n);

    if (node == NULL) {

        if (flags & NGX_HTTP_LUA_SHDICT_SAFE_STORE) {
            ngx_shmtx_unlock(&ctx->shpool->mutex);

            lua_pushboolean(L, 0);
            lua_pushliteral(L, "no memory");
            return 2;
        }

        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
                       "lua shared dict set: overriding non-expired items "
                       "due to memory shortage for entry \"%V\"", &key);

        for (i = 0; i < 30; i++) {
            if (ngx_http_lua_shdict_expire(ctx, 0) == 0) {
                break;
            }

            forcible = 1;

            node = ngx_slab_alloc_locked(ctx->shpool, n);
            if (node != NULL) {
                goto allocated;
            }
        }

        ngx_shmtx_unlock(&ctx->shpool->mutex);

        lua_pushboolean(L, 0);
        lua_pushliteral(L, "no memory");
        lua_pushboolean(L, forcible);
        return 3;
    }

allocated:

    sd = (ngx_http_lua_shdict_node_t *) &node->color;

    node->key = hash;
    sd->key_len = (u_short) key.len;

    if (exptime > 0) {
        tp = ngx_timeofday();
        sd->expires = (uint64_t) tp->sec * 1000 + tp->msec
                      + (uint64_t) (exptime * 1000);

    } else {
        sd->expires = 0;
    }

    sd->user_flags = user_flags;

    sd->value_len = (uint32_t) value.len;

    dd("setting value type to %d", value_type);

    sd->value_type = (uint8_t) value_type;

    p = ngx_copy(sd->data, key.data, key.len);
    ngx_memcpy(p, value.data, value.len);

    ngx_rbtree_insert(&ctx->sh->rbtree, node);

    ngx_queue_insert_head(&ctx->sh->queue, &sd->queue);

    ngx_shmtx_unlock(&ctx->shpool->mutex);

    lua_pushboolean(L, 1);
    lua_pushnil(L);
    lua_pushboolean(L, forcible);
    return 3;
}
Ejemplo n.º 27
0
static int _sasl_s_canon_user(sasl_conn_t *conn,
			      void *context,
			      const char *user, unsigned ulen,
			      unsigned flags,
			      const char *user_realm,
			      char *out_user, unsigned out_umax,
			      unsigned *out_ulen)
{
  struct _sasl_ctx *ctxp = context;

  if (!conn || !context || !user || ctxp->magic != CYRUSSASL_MAGIC)
    return SASL_BADPARAM;

  if (!(flags & SASL_CU_AUTHID) && !(flags & SASL_CU_AUTHZID))
    return SASL_BADPARAM;

  if (!out_user || !out_ulen || out_umax == 0)
    return SASL_BADPARAM;

  if (ctxp->canon_cb_ref == LUA_REFNIL) {
    if (ulen >= out_umax)
      return SASL_BUFOVER;

    /* out_user may be the same as user, so memmove, not memcpy */
    memmove(out_user, user, ulen);
    out_user[ulen] = '\0';
    *out_ulen = ulen;

    set_context_user(context, user, ulen);
    return SASL_OK;
  }

  /* We have a callback to deal with. */

  int ret = SASL_OK;
  const char *str = NULL;
  size_t len = 0;
  
  /* Function to call */
  lua_rawgeti(ctxp->L, LUA_REGISTRYINDEX, ctxp->canon_cb_ref);
  
  /* Username */
  lua_pushlstring(ctxp->L, user, ulen);
  /* Realm */
  lua_pushstring(ctxp->L, user_realm);
  /* flags (the type of username) */
  if ((flags & SASL_CU_AUTHID) && (flags & SASL_CU_AUTHZID))
    lua_pushliteral(ctxp->L, "both");
  else if (flags & SASL_CU_AUTHID)
    lua_pushliteral(ctxp->L, "authcid");
  else
    lua_pushliteral(ctxp->L, "authzid");
  /* Perform: str = cb(user, user_realm, "both|authcid|authzid") */
  lua_call(ctxp->L, 3, 1);
  
  /* Get the result */
  str = lua_tolstring(ctxp->L, -1, &len);
  if (str == NULL)
    ret = SASL_BADPROT;
  else if (len >= out_umax)
    ret = SASL_BUFOVER;
  else {
    memcpy(out_user, str, len + 1);
    *out_ulen = len;
  }
  
  /* Pop the result of the call off the stack */
  lua_pop(ctxp->L, 1);

  if (ret == SASL_OK)
    set_context_user(context, out_user, *out_ulen);
  else
    set_context_user(context, NULL, 0);

  return ret;
}
Ejemplo n.º 28
0
static void
ngx_http_lua_clear_package_loaded(lua_State *L)
{
    size_t       len;
    u_char      *p;

    dd("clear out package.loaded.* on the Lua land");
    lua_getglobal(L, "package"); /* package */
    lua_getfield(L, -1, "loaded"); /* package loaded */
    lua_pushnil(L); /* package loaded nil */

    while (lua_next(L, -2)) { /* package loaded key value */
        lua_pop(L, 1);  /* package loaded key */

        p = (u_char *) lua_tolstring(L, -1, &len);

#if 1
        /* XXX work-around the "stack overflow" issue of LuaRocks
         * while unloading and reloading Lua modules */
        if (len >= sizeof("luarocks") - 1
            && ngx_strncmp(p, "luarocks", sizeof("luarocks") - 1) == 0)
        {
            goto done;
        }
#endif

        switch (len) {
        case 2:
            if (p[0] == 'o' && p[1] == 's') {
                goto done;
            }

            if (p[0] == 'i' && p[1] == 'o') {
                goto done;
            }

#if 0
            if (ngx_strncmp(p, "_G", sizeof("_G") - 1) == 0) {
                goto done;
            }
#endif

            break;

        case 3:
            if (ngx_strncmp(p, "bit", sizeof("bit") - 1) == 0) {
                goto done;
            }

            if (ngx_strncmp(p, "jit", sizeof("jit") - 1) == 0) {
                goto done;
            }

            if (ngx_strncmp(p, "ngx", sizeof("ngx") - 1) == 0) {
                goto done;
            }

            if (ngx_strncmp(p, "ndk", sizeof("ndk") - 1) == 0) {
                goto done;
            }

            break;

        case 4:
            if (ngx_strncmp(p, "math", sizeof("math") - 1) == 0) {
                goto done;
            }

            break;

        case 5:
            if (ngx_strncmp(p, "table", sizeof("table") - 1) == 0) {
                goto done;
            }

            if (ngx_strncmp(p, "debug", sizeof("table") - 1) == 0) {
                goto done;
            }

            break;

        case 6:
            if (ngx_strncmp(p, "string", sizeof("string") - 1) == 0) {
                goto done;
            }

            break;

        case 7:
            if (ngx_strncmp(p, "package", sizeof("package") - 1) == 0) {
                goto done;
            }

            if (ngx_strncmp(p, "jit.opt", sizeof("jit.opt") - 1) == 0) {
                goto done;
            }

            break;

       case 8:
            if (ngx_strncmp(p, "jit.util", sizeof("jit.util") - 1) == 0) {
                goto done;
            }

            break;

       case 9:
            if (ngx_strncmp(p, "coroutine", sizeof("coroutine") - 1) == 0) {
                goto done;
            }

            break;

        default:
            break;
        }

        dd("clearing package %s", p);

        lua_pushvalue(L, -1);  /* package loaded key key */
        lua_pushnil(L); /* package loaded key key nil */
        lua_settable(L, -4);  /* package loaded key */
done:
        continue;
    }

    /* package loaded */
    lua_pop(L, 2);

    lua_newtable(L);
    lua_setglobal(L, "_G");
}
Ejemplo n.º 29
0
AV *
plu_table_obj_to_array(pTHX_ plu_table_t *THIS, int recursive)
{
  PLU_dSTACKASSERT;
  int table_stack_offset;
  lua_State *L;
  char *keystr;
  size_t keylen;
  SV *value_sv;
  int dopop;
  AV *RETVAL;
  I32 aryidx;

  L = THIS->L;
  PLU_ENTER_STACKASSERT(L);
  PLU_TABLE_PUSH_TO_STACK(*THIS);

  RETVAL = newAV();
  sv_2mortal((SV *)RETVAL);
  table_stack_offset = lua_gettop(L);

  lua_pushnil(L);  /* first key */
  while (lua_next(L, table_stack_offset) != 0) {
    /* uses 'key' (at index -2) and 'value' (at index -1) */

    /* Prepare key - cast to int if need be */
    switch (lua_type(L, -2)) {
    case LUA_TSTRING:
    {
      SV *tmpsv;
      keystr = (char *)lua_tolstring(L, -2, &keylen);
      /* Using SV is not efficient, but may cause the perl warnings we want.
       * That in turn may cause Perl code to be run that can throw exceptions.
       * So we need to mortalize. Grmpf. */
      tmpsv = newSVpvn(keystr, (STRLEN)keylen);
      sv_2mortal(tmpsv);
      aryidx = (I32)SvIV(tmpsv);
      SvREFCNT_dec(tmpsv);
      break;
    }
    case LUA_TNUMBER:
    {
      lua_Number n = lua_tonumber(L, -2); /* Don't change its type with lua_tointeger! */
      aryidx = (I32)n; /* FIXME should this warn for actual truncation? */
      break;
    }
    case LUA_TBOOLEAN:
      aryidx = lua_toboolean(L, -2);
      break;
    default:
      croak("Unsupported Lua type '%s' for Perl array indexes", lua_typename(L, lua_type(L, 02)));
    }

    /* Prepare value */
    value_sv = plu_luaval_to_perl(aTHX_ L, -1, &dopop);
    if (recursive && SvROK(value_sv)
        && sv_derived_from(value_sv, "PLua::Table"))
    {
      AV *tmpa;
      tmpa = plu_table_obj_to_array(aTHX_ (plu_table_t *)SvIV(SvRV(value_sv)), recursive);
      SvREFCNT_dec(value_sv);
      value_sv = newRV_inc((SV *)tmpa);
    }

    (void)av_store(RETVAL, aryidx, value_sv);

    /* removes 'value' if not already done; keeps 'key' for next iteration */
    if (dopop)
      lua_pop(L, 1);
  }
  lua_pop(L, 1);

  PLU_LEAVE_STACKASSERT(L);

  return RETVAL;
}
Ejemplo n.º 30
0
int am_require(lua_State *L) {
    am_check_nargs(L, 1);
    char tmpbuf1[TMP_BUF_SZ];
    char tmpbuf2[TMP_BUF_SZ];
    size_t len;
    const char *modname = lua_tolstring(L, 1, &len);

    // check for string argument
    if (modname == NULL) {
        return luaL_error(L, "require expects a string as its single argument");
    }

    // check module name not too long
    if (len > TMP_BUF_SZ - 10) {
        return luaL_error(L, "module name '%s' too long", modname);
    }

    // check if module has already been loaded
    lua_rawgeti(L, LUA_REGISTRYINDEX, AM_MODULE_TABLE);
    lua_pushvalue(L, 1); // module name
    lua_rawget(L, -2);
    if (!lua_isnil(L, -1)) {
        // already loaded, or busy loading
        lua_remove(L, -2); // module table
        return 1;
    }
    lua_pop(L, 1); // nil

    // create exports table and add to module table:
    lua_newtable(L);
    lua_pushvalue(L, 1); // module name
    lua_pushvalue(L, -2); // export table
    lua_rawset(L, -4); // set it
    // export table now on top

    // read in the module
    int sz;
    strncpy(tmpbuf1, modname, TMP_BUF_SZ);
    am_replchr(tmpbuf1, '.', AM_PATH_SEP);
    snprintf(tmpbuf2, TMP_BUF_SZ, "%s.lua", tmpbuf1);
    char *errmsg;
    void *buf = am_read_resource(tmpbuf2, &sz, &errmsg);
    if (buf == NULL) {
        lua_pushfstring(L, "unable to load module '%s': %s", modname, errmsg);
        free(errmsg);
        return lua_error(L);
    }

    // replace "#!" at start with "--"
    char *cbuf = (char*)buf;
    if (sz >= 2 && cbuf[0] == '#' && cbuf[1] == '!') {
        cbuf[0] = '-';
        cbuf[1] = '-';
    }

    // parse and load the module
    snprintf(tmpbuf2, TMP_BUF_SZ, "@%s.lua", tmpbuf1);
    int res = luaL_loadbuffer(L, (const char*)buf, sz, tmpbuf2);
    free(buf);
    if (res != 0) return lua_error(L);

    // pass export table as arg
    lua_pushvalue(L, -2); // export table
    lua_call(L, 1, 1);

    if (!lua_isnil(L, -1)) {
        // replace export table with returned value in module table
        lua_pushvalue(L, 1); // module name
        lua_pushvalue(L, -2); // returned value
        lua_rawset(L, -5);
        lua_remove(L, -2); // export table
        lua_remove(L, -2); // module table
        // return value now on top
    } else {
        lua_pop(L, 1); // nil
        lua_remove(L, -2); // module table
        // export table now on top
    }
    return 1;
}