Example #1
0
/* TODO: typed object support */
static void
amf0_encode_table_as_object(amf_buf *buf, lua_State *L, int idx, int ridx)
{
    size_t key_len;
    const char *key;
    amf_buf_append_char(buf, AMF0_OBJECT);

    for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 1)) {
        switch (lua_type(L, -2)) {
        case LUA_TNUMBER:
            lua_pushvalue(L, -2);
            key = lua_tolstring(L, -1, &key_len);
            amf_buf_append_u16(buf, (uint16_t)key_len);
            amf_buf_append(buf, key, key_len);
            lua_pop(L, 1);

            break;

        case LUA_TSTRING:
            key = lua_tolstring(L, -2, &key_len);
            amf_buf_append_u16(buf, (uint16_t)key_len);
            amf_buf_append(buf, key, key_len);

            break;

        default: continue;
        }
        amf0_encode(L, buf, 0, -1, ridx);
    }

    amf_buf_append_u16(buf, (uint16_t)0);
    amf_buf_append_char(buf, AMF0_END_OF_OBJECT);

}
Example #2
0
static int
amf0_encode_ref(amf_buf *buf, lua_State *L, int idx, int ridx)
{
    int ref;

    /* lookup in the ref table */
    lua_pushvalue(L, idx);
    lua_rawget(L, ridx);
    ref = (lua_isnumber(L, -1) ? lua_tonumber(L, -1) : -1);
    lua_pop(L, 1);

    if (ref >= 0) {
        amf_buf_append_char(buf, AMF0_REFERENCE);
        if (ref > UINT16_MAX) {
            luaL_error(L, "amf0 reference overflow");
        }
        amf_buf_append_u16(buf, ref);

    } else {
        save_ref(L, idx, ridx);

    }

    return ref;
}
Example #3
0
static void
amf3_encode_table_as_object(lua_State *L, amf_buf *buf, int idx, int sidx, int oidx, int tidx)
{
    abs_idx(L, idx);

    amf_buf_append_char(buf, AMF3_OBJECT);

    if (amf3_encode_ref(L, buf, idx, oidx) >= 0) {
        return;
    }

    lua_newtable(L); /* traits table */
    int members = 1;
    for(lua_pushnil(L); lua_next(L, idx); lua_pop(L, 1)) {
        switch (lua_type(L, -2)) {
            case LUA_TNUMBER:
                lua_pushvalue(L, -2);
                lua_tostring(L, -1);
                break;
            case LUA_TSTRING:
                lua_pushvalue(L, -2);
                break;
            default:
                continue;
        }
        lua_rawseti(L, -4, members++);
    }

    amf3_encode_traits(L, buf, lua_gettop(L), sidx, tidx);
    lua_pop(L, 1); /* drop the traits table */

    for(lua_pushnil(L); lua_next(L, idx); lua_pop(L, 1)) {
        amf3_encode(L, buf, -1, sidx, oidx, tidx);
    }
}
Example #4
0
static void
encode_hdr(lua_State *L, amf_buf *buf, int ver)
{
    if(!lua_istable(L, -1)) {
        luaL_error(L, "invalid header structure, must be a dense table");
    }

    /* name */
    lua_rawgeti(L, -1, 1);
    size_t len;
    const char *name = lua_tolstring(L, -1, &len);
    amf_buf_append_u16(buf, (uint16_t)len);
    if (len > 0)
        amf_buf_append(buf, name, (uint16_t)len);
    lua_pop(L, 1);

    /* must understand */
    lua_rawgeti(L, -1, 2);
    int mu = lua_toboolean(L, -1);
    amf_buf_append_char(buf, (char)mu);
    lua_pop(L, 1);

    /* content length */
    amf_buf_append_u32(buf, (uint32_t)0);

    lua_rawgeti(L, -1, 3);
    lua_newtable(L);
    amf0_encode(L, buf, (ver == 3), -2, lua_gettop(L));
    lua_pop(L, 2); /* pops the obj and ref table */
}
Example #5
0
static int
lua_amf_buffer_write_uchar(lua_State *L)
{
    amf_buf *b = luaL_checkudata(L, 1, "amf_buffer");
    unsigned char c = (unsigned char)luaL_checkint(L, 2);

    amf_buf_append_char(b, c);

    return 0;
}
Example #6
0
static void
amf0_encode_string(amf_buf *b, const char *s, size_t len)
{
    uint16_t u16;
    uint32_t u32;

    if (len < UINT16_MAX) {
        u16 = (uint16_t)len;

        amf_buf_append_char(b, AMF0_STRING);
        amf_buf_append_u16(b, u16);
        amf_buf_append(b, s, u16);

    } else { // long string
        if (len > UINT32_MAX) {
            len = UINT32_MAX;
        }
        u32 = (uint32_t)len;

        amf_buf_append_char(b, AMF0_L_STRING);
        amf_buf_append_u32(b, u32);
        amf_buf_append(b, s, u32);
    }
}
Example #7
0
static void
amf0_encode_table_as_array(amf_buf *buf, lua_State *L, int idx, int ridx, int len)
{
    amf_buf_append_char(buf, AMF0_STRICT_ARRAY);
    amf_buf_append_u32(buf, (uint32_t)len); // array count


    for (int i = 1; i <= len; i++) {
        lua_pushinteger(L, i);
        lua_gettable(L, idx);

        amf0_encode(L, buf, 0, -1, ridx);
        lua_pop(L, 1);
    }

}
Example #8
0
static void
amf3_encode_table_as_array(lua_State *L, amf_buf *buf, int idx, int sidx, int oidx, int tidx, int array_len)
{
    abs_idx(L, idx);
    amf_buf_append_char(buf, AMF3_ARRAY);
    if (amf3_encode_ref(L, buf, idx, oidx) >=0) {
        return;
    }

    amf_buf_append_u29(buf, (array_len << 1) | 1);
    /*Send an empty string to imply no named keys*/
    amf_buf_append_u29(buf, (0 << 1) | 1);

    for (int i = 1; i <= array_len; i++) {
        lua_rawgeti(L, idx, i);

        amf3_encode(L, buf, -1, sidx, oidx, tidx);
        lua_pop(L, 1);
    }

}
Example #9
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);
}
Example #10
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);
}