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_util.h"
15 
16 
17 int
ngx_http_lua_ffi_var_get(ngx_http_request_t * r,u_char * name_data,size_t name_len,u_char * lowcase_buf,int capture_id,u_char ** value,size_t * value_len,char ** err)18 ngx_http_lua_ffi_var_get(ngx_http_request_t *r, u_char *name_data,
19     size_t name_len, u_char *lowcase_buf, int capture_id, u_char **value,
20     size_t *value_len, char **err)
21 {
22     ngx_uint_t                   hash;
23     ngx_str_t                    name;
24     ngx_http_variable_value_t   *vv;
25 
26 #if (NGX_PCRE)
27     u_char                      *p;
28     ngx_uint_t                   n;
29     int                         *cap;
30 #endif
31 
32     if (r == NULL) {
33         *err = "no request object found";
34         return NGX_ERROR;
35     }
36 
37     if ((r)->connection->fd == (ngx_socket_t) -1) {
38         *err = "API disabled in the current context";
39         return NGX_ERROR;
40     }
41 
42 #if (NGX_PCRE)
43     if (name_data == 0) {
44         if (capture_id <= 0) {
45             return NGX_DECLINED;
46         }
47 
48         /* it is a regex capturing variable */
49 
50         n = (ngx_uint_t) capture_id * 2;
51 
52         dd("n = %d, ncaptures = %d", (int) n, (int) r->ncaptures);
53 
54         if (r->captures == NULL
55             || r->captures_data == NULL
56             || n >= r->ncaptures)
57         {
58             return NGX_DECLINED;
59         }
60 
61         /* n >= 0 && n < r->ncaptures */
62 
63         cap = r->captures;
64         p = r->captures_data;
65 
66         *value = &p[cap[n]];
67         *value_len = (size_t) (cap[n + 1] - cap[n]);
68 
69         return NGX_OK;
70     }
71 #endif
72 
73     hash = ngx_hash_strlow(lowcase_buf, name_data, name_len);
74 
75     name.data = lowcase_buf;
76     name.len = name_len;
77 
78     dd("variable name: %.*s", (int) name_len, lowcase_buf);
79 
80     vv = ngx_http_get_variable(r, &name, hash);
81     if (vv == NULL || vv->not_found) {
82         return NGX_DECLINED;
83     }
84 
85     *value = vv->data;
86     *value_len = vv->len;
87     return NGX_OK;
88 }
89 
90 
91 int
ngx_http_lua_ffi_var_set(ngx_http_request_t * r,u_char * name_data,size_t name_len,u_char * lowcase_buf,u_char * value,size_t value_len,u_char * errbuf,size_t * errlen)92 ngx_http_lua_ffi_var_set(ngx_http_request_t *r, u_char *name_data,
93     size_t name_len, u_char *lowcase_buf, u_char *value, size_t value_len,
94     u_char *errbuf, size_t *errlen)
95 {
96     u_char                      *p;
97     ngx_uint_t                   hash;
98     ngx_http_variable_t         *v;
99     ngx_http_variable_value_t   *vv;
100     ngx_http_core_main_conf_t   *cmcf;
101 
102     if (r == NULL) {
103         *errlen = ngx_snprintf(errbuf, *errlen, "no request object found")
104                   - errbuf;
105         return NGX_ERROR;
106     }
107 
108     if ((r)->connection->fd == (ngx_socket_t) -1) {
109         *errlen = ngx_snprintf(errbuf, *errlen,
110                                "API disabled in the current context")
111                   - errbuf;
112         return NGX_ERROR;
113     }
114 
115     hash = ngx_hash_strlow(lowcase_buf, name_data, name_len);
116 
117     dd("variable name: %.*s", (int) name_len, lowcase_buf);
118 
119     /* we fetch the variable itself */
120 
121     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
122 
123     v = ngx_hash_find(&cmcf->variables_hash, hash, lowcase_buf, name_len);
124 
125     if (v) {
126         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
127             dd("variable not changeable");
128             *errlen = ngx_snprintf(errbuf, *errlen,
129                                    "variable \"%*s\" not changeable",
130                                    name_len, lowcase_buf)
131                       - errbuf;
132             return NGX_ERROR;
133         }
134 
135         if (v->set_handler) {
136 
137             dd("set variables with set_handler");
138 
139             if (value != NULL && value_len) {
140                 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)
141                                 + value_len);
142                 if (vv == NULL) {
143                     goto nomem;
144                 }
145 
146                 p = (u_char *) vv + sizeof(ngx_http_variable_value_t);
147                 ngx_memcpy(p, value, value_len);
148                 value = p;
149 
150             } else {
151                 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
152                 if (vv == NULL) {
153                     goto nomem;
154                 }
155             }
156 
157             if (value == NULL) {
158                 vv->valid = 0;
159                 vv->not_found = 1;
160                 vv->no_cacheable = 0;
161                 vv->data = NULL;
162                 vv->len = 0;
163 
164             } else {
165                 vv->valid = 1;
166                 vv->not_found = 0;
167                 vv->no_cacheable = 0;
168 
169                 vv->data = value;
170                 vv->len = value_len;
171             }
172 
173             v->set_handler(r, vv, v->data);
174             return NGX_OK;
175         }
176 
177         if (v->flags & NGX_HTTP_VAR_INDEXED) {
178             vv = &r->variables[v->index];
179 
180             dd("set indexed variable");
181 
182             if (value == NULL) {
183                 vv->valid = 0;
184                 vv->not_found = 1;
185                 vv->no_cacheable = 0;
186 
187                 vv->data = NULL;
188                 vv->len = 0;
189 
190             } else {
191                 p = ngx_palloc(r->pool, value_len);
192                 if (p == NULL) {
193                     goto nomem;
194                 }
195 
196                 ngx_memcpy(p, value, value_len);
197                 value = p;
198 
199                 vv->valid = 1;
200                 vv->not_found = 0;
201                 vv->no_cacheable = 0;
202 
203                 vv->data = value;
204                 vv->len = value_len;
205             }
206 
207             return NGX_OK;
208         }
209 
210         *errlen = ngx_snprintf(errbuf, *errlen,
211                                "variable \"%*s\" cannot be assigned "
212                                "a value", name_len, lowcase_buf)
213                   - errbuf;
214         return NGX_ERROR;
215     }
216 
217     /* variable not found */
218 
219     *errlen = ngx_snprintf(errbuf, *errlen,
220                            "variable \"%*s\" not found for writing; "
221                            "maybe it is a built-in variable that is not "
222                            "changeable or you forgot to use \"set $%*s '';\" "
223                            "in the config file to define it first",
224                            name_len, lowcase_buf, name_len, lowcase_buf)
225               - errbuf;
226     return NGX_ERROR;
227 
228 nomem:
229 
230     *errlen = ngx_snprintf(errbuf, *errlen, "no memory") - errbuf;
231     return NGX_ERROR;
232 }
233 
234 
235 /* vi:set ft=c ts=4 sw=4 et fdm=marker: */
236