b056048018de5dbb038acdccba96f27805ca92c8
[m6w6/ext-http] / php_http_params.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 /* $Id: http_api.c 300299 2010-06-09 06:23:16Z mike $ */
14
15 #include "php_http.h"
16
17 PHP_HTTP_API void php_http_params_parse_default_func(void *arg, const char *key, int keylen, const char *val, int vallen TSRMLS_DC)
18 {
19 zval tmp, *entry;
20 HashTable *ht = (HashTable *) arg;
21
22 if (ht) {
23 INIT_PZVAL_ARRAY(&tmp, ht);
24
25 if (vallen) {
26 MAKE_STD_ZVAL(entry);
27 array_init(entry);
28 if (keylen) {
29 add_assoc_stringl_ex(entry, key, keylen + 1, estrndup(val, vallen), vallen, 0);
30 } else {
31 add_next_index_stringl(entry, val, vallen, 1);
32 }
33 add_next_index_zval(&tmp, entry);
34 } else {
35 add_next_index_stringl(&tmp, key, keylen, 1);
36 }
37 }
38 }
39
40 PHP_HTTP_API STATUS php_http_params_parse(const char *param, int flags, php_http_params_parse_func_t cb, void *cb_arg TSRMLS_DC)
41 {
42 #define ST_QUOTE 1
43 #define ST_VALUE 2
44 #define ST_KEY 3
45 #define ST_ASSIGN 4
46 #define ST_ADD 5
47
48 int st = ST_KEY, keylen = 0, vallen = 0;
49 char *s, *c, *key = NULL, *val = NULL;
50
51 if (!cb) {
52 cb = php_http_params_parse_default_func;
53 }
54
55 for(c = s = estrdup(param);;) {
56 continued:
57 #if 0
58 {
59 char *tk = NULL, *tv = NULL;
60
61 if (key) {
62 if (keylen) {
63 tk= estrndup(key, keylen);
64 } else {
65 tk = ecalloc(1, 7);
66 memcpy(tk, key, 3);
67 tk[3]='.'; tk[4]='.'; tk[5]='.';
68 }
69 }
70 if (val) {
71 if (vallen) {
72 tv = estrndup(val, vallen);
73 } else {
74 tv = ecalloc(1, 7);
75 memcpy(tv, val, 3);
76 tv[3]='.'; tv[4]='.'; tv[5]='.';
77 }
78 }
79 fprintf(stderr, "[%6s] %c \"%s=%s\"\n",
80 (
81 st == ST_QUOTE ? "QUOTE" :
82 st == ST_VALUE ? "VALUE" :
83 st == ST_KEY ? "KEY" :
84 st == ST_ASSIGN ? "ASSIGN" :
85 st == ST_ADD ? "ADD":
86 "HUH?"
87 ), *c?*c:'0', tk, tv
88 );
89 STR_FREE(tk); STR_FREE(tv);
90 }
91 #endif
92 switch (st) {
93 case ST_QUOTE:
94 quote:
95 if (*c == '"') {
96 if (*(c-1) == '\\') {
97 memmove(c-1, c, strlen(c)+1);
98 goto quote;
99 } else {
100 goto add;
101 }
102 } else {
103 if (!val) {
104 val = c;
105 }
106 if (!*c) {
107 --val;
108 st = ST_ADD;
109 }
110 }
111 break;
112
113 case ST_VALUE:
114 switch (*c) {
115 case '"':
116 if (!val) {
117 st = ST_QUOTE;
118 }
119 break;
120
121 case ' ':
122 break;
123
124 case ';':
125 case '\0':
126 goto add;
127 break;
128 case ',':
129 if (flags & PHP_HTTP_PARAMS_ALLOW_COMMA) {
130 goto add;
131 }
132 default:
133 if (!val) {
134 val = c;
135 }
136 break;
137 }
138 break;
139
140 case ST_KEY:
141 switch (*c) {
142 case ',':
143 if (flags & PHP_HTTP_PARAMS_ALLOW_COMMA) {
144 goto allow_comma;
145 }
146 case '\r':
147 case '\n':
148 case '\t':
149 case '\013':
150 case '\014':
151 goto failure;
152 break;
153
154 case ' ':
155 if (key) {
156 keylen = c - key;
157 st = ST_ASSIGN;
158 }
159 break;
160
161 case ';':
162 case '\0':
163 allow_comma:
164 if (key) {
165 keylen = c-- - key;
166 st = ST_ADD;
167 }
168 break;
169
170 case ':':
171 if (!(flags & PHP_HTTP_PARAMS_COLON_SEPARATOR)) {
172 goto not_separator;
173 }
174 if (key) {
175 keylen = c - key;
176 st = ST_VALUE;
177 } else {
178 goto failure;
179 }
180 break;
181
182 case '=':
183 if (flags & PHP_HTTP_PARAMS_COLON_SEPARATOR) {
184 goto not_separator;
185 }
186 if (key) {
187 keylen = c - key;
188 st = ST_VALUE;
189 } else {
190 goto failure;
191 }
192 break;
193
194 default:
195 not_separator:
196 if (!key) {
197 key = c;
198 }
199 break;
200 }
201 break;
202
203 case ST_ASSIGN:
204 if (*c == '=') {
205 st = ST_VALUE;
206 } else if (!*c || *c == ';' || ((flags & PHP_HTTP_PARAMS_ALLOW_COMMA) && *c == ',')) {
207 st = ST_ADD;
208 } else if (*c != ' ') {
209 goto failure;
210 }
211 break;
212
213 case ST_ADD:
214 add:
215 if (val) {
216 vallen = c - val;
217 if (st != ST_QUOTE) {
218 while (val[vallen-1] == ' ') --vallen;
219 }
220 } else {
221 val = "";
222 vallen = 0;
223 }
224
225 cb(cb_arg, key, keylen, val, vallen TSRMLS_CC);
226
227 st = ST_KEY;
228 key = val = NULL;
229 keylen = vallen = 0;
230 break;
231 }
232 if (*c) {
233 ++c;
234 } else if (st == ST_ADD) {
235 goto add;
236 } else {
237 break;
238 }
239 }
240
241 efree(s);
242 return SUCCESS;
243
244 failure:
245 if (flags & PHP_HTTP_PARAMS_RAISE_ERROR) {
246 php_http_error(HE_WARNING, PHP_HTTP_E_INVALID_PARAM, "Unexpected character (%c) at pos %tu of %zu", *c, c-s, strlen(s));
247 }
248 if (flags & PHP_HTTP_PARAMS_ALLOW_FAILURE) {
249 if (st == ST_KEY) {
250 if (key) {
251 keylen = c - key;
252 } else {
253 key = c;
254 }
255 } else {
256 --c;
257 }
258 st = ST_ADD;
259 goto continued;
260 }
261 efree(s);
262 return FAILURE;
263 }
264
265
266 /*
267 * Local variables:
268 * tab-width: 4
269 * c-basic-offset: 4
270 * End:
271 * vim600: noet sw=4 ts=4 fdm=marker
272 * vim<600: noet sw=4 ts=4
273 */
274