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