static int
ngx_http_lua_ngx_unescape_uri(lua_State *L)
{
    size_t                   len, dlen;
    u_char                  *p;
    u_char                  *src, *dst;

    if (lua_gettop(L) != 1) {
        return luaL_error(L, "expecting one argument");
    }

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

    /* the unescaped string can only be smaller */
    dlen = len;

    p = lua_newuserdata(L, dlen);

    dst = p;

    ngx_http_lua_unescape_uri(&dst, &src, len, NGX_UNESCAPE_URI_COMPONENT);

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

    return 1;
}
size_t
ngx_http_lua_ffi_unescape_uri(const u_char *src, size_t len, u_char *dst)
{
    u_char      *p = dst;

    ngx_http_lua_unescape_uri(&p, (u_char **) &src, len,
                              NGX_UNESCAPE_URI_COMPONENT);
    return p - dst;
}
Esempio n. 3
0
static int
ngx_http_lua_ngx_unescape_uri(lua_State *L)
{
    ngx_http_request_t      *r;
    size_t                   len, dlen;
    u_char                  *p;
    u_char                  *src, *dst;

    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");
    }

    if (lua_gettop(L) != 1) {
        return luaL_error(L, "expecting one argument");
    }

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

    /* the unescaped string can only be smaller */
    dlen = len;

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

    dst = p;

    ngx_http_lua_unescape_uri(&dst, &src, len, NGX_UNESCAPE_URI_COMPONENT);

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

    return 1;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
int worker_process ( epdata_t *epd, int thread_at )
{
    //printf("worker_process\n");
    working_at_fd = epd->fd;
    long start_time = longtime();
    //network_send_error(epd, 503, "Lua Error: main function not found !!!");return 0;
    //network_send(epd, "aaa", 3);network_be_end(epd);return 0;
    add_io_counts();
    lua_State *L = ( _L ); //lua_newthread

    if ( main_handle_ref != 0 ) {
        lua_rawgeti ( L, LUA_REGISTRYINDEX, main_handle_ref );

    } else {
        lua_getglobal ( L, "main" );
    }

    /*if(!lua_isfunction(L,-1))
    {
        lua_pop(L,1);
        printf("no function\n");
    }else*/{
        int init_tables = 0;
        char *pt1 = NULL, *pt2 = NULL, *t1 = NULL, *t2 = NULL, *t3 = NULL, *query = NULL;

        int is_form_post = 0;
        char *boundary_post = NULL;
        char *cookies = NULL;
        pt1 = epd->headers;
        int i = 0;

        while ( t1 = strtok_r ( pt1, "\n", &pt1 ) ) {
            if ( ++i == 1 ) { /// first line
                t2 = strtok_r ( t1, " ", &t1 );
                t3 = strtok_r ( t1, " ", &t1 );
                epd->http_ver = strtok_r ( t1, " ", &t1 );

                if ( !epd->http_ver ) {
                    return 1;

                } else {
                    if ( init_tables == 0 ) {
                        lua_pushlightuserdata ( L, epd );
                        //lua_pushstring(L, epd->headers);
                        lua_newtable ( L );
                    }
                }

                int len = strlen ( epd->http_ver );

                if ( epd->http_ver[len - 1] == 13 ) { // CR == 13
                    epd->http_ver[len - 1] = '\0';
                }

                if ( t2 && t3 ) {
                    for ( t1 = t2 ; *t1 ; *t1 = toupper ( *t1 ), t1++ );

                    epd->method = t2;
                    lua_pushstring ( L, t2 );
                    lua_setfield ( L, -2, "method" );
                    t1 = strtok_r ( t3, "?", &t3 );
                    t2 = strtok_r ( t3, "?", &t3 );
                    epd->uri = t1;
                    lua_pushstring ( L, t1 );
                    lua_setfield ( L, -2, "uri" );

                    if ( t2 ) {
                        epd->query = t2;
                        query = t2;
                        lua_pushstring ( L, t2 );
                        lua_setfield ( L, -2, "query" );
                    }
                }

                continue;
            }

            t2 = strtok_r ( t1, ":", &t1 );

            if ( t2 ) {
                for ( t3 = t2; *t3; ++t3 ) {
                    *t3 = *t3 >= 'A' && *t3 <= 'Z' ? *t3 | 0x60 : *t3;
                }

                t3 = t2 + strlen ( t2 ) + 1; //strtok_r ( t1, ":", &t1 )

                if ( t3 ) {
                    int len = strlen ( t3 );

                    if ( t3[len - 1] == 13 ) { /// 13 == CR
                        t3[len - 1] = '\0';
                    }

                    lua_pushstring ( L, t3 + ( t3[0] == ' ' ? 1 : 0 ) );
                    lua_setfield ( L, -2, t2 );

                    /// check content-type
                    if ( t2[1] == 'o' && strcmp ( t2, "content-type" ) == 0 ) {
                        if ( stristr ( t3, "x-www-form-urlencoded", len ) ) {
                            is_form_post = 1;

                        } else if ( stristr ( t3, "multipart/form-data", len ) ) {
                            boundary_post = stristr ( t3, "boundary=", len - 2 );
                        }

                    } else if ( !cookies && t2[1] == 'o' && strcmp ( t2, "cookie" ) == 0 ) {
                        cookies = t3 + ( t3[0] == ' ' ? 1 : 0 );

                    } else if ( !epd->user_agent && t2[1] == 's' && strcmp ( t2, "user-agent" ) == 0 ) {
                        epd->user_agent = t3 + ( t3[0] == ' ' ? 1 : 0 );

                    } else if ( !epd->referer && t2[1] == 'e' && strcmp ( t2, "referer" ) == 0 ) {
                        epd->referer = t3 + ( t3[0] == ' ' ? 1 : 0 );
                    }
                }
            }
        }

        char *client_ip = inet_ntoa ( epd->client_addr );
        lua_pushstring ( L, client_ip );
        lua_setfield ( L, -2, "remote-addr" );

        lua_newtable ( L ); /// _GET

        if ( query ) { /// parse query string /?a=1&b=2
            while ( t1 = strtok_r ( query, "&", &query ) ) {
                t2 = strtok_r ( t1, "=", &t1 );
                t3 = strtok_r ( t1, "=", &t1 );

                if ( t2 && t3 && strlen ( t2 ) > 0 && strlen ( t3 ) > 0 ) {
                    size_t len, dlen;
                    u_char *p;
                    u_char *src, *dst;
                    len = strlen ( t3 );
                    p = large_malloc ( len );
                    p[0] = '\0';
                    dst = p;
                    ngx_http_lua_unescape_uri ( &dst, &t3, len, 0 );
                    lua_pushlstring ( L, ( char * ) p, dst - p );

                    len = strlen ( t2 );

                    if ( len > 4096 ) {
                        free ( p );
                        p = large_malloc ( len );
                    }

                    p[0] = '\0';
                    dst = p;

                    ngx_http_lua_unescape_uri ( &dst, &t2, len, 0 );
                    p[dst - p] = '\0';
                    lua_setfield ( L, -2, p );
                    free ( p );
                }
            }
        }

        lua_newtable ( L ); /// _COOKIE

        if ( cookies ) {
            while ( t1 = strtok_r ( cookies, ";", &cookies ) ) {
                t2 = strtok_r ( t1, "=", &t1 );
                t3 = strtok_r ( t1, "=", &t1 );

                if ( t2 && t3 && strlen ( t2 ) > 0 && strlen ( t3 ) > 0 ) {
                    size_t len, dlen;
                    u_char *p;
                    u_char *src, *dst;
                    len = strlen ( t3 );
                    p = large_malloc ( len );
                    p[0] = '\0';
                    dst = p;
                    ngx_http_lua_unescape_uri ( &dst, &t3, len, 0 );
                    lua_pushlstring ( L, ( char * ) p, dst - p );

                    len = strlen ( t2 );

                    if ( len > 4096 ) {
                        free ( p );
                        p = large_malloc ( len );
                    }

                    p[0] = '\0';
                    dst = p;

                    ngx_http_lua_unescape_uri ( &dst, &t2, len, 0 );
                    p[dst - p] = '\0';
                    lua_setfield ( L, -2, p + ( p[0] == ' ' ? 1 : 0 ) );
                    free ( p );
                }
            }
        }

        lua_newtable ( L ); /// _POST

        if ( is_form_post == 1
             && epd->contents ) { /// parse post conents text=aa+bb&text2=%E4%B8%AD%E6%96%87+aa
            pt1 = epd->contents;

            while ( t1 = strtok_r ( pt1, "&", &pt1 ) ) {
                t2 = strtok_r ( t1, "=", &t1 );
                t3 = strtok_r ( t1, "=", &t1 );

                if ( t2 && t3 && strlen ( t2 ) > 0 && strlen ( t3 ) > 0 ) {
                    size_t len, dlen;
                    u_char *p;
                    u_char *src, *dst;
                    len = strlen ( t3 );
                    p = large_malloc ( len );
                    p[0] = '\0';
                    dst = p;
                    ngx_http_lua_unescape_uri ( &dst, &t3, len, 0 );
                    lua_pushlstring ( L, ( char * ) p, dst - p );
                    free ( p );
                    //lua_pushstring(L, t3);
                    lua_setfield ( L, -2, t2 );
                }
            }

        } else if ( boundary_post ) { /// parse boundary body
            boundary_post += 9;
            int blen = strlen ( boundary_post );
            int len = 0;
            char *start = epd->contents, *p2 = NULL, *p1 = NULL, *pp = NULL, *value = NULL;
            int i = 0;

            do {
                p2 = strstr ( start, boundary_post );

                if ( p2 ) {
                    start = p2 + blen;
                }

                if ( p1 ) {
                    p1 += blen;

                    if ( p2 ) {
                        * ( p2 - 4 ) = '\0';

                    } else {
                        break;
                    }

                    len = p2 - p1;
                    value = stristr ( p1, "\r\n\r\n", len );

                    if ( value && value[4] != '\0' ) {
                        value[0] = '\0';
                        value += 4;
                        char *keyname = strstr ( p1, "name=\"" );
                        char *filename = NULL;
                        char *content_type = NULL;

                        if ( keyname ) {
                            keyname += 6;

                            for ( pp = keyname; *pp != '\0'; pp++ ) {
                                if ( *pp == '"' ) {
                                    *pp = '\0';
                                    p1 = pp + 2;
                                    break;
                                }
                            }

                            filename = strstr ( p1, "filename=\"" );

                            if ( filename ) { /// is file filed
                                filename += 10;

                                for ( pp = filename; *pp != '\0'; pp++ ) {
                                    if ( *pp == '"' ) {
                                        *pp = '\0';
                                        p1 = pp + 2;
                                        break;
                                    }
                                }

                                content_type = strstr ( p1, "Content-Type:" );

                                if ( content_type ) {
                                    content_type += 13;

                                    if ( content_type[0] == ' ' ) {
                                        content_type += 1;
                                    }
                                }

                                lua_newtable ( L );
                                lua_pushstring ( L, filename );
                                lua_setfield ( L, -2, "filename" );
                                lua_pushstring ( L, content_type );
                                lua_setfield ( L, -2, "type" );
                                lua_pushnumber ( L, p2 - value - 4 );
                                lua_setfield ( L, -2, "size" );
                                lua_pushlstring ( L, value, p2 - value - 4 );
                                lua_setfield ( L, -2, "data" );

                                lua_setfield ( L, -2, keyname );

                            } else {
                                lua_pushstring ( L, value );
                                lua_setfield ( L, -2, keyname );
                            }
                        }
                    }
                }

                p1 = p2 + 2;
            } while ( p2 );
        }

        if ( epd->headers != &epd->iov ) {
            free ( epd->headers );
        }

        epd->headers = NULL;
        epd->header_len = 0;
        epd->contents = NULL;
        epd->content_length = 0;
        epd->iov[0].iov_base = NULL;
        epd->iov[0].iov_len = 0;
        epd->iov[1].iov_base = NULL;
        epd->iov[1].iov_len = 0;

        if ( lua_pcall ( L, 5, 0, 0 ) ) {
            if ( lua_isstring ( L, -1 ) ) {
                printf ( "Lua:error %s\n", lua_tostring ( L, -1 ) );
                const char *data = lua_tostring ( L, -1 );
                network_send_error ( epd, 503, data );
                lua_pop ( L, 1 );
                //network_be_end(epd);
            }
        }

        return 0;
    }

    network_send_error ( epd, 503, "Lua Error: main function not found !!!" );

    return 0;
}
Esempio n. 6
0
int
ngx_http_lua_ffi_req_get_uri_args(ngx_http_request_t *r, u_char *buf,
    ngx_http_lua_ffi_table_elt_t *out, int count)
{
    int                          i, parsing_value = 0;
    u_char                      *last, *p, *q;
    u_char                      *src, *dst;

    if (count <= 0) {
        return NGX_OK;
    }

    ngx_memcpy(buf, r->args.data, r->args.len);

    i = 0;
    last = buf + r->args.len;
    p = buf;
    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("saving key %.*s", (int) (dst - q), q);

            out[i].key.data = q;
            out[i].key.len = (int) (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);

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

                if (out[i].key.len) {
                    out[i].value.data = q;
                    out[i].value.len = (int) (dst - q);
                    i++;
                }

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

                if (dst - q) {
                    out[i].key.data = q;
                    out[i].key.len = (int) (dst - q);
                    out[i].value.len = -1;
                    i++;
                }
            }

            if (i == count) {
                return i;
            }

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

            q = p;

        } 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);

        if (parsing_value) {
            if (out[i].key.len) {
                out[i].value.data = q;
                out[i].value.len = (int) (dst - q);
                i++;
            }

        } else {
            if (dst - q) {
                out[i].key.data = q;
                out[i].key.len = (int) (dst - q);
                out[i].value.len = (int) -1;
                i++;
            }
        }
    }

    return i;
}