POC for HTTP2 support
[m6w6/ext-http] / php_http_message.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-2014, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #include "php_http_api.h"
14
15 static void message_headers(php_http_message_t *msg, php_http_buffer_t *str);
16
17 zend_bool php_http_message_info_callback(php_http_message_t **message, HashTable **headers, php_http_info_t *info TSRMLS_DC)
18 {
19 php_http_message_t *old = *message;
20
21 /* advance message */
22 if (!old || old->type || zend_hash_num_elements(&old->hdrs)) {
23 (*message) = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
24 (*message)->parent = old;
25 if (headers) {
26 (*headers) = &((*message)->hdrs);
27 }
28 }
29
30 if (info) {
31 php_http_message_set_info(*message, info);
32 }
33
34 return old != *message;
35 }
36
37 php_http_message_t *php_http_message_init(php_http_message_t *message, php_http_message_type_t type, php_http_message_body_t *body TSRMLS_DC)
38 {
39 if (!message) {
40 message = emalloc(sizeof(*message));
41 }
42 memset(message, 0, sizeof(*message));
43 TSRMLS_SET_CTX(message->ts);
44
45 php_http_message_set_type(message, type);
46 message->http.version.major = 1;
47 message->http.version.minor = 1;
48 zend_hash_init(&message->hdrs, 0, NULL, ZVAL_PTR_DTOR, 0);
49 message->body = body ? body : php_http_message_body_init(NULL, NULL TSRMLS_CC);
50
51 return message;
52 }
53
54 php_http_message_t *php_http_message_init_env(php_http_message_t *message, php_http_message_type_t type TSRMLS_DC)
55 {
56 int free_msg = !message;
57 zval *sval, tval;
58 php_http_message_body_t *mbody;
59
60 switch (type) {
61 case PHP_HTTP_REQUEST:
62 mbody = php_http_env_get_request_body(TSRMLS_C);
63 php_http_message_body_addref(mbody);
64 message = php_http_message_init(message, type, mbody TSRMLS_CC);
65 if ((sval = php_http_env_get_server_var(ZEND_STRL("SERVER_PROTOCOL"), 1 TSRMLS_CC)) && !strncmp(Z_STRVAL_P(sval), "HTTP/", lenof("HTTP/"))) {
66 php_http_version_parse(&message->http.version, Z_STRVAL_P(sval) TSRMLS_CC);
67 }
68 if ((sval = php_http_env_get_server_var(ZEND_STRL("REQUEST_METHOD"), 1 TSRMLS_CC))) {
69 message->http.info.request.method = estrdup(Z_STRVAL_P(sval));
70 }
71 if ((sval = php_http_env_get_server_var(ZEND_STRL("REQUEST_URI"), 1 TSRMLS_CC))) {
72 message->http.info.request.url = php_http_url_parse(Z_STRVAL_P(sval), Z_STRLEN_P(sval), ~0 TSRMLS_CC);
73 }
74
75 php_http_env_get_request_headers(&message->hdrs TSRMLS_CC);
76 break;
77
78 case PHP_HTTP_RESPONSE:
79 message = php_http_message_init(NULL, type, NULL TSRMLS_CC);
80 if (!SG(sapi_headers).http_status_line || !php_http_info_parse((php_http_info_t *) &message->http, SG(sapi_headers).http_status_line TSRMLS_CC)) {
81 if (!(message->http.info.response.code = SG(sapi_headers).http_response_code)) {
82 message->http.info.response.code = 200;
83 }
84 message->http.info.response.status = estrdup(php_http_env_get_response_status_for_code(message->http.info.response.code));
85 }
86
87 php_http_env_get_response_headers(&message->hdrs TSRMLS_CC);
88 #if PHP_VERSION_ID >= 50400
89 if (php_output_get_level(TSRMLS_C)) {
90 if (php_output_get_status(TSRMLS_C) & PHP_OUTPUT_SENT) {
91 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch response body, output has already been sent at %s:%d", php_output_get_start_filename(TSRMLS_C), php_output_get_start_lineno(TSRMLS_C));
92 goto error;
93 } else if (SUCCESS != php_output_get_contents(&tval TSRMLS_CC)) {
94 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch response body");
95 goto error;
96 } else {
97 php_http_message_body_append(message->body, Z_STRVAL(tval), Z_STRLEN(tval));
98 zval_dtor(&tval);
99 }
100 }
101 #else
102 if (OG(ob_nesting_level)) {
103 if (php_get_output_start_filename(TSRMLS_C)) {
104 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch response body, output has already been sent at %s:%d", php_get_output_start_filename(TSRMLS_C), php_get_output_start_lineno(TSRMLS_C));
105 goto error;
106 } else if (SUCCESS != php_ob_get_buffer(&tval TSRMLS_CC)) {
107 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch response body");
108 goto error;
109 } else {
110 php_http_message_body_append(message->body, Z_STRVAL(tval), Z_STRLEN(tval));
111 zval_dtor(&tval);
112 }
113 }
114 #endif
115 break;
116
117 default:
118 error:
119 if (free_msg) {
120 if (message) {
121 php_http_message_free(&message);
122 }
123 } else {
124 message = NULL;
125 }
126 break;
127 }
128
129 return message;
130 }
131
132 php_http_message_t *php_http_message_parse(php_http_message_t *msg, const char *str, size_t len, zend_bool greedy TSRMLS_DC)
133 {
134 php_http_message_parser_t p;
135 php_http_buffer_t buf;
136 unsigned flags = PHP_HTTP_MESSAGE_PARSER_CLEANUP;
137 int free_msg;
138
139 php_http_buffer_from_string_ex(&buf, str, len);
140 php_http_message_parser_init(&p TSRMLS_CC);
141
142 if ((free_msg = !msg)) {
143 msg = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
144 }
145
146 if (greedy) {
147 flags |= PHP_HTTP_MESSAGE_PARSER_GREEDY;
148 }
149 if (PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE == php_http_message_parser_parse(&p, &buf, flags, &msg)) {
150 if (free_msg) {
151 php_http_message_free(&msg);
152 }
153 msg = NULL;
154 }
155
156 php_http_message_parser_dtor(&p);
157 php_http_buffer_dtor(&buf);
158
159 return msg;
160 }
161
162 zval *php_http_message_header(php_http_message_t *msg, const char *key_str, size_t key_len, int join)
163 {
164 zval *ret = NULL, **header;
165 char *key;
166 ALLOCA_FLAG(free_key);
167
168 key = do_alloca(key_len + 1, free_key);
169 memcpy(key, key_str, key_len);
170 key[key_len] = '\0';
171 php_http_pretty_key(key, key_len, 1, 1);
172
173 if (SUCCESS == zend_symtable_find(&msg->hdrs, key, key_len + 1, (void *) &header)) {
174 if (join && Z_TYPE_PP(header) == IS_ARRAY) {
175 TSRMLS_FETCH_FROM_CTX(msg->ts);
176
177 ret = php_http_header_value_to_string(*header TSRMLS_CC);
178 } else {
179 Z_ADDREF_PP(header);
180 ret = *header;
181 }
182 }
183
184 free_alloca(key, free_key);
185
186 return ret;
187 }
188
189 zend_bool php_http_message_is_multipart(php_http_message_t *msg, char **boundary)
190 {
191 zval *ct = php_http_message_header(msg, ZEND_STRL("Content-Type"), 1);
192 zend_bool is_multipart = 0;
193 TSRMLS_FETCH_FROM_CTX(msg->ts);
194
195 if (ct) {
196 php_http_params_opts_t popts;
197 HashTable params;
198
199 ZEND_INIT_SYMTABLE(&params);
200 php_http_params_opts_default_get(&popts);
201 popts.input.str = Z_STRVAL_P(ct);
202 popts.input.len = Z_STRLEN_P(ct);
203
204 if (php_http_params_parse(&params, &popts TSRMLS_CC)) {
205 zval **cur, **arg;
206 char *ct_str;
207
208 zend_hash_internal_pointer_reset(&params);
209
210 if (SUCCESS == zend_hash_get_current_data(&params, (void *) &cur)
211 && Z_TYPE_PP(cur) == IS_ARRAY
212 && HASH_KEY_IS_STRING == zend_hash_get_current_key(&params, &ct_str, NULL, 0)
213 ) {
214 if (php_http_match(ct_str, "multipart", PHP_HTTP_MATCH_WORD)) {
215 is_multipart = 1;
216
217 /* get boundary */
218 if (boundary
219 && SUCCESS == zend_hash_find(Z_ARRVAL_PP(cur), ZEND_STRS("arguments"), (void *) &arg)
220 && Z_TYPE_PP(arg) == IS_ARRAY
221 ) {
222 zval **val;
223 HashPosition pos;
224 php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
225
226 FOREACH_KEYVAL(pos, *arg, key, val) {
227 if (key.type == HASH_KEY_IS_STRING && !strcasecmp(key.str, "boundary")) {
228 zval *bnd = php_http_ztyp(IS_STRING, *val);
229
230 if (Z_STRLEN_P(bnd)) {
231 *boundary = estrndup(Z_STRVAL_P(bnd), Z_STRLEN_P(bnd));
232 }
233 zval_ptr_dtor(&bnd);
234 }
235 }
236 }
237 }
238 }
239 }
240 zend_hash_destroy(&params);
241 zval_ptr_dtor(&ct);
242 }
243
244 return is_multipart;
245 }
246
247 /* */
248 void php_http_message_set_type(php_http_message_t *message, php_http_message_type_t type)
249 {
250 /* just act if different */
251 if (type != message->type) {
252
253 /* free request info */
254 switch (message->type) {
255 case PHP_HTTP_REQUEST:
256 PTR_FREE(message->http.info.request.method);
257 PTR_FREE(message->http.info.request.url);
258 break;
259
260 case PHP_HTTP_RESPONSE:
261 PTR_FREE(message->http.info.response.status);
262 break;
263
264 default:
265 break;
266 }
267
268 message->type = type;
269 memset(&message->http, 0, sizeof(message->http));
270 }
271 }
272
273 void php_http_message_set_info(php_http_message_t *message, php_http_info_t *info)
274 {
275 php_http_message_set_type(message, info->type);
276 message->http.version = info->http.version;
277 switch (message->type) {
278 case PHP_HTTP_REQUEST:
279 PTR_SET(PHP_HTTP_INFO(message).request.url, PHP_HTTP_INFO(info).request.url ? php_http_url_copy(PHP_HTTP_INFO(info).request.url, 0) : NULL);
280 PTR_SET(PHP_HTTP_INFO(message).request.method, PHP_HTTP_INFO(info).request.method ? estrdup(PHP_HTTP_INFO(info).request.method) : NULL);
281 break;
282
283 case PHP_HTTP_RESPONSE:
284 PHP_HTTP_INFO(message).response.code = PHP_HTTP_INFO(info).response.code;
285 PTR_SET(PHP_HTTP_INFO(message).response.status, PHP_HTTP_INFO(info).response.status ? estrdup(PHP_HTTP_INFO(info).response.status) : NULL);
286 break;
287
288 default:
289 break;
290 }
291 }
292
293 void php_http_message_update_headers(php_http_message_t *msg)
294 {
295 zval *h;
296 size_t size;
297
298 if (php_http_message_body_stream(msg->body)->readfilters.head) {
299 /* if a read stream filter is attached to the body the caller must also care for the headers */
300 } else if ((size = php_http_message_body_size(msg->body))) {
301 MAKE_STD_ZVAL(h);
302 ZVAL_LONG(h, size);
303 zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), &h, sizeof(zval *), NULL);
304
305 if ((h = php_http_message_header(msg, ZEND_STRL("Transfer-Encoding"), 0))) {
306 zend_hash_update(&msg->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &h, sizeof(zval *), NULL);
307 zend_hash_del(&msg->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding"));
308 }
309
310 if (msg->body->boundary) {
311 char *str;
312 size_t len;
313
314 if (!(h = php_http_message_header(msg, ZEND_STRL("Content-Type"), 1))) {
315 len = spprintf(&str, 0, "multipart/form-data; boundary=\"%s\"", msg->body->boundary);
316 MAKE_STD_ZVAL(h);
317 ZVAL_STRINGL(h, str, len, 0);
318 zend_hash_update(&msg->hdrs, "Content-Type", sizeof("Content-Type"), &h, sizeof(zval *), NULL);
319 } else if (!php_http_match(Z_STRVAL_P(h), "boundary=", PHP_HTTP_MATCH_WORD)) {
320 zval_dtor(h);
321 Z_STRLEN_P(h) = spprintf(&Z_STRVAL_P(h), 0, "%s; boundary=\"%s\"", Z_STRVAL_P(h), msg->body->boundary);
322 zend_hash_update(&msg->hdrs, "Content-Type", sizeof("Content-Type"), &h, sizeof(zval *), NULL);
323 } else {
324 zval_ptr_dtor(&h);
325 }
326 }
327 } else if ((h = php_http_message_header(msg, ZEND_STRL("Content-Length"), 1))) {
328 zval *h_cpy = php_http_ztyp(IS_LONG, h);
329
330 zval_ptr_dtor(&h);
331 if (Z_LVAL_P(h_cpy)) {
332 zend_hash_del(&msg->hdrs, "Content-Length", sizeof("Content-Length"));
333 }
334 zval_ptr_dtor(&h_cpy);
335 }
336 }
337
338 static void message_headers(php_http_message_t *msg, php_http_buffer_t *str)
339 {
340 char *tmp = NULL;
341 TSRMLS_FETCH_FROM_CTX(msg->ts);
342
343 switch (msg->type) {
344 case PHP_HTTP_REQUEST:
345 php_http_buffer_appendf(str, PHP_HTTP_INFO_REQUEST_FMT_ARGS(&msg->http, tmp, PHP_HTTP_CRLF));
346 PTR_FREE(tmp);
347 break;
348
349 case PHP_HTTP_RESPONSE:
350 php_http_buffer_appendf(str, PHP_HTTP_INFO_RESPONSE_FMT_ARGS(&msg->http, tmp, PHP_HTTP_CRLF));
351 PTR_FREE(tmp);
352 break;
353
354 default:
355 break;
356 }
357
358 php_http_message_update_headers(msg);
359 php_http_header_to_string(str, &msg->hdrs TSRMLS_CC);
360 }
361
362 void php_http_message_to_callback(php_http_message_t *msg, php_http_pass_callback_t cb, void *cb_arg)
363 {
364 php_http_buffer_t str;
365
366 php_http_buffer_init_ex(&str, 0x1000, 0);
367 message_headers(msg, &str);
368 cb(cb_arg, str.data, str.used);
369 php_http_buffer_dtor(&str);
370
371 if (php_http_message_body_size(msg->body)) {
372 cb(cb_arg, ZEND_STRL(PHP_HTTP_CRLF));
373 php_http_message_body_to_callback(msg->body, cb, cb_arg, 0, 0);
374 }
375 }
376
377 void php_http_message_to_string(php_http_message_t *msg, char **string, size_t *length)
378 {
379 php_http_buffer_t str;
380 char *data;
381
382 php_http_buffer_init_ex(&str, 0x1000, 0);
383 message_headers(msg, &str);
384 if (php_http_message_body_size(msg->body)) {
385 php_http_buffer_appends(&str, PHP_HTTP_CRLF);
386 php_http_message_body_to_callback(msg->body, (php_http_pass_callback_t) php_http_buffer_append, &str, 0, 0);
387 }
388
389 data = php_http_buffer_data(&str, string, length);
390 if (!string) {
391 efree(data);
392 }
393
394 php_http_buffer_dtor(&str);
395 }
396
397 void php_http_message_serialize(php_http_message_t *message, char **string, size_t *length)
398 {
399 char *buf;
400 php_http_buffer_t str;
401 php_http_message_t *msg;
402
403 php_http_buffer_init(&str);
404
405 msg = message = php_http_message_reverse(message);
406 do {
407 php_http_message_to_callback(message, (php_http_pass_callback_t) php_http_buffer_append, &str);
408 php_http_buffer_appends(&str, PHP_HTTP_CRLF);
409 } while ((message = message->parent));
410 php_http_message_reverse(msg);
411
412 buf = php_http_buffer_data(&str, string, length);
413 if (!string) {
414 efree(buf);
415 }
416
417 php_http_buffer_dtor(&str);
418 }
419
420 php_http_message_t *php_http_message_reverse(php_http_message_t *msg)
421 {
422 int i, c = 0;
423
424 php_http_message_count(c, msg);
425
426 if (c > 1) {
427 php_http_message_t *tmp = msg, **arr;
428
429 arr = ecalloc(c, sizeof(**arr));
430 for (i = 0; i < c; ++i) {
431 arr[i] = tmp;
432 tmp = tmp->parent;
433 }
434 arr[0]->parent = NULL;
435 for (i = 0; i < c-1; ++i) {
436 arr[i+1]->parent = arr[i];
437 }
438
439 msg = arr[c-1];
440 efree(arr);
441 }
442
443 return msg;
444 }
445
446 php_http_message_t *php_http_message_zip(php_http_message_t *one, php_http_message_t *two)
447 {
448 php_http_message_t *dst = php_http_message_copy(one, NULL), *src = php_http_message_copy(two, NULL), *tmp_dst, *tmp_src, *ret = dst;
449
450 while(dst && src) {
451 tmp_dst = dst->parent;
452 tmp_src = src->parent;
453 dst->parent = src;
454 if (tmp_dst) {
455 src->parent = tmp_dst;
456 }
457 src = tmp_src;
458 dst = tmp_dst;
459 }
460
461 return ret;
462 }
463
464 php_http_message_t *php_http_message_copy_ex(php_http_message_t *from, php_http_message_t *to, zend_bool parents)
465 {
466 php_http_message_t *temp, *copy = NULL;
467 php_http_info_t info;
468 TSRMLS_FETCH_FROM_CTX(from->ts);
469
470 if (from) {
471 info.type = from->type;
472 info.http = from->http;
473
474 copy = temp = php_http_message_init(to, 0, php_http_message_body_copy(from->body, NULL) TSRMLS_CC);
475 php_http_message_set_info(temp, &info);
476 zend_hash_copy(&temp->hdrs, &from->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
477
478 if (parents) while (from->parent) {
479 info.type = from->parent->type;
480 info.http = from->parent->http;
481
482 temp->parent = php_http_message_init(NULL, 0, php_http_message_body_copy(from->parent->body, NULL) TSRMLS_CC);
483 php_http_message_set_info(temp->parent, &info);
484 zend_hash_copy(&temp->parent->hdrs, &from->parent->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
485
486 temp = temp->parent;
487 from = from->parent;
488 }
489 }
490
491 return copy;
492 }
493
494 php_http_message_t *php_http_message_copy(php_http_message_t *from, php_http_message_t *to)
495 {
496 return php_http_message_copy_ex(from, to, 1);
497 }
498
499 void php_http_message_dtor(php_http_message_t *message)
500 {
501 if (message) {
502 zend_hash_destroy(&message->hdrs);
503 php_http_message_body_free(&message->body);
504
505 switch (message->type) {
506 case PHP_HTTP_REQUEST:
507 PTR_SET(message->http.info.request.method, NULL);
508 PTR_SET(message->http.info.request.url, NULL);
509 break;
510
511 case PHP_HTTP_RESPONSE:
512 PTR_SET(message->http.info.response.status, NULL);
513 break;
514
515 default:
516 break;
517 }
518 }
519 }
520
521 void php_http_message_free(php_http_message_t **message)
522 {
523 if (*message) {
524 if ((*message)->parent) {
525 php_http_message_free(&(*message)->parent);
526 }
527 php_http_message_dtor(*message);
528 efree(*message);
529 *message = NULL;
530 }
531 }
532
533 static zval *php_http_message_object_read_prop(zval *object, zval *member, int type PHP_HTTP_ZEND_LITERAL_DC TSRMLS_DC);
534 static void php_http_message_object_write_prop(zval *object, zval *member, zval *value PHP_HTTP_ZEND_LITERAL_DC TSRMLS_DC);
535 static HashTable *php_http_message_object_get_props(zval *object TSRMLS_DC);
536
537 static zend_object_handlers php_http_message_object_handlers;
538 static HashTable php_http_message_object_prophandlers;
539
540 typedef void (*php_http_message_object_prophandler_func_t)(php_http_message_object_t *o, zval *v TSRMLS_DC);
541
542 typedef struct php_http_message_object_prophandler {
543 php_http_message_object_prophandler_func_t read;
544 php_http_message_object_prophandler_func_t write;
545 } php_http_message_object_prophandler_t;
546
547 static STATUS php_http_message_object_add_prophandler(const char *prop_str, size_t prop_len, php_http_message_object_prophandler_func_t read, php_http_message_object_prophandler_func_t write) {
548 php_http_message_object_prophandler_t h = { read, write };
549 return zend_hash_add(&php_http_message_object_prophandlers, prop_str, prop_len + 1, (void *) &h, sizeof(h), NULL);
550 }
551 static STATUS php_http_message_object_get_prophandler(const char *prop_str, size_t prop_len, php_http_message_object_prophandler_t **handler) {
552 return zend_hash_find(&php_http_message_object_prophandlers, prop_str, prop_len + 1, (void *) handler);
553 }
554 static void php_http_message_object_prophandler_get_type(php_http_message_object_t *obj, zval *return_value TSRMLS_DC) {
555 RETVAL_LONG(obj->message->type);
556 }
557 static void php_http_message_object_prophandler_set_type(php_http_message_object_t *obj, zval *value TSRMLS_DC) {
558 zval *cpy = php_http_ztyp(IS_LONG, value);
559 php_http_message_set_type(obj->message, Z_LVAL_P(cpy));
560 zval_ptr_dtor(&cpy);
561 }
562 static void php_http_message_object_prophandler_get_request_method(php_http_message_object_t *obj, zval *return_value TSRMLS_DC) {
563 if (PHP_HTTP_MESSAGE_TYPE(REQUEST, obj->message) && obj->message->http.info.request.method) {
564 RETVAL_STRING(obj->message->http.info.request.method, 1);
565 } else {
566 RETVAL_NULL();
567 }
568 }
569 static void php_http_message_object_prophandler_set_request_method(php_http_message_object_t *obj, zval *value TSRMLS_DC) {
570 if (PHP_HTTP_MESSAGE_TYPE(REQUEST, obj->message)) {
571 zval *cpy = php_http_ztyp(IS_STRING, value);
572 PTR_SET(obj->message->http.info.request.method, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
573 zval_ptr_dtor(&cpy);
574 }
575 }
576 static void php_http_message_object_prophandler_get_request_url(php_http_message_object_t *obj, zval *return_value TSRMLS_DC) {
577 char *url_str;
578 size_t url_len;
579
580 if (PHP_HTTP_MESSAGE_TYPE(REQUEST, obj->message) && obj->message->http.info.request.url && php_http_url_to_string(obj->message->http.info.request.url, &url_str, &url_len, 0)) {
581 RETVAL_STRINGL(url_str, url_len, 0);
582 } else {
583 RETVAL_NULL();
584 }
585 }
586 static void php_http_message_object_prophandler_set_request_url(php_http_message_object_t *obj, zval *value TSRMLS_DC) {
587 if (PHP_HTTP_MESSAGE_TYPE(REQUEST, obj->message)) {
588 PTR_SET(obj->message->http.info.request.url, php_http_url_from_zval(value, ~0 TSRMLS_CC));
589 }
590 }
591 static void php_http_message_object_prophandler_get_response_status(php_http_message_object_t *obj, zval *return_value TSRMLS_DC) {
592 if (PHP_HTTP_MESSAGE_TYPE(RESPONSE, obj->message) && obj->message->http.info.response.status) {
593 RETVAL_STRING(obj->message->http.info.response.status, 1);
594 } else {
595 RETVAL_NULL();
596 }
597 }
598 static void php_http_message_object_prophandler_set_response_status(php_http_message_object_t *obj, zval *value TSRMLS_DC) {
599 if (PHP_HTTP_MESSAGE_TYPE(RESPONSE, obj->message)) {
600 zval *cpy = php_http_ztyp(IS_STRING, value);
601 PTR_SET(obj->message->http.info.response.status, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
602 zval_ptr_dtor(&cpy);
603 }
604 }
605 static void php_http_message_object_prophandler_get_response_code(php_http_message_object_t *obj, zval *return_value TSRMLS_DC) {
606 if (PHP_HTTP_MESSAGE_TYPE(RESPONSE, obj->message)) {
607 RETVAL_LONG(obj->message->http.info.response.code);
608 } else {
609 RETVAL_NULL();
610 }
611 }
612 static void php_http_message_object_prophandler_set_response_code(php_http_message_object_t *obj, zval *value TSRMLS_DC) {
613 if (PHP_HTTP_MESSAGE_TYPE(RESPONSE, obj->message)) {
614 zval *cpy = php_http_ztyp(IS_LONG, value);
615 obj->message->http.info.response.code = Z_LVAL_P(cpy);
616 PTR_SET(obj->message->http.info.response.status, estrdup(php_http_env_get_response_status_for_code(obj->message->http.info.response.code)));
617 zval_ptr_dtor(&cpy);
618 }
619 }
620 static void php_http_message_object_prophandler_get_http_version(php_http_message_object_t *obj, zval *return_value TSRMLS_DC) {
621 char *version_str;
622 size_t version_len;
623
624 php_http_version_to_string(&obj->message->http.version, &version_str, &version_len, NULL, NULL TSRMLS_CC);
625 RETVAL_STRINGL(version_str, version_len, 0);
626 }
627 static void php_http_message_object_prophandler_set_http_version(php_http_message_object_t *obj, zval *value TSRMLS_DC) {
628 zval *cpy = php_http_ztyp(IS_STRING, value);
629 php_http_version_parse(&obj->message->http.version, Z_STRVAL_P(cpy) TSRMLS_CC);
630 zval_ptr_dtor(&cpy);
631 }
632 static void php_http_message_object_prophandler_get_headers(php_http_message_object_t *obj, zval *return_value TSRMLS_DC) {
633 array_init(return_value);
634 zend_hash_copy(Z_ARRVAL_P(return_value), &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
635 }
636 static void php_http_message_object_prophandler_set_headers(php_http_message_object_t *obj, zval *value TSRMLS_DC) {
637 zval *cpy = php_http_ztyp(IS_ARRAY, value);
638
639 zend_hash_clean(&obj->message->hdrs);
640 zend_hash_copy(&obj->message->hdrs, Z_ARRVAL_P(cpy), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
641 zval_ptr_dtor(&cpy);
642 }
643 static void php_http_message_object_prophandler_get_body(php_http_message_object_t *obj, zval *return_value TSRMLS_DC) {
644 if (obj->body) {
645 RETVAL_OBJVAL(obj->body->zv, 1);
646 } else {
647 RETVAL_NULL();
648 }
649 }
650 static void php_http_message_object_prophandler_set_body(php_http_message_object_t *obj, zval *value TSRMLS_DC) {
651 php_http_message_object_set_body(obj, value TSRMLS_CC);
652 }
653 static void php_http_message_object_prophandler_get_parent_message(php_http_message_object_t *obj, zval *return_value TSRMLS_DC) {
654 if (obj->message->parent) {
655 RETVAL_OBJVAL(obj->parent->zv, 1);
656 } else {
657 RETVAL_NULL();
658 }
659 }
660 static void php_http_message_object_prophandler_set_parent_message(php_http_message_object_t *obj, zval *value TSRMLS_DC) {
661 if (Z_TYPE_P(value) == IS_OBJECT && instanceof_function(Z_OBJCE_P(value), php_http_message_class_entry TSRMLS_CC)) {
662 php_http_message_object_t *parent_obj = zend_object_store_get_object(value TSRMLS_CC);
663
664 if (obj->message->parent) {
665 zend_objects_store_del_ref_by_handle(obj->parent->zv.handle TSRMLS_CC);
666 }
667 Z_OBJ_ADDREF_P(value);
668 obj->parent = parent_obj;
669 obj->message->parent = parent_obj->message;
670 }
671 }
672
673 #define PHP_HTTP_MESSAGE_OBJECT_INIT(obj) \
674 do { \
675 if (!obj->message) { \
676 obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC); \
677 } \
678 } while(0)
679
680
681 void php_http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC)
682 {
683 int i = 0;
684 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
685
686 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
687
688 /* count */
689 php_http_message_count(i, obj->message);
690
691 if (i > 1) {
692 php_http_message_object_t **objects;
693 int last;
694
695 objects = ecalloc(i, sizeof(**objects));
696
697 /* we are the first message */
698 objects[0] = obj;
699
700 /* fetch parents */
701 for (i = 1; obj->parent; ++i) {
702 objects[i] = obj = obj->parent;
703 }
704
705 /* reorder parents */
706 for (last = --i; i; --i) {
707 objects[i]->message->parent = objects[i-1]->message;
708 objects[i]->parent = objects[i-1];
709 }
710
711 objects[0]->message->parent = NULL;
712 objects[0]->parent = NULL;
713
714 /* add ref, because we previously have not been a parent message */
715 Z_OBJ_ADDREF_P(getThis());
716 RETVAL_OBJVAL(objects[last]->zv, 0);
717
718 efree(objects);
719 } else {
720 RETURN_ZVAL(getThis(), 1, 0);
721 }
722 }
723
724 void php_http_message_object_prepend(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC)
725 {
726 zval m;
727 php_http_message_t *save_parent_msg = NULL;
728 php_http_message_object_t *save_parent_obj = NULL, *obj = zend_object_store_get_object(this_ptr TSRMLS_CC);
729 php_http_message_object_t *prepend_obj = zend_object_store_get_object(prepend TSRMLS_CC);
730
731 INIT_PZVAL(&m);
732 m.type = IS_OBJECT;
733
734 if (!top) {
735 save_parent_obj = obj->parent;
736 save_parent_msg = obj->message->parent;
737 } else {
738 /* iterate to the most parent object */
739 while (obj->parent) {
740 obj = obj->parent;
741 }
742 }
743
744 /* prepend */
745 obj->parent = prepend_obj;
746 obj->message->parent = prepend_obj->message;
747
748 /* add ref */
749 zend_objects_store_add_ref(prepend TSRMLS_CC);
750
751 if (!top) {
752 prepend_obj->parent = save_parent_obj;
753 prepend_obj->message->parent = save_parent_msg;
754 }
755 }
756
757 STATUS php_http_message_object_set_body(php_http_message_object_t *msg_obj, zval *zbody TSRMLS_DC)
758 {
759 zval *tmp = NULL;
760 php_stream *s;
761 zend_object_value ov;
762 php_http_message_body_t *body;
763 php_http_message_body_object_t *body_obj;
764
765 switch (Z_TYPE_P(zbody)) {
766 case IS_RESOURCE:
767 php_stream_from_zval_no_verify(s, &zbody);
768 if (!s) {
769 php_http_throw(unexpected_val, "The stream is not a valid resource", NULL);
770 return FAILURE;
771 }
772
773 is_resource:
774
775 body = php_http_message_body_init(NULL, s TSRMLS_CC);
776 if (SUCCESS != php_http_new(&ov, php_http_message_body_class_entry, (php_http_new_t) php_http_message_body_object_new_ex, NULL, body, NULL TSRMLS_CC)) {
777 php_http_message_body_free(&body);
778 return FAILURE;
779 }
780 MAKE_STD_ZVAL(tmp);
781 ZVAL_OBJVAL(tmp, ov, 0);
782 zbody = tmp;
783 break;
784
785 case IS_OBJECT:
786 if (instanceof_function(Z_OBJCE_P(zbody), php_http_message_body_class_entry TSRMLS_CC)) {
787 Z_OBJ_ADDREF_P(zbody);
788 break;
789 }
790 /* no break */
791
792 default:
793 tmp = php_http_ztyp(IS_STRING, zbody);
794 s = php_stream_temp_new();
795 php_stream_write(s, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
796 zval_ptr_dtor(&tmp);
797 tmp = NULL;
798 goto is_resource;
799
800 }
801
802 body_obj = zend_object_store_get_object(zbody TSRMLS_CC);
803 if (!body_obj->body) {
804 body_obj->body = php_http_message_body_init(NULL, NULL TSRMLS_CC);
805 }
806 if (msg_obj->body) {
807 zend_objects_store_del_ref_by_handle(msg_obj->body->zv.handle TSRMLS_CC);
808 }
809 if (msg_obj->message) {
810 php_http_message_body_free(&msg_obj->message->body);
811 msg_obj->message->body = php_http_message_body_init(&body_obj->body, NULL TSRMLS_CC);
812 } else {
813 msg_obj->message = php_http_message_init(NULL, 0, php_http_message_body_init(&body_obj->body, NULL TSRMLS_CC) TSRMLS_CC);
814 }
815 msg_obj->body = body_obj;
816
817 if (tmp) {
818 FREE_ZVAL(tmp);
819 }
820 return SUCCESS;
821 }
822
823 STATUS php_http_message_object_init_body_object(php_http_message_object_t *obj)
824 {
825 TSRMLS_FETCH_FROM_CTX(obj->message->ts);
826
827 php_http_message_body_addref(obj->message->body);
828 return php_http_new(NULL, php_http_message_body_class_entry, (php_http_new_t) php_http_message_body_object_new_ex, NULL, obj->message->body, (void *) &obj->body TSRMLS_CC);
829 }
830
831 zend_object_value php_http_message_object_new(zend_class_entry *ce TSRMLS_DC)
832 {
833 return php_http_message_object_new_ex(ce, NULL, NULL TSRMLS_CC);
834 }
835
836 zend_object_value php_http_message_object_new_ex(zend_class_entry *ce, php_http_message_t *msg, php_http_message_object_t **ptr TSRMLS_DC)
837 {
838 php_http_message_object_t *o;
839
840 o = ecalloc(1, sizeof(php_http_message_object_t));
841 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
842 object_properties_init((zend_object *) o, ce);
843
844 if (ptr) {
845 *ptr = o;
846 }
847
848 if (msg) {
849 o->message = msg;
850 if (msg->parent) {
851 php_http_message_object_new_ex(ce, msg->parent, &o->parent TSRMLS_CC);
852 }
853 php_http_message_body_object_new_ex(php_http_message_body_class_entry, php_http_message_body_init(&msg->body, NULL TSRMLS_CC), &o->body TSRMLS_CC);
854 }
855
856 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_http_message_object_free, NULL TSRMLS_CC);
857 o->zv.handlers = &php_http_message_object_handlers;
858
859 return o->zv;
860 }
861
862 zend_object_value php_http_message_object_clone(zval *this_ptr TSRMLS_DC)
863 {
864 zend_object_value new_ov;
865 php_http_message_object_t *new_obj = NULL;
866 php_http_message_object_t *old_obj = zend_object_store_get_object(this_ptr TSRMLS_CC);
867
868 new_ov = php_http_message_object_new_ex(old_obj->zo.ce, php_http_message_copy(old_obj->message, NULL), &new_obj TSRMLS_CC);
869 zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
870
871 return new_ov;
872 }
873
874 void php_http_message_object_free(void *object TSRMLS_DC)
875 {
876 php_http_message_object_t *o = (php_http_message_object_t *) object;
877
878 if (o->iterator) {
879 zval_ptr_dtor(&o->iterator);
880 o->iterator = NULL;
881 }
882 if (o->message) {
883 /* do NOT free recursivly */
884 php_http_message_dtor(o->message);
885 efree(o->message);
886 o->message = NULL;
887 }
888 if (o->parent) {
889 zend_objects_store_del_ref_by_handle(o->parent->zv.handle TSRMLS_CC);
890 o->parent = NULL;
891 }
892 if (o->body) {
893 zend_objects_store_del_ref_by_handle(o->body->zv.handle TSRMLS_CC);
894 o->body = NULL;
895 }
896 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
897 efree(o);
898 }
899
900 static zval *php_http_message_object_read_prop(zval *object, zval *member, int type PHP_HTTP_ZEND_LITERAL_DC TSRMLS_DC)
901 {
902 php_http_message_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
903 php_http_message_object_prophandler_t *handler;
904 zval *return_value, *copy = php_http_ztyp(IS_STRING, member);
905
906 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
907
908 if (SUCCESS == php_http_message_object_get_prophandler(Z_STRVAL_P(copy), Z_STRLEN_P(copy), &handler)) {
909 ALLOC_ZVAL(return_value);
910 Z_SET_REFCOUNT_P(return_value, 0);
911 Z_UNSET_ISREF_P(return_value);
912
913 if (type == BP_VAR_R) {
914 handler->read(obj, return_value TSRMLS_CC);
915 } else {
916 php_property_proxy_t *proxy = php_property_proxy_init(object, Z_STRVAL_P(copy), Z_STRLEN_P(copy) TSRMLS_CC);
917 RETVAL_OBJVAL(php_property_proxy_object_new_ex(php_property_proxy_get_class_entry(), proxy, NULL TSRMLS_CC), 0);
918 }
919 } else {
920 return_value = zend_get_std_object_handlers()->read_property(object, member, type PHP_HTTP_ZEND_LITERAL_CC TSRMLS_CC);
921 }
922
923 zval_ptr_dtor(&copy);
924
925 return return_value;
926 }
927
928 static void php_http_message_object_write_prop(zval *object, zval *member, zval *value PHP_HTTP_ZEND_LITERAL_DC TSRMLS_DC)
929 {
930 php_http_message_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
931 php_http_message_object_prophandler_t *handler;
932 zval *copy = php_http_ztyp(IS_STRING, member);
933
934 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
935
936 if (SUCCESS == php_http_message_object_get_prophandler(Z_STRVAL_P(copy), Z_STRLEN_P(copy), &handler)) {
937 handler->write(obj, value TSRMLS_CC);
938 } else {
939 zend_get_std_object_handlers()->write_property(object, member, value PHP_HTTP_ZEND_LITERAL_CC TSRMLS_CC);
940 }
941
942 zval_ptr_dtor(&copy);
943 }
944
945 static HashTable *php_http_message_object_get_props(zval *object TSRMLS_DC)
946 {
947 zval *headers;
948 php_http_message_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
949 HashTable *props = zend_get_std_object_handlers()->get_properties(object TSRMLS_CC);
950 zval array, *parent, *body;
951 char *ver_str, *url_str = NULL;
952 size_t ver_len, url_len = 0;
953
954 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
955 INIT_PZVAL_ARRAY(&array, props);
956
957 #define ASSOC_PROP(ptype, n, val) \
958 do { \
959 zend_property_info *pi; \
960 if (SUCCESS == zend_hash_find(&obj->zo.ce->properties_info, n, sizeof(n), (void *) &pi)) { \
961 add_assoc_ ##ptype## _ex(&array, pi->name, pi->name_length + 1, val); \
962 } \
963 } while(0) \
964
965 #define ASSOC_STRING(name, val) ASSOC_STRINGL(name, val, strlen(val))
966 #define ASSOC_STRINGL(name, val, len) ASSOC_STRINGL_EX(name, val, len, 1)
967 #define ASSOC_STRINGL_EX(n, val, len, cpy) \
968 do { \
969 zend_property_info *pi; \
970 if (SUCCESS == zend_hash_find(&obj->zo.ce->properties_info, n, sizeof(n), (void *) &pi)) { \
971 add_assoc_stringl_ex(&array, pi->name, pi->name_length + 1, val, len, cpy); \
972 } \
973 } while(0)
974
975 ASSOC_PROP(long, "type", obj->message->type);
976 ver_len = spprintf(&ver_str, 0, "%u.%u", obj->message->http.version.major, obj->message->http.version.minor);
977 ASSOC_STRINGL_EX("httpVersion", ver_str, ver_len, 0);
978
979 switch (obj->message->type) {
980 case PHP_HTTP_REQUEST:
981 ASSOC_PROP(long, "responseCode", 0);
982 ASSOC_STRINGL("responseStatus", "", 0);
983 ASSOC_STRING("requestMethod", STR_PTR(obj->message->http.info.request.method));
984 if (obj->message->http.info.request.url) {
985 php_http_url_to_string(obj->message->http.info.request.url, &url_str, &url_len, 0);
986 ASSOC_STRINGL_EX("requestUrl", url_str, url_len, 0);
987 } else {
988 ASSOC_STRINGL("requestUrl", "", 0);
989 }
990
991 break;
992
993 case PHP_HTTP_RESPONSE:
994 ASSOC_PROP(long, "responseCode", obj->message->http.info.response.code);
995 ASSOC_STRING("responseStatus", STR_PTR(obj->message->http.info.response.status));
996 ASSOC_STRINGL("requestMethod", "", 0);
997 ASSOC_STRINGL("requestUrl", "", 0);
998 break;
999
1000 case PHP_HTTP_NONE:
1001 default:
1002 ASSOC_PROP(long, "responseCode", 0);
1003 ASSOC_STRINGL("responseStatus", "", 0);
1004 ASSOC_STRINGL("requestMethod", "", 0);
1005 ASSOC_STRINGL("requestUrl", "", 0);
1006 break;
1007 }
1008
1009 MAKE_STD_ZVAL(headers);
1010 array_init(headers);
1011 zend_hash_copy(Z_ARRVAL_P(headers), &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
1012 ASSOC_PROP(zval, "headers", headers);
1013
1014 MAKE_STD_ZVAL(body);
1015 if (obj->body) {
1016 ZVAL_OBJVAL(body, obj->body->zv, 1);
1017 } else {
1018 ZVAL_NULL(body);
1019 }
1020 ASSOC_PROP(zval, "body", body);
1021
1022 MAKE_STD_ZVAL(parent);
1023 if (obj->message->parent) {
1024 ZVAL_OBJVAL(parent, obj->parent->zv, 1);
1025 } else {
1026 ZVAL_NULL(parent);
1027 }
1028 ASSOC_PROP(zval, "parentMessage", parent);
1029
1030 return props;
1031 }
1032
1033 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage___construct, 0, 0, 0)
1034 ZEND_ARG_INFO(0, message)
1035 ZEND_ARG_INFO(0, greedy)
1036 ZEND_END_ARG_INFO();
1037 static PHP_METHOD(HttpMessage, __construct)
1038 {
1039 zend_bool greedy = 1;
1040 zval *zmessage = NULL;
1041 php_http_message_t *msg = NULL;
1042 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1043 zend_error_handling zeh;
1044
1045 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!b", &zmessage, &greedy), invalid_arg, return);
1046
1047 zend_replace_error_handling(EH_THROW, php_http_exception_bad_message_class_entry, &zeh TSRMLS_CC);
1048 if (zmessage && Z_TYPE_P(zmessage) == IS_RESOURCE) {
1049 php_stream *s;
1050 php_http_message_parser_t p;
1051 zend_error_handling zeh;
1052
1053 zend_replace_error_handling(EH_THROW, php_http_exception_unexpected_val_class_entry, &zeh TSRMLS_CC);
1054 php_stream_from_zval(s, &zmessage);
1055 zend_restore_error_handling(&zeh TSRMLS_CC);
1056
1057 if (s && php_http_message_parser_init(&p TSRMLS_CC)) {
1058 unsigned flags = (greedy ? PHP_HTTP_MESSAGE_PARSER_GREEDY : 0);
1059 php_http_buffer_t buf;
1060
1061 php_http_buffer_init_ex(&buf, 0x1000, PHP_HTTP_BUFFER_INIT_PREALLOC);
1062 if (PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE == php_http_message_parser_parse_stream(&p, &buf, s, flags, &msg)) {
1063 if (!EG(exception)) {
1064 php_http_throw(bad_message, "Could not parse message from stream", NULL);
1065 }
1066 }
1067 php_http_buffer_dtor(&buf);
1068 php_http_message_parser_dtor(&p);
1069 }
1070
1071 if (!msg && !EG(exception)) {
1072 php_http_throw(bad_message, "Empty message received from stream", NULL);
1073 }
1074 } else if (zmessage) {
1075 zmessage = php_http_ztyp(IS_STRING, zmessage);
1076 msg = php_http_message_parse(NULL, Z_STRVAL_P(zmessage), Z_STRLEN_P(zmessage), greedy TSRMLS_CC);
1077
1078 if (!msg && !EG(exception)) {
1079 php_http_throw(bad_message, "Could not parse message: %.*s", MIN(25, Z_STRLEN_P(zmessage)), Z_STRVAL_P(zmessage));
1080 }
1081 zval_ptr_dtor(&zmessage);
1082 }
1083
1084 if (msg) {
1085 php_http_message_dtor(obj->message);
1086 obj->message = msg;
1087 if (obj->message->parent) {
1088 php_http_message_object_new_ex(Z_OBJCE_P(getThis()), obj->message->parent, &obj->parent TSRMLS_CC);
1089 }
1090 }
1091 zend_restore_error_handling(&zeh TSRMLS_CC);
1092 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1093 }
1094
1095 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getBody, 0, 0, 0)
1096 ZEND_END_ARG_INFO();
1097 static PHP_METHOD(HttpMessage, getBody)
1098 {
1099 php_http_message_object_t *obj;
1100
1101 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
1102
1103 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1104
1105 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1106
1107 if (!obj->body) {
1108 php_http_message_object_init_body_object(obj);
1109
1110 }
1111 if (obj->body) {
1112 RETVAL_OBJVAL(obj->body->zv, 1);
1113 }
1114 }
1115
1116 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_setBody, 0, 0, 1)
1117 ZEND_ARG_OBJ_INFO(0, body, http\\Message\\Body, 0)
1118 ZEND_END_ARG_INFO();
1119 static PHP_METHOD(HttpMessage, setBody)
1120 {
1121 zval *zbody;
1122
1123 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zbody, php_http_message_body_class_entry)) {
1124 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1125
1126 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1127 php_http_message_object_prophandler_set_body(obj, zbody TSRMLS_CC);
1128 }
1129 RETVAL_ZVAL(getThis(), 1, 0);
1130 }
1131
1132 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_addBody, 0, 0, 1)
1133 ZEND_ARG_OBJ_INFO(0, body, http\\Message\\Body, 0)
1134 ZEND_END_ARG_INFO();
1135 static PHP_METHOD(HttpMessage, addBody)
1136 {
1137 zval *new_body;
1138
1139 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &new_body, php_http_message_body_class_entry)) {
1140 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1141 php_http_message_body_object_t *new_obj = zend_object_store_get_object(new_body TSRMLS_CC);
1142
1143 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1144 php_http_message_body_to_callback(new_obj->body, (php_http_pass_callback_t) php_http_message_body_append, obj->message->body, 0, 0);
1145 }
1146 RETVAL_ZVAL(getThis(), 1, 0);
1147 }
1148
1149 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getHeader, 0, 0, 1)
1150 ZEND_ARG_INFO(0, header)
1151 ZEND_ARG_INFO(0, into_class)
1152 ZEND_END_ARG_INFO();
1153 static PHP_METHOD(HttpMessage, getHeader)
1154 {
1155 char *header_str;
1156 int header_len;
1157 zend_class_entry *header_ce = NULL;
1158
1159 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|C!", &header_str, &header_len, &header_ce)) {
1160 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1161 zval *header;
1162
1163 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1164
1165 if ((header = php_http_message_header(obj->message, header_str, header_len, 0))) {
1166 if (!header_ce) {
1167 RETURN_ZVAL(header, 1, 1);
1168 } else if (instanceof_function(header_ce, php_http_header_class_entry TSRMLS_CC)) {
1169 zval *header_name, **argv[2];
1170
1171 MAKE_STD_ZVAL(header_name);
1172 ZVAL_STRINGL(header_name, header_str, header_len, 1);
1173 Z_ADDREF_P(header);
1174
1175 argv[0] = &header_name;
1176 argv[1] = &header;
1177
1178 object_init_ex(return_value, header_ce);
1179 php_http_method_call(return_value, ZEND_STRL("__construct"), 2, argv, NULL TSRMLS_CC);
1180
1181 zval_ptr_dtor(&header_name);
1182 zval_ptr_dtor(&header);
1183
1184 return;
1185 } else {
1186 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class '%s' is not as descendant of http\\Header", header_ce->name);
1187 }
1188 }
1189 }
1190 RETURN_FALSE;
1191 }
1192
1193 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getHeaders, 0, 0, 0)
1194 ZEND_END_ARG_INFO();
1195 static PHP_METHOD(HttpMessage, getHeaders)
1196 {
1197 if (SUCCESS == zend_parse_parameters_none()) {
1198 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1199
1200 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1201
1202 array_init(return_value);
1203 array_copy(&obj->message->hdrs, Z_ARRVAL_P(return_value));
1204 }
1205 }
1206
1207 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_setHeader, 0, 0, 1)
1208 ZEND_ARG_INFO(0, header)
1209 ZEND_ARG_INFO(0, value)
1210 ZEND_END_ARG_INFO();
1211 static PHP_METHOD(HttpMessage, setHeader)
1212 {
1213 zval *zvalue = NULL;
1214 char *name_str;
1215 int name_len;
1216
1217 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z!", &name_str, &name_len, &zvalue)) {
1218 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1219 char *name = php_http_pretty_key(estrndup(name_str, name_len), name_len, 1, 1);
1220
1221 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1222
1223 if (!zvalue) {
1224 zend_symtable_del(&obj->message->hdrs, name, name_len + 1);
1225 } else {
1226 Z_ADDREF_P(zvalue);
1227 zend_symtable_update(&obj->message->hdrs, name, name_len + 1, &zvalue, sizeof(void *), NULL);
1228 }
1229 efree(name);
1230 }
1231 RETVAL_ZVAL(getThis(), 1, 0);
1232 }
1233
1234 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_setHeaders, 0, 0, 1)
1235 ZEND_ARG_ARRAY_INFO(0, headers, 1)
1236 ZEND_END_ARG_INFO();
1237 static PHP_METHOD(HttpMessage, setHeaders)
1238 {
1239 zval *new_headers = NULL;
1240
1241 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &new_headers)) {
1242 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1243
1244 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1245
1246 zend_hash_clean(&obj->message->hdrs);
1247 if (new_headers) {
1248 array_join(Z_ARRVAL_P(new_headers), &obj->message->hdrs, 0, ARRAY_JOIN_PRETTIFY|ARRAY_JOIN_STRONLY);
1249 }
1250 }
1251 RETVAL_ZVAL(getThis(), 1, 0);
1252 }
1253
1254 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_addHeader, 0, 0, 2)
1255 ZEND_ARG_INFO(0, header)
1256 ZEND_ARG_INFO(0, value)
1257 ZEND_END_ARG_INFO();
1258 static PHP_METHOD(HttpMessage, addHeader)
1259 {
1260 zval *zvalue;
1261 char *name_str;
1262 int name_len;
1263
1264 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name_str, &name_len, &zvalue)) {
1265 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1266 char *name = php_http_pretty_key(estrndup(name_str, name_len), name_len, 1, 1);
1267 zval *header;
1268
1269 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1270
1271 Z_ADDREF_P(zvalue);
1272 if ((header = php_http_message_header(obj->message, name, name_len, 0))) {
1273 convert_to_array(header);
1274 zend_hash_next_index_insert(Z_ARRVAL_P(header), &zvalue, sizeof(void *), NULL);
1275 zval_ptr_dtor(&header);
1276 } else {
1277 zend_symtable_update(&obj->message->hdrs, name, name_len + 1, &zvalue, sizeof(void *), NULL);
1278 }
1279 efree(name);
1280 }
1281 RETVAL_ZVAL(getThis(), 1, 0);
1282 }
1283
1284 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_addHeaders, 0, 0, 1)
1285 ZEND_ARG_ARRAY_INFO(0, headers, 0)
1286 ZEND_ARG_INFO(0, append)
1287 ZEND_END_ARG_INFO();
1288 static PHP_METHOD(HttpMessage, addHeaders)
1289 {
1290 zval *new_headers;
1291 zend_bool append = 0;
1292
1293 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &new_headers, &append)) {
1294 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1295
1296 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1297
1298 array_join(Z_ARRVAL_P(new_headers), &obj->message->hdrs, append, ARRAY_JOIN_STRONLY|ARRAY_JOIN_PRETTIFY);
1299 }
1300 RETVAL_ZVAL(getThis(), 1, 0);
1301 }
1302
1303 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getType, 0, 0, 0)
1304 ZEND_END_ARG_INFO();
1305 static PHP_METHOD(HttpMessage, getType)
1306 {
1307 if (SUCCESS == zend_parse_parameters_none()) {
1308 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1309
1310 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1311
1312 RETURN_LONG(obj->message->type);
1313 }
1314 }
1315
1316 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_setType, 0, 0, 1)
1317 ZEND_ARG_INFO(0, type)
1318 ZEND_END_ARG_INFO();
1319 static PHP_METHOD(HttpMessage, setType)
1320 {
1321 long type;
1322
1323 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type)) {
1324 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1325
1326 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1327
1328 php_http_message_set_type(obj->message, type);
1329 }
1330 RETVAL_ZVAL(getThis(), 1, 0);
1331 }
1332
1333 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getInfo, 0, 0, 0)
1334 ZEND_END_ARG_INFO();
1335 static PHP_METHOD(HttpMessage, getInfo)
1336 {
1337 if (SUCCESS == zend_parse_parameters_none()) {
1338 char *tmp = NULL;
1339 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1340
1341 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1342
1343 switch (obj->message->type) {
1344 case PHP_HTTP_REQUEST:
1345 Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, PHP_HTTP_INFO_REQUEST_FMT_ARGS(&obj->message->http, tmp, ""));
1346 PTR_FREE(tmp);
1347 break;
1348 case PHP_HTTP_RESPONSE:
1349 Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, PHP_HTTP_INFO_RESPONSE_FMT_ARGS(&obj->message->http, tmp, ""));
1350 PTR_FREE(tmp);
1351 break;
1352 default:
1353 RETURN_NULL();
1354 break;
1355 }
1356 Z_TYPE_P(return_value) = IS_STRING;
1357 return;
1358 }
1359 }
1360
1361 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_setInfo, 0, 0, 1)
1362 ZEND_ARG_INFO(0, http_info)
1363 ZEND_END_ARG_INFO();
1364 static PHP_METHOD(HttpMessage, setInfo)
1365 {
1366 char *str;
1367 int len;
1368 php_http_message_object_t *obj;
1369 php_http_info_t inf;
1370
1371 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len), invalid_arg, return);
1372
1373 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1374 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1375
1376 if (!php_http_info_parse(&inf, str TSRMLS_CC)) {
1377 php_http_throw(bad_header, "Could not parse message info '%s'", str);
1378 return;
1379 }
1380
1381 php_http_message_set_info(obj->message, &inf);
1382 php_http_info_dtor(&inf);
1383
1384 RETVAL_ZVAL(getThis(), 1, 0);
1385 }
1386
1387 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getHttpVersion, 0, 0, 0)
1388 ZEND_END_ARG_INFO();
1389 static PHP_METHOD(HttpMessage, getHttpVersion)
1390 {
1391 if (SUCCESS == zend_parse_parameters_none()) {
1392 char *str;
1393 size_t len;
1394 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1395
1396 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1397
1398 php_http_version_to_string(&obj->message->http.version, &str, &len, NULL, NULL TSRMLS_CC);
1399 RETURN_STRINGL(str, len, 0);
1400 }
1401 }
1402
1403 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_setHttpVersion, 0, 0, 1)
1404 ZEND_ARG_INFO(0, http_version)
1405 ZEND_END_ARG_INFO();
1406 static PHP_METHOD(HttpMessage, setHttpVersion)
1407 {
1408 char *v_str;
1409 int v_len;
1410 php_http_version_t version;
1411 php_http_message_object_t *obj;
1412
1413 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &v_str, &v_len), invalid_arg, return);
1414
1415 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1416 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1417
1418 php_http_expect(php_http_version_parse(&version, v_str TSRMLS_CC), unexpected_val, return);
1419
1420 obj->message->http.version = version;
1421
1422 RETVAL_ZVAL(getThis(), 1, 0);
1423 }
1424
1425 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getResponseCode, 0, 0, 0)
1426 ZEND_END_ARG_INFO();
1427 static PHP_METHOD(HttpMessage, getResponseCode)
1428 {
1429 if (SUCCESS == zend_parse_parameters_none()) {
1430 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1431
1432 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1433
1434 if (obj->message->type != PHP_HTTP_RESPONSE) {
1435 php_error_docref(NULL TSRMLS_CC, E_WARNING, "http\\Message is not if type response");
1436 RETURN_FALSE;
1437 }
1438
1439 RETURN_LONG(obj->message->http.info.response.code);
1440 }
1441 }
1442
1443 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_setResponseCode, 0, 0, 1)
1444 ZEND_ARG_INFO(0, response_code)
1445 ZEND_ARG_INFO(0, strict)
1446 ZEND_END_ARG_INFO();
1447 static PHP_METHOD(HttpMessage, setResponseCode)
1448 {
1449 long code;
1450 zend_bool strict = 1;
1451 php_http_message_object_t *obj;
1452
1453 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|b", &code, &strict), invalid_arg, return);
1454
1455 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1456
1457 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1458
1459 if (obj->message->type != PHP_HTTP_RESPONSE) {
1460 php_http_throw(bad_method_call, "http\\Message is not of type response", NULL);
1461 return;
1462 }
1463
1464 if (strict && (code < 100 || code > 599)) {
1465 php_http_throw(invalid_arg, "Invalid response code (100-599): %ld", code);
1466 return;
1467 }
1468
1469 obj->message->http.info.response.code = code;
1470 PTR_SET(obj->message->http.info.response.status, estrdup(php_http_env_get_response_status_for_code(code)));
1471
1472 RETVAL_ZVAL(getThis(), 1, 0);
1473 }
1474
1475 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getResponseStatus, 0, 0, 0)
1476 ZEND_END_ARG_INFO();
1477 static PHP_METHOD(HttpMessage, getResponseStatus)
1478 {
1479 if (SUCCESS == zend_parse_parameters_none()) {
1480 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1481
1482 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1483
1484 if (obj->message->type != PHP_HTTP_RESPONSE) {
1485 php_error_docref(NULL TSRMLS_CC, E_WARNING, "http\\Message is not of type response");
1486 }
1487
1488 if (obj->message->http.info.response.status) {
1489 RETURN_STRING(obj->message->http.info.response.status, 1);
1490 } else {
1491 RETURN_EMPTY_STRING();
1492 }
1493 }
1494 }
1495
1496 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_setResponseStatus, 0, 0, 1)
1497 ZEND_ARG_INFO(0, response_status)
1498 ZEND_END_ARG_INFO();
1499 static PHP_METHOD(HttpMessage, setResponseStatus)
1500 {
1501 char *status;
1502 int status_len;
1503 php_http_message_object_t *obj;
1504
1505 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &status, &status_len), invalid_arg, return);
1506
1507 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1508
1509 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1510
1511 if (obj->message->type != PHP_HTTP_RESPONSE) {
1512 php_http_throw(bad_method_call, "http\\Message is not of type response", NULL);
1513 }
1514
1515 PTR_SET(obj->message->http.info.response.status, estrndup(status, status_len));
1516 RETVAL_ZVAL(getThis(), 1, 0);
1517 }
1518
1519 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getRequestMethod, 0, 0, 0)
1520 ZEND_END_ARG_INFO();
1521 static PHP_METHOD(HttpMessage, getRequestMethod)
1522 {
1523 if (SUCCESS == zend_parse_parameters_none()) {
1524 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1525
1526 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1527
1528 if (obj->message->type != PHP_HTTP_REQUEST) {
1529 php_error_docref(NULL TSRMLS_CC, E_WARNING, "http\\Message is not of type request");
1530 RETURN_FALSE;
1531 }
1532
1533 if (obj->message->http.info.request.method) {
1534 RETURN_STRING(obj->message->http.info.request.method, 1);
1535 } else {
1536 RETURN_EMPTY_STRING();
1537 }
1538 }
1539 }
1540
1541 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_setRequestMethod, 0, 0, 1)
1542 ZEND_ARG_INFO(0, request_method)
1543 ZEND_END_ARG_INFO();
1544 static PHP_METHOD(HttpMessage, setRequestMethod)
1545 {
1546 char *method;
1547 int method_len;
1548 php_http_message_object_t *obj;
1549
1550 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len), invalid_arg, return);
1551
1552 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1553
1554 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1555
1556 if (obj->message->type != PHP_HTTP_REQUEST) {
1557 php_http_throw(bad_method_call, "http\\Message is not of type request", NULL);
1558 return;
1559 }
1560
1561 if (method_len < 1) {
1562 php_http_throw(invalid_arg, "Cannot set http\\Message's request method to an empty string", NULL);
1563 return;
1564 }
1565
1566 PTR_SET(obj->message->http.info.request.method, estrndup(method, method_len));
1567 RETVAL_ZVAL(getThis(), 1, 0);
1568 }
1569
1570 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getRequestUrl, 0, 0, 0)
1571 ZEND_END_ARG_INFO();
1572 static PHP_METHOD(HttpMessage, getRequestUrl)
1573 {
1574 if (SUCCESS == zend_parse_parameters_none()) {
1575 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1576
1577 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1578
1579 if (obj->message->type != PHP_HTTP_REQUEST) {
1580 php_error_docref(NULL TSRMLS_CC, E_WARNING, "http\\Message is not of type request");
1581 RETURN_FALSE;
1582 }
1583
1584 if (obj->message->http.info.request.url) {
1585 char *url_str;
1586 size_t url_len;
1587
1588 php_http_url_to_string(obj->message->http.info.request.url, &url_str, &url_len, 0);
1589 RETURN_STRINGL(url_str, url_len, 0);
1590 } else {
1591 RETURN_EMPTY_STRING();
1592 }
1593 }
1594 }
1595
1596 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_setRequestUrl, 0, 0, 1)
1597 ZEND_ARG_INFO(0, url)
1598 ZEND_END_ARG_INFO();
1599 static PHP_METHOD(HttpMessage, setRequestUrl)
1600 {
1601 zval *zurl;
1602 php_http_url_t *url;
1603 php_http_message_object_t *obj;
1604 zend_error_handling zeh;
1605
1606 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zurl), invalid_arg, return);
1607
1608 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1609
1610 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1611
1612 if (obj->message->type != PHP_HTTP_REQUEST) {
1613 php_http_throw(bad_method_call, "http\\Message is not of type request", NULL);
1614 return;
1615 }
1616
1617 zend_replace_error_handling(EH_THROW, php_http_exception_bad_url_class_entry, &zeh TSRMLS_CC);
1618 url = php_http_url_from_zval(zurl, ~0 TSRMLS_CC);
1619 zend_restore_error_handling(&zeh TSRMLS_CC);
1620
1621 if (php_http_url_is_empty(url)) {
1622 php_http_url_free(&url);
1623 php_http_throw(invalid_arg, "Cannot set http\\Message's request url to an empty string", NULL);
1624 } else {
1625 PTR_SET(obj->message->http.info.request.url, url);
1626 }
1627
1628 RETVAL_ZVAL(getThis(), 1, 0);
1629 }
1630
1631 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_getParentMessage, 0, 0, 0)
1632 ZEND_END_ARG_INFO();
1633 static PHP_METHOD(HttpMessage, getParentMessage)
1634 {
1635 php_http_message_object_t *obj;
1636
1637 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
1638
1639 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1640
1641 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1642
1643 if (!obj->message->parent) {
1644 php_http_throw(unexpected_val, "http\\Message has not parent message", NULL);
1645 return;
1646 }
1647
1648 RETVAL_OBJVAL(obj->parent->zv, 1);
1649 }
1650
1651 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage___toString, 0, 0, 0)
1652 ZEND_END_ARG_INFO();
1653 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_toString, 0, 0, 0)
1654 ZEND_ARG_INFO(0, include_parent)
1655 ZEND_END_ARG_INFO();
1656 static PHP_METHOD(HttpMessage, toString)
1657 {
1658 zend_bool include_parent = 0;
1659
1660 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &include_parent)) {
1661 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1662 char *string;
1663 size_t length;
1664
1665 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1666
1667 if (include_parent) {
1668 php_http_message_serialize(obj->message, &string, &length);
1669 } else {
1670 php_http_message_to_string(obj->message, &string, &length);
1671 }
1672 if (string) {
1673 RETURN_STRINGL(string, length, 0);
1674 }
1675 }
1676 RETURN_EMPTY_STRING();
1677 }
1678
1679 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_toStream, 0, 0, 1)
1680 ZEND_ARG_INFO(0, stream)
1681 ZEND_END_ARG_INFO();
1682 static PHP_METHOD(HttpMessage, toStream)
1683 {
1684 zval *zstream;
1685
1686 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream)) {
1687 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1688 php_stream *s;
1689
1690 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1691
1692 php_stream_from_zval(s, &zstream);
1693 php_http_message_to_callback(obj->message, (php_http_pass_callback_t) _php_stream_write, s);
1694 }
1695 }
1696
1697 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_toCallback, 0, 0, 1)
1698 ZEND_ARG_INFO(0, callback)
1699 ZEND_END_ARG_INFO();
1700 static PHP_METHOD(HttpMessage, toCallback)
1701 {
1702 php_http_pass_fcall_arg_t fcd;
1703
1704 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f", &fcd.fci, &fcd.fcc)) {
1705 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1706
1707 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1708
1709 fcd.fcz = getThis();
1710 Z_ADDREF_P(fcd.fcz);
1711 TSRMLS_SET_CTX(fcd.ts);
1712
1713 php_http_message_to_callback(obj->message, php_http_pass_fcall_callback, &fcd);
1714 zend_fcall_info_args_clear(&fcd.fci, 1);
1715
1716 zval_ptr_dtor(&fcd.fcz);
1717 RETURN_ZVAL(getThis(), 1, 0);
1718 }
1719 }
1720
1721 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_serialize, 0, 0, 0)
1722 ZEND_END_ARG_INFO();
1723 static PHP_METHOD(HttpMessage, serialize)
1724 {
1725 if (SUCCESS == zend_parse_parameters_none()) {
1726 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1727 char *string;
1728 size_t length;
1729
1730 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1731
1732 php_http_message_serialize(obj->message, &string, &length);
1733 RETURN_STRINGL(string, length, 0);
1734 }
1735 RETURN_EMPTY_STRING();
1736 }
1737
1738 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_unserialize, 0, 0, 1)
1739 ZEND_ARG_INFO(0, serialized)
1740 ZEND_END_ARG_INFO();
1741 static PHP_METHOD(HttpMessage, unserialize)
1742 {
1743 int length;
1744 char *serialized;
1745
1746 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &length)) {
1747 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1748 php_http_message_t *msg;
1749
1750 if (obj->message) {
1751 php_http_message_dtor(obj->message);
1752 efree(obj->message);
1753 }
1754 if ((msg = php_http_message_parse(NULL, serialized, (size_t) length, 1 TSRMLS_CC))) {
1755 obj->message = msg;
1756 } else {
1757 obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
1758 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not unserialize http\\Message");
1759 }
1760 }
1761 }
1762
1763 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_detach, 0, 0, 0)
1764 ZEND_END_ARG_INFO();
1765 static PHP_METHOD(HttpMessage, detach)
1766 {
1767 php_http_message_object_t *obj;
1768
1769 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
1770
1771 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1772
1773 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1774
1775 RETVAL_OBJVAL(php_http_message_object_new_ex(obj->zo.ce, php_http_message_copy_ex(obj->message, NULL, 0), NULL TSRMLS_CC), 0);
1776 }
1777
1778 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_prepend, 0, 0, 1)
1779 ZEND_ARG_OBJ_INFO(0, message, http\\Message, 0)
1780 ZEND_ARG_INFO(0, top)
1781 ZEND_END_ARG_INFO();
1782 static PHP_METHOD(HttpMessage, prepend)
1783 {
1784 zval *prepend;
1785 zend_bool top = 1;
1786 php_http_message_t *msg[2];
1787 php_http_message_object_t *obj, *prepend_obj;
1788
1789 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &prepend, php_http_message_class_entry, &top), invalid_arg, return);
1790
1791 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1792 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1793 prepend_obj = zend_object_store_get_object(prepend TSRMLS_CC);
1794 PHP_HTTP_MESSAGE_OBJECT_INIT(prepend_obj);
1795
1796 /* safety check */
1797 for (msg[0] = obj->message; msg[0]; msg[0] = msg[0]->parent) {
1798 for (msg[1] = prepend_obj->message; msg[1]; msg[1] = msg[1]->parent) {
1799 if (msg[0] == msg[1]) {
1800 php_http_throw(unexpected_val, "Cannot prepend a message located within the same message chain", NULL);
1801 return;
1802 }
1803 }
1804 }
1805
1806 php_http_message_object_prepend(getThis(), prepend, top TSRMLS_CC);
1807 RETURN_ZVAL(getThis(), 1, 0);
1808 }
1809
1810 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_reverse, 0, 0, 0)
1811 ZEND_END_ARG_INFO();
1812 static PHP_METHOD(HttpMessage, reverse)
1813 {
1814 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
1815
1816 php_http_message_object_reverse(getThis(), return_value TSRMLS_CC);
1817 }
1818
1819 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_isMultipart, 0, 0, 0)
1820 ZEND_ARG_INFO(1, boundary)
1821 ZEND_END_ARG_INFO();
1822 static PHP_METHOD(HttpMessage, isMultipart)
1823 {
1824 zval *zboundary = NULL;
1825
1826 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &zboundary)) {
1827 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1828 char *boundary = NULL;
1829
1830 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1831
1832 RETVAL_BOOL(php_http_message_is_multipart(obj->message, zboundary ? &boundary : NULL));
1833
1834 if (zboundary && boundary) {
1835 zval_dtor(zboundary);
1836 ZVAL_STRING(zboundary, boundary, 0);
1837 }
1838 }
1839 }
1840
1841 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_splitMultipartBody, 0, 0, 0)
1842 ZEND_END_ARG_INFO();
1843 static PHP_METHOD(HttpMessage, splitMultipartBody)
1844 {
1845 php_http_message_object_t *obj;
1846 php_http_message_t *msg;
1847 char *boundary = NULL;
1848
1849 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
1850
1851 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1852
1853 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1854
1855 if (!php_http_message_is_multipart(obj->message, &boundary)) {
1856 php_http_throw(bad_method_call, "http\\Message is not a multipart message", NULL);
1857 return;
1858 }
1859
1860 php_http_expect(msg = php_http_message_body_split(obj->message->body, boundary), bad_message, return);
1861
1862 PTR_FREE(boundary);
1863
1864 RETURN_OBJVAL(php_http_message_object_new_ex(php_http_message_class_entry, msg, NULL TSRMLS_CC), 0);
1865 }
1866
1867 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_count, 0, 0, 0)
1868 ZEND_END_ARG_INFO();
1869 static PHP_METHOD(HttpMessage, count)
1870 {
1871 long count_mode = -1;
1872
1873 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &count_mode)) {
1874 long i = 0;
1875 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1876
1877 PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
1878
1879 php_http_message_count(i, obj->message);
1880 RETURN_LONG(i);
1881 }
1882 }
1883
1884 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_rewind, 0, 0, 0)
1885 ZEND_END_ARG_INFO();
1886 static PHP_METHOD(HttpMessage, rewind)
1887 {
1888 if (SUCCESS == zend_parse_parameters_none()) {
1889 zval *zobj = getThis();
1890 php_http_message_object_t *obj = zend_object_store_get_object(zobj TSRMLS_CC);
1891
1892 if (obj->iterator) {
1893 zval_ptr_dtor(&obj->iterator);
1894 }
1895 Z_ADDREF_P(zobj);
1896 obj->iterator = zobj;
1897 }
1898 }
1899
1900 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_valid, 0, 0, 0)
1901 ZEND_END_ARG_INFO();
1902 static PHP_METHOD(HttpMessage, valid)
1903 {
1904 if (SUCCESS == zend_parse_parameters_none()) {
1905 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1906
1907 RETURN_BOOL(obj->iterator != NULL);
1908 }
1909 }
1910
1911 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_next, 0, 0, 0)
1912 ZEND_END_ARG_INFO();
1913 static PHP_METHOD(HttpMessage, next)
1914 {
1915 if (SUCCESS == zend_parse_parameters_none()) {
1916 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1917
1918 if (obj->iterator) {
1919 php_http_message_object_t *itr = zend_object_store_get_object(obj->iterator TSRMLS_CC);
1920
1921 if (itr && itr->parent) {
1922 zval *old = obj->iterator;
1923 MAKE_STD_ZVAL(obj->iterator);
1924 ZVAL_OBJVAL(obj->iterator, itr->parent->zv, 1);
1925 zval_ptr_dtor(&old);
1926 } else {
1927 zval_ptr_dtor(&obj->iterator);
1928 obj->iterator = NULL;
1929 }
1930 }
1931 }
1932 }
1933
1934 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_key, 0, 0, 0)
1935 ZEND_END_ARG_INFO();
1936 static PHP_METHOD(HttpMessage, key)
1937 {
1938 if (SUCCESS == zend_parse_parameters_none()) {
1939 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1940
1941 RETURN_LONG(obj->iterator ? obj->iterator->value.obj.handle:0);
1942 }
1943 }
1944
1945 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_current, 0, 0, 0)
1946 ZEND_END_ARG_INFO();
1947 static PHP_METHOD(HttpMessage, current)
1948 {
1949 if (SUCCESS == zend_parse_parameters_none()) {
1950 php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1951
1952 if (obj->iterator) {
1953 RETURN_ZVAL(obj->iterator, 1, 0);
1954 }
1955 }
1956 }
1957
1958 static zend_function_entry php_http_message_methods[] = {
1959 PHP_ME(HttpMessage, __construct, ai_HttpMessage___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
1960 PHP_ME(HttpMessage, getBody, ai_HttpMessage_getBody, ZEND_ACC_PUBLIC)
1961 PHP_ME(HttpMessage, setBody, ai_HttpMessage_setBody, ZEND_ACC_PUBLIC)
1962 PHP_ME(HttpMessage, addBody, ai_HttpMessage_addBody, ZEND_ACC_PUBLIC)
1963 PHP_ME(HttpMessage, getHeader, ai_HttpMessage_getHeader, ZEND_ACC_PUBLIC)
1964 PHP_ME(HttpMessage, setHeader, ai_HttpMessage_setHeader, ZEND_ACC_PUBLIC)
1965 PHP_ME(HttpMessage, addHeader, ai_HttpMessage_addHeader, ZEND_ACC_PUBLIC)
1966 PHP_ME(HttpMessage, getHeaders, ai_HttpMessage_getHeaders, ZEND_ACC_PUBLIC)
1967 PHP_ME(HttpMessage, setHeaders, ai_HttpMessage_setHeaders, ZEND_ACC_PUBLIC)
1968 PHP_ME(HttpMessage, addHeaders, ai_HttpMessage_addHeaders, ZEND_ACC_PUBLIC)
1969 PHP_ME(HttpMessage, getType, ai_HttpMessage_getType, ZEND_ACC_PUBLIC)
1970 PHP_ME(HttpMessage, setType, ai_HttpMessage_setType, ZEND_ACC_PUBLIC)
1971 PHP_ME(HttpMessage, getInfo, ai_HttpMessage_getInfo, ZEND_ACC_PUBLIC)
1972 PHP_ME(HttpMessage, setInfo, ai_HttpMessage_setInfo, ZEND_ACC_PUBLIC)
1973 PHP_ME(HttpMessage, getResponseCode, ai_HttpMessage_getResponseCode, ZEND_ACC_PUBLIC)
1974 PHP_ME(HttpMessage, setResponseCode, ai_HttpMessage_setResponseCode, ZEND_ACC_PUBLIC)
1975 PHP_ME(HttpMessage, getResponseStatus, ai_HttpMessage_getResponseStatus, ZEND_ACC_PUBLIC)
1976 PHP_ME(HttpMessage, setResponseStatus, ai_HttpMessage_setResponseStatus, ZEND_ACC_PUBLIC)
1977 PHP_ME(HttpMessage, getRequestMethod, ai_HttpMessage_getRequestMethod, ZEND_ACC_PUBLIC)
1978 PHP_ME(HttpMessage, setRequestMethod, ai_HttpMessage_setRequestMethod, ZEND_ACC_PUBLIC)
1979 PHP_ME(HttpMessage, getRequestUrl, ai_HttpMessage_getRequestUrl, ZEND_ACC_PUBLIC)
1980 PHP_ME(HttpMessage, setRequestUrl, ai_HttpMessage_setRequestUrl, ZEND_ACC_PUBLIC)
1981 PHP_ME(HttpMessage, getHttpVersion, ai_HttpMessage_getHttpVersion, ZEND_ACC_PUBLIC)
1982 PHP_ME(HttpMessage, setHttpVersion, ai_HttpMessage_setHttpVersion, ZEND_ACC_PUBLIC)
1983 PHP_ME(HttpMessage, getParentMessage, ai_HttpMessage_getParentMessage, ZEND_ACC_PUBLIC)
1984 PHP_ME(HttpMessage, toString, ai_HttpMessage_toString, ZEND_ACC_PUBLIC)
1985 PHP_ME(HttpMessage, toCallback, ai_HttpMessage_toCallback, ZEND_ACC_PUBLIC)
1986 PHP_ME(HttpMessage, toStream, ai_HttpMessage_toStream, ZEND_ACC_PUBLIC)
1987
1988 /* implements Countable */
1989 PHP_ME(HttpMessage, count, ai_HttpMessage_count, ZEND_ACC_PUBLIC)
1990
1991 /* implements Serializable */
1992 PHP_ME(HttpMessage, serialize, ai_HttpMessage_serialize, ZEND_ACC_PUBLIC)
1993 PHP_ME(HttpMessage, unserialize, ai_HttpMessage_unserialize, ZEND_ACC_PUBLIC)
1994
1995 /* implements Iterator */
1996 PHP_ME(HttpMessage, rewind, ai_HttpMessage_rewind, ZEND_ACC_PUBLIC)
1997 PHP_ME(HttpMessage, valid, ai_HttpMessage_valid, ZEND_ACC_PUBLIC)
1998 PHP_ME(HttpMessage, current, ai_HttpMessage_current, ZEND_ACC_PUBLIC)
1999 PHP_ME(HttpMessage, key, ai_HttpMessage_key, ZEND_ACC_PUBLIC)
2000 PHP_ME(HttpMessage, next, ai_HttpMessage_next, ZEND_ACC_PUBLIC)
2001
2002 ZEND_MALIAS(HttpMessage, __toString, toString, ai_HttpMessage___toString, ZEND_ACC_PUBLIC)
2003
2004 PHP_ME(HttpMessage, detach, ai_HttpMessage_detach, ZEND_ACC_PUBLIC)
2005 PHP_ME(HttpMessage, prepend, ai_HttpMessage_prepend, ZEND_ACC_PUBLIC)
2006 PHP_ME(HttpMessage, reverse, ai_HttpMessage_reverse, ZEND_ACC_PUBLIC)
2007
2008 PHP_ME(HttpMessage, isMultipart, ai_HttpMessage_isMultipart, ZEND_ACC_PUBLIC)
2009 PHP_ME(HttpMessage, splitMultipartBody, ai_HttpMessage_splitMultipartBody, ZEND_ACC_PUBLIC)
2010
2011 EMPTY_FUNCTION_ENTRY
2012 };
2013
2014 zend_class_entry *php_http_message_class_entry;
2015
2016 PHP_MINIT_FUNCTION(http_message)
2017 {
2018 zend_class_entry ce = {0};
2019
2020 INIT_NS_CLASS_ENTRY(ce, "http", "Message", php_http_message_methods);
2021 php_http_message_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
2022 php_http_message_class_entry->create_object = php_http_message_object_new;
2023 memcpy(&php_http_message_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2024 php_http_message_object_handlers.clone_obj = php_http_message_object_clone;
2025 php_http_message_object_handlers.read_property = php_http_message_object_read_prop;
2026 php_http_message_object_handlers.write_property = php_http_message_object_write_prop;
2027 php_http_message_object_handlers.get_properties = php_http_message_object_get_props;
2028 php_http_message_object_handlers.get_property_ptr_ptr = NULL;
2029
2030 zend_class_implements(php_http_message_class_entry TSRMLS_CC, 3, spl_ce_Countable, zend_ce_serializable, zend_ce_iterator);
2031
2032 zend_hash_init(&php_http_message_object_prophandlers, 9, NULL, NULL, 1);
2033 zend_declare_property_long(php_http_message_class_entry, ZEND_STRL("type"), PHP_HTTP_NONE, ZEND_ACC_PROTECTED TSRMLS_CC);
2034 php_http_message_object_add_prophandler(ZEND_STRL("type"), php_http_message_object_prophandler_get_type, php_http_message_object_prophandler_set_type);
2035 zend_declare_property_null(php_http_message_class_entry, ZEND_STRL("body"), ZEND_ACC_PROTECTED TSRMLS_CC);
2036 php_http_message_object_add_prophandler(ZEND_STRL("body"), php_http_message_object_prophandler_get_body, php_http_message_object_prophandler_set_body);
2037 zend_declare_property_string(php_http_message_class_entry, ZEND_STRL("requestMethod"), "", ZEND_ACC_PROTECTED TSRMLS_CC);
2038 php_http_message_object_add_prophandler(ZEND_STRL("requestMethod"), php_http_message_object_prophandler_get_request_method, php_http_message_object_prophandler_set_request_method);
2039 zend_declare_property_string(php_http_message_class_entry, ZEND_STRL("requestUrl"), "", ZEND_ACC_PROTECTED TSRMLS_CC);
2040 php_http_message_object_add_prophandler(ZEND_STRL("requestUrl"), php_http_message_object_prophandler_get_request_url, php_http_message_object_prophandler_set_request_url);
2041 zend_declare_property_string(php_http_message_class_entry, ZEND_STRL("responseStatus"), "", ZEND_ACC_PROTECTED TSRMLS_CC);
2042 php_http_message_object_add_prophandler(ZEND_STRL("responseStatus"), php_http_message_object_prophandler_get_response_status, php_http_message_object_prophandler_set_response_status);
2043 zend_declare_property_long(php_http_message_class_entry, ZEND_STRL("responseCode"), 0, ZEND_ACC_PROTECTED TSRMLS_CC);
2044 php_http_message_object_add_prophandler(ZEND_STRL("responseCode"), php_http_message_object_prophandler_get_response_code, php_http_message_object_prophandler_set_response_code);
2045 zend_declare_property_null(php_http_message_class_entry, ZEND_STRL("httpVersion"), ZEND_ACC_PROTECTED TSRMLS_CC);
2046 php_http_message_object_add_prophandler(ZEND_STRL("httpVersion"), php_http_message_object_prophandler_get_http_version, php_http_message_object_prophandler_set_http_version);
2047 zend_declare_property_null(php_http_message_class_entry, ZEND_STRL("headers"), ZEND_ACC_PROTECTED TSRMLS_CC);
2048 php_http_message_object_add_prophandler(ZEND_STRL("headers"), php_http_message_object_prophandler_get_headers, php_http_message_object_prophandler_set_headers);
2049 zend_declare_property_null(php_http_message_class_entry, ZEND_STRL("parentMessage"), ZEND_ACC_PROTECTED TSRMLS_CC);
2050 php_http_message_object_add_prophandler(ZEND_STRL("parentMessage"), php_http_message_object_prophandler_get_parent_message, php_http_message_object_prophandler_set_parent_message);
2051
2052 zend_declare_class_constant_long(php_http_message_class_entry, ZEND_STRL("TYPE_NONE"), PHP_HTTP_NONE TSRMLS_CC);
2053 zend_declare_class_constant_long(php_http_message_class_entry, ZEND_STRL("TYPE_REQUEST"), PHP_HTTP_REQUEST TSRMLS_CC);
2054 zend_declare_class_constant_long(php_http_message_class_entry, ZEND_STRL("TYPE_RESPONSE"), PHP_HTTP_RESPONSE TSRMLS_CC);
2055
2056 return SUCCESS;
2057 }
2058
2059 PHP_MSHUTDOWN_FUNCTION(http_message)
2060 {
2061 zend_hash_destroy(&php_http_message_object_prophandlers);
2062
2063 return SUCCESS;
2064 }
2065
2066 /*
2067 * Local variables:
2068 * tab-width: 4
2069 * c-basic-offset: 4
2070 * End:
2071 * vim600: noet sw=4 ts=4 fdm=marker
2072 * vim<600: noet sw=4 ts=4
2073 */
2074