2 +----------------------------------------------------------------------+
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 +----------------------------------------------------------------------+
19 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
27 #include "php_http_api.h"
28 #include "php_http_curl_api.h"
29 #include "php_http_std_defs.h"
31 #include "ext/standard/php_smart_str.h"
35 /* {{{ HTTPi_Response */
37 /* {{{ proto void HTTPi_Response::__construct(bool cache, bool gzip)
39 * Instantiates a new HTTPi_Response object, which can be used to send
40 * any data/resource/file to an HTTP client with caching and multiple
41 * ranges/resuming support.
43 * NOTE: GZIPping is not implemented yet.
45 PHP_METHOD(HTTPi_Response
, __construct
)
47 zend_bool do_cache
= 0, do_gzip
= 0;
48 getObject(httpi_response_object
, obj
);
50 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|bb", &do_cache
, &do_gzip
)) {
55 UPD_PROP(obj
, long, cache
, do_cache
);
56 UPD_PROP(obj
, long, gzip
, do_gzip
);
60 /* {{{ proto bool HTTPi_Response::setCache(bool cache)
62 * Whether it sould be attempted to cache the entitity.
63 * This will result in necessary caching headers and checks of clients
64 * "If-Modified-Since" and "If-None-Match" headers. If one of those headers
65 * matches a "304 Not Modified" status code will be issued.
67 * NOTE: If you're using sessions, be shure that you set session.cache_limiter
68 * to something more appropriate than "no-cache"!
70 PHP_METHOD(HTTPi_Response
, setCache
)
72 zend_bool do_cache
= 0;
73 getObject(httpi_response_object
, obj
);
75 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "b", &do_cache
)) {
79 UPD_PROP(obj
, long, cache
, do_cache
);
84 /* {{{ proto bool HTTPi_Response::getCache()
86 * Get current caching setting.
88 PHP_METHOD(HTTPi_Response
, getCache
)
90 zval
*do_cache
= NULL
;
91 getObject(httpi_response_object
, obj
);
95 do_cache
= GET_PROP(obj
, cache
);
96 RETURN_BOOL(Z_LVAL_P(do_cache
));
100 /* {{{ proto bool HTTPi_Response::setGzip(bool gzip)
102 * Enable on-thy-fly gzipping of the sent entity. NOT IMPLEMENTED YET.
104 PHP_METHOD(HTTPi_Response
, setGzip
)
106 zend_bool do_gzip
= 0;
107 getObject(httpi_response_object
, obj
);
109 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "b", &do_gzip
)) {
113 UPD_PROP(obj
, long, gzip
, do_gzip
);
118 /* {{{ proto bool HTTPi_Response::getGzip()
120 * Get current gzipping setting.
122 PHP_METHOD(HTTPi_Response
, getGzip
)
124 zval
*do_gzip
= NULL
;
125 getObject(httpi_response_object
, obj
);
129 do_gzip
= GET_PROP(obj
, gzip
);
130 RETURN_BOOL(Z_LVAL_P(do_gzip
));
134 /* {{{ proto bool HTTPi_Response::setCacheControl(string control[, bool raw = false])
136 * Set a custom cache-control header, usually being "private" or "public"; if
137 * $raw is set to true the header will be sent as-is.
139 PHP_METHOD(HTTPi_Response
, setCacheControl
)
144 getObject(httpi_response_object
, obj
);
146 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|b", &ccontrol
, &cc_len
, &raw
)) {
150 if ((!raw
) && (strcmp(ccontrol
, "public") && strcmp(ccontrol
, "private") && strcmp(ccontrol
, "no-cache"))) {
151 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol
);
155 UPD_PROP(obj
, long, raw_cache_header
, raw
);
156 UPD_PROP(obj
, string
, cacheControl
, ccontrol
);
161 /* {{{ proto string HTTPi_Response::getCacheControl()
163 * Get current Cache-Control header setting.
165 PHP_METHOD(HTTPi_Response
, getCacheControl
)
168 getObject(httpi_response_object
, obj
);
172 ccontrol
= GET_PROP(obj
, cacheControl
);
173 RETURN_STRINGL(Z_STRVAL_P(ccontrol
), Z_STRLEN_P(ccontrol
), 1);
177 /* {{{ proto bool HTTPi_Response::setContentType(string content_type)
179 * Set the content-type of the sent entity.
181 PHP_METHOD(HTTPi_Response
, setContentType
)
185 getObject(httpi_response_object
, obj
);
187 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &ctype
, &ctype_len
)) {
191 if (!strchr(ctype
, '/')) {
192 php_error_docref(NULL TSRMLS_CC
, E_WARNING
,
193 "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype
);
197 UPD_PROP(obj
, string
, contentType
, ctype
);
203 /* {{{ proto string HTTPi_Response::getContentType()
205 * Get current Content-Type header setting.
207 PHP_METHOD(HTTPi_Response
, getContentType
)
210 getObject(httpi_response_object
, obj
);
214 ctype
= GET_PROP(obj
, contentType
);
215 RETURN_STRINGL(Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
219 /* {{{ proto bool HTTPi_Response::setContentDisposition(string filename[, bool inline = false])
221 * Set the Content-Disposition of the sent entity. This setting aims to suggest
222 * the receiveing user agent how to handle the sent entity; usually the client
223 * will show the user a "Save As..." popup.
225 PHP_METHOD(HTTPi_Response
, setContentDisposition
)
229 zend_bool is_inline
= 0;
230 getObject(httpi_response_object
, obj
);
232 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|b", &file
, &file_len
, &is_inline
)) {
236 UPD_PROP(obj
, string
, dispoFile
, file
);
237 UPD_PROP(obj
, long, dispoInline
, is_inline
);
242 /* {{{ proto array HTTPi_Response::getContentDisposition()
244 * Get current Content-Disposition setting.
245 * Will return an associative array like:
248 * 'filename' => 'foo.bar',
253 PHP_METHOD(HTTPi_Response
, getContentDisposition
)
257 getObject(httpi_response_object
, obj
);
259 if (ZEND_NUM_ARGS()) {
263 file
= GET_PROP(obj
, dispoFile
);
264 is_inline
= GET_PROP(obj
, dispoInline
);
266 array_init(return_value
);
267 add_assoc_stringl(return_value
, "filename", Z_STRVAL_P(file
), Z_STRLEN_P(file
), 1);
268 add_assoc_bool(return_value
, "inline", Z_LVAL_P(is_inline
));
272 /* {{{ proto bool HTTPi_Response::setETag(string etag)
274 * Set a custom ETag. Use this only if you know what you're doing.
276 PHP_METHOD(HTTPi_Response
, setETag
)
280 getObject(httpi_response_object
, obj
);
282 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &etag
, &etag_len
)) {
286 UPD_PROP(obj
, string
, eTag
, etag
);
291 /* {{{ proto string HTTPi_Response::getETag()
293 * Get the previously set custom ETag.
295 PHP_METHOD(HTTPi_Response
, getETag
)
298 getObject(httpi_response_object
, obj
);
302 etag
= GET_PROP(obj
, eTag
);
303 RETURN_STRINGL(Z_STRVAL_P(etag
), Z_STRLEN_P(etag
), 1);
307 /* {{{ proto bool HTTPi_Response::setData(string data)
309 * Set the data to be sent.
311 PHP_METHOD(HTTPi_Response
, setData
)
314 getObject(httpi_response_object
, obj
);
316 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z", &the_data
)) {
320 convert_to_string_ex(&the_data
);
321 SET_PROP(obj
, data
, the_data
);
322 UPD_PROP(obj
, long, lastModified
, http_lmod(the_data
, SEND_DATA
));
323 UPD_PROP(obj
, long, send_mode
, SEND_DATA
);
328 /* {{{ proto string HTTPi_Response::getData()
330 * Get the previously set data to be sent.
332 PHP_METHOD(HTTPi_Response
, getData
)
335 getObject(httpi_response_object
, obj
);
339 the_data
= GET_PROP(obj
, data
);
340 RETURN_STRINGL(Z_STRVAL_P(the_data
), Z_STRLEN_P(the_data
), 1);
344 /* {{{ proto bool HTTPi_Response::setStream(resource stream)
346 * Set the resource to be sent.
348 PHP_METHOD(HTTPi_Response
, setStream
)
351 php_stream
*the_real_stream
;
352 getObject(httpi_response_object
, obj
);
354 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "r", &the_stream
)) {
358 php_stream_from_zval(the_real_stream
, &the_stream
);
360 SET_PROP(obj
, stream
, the_stream
);
361 UPD_PROP(obj
, long, lastModified
, http_lmod(the_real_stream
, SEND_RSRC
));
362 UPD_PROP(obj
, long, send_mode
, SEND_RSRC
);
367 /* {{{ proto resource HTTPi_Response::getStream()
369 * Get the previously set resource to be sent.
371 PHP_METHOD(HTTPi_Response
, getStream
)
374 getObject(httpi_response_object
, obj
);
378 the_stream
= GET_PROP(obj
, stream
);
379 RETURN_RESOURCE(Z_LVAL_P(the_stream
));
383 /* {{{ proto bool HTTPi_Response::setFile(string file)
385 * Set the file to be sent.
387 PHP_METHOD(HTTPi_Response
, setFile
)
390 getObject(httpi_response_object
, obj
);
392 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z", &the_file
)) {
396 convert_to_string_ex(&the_file
);
398 UPD_PROP(obj
, string
, file
, Z_STRVAL_P(the_file
));
399 UPD_PROP(obj
, long, lastModified
, http_lmod(the_file
, -1));
400 UPD_PROP(obj
, long, send_mode
, -1);
405 /* {{{ proto string HTTPi_Response::getFile()
407 * Get the previously set file to be sent.
409 PHP_METHOD(HTTPi_Response
, getFile
)
412 getObject(httpi_response_object
, obj
);
416 the_file
= GET_PROP(obj
, file
);
417 RETURN_STRINGL(Z_STRVAL_P(the_file
), Z_STRLEN_P(the_file
), 1);
421 /* {{{ proto bool HTTPi_Response::send()
423 * Finally send the entity.
428 * $r = new HTTPi_Response(true);
429 * $r->setFile('../hidden/contract.pdf');
430 * $r->setContentType('application/pdf');
436 PHP_METHOD(HTTPi_Response
, send
)
438 zval
*do_cache
, *do_gzip
;
439 getObject(httpi_response_object
, obj
);
443 do_cache
= GET_PROP(obj
, cache
);
444 do_gzip
= GET_PROP(obj
, gzip
);
447 if (Z_LVAL_P(do_cache
)) {
448 zval
*cctrl
, *etag
, *lmod
, *ccraw
;
450 etag
= GET_PROP(obj
, eTag
);
451 lmod
= GET_PROP(obj
, lastModified
);
452 cctrl
= GET_PROP(obj
, cacheControl
);
453 ccraw
= GET_PROP(obj
, raw_cache_header
);
455 if (Z_LVAL_P(ccraw
)) {
456 http_cache_etag(Z_STRVAL_P(etag
), Z_STRLEN_P(etag
), Z_STRVAL_P(cctrl
), Z_STRLEN_P(cctrl
));
457 http_cache_last_modified(Z_LVAL_P(lmod
), Z_LVAL_P(lmod
) ? Z_LVAL_P(lmod
) : time(NULL
), Z_STRVAL_P(cctrl
), Z_STRLEN_P(cctrl
));
459 char cc_header
[42] = {0};
460 sprintf(cc_header
, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl
));
461 http_cache_etag(Z_STRVAL_P(etag
), Z_STRLEN_P(etag
), cc_header
, strlen(cc_header
));
462 http_cache_last_modified(Z_LVAL_P(lmod
), Z_LVAL_P(lmod
) ? Z_LVAL_P(lmod
) : time(NULL
), cc_header
, strlen(cc_header
));
467 if (Z_LVAL_P(do_gzip
)) {
473 zval
*ctype
= GET_PROP(obj
, contentType
);
474 if (Z_STRLEN_P(ctype
)) {
475 http_send_content_type(Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
));
477 http_send_content_type("application/x-octetstream", sizeof("application/x-octetstream") - 1);
481 /* content disposition */
483 zval
*dispo_file
= GET_PROP(obj
, dispoFile
);
484 if (Z_STRLEN_P(dispo_file
)) {
485 zval
*dispo_inline
= GET_PROP(obj
, dispoInline
);
486 http_send_content_disposition(Z_STRVAL_P(dispo_file
), Z_STRLEN_P(dispo_file
), Z_LVAL_P(dispo_inline
));
492 zval
*send_mode
= GET_PROP(obj
, send_mode
);
493 switch (Z_LVAL_P(send_mode
))
497 zval
*zdata
= GET_PROP(obj
, data
);
498 RETURN_SUCCESS(http_send_data(Z_STRVAL_P(zdata
), Z_STRLEN_P(zdata
)));
503 php_stream
*the_real_stream
;
504 zval
*the_stream
= GET_PROP(obj
, stream
);
505 php_stream_from_zval(the_real_stream
, &the_stream
);
506 RETURN_SUCCESS(http_send_stream(the_real_stream
));
511 zval
*zfile
= GET_PROP(obj
, file
);
512 RETURN_SUCCESS(http_send_file(Z_STRVAL_P(zfile
)));
520 #ifdef HTTP_HAVE_CURL
521 /* {{{ HTTPi_Request */
523 /* {{{ proto void HTTPi_Request::__construct([string url[, long request_method = HTTP_GET]])
525 * Instantiate a new HTTPi_Request object which can be used to issue HEAD, GET
526 * and POST (including posting files) HTTP requests.
528 PHP_METHOD(HTTPi_Request
, __construct
)
533 getObject(httpi_request_object
, obj
);
535 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|sl", &URL
, &URL_len
, &meth
)) {
539 INIT_PARR(obj
, options
);
540 INIT_PARR(obj
, responseInfo
);
541 INIT_PARR(obj
, responseData
);
542 INIT_PARR(obj
, postData
);
543 INIT_PARR(obj
, postFiles
);
546 UPD_PROP(obj
, string
, url
, URL
);
549 UPD_PROP(obj
, long, method
, meth
);
554 /* {{{ proto void HTTPi_Request::__destruct()
556 * Destroys the HTTPi_Request object.
558 PHP_METHOD(HTTPi_Request
, __destruct
)
560 getObject(httpi_request_object
, obj
);
564 FREE_PARR(obj
, options
);
565 FREE_PARR(obj
, responseInfo
);
566 FREE_PARR(obj
, responseData
);
567 FREE_PARR(obj
, postData
);
568 FREE_PARR(obj
, postFiles
);
572 /* {{{ proto bool HTTPi_Request::setOptions(array options)
574 * Set the request options to use. See http_get() for a full list of available options.
576 PHP_METHOD(HTTPi_Request
, setOptions
)
580 zval
*opts
, *old_opts
, **opt
;
581 getObject(httpi_request_object
, obj
);
583 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a/", &opts
)) {
587 old_opts
= GET_PROP(obj
, options
);
589 /* headers and cookies need extra attention -- thus cannot use array_merge() directly */
590 FOREACH_KEYVAL(opts
, key
, idx
, opt
) {
592 if (!strcmp(key
, "headers")) {
594 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(old_opts
), "headers", sizeof("headers"), (void **) &headers
)) {
595 array_merge(*opt
, *headers
);
598 } else if (!strcmp(key
, "cookies")) {
600 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(old_opts
), "cookies", sizeof("cookies"), (void **) &cookies
)) {
601 array_merge(*opt
, *cookies
);
606 add_assoc_zval(old_opts
, key
, *opt
);
617 /* {{{ proto array HTTPi_Request::getOptions()
619 * Get current set options.
621 PHP_METHOD(HTTPi_Request
, getOptions
)
624 getObject(httpi_request_object
, obj
);
628 opts
= GET_PROP(obj
, options
);
629 array_init(return_value
);
630 array_copy(opts
, return_value
);
634 /* {{{ proto bool HTTPi_Request::setURL(string url)
636 * Set the request URL.
638 PHP_METHOD(HTTPi_Request
, setURL
)
642 getObject(httpi_request_object
, obj
);
644 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &URL
, &URL_len
)) {
648 UPD_PROP(obj
, string
, url
, URL
);
653 /* {{{ proto string HTTPi_Request::getUrl()
655 * Get the previously set request URL.
657 PHP_METHOD(HTTPi_Request
, getURL
)
660 getObject(httpi_request_object
, obj
);
664 URL
= GET_PROP(obj
, url
);
665 RETURN_STRINGL(Z_STRVAL_P(URL
), Z_STRLEN_P(URL
), 1);
669 /* {{{ proto bool HTTPi_Request::setMethod(long request_method)
671 * Set the request methods; one of the <tt>HTTP_HEAD</tt>, <tt>HTTP_GET</tt> or
672 * <tt>HTTP_POST</tt> constants.
674 PHP_METHOD(HTTPi_Request
, setMethod
)
677 getObject(httpi_request_object
, obj
);
679 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &meth
)) {
683 UPD_PROP(obj
, long, method
, meth
);
688 /* {{{ proto long HTTPi_Request::getMethod()
690 * Get the previously set request method.
692 PHP_METHOD(HTTPi_Request
, getMethod
)
695 getObject(httpi_request_object
, obj
);
699 meth
= GET_PROP(obj
, method
);
700 RETURN_LONG(Z_LVAL_P(meth
));
704 /* {{{ proto bool HTTPi_Request::setContentType(string content_type)
706 * Set the content type the post request should have.
707 * Use this only if you know what you're doing.
709 PHP_METHOD(HTTPi_Request
, setContentType
)
713 getObject(httpi_request_object
, obj
);
715 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &ctype
, &ct_len
)) {
719 if (!strchr(ctype
, '/')) {
720 php_error_docref(NULL TSRMLS_CC
, E_WARNING
,
721 "Content-Type '%s' doesn't seem to contain a primary and a secondary part",
726 UPD_PROP(obj
, string
, contentType
, ctype
);
731 /* {{{ proto string HTTPi_Request::getContentType()
733 * Get the previously content type.
735 PHP_METHOD(HTTPi_Request
, getContentType
)
738 getObject(httpi_request_object
, obj
);
742 ctype
= GET_PROP(obj
, contentType
);
743 RETURN_STRINGL(Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
747 /* {{{ proto bool HTTPi_Request::setQueryData(mixed query_data)
749 * Set the URL query parameters to use.
750 * Overwrites previously set query parameters.
751 * Affects any request types.
753 PHP_METHOD(HTTPi_Request
, setQueryData
)
756 char *query_data
= NULL
;
757 getObject(httpi_request_object
, obj
);
759 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z", &qdata
)) {
763 if ((Z_TYPE_P(qdata
) == IS_ARRAY
) || (Z_TYPE_P(qdata
) == IS_OBJECT
)) {
764 if (SUCCESS
!= http_urlencode_hash(HASH_OF(qdata
), &query_data
)) {
767 UPD_PROP(obj
, string
, queryData
, query_data
);
772 convert_to_string(qdata
);
773 UPD_PROP(obj
, string
, queryData
, Z_STRVAL_P(qdata
));
778 /* {{{ proto string HTTPi_Request::getQueryData()
780 * Get the current query data in form of an urlencoded query string.
782 PHP_METHOD(HTTPi_Request
, getQueryData
)
785 getObject(httpi_request_object
, obj
);
789 qdata
= GET_PROP(obj
, queryData
);
790 RETURN_STRINGL(Z_STRVAL_P(qdata
), Z_STRLEN_P(qdata
), 1);
794 /* {{{ proto bool HTTPi_Request::addQueryData(array query_params)
796 * Add parameters to the query parameter list.
797 * Affects any request type.
799 PHP_METHOD(HTTPi_Request
, addQueryData
)
801 zval
*qdata
, *old_qdata
;
802 char *query_data
= NULL
;
803 getObject(httpi_request_object
, obj
);
805 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a", &qdata
)) {
809 old_qdata
= GET_PROP(obj
, queryData
);
811 if (SUCCESS
!= http_urlencode_hash_ex(HASH_OF(qdata
), 1, Z_STRVAL_P(old_qdata
), Z_STRLEN_P(old_qdata
), &query_data
, NULL
)) {
815 UPD_PROP(obj
, string
, queryData
, query_data
);
822 /* {{{ proto void HTTPi_Request::unsetQueryData()
824 * Clean the query parameters.
825 * Affects any request type.
827 PHP_METHOD(HTTPi_Request
, unsetQueryData
)
829 getObject(httpi_request_object
, obj
);
833 UPD_PROP(obj
, string
, queryData
, "");
837 /* {{{ proto bool HTTPi_Request::addPostData(array post_data)
839 * Adds POST data entries.
840 * Affects only POST requests.
842 PHP_METHOD(HTTPi_Request
, addPostData
)
844 zval
*post
, *post_data
;
845 getObject(httpi_request_object
, obj
);
847 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a", &post_data
)) {
851 post
= GET_PROP(obj
, postData
);
852 array_merge(post_data
, post
);
858 /* {{{ proto bool HTTPi_Request::setPostData(array post_data)
860 * Set the POST data entries.
861 * Overwrites previously set POST data.
862 * Affects only POST requests.
864 PHP_METHOD(HTTPi_Request
, setPostData
)
866 zval
*post
, *post_data
;
867 getObject(httpi_request_object
, obj
);
869 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a", &post_data
)) {
873 post
= GET_PROP(obj
, postData
);
874 zend_hash_clean(Z_ARRVAL_P(post
));
875 array_copy(post_data
, post
);
881 /* {{{ proto array HTTPi_Request::getPostData()
883 * Get previously set POST data.
885 PHP_METHOD(HTTPi_Request
, getPostData
)
888 getObject(httpi_request_object
, obj
);
892 post_data
= GET_PROP(obj
, postData
);
893 array_init(return_value
);
894 array_copy(post_data
, return_value
);
898 /* {{{ proto void HTTPi_Request::unsetPostData()
900 * Clean POST data entires.
901 * Affects only POST requests.
903 PHP_METHOD(HTTPi_Request
, unsetPostData
)
906 getObject(httpi_request_object
, obj
);
910 post_data
= GET_PROP(obj
, postData
);
911 zend_hash_clean(Z_ARRVAL_P(post_data
));
915 /* {{{ proto bool HTTPi_Request::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
917 * Add a file to the POST request.
918 * Affects only POST requests.
920 PHP_METHOD(HTTPi_Request
, addPostFile
)
923 char *name
, *file
, *type
= NULL
;
924 int name_len
, file_len
, type_len
= 0;
925 getObject(httpi_request_object
, obj
);
927 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss|s", &name
, &name_len
, &file
, &file_len
, &type
, &type_len
)) {
932 if (!strchr(type
, '/')) {
933 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type
);
937 type
= "application/x-octetstream";
938 type_len
= sizeof("application/x-octetstream") - 1;
941 MAKE_STD_ZVAL(entry
);
944 add_assoc_stringl(entry
, "name", name
, name_len
, 1);
945 add_assoc_stringl(entry
, "type", type
, type_len
, 1);
946 add_assoc_stringl(entry
, "file", file
, file_len
, 1);
948 files
= GET_PROP(obj
, postFiles
);
949 add_next_index_zval(files
, entry
);
955 /* {{{ proto array HTTPi_Request::getPostFiles()
957 * Get all previously added POST files.
959 PHP_METHOD(HTTPi_Request
, getPostFiles
)
962 getObject(httpi_request_object
, obj
);
966 files
= GET_PROP(obj
, postFiles
);
968 array_init(return_value
);
969 array_copy(files
, return_value
);
973 /* {{{ proto void HTTPi_Request::unsetPostFiles()
975 * Unset the POST files list.
976 * Affects only POST requests.
978 PHP_METHOD(HTTPi_Request
, unsetPostFiles
)
981 getObject(httpi_request_object
, obj
);
985 files
= GET_PROP(obj
, postFiles
);
986 zend_hash_clean(Z_ARRVAL_P(files
));
990 /* {{{ proto array HTTPi_Request::getResponseData()
992 * Get all resposonse data after sending the request.
994 PHP_METHOD(HTTPi_Request
, getResponseData
)
997 getObject(httpi_request_object
, obj
);
1001 data
= GET_PROP(obj
, responseData
);
1002 array_init(return_value
);
1003 array_copy(data
, return_value
);
1007 /* {{{ proto array HTTPi_Request::getResponseHeaders()
1009 * Get the response headers after sending the request.
1011 PHP_METHOD(HTTPi_Request
, getResponseHeaders
)
1013 zval
*data
, **headers
;
1014 getObject(httpi_request_object
, obj
);
1018 array_init(return_value
);
1019 data
= GET_PROP(obj
, responseData
);
1020 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(data
), "headers", sizeof("headers"), (void **) &headers
)) {
1021 array_copy(*headers
, return_value
);
1026 /* {{{ proto string HTTPi_Request::getResponseBody()
1028 * Get the response body after sending the request.
1030 PHP_METHOD(HTTPi_Request
, getResponseBody
)
1033 getObject(httpi_request_object
, obj
);
1037 data
= GET_PROP(obj
, responseData
);
1038 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(data
), "body", sizeof("body"), (void **) &body
)) {
1039 RETURN_STRINGL(Z_STRVAL_PP(body
), Z_STRLEN_PP(body
), 1);
1041 Z_TYPE_P(return_value
) = IS_NULL
;
1046 /* {{{ proto array HTTPi_Request::getResponseInfo()
1048 * Get response info after sending the request.
1049 * See http_get() for a full list of returned info.
1051 PHP_METHOD(HTTPi_Request
, getResponseInfo
)
1054 getObject(httpi_request_object
, obj
);
1058 info
= GET_PROP(obj
, responseInfo
);
1059 array_init(return_value
);
1060 array_copy(info
, return_value
);
1064 /* {{{ proto bool HTTPi_Request::send()
1066 * Send the HTTP request.
1068 PHP_METHOD(HTTPi_Request
, send
)
1070 STATUS status
= FAILURE
;
1071 zval
*meth
, *URL
, *qdata
, *opts
, *info
, *resp
;
1072 char *response_data
, *request_uri
;
1073 size_t response_len
;
1074 getObject(httpi_request_object
, obj
);
1078 if ((!obj
->ch
) && (!(obj
->ch
= curl_easy_init()))) {
1079 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not initilaize cURL");
1083 meth
= GET_PROP(obj
, method
);
1084 URL
= GET_PROP(obj
, url
);
1085 qdata
= GET_PROP(obj
, queryData
);
1086 opts
= GET_PROP(obj
, options
);
1087 info
= GET_PROP(obj
, responseInfo
);
1088 resp
= GET_PROP(obj
, responseData
);
1090 // HTTP_URI_MAXLEN+1 big char *
1091 request_uri
= http_absolute_uri(Z_STRVAL_P(URL
), NULL
);
1093 if (Z_STRLEN_P(qdata
) && (strlen(request_uri
) < HTTP_URI_MAXLEN
)) {
1094 if (!strchr(request_uri
, '?')) {
1095 strcat(request_uri
, "?");
1097 strcat(request_uri
, "&");
1099 strncat(request_uri
, Z_STRVAL_P(qdata
), HTTP_URI_MAXLEN
- strlen(request_uri
));
1102 switch (Z_LVAL_P(meth
))
1105 status
= http_get_ex(obj
->ch
, request_uri
, Z_ARRVAL_P(opts
), Z_ARRVAL_P(info
), &response_data
, &response_len
);
1109 status
= http_head_ex(obj
->ch
, request_uri
, Z_ARRVAL_P(opts
), Z_ARRVAL_P(info
), &response_data
, &response_len
);
1114 zval
*post_files
, *post_data
;
1116 post_files
= GET_PROP(obj
, postFiles
);
1117 post_data
= GET_PROP(obj
, postData
);
1119 if (!zend_hash_num_elements(Z_ARRVAL_P(post_files
))) {
1121 /* urlencoded post */
1122 status
= http_post_array_ex(obj
->ch
, request_uri
, Z_ARRVAL_P(post_data
), Z_ARRVAL_P(opts
), Z_ARRVAL_P(info
), &response_data
, &response_len
);
1132 struct curl_httppost
*http_post_data
[2] = {NULL
, NULL
};
1135 FOREACH_KEYVAL(post_data
, key
, idx
, data
) {
1137 convert_to_string_ex(data
);
1138 curl_formadd(&http_post_data
[0], &http_post_data
[1],
1139 CURLFORM_COPYNAME
, key
,
1140 CURLFORM_COPYCONTENTS
, Z_STRVAL_PP(data
),
1141 CURLFORM_CONTENTSLENGTH
, Z_STRLEN_PP(data
),
1151 FOREACH_VAL(post_files
, data
) {
1152 zval
**file
, **type
, **name
;
1154 if ( SUCCESS
== zend_hash_find(Z_ARRVAL_PP(data
), "name", sizeof("name"), (void **) &name
) &&
1155 SUCCESS
== zend_hash_find(Z_ARRVAL_PP(data
), "type", sizeof("type"), (void **) &type
) &&
1156 SUCCESS
== zend_hash_find(Z_ARRVAL_PP(data
), "file", sizeof("file"), (void **) &file
)) {
1158 curl_formadd(&http_post_data
[0], &http_post_data
[1],
1159 CURLFORM_COPYNAME
, Z_STRVAL_PP(name
),
1160 CURLFORM_FILE
, Z_STRVAL_PP(file
),
1161 CURLFORM_CONTENTTYPE
, Z_STRVAL_PP(type
),
1167 status
= http_post_curldata_ex(obj
->ch
, request_uri
, http_post_data
[0], Z_ARRVAL_P(opts
), Z_ARRVAL_P(info
), &response_data
, &response_len
);
1168 curl_formfree(http_post_data
[0]);
1179 /* final data handling */
1180 if (status
!= SUCCESS
) {
1184 size_t body_len
= 0;
1187 MAKE_STD_ZVAL(zheaders
)
1188 array_init(zheaders
);
1190 if (SUCCESS
!= http_split_response_ex(response_data
, response_len
, Z_ARRVAL_P(zheaders
), &body
, &body_len
)) {
1191 zval_dtor(zheaders
);
1193 efree(response_data
);
1197 add_assoc_zval(resp
, "headers", zheaders
);
1198 add_assoc_stringl(resp
, "body", body
, body_len
, 0);
1200 efree(response_data
);
1208 #endif /* HTTP_HAVE_CURL */
1210 #endif /* ZEND_ENGINE_2 */
1217 * vim600: noet sw=4 ts=4 fdm=marker
1218 * vim<600: noet sw=4 ts=4