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_unescape_uri.h"
8 :
9 : #define NGX_UNESCAPE_URI_COMPONENT 0
10 :
11 :
12 : static void ngx_unescape_uri_patched(u_char **dst, u_char **src, size_t size,
13 : ngx_uint_t type);
14 :
15 :
16 : ngx_int_t
17 0 : ngx_http_set_misc_unescape_uri(ngx_http_request_t *r, ngx_str_t *res,
18 : ngx_http_variable_value_t *v)
19 : {
20 : size_t len;
21 : u_char *p;
22 : u_char *src, *dst;
23 :
24 : /* the unescaped string can only be smaller */
25 0 : len = v->len;
26 :
27 0 : p = ngx_palloc(r->pool, len);
28 0 : if (p == NULL) {
29 0 : return NGX_ERROR;
30 : }
31 :
32 0 : src = v->data; dst = p;
33 :
34 0 : ngx_unescape_uri_patched(&dst, &src, v->len, NGX_UNESCAPE_URI_COMPONENT);
35 :
36 0 : if (src != v->data + v->len) {
37 0 : ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
38 : "set_unescape_uri: input data not consumed completely");
39 0 : return NGX_ERROR;
40 : }
41 :
42 0 : res->data = p;
43 0 : res->len = dst - p;
44 :
45 0 : return NGX_OK;
46 : }
47 :
48 :
49 : /* XXX we also decode '+' to ' ' */
50 : static void
51 0 : ngx_unescape_uri_patched(u_char **dst, u_char **src, size_t size,
52 : ngx_uint_t type)
53 : {
54 : u_char *d, *s, ch, c, decoded;
55 : enum {
56 : sw_usual = 0,
57 : sw_quoted,
58 : sw_quoted_second
59 : } state;
60 :
61 0 : d = *dst;
62 0 : s = *src;
63 :
64 0 : state = 0;
65 0 : decoded = 0;
66 :
67 0 : while (size--) {
68 :
69 0 : ch = *s++;
70 :
71 0 : switch (state) {
72 0 : case sw_usual:
73 0 : if (ch == '?'
74 0 : && (type & (NGX_UNESCAPE_URI|NGX_UNESCAPE_REDIRECT)))
75 : {
76 0 : *d++ = ch;
77 0 : goto done;
78 : }
79 :
80 0 : if (ch == '%') {
81 0 : state = sw_quoted;
82 0 : break;
83 : }
84 :
85 0 : if (ch == '+') {
86 0 : *d++ = ' ';
87 0 : break;
88 : }
89 :
90 0 : *d++ = ch;
91 0 : break;
92 :
93 0 : case sw_quoted:
94 :
95 0 : if (ch >= '0' && ch <= '9') {
96 0 : decoded = (u_char) (ch - '0');
97 0 : state = sw_quoted_second;
98 0 : break;
99 : }
100 :
101 0 : c = (u_char) (ch | 0x20);
102 0 : if (c >= 'a' && c <= 'f') {
103 0 : decoded = (u_char) (c - 'a' + 10);
104 0 : state = sw_quoted_second;
105 0 : break;
106 : }
107 :
108 : /* the invalid quoted character */
109 :
110 0 : state = sw_usual;
111 :
112 0 : *d++ = ch;
113 :
114 0 : break;
115 :
116 0 : case sw_quoted_second:
117 :
118 0 : state = sw_usual;
119 :
120 0 : if (ch >= '0' && ch <= '9') {
121 0 : ch = (u_char) ((decoded << 4) + ch - '0');
122 :
123 0 : if (type & NGX_UNESCAPE_REDIRECT) {
124 0 : if (ch > '%' && ch < 0x7f) {
125 0 : *d++ = ch;
126 0 : break;
127 : }
128 :
129 0 : *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
130 :
131 0 : break;
132 : }
133 :
134 0 : *d++ = ch;
135 :
136 0 : break;
137 : }
138 :
139 0 : c = (u_char) (ch | 0x20);
140 0 : if (c >= 'a' && c <= 'f') {
141 0 : ch = (u_char) ((decoded << 4) + c - 'a' + 10);
142 :
143 0 : if (type & NGX_UNESCAPE_URI) {
144 0 : if (ch == '?') {
145 0 : *d++ = ch;
146 0 : goto done;
147 : }
148 :
149 0 : *d++ = ch;
150 0 : break;
151 : }
152 :
153 0 : if (type & NGX_UNESCAPE_REDIRECT) {
154 0 : if (ch == '?') {
155 0 : *d++ = ch;
156 0 : goto done;
157 : }
158 :
159 0 : if (ch > '%' && ch < 0x7f) {
160 0 : *d++ = ch;
161 0 : break;
162 : }
163 :
164 0 : *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
165 0 : break;
166 : }
167 :
168 0 : *d++ = ch;
169 :
170 0 : break;
171 : }
172 :
173 : /* the invalid quoted character */
174 :
175 0 : break;
176 : }
177 : }
178 :
179 0 : done:
180 :
181 0 : *dst = d;
182 0 : *src = s;
183 0 : }
184 :
|