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