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