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-2014, Michael Wallner <mike@php.net>            |
10     +--------------------------------------------------------------------+
11 */
12 
13 #include "php_http_api.h"
14 
15 #ifndef DBG_PARSER
16 #	define DBG_PARSER 0
17 #endif
18 
19 typedef struct php_http_header_parser_state_spec {
20 	php_http_header_parser_state_t state;
21 	unsigned need_data:1;
22 } php_http_header_parser_state_spec_t;
23 
24 static const php_http_header_parser_state_spec_t php_http_header_parser_states[] = {
25 		{PHP_HTTP_HEADER_PARSER_STATE_START,		1},
26 		{PHP_HTTP_HEADER_PARSER_STATE_KEY,			1},
27 		{PHP_HTTP_HEADER_PARSER_STATE_VALUE,		1},
28 		{PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX,		0},
29 		{PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE,	0},
30 		{PHP_HTTP_HEADER_PARSER_STATE_DONE,			0}
31 };
32 
php_http_header_parser_init(php_http_header_parser_t * parser)33 php_http_header_parser_t *php_http_header_parser_init(php_http_header_parser_t *parser)
34 {
35 	if (!parser) {
36 		parser = emalloc(sizeof(*parser));
37 	}
38 	memset(parser, 0, sizeof(*parser));
39 
40 	return parser;
41 }
42 
43 #define php_http_header_parser_state_push(parser, state) zend_ptr_stack_push(&(parser)->stack, (void *) (state)), (state)
44 #define php_http_header_parser_state_ex(parser) ((parser)->stack.top \
45 		? (php_http_header_parser_state_t) (parser)->stack.elements[(parser)->stack.top - 1] \
46 		: PHP_HTTP_HEADER_PARSER_STATE_START)
47 
php_http_header_parser_state_is(php_http_header_parser_t * parser)48 php_http_header_parser_state_t php_http_header_parser_state_is(php_http_header_parser_t *parser)
49 {
50 	return php_http_header_parser_state_ex(parser);
51 }
52 
53 #define php_http_header_parser_state_pop(parser) ((parser)->stack.top \
54 		? (php_http_header_parser_state_t) zend_ptr_stack_pop(&(parser)->stack) \
55 		: PHP_HTTP_HEADER_PARSER_STATE_START)
56 
php_http_header_parser_dtor(php_http_header_parser_t * parser)57 void php_http_header_parser_dtor(php_http_header_parser_t *parser)
58 {
59 	zend_ptr_stack_destroy(&parser->stack);
60 	php_http_info_dtor(&parser->info);
61 	PTR_FREE(parser->_key.str);
62 	PTR_FREE(parser->_val.str);
63 }
64 
php_http_header_parser_free(php_http_header_parser_t ** parser)65 void php_http_header_parser_free(php_http_header_parser_t **parser)
66 {
67 	if (*parser) {
68 		php_http_header_parser_dtor(*parser);
69 		efree(*parser);
70 		*parser = NULL;
71 	}
72 }
73 
74 /* NOTE: 'str' has to be null terminated */
php_http_header_parser_error(size_t valid_len,char * str,size_t len,const char * eol_str)75 static void php_http_header_parser_error(size_t valid_len, char *str, size_t len, const char *eol_str )
76 {
77 	zend_string *escaped_str, *zstr_str = zend_string_init(str, len, 0);
78 
79 #if PHP_VERSION_ID < 70300
80 	escaped_str = php_addcslashes(zstr_str, 1, ZEND_STRL("\x0..\x1F\x7F..\xFF"));
81 #else
82 	escaped_str = php_addcslashes(zstr_str, ZEND_STRL("\x0..\x1F\x7F..\xFF"));
83 	zend_string_release_ex(zstr_str, 0);
84 #endif
85 
86 	if (valid_len != len && (!eol_str || (str+valid_len) != eol_str)) {
87 		php_error_docref(NULL, E_WARNING, "Failed to parse headers: unexpected character '\\%03o' at pos %zu of '%s'", str[valid_len], valid_len, escaped_str->val);
88 	} else if (eol_str) {
89 		php_error_docref(NULL, E_WARNING, "Failed to parse headers: unexpected end of line at pos %zu of '%s'", eol_str - str, escaped_str->val);
90 	} else {
91 		php_error_docref(NULL, E_WARNING, "Failed to parse headers: unexpected end of input at pos %zu of '%s'", len, escaped_str->val);
92 	}
93 
94 	efree(escaped_str);
95 }
96 
php_http_header_parser_parse(php_http_header_parser_t * parser,php_http_buffer_t * buffer,unsigned flags,HashTable * headers,php_http_info_callback_t callback_func,void * callback_arg)97 php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
98 {
99 	while (buffer->used || !php_http_header_parser_states[php_http_header_parser_state_ex(parser)].need_data) {
100 #if DBG_PARSER
101 		const char *state[] = {"START", "KEY", "VALUE", "VALUE_EX", "HEADER_DONE", "DONE"};
102 		fprintf(stderr, "#HP: %s (avail:%zu, num:%d cleanup:%u)\n", php_http_header_parser_state_is(parser) < 0 ? "FAILURE" : state[php_http_header_parser_state_is(parser)], buffer->used, headers?zend_hash_num_elements(headers):0, flags);
103 		_dpf(0, buffer->data, buffer->used);
104 #endif
105 		switch (php_http_header_parser_state_pop(parser)) {
106 			case PHP_HTTP_HEADER_PARSER_STATE_FAILURE:
107 				php_error_docref(NULL, E_WARNING, "Failed to parse headers");
108 				return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
109 
110 			case PHP_HTTP_HEADER_PARSER_STATE_START: {
111 				char *ptr = buffer->data;
112 
113 				while (ptr - buffer->data < buffer->used && PHP_HTTP_IS_CTYPE(space, *ptr)) {
114 					++ptr;
115 				}
116 
117 				php_http_buffer_cut(buffer, 0, ptr - buffer->data);
118 				php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_KEY);
119 				break;
120 			}
121 
122 			case PHP_HTTP_HEADER_PARSER_STATE_KEY: {
123 				const char *colon, *eol_str = NULL;
124 				int eol_len = 0;
125 
126 				/* fix buffer here, so eol_str pointer doesn't become obsolete afterwards */
127 				php_http_buffer_fix(buffer);
128 
129 				if (buffer->data == (eol_str = php_http_locate_bin_eol(buffer->data, buffer->used, &eol_len))) {
130 					/* end of headers */
131 					php_http_buffer_cut(buffer, 0, eol_len);
132 					php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_DONE);
133 				} else if (php_http_info_parse(&parser->info, buffer->data)) {
134 					/* new message starting with request/response line */
135 					if (callback_func) {
136 						callback_func(callback_arg, &headers, &parser->info);
137 					}
138 					php_http_info_dtor(&parser->info);
139 					php_http_buffer_cut(buffer, 0, eol_str + eol_len - buffer->data);
140 					php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
141 				} else if ((colon = memchr(buffer->data, ':', buffer->used)) && (!eol_str || eol_str > colon)) {
142 					/* header: string */
143 					size_t valid_len;
144 
145 					parser->_key.len = colon - buffer->data;
146 					parser->_key.str = estrndup(buffer->data, parser->_key.len);
147 
148 					valid_len = strspn(parser->_key.str, PHP_HTTP_HEADER_NAME_CHARS);
149 					if (valid_len != parser->_key.len) {
150 						php_http_header_parser_error(valid_len, parser->_key.str, parser->_key.len, eol_str);
151 						PTR_SET(parser->_key.str, NULL);
152 						return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
153 					}
154 					while (PHP_HTTP_IS_CTYPE(space, *++colon) && *colon != '\n' && *colon != '\r');
155 					php_http_buffer_cut(buffer, 0, colon - buffer->data);
156 					php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
157 				} else if (eol_str || (flags & PHP_HTTP_HEADER_PARSER_CLEANUP)) {
158 					/* neither reqeust/response line nor 'header:' string, or injected new line or NUL etc. */
159 					php_http_header_parser_error(strspn(buffer->data, PHP_HTTP_HEADER_NAME_CHARS), buffer->data, buffer->used, eol_str);
160 					return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
161 				} else {
162 					/* keep feeding */
163 					return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_KEY);
164 				}
165 				break;
166 			}
167 
168 			case PHP_HTTP_HEADER_PARSER_STATE_VALUE: {
169 				const char *eol_str;
170 				int eol_len;
171 
172 #define SET_ADD_VAL(slen, eol_len) \
173 	do { \
174 		const char *ptr = buffer->data; \
175 		size_t len = slen; \
176 		 \
177 		while (len > 0 && PHP_HTTP_IS_CTYPE(space, *ptr)) { \
178 			++ptr; \
179 			--len; \
180 		} \
181 		while (len > 0 && PHP_HTTP_IS_CTYPE(space, ptr[len - 1])) { \
182 			--len; \
183 		} \
184 		 \
185 		if (len > 0) { \
186 			if (parser->_val.str) { \
187 				parser->_val.str = erealloc(parser->_val.str, parser->_val.len + len + 2); \
188 				parser->_val.str[parser->_val.len++] = ' '; \
189 				memcpy(&parser->_val.str[parser->_val.len], ptr, len); \
190 				parser->_val.len += len; \
191 				parser->_val.str[parser->_val.len] = '\0'; \
192 			} else { \
193 				parser->_val.len = len; \
194 				parser->_val.str = estrndup(ptr, len); \
195 			} \
196 		} \
197 		php_http_buffer_cut(buffer, 0, slen + eol_len); \
198 	} while (0)
199 
200 				if ((eol_str = php_http_locate_bin_eol(buffer->data, buffer->used, &eol_len))) {
201 					SET_ADD_VAL(eol_str - buffer->data, eol_len);
202 					php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
203 				} else if (flags & PHP_HTTP_HEADER_PARSER_CLEANUP) {
204 					if (buffer->used) {
205 						SET_ADD_VAL(buffer->used, 0);
206 					}
207 					php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
208 				} else {
209 					return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
210 				}
211 				break;
212 			}
213 
214 			case PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX:
215 				if (buffer->used && (*buffer->data == ' ' || *buffer->data == '\t')) {
216 					php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
217 				} else if (buffer->used || (flags & PHP_HTTP_HEADER_PARSER_CLEANUP)) {
218 					php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
219 				} else {
220 					/* keep feeding */
221 					return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
222 				}
223 				break;
224 
225 			case PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE:
226 				if (parser->_key.str && parser->_val.str) {
227 					zval tmp, *exist;
228 					size_t valid_len = strlen(parser->_val.str);
229 
230 					/* check for truncation */
231 					if (valid_len != parser->_val.len) {
232 						php_http_header_parser_error(valid_len, parser->_val.str, parser->_val.len, NULL);
233 
234 						PTR_SET(parser->_key.str, NULL);
235 						PTR_SET(parser->_val.str, NULL);
236 
237 						return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
238 					}
239 
240 					if (!headers && callback_func) {
241 						callback_func(callback_arg, &headers, NULL);
242 					}
243 
244 					php_http_pretty_key(parser->_key.str, parser->_key.len, 1, 1);
245 					if ((exist = zend_symtable_str_find(headers, parser->_key.str, parser->_key.len))) {
246 						convert_to_array(exist);
247 						add_next_index_str(exist, php_http_cs2zs(parser->_val.str, parser->_val.len));
248 					} else {
249 						ZVAL_STR(&tmp, php_http_cs2zs(parser->_val.str, parser->_val.len));
250 						zend_symtable_str_update(headers, parser->_key.str, parser->_key.len, &tmp);
251 					}
252 					parser->_val.str = NULL;
253 				}
254 
255 				PTR_SET(parser->_key.str, NULL);
256 				PTR_SET(parser->_val.str, NULL);
257 
258 				php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_KEY);
259 				break;
260 
261 			case PHP_HTTP_HEADER_PARSER_STATE_DONE:
262 				return PHP_HTTP_HEADER_PARSER_STATE_DONE;
263 		}
264 	}
265 
266 	return php_http_header_parser_state_is(parser);
267 }
268 
php_http_header_parser_parse_stream(php_http_header_parser_t * parser,php_http_buffer_t * buf,php_stream * s,unsigned flags,HashTable * headers,php_http_info_callback_t callback_func,void * callback_arg)269 php_http_header_parser_state_t php_http_header_parser_parse_stream(php_http_header_parser_t *parser, php_http_buffer_t *buf, php_stream *s, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
270 {
271 	php_http_header_parser_state_t state = PHP_HTTP_HEADER_PARSER_STATE_START;
272 
273 	if (!buf->data) {
274 		php_http_buffer_resize_ex(buf, 0x1000, 1, 0);
275 	}
276 	while (1) {
277 		size_t justread = 0;
278 #if DBG_PARSER
279 		const char *states[] = {"START", "KEY", "VALUE", "VALUE_EX", "HEADER_DONE", "DONE"};
280 		fprintf(stderr, "#SHP: %s (f:%u)\n", states[state], flags);
281 #endif
282 		/* resize if needed */
283 		if (buf->free < 0x1000) {
284 			php_http_buffer_resize_ex(buf, 0x1000, 1, 0);
285 		}
286 		switch (state) {
287 		case PHP_HTTP_HEADER_PARSER_STATE_FAILURE:
288 		case PHP_HTTP_HEADER_PARSER_STATE_DONE:
289 			return state;
290 
291 		default:
292 			/* read line */
293 			php_stream_get_line(s, buf->data + buf->used, buf->free, &justread);
294 			/* if we fail reading a whole line, try a single char */
295 			if (!justread) {
296 				int c = php_stream_getc(s);
297 
298 				if (c != EOF) {
299 					char s[1] = {c};
300 					justread = php_http_buffer_append(buf, s, 1);
301 				}
302 			}
303 			php_http_buffer_account(buf, justread);
304 		}
305 
306 		if (justread) {
307 			state = php_http_header_parser_parse(parser, buf, flags, headers, callback_func, callback_arg);
308 		} else if (php_stream_eof(s)) {
309 			return php_http_header_parser_parse(parser, buf, flags | PHP_HTTP_HEADER_PARSER_CLEANUP, headers, callback_func, callback_arg);
310 		} else  {
311 			return state;
312 		}
313 	}
314 
315 	return PHP_HTTP_HEADER_PARSER_STATE_DONE;
316 }
317 
318 static zend_class_entry *php_http_header_parser_class_entry;
php_http_get_header_parser_class_entry(void)319 zend_class_entry *php_http_get_header_parser_class_entry(void)
320 {
321 	return php_http_header_parser_class_entry;
322 }
323 static zend_object_handlers php_http_header_parser_object_handlers;
324 
php_http_header_parser_object_new(zend_class_entry * ce)325 zend_object *php_http_header_parser_object_new(zend_class_entry *ce)
326 {
327 	return &php_http_header_parser_object_new_ex(ce, NULL)->zo;
328 }
329 
php_http_header_parser_object_new_ex(zend_class_entry * ce,php_http_header_parser_t * parser)330 php_http_header_parser_object_t *php_http_header_parser_object_new_ex(zend_class_entry *ce, php_http_header_parser_t *parser)
331 {
332 	php_http_header_parser_object_t *o;
333 
334 	o = ecalloc(1, sizeof(php_http_header_parser_object_t) + zend_object_properties_size(ce));
335 	zend_object_std_init(&o->zo, ce);
336 	object_properties_init(&o->zo, ce);
337 
338 	if (parser) {
339 		o->parser = parser;
340 	} else {
341 		o->parser = php_http_header_parser_init(NULL);
342 	}
343 	o->buffer = php_http_buffer_new();
344 
345 	o->zo.handlers = &php_http_header_parser_object_handlers;
346 
347 	return o;
348 }
349 
php_http_header_parser_object_free(zend_object * object)350 void php_http_header_parser_object_free(zend_object *object)
351 {
352 	php_http_header_parser_object_t *o = PHP_HTTP_OBJ(object, NULL);
353 
354 	if (o->parser) {
355 		php_http_header_parser_free(&o->parser);
356 	}
357 	if (o->buffer) {
358 		php_http_buffer_free(&o->buffer);
359 	}
360 	zend_object_std_dtor(object);
361 }
362 
363 ZEND_BEGIN_ARG_INFO_EX(ai_HttpHeaderParser_getState, 0, 0, 0)
364 ZEND_END_ARG_INFO();
PHP_METHOD(HttpHeaderParser,getState)365 static PHP_METHOD(HttpHeaderParser, getState)
366 {
367 	php_http_header_parser_object_t *parser_obj = PHP_HTTP_OBJ(NULL, getThis());
368 
369 	zend_parse_parameters_none();
370 	/* always return the real state */
371 	RETVAL_LONG(php_http_header_parser_state_is(parser_obj->parser));
372 }
373 
374 ZEND_BEGIN_ARG_INFO_EX(ai_HttpHeaderParser_parse, 0, 0, 3)
375 	ZEND_ARG_INFO(0, data)
376 	ZEND_ARG_INFO(0, flags)
377 	ZEND_ARG_ARRAY_INFO(1, headers, 1)
378 ZEND_END_ARG_INFO();
PHP_METHOD(HttpHeaderParser,parse)379 static PHP_METHOD(HttpHeaderParser, parse)
380 {
381 	php_http_header_parser_object_t *parser_obj;
382 	zval *zmsg;
383 	char *data_str;
384 	size_t data_len;
385 	zend_long flags;
386 
387 	php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "slz", &data_str, &data_len, &flags, &zmsg), invalid_arg, return);
388 
389 	ZVAL_DEREF(zmsg);
390 	if (Z_TYPE_P(zmsg) != IS_ARRAY) {
391 		zval_dtor(zmsg);
392 		array_init(zmsg);
393 	}
394 	parser_obj = PHP_HTTP_OBJ(NULL, getThis());
395 	php_http_buffer_append(parser_obj->buffer, data_str, data_len);
396 	RETVAL_LONG(php_http_header_parser_parse(parser_obj->parser, parser_obj->buffer, flags, Z_ARRVAL_P(zmsg), NULL, NULL));
397 }
398 
399 ZEND_BEGIN_ARG_INFO_EX(ai_HttpHeaderParser_stream, 0, 0, 3)
400 	ZEND_ARG_INFO(0, stream)
401 	ZEND_ARG_INFO(0, flags)
402 	ZEND_ARG_ARRAY_INFO(1, headers, 1)
403 ZEND_END_ARG_INFO();
PHP_METHOD(HttpHeaderParser,stream)404 static PHP_METHOD(HttpHeaderParser, stream)
405 {
406 	php_http_header_parser_object_t *parser_obj;
407 	zend_error_handling zeh;
408 	zval *zmsg, *zstream;
409 	php_stream *s;
410 	zend_long flags;
411 
412 	php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "rlz", &zstream, &flags, &zmsg), invalid_arg, return);
413 
414 	zend_replace_error_handling(EH_THROW, php_http_get_exception_unexpected_val_class_entry(), &zeh);
415 	php_stream_from_zval(s, zstream);
416 	zend_restore_error_handling(&zeh);
417 
418 	ZVAL_DEREF(zmsg);
419 	if (Z_TYPE_P(zmsg) != IS_ARRAY) {
420 		zval_dtor(zmsg);
421 		array_init(zmsg);
422 	}
423 	parser_obj = PHP_HTTP_OBJ(NULL, getThis());
424 	RETVAL_LONG(php_http_header_parser_parse_stream(parser_obj->parser, parser_obj->buffer, s, flags, Z_ARRVAL_P(zmsg), NULL, NULL));
425 }
426 
427 static zend_function_entry php_http_header_parser_methods[] = {
428 		PHP_ME(HttpHeaderParser, getState, ai_HttpHeaderParser_getState, ZEND_ACC_PUBLIC)
429 		PHP_ME(HttpHeaderParser, parse, ai_HttpHeaderParser_parse, ZEND_ACC_PUBLIC)
430 		PHP_ME(HttpHeaderParser, stream, ai_HttpHeaderParser_stream, ZEND_ACC_PUBLIC)
431 		{NULL, NULL, NULL}
432 };
433 
PHP_MINIT_FUNCTION(http_header_parser)434 PHP_MINIT_FUNCTION(http_header_parser)
435 {
436 	zend_class_entry ce;
437 
438 	INIT_NS_CLASS_ENTRY(ce, "http\\Header", "Parser", php_http_header_parser_methods);
439 	php_http_header_parser_class_entry = zend_register_internal_class(&ce);
440 	memcpy(&php_http_header_parser_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
441 	php_http_header_parser_class_entry->create_object = php_http_header_parser_object_new;
442 	php_http_header_parser_object_handlers.offset = XtOffsetOf(php_http_header_parser_object_t, zo);
443 	php_http_header_parser_object_handlers.clone_obj = NULL;
444 	php_http_header_parser_object_handlers.free_obj = php_http_header_parser_object_free;
445 
446 	zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("CLEANUP"), PHP_HTTP_HEADER_PARSER_CLEANUP);
447 
448 	zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_FAILURE"), PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
449 	zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_START"), PHP_HTTP_HEADER_PARSER_STATE_START);
450 	zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_KEY"), PHP_HTTP_HEADER_PARSER_STATE_KEY);
451 	zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE"), PHP_HTTP_HEADER_PARSER_STATE_VALUE);
452 	zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE_EX"), PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
453 	zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_HEADER_DONE"), PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
454 	zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_DONE"), PHP_HTTP_HEADER_PARSER_STATE_DONE);
455 
456 	return SUCCESS;
457 }
458 
459 /*
460  * Local variables:
461  * tab-width: 4
462  * c-basic-offset: 4
463  * End:
464  * vim600: noet sw=4 ts=4 fdm=marker
465  * vim<600: noet sw=4 ts=4
466  */
467 
468