- update Makefile fragments
[m6w6/ext-http] / http_methods.c
1 /*
2 +----------------------------------------------------------------------+
3 | PECL :: http |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.0 of the PHP license, that |
6 | is bundled with this package in the file LICENSE, and is available |
7 | through the world-wide-web at http://www.php.net/license/3_0.txt. |
8 | If you did not receive a copy of the PHP license and are unable to |
9 | obtain it through the world-wide-web, please send a note to |
10 | license@php.net so we can mail you a copy immediately. |
11 +----------------------------------------------------------------------+
12 | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
13 +----------------------------------------------------------------------+
14 */
15
16 /* $Id$ */
17
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
21
22 #include "php.h"
23 #include "php_streams.h"
24
25 #include "php_http.h"
26 #include "php_http_std_defs.h"
27 #include "php_http_api.h"
28 #include "php_http_cache_api.h"
29 #include "php_http_request_api.h"
30 #include "php_http_date_api.h"
31 #include "php_http_headers_api.h"
32 #include "php_http_message_api.h"
33 #include "php_http_send_api.h"
34 #include "php_http_url_api.h"
35
36 #include "php_http_message_object.h"
37 #include "php_http_response_object.h"
38 #include "php_http_request_object.h"
39 #include "php_http_exception_object.h"
40
41 #ifdef ZEND_ENGINE_2
42
43 ZEND_EXTERN_MODULE_GLOBALS(http)
44
45 /* {{{ HttpResponse */
46
47 /* {{{ proto void HttpResponse::__construct(bool cache, bool gzip)
48 *
49 * Instantiates a new HttpResponse object, which can be used to send
50 * any data/resource/file to an HTTP client with caching and multiple
51 * ranges/resuming support.
52 *
53 * NOTE: GZIPping is not implemented yet.
54 */
55 PHP_METHOD(HttpResponse, __construct)
56 {
57 zend_bool do_cache = 0, do_gzip = 0;
58 getObject(http_response_object, obj);
59
60 SET_EH_THROW_HTTP();
61 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bb", &do_cache, &do_gzip)) {
62 UPD_PROP(obj, long, cache, do_cache);
63 UPD_PROP(obj, long, gzip, do_gzip);
64 }
65 SET_EH_NORMAL();
66 }
67 /* }}} */
68
69 /* {{{ proto bool HttpResponse::setCache(bool cache)
70 *
71 * Whether it sould be attempted to cache the entitity.
72 * This will result in necessary caching headers and checks of clients
73 * "If-Modified-Since" and "If-None-Match" headers. If one of those headers
74 * matches a "304 Not Modified" status code will be issued.
75 *
76 * NOTE: If you're using sessions, be shure that you set session.cache_limiter
77 * to something more appropriate than "no-cache"!
78 */
79 PHP_METHOD(HttpResponse, setCache)
80 {
81 zend_bool do_cache = 0;
82 getObject(http_response_object, obj);
83
84 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) {
85 RETURN_FALSE;
86 }
87
88 UPD_PROP(obj, long, cache, do_cache);
89 RETURN_TRUE;
90 }
91 /* }}} */
92
93 /* {{{ proto bool HttpResponse::getCache()
94 *
95 * Get current caching setting.
96 */
97 PHP_METHOD(HttpResponse, getCache)
98 {
99 NO_ARGS;
100
101 IF_RETVAL_USED {
102 zval *do_cache = NULL;
103 getObject(http_response_object, obj);
104
105 do_cache = GET_PROP(obj, cache);
106 RETURN_BOOL(Z_LVAL_P(do_cache));
107 }
108 }
109 /* }}}*/
110
111 /* {{{ proto bool HttpResponse::setGzip(bool gzip)
112 *
113 * Enable on-thy-fly gzipping of the sent entity. NOT IMPLEMENTED YET.
114 */
115 PHP_METHOD(HttpResponse, setGzip)
116 {
117 zend_bool do_gzip = 0;
118 getObject(http_response_object, obj);
119
120 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) {
121 RETURN_FALSE;
122 }
123
124 UPD_PROP(obj, long, gzip, do_gzip);
125 RETURN_TRUE;
126 }
127 /* }}} */
128
129 /* {{{ proto bool HttpResponse::getGzip()
130 *
131 * Get current gzipping setting.
132 */
133 PHP_METHOD(HttpResponse, getGzip)
134 {
135 NO_ARGS;
136
137 IF_RETVAL_USED {
138 zval *do_gzip;
139 getObject(http_response_object, obj);
140
141 do_gzip = GET_PROP(obj, gzip);
142 RETURN_BOOL(Z_LVAL_P(do_gzip));
143 }
144 }
145 /* }}} */
146
147 /* {{{ proto bool HttpResponse::setCacheControl(string control[, bool raw = false])
148 *
149 * Set a custom cache-control header, usually being "private" or "public"; if
150 * $raw is set to true the header will be sent as-is.
151 */
152 PHP_METHOD(HttpResponse, setCacheControl)
153 {
154 char *ccontrol;
155 int cc_len;
156 zend_bool raw = 0;
157 getObject(http_response_object, obj);
158
159 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &ccontrol, &cc_len, &raw)) {
160 RETURN_FALSE;
161 }
162
163 if ((!raw) && (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache"))) {
164 http_error_ex(E_WARNING, HTTP_E_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
165 RETURN_FALSE;
166 }
167
168 UPD_PROP(obj, long, raw_cache_header, raw);
169 UPD_PROP(obj, string, cacheControl, ccontrol);
170 RETURN_TRUE;
171 }
172 /* }}} */
173
174 /* {{{ proto string HttpResponse::getCacheControl()
175 *
176 * Get current Cache-Control header setting.
177 */
178 PHP_METHOD(HttpResponse, getCacheControl)
179 {
180 NO_ARGS;
181
182 IF_RETVAL_USED {
183 zval *ccontrol;
184 getObject(http_response_object, obj);
185
186 ccontrol = GET_PROP(obj, cacheControl);
187 RETURN_STRINGL(Z_STRVAL_P(ccontrol), Z_STRLEN_P(ccontrol), 1);
188 }
189 }
190 /* }}} */
191
192 /* {{{ proto bool HttpResponse::setContentType(string content_type)
193 *
194 * Set the content-type of the sent entity.
195 */
196 PHP_METHOD(HttpResponse, setContentType)
197 {
198 char *ctype;
199 int ctype_len;
200 getObject(http_response_object, obj);
201
202 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) {
203 RETURN_FALSE;
204 }
205
206 if (!strchr(ctype, '/')) {
207 http_error_ex(E_WARNING, HTTP_E_PARAM, "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype);
208 RETURN_FALSE;
209 }
210
211 UPD_PROP(obj, string, contentType, ctype);
212
213 RETURN_TRUE;
214 }
215 /* }}} */
216
217 /* {{{ proto string HttpResponse::getContentType()
218 *
219 * Get current Content-Type header setting.
220 */
221 PHP_METHOD(HttpResponse, getContentType)
222 {
223 NO_ARGS;
224
225 IF_RETVAL_USED {
226 zval *ctype;
227 getObject(http_response_object, obj);
228
229 ctype = GET_PROP(obj, contentType);
230 RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
231 }
232 }
233 /* }}} */
234
235 /* {{{ proto bool HttpResponse::setContentDisposition(string filename[, bool inline = false])
236 *
237 * Set the Content-Disposition of the sent entity. This setting aims to suggest
238 * the receiveing user agent how to handle the sent entity; usually the client
239 * will show the user a "Save As..." popup.
240 */
241 PHP_METHOD(HttpResponse, setContentDisposition)
242 {
243 char *file;
244 int file_len;
245 zend_bool is_inline = 0;
246 getObject(http_response_object, obj);
247
248 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &is_inline)) {
249 RETURN_FALSE;
250 }
251
252 UPD_PROP(obj, string, dispoFile, file);
253 UPD_PROP(obj, long, dispoInline, is_inline);
254 RETURN_TRUE;
255 }
256 /* }}} */
257
258 /* {{{ proto array HttpResponse::getContentDisposition()
259 *
260 * Get current Content-Disposition setting.
261 * Will return an associative array like:
262 * <pre>
263 * array(
264 * 'filename' => 'foo.bar',
265 * 'inline' => false
266 * )
267 * </pre>
268 */
269 PHP_METHOD(HttpResponse, getContentDisposition)
270 {
271 NO_ARGS;
272
273 IF_RETVAL_USED {
274 zval *file, *is_inline;
275 getObject(http_response_object, obj);
276
277 file = GET_PROP(obj, dispoFile);
278 is_inline = GET_PROP(obj, dispoInline);
279
280 array_init(return_value);
281 add_assoc_stringl(return_value, "filename", Z_STRVAL_P(file), Z_STRLEN_P(file), 1);
282 add_assoc_bool(return_value, "inline", Z_LVAL_P(is_inline));
283 }
284 }
285 /* }}} */
286
287 /* {{{ proto bool HttpResponse::setETag(string etag)
288 *
289 * Set a custom ETag. Use this only if you know what you're doing.
290 */
291 PHP_METHOD(HttpResponse, setETag)
292 {
293 char *etag;
294 int etag_len;
295 getObject(http_response_object, obj);
296
297 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) {
298 RETURN_FALSE;
299 }
300
301 UPD_PROP(obj, string, eTag, etag);
302 RETURN_TRUE;
303 }
304 /* }}} */
305
306 /* {{{ proto string HttpResponse::getETag()
307 *
308 * Get the previously set custom ETag.
309 */
310 PHP_METHOD(HttpResponse, getETag)
311 {
312 NO_ARGS;
313
314 IF_RETVAL_USED {
315 zval *etag;
316 getObject(http_response_object, obj);
317
318 etag = GET_PROP(obj, eTag);
319 RETURN_STRINGL(Z_STRVAL_P(etag), Z_STRLEN_P(etag), 1);
320 }
321 }
322 /* }}} */
323
324 /* {{{ proto void HttpResponse::setThrottleDelay(double seconds)
325 *
326 */
327 PHP_METHOD(HttpResponse, setThrottleDelay)
328 {
329 double seconds;
330
331 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &seconds)) {
332 getObject(http_response_object, obj);
333
334 UPD_PROP(obj, double, throttleDelay, seconds);
335 }
336 }
337 /* }}} */
338
339 /* {{{ proto double HttpResponse::getThrottleDelay()
340 *
341 */
342 PHP_METHOD(HttpResponse, getThrottleDelay)
343 {
344 NO_ARGS;
345
346 IF_RETVAL_USED {
347 zval *seconds;
348 getObject(http_response_object, obj);
349
350 seconds = GET_PROP(obj, throttleDelay);
351 RETURN_DOUBLE(Z_DVAL_P(seconds));
352 }
353 }
354 /* }}} */
355
356 /* {{{ proto void HttpResponse::setSendBuffersize(long bytes)
357 *
358 */
359 PHP_METHOD(HttpResponse, setSendBuffersize)
360 {
361 long bytes;
362
363 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bytes)) {
364 getObject(http_response_object, obj);
365
366 UPD_PROP(obj, long, sendBuffersize, bytes);
367 }
368 }
369 /* }}} */
370
371 /* {{{ proto long HttpResponse::getSendBuffersize()
372 *
373 */
374 PHP_METHOD(HttpResponse, getSendBuffersize)
375 {
376 NO_ARGS;
377
378 IF_RETVAL_USED {
379 zval *bytes;
380 getObject(http_response_object, obj);
381
382 bytes = GET_PROP(obj, sendBuffersize);
383 RETURN_LONG(Z_LVAL_P(bytes));
384 }
385 }
386 /* }}} */
387
388 /* {{{ proto bool HttpResponse::setData(string data)
389 *
390 * Set the data to be sent.
391 */
392 PHP_METHOD(HttpResponse, setData)
393 {
394 zval *the_data;
395 getObject(http_response_object, obj);
396
397 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &the_data)) {
398 RETURN_FALSE;
399 }
400
401 convert_to_string_ex(&the_data);
402 SET_PROP(obj, data, the_data);
403 UPD_PROP(obj, long, lastModified, http_last_modified(the_data, SEND_DATA));
404 UPD_PROP(obj, long, send_mode, SEND_DATA);
405 RETURN_TRUE;
406 }
407 /* }}} */
408
409 /* {{{ proto string HttpResponse::getData()
410 *
411 * Get the previously set data to be sent.
412 */
413 PHP_METHOD(HttpResponse, getData)
414 {
415 NO_ARGS;
416
417 IF_RETVAL_USED {
418 zval *the_data;
419 getObject(http_response_object, obj);
420
421 the_data = GET_PROP(obj, data);
422 RETURN_STRINGL(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), 1);
423 }
424 }
425 /* }}} */
426
427 /* {{{ proto bool HttpResponse::setStream(resource stream)
428 *
429 * Set the resource to be sent.
430 */
431 PHP_METHOD(HttpResponse, setStream)
432 {
433 zval *the_stream;
434 php_stream *the_real_stream;
435 getObject(http_response_object, obj);
436
437 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
438 RETURN_FALSE;
439 }
440
441 php_stream_from_zval(the_real_stream, &the_stream);
442
443 SET_PROP(obj, stream, the_stream);
444 UPD_PROP(obj, long, lastModified, http_last_modified(the_real_stream, SEND_RSRC));
445 UPD_PROP(obj, long, send_mode, SEND_RSRC);
446 RETURN_TRUE;
447 }
448 /* }}} */
449
450 /* {{{ proto resource HttpResponse::getStream()
451 *
452 * Get the previously set resource to be sent.
453 */
454 PHP_METHOD(HttpResponse, getStream)
455 {
456 NO_ARGS;
457
458 IF_RETVAL_USED {
459 zval *the_stream;
460 getObject(http_response_object, obj);
461
462 the_stream = GET_PROP(obj, stream);
463 RETURN_RESOURCE(Z_LVAL_P(the_stream));
464 }
465 }
466 /* }}} */
467
468 /* {{{ proto bool HttpResponse::setFile(string file)
469 *
470 * Set the file to be sent.
471 */
472 PHP_METHOD(HttpResponse, setFile)
473 {
474 zval *the_file;
475 getObject(http_response_object, obj);
476
477 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_file)) {
478 RETURN_FALSE;
479 }
480
481 convert_to_string_ex(&the_file);
482
483 UPD_PROP(obj, string, file, Z_STRVAL_P(the_file));
484 UPD_PROP(obj, long, lastModified, http_last_modified(the_file, -1));
485 UPD_PROP(obj, long, send_mode, -1);
486 RETURN_TRUE;
487 }
488 /* }}} */
489
490 /* {{{ proto string HttpResponse::getFile()
491 *
492 * Get the previously set file to be sent.
493 */
494 PHP_METHOD(HttpResponse, getFile)
495 {
496 NO_ARGS;
497
498 IF_RETVAL_USED {
499 zval *the_file;
500 getObject(http_response_object, obj);
501
502 the_file = GET_PROP(obj, file);
503 RETURN_STRINGL(Z_STRVAL_P(the_file), Z_STRLEN_P(the_file), 1);
504 }
505 }
506 /* }}} */
507
508 /* {{{ proto bool HttpResponse::send()
509 *
510 * Finally send the entity.
511 *
512 * Example:
513 * <pre>
514 * <?php
515 * $r = new HttpResponse(true);
516 * $r->setFile('../hidden/contract.pdf');
517 * $r->setContentType('application/pdf');
518 * $r->send();
519 * ?>
520 * </pre>
521 *
522 */
523 PHP_METHOD(HttpResponse, send)
524 {
525 zval *do_cache, *do_gzip;
526 getObject(http_response_object, obj);
527
528 NO_ARGS;
529
530 do_cache = GET_PROP(obj, cache);
531 do_gzip = GET_PROP(obj, gzip);
532
533 /* gzip */
534 if (Z_LVAL_P(do_gzip)) {
535 php_start_ob_buffer_named("ob_gzhandler", 0, 1 TSRMLS_CC);
536 }
537
538 /* caching */
539 if (Z_LVAL_P(do_cache)) {
540 char *cc_hdr;
541 int cc_len;
542 zval *cctrl, *etag, *lmod, *ccraw;
543
544 etag = GET_PROP(obj, eTag);
545 lmod = GET_PROP(obj, lastModified);
546 cctrl = GET_PROP(obj, cacheControl);
547 ccraw = GET_PROP(obj, raw_cache_header);
548
549 if (Z_LVAL_P(ccraw)) {
550 cc_hdr = Z_STRVAL_P(cctrl);
551 cc_len = Z_STRLEN_P(cctrl);
552 } else {
553 char cc_header[42] = {0};
554 sprintf(cc_header, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl));
555 cc_hdr = cc_header;
556 cc_len = Z_STRLEN_P(cctrl) + lenof(", must-revalidate, max-age=0");
557 }
558
559 http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), cc_hdr, cc_len);
560 http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), cc_hdr, cc_len);
561 }
562
563 /* content type */
564 {
565 zval *ctype = GET_PROP(obj, contentType);
566 if (Z_STRLEN_P(ctype)) {
567 http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
568 } else {
569 http_send_content_type("application/x-octetstream", lenof("application/x-octetstream"));
570 }
571 }
572
573 /* content disposition */
574 {
575 zval *dispo_file = GET_PROP(obj, dispoFile);
576 if (Z_STRLEN_P(dispo_file)) {
577 zval *dispo_inline = GET_PROP(obj, dispoInline);
578 http_send_content_disposition(Z_STRVAL_P(dispo_file), Z_STRLEN_P(dispo_file), (zend_bool) Z_LVAL_P(dispo_inline));
579 }
580 }
581
582 /* throttling */
583 {
584 zval *send_buffersize, *throttle_delay;
585 send_buffersize = GET_PROP(obj, sendBuffersize);
586 throttle_delay = GET_PROP(obj, throttleDelay);
587 HTTP_G(send).buffer_size = Z_LVAL_P(send_buffersize);
588 HTTP_G(send).throttle_delay = Z_DVAL_P(throttle_delay);
589 }
590
591 /* send */
592 {
593 zval *send_mode = GET_PROP(obj, send_mode);
594 switch (Z_LVAL_P(send_mode))
595 {
596 case SEND_DATA:
597 {
598 zval *zdata = GET_PROP(obj, data);
599 RETURN_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)));
600 }
601
602 case SEND_RSRC:
603 {
604 php_stream *the_real_stream;
605 zval *the_stream = GET_PROP(obj, stream);
606 php_stream_from_zval(the_real_stream, &the_stream);
607 RETURN_SUCCESS(http_send_stream(the_real_stream));
608 }
609
610 default:
611 {
612 zval *zfile = GET_PROP(obj, file);
613 RETURN_SUCCESS(http_send_file(Z_STRVAL_P(zfile)));
614 }
615 }
616 }
617 }
618 /* }}} */
619 /* }}} */
620
621 /* {{{ HttpMessage */
622
623 /* {{{ proto static HttpMessage HttpMessage::fromString(string raw_message)
624 *
625 * Create an HttpMessage object from a string.
626 */
627 PHP_METHOD(HttpMessage, fromString)
628 {
629 char *string = NULL;
630 int length = 0;
631 http_message *msg = NULL;
632 http_message_object obj;
633
634 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &length)) {
635 RETURN_NULL();
636 }
637
638 if (!(msg = http_message_parse(string, length))) {
639 RETURN_NULL();
640 }
641
642 Z_TYPE_P(return_value) = IS_OBJECT;
643 return_value->value.obj = http_message_object_from_msg(msg);
644 }
645 /* }}} */
646
647 /* {{{ proto void HttpMessage::__construct([string message])
648 *
649 * Instantiate a new HttpMessage object.
650 */
651 PHP_METHOD(HttpMessage, __construct)
652 {
653 char *message = NULL;
654 int length = 0;
655 getObject(http_message_object, obj);
656
657 SET_EH_THROW_HTTP();
658 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &message, &length) && message && length) {
659 if (obj->message = http_message_parse(message, length)) {
660 if (obj->message->parent) {
661 obj->parent = http_message_object_from_msg(obj->message->parent);
662 }
663 }
664 } else if (!obj->message) {
665 obj->message = http_message_new();
666 }
667 SET_EH_NORMAL();
668 }
669 /* }}} */
670
671 /* {{{ proto string HttpMessage::getBody()
672 *
673 * Get the body of the parsed Message.
674 */
675 PHP_METHOD(HttpMessage, getBody)
676 {
677 NO_ARGS;
678
679 IF_RETVAL_USED {
680 getObject(http_message_object, obj);
681 RETURN_PHPSTR(&obj->message->body, PHPSTR_FREE_NOT, 1);
682 }
683 }
684 /* }}} */
685
686 /* {{{ proto array HttpMessage::getHeaders()
687 *
688 * Get Message Headers.
689 */
690 PHP_METHOD(HttpMessage, getHeaders)
691 {
692 NO_ARGS;
693
694 IF_RETVAL_USED {
695 zval headers;
696 getObject(http_message_object, obj);
697
698 Z_ARRVAL(headers) = &obj->message->hdrs;
699 array_init(return_value);
700 array_copy(&headers, return_value);
701 }
702 }
703 /* }}} */
704
705 /* {{{ proto void HttpMessage::setHeaders(array headers)
706 *
707 * Sets new headers.
708 */
709 PHP_METHOD(HttpMessage, setHeaders)
710 {
711 zval *new_headers, old_headers;
712 getObject(http_message_object, obj);
713
714 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &new_headers)) {
715 return;
716 }
717
718 zend_hash_clean(&obj->message->hdrs);
719 Z_ARRVAL(old_headers) = &obj->message->hdrs;
720 array_copy(new_headers, &old_headers);
721 }
722 /* }}} */
723
724 /* {{{ proto void HttpMessage::addHeaders(array headers[, bool append = false])
725 *
726 * Add headers. If append is true, headers with the same name will be separated, else overwritten.
727 */
728 PHP_METHOD(HttpMessage, addHeaders)
729 {
730 zval old_headers, *new_headers;
731 zend_bool append = 0;
732 getObject(http_message_object, obj);
733
734 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &new_headers, &append)) {
735 return;
736 }
737
738 Z_ARRVAL(old_headers) = &obj->message->hdrs;
739 if (append) {
740 array_append(new_headers, &old_headers);
741 } else {
742 array_merge(new_headers, &old_headers);
743 }
744 }
745 /* }}} */
746
747 /* {{{ proto long HttpMessage::getType()
748 *
749 * Get Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE)
750 */
751 PHP_METHOD(HttpMessage, getType)
752 {
753 NO_ARGS;
754
755 IF_RETVAL_USED {
756 getObject(http_message_object, obj);
757 RETURN_LONG(obj->message->type);
758 }
759 }
760 /* }}} */
761
762 /* {{{ proto void HttpMessage::setType(long type)
763 *
764 * Set Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE)
765 */
766 PHP_METHOD(HttpMessage, setType)
767 {
768 long type;
769 getObject(http_message_object, obj);
770
771 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type)) {
772 return;
773 }
774 http_message_set_type(obj->message, type);
775 }
776 /* }}} */
777
778 /* {{{ proto long HttpMessage::getResponseCode()
779 *
780 * Get the Response Code of the Message.
781 */
782 PHP_METHOD(HttpMessage, getResponseCode)
783 {
784 NO_ARGS;
785
786 IF_RETVAL_USED {
787 getObject(http_message_object, obj);
788
789 if (!HTTP_MSG_TYPE(RESPONSE, obj->message)) {
790 http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
791 RETURN_NULL();
792 }
793
794 RETURN_LONG(obj->message->info.response.code);
795 }
796 }
797 /* }}} */
798
799 /* {{{ proto bool HttpMessage::setResponseCode(long code)
800 *
801 * Set the response code of an HTTP Response Message.
802 * Returns false if the Message is not of type HTTP_MSG_RESPONSE,
803 * or if the response code is out of range (100-510).
804 */
805 PHP_METHOD(HttpMessage, setResponseCode)
806 {
807 long code;
808 getObject(http_message_object, obj);
809
810 if (!HTTP_MSG_TYPE(RESPONSE, obj->message)) {
811 http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
812 RETURN_FALSE;
813 }
814
815 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
816 RETURN_FALSE;
817 }
818 if (code < 100 || code > 510) {
819 http_error_ex(E_WARNING, HTTP_E_PARAM, "Invalid response code (100-510): %ld", code);
820 RETURN_FALSE;
821 }
822
823 obj->message->info.response.code = code;
824 RETURN_TRUE;
825 }
826 /* }}} */
827
828 /* {{{ proto string HttpMessage::getRequestMethod()
829 *
830 * Get the Request Method of the Message.
831 * Returns false if the Message is not of type HTTP_MSG_REQUEST.
832 */
833 PHP_METHOD(HttpMessage, getRequestMethod)
834 {
835 NO_ARGS;
836
837 IF_RETVAL_USED {
838 getObject(http_message_object, obj);
839
840 if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
841 http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
842 RETURN_NULL();
843 }
844
845 RETURN_STRING(obj->message->info.request.method, 1);
846 }
847 }
848 /* }}} */
849
850 /* {{{ proto bool HttpMessage::setRequestMethod(string method)
851 *
852 * Set the Request Method of the HTTP Message.
853 * Returns false if the Message is not of type HTTP_MSG_REQUEST.
854 */
855 PHP_METHOD(HttpMessage, setRequestMethod)
856 {
857 char *method;
858 int method_len;
859 getObject(http_message_object, obj);
860
861 if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
862 http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
863 RETURN_FALSE;
864 }
865
866 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
867 RETURN_FALSE;
868 }
869 if (method_len < 1) {
870 http_error(E_WARNING, HTTP_E_PARAM, "Cannot set HttpMessage::requestMethod to an empty string");
871 RETURN_FALSE;
872 }
873 if (SUCCESS != http_check_method(method)) {
874 http_error_ex(E_WARNING, HTTP_E_PARAM, "Unkown request method: %s", method);
875 RETURN_FALSE;
876 }
877
878 STR_SET(obj->message->info.request.method, estrndup(method, method_len));
879 RETURN_TRUE;
880 }
881 /* }}} */
882
883 /* {{{ proto string HttpMessage::getRequestUri()
884 *
885 * Get the Request URI of the Message.
886 */
887 PHP_METHOD(HttpMessage, getRequestUri)
888 {
889 NO_ARGS;
890
891 IF_RETVAL_USED {
892 zval *uri;
893 getObject(http_message_object, obj);
894
895 if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
896 http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
897 RETURN_NULL();
898 }
899
900 RETURN_STRING(obj->message->info.request.URI, 1);
901 }
902 }
903 /* }}} */
904
905 /* {{{ proto bool HttpMessage::setRequestUri(string URI)
906 *
907 * Set the Request URI of the HTTP Message.
908 * Returns false if the Message is not of type HTTP_MSG_REQUEST,
909 * or if paramtere URI was empty.
910 */
911 PHP_METHOD(HttpMessage, setRequestUri)
912 {
913 char *URI;
914 int URIlen;
915 getObject(http_message_object, obj);
916
917 if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
918 http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
919 RETURN_FALSE;
920 }
921 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URI, &URIlen)) {
922 RETURN_FALSE;
923 }
924 if (URIlen < 1) {
925 http_error(E_WARNING, HTTP_E_PARAM, "Cannot set HttpMessage::requestUri to an empty string");
926 RETURN_FALSE;
927 }
928
929 STR_SET(obj->message->info.request.URI, estrndup(URI, URIlen));
930 RETURN_TRUE;
931 }
932 /* }}} */
933
934 /* {{{ proto string HttpMessage::getHttpVersion()
935 *
936 * Get the HTTP Protocol Version of the Message.
937 */
938 PHP_METHOD(HttpMessage, getHttpVersion)
939 {
940 NO_ARGS;
941
942 IF_RETVAL_USED {
943 char ver[4] = {0};
944 float version;
945 getObject(http_message_object, obj);
946
947 switch (obj->message->type)
948 {
949 case HTTP_MSG_RESPONSE:
950 version = obj->message->info.response.http_version;
951 break;
952
953 case HTTP_MSG_REQUEST:
954 version = obj->message->info.request.http_version;
955 break;
956
957 case HTTP_MSG_NONE:
958 default:
959 RETURN_NULL();
960 }
961 sprintf(ver, "%1.1f", version);
962 RETURN_STRINGL(ver, 3, 1);
963 }
964 }
965 /* }}} */
966
967 /* {{{ proto bool HttpMessage::setHttpVersion(string version)
968 *
969 * Set the HTTP Protocol version of the Message.
970 * Returns false if version is invalid (1.0 and 1.1).
971 */
972 PHP_METHOD(HttpMessage, setHttpVersion)
973 {
974 char v[4];
975 zval *zv, *version;
976 getObject(http_message_object, obj);
977
978 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &zv)) {
979 return;
980 }
981
982 if (HTTP_MSG_TYPE(NONE, obj->message)) {
983 http_error(E_WARNING, HTTP_E_MSG, "Message is neither of type HTTP_MSG_RESPONSE nor HTTP_MSG_REQUEST");
984 RETURN_FALSE;
985 }
986
987 convert_to_double(zv);
988 sprintf(v, "%1.1f", Z_DVAL_P(zv));
989 if (strcmp(v, "1.0") && strcmp(v, "1.1")) {
990 http_error_ex(E_WARNING, HTTP_E_PARAM, "Invalid HTTP protocol version (1.0 or 1.1): %s", v);
991 RETURN_FALSE;
992 }
993
994 if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
995 obj->message->info.response.http_version = (float) Z_DVAL_P(zv);
996 } else {
997 obj->message->info.request.http_version = (float) Z_DVAL_P(zv);
998 }
999 RETURN_TRUE;
1000 }
1001 /* }}} */
1002
1003 /* {{{ proto HttpMessage HttpMessage::getParentMessage()
1004 *
1005 * Get parent Message.
1006 */
1007 PHP_METHOD(HttpMessage, getParentMessage)
1008 {
1009 NO_ARGS;
1010
1011 IF_RETVAL_USED {
1012 getObject(http_message_object, obj);
1013
1014 if (obj->message->parent) {
1015 RETVAL_OBJVAL(obj->parent);
1016 } else {
1017 RETVAL_NULL();
1018 }
1019 }
1020 }
1021 /* }}} */
1022
1023 /* {{{ proto bool HttpMessage::send()
1024 *
1025 * Send the Message according to its type as Response or Request.
1026 */
1027 PHP_METHOD(HttpMessage, send)
1028 {
1029 getObject(http_message_object, obj);
1030
1031 NO_ARGS;
1032
1033 RETURN_SUCCESS(http_message_send(obj->message));
1034 }
1035 /* }}} */
1036
1037 /* {{{ proto string HttpMessage::toString([bool include_parent = true])
1038 *
1039 * Get the string representation of the Message.
1040 */
1041 PHP_METHOD(HttpMessage, toString)
1042 {
1043 IF_RETVAL_USED {
1044 char *string;
1045 size_t length;
1046 zend_bool include_parent = 1;
1047 getObject(http_message_object, obj);
1048
1049 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &include_parent)) {
1050 RETURN_FALSE;
1051 }
1052
1053 if (include_parent) {
1054 http_message_serialize(obj->message, &string, &length);
1055 } else {
1056 http_message_tostring(obj->message, &string, &length);
1057 }
1058 RETURN_STRINGL(string, length, 0);
1059 }
1060 }
1061 /* }}} */
1062
1063 /* }}} */
1064
1065 #ifdef HTTP_HAVE_CURL
1066 /* {{{ HttpRequest */
1067
1068 /* {{{ proto void HttpRequest::__construct([string url[, long request_method = HTTP_GET]])
1069 *
1070 * Instantiate a new HttpRequest object which can be used to issue HEAD, GET
1071 * and POST (including posting files) HTTP requests.
1072 */
1073 PHP_METHOD(HttpRequest, __construct)
1074 {
1075 char *URL = NULL;
1076 int URL_len;
1077 long meth = -1;
1078 getObject(http_request_object, obj);
1079
1080 SET_EH_THROW_HTTP();
1081 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &URL, &URL_len, &meth)) {
1082 INIT_PARR(obj, options);
1083 INIT_PARR(obj, responseInfo);
1084 INIT_PARR(obj, responseData);
1085 INIT_PARR(obj, postFields);
1086 INIT_PARR(obj, postFiles);
1087
1088 if (URL) {
1089 UPD_PROP(obj, string, url, URL);
1090 }
1091 if (meth > -1) {
1092 UPD_PROP(obj, long, method, meth);
1093 }
1094 }
1095 SET_EH_NORMAL();
1096 }
1097 /* }}} */
1098
1099 /* {{{ proto void HttpRequest::__destruct()
1100 *
1101 * Destroys the HttpRequest object.
1102 */
1103 PHP_METHOD(HttpRequest, __destruct)
1104 {
1105 getObject(http_request_object, obj);
1106
1107 NO_ARGS;
1108
1109 FREE_PARR(obj, options);
1110 FREE_PARR(obj, responseInfo);
1111 FREE_PARR(obj, responseData);
1112 FREE_PARR(obj, postFields);
1113 FREE_PARR(obj, postFiles);
1114 }
1115 /* }}} */
1116
1117 /* {{{ proto bool HttpRequest::setOptions(array options)
1118 *
1119 * Set the request options to use. See http_get() for a full list of available options.
1120 */
1121 PHP_METHOD(HttpRequest, setOptions)
1122 {
1123 char *key = NULL;
1124 long idx = 0;
1125 zval *opts, *old_opts, **opt;
1126 getObject(http_request_object, obj);
1127
1128 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &opts)) {
1129 RETURN_FALSE;
1130 }
1131
1132 old_opts = GET_PROP(obj, options);
1133
1134 /* headers and cookies need extra attention -- thus cannot use array_merge() directly */
1135 FOREACH_KEYVAL(opts, key, idx, opt) {
1136 if (key) {
1137 if (!strcmp(key, "headers")) {
1138 zval **headers;
1139 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "headers", sizeof("headers"), (void **) &headers)) {
1140 array_merge(*opt, *headers);
1141 continue;
1142 }
1143 } else if (!strcmp(key, "cookies")) {
1144 zval **cookies;
1145 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
1146 array_merge(*opt, *cookies);
1147 continue;
1148 }
1149 }
1150 zval_add_ref(opt);
1151 add_assoc_zval(old_opts, key, *opt);
1152
1153 /* reset */
1154 key = NULL;
1155 }
1156 }
1157
1158 RETURN_TRUE;
1159 }
1160 /* }}} */
1161
1162 /* {{{ proto array HttpRequest::getOptions()
1163 *
1164 * Get current set options.
1165 */
1166 PHP_METHOD(HttpRequest, getOptions)
1167 {
1168 NO_ARGS;
1169
1170 IF_RETVAL_USED {
1171 zval *opts;
1172 getObject(http_request_object, obj);
1173
1174 opts = GET_PROP(obj, options);
1175 array_init(return_value);
1176 array_copy(opts, return_value);
1177 }
1178 }
1179 /* }}} */
1180
1181 /* {{{ proto void HttpRequest::unsetOptions()
1182 *
1183 * Unset all options/headers/cookies.
1184 */
1185 PHP_METHOD(HttpRequest, unsetOptions)
1186 {
1187 getObject(http_request_object, obj);
1188
1189 NO_ARGS;
1190
1191 FREE_PARR(obj, options);
1192 INIT_PARR(obj, options);
1193 }
1194 /* }}} */
1195
1196 /* {{{ proto bool HttpRequest::setSslOptions(array options)
1197 *
1198 * Set additional SSL options.
1199 */
1200 PHP_METHOD(HttpRequest, setSslOptions)
1201 {
1202 zval *opts, *old_opts, **ssl_options;
1203 getObject(http_request_object, obj);
1204
1205 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &opts)) {
1206 RETURN_FALSE;
1207 }
1208
1209 old_opts = GET_PROP(obj, options);
1210
1211 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "ssl", sizeof("ssl"), (void **) &ssl_options)) {
1212 array_merge(opts, *ssl_options);
1213 } else {
1214 zval_add_ref(&opts);
1215 add_assoc_zval(old_opts, "ssl", opts);
1216 }
1217
1218 RETURN_TRUE;
1219 }
1220 /* }}} */
1221
1222 /* {{{ proto array HttpRequest::getSslOtpions()
1223 *
1224 * Get previously set SSL options.
1225 */
1226 PHP_METHOD(HttpRequest, getSslOptions)
1227 {
1228 NO_ARGS;
1229
1230 IF_RETVAL_USED {
1231 zval *opts, **ssl_options;
1232 getObject(http_request_object, obj);
1233
1234 opts = GET_PROP(obj, options);
1235
1236 array_init(return_value);
1237
1238 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "ssl", sizeof("ssl"), (void **) &ssl_options)) {
1239 array_copy(*ssl_options, return_value);
1240 }
1241 }
1242 }
1243 /* }}} */
1244
1245 /* {{{ proto void HttpRequest::unsetSslOptions()
1246 *
1247 * Unset previously set SSL options.
1248 */
1249 PHP_METHOD(HttpRequest, unsetSslOptions)
1250 {
1251 zval *opts;
1252 getObject(http_request_object, obj);
1253
1254 NO_ARGS;
1255
1256 opts = GET_PROP(obj, options);
1257 zend_hash_del(Z_ARRVAL_P(opts), "ssl", sizeof("ssl"));
1258 }
1259 /* }}} */
1260
1261 /* {{{ proto bool HttpRequest::addHeaders(array headers)
1262 *
1263 * Add request header name/value pairs.
1264 */
1265 PHP_METHOD(HttpRequest, addHeaders)
1266 {
1267 zval *opts, **headers, *new_headers;
1268 getObject(http_request_object, obj);
1269
1270 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &new_headers)) {
1271 RETURN_FALSE;
1272 }
1273
1274 opts = GET_PROP(obj, options);
1275
1276 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void **) &headers)) {
1277 array_merge(new_headers, *headers);
1278 } else {
1279 zval_add_ref(&new_headers);
1280 add_assoc_zval(opts, "headers", new_headers);
1281 }
1282
1283 RETURN_TRUE;
1284 }
1285 /* }}} */
1286
1287 /* {{{ proto array HttpRequest::getHeaders()
1288 *
1289 * Get previously set request headers.
1290 */
1291 PHP_METHOD(HttpRequest, getHeaders)
1292 {
1293 NO_ARGS;
1294
1295 IF_RETVAL_USED {
1296 zval *opts, **headers;
1297 getObject(http_request_object, obj);
1298
1299 opts = GET_PROP(obj, options);
1300
1301 array_init(return_value);
1302
1303 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void **) &headers)) {
1304 array_copy(*headers, return_value);
1305 }
1306 }
1307 }
1308 /* }}} */
1309
1310 /* {{{ proto void HttpRequest::unsetHeaders()
1311 *
1312 * Unset previously set request headers.
1313 */
1314 PHP_METHOD(HttpRequest, unsetHeaders)
1315 {
1316 zval *opts;
1317 getObject(http_request_object, obj);
1318
1319 NO_ARGS;
1320
1321 opts = GET_PROP(obj, options);
1322 zend_hash_del(Z_ARRVAL_P(opts), "headers", sizeof("headers"));
1323 }
1324 /* }}} */
1325
1326 /* {{{ proto bool HttpRequest::addCookies(array cookies)
1327 *
1328 * Add cookies.
1329 */
1330 PHP_METHOD(HttpRequest, addCookies)
1331 {
1332 zval *opts, **cookies, *new_cookies;
1333 getObject(http_request_object, obj);
1334
1335 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &new_cookies)) {
1336 RETURN_FALSE;
1337 }
1338
1339 opts = GET_PROP(obj, options);
1340
1341 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
1342 array_merge(new_cookies, *cookies);
1343 } else {
1344 zval_add_ref(&new_cookies);
1345 add_assoc_zval(opts, "cookies", new_cookies);
1346 }
1347
1348 RETURN_TRUE;
1349 }
1350 /* }}} */
1351
1352 /* {{{ proto array HttpRequest::getCookies()
1353 *
1354 * Get previously set cookies.
1355 */
1356 PHP_METHOD(HttpRequest, getCookies)
1357 {
1358 NO_ARGS;
1359
1360 IF_RETVAL_USED {
1361 zval *opts, **cookies;
1362 getObject(http_request_object, obj);
1363
1364 opts = GET_PROP(obj, options);
1365
1366 array_init(return_value);
1367
1368 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
1369 array_copy(*cookies, return_value);
1370 }
1371 }
1372 }
1373 /* }}} */
1374
1375 /* {{{ proto void HttpRequest::unsetCookies()
1376 *
1377 */
1378 PHP_METHOD(HttpRequest, unsetCookies)
1379 {
1380 zval *opts;
1381 getObject(http_request_object, obj);
1382
1383 NO_ARGS;
1384
1385 opts = GET_PROP(obj, options);
1386 zend_hash_del(Z_ARRVAL_P(opts), "cookies", sizeof("cookies"));
1387 }
1388 /* }}} */
1389
1390 /* {{{ proto bool HttpRequest::setURL(string url)
1391 *
1392 * Set the request URL.
1393 */
1394 PHP_METHOD(HttpRequest, setURL)
1395 {
1396 char *URL = NULL;
1397 int URL_len;
1398 getObject(http_request_object, obj);
1399
1400 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) {
1401 RETURN_FALSE;
1402 }
1403
1404 UPD_PROP(obj, string, url, URL);
1405 RETURN_TRUE;
1406 }
1407 /* }}} */
1408
1409 /* {{{ proto string HttpRequest::getUrl()
1410 *
1411 * Get the previously set request URL.
1412 */
1413 PHP_METHOD(HttpRequest, getURL)
1414 {
1415 NO_ARGS;
1416
1417 IF_RETVAL_USED {
1418 zval *URL;
1419 getObject(http_request_object, obj);
1420
1421 URL = GET_PROP(obj, url);
1422 RETURN_STRINGL(Z_STRVAL_P(URL), Z_STRLEN_P(URL), 1);
1423 }
1424 }
1425 /* }}} */
1426
1427 /* {{{ proto bool HttpRequest::setMethod(long request_method)
1428 *
1429 * Set the request methods; one of the <tt>HTTP_HEAD</tt>, <tt>HTTP_GET</tt> or
1430 * <tt>HTTP_POST</tt> constants.
1431 */
1432 PHP_METHOD(HttpRequest, setMethod)
1433 {
1434 long meth;
1435 getObject(http_request_object, obj);
1436
1437 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) {
1438 RETURN_FALSE;
1439 }
1440
1441 UPD_PROP(obj, long, method, meth);
1442 RETURN_TRUE;
1443 }
1444 /* }}} */
1445
1446 /* {{{ proto long HttpRequest::getMethod()
1447 *
1448 * Get the previously set request method.
1449 */
1450 PHP_METHOD(HttpRequest, getMethod)
1451 {
1452 NO_ARGS;
1453
1454 IF_RETVAL_USED {
1455 zval *meth;
1456 getObject(http_request_object, obj);
1457
1458 meth = GET_PROP(obj, method);
1459 RETURN_LONG(Z_LVAL_P(meth));
1460 }
1461 }
1462 /* }}} */
1463
1464 /* {{{ proto bool HttpRequest::setContentType(string content_type)
1465 *
1466 * Set the content type the post request should have.
1467 * Use this only if you know what you're doing.
1468 */
1469 PHP_METHOD(HttpRequest, setContentType)
1470 {
1471 char *ctype;
1472 int ct_len;
1473 getObject(http_request_object, obj);
1474
1475 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) {
1476 RETURN_FALSE;
1477 }
1478
1479 if (!strchr(ctype, '/')) {
1480 http_error_ex(E_WARNING, HTTP_E_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", ctype);
1481 RETURN_FALSE;
1482 }
1483
1484 UPD_PROP(obj, string, contentType, ctype);
1485 RETURN_TRUE;
1486 }
1487 /* }}} */
1488
1489 /* {{{ proto string HttpRequest::getContentType()
1490 *
1491 * Get the previously content type.
1492 */
1493 PHP_METHOD(HttpRequest, getContentType)
1494 {
1495 NO_ARGS;
1496
1497 IF_RETVAL_USED {
1498 zval *ctype;
1499 getObject(http_request_object, obj);
1500
1501 ctype = GET_PROP(obj, contentType);
1502 RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
1503 }
1504 }
1505 /* }}} */
1506
1507 /* {{{ proto bool HttpRequest::setQueryData(mixed query_data)
1508 *
1509 * Set the URL query parameters to use.
1510 * Overwrites previously set query parameters.
1511 * Affects any request types.
1512 */
1513 PHP_METHOD(HttpRequest, setQueryData)
1514 {
1515 zval *qdata;
1516 char *query_data = NULL;
1517 getObject(http_request_object, obj);
1518
1519 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &qdata)) {
1520 RETURN_FALSE;
1521 }
1522
1523 if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
1524 if (SUCCESS != http_urlencode_hash(HASH_OF(qdata), &query_data)) {
1525 RETURN_FALSE;
1526 }
1527 UPD_PROP(obj, string, queryData, query_data);
1528 efree(query_data);
1529 RETURN_TRUE;
1530 }
1531
1532 convert_to_string(qdata);
1533 UPD_PROP(obj, string, queryData, Z_STRVAL_P(qdata));
1534 RETURN_TRUE;
1535 }
1536 /* }}} */
1537
1538 /* {{{ proto string HttpRequest::getQueryData()
1539 *
1540 * Get the current query data in form of an urlencoded query string.
1541 */
1542 PHP_METHOD(HttpRequest, getQueryData)
1543 {
1544 NO_ARGS;
1545
1546 IF_RETVAL_USED {
1547 zval *qdata;
1548 getObject(http_request_object, obj);
1549
1550 qdata = GET_PROP(obj, queryData);
1551 RETURN_STRINGL(Z_STRVAL_P(qdata), Z_STRLEN_P(qdata), 1);
1552 }
1553 }
1554 /* }}} */
1555
1556 /* {{{ proto bool HttpRequest::addQueryData(array query_params)
1557 *
1558 * Add parameters to the query parameter list.
1559 * Affects any request type.
1560 */
1561 PHP_METHOD(HttpRequest, addQueryData)
1562 {
1563 zval *qdata, *old_qdata;
1564 char *query_data = NULL;
1565 getObject(http_request_object, obj);
1566
1567 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &qdata)) {
1568 RETURN_FALSE;
1569 }
1570
1571 old_qdata = GET_PROP(obj, queryData);
1572
1573 if (SUCCESS != http_urlencode_hash_ex(HASH_OF(qdata), 1, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata), &query_data, NULL)) {
1574 RETURN_FALSE;
1575 }
1576
1577 UPD_PROP(obj, string, queryData, query_data);
1578 efree(query_data);
1579
1580 RETURN_TRUE;
1581 }
1582 /* }}} */
1583
1584 /* {{{ proto void HttpRequest::unsetQueryData()
1585 *
1586 * Clean the query parameters.
1587 * Affects any request type.
1588 */
1589 PHP_METHOD(HttpRequest, unsetQueryData)
1590 {
1591 getObject(http_request_object, obj);
1592
1593 NO_ARGS;
1594
1595 UPD_PROP(obj, string, queryData, "");
1596 }
1597 /* }}} */
1598
1599 /* {{{ proto bool HttpRequest::addPostFields(array post_data)
1600 *
1601 * Adds POST data entries.
1602 * Affects only POST requests.
1603 */
1604 PHP_METHOD(HttpRequest, addPostFields)
1605 {
1606 zval *post, *post_data;
1607 getObject(http_request_object, obj);
1608
1609 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
1610 RETURN_FALSE;
1611 }
1612
1613 post = GET_PROP(obj, postFields);
1614 array_merge(post_data, post);
1615
1616 RETURN_TRUE;
1617 }
1618 /* }}} */
1619
1620 /* {{{ proto bool HttpRequest::setPostFields(array post_data)
1621 *
1622 * Set the POST data entries.
1623 * Overwrites previously set POST data.
1624 * Affects only POST requests.
1625 */
1626 PHP_METHOD(HttpRequest, setPostFields)
1627 {
1628 zval *post, *post_data;
1629 getObject(http_request_object, obj);
1630
1631 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
1632 RETURN_FALSE;
1633 }
1634
1635 post = GET_PROP(obj, postFields);
1636 zend_hash_clean(Z_ARRVAL_P(post));
1637 array_copy(post_data, post);
1638
1639 RETURN_TRUE;
1640 }
1641 /* }}}*/
1642
1643 /* {{{ proto array HttpRequest::getPostFields()
1644 *
1645 * Get previously set POST data.
1646 */
1647 PHP_METHOD(HttpRequest, getPostFields)
1648 {
1649 NO_ARGS;
1650
1651 IF_RETVAL_USED {
1652 zval *post_data;
1653 getObject(http_request_object, obj);
1654
1655 post_data = GET_PROP(obj, postFields);
1656 array_init(return_value);
1657 array_copy(post_data, return_value);
1658 }
1659 }
1660 /* }}} */
1661
1662 /* {{{ proto void HttpRequest::unsetPostFields()
1663 *
1664 * Clean POST data entires.
1665 * Affects only POST requests.
1666 */
1667 PHP_METHOD(HttpRequest, unsetPostFields)
1668 {
1669 zval *post_data;
1670 getObject(http_request_object, obj);
1671
1672 NO_ARGS;
1673
1674 post_data = GET_PROP(obj, postFields);
1675 zend_hash_clean(Z_ARRVAL_P(post_data));
1676 }
1677 /* }}} */
1678
1679 /* {{{ proto bool HttpRequest::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
1680 *
1681 * Add a file to the POST request.
1682 * Affects only POST requests.
1683 */
1684 PHP_METHOD(HttpRequest, addPostFile)
1685 {
1686 zval *files, *entry;
1687 char *name, *file, *type = NULL;
1688 int name_len, file_len, type_len = 0;
1689 getObject(http_request_object, obj);
1690
1691 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) {
1692 RETURN_FALSE;
1693 }
1694
1695 if (type_len) {
1696 if (!strchr(type, '/')) {
1697 http_error_ex(E_WARNING, HTTP_E_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
1698 RETURN_FALSE;
1699 }
1700 } else {
1701 type = "application/x-octetstream";
1702 type_len = sizeof("application/x-octetstream") - 1;
1703 }
1704
1705 MAKE_STD_ZVAL(entry);
1706 array_init(entry);
1707
1708 add_assoc_stringl(entry, "name", name, name_len, 1);
1709 add_assoc_stringl(entry, "type", type, type_len, 1);
1710 add_assoc_stringl(entry, "file", file, file_len, 1);
1711
1712 files = GET_PROP(obj, postFiles);
1713 add_next_index_zval(files, entry);
1714
1715 RETURN_TRUE;
1716 }
1717 /* }}} */
1718
1719 /* {{{ proto array HttpRequest::getPostFiles()
1720 *
1721 * Get all previously added POST files.
1722 */
1723 PHP_METHOD(HttpRequest, getPostFiles)
1724 {
1725 NO_ARGS;
1726
1727 IF_RETVAL_USED {
1728 zval *files;
1729 getObject(http_request_object, obj);
1730
1731 files = GET_PROP(obj, postFiles);
1732
1733 array_init(return_value);
1734 array_copy(files, return_value);
1735 }
1736 }
1737 /* }}} */
1738
1739 /* {{{ proto void HttpRequest::unsetPostFiles()
1740 *
1741 * Unset the POST files list.
1742 * Affects only POST requests.
1743 */
1744 PHP_METHOD(HttpRequest, unsetPostFiles)
1745 {
1746 zval *files;
1747 getObject(http_request_object, obj);
1748
1749 NO_ARGS;
1750
1751 files = GET_PROP(obj, postFiles);
1752 zend_hash_clean(Z_ARRVAL_P(files));
1753 }
1754 /* }}} */
1755
1756 /* {{{ proto array HttpRequest::getResponseData()
1757 *
1758 * Get all response data after the request has been sent.
1759 */
1760 PHP_METHOD(HttpRequest, getResponseData)
1761 {
1762 NO_ARGS;
1763
1764 IF_RETVAL_USED {
1765 zval *data;
1766 getObject(http_request_object, obj);
1767
1768 data = GET_PROP(obj, responseData);
1769 array_init(return_value);
1770 array_copy(data, return_value);
1771 }
1772 }
1773 /* }}} */
1774
1775 /* {{{ proto mixed HttpRequest::getResponseHeader([string name])
1776 *
1777 * Get response header(s) after the request has been sent.
1778 */
1779 PHP_METHOD(HttpRequest, getResponseHeader)
1780 {
1781 IF_RETVAL_USED {
1782 zval *data, **headers, **header;
1783 char *header_name = NULL;
1784 int header_len = 0;
1785 getObject(http_response_object, obj);
1786
1787 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &header_name, &header_len)) {
1788 RETURN_FALSE;
1789 }
1790
1791 data = GET_PROP(obj, responseData);
1792 if (SUCCESS != zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
1793 RETURN_FALSE;
1794 }
1795
1796 if (!header_len || !header_name) {
1797 array_init(return_value);
1798 array_copy(*headers, return_value);
1799 } else if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(headers), pretty_key(header_name, header_len, 1, 1), header_len + 1, (void **) &header)) {
1800 RETURN_STRINGL(Z_STRVAL_PP(header), Z_STRLEN_PP(header), 1);
1801 } else {
1802 RETURN_FALSE;
1803 }
1804 }
1805 }
1806 /* }}} */
1807
1808 /* {{{ proto array HttpRequest::getResponseCookie([string name])
1809 *
1810 * Get response cookie(s) after the request has been sent.
1811 */
1812 PHP_METHOD(HttpRequest, getResponseCookie)
1813 {
1814 IF_RETVAL_USED {
1815 zval *data, **headers;
1816 char *cookie_name = NULL;
1817 int cookie_len = 0;
1818 getObject(http_request_object, obj);
1819
1820 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cookie_name, &cookie_len)) {
1821 RETURN_FALSE;
1822 }
1823
1824 array_init(return_value);
1825
1826 data = GET_PROP(obj, responseData);
1827 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
1828 ulong idx = 0;
1829 char *key = NULL;
1830 zval **header = NULL;
1831
1832 FOREACH_HASH_KEYVAL(Z_ARRVAL_PP(headers), key, idx, header) {
1833 if (key && !strcasecmp(key, "Set-Cookie")) {
1834 /* several cookies? */
1835 if (Z_TYPE_PP(header) == IS_ARRAY) {
1836 zval **cookie;
1837
1838 FOREACH_HASH_VAL(Z_ARRVAL_PP(header), cookie) {
1839 zval *cookie_hash;
1840 MAKE_STD_ZVAL(cookie_hash);
1841 array_init(cookie_hash);
1842
1843 if (SUCCESS == http_parse_cookie(Z_STRVAL_PP(cookie), Z_ARRVAL_P(cookie_hash))) {
1844 if (!cookie_len) {
1845 add_next_index_zval(return_value, cookie_hash);
1846 } else {
1847 zval **name;
1848
1849 if ( (SUCCESS == zend_hash_find(Z_ARRVAL_P(cookie_hash), "name", sizeof("name"), (void **) &name)) &&
1850 (!strcmp(Z_STRVAL_PP(name), cookie_name))) {
1851 add_next_index_zval(return_value, cookie_hash);
1852 return; /* <<< FOUND >>> */
1853 } else {
1854 zval_dtor(cookie_hash);
1855 efree(cookie_hash);
1856 }
1857 }
1858 } else {
1859 zval_dtor(cookie_hash);
1860 efree(cookie_hash);
1861 }
1862 }
1863 } else {
1864 zval *cookie_hash;
1865 MAKE_STD_ZVAL(cookie_hash);
1866 array_init(cookie_hash);
1867
1868 if (SUCCESS == http_parse_cookie(Z_STRVAL_PP(header), Z_ARRVAL_P(cookie_hash))) {
1869 if (!cookie_len) {
1870 add_next_index_zval(return_value, cookie_hash);
1871 } else {
1872 zval **name;
1873
1874 if ( (SUCCESS == zend_hash_find(Z_ARRVAL_P(cookie_hash), "name", sizeof("name"), (void **) &name)) &&
1875 (!strcmp(Z_STRVAL_PP(name), cookie_name))) {
1876 add_next_index_zval(return_value, cookie_hash);
1877 } else {
1878 zval_dtor(cookie_hash);
1879 efree(cookie_hash);
1880 }
1881 }
1882 } else {
1883 zval_dtor(cookie_hash);
1884 efree(cookie_hash);
1885 }
1886 }
1887 break;
1888 }
1889 /* reset key */
1890 key = NULL;
1891 }
1892 }
1893 }
1894 }
1895 /* }}} */
1896
1897 /* {{{ proto string HttpRequest::getResponseBody()
1898 *
1899 * Get the response body after the request has been sent.
1900 */
1901 PHP_METHOD(HttpRequest, getResponseBody)
1902 {
1903 NO_ARGS;
1904
1905 IF_RETVAL_USED {
1906 zval *data, **body;
1907 getObject(http_request_object, obj);
1908
1909 data = GET_PROP(obj, responseData);
1910 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) {
1911 RETURN_STRINGL(Z_STRVAL_PP(body), Z_STRLEN_PP(body), 1);
1912 } else {
1913 RETURN_FALSE;
1914 }
1915 }
1916 }
1917 /* }}} */
1918
1919 /* {{{ proto int HttpRequest::getResponseCode()
1920 *
1921 * Get the response code after the request has been sent.
1922 */
1923 PHP_METHOD(HttpRequest, getResponseCode)
1924 {
1925 NO_ARGS;
1926
1927 IF_RETVAL_USED {
1928 zval *code;
1929 getObject(http_request_object, obj);
1930
1931 code = GET_PROP(obj, responseCode);
1932 RETURN_LONG(Z_LVAL_P(code));
1933 }
1934 }
1935 /* }}} */
1936
1937 /* {{{ proto array HttpRequest::getResponseInfo([string name])
1938 *
1939 * Get response info after the request has been sent.
1940 * See http_get() for a full list of returned info.
1941 */
1942 PHP_METHOD(HttpRequest, getResponseInfo)
1943 {
1944 IF_RETVAL_USED {
1945 zval *info, **infop;
1946 char *info_name = NULL;
1947 int info_len = 0;
1948 getObject(http_request_object, obj);
1949
1950 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &info_name, &info_len)) {
1951 RETURN_FALSE;
1952 }
1953
1954 info = GET_PROP(obj, responseInfo);
1955
1956 if (info_len && info_name) {
1957 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void **) &infop)) {
1958 RETURN_ZVAL(*infop, 1, ZVAL_PTR_DTOR);
1959 } else {
1960 http_error_ex(E_NOTICE, HTTP_E_PARAM, "Could not find response info named %s", info_name);
1961 RETURN_FALSE;
1962 }
1963 } else {
1964 array_init(return_value);
1965 array_copy(info, return_value);
1966 }
1967 }
1968 }
1969 /* }}}*/
1970
1971 /* {{{ proto HttpMessage HttpRequest::getResponseMessage()
1972 *
1973 * Get the full response as HttpMessage object.
1974 */
1975 PHP_METHOD(HttpRequest, getResponseMessage)
1976 {
1977 NO_ARGS;
1978
1979 IF_RETVAL_USED {
1980 zval *message;
1981 getObject(http_request_object, obj);
1982
1983 message = GET_PROP(obj, responseMessage);
1984 Z_TYPE_P(return_value) = IS_OBJECT;
1985 return_value->is_ref = 1;
1986 return_value->value.obj = message->value.obj;
1987 zval_add_ref(&return_value);
1988 }
1989 }
1990
1991 /* {{{ proto bool HttpRequest::send()
1992 *
1993 * Send the HTTP request.
1994 *
1995 * GET example:
1996 * <pre>
1997 * <?php
1998 * $r = new HttpRequest('http://example.com/feed.rss', HTTP_GET);
1999 * $r->setOptions(array('lastmodified' => filemtime('local.rss')));
2000 * $r->addQueryData(array('category' => 3));
2001 * try {
2002 * $r->send();
2003 * if ($r->getResponseCode() == 200) {
2004 * file_put_contents('local.rss', $r->getResponseBody());
2005 * }
2006 * } catch (HttpException $ex) {
2007 * echo $ex;
2008 * }
2009 * ?>
2010 * </pre>
2011 *
2012 * POST example:
2013 * <pre>
2014 * <?php
2015 * $r = new HttpRequest('http://example.com/form.php', HTTP_POST);
2016 * $r->setOptions(array('cookies' => array('lang' => 'de')));
2017 * $r->addpostFields(array('user' => 'mike', 'pass' => 's3c|r3t'));
2018 * $r->addPostFile('image', 'profile.jpg', 'image/jpeg');
2019 * if ($r->send()) {
2020 * echo $r->getResponseBody();
2021 * }
2022 * ?>
2023 * </pre>
2024 */
2025 PHP_METHOD(HttpRequest, send)
2026 {
2027 STATUS status = FAILURE;
2028 zval *meth, *URL, *qdata, *opts, *info, *resp;
2029 char *request_uri;
2030 getObject(http_request_object, obj);
2031
2032 NO_ARGS;
2033
2034 SET_EH_THROW_HTTP();
2035
2036 if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) {
2037 http_error(E_WARNING, HTTP_E_CURL, "Could not initilaize curl");
2038 RETURN_FALSE;
2039 }
2040
2041 meth = GET_PROP(obj, method);
2042 URL = GET_PROP(obj, url);
2043 qdata = GET_PROP(obj, queryData);
2044 opts = GET_PROP(obj, options);
2045 info = GET_PROP(obj, responseInfo);
2046 resp = GET_PROP(obj, responseData);
2047
2048 // HTTP_URI_MAXLEN+1 long char *
2049 if (!(request_uri = http_absolute_uri_ex(Z_STRVAL_P(URL), Z_STRLEN_P(URL), NULL, 0, NULL, 0, 0))) {
2050 RETURN_FALSE;
2051 }
2052
2053 if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) {
2054 if (!strchr(request_uri, '?')) {
2055 strcat(request_uri, "?");
2056 } else {
2057 strcat(request_uri, "&");
2058 }
2059 strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri));
2060 }
2061
2062 switch (Z_LVAL_P(meth))
2063 {
2064 case HTTP_GET:
2065 case HTTP_HEAD:
2066 status = http_request_ex(obj->ch, Z_LVAL_P(meth), request_uri, NULL, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
2067 break;
2068
2069 case HTTP_PUT:
2070 {
2071 http_request_body body;
2072 php_stream *stream;
2073 php_stream_statbuf ssb;
2074 zval *file = GET_PROP(obj, putFile);
2075
2076 if ( (stream = php_stream_open_wrapper(Z_STRVAL_P(file), "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL)) &&
2077 !php_stream_stat(stream, &ssb)) {
2078 body.type = HTTP_REQUEST_BODY_UPLOADFILE;
2079 body.data = stream;
2080 body.size = ssb.sb.st_size;
2081
2082 status = http_put_ex(obj->ch, request_uri, &body, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
2083 http_request_body_dtor(&body);
2084 } else {
2085 status = FAILURE;
2086 }
2087 }
2088 break;
2089
2090 case HTTP_POST:
2091 {
2092 http_request_body body;
2093 zval *fields = GET_PROP(obj, postFields), *files = GET_PROP(obj, postFiles);
2094
2095 if (SUCCESS == (status = http_request_body_fill(&body, Z_ARRVAL_P(fields), Z_ARRVAL_P(files)))) {
2096 status = http_post_ex(obj->ch, request_uri, &body, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
2097 http_request_body_dtor(&body);
2098 }
2099 }
2100 break;
2101
2102 default:
2103 {
2104 http_request_body body;
2105 zval *post = GET_PROP(obj, postData);
2106
2107 body.type = HTTP_REQUEST_BODY_CSTRING;
2108 body.data = Z_STRVAL_P(post);
2109 body.size = Z_STRLEN_P(post);
2110
2111 status = http_request_ex(obj->ch, Z_LVAL_P(meth), request_uri, &body, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
2112 }
2113 break;
2114 }
2115
2116 efree(request_uri);
2117
2118 /* final data handling */
2119 if (status == SUCCESS) {
2120 http_message *msg;
2121
2122 if (msg = http_message_parse(PHPSTR_VAL(&obj->response), PHPSTR_LEN(&obj->response))) {
2123 zval *headers, *message;
2124 char *body;
2125 size_t body_len;
2126
2127 UPD_PROP(obj, long, responseCode, msg->info.response.code);
2128
2129 MAKE_STD_ZVAL(headers)
2130 array_init(headers);
2131
2132 zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
2133 phpstr_data(PHPSTR(msg), &body, &body_len);
2134
2135 add_assoc_zval(resp, "headers", headers);
2136 add_assoc_stringl(resp, "body", body, body_len, 0);
2137
2138 message = GET_PROP(obj, responseMessage);
2139 zval_dtor(message);
2140 Z_TYPE_P(message) = IS_OBJECT;
2141 message->value.obj = http_message_object_from_msg(msg);
2142 SET_PROP(obj, responseMessage, message);
2143 } else {
2144 status = FAILURE;
2145 }
2146 }
2147
2148 SET_EH_NORMAL();
2149 RETURN_SUCCESS(status);
2150 }
2151 /* }}} */
2152 /* }}} */
2153 #endif /* HTTP_HAVE_CURL */
2154
2155 #endif /* ZEND_ENGINE_2 */
2156
2157 /*
2158 * Local variables:
2159 * tab-width: 4
2160 * c-basic-offset: 4
2161 * End:
2162 * vim600: noet sw=4 ts=4 fdm=marker
2163 * vim<600: noet sw=4 ts=4
2164 */