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_variable.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 10 204 4.9 %
Date: 2020-03-03 04:25:50 Functions: 1 5 20.0 %
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_variable.h"
      15             : #include "ngx_http_lua_util.h"
      16             : 
      17             : 
      18             : static int ngx_http_lua_var_get(lua_State *L);
      19             : static int ngx_http_lua_var_set(lua_State *L);
      20             : 
      21             : 
      22             : void
      23          18 : ngx_http_lua_inject_variable_api(lua_State *L)
      24             : {
      25             :     /* {{{ register reference maps */
      26          18 :     lua_newtable(L);    /* ngx.var */
      27             : 
      28          18 :     lua_createtable(L, 0, 2 /* nrec */); /* metatable for .var */
      29          18 :     lua_pushcfunction(L, ngx_http_lua_var_get);
      30          18 :     lua_setfield(L, -2, "__index");
      31          18 :     lua_pushcfunction(L, ngx_http_lua_var_set);
      32          18 :     lua_setfield(L, -2, "__newindex");
      33          18 :     lua_setmetatable(L, -2);
      34             : 
      35          18 :     lua_setfield(L, -2, "var");
      36          18 : }
      37             : 
      38             : 
      39             : /**
      40             :  * Get nginx internal variables content
      41             :  *
      42             :  * @retval Always return a string or nil on Lua stack. Return nil when failed
      43             :  * to get content, and actual content string when found the specified variable.
      44             :  * @seealso ngx_http_lua_var_set
      45             :  * */
      46             : static int
      47           0 : ngx_http_lua_var_get(lua_State *L)
      48             : {
      49             :     ngx_http_request_t          *r;
      50             :     u_char                      *p, *lowcase;
      51             :     size_t                       len;
      52             :     ngx_uint_t                   hash;
      53             :     ngx_str_t                    name;
      54             :     ngx_http_variable_value_t   *vv;
      55             : 
      56             : #if (NGX_PCRE)
      57             :     u_char                      *val;
      58             :     ngx_uint_t                   n;
      59             :     LUA_NUMBER                   index;
      60             :     int                         *cap;
      61             : #endif
      62             : 
      63           0 :     r = ngx_http_lua_get_req(L);
      64           0 :     if (r == NULL) {
      65           0 :         return luaL_error(L, "no request object found");
      66             :     }
      67             : 
      68           0 :     ngx_http_lua_check_fake_request(L, r);
      69             : 
      70             : #if (NGX_PCRE)
      71           0 :     if (lua_type(L, -1) == LUA_TNUMBER) {
      72             :         /* it is a regex capturing variable */
      73             : 
      74           0 :         index = lua_tonumber(L, -1);
      75             : 
      76           0 :         if (index <= 0) {
      77           0 :             lua_pushnil(L);
      78           0 :             return 1;
      79             :         }
      80             : 
      81           0 :         n = (ngx_uint_t) index * 2;
      82             : 
      83             :         dd("n = %d, ncaptures = %d", (int) n, (int) r->ncaptures);
      84             : 
      85           0 :         if (r->captures == NULL
      86           0 :             || r->captures_data == NULL
      87           0 :             || n >= r->ncaptures)
      88             :         {
      89           0 :             lua_pushnil(L);
      90           0 :             return 1;
      91             :         }
      92             : 
      93             :         /* n >= 0 && n < r->ncaptures */
      94             : 
      95           0 :         cap = r->captures;
      96             : 
      97           0 :         p = r->captures_data;
      98             : 
      99           0 :         val = &p[cap[n]];
     100             : 
     101           0 :         lua_pushlstring(L, (const char *) val, (size_t) (cap[n + 1] - cap[n]));
     102             : 
     103           0 :         return 1;
     104             :     }
     105             : #endif
     106             : 
     107           0 :     if (lua_type(L, -1) != LUA_TSTRING) {
     108           0 :         return luaL_error(L, "bad variable name");
     109             :     }
     110             : 
     111           0 :     p = (u_char *) lua_tolstring(L, -1, &len);
     112             : 
     113           0 :     lowcase = lua_newuserdata(L, len);
     114             : 
     115           0 :     hash = ngx_hash_strlow(lowcase, p, len);
     116             : 
     117           0 :     name.len = len;
     118           0 :     name.data = lowcase;
     119             : 
     120           0 :     vv = ngx_http_get_variable(r, &name, hash);
     121             : 
     122           0 :     if (vv == NULL || vv->not_found) {
     123           0 :         lua_pushnil(L);
     124           0 :         return 1;
     125             :     }
     126             : 
     127           0 :     lua_pushlstring(L, (const char *) vv->data, (size_t) vv->len);
     128           0 :     return 1;
     129             : }
     130             : 
     131             : 
     132             : /**
     133             :  * Set nginx internal variable content
     134             :  *
     135             :  * @retval Always return a boolean on Lua stack. Return true when variable
     136             :  * content was modified successfully, false otherwise.
     137             :  * @seealso ngx_http_lua_var_get
     138             :  * */
     139             : static int
     140           0 : ngx_http_lua_var_set(lua_State *L)
     141             : {
     142             :     ngx_http_variable_t         *v;
     143             :     ngx_http_variable_value_t   *vv;
     144             :     ngx_http_core_main_conf_t   *cmcf;
     145             :     u_char                      *p, *lowcase, *val;
     146             :     size_t                       len;
     147             :     ngx_str_t                    name;
     148             :     ngx_uint_t                   hash;
     149             :     ngx_http_request_t          *r;
     150             :     int                          value_type;
     151             :     const char                  *msg;
     152             : 
     153           0 :     r = ngx_http_lua_get_req(L);
     154           0 :     if (r == NULL) {
     155           0 :         return luaL_error(L, "no request object found");
     156             :     }
     157             : 
     158           0 :     ngx_http_lua_check_fake_request(L, r);
     159             : 
     160             :     /* we skip the first argument that is the table */
     161             : 
     162             :     /* we read the variable name */
     163             : 
     164           0 :     if (lua_type(L, 2) != LUA_TSTRING) {
     165           0 :         return luaL_error(L, "bad variable name");
     166             :     }
     167             : 
     168           0 :     p = (u_char *) lua_tolstring(L, 2, &len);
     169             : 
     170           0 :     lowcase = lua_newuserdata(L, len + 1);
     171             : 
     172           0 :     hash = ngx_hash_strlow(lowcase, p, len);
     173           0 :     lowcase[len] = '\0';
     174             : 
     175           0 :     name.len = len;
     176           0 :     name.data = lowcase;
     177             : 
     178             :     /* we read the variable new value */
     179             : 
     180           0 :     value_type = lua_type(L, 3);
     181           0 :     switch (value_type) {
     182           0 :     case LUA_TNUMBER:
     183             :     case LUA_TSTRING:
     184           0 :         p = (u_char *) luaL_checklstring(L, 3, &len);
     185             : 
     186           0 :         val = ngx_palloc(r->pool, len);
     187           0 :         if (val == NULL) {
     188           0 :             return luaL_error(L, "memory allocation error");
     189             :         }
     190             : 
     191           0 :         ngx_memcpy(val, p, len);
     192             : 
     193           0 :         break;
     194             : 
     195           0 :     case LUA_TNIL:
     196             :         /* undef the variable */
     197             : 
     198           0 :         val = NULL;
     199           0 :         len = 0;
     200             : 
     201           0 :         break;
     202             : 
     203           0 :     default:
     204           0 :         msg = lua_pushfstring(L, "string, number, or nil expected, "
     205             :                               "but got %s", lua_typename(L, value_type));
     206           0 :         return luaL_argerror(L, 1, msg);
     207             :     }
     208             : 
     209             :     /* we fetch the variable itself */
     210             : 
     211           0 :     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
     212             : 
     213           0 :     v = ngx_hash_find(&cmcf->variables_hash, hash, name.data, name.len);
     214             : 
     215           0 :     if (v) {
     216           0 :         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
     217           0 :             return luaL_error(L, "variable \"%s\" not changeable", lowcase);
     218             :         }
     219             : 
     220           0 :         if (v->set_handler) {
     221             : 
     222             :             dd("set variables with set_handler");
     223             : 
     224           0 :             vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
     225           0 :             if (vv == NULL) {
     226           0 :                 return luaL_error(L, "no memory");
     227             :             }
     228             : 
     229           0 :             if (value_type == LUA_TNIL) {
     230           0 :                 vv->valid = 0;
     231           0 :                 vv->not_found = 1;
     232           0 :                 vv->no_cacheable = 0;
     233           0 :                 vv->data = NULL;
     234           0 :                 vv->len = 0;
     235             : 
     236             :             } else {
     237           0 :                 vv->valid = 1;
     238           0 :                 vv->not_found = 0;
     239           0 :                 vv->no_cacheable = 0;
     240             : 
     241           0 :                 vv->data = val;
     242           0 :                 vv->len = len;
     243             :             }
     244             : 
     245           0 :             v->set_handler(r, vv, v->data);
     246             : 
     247           0 :             return 0;
     248             :         }
     249             : 
     250           0 :         if (v->flags & NGX_HTTP_VAR_INDEXED) {
     251           0 :             vv = &r->variables[v->index];
     252             : 
     253             :             dd("set indexed variable");
     254             : 
     255           0 :             if (value_type == LUA_TNIL) {
     256           0 :                 vv->valid = 0;
     257           0 :                 vv->not_found = 1;
     258           0 :                 vv->no_cacheable = 0;
     259             : 
     260           0 :                 vv->data = NULL;
     261           0 :                 vv->len = 0;
     262             : 
     263             :             } else {
     264           0 :                 vv->valid = 1;
     265           0 :                 vv->not_found = 0;
     266           0 :                 vv->no_cacheable = 0;
     267             : 
     268           0 :                 vv->data = val;
     269           0 :                 vv->len = len;
     270             :             }
     271             : 
     272           0 :             return 0;
     273             :         }
     274             : 
     275           0 :         return luaL_error(L, "variable \"%s\" cannot be assigned a value",
     276             :                           lowcase);
     277             :     }
     278             : 
     279             :     /* variable not found */
     280             : 
     281           0 :     return luaL_error(L, "variable \"%s\" not found for writing; "
     282             :                       "maybe it is a built-in variable that is not changeable "
     283             :                       "or you forgot to use \"set $%s '';\" "
     284             :                       "in the config file to define it first",
     285             :                       lowcase, lowcase);
     286             : }
     287             : 
     288             : 
     289             : #ifndef NGX_LUA_NO_FFI_API
     290             : int
     291           0 : ngx_http_lua_ffi_var_get(ngx_http_request_t *r, u_char *name_data,
     292             :     size_t name_len, u_char *lowcase_buf, int capture_id, u_char **value,
     293             :     size_t *value_len, char **err)
     294             : {
     295             :     ngx_uint_t                   hash;
     296             :     ngx_str_t                    name;
     297             :     ngx_http_variable_value_t   *vv;
     298             : 
     299             : #if (NGX_PCRE)
     300             :     u_char                      *p;
     301             :     ngx_uint_t                   n;
     302             :     int                         *cap;
     303             : #endif
     304             : 
     305           0 :     if (r == NULL) {
     306           0 :         *err = "no request object found";
     307           0 :         return NGX_ERROR;
     308             :     }
     309             : 
     310           0 :     if ((r)->connection->fd == (ngx_socket_t) -1) {
     311           0 :         *err = "API disabled in the current context";
     312           0 :         return NGX_ERROR;
     313             :     }
     314             : 
     315             : #if (NGX_PCRE)
     316           0 :     if (name_data == 0) {
     317           0 :         if (capture_id <= 0) {
     318           0 :             return NGX_DECLINED;
     319             :         }
     320             : 
     321             :         /* it is a regex capturing variable */
     322             : 
     323           0 :         n = (ngx_uint_t) capture_id * 2;
     324             : 
     325             :         dd("n = %d, ncaptures = %d", (int) n, (int) r->ncaptures);
     326             : 
     327           0 :         if (r->captures == NULL
     328           0 :             || r->captures_data == NULL
     329           0 :             || n >= r->ncaptures)
     330             :         {
     331           0 :             return NGX_DECLINED;
     332             :         }
     333             : 
     334             :         /* n >= 0 && n < r->ncaptures */
     335             : 
     336           0 :         cap = r->captures;
     337           0 :         p = r->captures_data;
     338             : 
     339           0 :         *value = &p[cap[n]];
     340           0 :         *value_len = (size_t) (cap[n + 1] - cap[n]);
     341             : 
     342           0 :         return NGX_OK;
     343             :     }
     344             : #endif
     345             : 
     346           0 :     hash = ngx_hash_strlow(lowcase_buf, name_data, name_len);
     347             : 
     348           0 :     name.data = lowcase_buf;
     349           0 :     name.len = name_len;
     350             : 
     351             :     dd("variable name: %.*s", (int) name_len, lowcase_buf);
     352             : 
     353           0 :     vv = ngx_http_get_variable(r, &name, hash);
     354           0 :     if (vv == NULL || vv->not_found) {
     355           0 :         return NGX_DECLINED;
     356             :     }
     357             : 
     358           0 :     *value = vv->data;
     359           0 :     *value_len = vv->len;
     360           0 :     return NGX_OK;
     361             : }
     362             : 
     363             : 
     364             : int
     365           0 : ngx_http_lua_ffi_var_set(ngx_http_request_t *r, u_char *name_data,
     366             :     size_t name_len, u_char *lowcase_buf, u_char *value, size_t value_len,
     367             :     u_char *errbuf, size_t errlen)
     368             : {
     369             :     u_char                      *p;
     370             :     ngx_uint_t                   hash;
     371             :     ngx_http_variable_t         *v;
     372             :     ngx_http_variable_value_t   *vv;
     373             :     ngx_http_core_main_conf_t   *cmcf;
     374             : 
     375           0 :     if (r == NULL) {
     376           0 :         ngx_snprintf(errbuf, errlen, "no request object found");
     377           0 :         return NGX_ERROR;
     378             :     }
     379             : 
     380           0 :     if ((r)->connection->fd == (ngx_socket_t) -1) {
     381           0 :         ngx_snprintf(errbuf, errlen, "API disabled in the current context");
     382           0 :         return NGX_ERROR;
     383             :     }
     384             : 
     385           0 :     hash = ngx_hash_strlow(lowcase_buf, name_data, name_len);
     386             : 
     387             :     dd("variable name: %.*s", (int) name_len, lowcase_buf);
     388             : 
     389             :     /* we fetch the variable itself */
     390             : 
     391           0 :     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
     392             : 
     393           0 :     v = ngx_hash_find(&cmcf->variables_hash, hash, lowcase_buf, name_len);
     394             : 
     395           0 :     if (v) {
     396           0 :         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
     397             :             dd("variable not changeable");
     398           0 :             ngx_snprintf(errbuf, errlen, "variable \"%*s\" not changeable",
     399             :                          name_len, lowcase_buf);
     400           0 :             return NGX_ERROR;
     401             :         }
     402             : 
     403           0 :         if (v->set_handler) {
     404             : 
     405             :             dd("set variables with set_handler");
     406             : 
     407           0 :             if (value != NULL && value_len) {
     408           0 :                 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)
     409             :                                 + value_len);
     410           0 :                 if (vv == NULL) {
     411           0 :                     goto nomem;
     412             :                 }
     413             : 
     414           0 :                 p = (u_char *) vv + sizeof(ngx_http_variable_value_t);
     415           0 :                 ngx_memcpy(p, value, value_len);
     416           0 :                 value = p;
     417             : 
     418             :             } else {
     419           0 :                 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
     420           0 :                 if (vv == NULL) {
     421           0 :                     goto nomem;
     422             :                 }
     423             :             }
     424             : 
     425           0 :             if (value == NULL) {
     426           0 :                 vv->valid = 0;
     427           0 :                 vv->not_found = 1;
     428           0 :                 vv->no_cacheable = 0;
     429           0 :                 vv->data = NULL;
     430           0 :                 vv->len = 0;
     431             : 
     432             :             } else {
     433           0 :                 vv->valid = 1;
     434           0 :                 vv->not_found = 0;
     435           0 :                 vv->no_cacheable = 0;
     436             : 
     437           0 :                 vv->data = value;
     438           0 :                 vv->len = value_len;
     439             :             }
     440             : 
     441           0 :             v->set_handler(r, vv, v->data);
     442           0 :             return NGX_OK;
     443             :         }
     444             : 
     445           0 :         if (v->flags & NGX_HTTP_VAR_INDEXED) {
     446           0 :             vv = &r->variables[v->index];
     447             : 
     448             :             dd("set indexed variable");
     449             : 
     450           0 :             if (value == NULL) {
     451           0 :                 vv->valid = 0;
     452           0 :                 vv->not_found = 1;
     453           0 :                 vv->no_cacheable = 0;
     454             : 
     455           0 :                 vv->data = NULL;
     456           0 :                 vv->len = 0;
     457             : 
     458             :             } else {
     459           0 :                 p = ngx_palloc(r->pool, value_len);
     460           0 :                 if (p == NULL) {
     461           0 :                     goto nomem;
     462             :                 }
     463             : 
     464           0 :                 ngx_memcpy(p, value, value_len);
     465           0 :                 value = p;
     466             : 
     467           0 :                 vv->valid = 1;
     468           0 :                 vv->not_found = 0;
     469           0 :                 vv->no_cacheable = 0;
     470             : 
     471           0 :                 vv->data = value;
     472           0 :                 vv->len = value_len;
     473             :             }
     474             : 
     475           0 :             return NGX_OK;
     476             :         }
     477             : 
     478           0 :         ngx_snprintf(errbuf, errlen, "variable \"%*s\" cannot be assigned "
     479             :                      "a value", name_len, lowcase_buf);
     480           0 :         return NGX_ERROR;
     481             :     }
     482             : 
     483             :     /* variable not found */
     484             : 
     485           0 :     ngx_snprintf(errbuf, errlen, "variable \"%*s\" not found for writing; "
     486             :                  "maybe it is a built-in variable that is not changeable "
     487             :                  "or you forgot to use \"set $%*s '';\" "
     488             :                  "in the config file to define it first",
     489             :                  name_len, lowcase_buf, name_len, lowcase_buf);
     490           0 :     return NGX_ERROR;
     491             : 
     492           0 : nomem:
     493             : 
     494           0 :     ngx_snprintf(errbuf, errlen, "no memory");
     495           0 :     return NGX_ERROR;
     496             : }
     497             : #endif /* NGX_LUA_NO_FFI_API */
     498             : 
     499             : 
     500             : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */

Generated by: LCOV version 1.13