- docs
[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 #include "missing.h"
44
45 ZEND_EXTERN_MODULE_GLOBALS(http)
46
47 /* {{{ HttpResponse */
48
49 /* {{{ proto void HttpResponse::__construct(bool cache, bool gzip)
50 *
51 * Instantiates a new HttpResponse object, which can be used to send
52 * any data/resource/file to an HTTP client with caching and multiple
53 * ranges/resuming support.
54 *
55 * NOTE: GZIPping is not implemented yet.
56 */
57 PHP_METHOD(HttpResponse, __construct)
58 {
59 zend_bool do_cache = 0, do_gzip = 0;
60 getObject(http_response_object, obj);
61
62 SET_EH_THROW_HTTP();
63 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bb", &do_cache, &do_gzip)) {
64 UPD_PROP(obj, long, cache, do_cache);
65 UPD_PROP(obj, long, gzip, do_gzip);
66 }
67 SET_EH_NORMAL();
68 }
69 /* }}} */
70
71 /* {{{ proto bool HttpResponse::setCache(bool cache)
72 *
73 * Whether it sould be attempted to cache the entitity.
74 * This will result in necessary caching headers and checks of clients
75 * "If-Modified-Since" and "If-None-Match" headers. If one of those headers
76 * matches a "304 Not Modified" status code will be issued.
77 *
78 * NOTE: If you're using sessions, be shure that you set session.cache_limiter
79 * to something more appropriate than "no-cache"!
80 */
81 PHP_METHOD(HttpResponse, setCache)
82 {
83 zend_bool do_cache = 0;
84 getObject(http_response_object, obj);
85
86 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) {
87 RETURN_FALSE;
88 }
89
90 UPD_PROP(obj, long, cache, do_cache);
91 RETURN_TRUE;
92 }
93 /* }}} */
94
95 /* {{{ proto bool HttpResponse::getCache()
96 *
97 * Get current caching setting.
98 */
99 PHP_METHOD(HttpResponse, getCache)
100 {
101 NO_ARGS;
102
103 IF_RETVAL_USED {
104 zval *do_cache = NULL;
105 getObject(http_response_object, obj);
106
107 do_cache = GET_PROP(obj, cache);
108 RETURN_BOOL(Z_LVAL_P(do_cache));
109 }
110 }
111 /* }}}*/
112
113 /* {{{ proto bool HttpResponse::setGzip(bool gzip)
114 *
115 * Enable on-thy-fly gzipping of the sent entity. NOT IMPLEMENTED YET.
116 */
117 PHP_METHOD(HttpResponse, setGzip)
118 {
119 zend_bool do_gzip = 0;
120 getObject(http_response_object, obj);
121
122 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) {
123 RETURN_FALSE;
124 }
125
126 UPD_PROP(obj, long, gzip, do_gzip);
127 RETURN_TRUE;
128 }
129 /* }}} */
130
131 /* {{{ proto bool HttpResponse::getGzip()
132 *
133 * Get current gzipping setting.
134 */
135 PHP_METHOD(HttpResponse, getGzip)
136 {
137 NO_ARGS;
138
139 IF_RETVAL_USED {
140 zval *do_gzip;
141 getObject(http_response_object, obj);
142
143 do_gzip = GET_PROP(obj, gzip);
144 RETURN_BOOL(Z_LVAL_P(do_gzip));
145 }
146 }
147 /* }}} */
148
149 /* {{{ proto bool HttpResponse::setCacheControl(string control[, bool raw = false])
150 *
151 * Set a custom cache-control header, usually being "private" or "public"; if
152 * $raw is set to true the header will be sent as-is.
153 */
154 PHP_METHOD(HttpResponse, setCacheControl)
155 {
156 char *ccontrol;
157 int cc_len;
158 zend_bool raw = 0;
159 getObject(http_response_object, obj);
160
161 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &ccontrol, &cc_len, &raw)) {
162 RETURN_FALSE;
163 }
164
165 if ((!raw) && (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache"))) {
166 http_error_ex(E_WARNING, HTTP_E_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
167 RETURN_FALSE;
168 }
169
170 UPD_PROP(obj, long, raw_cache_header, raw);
171 UPD_PROP(obj, string, cacheControl, ccontrol);
172 RETURN_TRUE;
173 }
174 /* }}} */
175
176 /* {{{ proto string HttpResponse::getCacheControl()
177 *
178 * Get current Cache-Control header setting.
179 */
180 PHP_METHOD(HttpResponse, getCacheControl)
181 {
182 NO_ARGS;
183
184 IF_RETVAL_USED {
185 zval *ccontrol;
186 getObject(http_response_object, obj);
187
188 ccontrol = GET_PROP(obj, cacheControl);
189 RETURN_STRINGL(Z_STRVAL_P(ccontrol), Z_STRLEN_P(ccontrol), 1);
190 }
191 }
192 /* }}} */
193
194 /* {{{ proto bool HttpResponse::setContentType(string content_type)
195 *
196 * Set the content-type of the sent entity.
197 */
198 PHP_METHOD(HttpResponse, setContentType)
199 {
200 char *ctype;
201 int ctype_len;
202 getObject(http_response_object, obj);
203
204 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) {
205 RETURN_FALSE;
206 }
207
208 if (!strchr(ctype, '/')) {
209 http_error_ex(E_WARNING, HTTP_E_PARAM, "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype);
210 RETURN_FALSE;
211 }
212
213 UPD_PROP(obj, string, contentType, ctype);
214
215 RETURN_TRUE;
216 }
217 /* }}} */
218
219 /* {{{ proto string HttpResponse::getContentType()
220 *
221 * Get current Content-Type header setting.
222 */
223 PHP_METHOD(HttpResponse, getContentType)
224 {
225 NO_ARGS;
226
227 IF_RETVAL_USED {
228 zval *ctype;
229 getObject(http_response_object, obj);
230
231 ctype = GET_PROP(obj, contentType);
232 RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
233 }
234 }
235 /* }}} */
236
237 /* {{{ proto bool HttpResponse::setContentDisposition(string filename[, bool inline = false])
238 *
239 * Set the Content-Disposition of the sent entity. This setting aims to suggest
240 * the receiveing user agent how to handle the sent entity; usually the client
241 * will show the user a "Save As..." popup.
242 */
243 PHP_METHOD(HttpResponse, setContentDisposition)
244 {
245 char *file;
246 int file_len;
247 zend_bool is_inline = 0;
248 getObject(http_response_object, obj);
249
250 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &is_inline)) {
251 RETURN_FALSE;
252 }
253
254 UPD_PROP(obj, string, dispoFile, file);
255 UPD_PROP(obj, long, dispoInline, is_inline);
256 RETURN_TRUE;
257 }
258 /* }}} */
259
260 /* {{{ proto array HttpResponse::getContentDisposition()
261 *
262 * Get current Content-Disposition setting.
263 * Will return an associative array like:
264 * <pre>
265 * array(
266 * 'filename' => 'foo.bar',
267 * 'inline' => false
268 * )
269 * </pre>
270 */
271 PHP_METHOD(HttpResponse, getContentDisposition)
272 {
273 NO_ARGS;
274
275 IF_RETVAL_USED {
276 zval *file, *is_inline;
277 getObject(http_response_object, obj);
278
279 file = GET_PROP(obj, dispoFile);
280 is_inline = GET_PROP(obj, dispoInline);
281
282 array_init(return_value);
283 add_assoc_stringl(return_value, "filename", Z_STRVAL_P(file), Z_STRLEN_P(file), 1);
284 add_assoc_bool(return_value, "inline", Z_LVAL_P(is_inline));
285 }
286 }
287 /* }}} */
288
289 /* {{{ proto bool HttpResponse::setETag(string etag)
290 *
291 * Set a custom ETag. Use this only if you know what you're doing.
292 */
293 PHP_METHOD(HttpResponse, setETag)
294 {
295 char *etag;
296 int etag_len;
297 getObject(http_response_object, obj);
298
299 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) {
300 RETURN_FALSE;
301 }
302
303 UPD_PROP(obj, string, eTag, etag);
304 RETURN_TRUE;
305 }
306 /* }}} */
307
308 /* {{{ proto string HttpResponse::getETag()
309 *
310 * Get the previously set custom ETag.
311 */
312 PHP_METHOD(HttpResponse, getETag)
313 {
314 NO_ARGS;
315
316 IF_RETVAL_USED {
317 zval *etag;
318 getObject(http_response_object, obj);
319
320 etag = GET_PROP(obj, eTag);
321 RETURN_STRINGL(Z_STRVAL_P(etag), Z_STRLEN_P(etag), 1);
322 }
323 }
324 /* }}} */
325
326 /* {{{ proto void HttpResponse::setThrottleDelay(double seconds)
327 *
328 */
329 PHP_METHOD(HttpResponse, setThrottleDelay)
330 {
331 double seconds;
332
333 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &seconds)) {
334 getObject(http_response_object, obj);
335
336 UPD_PROP(obj, double, throttleDelay, seconds);
337 }
338 }
339 /* }}} */
340
341 /* {{{ proto double HttpResponse::getThrottleDelay()
342 *
343 */
344 PHP_METHOD(HttpResponse, getThrottleDelay)
345 {
346 NO_ARGS;
347
348 IF_RETVAL_USED {
349 zval *seconds;
350 getObject(http_response_object, obj);
351
352 seconds = GET_PROP(obj, throttleDelay);
353 RETURN_DOUBLE(Z_DVAL_P(seconds));
354 }
355 }
356 /* }}} */
357
358 /* {{{ proto void HttpResponse::setSendBuffersize(long bytes)
359 *
360 */
361 PHP_METHOD(HttpResponse, setSendBuffersize)
362 {
363 long bytes;
364
365 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bytes)) {
366 getObject(http_response_object, obj);
367
368 UPD_PROP(obj, long, sendBuffersize, bytes);
369 }
370 }
371 /* }}} */
372
373 /* {{{ proto long HttpResponse::getSendBuffersize()
374 *
375 */
376 PHP_METHOD(HttpResponse, getSendBuffersize)
377 {
378 NO_ARGS;
379
380 IF_RETVAL_USED {
381 zval *bytes;
382 getObject(http_response_object, obj);
383
384 bytes = GET_PROP(obj, sendBuffersize);
385 RETURN_LONG(Z_LVAL_P(bytes));
386 }
387 }
388 /* }}} */
389
390 /* {{{ proto bool HttpResponse::setData(string data)
391 *
392 * Set the data to be sent.
393 */
394 PHP_METHOD(HttpResponse, setData)
395 {
396 zval *the_data;
397 getObject(http_response_object, obj);
398
399 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &the_data)) {
400 RETURN_FALSE;
401 }
402
403 convert_to_string_ex(&the_data);
404 SET_PROP(obj, data, the_data);
405 UPD_PROP(obj, long, lastModified, http_last_modified(the_data, SEND_DATA));
406 UPD_PROP(obj, long, send_mode, SEND_DATA);
407 RETURN_TRUE;
408 }
409 /* }}} */
410
411 /* {{{ proto string HttpResponse::getData()
412 *
413 * Get the previously set data to be sent.
414 */
415 PHP_METHOD(HttpResponse, getData)
416 {
417 NO_ARGS;
418
419 IF_RETVAL_USED {
420 zval *the_data;
421 getObject(http_response_object, obj);
422
423 the_data = GET_PROP(obj, data);
424 RETURN_STRINGL(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), 1);
425 }
426 }
427 /* }}} */
428
429 /* {{{ proto bool HttpResponse::setStream(resource stream)
430 *
431 * Set the resource to be sent.
432 */
433 PHP_METHOD(HttpResponse, setStream)
434 {
435 zval *the_stream;
436 php_stream *the_real_stream;
437 getObject(http_response_object, obj);
438
439 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
440 RETURN_FALSE;
441 }
442
443 php_stream_from_zval(the_real_stream, &the_stream);
444
445 SET_PROP(obj, stream, the_stream);
446 UPD_PROP(obj, long, lastModified, http_last_modified(the_real_stream, SEND_RSRC));
447 UPD_PROP(obj, long, send_mode, SEND_RSRC);
448 RETURN_TRUE;
449 }
450 /* }}} */
451
452 /* {{{ proto resource HttpResponse::getStream()
453 *
454 * Get the previously set resource to be sent.
455 */
456 PHP_METHOD(HttpResponse, getStream)
457 {
458 NO_ARGS;
459
460 IF_RETVAL_USED {
461 zval *the_stream;
462 getObject(http_response_object, obj);
463
464 the_stream = GET_PROP(obj, stream);
465 RETURN_RESOURCE(Z_LVAL_P(the_stream));
466 }
467 }
468 /* }}} */
469
470 /* {{{ proto bool HttpResponse::setFile(string file)
471 *
472 * Set the file to be sent.
473 */
474 PHP_METHOD(HttpResponse, setFile)
475 {
476 zval *the_file;
477 getObject(http_response_object, obj);
478
479 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_file)) {
480 RETURN_FALSE;
481 }
482
483 convert_to_string_ex(&the_file);
484
485 UPD_PROP(obj, string, file, Z_STRVAL_P(the_file));
486 UPD_PROP(obj, long, lastModified, http_last_modified(the_file, -1));
487 UPD_PROP(obj, long, send_mode, -1);
488 RETURN_TRUE;
489 }
490 /* }}} */
491
492 /* {{{ proto string HttpResponse::getFile()
493 *
494 * Get the previously set file to be sent.
495 */
496 PHP_METHOD(HttpResponse, getFile)
497 {
498 NO_ARGS;
499
500 IF_RETVAL_USED {
501 zval *the_file;
502 getObject(http_response_object, obj);
503
504 the_file = GET_PROP(obj, file);
505 RETURN_STRINGL(Z_STRVAL_P(the_file), Z_STRLEN_P(the_file), 1);
506 }
507 }
508 /* }}} */
509
510 /* {{{ proto bool HttpResponse::send()
511 *
512 * Finally send the entity.
513 *
514 * Example:
515 * <pre>
516 * <?php
517 * $r = new HttpResponse(true);
518 * $r->setFile('../hidden/contract.pdf');
519 * $r->setContentType('application/pdf');
520 * $r->send();
521 * ?>
522 * </pre>
523 *
524 */
525 PHP_METHOD(HttpResponse, send)
526 {
527 zval *do_cache, *do_gzip;
528 getObject(http_response_object, obj);
529
530 NO_ARGS;
531
532 do_cache = GET_PROP(obj, cache);
533 do_gzip = GET_PROP(obj, gzip);
534
535 /* gzip */
536 if (Z_LVAL_P(do_gzip)) {
537 php_start_ob_buffer_named("ob_gzhandler", 0, 1 TSRMLS_CC);
538 }
539
540 /* caching */
541 if (Z_LVAL_P(do_cache)) {
542 char *cc_hdr;
543 int cc_len;
544 zval *cctrl, *etag, *lmod, *ccraw;
545
546 etag = GET_PROP(obj, eTag);
547 lmod = GET_PROP(obj, lastModified);
548 cctrl = GET_PROP(obj, cacheControl);
549 ccraw = GET_PROP(obj, raw_cache_header);
550
551 if (Z_LVAL_P(ccraw)) {
552 cc_hdr = Z_STRVAL_P(cctrl);
553 cc_len = Z_STRLEN_P(cctrl);
554 } else {
555 char cc_header[42] = {0};
556 sprintf(cc_header, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl));
557 cc_hdr = cc_header;
558 cc_len = Z_STRLEN_P(cctrl) + lenof(", must-revalidate, max-age=0");
559 }
560
561 http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), cc_hdr, cc_len);
562 http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), cc_hdr, cc_len);
563 }
564
565 /* content type */
566 {
567 zval *ctype = GET_PROP(obj, contentType);
568 if (Z_STRLEN_P(ctype)) {
569 http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
570 } else {
571 http_send_content_type("application/x-octetstream", lenof("application/x-octetstream"));
572 }
573 }
574
575 /* content disposition */
576 {
577 zval *dispo_file = GET_PROP(obj, dispoFile);
578 if (Z_STRLEN_P(dispo_file)) {
579 zval *dispo_inline = GET_PROP(obj, dispoInline);
580 http_send_content_disposition(Z_STRVAL_P(dispo_file), Z_STRLEN_P(dispo_file), (zend_bool) Z_LVAL_P(dispo_inline));
581 }
582 }
583
584 /* throttling */
585 {
586 zval *send_buffersize, *throttle_delay;
587 send_buffersize = GET_PROP(obj, sendBuffersize);
588 throttle_delay = GET_PROP(obj, throttleDelay);
589 HTTP_G(send).buffer_size = Z_LVAL_P(send_buffersize);
590 HTTP_G(send).throttle_delay = Z_DVAL_P(throttle_delay);
591 }
592
593 /* send */
594 {
595 zval *send_mode = GET_PROP(obj, send_mode);
596 switch (Z_LVAL_P(send_mode))
597 {
598 case SEND_DATA:
599 {
600 zval *zdata = GET_PROP(obj, data);
601 RETURN_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)));
602 }
603
604 case SEND_RSRC:
605 {
606 php_stream *the_real_stream;
607 zval *the_stream = GET_PROP(obj, stream);
608 php_stream_from_zval(the_real_stream, &the_stream);
609 RETURN_SUCCESS(http_send_stream(the_real_stream));
610 }
611
612 default:
613 {
614 zval *zfile = GET_PROP(obj, file);
615 RETURN_SUCCESS(http_send_file(Z_STRVAL_P(zfile)));
616 }
617 }
618 }
619 }
620 /* }}} */
621 /* }}} */
622
623 /* {{{ HttpMessage */
624
625 /* {{{ proto static HttpMessage HttpMessage::fromString(string raw_message)
626 *
627 * Create an HttpMessage object from a string.
628 */
629 PHP_METHOD(HttpMessage, fromString)
630 {
631 char *string = NULL;
632 int length = 0;
633 http_message *msg = NULL;
634
635 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &length)) {
636 RETURN_NULL();
637 }
638
639 if (!(msg = http_message_parse(string, length))) {
640 RETURN_NULL();
641 }
642
643 Z_TYPE_P(return_value) = IS_OBJECT;
644 return_value->value.obj = http_message_object_from_msg(msg);
645 }
646 /* }}} */
647
648 /* {{{ proto void HttpMessage::__construct([string message])
649 *
650 * Instantiate a new HttpMessage object.
651 */
652 PHP_METHOD(HttpMessage, __construct)
653 {
654 char *message = NULL;
655 int length = 0;
656 getObject(http_message_object, obj);
657
658 SET_EH_THROW_HTTP();
659 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &message, &length) && message && length) {
660 if (obj->message = http_message_parse(message, length)) {
661 if (obj->message->parent) {
662 obj->parent = http_message_object_from_msg(obj->message->parent);
663 }
664 }
665 } else if (!obj->message) {
666 obj->message = http_message_new();
667 }
668 SET_EH_NORMAL();
669 }
670 /* }}} */
671
672 /* {{{ proto string HttpMessage::getBody()
673 *
674 * Get the body of the parsed Message.
675 */
676 PHP_METHOD(HttpMessage, getBody)
677 {
678 NO_ARGS;
679
680 IF_RETVAL_USED {
681 getObject(http_message_object, obj);
682 RETURN_PHPSTR(&obj->message->body, PHPSTR_FREE_NOT, 1);
683 }
684 }
685 /* }}} */
686
687 /* {{{ proto array HttpMessage::getHeaders()
688 *
689 * Get Message Headers.
690 */
691 PHP_METHOD(HttpMessage, getHeaders)
692 {
693 NO_ARGS;
694
695 IF_RETVAL_USED {
696 zval headers;
697 getObject(http_message_object, obj);
698
699 Z_ARRVAL(headers) = &obj->message->hdrs;
700 array_init(return_value);
701 array_copy(&headers, return_value);
702 }
703 }
704 /* }}} */
705
706 /* {{{ proto void HttpMessage::setHeaders(array headers)
707 *
708 * Sets new headers.
709 */
710 PHP_METHOD(HttpMessage, setHeaders)
711 {
712 zval *new_headers, old_headers;
713 getObject(http_message_object, obj);
714
715 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &new_headers)) {
716 return;
717 }
718
719 zend_hash_clean(&obj->message->hdrs);
720 Z_ARRVAL(old_headers) = &obj->message->hdrs;
721 array_copy(new_headers, &old_headers);
722 }
723 /* }}} */
724
725 /* {{{ proto void HttpMessage::addHeaders(array headers[, bool append = false])
726 *
727 * Add headers. If append is true, headers with the same name will be separated, else overwritten.
728 */
729 PHP_METHOD(HttpMessage, addHeaders)
730 {
731 zval old_headers, *new_headers;
732 zend_bool append = 0;
733 getObject(http_message_object, obj);
734
735 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &new_headers, &append)) {
736 return;
737 }
738
739 Z_ARRVAL(old_headers) = &obj->message->hdrs;
740 if (append) {
741 array_append(new_headers, &old_headers);
742 } else {
743 array_merge(new_headers, &old_headers);
744 }
745 }
746 /* }}} */
747
748 /* {{{ proto long HttpMessage::getType()
749 *
750 * Get Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE)
751 */
752 PHP_METHOD(HttpMessage, getType)
753 {
754 NO_ARGS;
755
756 IF_RETVAL_USED {
757 getObject(http_message_object, obj);
758 RETURN_LONG(obj->message->type);
759 }
760 }
761 /* }}} */
762
763 /* {{{ proto void HttpMessage::setType(long type)
764 *
765 * Set Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE)
766 */
767 PHP_METHOD(HttpMessage, setType)
768 {
769 long type;
770 getObject(http_message_object, obj);
771
772 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type)) {
773 return;
774 }
775 http_message_set_type(obj->message, type);
776 }
777 /* }}} */
778
779 /* {{{ proto long HttpMessage::getResponseCode()
780 *
781 * Get the Response Code of the Message.
782 */
783 PHP_METHOD(HttpMessage, getResponseCode)
784 {
785 NO_ARGS;
786
787 IF_RETVAL_USED {
788 getObject(http_message_object, obj);
789
790 if (!HTTP_MSG_TYPE(RESPONSE, obj->message)) {
791 http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
792 RETURN_NULL();
793 }
794
795 RETURN_LONG(obj->message->info.response.code);
796 }
797 }
798 /* }}} */
799
800 /* {{{ proto bool HttpMessage::setResponseCode(long code)
801 *
802 * Set the response code of an HTTP Response Message.
803 * Returns false if the Message is not of type HTTP_MSG_RESPONSE,
804 * or if the response code is out of range (100-510).
805 */
806 PHP_METHOD(HttpMessage, setResponseCode)
807 {
808 long code;
809 getObject(http_message_object, obj);
810
811 if (!HTTP_MSG_TYPE(RESPONSE, obj->message)) {
812 http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
813 RETURN_FALSE;
814 }
815
816 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
817 RETURN_FALSE;
818 }
819 if (code < 100 || code > 510) {
820 http_error_ex(E_WARNING, HTTP_E_PARAM, "Invalid response code (100-510): %ld", code);
821 RETURN_FALSE;
822 }
823
824 obj->message->info.response.code = code;
825 RETURN_TRUE;
826 }
827 /* }}} */
828
829 /* {{{ proto string HttpMessage::getRequestMethod()
830 *
831 * Get the Request Method of the Message.
832 * Returns false if the Message is not of type HTTP_MSG_REQUEST.
833 */
834 PHP_METHOD(HttpMessage, getRequestMethod)
835 {
836 NO_ARGS;
837
838 IF_RETVAL_USED {
839 getObject(http_message_object, obj);
840
841 if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
842 http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
843 RETURN_NULL();
844 }
845
846 RETURN_STRING(obj->message->info.request.method, 1);
847 }
848 }
849 /* }}} */
850
851 /* {{{ proto bool HttpMessage::setRequestMethod(string method)
852 *
853 * Set the Request Method of the HTTP Message.
854 * Returns false if the Message is not of type HTTP_MSG_REQUEST.
855 */
856 PHP_METHOD(HttpMessage, setRequestMethod)
857 {
858 char *method;
859 int method_len;
860 getObject(http_message_object, obj);
861
862 if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
863 http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
864 RETURN_FALSE;
865 }
866
867 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
868 RETURN_FALSE;
869 }
870 if (method_len < 1) {
871 http_error(E_WARNING, HTTP_E_PARAM, "Cannot set HttpMessage::requestMethod to an empty string");
872 RETURN_FALSE;
873 }
874 if (SUCCESS != http_check_method(method)) {
875 http_error_ex(E_WARNING, HTTP_E_PARAM, "Unkown request method: %s", method);
876 RETURN_FALSE;
877 }
878
879 STR_SET(obj->message->info.request.method, estrndup(method, method_len));
880 RETURN_TRUE;
881 }
882 /* }}} */
883
884 /* {{{ proto string HttpMessage::getRequestUri()
885 *
886 * Get the Request URI of the Message.
887 */
888 PHP_METHOD(HttpMessage, getRequestUri)
889 {
890 NO_ARGS;
891
892 IF_RETVAL_USED {
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;
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 */