LCOV - code coverage report
Current view: top level - home/build/openresty-1.13.6.1/build/ngx_lua-0.10.11/src - ngx_http_lua_args.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 10 218 4.6 %
Date: 2020-03-03 04:25:50 Functions: 1 8 12.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : 
       2             : /*
       3             :  * Copyright (C) Xiaozhe Wang (chaoslawful)
       4             :  * Copyright (C) Yichun Zhang (agentzh)
       5             :  */
       6             : 
       7             : 
       8             : #ifndef DDEBUG
       9             : #define DDEBUG 0
      10             : #endif
      11             : #include "ddebug.h"
      12             : 
      13             : 
      14             : #include "ngx_http_lua_args.h"
      15             : #include "ngx_http_lua_util.h"
      16             : 
      17             : 
      18             : static int ngx_http_lua_ngx_req_set_uri_args(lua_State *L);
      19             : static int ngx_http_lua_ngx_req_get_uri_args(lua_State *L);
      20             : static int ngx_http_lua_ngx_req_get_post_args(lua_State *L);
      21             : 
      22             : 
      23             : static int
      24           0 : ngx_http_lua_ngx_req_set_uri_args(lua_State *L)
      25             : {
      26             :     ngx_http_request_t          *r;
      27             :     ngx_str_t                    args;
      28             :     const char                  *msg;
      29             :     size_t                       len;
      30             :     u_char                      *p;
      31             : 
      32           0 :     if (lua_gettop(L) != 1) {
      33           0 :         return luaL_error(L, "expecting 1 argument but seen %d",
      34             :                           lua_gettop(L));
      35             :     }
      36             : 
      37           0 :     r = ngx_http_lua_get_req(L);
      38           0 :     if (r == NULL) {
      39           0 :         return luaL_error(L, "no request object found");
      40             :     }
      41             : 
      42           0 :     ngx_http_lua_check_fake_request(L, r);
      43             : 
      44           0 :     switch (lua_type(L, 1)) {
      45           0 :     case LUA_TNUMBER:
      46             :     case LUA_TSTRING:
      47           0 :         p = (u_char *) lua_tolstring(L, 1, &len);
      48             : 
      49           0 :         args.data = ngx_palloc(r->pool, len);
      50           0 :         if (args.data == NULL) {
      51           0 :             return luaL_error(L, "no memory");
      52             :         }
      53             : 
      54           0 :         ngx_memcpy(args.data, p, len);
      55             : 
      56           0 :         args.len = len;
      57           0 :         break;
      58             : 
      59           0 :     case LUA_TTABLE:
      60           0 :         ngx_http_lua_process_args_option(r, L, 1, &args);
      61             : 
      62             :         dd("args: %.*s", (int) args.len, args.data);
      63             : 
      64           0 :         break;
      65             : 
      66           0 :     default:
      67           0 :         msg = lua_pushfstring(L, "string, number, or table expected, "
      68             :                               "but got %s", luaL_typename(L, 2));
      69           0 :         return luaL_argerror(L, 1, msg);
      70             :     }
      71             : 
      72             :     dd("args: %.*s", (int) args.len, args.data);
      73             : 
      74           0 :     r->args.data = args.data;
      75           0 :     r->args.len = args.len;
      76             : 
      77           0 :     r->valid_unparsed_uri = 0;
      78             : 
      79           0 :     return 0;
      80             : }
      81             : 
      82             : 
      83             : static int
      84           0 : ngx_http_lua_ngx_req_get_uri_args(lua_State *L)
      85             : {
      86             :     ngx_http_request_t          *r;
      87             :     u_char                      *buf;
      88             :     u_char                      *last;
      89             :     int                          retval;
      90             :     int                          n;
      91             :     int                          max;
      92             : 
      93           0 :     n = lua_gettop(L);
      94             : 
      95           0 :     if (n != 0 && n != 1) {
      96           0 :         return luaL_error(L, "expecting 0 or 1 arguments but seen %d", n);
      97             :     }
      98             : 
      99           0 :     if (n == 1) {
     100           0 :         max = luaL_checkinteger(L, 1);
     101           0 :         lua_pop(L, 1);
     102             : 
     103             :     } else {
     104           0 :         max = NGX_HTTP_LUA_MAX_ARGS;
     105             :     }
     106             : 
     107           0 :     r = ngx_http_lua_get_req(L);
     108           0 :     if (r == NULL) {
     109           0 :         return luaL_error(L, "no request object found");
     110             :     }
     111             : 
     112           0 :     ngx_http_lua_check_fake_request(L, r);
     113             : 
     114           0 :     if (r->args.len == 0) {
     115           0 :         lua_createtable(L, 0, 0);
     116           0 :         return 1;
     117             :     }
     118             : 
     119             :     /* we copy r->args over to buf to simplify
     120             :      * unescaping query arg keys and values */
     121             : 
     122           0 :     buf = ngx_palloc(r->pool, r->args.len);
     123           0 :     if (buf == NULL) {
     124           0 :         return luaL_error(L, "no memory");
     125             :     }
     126             : 
     127           0 :     lua_createtable(L, 0, 4);
     128             : 
     129           0 :     ngx_memcpy(buf, r->args.data, r->args.len);
     130             : 
     131           0 :     last = buf + r->args.len;
     132             : 
     133           0 :     retval = ngx_http_lua_parse_args(L, buf, last, max);
     134             : 
     135           0 :     ngx_pfree(r->pool, buf);
     136             : 
     137           0 :     return retval;
     138             : }
     139             : 
     140             : 
     141             : static int
     142           0 : ngx_http_lua_ngx_req_get_post_args(lua_State *L)
     143             : {
     144             :     ngx_http_request_t          *r;
     145             :     u_char                      *buf;
     146             :     int                          retval;
     147             :     size_t                       len;
     148             :     ngx_chain_t                 *cl;
     149             :     u_char                      *p;
     150             :     u_char                      *last;
     151             :     int                          n;
     152             :     int                          max;
     153             : 
     154           0 :     n = lua_gettop(L);
     155             : 
     156           0 :     if (n != 0 && n != 1) {
     157           0 :         return luaL_error(L, "expecting 0 or 1 arguments but seen %d", n);
     158             :     }
     159             : 
     160           0 :     if (n == 1) {
     161           0 :         max = luaL_checkinteger(L, 1);
     162           0 :         lua_pop(L, 1);
     163             : 
     164             :     } else {
     165           0 :         max = NGX_HTTP_LUA_MAX_ARGS;
     166             :     }
     167             : 
     168           0 :     r = ngx_http_lua_get_req(L);
     169           0 :     if (r == NULL) {
     170           0 :         return luaL_error(L, "no request object found");
     171             :     }
     172             : 
     173           0 :     ngx_http_lua_check_fake_request(L, r);
     174             : 
     175           0 :     if (r->discard_body) {
     176           0 :         lua_createtable(L, 0, 0);
     177           0 :         return 1;
     178             :     }
     179             : 
     180           0 :     if (r->request_body == NULL) {
     181           0 :         return luaL_error(L, "no request body found; "
     182             :                           "maybe you should turn on lua_need_request_body?");
     183             :     }
     184             : 
     185           0 :     if (r->request_body->temp_file) {
     186           0 :         lua_pushnil(L);
     187           0 :         lua_pushliteral(L, "request body in temp file not supported");
     188           0 :         return 2;
     189             :     }
     190             : 
     191           0 :     if (r->request_body->bufs == NULL) {
     192           0 :         lua_createtable(L, 0, 0);
     193           0 :         return 1;
     194             :     }
     195             : 
     196             :     /* we copy r->request_body->bufs over to buf to simplify
     197             :      * unescaping query arg keys and values */
     198             : 
     199           0 :     len = 0;
     200           0 :     for (cl = r->request_body->bufs; cl; cl = cl->next) {
     201           0 :         len += cl->buf->last - cl->buf->pos;
     202             :     }
     203             : 
     204             :     dd("post body length: %d", (int) len);
     205             : 
     206           0 :     if (len == 0) {
     207           0 :         lua_createtable(L, 0, 0);
     208           0 :         return 1;
     209             :     }
     210             : 
     211           0 :     buf = ngx_palloc(r->pool, len);
     212           0 :     if (buf == NULL) {
     213           0 :         return luaL_error(L, "no memory");
     214             :     }
     215             : 
     216           0 :     lua_createtable(L, 0, 4);
     217             : 
     218           0 :     p = buf;
     219           0 :     for (cl = r->request_body->bufs; cl; cl = cl->next) {
     220           0 :         p = ngx_copy(p, cl->buf->pos, cl->buf->last - cl->buf->pos);
     221             :     }
     222             : 
     223             :     dd("post body: %.*s", (int) len, buf);
     224             : 
     225           0 :     last = buf + len;
     226             : 
     227           0 :     retval = ngx_http_lua_parse_args(L, buf, last, max);
     228             : 
     229           0 :     ngx_pfree(r->pool, buf);
     230             : 
     231           0 :     return retval;
     232             : }
     233             : 
     234             : 
     235             : int
     236           0 : ngx_http_lua_parse_args(lua_State *L, u_char *buf, u_char *last, int max)
     237             : {
     238             :     u_char                      *p, *q;
     239             :     u_char                      *src, *dst;
     240             :     unsigned                     parsing_value;
     241             :     size_t                       len;
     242           0 :     int                          count = 0;
     243             :     int                          top;
     244             : 
     245           0 :     top = lua_gettop(L);
     246             : 
     247           0 :     p = buf;
     248             : 
     249           0 :     parsing_value = 0;
     250           0 :     q = p;
     251             : 
     252           0 :     while (p != last) {
     253           0 :         if (*p == '=' && ! parsing_value) {
     254             :             /* key data is between p and q */
     255             : 
     256           0 :             src = q; dst = q;
     257             : 
     258           0 :             ngx_http_lua_unescape_uri(&dst, &src, p - q,
     259             :                                       NGX_UNESCAPE_URI_COMPONENT);
     260             : 
     261             :             dd("pushing key %.*s", (int) (dst - q), q);
     262             : 
     263             :             /* push the key */
     264           0 :             lua_pushlstring(L, (char *) q, dst - q);
     265             : 
     266             :             /* skip the current '=' char */
     267           0 :             p++;
     268             : 
     269           0 :             q = p;
     270           0 :             parsing_value = 1;
     271             : 
     272           0 :         } else if (*p == '&') {
     273             :             /* reached the end of a key or a value, just save it */
     274           0 :             src = q; dst = q;
     275             : 
     276           0 :             ngx_http_lua_unescape_uri(&dst, &src, p - q,
     277             :                                       NGX_UNESCAPE_URI_COMPONENT);
     278             : 
     279             :             dd("pushing key or value %.*s", (int) (dst - q), q);
     280             : 
     281             :             /* push the value or key */
     282           0 :             lua_pushlstring(L, (char *) q, dst - q);
     283             : 
     284             :             /* skip the current '&' char */
     285           0 :             p++;
     286             : 
     287           0 :             q = p;
     288             : 
     289           0 :             if (parsing_value) {
     290             :                 /* end of the current pair's value */
     291           0 :                 parsing_value = 0;
     292             : 
     293             :             } else {
     294             :                 /* the current parsing pair takes no value,
     295             :                  * just push the value "true" */
     296             :                 dd("pushing boolean true");
     297             : 
     298           0 :                 lua_pushboolean(L, 1);
     299             :             }
     300             : 
     301           0 :             (void) lua_tolstring(L, -2, &len);
     302             : 
     303           0 :             if (len == 0) {
     304             :                 /* ignore empty string key pairs */
     305             :                 dd("popping key and value...");
     306           0 :                 lua_pop(L, 2);
     307             : 
     308             :             } else {
     309             :                 dd("setting table...");
     310           0 :                 ngx_http_lua_set_multi_value_table(L, top);
     311             :             }
     312             : 
     313           0 :             if (max > 0 && ++count == max) {
     314           0 :                 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
     315             :                                "lua hit query args limit %d", max);
     316             : 
     317           0 :                 return 1;
     318             :             }
     319             : 
     320             :         } else {
     321           0 :             p++;
     322             :         }
     323             :     }
     324             : 
     325           0 :     if (p != q || parsing_value) {
     326           0 :         src = q; dst = q;
     327             : 
     328           0 :         ngx_http_lua_unescape_uri(&dst, &src, p - q,
     329             :                                   NGX_UNESCAPE_URI_COMPONENT);
     330             : 
     331             :         dd("pushing key or value %.*s", (int) (dst - q), q);
     332             : 
     333           0 :         lua_pushlstring(L, (char *) q, dst - q);
     334             : 
     335           0 :         if (!parsing_value) {
     336             :             dd("pushing boolean true...");
     337           0 :             lua_pushboolean(L, 1);
     338             :         }
     339             : 
     340           0 :         (void) lua_tolstring(L, -2, &len);
     341             : 
     342           0 :         if (len == 0) {
     343             :             /* ignore empty string key pairs */
     344             :             dd("popping key and value...");
     345           0 :             lua_pop(L, 2);
     346             : 
     347             :         } else {
     348             :             dd("setting table...");
     349           0 :             ngx_http_lua_set_multi_value_table(L, top);
     350             :         }
     351             :     }
     352             : 
     353             :     dd("gettop: %d", lua_gettop(L));
     354             :     dd("type: %s", lua_typename(L, lua_type(L, 1)));
     355             : 
     356           0 :     if (lua_gettop(L) != top) {
     357           0 :         return luaL_error(L, "internal error: stack in bad state");
     358             :     }
     359             : 
     360           0 :     return 1;
     361             : }
     362             : 
     363             : 
     364             : void
     365          18 : ngx_http_lua_inject_req_args_api(lua_State *L)
     366             : {
     367          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_req_set_uri_args);
     368          18 :     lua_setfield(L, -2, "set_uri_args");
     369             : 
     370          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_req_get_uri_args);
     371          18 :     lua_setfield(L, -2, "get_uri_args");
     372             : 
     373          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_req_get_uri_args);
     374          18 :     lua_setfield(L, -2, "get_query_args"); /* deprecated */
     375             : 
     376          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_req_get_post_args);
     377          18 :     lua_setfield(L, -2, "get_post_args");
     378          18 : }
     379             : 
     380             : 
     381             : #ifndef NGX_LUA_NO_FFI_API
     382             : size_t
     383           0 : ngx_http_lua_ffi_req_get_querystring_len(ngx_http_request_t *r)
     384             : {
     385           0 :     return r->args.len;
     386             : }
     387             : 
     388             : 
     389             : int
     390           0 : ngx_http_lua_ffi_req_get_uri_args_count(ngx_http_request_t *r, int max)
     391             : {
     392             :     int                      count;
     393             :     u_char                  *p, *last;
     394             : 
     395           0 :     if (r->connection->fd == (ngx_socket_t) -1) {
     396           0 :         return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
     397             :     }
     398             : 
     399           0 :     if (max < 0) {
     400           0 :         max = NGX_HTTP_LUA_MAX_ARGS;
     401             :     }
     402             : 
     403           0 :     last = r->args.data + r->args.len;
     404           0 :     count = 0;
     405             : 
     406           0 :     for (p = r->args.data; p != last; p++) {
     407           0 :         if (*p == '&') {
     408           0 :             if (count == 0) {
     409           0 :                 count += 2;
     410             : 
     411             :             } else {
     412           0 :                 count++;
     413             :             }
     414             :         }
     415             :     }
     416             : 
     417           0 :     if (count) {
     418           0 :         if (max > 0 && count > max) {
     419           0 :             count = max;
     420           0 :             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
     421             :                            "lua hit query args limit %d", max);
     422             :         }
     423             : 
     424           0 :         return count;
     425             :     }
     426             : 
     427           0 :     if (r->args.len) {
     428           0 :         return 1;
     429             :     }
     430             : 
     431           0 :     return 0;
     432             : }
     433             : 
     434             : 
     435             : int
     436           0 : ngx_http_lua_ffi_req_get_uri_args(ngx_http_request_t *r, u_char *buf,
     437             :     ngx_http_lua_ffi_table_elt_t *out, int count)
     438             : {
     439           0 :     int                          i, parsing_value = 0;
     440             :     u_char                      *last, *p, *q;
     441             :     u_char                      *src, *dst;
     442             : 
     443           0 :     if (count <= 0) {
     444           0 :         return NGX_OK;
     445             :     }
     446             : 
     447           0 :     ngx_memcpy(buf, r->args.data, r->args.len);
     448             : 
     449           0 :     i = 0;
     450           0 :     last = buf + r->args.len;
     451           0 :     p = buf;
     452           0 :     q = p;
     453             : 
     454           0 :     while (p != last) {
     455           0 :         if (*p == '=' && !parsing_value) {
     456             :             /* key data is between p and q */
     457             : 
     458           0 :             src = q; dst = q;
     459             : 
     460           0 :             ngx_http_lua_unescape_uri(&dst, &src, p - q,
     461             :                                       NGX_UNESCAPE_URI_COMPONENT);
     462             : 
     463             :             dd("saving key %.*s", (int) (dst - q), q);
     464             : 
     465           0 :             out[i].key.data = q;
     466           0 :             out[i].key.len = (int) (dst - q);
     467             : 
     468             :             /* skip the current '=' char */
     469           0 :             p++;
     470             : 
     471           0 :             q = p;
     472           0 :             parsing_value = 1;
     473             : 
     474           0 :         } else if (*p == '&') {
     475             :             /* reached the end of a key or a value, just save it */
     476           0 :             src = q; dst = q;
     477             : 
     478           0 :             ngx_http_lua_unescape_uri(&dst, &src, p - q,
     479             :                                       NGX_UNESCAPE_URI_COMPONENT);
     480             : 
     481             :             dd("pushing key or value %.*s", (int) (dst - q), q);
     482             : 
     483           0 :             if (parsing_value) {
     484             :                 /* end of the current pair's value */
     485           0 :                 parsing_value = 0;
     486             : 
     487           0 :                 if (out[i].key.len) {
     488           0 :                     out[i].value.data = q;
     489           0 :                     out[i].value.len = (int) (dst - q);
     490           0 :                     i++;
     491             :                 }
     492             : 
     493             :             } else {
     494             :                 /* the current parsing pair takes no value,
     495             :                  * just push the value "true" */
     496             :                 dd("pushing boolean true");
     497             : 
     498           0 :                 if (dst - q) {
     499           0 :                     out[i].key.data = q;
     500           0 :                     out[i].key.len = (int) (dst - q);
     501           0 :                     out[i].value.len = -1;
     502           0 :                     i++;
     503             :                 }
     504             :             }
     505             : 
     506           0 :             if (i == count) {
     507           0 :                 return i;
     508             :             }
     509             : 
     510             :             /* skip the current '&' char */
     511           0 :             p++;
     512             : 
     513           0 :             q = p;
     514             : 
     515             :         } else {
     516           0 :             p++;
     517             :         }
     518             :     }
     519             : 
     520           0 :     if (p != q || parsing_value) {
     521           0 :         src = q; dst = q;
     522             : 
     523           0 :         ngx_http_lua_unescape_uri(&dst, &src, p - q,
     524             :                                   NGX_UNESCAPE_URI_COMPONENT);
     525             : 
     526             :         dd("pushing key or value %.*s", (int) (dst - q), q);
     527             : 
     528           0 :         if (parsing_value) {
     529           0 :             if (out[i].key.len) {
     530           0 :                 out[i].value.data = q;
     531           0 :                 out[i].value.len = (int) (dst - q);
     532           0 :                 i++;
     533             :             }
     534             : 
     535             :         } else {
     536           0 :             if (dst - q) {
     537           0 :                 out[i].key.data = q;
     538           0 :                 out[i].key.len = (int) (dst - q);
     539           0 :                 out[i].value.len = (int) -1;
     540           0 :                 i++;
     541             :             }
     542             :         }
     543             :     }
     544             : 
     545           0 :     return i;
     546             : }
     547             : #endif /* NGX_LUA_NO_FFI_API */
     548             : 
     549             : 
     550             : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */

Generated by: LCOV version 1.13