Line data Source code
1 : #ifndef DDEBUG
2 : #define DDEBUG 0
3 : #endif
4 : #include "ddebug.h"
5 :
6 : #include <ndk.h>
7 : #include "ngx_http_set_quote_sql.h"
8 :
9 :
10 : static ngx_int_t ngx_http_pg_utf_escape(ngx_http_request_t *r, ngx_str_t *res);
11 : static ngx_int_t ngx_http_pg_utf_islegal(const unsigned char *s, ngx_int_t len);
12 : static ngx_int_t ngx_http_pg_utf_mblen(const unsigned char *s);
13 :
14 :
15 : ngx_int_t
16 0 : ngx_http_set_misc_quote_pgsql_str(ngx_http_request_t *r, ngx_str_t *res,
17 : ngx_http_variable_value_t *v)
18 : {
19 : u_char *pstr;
20 : ngx_int_t length;
21 :
22 0 : if (v->not_found || v->len ==0) {
23 0 : res->data = (u_char *) "''";
24 0 : res->len = sizeof("''") - 1;
25 0 : return NGX_OK;
26 : }
27 :
28 0 : ngx_http_set_misc_quote_sql_str(r, res, v);
29 0 : length = res->len;
30 :
31 0 : pstr = ngx_palloc(r->pool, length + 1);
32 0 : if (pstr == NULL) {
33 0 : return NGX_ERROR;
34 : }
35 :
36 0 : *pstr = 'E';
37 0 : memcpy(pstr + 1, res->data, length);
38 0 : res->data = pstr;
39 0 : res->len = length + 1;
40 :
41 0 : if (ngx_http_pg_utf_islegal(res->data, res->len)) {
42 0 : return NGX_OK;
43 : }
44 :
45 0 : if (ngx_http_pg_utf_escape(r, res) != NGX_OK) {
46 0 : return NGX_ERROR;
47 : }
48 :
49 0 : return NGX_OK;
50 : }
51 :
52 :
53 : static ngx_int_t
54 0 : ngx_http_pg_utf_mblen(const unsigned char *s)
55 : {
56 : int len;
57 :
58 0 : if ((*s & 0x80) == 0)
59 0 : len = 1;
60 0 : else if ((*s & 0xe0) == 0xc0)
61 0 : len = 2;
62 0 : else if ((*s & 0xf0) == 0xe0)
63 0 : len = 3;
64 0 : else if ((*s & 0xf8) == 0xf0)
65 0 : len = 4;
66 : #ifdef NOT_USED
67 : else if ((*s & 0xfc) == 0xf8)
68 : len = 5;
69 : else if ((*s & 0xfe) == 0xfc)
70 : len = 6;
71 : #endif
72 : else
73 0 : len = 1;
74 0 : return len;
75 : }
76 :
77 :
78 : static ngx_int_t
79 0 : ngx_http_pg_utf_islegal(const unsigned char *s, ngx_int_t len)
80 : {
81 : ngx_int_t mblen;
82 : ngx_int_t slen;
83 : u_char a;
84 :
85 0 : slen = len;
86 :
87 0 : while (slen > 0) {
88 0 : mblen = ngx_http_pg_utf_mblen(s);
89 0 : if (slen < mblen)
90 0 : return 0;
91 :
92 0 : switch(mblen)
93 : {
94 0 : default:
95 0 : return 0;
96 0 : case 4:
97 0 : a = *(s + 3);
98 0 : if (a < 0x80 || a > 0xBF)
99 0 : return 0;
100 : case 3:
101 0 : a = *(s + 2);
102 0 : if (a < 0x80 || a > 0xBF)
103 0 : return 0;
104 : case 2:
105 0 : a = *(s + 1);
106 0 : switch (*s)
107 : {
108 0 : case 0xE0:
109 0 : if (a < 0xA0 || a > 0xBF)
110 0 : return 0;
111 0 : break;
112 0 : case 0xED:
113 0 : if (a < 0x80 || a > 0x9F)
114 0 : return 0;
115 0 : break;
116 0 : case 0xF0:
117 0 : if (a < 0x90 || a > 0xBF)
118 0 : return 0;
119 0 : break;
120 0 : case 0xF4:
121 0 : if (a < 0x80 || a > 0x8F)
122 0 : return 0;
123 0 : break;
124 0 : default:
125 0 : if (a < 0x80 || a > 0xBF)
126 0 : return 0;
127 0 : break;
128 : }
129 0 : case 1:
130 0 : a = *s;
131 0 : if (a >= 0x80 && a < 0xC2)
132 0 : return 0;
133 0 : if (a > 0xF4)
134 0 : return 0;
135 0 : break;
136 : }
137 :
138 0 : s += mblen;
139 0 : slen -= mblen;
140 : }
141 :
142 0 : return 1;
143 : }
144 :
145 :
146 : static ngx_int_t
147 0 : ngx_http_pg_utf_escape(ngx_http_request_t *r, ngx_str_t *res)
148 : {
149 : ngx_str_t *result;
150 : ngx_int_t l, count;
151 : u_char *d, *p, *p1;
152 :
153 0 : l = res->len;
154 0 : d = res->data;
155 0 : result = res;
156 0 : count = 0;
157 :
158 0 : while (l-- > 0) {
159 0 : if (*d & 0x80) {
160 0 : count += 4;
161 : }
162 0 : d++;
163 0 : count++;
164 : }
165 :
166 0 : d = res->data;
167 0 : l = res->len;
168 :
169 0 : p = ngx_palloc(r->pool, count);
170 0 : if (p == NULL) {
171 0 : return NGX_ERROR;
172 : }
173 :
174 0 : p1 = p;
175 0 : while (l-- > 0) {
176 0 : if ((*d & 0x80)) {
177 0 : *p++ = '\\';
178 0 : *p++ = '\\';
179 0 : *p++ = (*d >> 6) + '0';
180 0 : *p++ = ((*d >> 3) & 07) + '0';
181 0 : *p++ = (*d & 07) + '0';
182 : } else {
183 0 : *p++ = *d;
184 : }
185 0 : d++;
186 : }
187 :
188 0 : result->len = count;
189 0 : result->data = p1;
190 :
191 0 : return NGX_OK;
192 : }
193 :
194 :
195 : ngx_int_t
196 0 : ngx_http_set_misc_quote_sql_str(ngx_http_request_t *r, ngx_str_t *res,
197 : ngx_http_variable_value_t *v)
198 : {
199 : size_t len;
200 : u_char *p;
201 : size_t escape;
202 :
203 0 : if (v->not_found || v->len == 0) {
204 0 : res->data = (u_char *) "''";
205 0 : res->len = sizeof("''") - 1;
206 0 : return NGX_OK;
207 : }
208 :
209 0 : escape = ngx_http_set_misc_escape_sql_str(NULL, v->data, v->len);
210 :
211 0 : len = sizeof("''") - 1 + v->len + escape;
212 :
213 0 : p = ngx_palloc(r->pool, len);
214 0 : if (p == NULL) {
215 0 : return NGX_ERROR;
216 : }
217 :
218 0 : res->data = p;
219 0 : res->len = len;
220 :
221 0 : *p++ = '\'';
222 :
223 0 : if (escape == 0) {
224 0 : p = ngx_copy(p, v->data, v->len);
225 :
226 : } else {
227 0 : p = (u_char *) ngx_http_set_misc_escape_sql_str(p, v->data, v->len);
228 : }
229 :
230 0 : *p++ = '\'';
231 :
232 0 : if (p != res->data + res->len) {
233 0 : ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
234 : "set_quote_sql_str: buffer error");
235 0 : return NGX_ERROR;
236 : }
237 :
238 0 : return NGX_OK;
239 : }
240 :
241 :
242 : uintptr_t
243 0 : ngx_http_set_misc_escape_sql_str(u_char *dst, u_char *src, size_t size)
244 : {
245 : ngx_uint_t n;
246 :
247 0 : if (dst == NULL) {
248 : /* find the number of chars to be escaped */
249 0 : n = 0;
250 0 : while (size) {
251 : /* the highest bit of all the UTF-8 chars
252 : * is always 1 */
253 0 : if ((*src & 0x80) == 0) {
254 0 : switch (*src) {
255 0 : case '\0':
256 : case '\b':
257 : case '\n':
258 : case '\r':
259 : case '\t':
260 : case '\\':
261 : case '\'':
262 : case '"':
263 : case 26: /* \Z */
264 0 : n++;
265 0 : break;
266 0 : default:
267 0 : break;
268 : }
269 0 : }
270 0 : src++;
271 0 : size--;
272 : }
273 :
274 0 : return (uintptr_t) n;
275 : }
276 :
277 0 : while (size) {
278 0 : if ((*src & 0x80) == 0) {
279 0 : switch (*src) {
280 0 : case '\0':
281 0 : *dst++ = '\\';
282 0 : *dst++ = '0';
283 0 : break;
284 :
285 0 : case '\b':
286 0 : *dst++ = '\\';
287 0 : *dst++ = 'b';
288 0 : break;
289 :
290 0 : case '\n':
291 0 : *dst++ = '\\';
292 0 : *dst++ = 'n';
293 0 : break;
294 :
295 0 : case '\r':
296 0 : *dst++ = '\\';
297 0 : *dst++ = 'r';
298 0 : break;
299 :
300 0 : case '\t':
301 0 : *dst++ = '\\';
302 0 : *dst++ = 't';
303 0 : break;
304 :
305 0 : case '\\':
306 0 : *dst++ = '\\';
307 0 : *dst++ = '\\';
308 0 : break;
309 :
310 0 : case '\'':
311 0 : *dst++ = '\\';
312 0 : *dst++ = '\'';
313 0 : break;
314 :
315 0 : case '"':
316 0 : *dst++ = '\\';
317 0 : *dst++ = '"';
318 0 : break;
319 :
320 0 : case 26:
321 0 : *dst++ = '\\';
322 0 : *dst++ = 'Z';
323 0 : break;
324 :
325 0 : default:
326 0 : *dst++ = *src;
327 0 : break;
328 : }
329 : } else {
330 0 : *dst++ = *src;
331 : }
332 0 : src++;
333 0 : size--;
334 : } /* while (size) */
335 :
336 0 : return (uintptr_t) dst;
337 : }
338 :
|