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 +----------------------------------------------------------------------+
23 #include "php_streams.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"
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"
43 /* {{{ HttpResponse */
45 /* {{{ proto void HttpResponse::__construct(bool cache, bool gzip)
47 * Instantiates a new HttpResponse object, which can be used to send
48 * any data/resource/file to an HTTP client with caching and multiple
49 * ranges/resuming support.
51 * NOTE: GZIPping is not implemented yet.
53 PHP_METHOD(HttpResponse
, __construct
)
55 zend_bool do_cache
= 0, do_gzip
= 0;
56 getObject(http_response_object
, obj
);
59 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|bb", &do_cache
, &do_gzip
)) {
60 UPD_PROP(obj
, long, cache
, do_cache
);
61 UPD_PROP(obj
, long, gzip
, do_gzip
);
67 /* {{{ proto bool HttpResponse::setCache(bool cache)
69 * Whether it sould be attempted to cache the entitity.
70 * This will result in necessary caching headers and checks of clients
71 * "If-Modified-Since" and "If-None-Match" headers. If one of those headers
72 * matches a "304 Not Modified" status code will be issued.
74 * NOTE: If you're using sessions, be shure that you set session.cache_limiter
75 * to something more appropriate than "no-cache"!
77 PHP_METHOD(HttpResponse
, setCache
)
79 zend_bool do_cache
= 0;
80 getObject(http_response_object
, obj
);
82 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "b", &do_cache
)) {
86 UPD_PROP(obj
, long, cache
, do_cache
);
91 /* {{{ proto bool HttpResponse::getCache()
93 * Get current caching setting.
95 PHP_METHOD(HttpResponse
, getCache
)
97 zval
*do_cache
= NULL
;
98 getObject(http_response_object
, obj
);
102 do_cache
= GET_PROP(obj
, cache
);
103 RETURN_BOOL(Z_LVAL_P(do_cache
));
107 /* {{{ proto bool HttpResponse::setGzip(bool gzip)
109 * Enable on-thy-fly gzipping of the sent entity. NOT IMPLEMENTED YET.
111 PHP_METHOD(HttpResponse
, setGzip
)
113 zend_bool do_gzip
= 0;
114 getObject(http_response_object
, obj
);
116 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "b", &do_gzip
)) {
120 UPD_PROP(obj
, long, gzip
, do_gzip
);
125 /* {{{ proto bool HttpResponse::getGzip()
127 * Get current gzipping setting.
129 PHP_METHOD(HttpResponse
, getGzip
)
131 zval
*do_gzip
= NULL
;
132 getObject(http_response_object
, obj
);
136 do_gzip
= GET_PROP(obj
, gzip
);
137 RETURN_BOOL(Z_LVAL_P(do_gzip
));
141 /* {{{ proto bool HttpResponse::setCacheControl(string control[, bool raw = false])
143 * Set a custom cache-control header, usually being "private" or "public"; if
144 * $raw is set to true the header will be sent as-is.
146 PHP_METHOD(HttpResponse
, setCacheControl
)
151 getObject(http_response_object
, obj
);
153 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|b", &ccontrol
, &cc_len
, &raw
)) {
157 if ((!raw
) && (strcmp(ccontrol
, "public") && strcmp(ccontrol
, "private") && strcmp(ccontrol
, "no-cache"))) {
158 http_error_ex(E_WARNING
, HTTP_E_PARAM
, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol
);
162 UPD_PROP(obj
, long, raw_cache_header
, raw
);
163 UPD_PROP(obj
, string
, cacheControl
, ccontrol
);
168 /* {{{ proto string HttpResponse::getCacheControl()
170 * Get current Cache-Control header setting.
172 PHP_METHOD(HttpResponse
, getCacheControl
)
175 getObject(http_response_object
, obj
);
179 ccontrol
= GET_PROP(obj
, cacheControl
);
180 RETURN_STRINGL(Z_STRVAL_P(ccontrol
), Z_STRLEN_P(ccontrol
), 1);
184 /* {{{ proto bool HttpResponse::setContentType(string content_type)
186 * Set the content-type of the sent entity.
188 PHP_METHOD(HttpResponse
, setContentType
)
192 getObject(http_response_object
, obj
);
194 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &ctype
, &ctype_len
)) {
198 if (!strchr(ctype
, '/')) {
199 http_error_ex(E_WARNING
, HTTP_E_PARAM
, "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype
);
203 UPD_PROP(obj
, string
, contentType
, ctype
);
209 /* {{{ proto string HttpResponse::getContentType()
211 * Get current Content-Type header setting.
213 PHP_METHOD(HttpResponse
, getContentType
)
216 getObject(http_response_object
, obj
);
220 ctype
= GET_PROP(obj
, contentType
);
221 RETURN_STRINGL(Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
225 /* {{{ proto bool HttpResponse::setContentDisposition(string filename[, bool inline = false])
227 * Set the Content-Disposition of the sent entity. This setting aims to suggest
228 * the receiveing user agent how to handle the sent entity; usually the client
229 * will show the user a "Save As..." popup.
231 PHP_METHOD(HttpResponse
, setContentDisposition
)
235 zend_bool is_inline
= 0;
236 getObject(http_response_object
, obj
);
238 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|b", &file
, &file_len
, &is_inline
)) {
242 UPD_PROP(obj
, string
, dispoFile
, file
);
243 UPD_PROP(obj
, long, dispoInline
, is_inline
);
248 /* {{{ proto array HttpResponse::getContentDisposition()
250 * Get current Content-Disposition setting.
251 * Will return an associative array like:
254 * 'filename' => 'foo.bar',
259 PHP_METHOD(HttpResponse
, getContentDisposition
)
263 getObject(http_response_object
, obj
);
265 if (ZEND_NUM_ARGS()) {
269 file
= GET_PROP(obj
, dispoFile
);
270 is_inline
= GET_PROP(obj
, dispoInline
);
272 array_init(return_value
);
273 add_assoc_stringl(return_value
, "filename", Z_STRVAL_P(file
), Z_STRLEN_P(file
), 1);
274 add_assoc_bool(return_value
, "inline", Z_LVAL_P(is_inline
));
278 /* {{{ proto bool HttpResponse::setETag(string etag)
280 * Set a custom ETag. Use this only if you know what you're doing.
282 PHP_METHOD(HttpResponse
, setETag
)
286 getObject(http_response_object
, obj
);
288 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &etag
, &etag_len
)) {
292 UPD_PROP(obj
, string
, eTag
, etag
);
297 /* {{{ proto string HttpResponse::getETag()
299 * Get the previously set custom ETag.
301 PHP_METHOD(HttpResponse
, getETag
)
304 getObject(http_response_object
, obj
);
308 etag
= GET_PROP(obj
, eTag
);
309 RETURN_STRINGL(Z_STRVAL_P(etag
), Z_STRLEN_P(etag
), 1);
313 /* {{{ proto bool HttpResponse::setData(string data)
315 * Set the data to be sent.
317 PHP_METHOD(HttpResponse
, setData
)
320 getObject(http_response_object
, obj
);
322 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z/", &the_data
)) {
326 convert_to_string_ex(&the_data
);
327 SET_PROP(obj
, data
, the_data
);
328 UPD_PROP(obj
, long, lastModified
, http_last_modified(the_data
, SEND_DATA
));
329 UPD_PROP(obj
, long, send_mode
, SEND_DATA
);
334 /* {{{ proto string HttpResponse::getData()
336 * Get the previously set data to be sent.
338 PHP_METHOD(HttpResponse
, getData
)
341 getObject(http_response_object
, obj
);
345 the_data
= GET_PROP(obj
, data
);
346 RETURN_STRINGL(Z_STRVAL_P(the_data
), Z_STRLEN_P(the_data
), 1);
350 /* {{{ proto bool HttpResponse::setStream(resource stream)
352 * Set the resource to be sent.
354 PHP_METHOD(HttpResponse
, setStream
)
357 php_stream
*the_real_stream
;
358 getObject(http_response_object
, obj
);
360 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "r", &the_stream
)) {
364 php_stream_from_zval(the_real_stream
, &the_stream
);
366 SET_PROP(obj
, stream
, the_stream
);
367 UPD_PROP(obj
, long, lastModified
, http_last_modified(the_real_stream
, SEND_RSRC
));
368 UPD_PROP(obj
, long, send_mode
, SEND_RSRC
);
373 /* {{{ proto resource HttpResponse::getStream()
375 * Get the previously set resource to be sent.
377 PHP_METHOD(HttpResponse
, getStream
)
380 getObject(http_response_object
, obj
);
384 the_stream
= GET_PROP(obj
, stream
);
385 RETURN_RESOURCE(Z_LVAL_P(the_stream
));
389 /* {{{ proto bool HttpResponse::setFile(string file)
391 * Set the file to be sent.
393 PHP_METHOD(HttpResponse
, setFile
)
396 getObject(http_response_object
, obj
);
398 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z", &the_file
)) {
402 convert_to_string_ex(&the_file
);
404 UPD_PROP(obj
, string
, file
, Z_STRVAL_P(the_file
));
405 UPD_PROP(obj
, long, lastModified
, http_last_modified(the_file
, -1));
406 UPD_PROP(obj
, long, send_mode
, -1);
411 /* {{{ proto string HttpResponse::getFile()
413 * Get the previously set file to be sent.
415 PHP_METHOD(HttpResponse
, getFile
)
418 getObject(http_response_object
, obj
);
422 the_file
= GET_PROP(obj
, file
);
423 RETURN_STRINGL(Z_STRVAL_P(the_file
), Z_STRLEN_P(the_file
), 1);
427 /* {{{ proto bool HttpResponse::send()
429 * Finally send the entity.
434 * $r = new HttpResponse(true);
435 * $r->setFile('../hidden/contract.pdf');
436 * $r->setContentType('application/pdf');
442 PHP_METHOD(HttpResponse
, send
)
444 zval
*do_cache
, *do_gzip
;
445 getObject(http_response_object
, obj
);
449 do_cache
= GET_PROP(obj
, cache
);
450 do_gzip
= GET_PROP(obj
, gzip
);
453 if (Z_LVAL_P(do_gzip
)) {
454 php_start_ob_buffer_named("ob_gzhandler", 0, 1 TSRMLS_CC
);
458 if (Z_LVAL_P(do_cache
)) {
459 zval
*cctrl
, *etag
, *lmod
, *ccraw
;
461 etag
= GET_PROP(obj
, eTag
);
462 lmod
= GET_PROP(obj
, lastModified
);
463 cctrl
= GET_PROP(obj
, cacheControl
);
464 ccraw
= GET_PROP(obj
, raw_cache_header
);
466 if (Z_LVAL_P(ccraw
)) {
467 http_cache_etag(Z_STRVAL_P(etag
), Z_STRLEN_P(etag
), Z_STRVAL_P(cctrl
), Z_STRLEN_P(cctrl
));
468 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
));
470 char cc_header
[42] = {0};
471 sprintf(cc_header
, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl
));
472 http_cache_etag(Z_STRVAL_P(etag
), Z_STRLEN_P(etag
), cc_header
, strlen(cc_header
));
473 http_cache_last_modified(Z_LVAL_P(lmod
), Z_LVAL_P(lmod
) ? Z_LVAL_P(lmod
) : time(NULL
), cc_header
, strlen(cc_header
));
479 zval
*ctype
= GET_PROP(obj
, contentType
);
480 if (Z_STRLEN_P(ctype
)) {
481 http_send_content_type(Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
));
483 http_send_content_type("application/x-octetstream", sizeof("application/x-octetstream") - 1);
487 /* content disposition */
489 zval
*dispo_file
= GET_PROP(obj
, dispoFile
);
490 if (Z_STRLEN_P(dispo_file
)) {
491 zval
*dispo_inline
= GET_PROP(obj
, dispoInline
);
492 http_send_content_disposition(Z_STRVAL_P(dispo_file
), Z_STRLEN_P(dispo_file
), (zend_bool
) Z_LVAL_P(dispo_inline
));
498 zval
*send_mode
= GET_PROP(obj
, send_mode
);
499 switch (Z_LVAL_P(send_mode
))
503 zval
*zdata
= GET_PROP(obj
, data
);
504 RETURN_SUCCESS(http_send_data(Z_STRVAL_P(zdata
), Z_STRLEN_P(zdata
)));
509 php_stream
*the_real_stream
;
510 zval
*the_stream
= GET_PROP(obj
, stream
);
511 php_stream_from_zval(the_real_stream
, &the_stream
);
512 RETURN_SUCCESS(http_send_stream(the_real_stream
));
517 zval
*zfile
= GET_PROP(obj
, file
);
518 RETURN_SUCCESS(http_send_file(Z_STRVAL_P(zfile
)));
526 /* {{{ HttpMessage */
528 /* {{{ proto static HttpMessage HttpMessage::fromString(string raw_message)
530 * Create an HttpMessage object from a string.
532 PHP_METHOD(HttpMessage
, fromString
)
536 http_message
*msg
= NULL
;
537 http_message_object obj
;
539 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &string
, &length
)) {
543 if (!(msg
= http_message_parse(string
, length
))) {
547 Z_TYPE_P(return_value
) = IS_OBJECT
;
548 return_value
->value
.obj
= http_message_object_from_msg(msg
);
552 /* {{{ proto void HttpMessage::__construct([string message])
554 * Instantiate a new HttpMessage object.
556 PHP_METHOD(HttpMessage
, __construct
)
558 char *message
= NULL
;
560 getObject(http_message_object
, obj
);
563 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s", &message
, &length
) && message
&& length
) {
564 if (obj
->message
= http_message_parse(message
, length
)) {
565 if (obj
->message
->parent
) {
566 obj
->parent
= http_message_object_from_msg(obj
->message
->parent
);
569 } else if (!obj
->message
) {
570 obj
->message
= http_message_new();
576 /* {{{ proto string HttpMessage::getBody()
578 * Get the body of the parsed Message.
580 PHP_METHOD(HttpMessage
, getBody
)
583 getObject(http_message_object
, obj
);
587 RETURN_PHPSTR(&obj
->message
->body
, PHPSTR_FREE_NOT
, 1);
591 /* {{{ proto array HttpMessage::getHeaders()
593 * Get Message Headers.
595 PHP_METHOD(HttpMessage
, getHeaders
)
598 getObject(http_message_object
, obj
);
602 Z_ARRVAL(headers
) = &obj
->message
->hdrs
;
603 array_init(return_value
);
604 array_copy(&headers
, return_value
);
608 /* {{{ proto void HttpMessage::setHeaders(array headers)
612 PHP_METHOD(HttpMessage
, setHeaders
)
614 zval
*new_headers
, old_headers
;
615 getObject(http_message_object
, obj
);
617 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a/", &new_headers
)) {
621 zend_hash_clean(&obj
->message
->hdrs
);
622 Z_ARRVAL(old_headers
) = &obj
->message
->hdrs
;
623 array_copy(new_headers
, &old_headers
);
627 /* {{{ proto void HttpMessage::addHeaders(array headers[, bool append = false])
629 * Add headers. If append is true, headers with the same name will be separated, else overwritten.
631 PHP_METHOD(HttpMessage
, addHeaders
)
633 zval old_headers
, *new_headers
;
634 zend_bool append
= 0;
635 getObject(http_message_object
, obj
);
637 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a|b", &new_headers
, &append
)) {
641 Z_ARRVAL(old_headers
) = &obj
->message
->hdrs
;
643 array_append(new_headers
, &old_headers
);
645 array_merge(new_headers
, &old_headers
);
650 /* {{{ proto long HttpMessage::getType()
652 * Get Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE)
654 PHP_METHOD(HttpMessage
, getType
)
656 getObject(http_message_object
, obj
);
660 RETURN_LONG(obj
->message
->type
);
664 /* {{{ proto void HttpMessage::setType(long type)
666 * Set Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE)
668 PHP_METHOD(HttpMessage
, setType
)
671 getObject(http_message_object
, obj
);
673 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &type
)) {
676 http_message_set_type(obj
->message
, type
);
680 /* {{{ proto long HttpMessage::getResponseCode()
682 * Get the Response Code of the Message.
684 PHP_METHOD(HttpMessage
, getResponseCode
)
686 getObject(http_message_object
, obj
);
690 if (!HTTP_MSG_TYPE(RESPONSE
, obj
->message
)) {
691 http_error(E_NOTICE
, HTTP_E_MSG
, "HttpMessage is not of type HTTP_MSG_RESPONSE");
695 RETURN_LONG(obj
->message
->info
.response
.code
);
699 /* {{{ proto bool HttpMessage::setResponseCode(long code)
701 * Set the response code of an HTTP Response Message.
702 * Returns false if the Message is not of type HTTP_MSG_RESPONSE,
703 * or if the response code is out of range (100-510).
705 PHP_METHOD(HttpMessage
, setResponseCode
)
708 getObject(http_message_object
, obj
);
710 if (obj
->message
->type
!= HTTP_MSG_RESPONSE
) {
711 http_error(E_WARNING
, HTTP_E_MSG
, "HttpMessage is not of type HTTP_MSG_RESPONSE");
715 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &code
)) {
718 if (code
< 100 || code
> 510) {
719 http_error_ex(E_WARNING
, HTTP_E_PARAM
, "Invalid response code (100-510): %ld", code
);
723 obj
->message
->info
.response
.code
= code
;
728 /* {{{ proto string HttpMessage::getRequestMethod()
730 * Get the Request Method of the Message.
731 * Returns false if the Message is not of type HTTP_MSG_REQUEST.
733 PHP_METHOD(HttpMessage
, getRequestMethod
)
735 getObject(http_message_object
, obj
);
739 if (obj
->message
->type
!= HTTP_MSG_REQUEST
) {
740 http_error(E_NOTICE
, HTTP_E_MSG
, "HttpMessage is not of type HTTP_MSG_REQUEST");
744 RETURN_STRING(obj
->message
->info
.request
.method
, 1);
748 /* {{{ proto bool HttpMessage::setRequestMethod(string method)
750 * Set the Request Method of the HTTP Message.
751 * Returns false if the Message is not of type HTTP_MSG_REQUEST.
753 PHP_METHOD(HttpMessage
, setRequestMethod
)
757 getObject(http_message_object
, obj
);
759 if (obj
->message
->type
!= HTTP_MSG_REQUEST
) {
760 http_error(E_WARNING
, HTTP_E_MSG
, "HttpMessage is not of type HTTP_MSG_REQUEST");
764 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &method
, &method_len
)) {
767 if (method_len
< 1) {
768 http_error(E_WARNING
, HTTP_E_PARAM
, "Cannot set HttpMessage::requestMethod to an empty string");
771 if (SUCCESS
!= http_check_method(method
)) {
772 http_error_ex(E_WARNING
, HTTP_E_PARAM
, "Unkown request method: %s", method
);
776 if (obj
->message
->info
.request
.method
) {
777 efree(obj
->message
->info
.request
.method
);
779 obj
->message
->info
.request
.method
= estrndup(method
, method_len
);
784 /* {{{ proto string HttpMessage::getRequestUri()
786 * Get the Request URI of the Message.
788 PHP_METHOD(HttpMessage
, getRequestUri
)
791 getObject(http_message_object
, obj
);
795 if (obj
->message
->type
!= HTTP_MSG_REQUEST
) {
796 http_error(E_WARNING
, HTTP_E_MSG
, "HttpMessage is not of type HTTP_MSG_REQUEST");
800 RETURN_STRING(obj
->message
->info
.request
.URI
, 1);
804 /* {{{ proto bool HttpMessage::setRequestUri(string URI)
806 * Set the Request URI of the HTTP Message.
807 * Returns false if the Message is not of type HTTP_MSG_REQUEST,
808 * or if paramtere URI was empty.
810 PHP_METHOD(HttpMessage
, setRequestUri
)
814 getObject(http_message_object
, obj
);
816 if (obj
->message
->type
!= HTTP_MSG_REQUEST
) {
817 http_error(E_WARNING
, HTTP_E_MSG
, "HttpMessage is not of type HTTP_MSG_REQUEST");
820 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &URI
, &URIlen
)) {
824 http_error(E_WARNING
, HTTP_E_PARAM
, "Cannot set HttpMessage::requestUri to an empty string");
828 if (obj
->message
->info
.request
.URI
) {
829 efree(obj
->message
->info
.request
.URI
);
831 obj
->message
->info
.request
.URI
= estrndup(URI
, URIlen
);
836 /* {{{ proto string HttpMessage::getHttpVersion()
838 * Get the HTTP Protocol Version of the Message.
840 PHP_METHOD(HttpMessage
, getHttpVersion
)
844 getObject(http_message_object
, obj
);
848 switch (obj
->message
->type
)
850 case HTTP_MSG_RESPONSE
:
851 version
= obj
->message
->info
.response
.http_version
;
854 case HTTP_MSG_REQUEST
:
855 version
= obj
->message
->info
.request
.http_version
;
862 sprintf(ver
, "%1.1f", version
);
863 RETURN_STRINGL(ver
, 3, 1);
867 /* {{{ proto bool HttpMessage::setHttpVersion(string version)
869 * Set the HTTP Protocol version of the Message.
870 * Returns false if version is invalid (1.0 and 1.1).
872 PHP_METHOD(HttpMessage
, setHttpVersion
)
876 getObject(http_message_object
, obj
);
878 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z/", &zv
)) {
882 if (obj
->message
->type
== HTTP_MSG_NONE
) {
883 http_error(E_WARNING
, HTTP_E_MSG
, "Message is neither of type HTTP_MSG_RESPONSE nor HTTP_MSG_REQUEST");
887 convert_to_double_ex(&zv
);
888 sprintf(v
, "%1.1f", Z_DVAL_P(zv
));
889 if (strcmp(v
, "1.0") && strcmp(v
, "1.1")) {
890 http_error_ex(E_WARNING
, HTTP_E_PARAM
, "Invalid HTTP protocol version (1.0 or 1.1): %s", v
);
894 if (obj
->message
->type
== HTTP_MSG_RESPONSE
) {
895 obj
->message
->info
.response
.http_version
= (float) Z_DVAL_P(zv
);
897 obj
->message
->info
.request
.http_version
= (float) Z_DVAL_P(zv
);
903 /* {{{ proto HttpMessage HttpMessage::getParentMessage()
905 * Get parent Message.
907 PHP_METHOD(HttpMessage
, getParentMessage
)
909 getObject(http_message_object
, obj
);
913 if (obj
->message
->parent
) {
914 RETVAL_OBJVAL(obj
->parent
);
921 /* {{{ proto bool HttpMessage::send()
923 * Send the Message according to its type as Response or Request.
925 PHP_METHOD(HttpMessage
, send
)
927 getObject(http_message_object
, obj
);
931 RETURN_SUCCESS(http_message_send(obj
->message
));
935 /* {{{ proto string HttpMessage::toString([bool include_parent = true])
937 * Get the string representation of the Message.
939 PHP_METHOD(HttpMessage
, toString
)
943 zend_bool include_parent
= 1;
944 getObject(http_message_object
, obj
);
946 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|b", &include_parent
)) {
950 if (include_parent
) {
951 http_message_serialize(obj
->message
, &string
, &length
);
953 http_message_tostring(obj
->message
, &string
, &length
);
955 RETURN_STRINGL(string
, length
, 0);
961 #ifdef HTTP_HAVE_CURL
962 /* {{{ HttpRequest */
964 /* {{{ proto void HttpRequest::__construct([string url[, long request_method = HTTP_GET]])
966 * Instantiate a new HttpRequest object which can be used to issue HEAD, GET
967 * and POST (including posting files) HTTP requests.
969 PHP_METHOD(HttpRequest
, __construct
)
974 getObject(http_request_object
, obj
);
977 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|sl", &URL
, &URL_len
, &meth
)) {
978 INIT_PARR(obj
, options
);
979 INIT_PARR(obj
, responseInfo
);
980 INIT_PARR(obj
, responseData
);
981 INIT_PARR(obj
, postFields
);
982 INIT_PARR(obj
, postFiles
);
985 UPD_PROP(obj
, string
, url
, URL
);
988 UPD_PROP(obj
, long, method
, meth
);
995 /* {{{ proto void HttpRequest::__destruct()
997 * Destroys the HttpRequest object.
999 PHP_METHOD(HttpRequest
, __destruct
)
1001 getObject(http_request_object
, obj
);
1005 FREE_PARR(obj
, options
);
1006 FREE_PARR(obj
, responseInfo
);
1007 FREE_PARR(obj
, responseData
);
1008 FREE_PARR(obj
, postFields
);
1009 FREE_PARR(obj
, postFiles
);
1013 /* {{{ proto bool HttpRequest::setOptions(array options)
1015 * Set the request options to use. See http_get() for a full list of available options.
1017 PHP_METHOD(HttpRequest
, setOptions
)
1021 zval
*opts
, *old_opts
, **opt
;
1022 getObject(http_request_object
, obj
);
1024 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a/", &opts
)) {
1028 old_opts
= GET_PROP(obj
, options
);
1030 /* headers and cookies need extra attention -- thus cannot use array_merge() directly */
1031 FOREACH_KEYVAL(opts
, key
, idx
, opt
) {
1033 if (!strcmp(key
, "headers")) {
1035 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(old_opts
), "headers", sizeof("headers"), (void **) &headers
)) {
1036 array_merge(*opt
, *headers
);
1039 } else if (!strcmp(key
, "cookies")) {
1041 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(old_opts
), "cookies", sizeof("cookies"), (void **) &cookies
)) {
1042 array_merge(*opt
, *cookies
);
1047 add_assoc_zval(old_opts
, key
, *opt
);
1058 /* {{{ proto array HttpRequest::getOptions()
1060 * Get current set options.
1062 PHP_METHOD(HttpRequest
, getOptions
)
1065 getObject(http_request_object
, obj
);
1069 opts
= GET_PROP(obj
, options
);
1070 array_init(return_value
);
1071 array_copy(opts
, return_value
);
1075 /* {{{ proto void HttpRequest::unsetOptions()
1077 * Unset all options/headers/cookies.
1079 PHP_METHOD(HttpRequest
, unsetOptions
)
1081 getObject(http_request_object
, obj
);
1085 FREE_PARR(obj
, options
);
1086 INIT_PARR(obj
, options
);
1090 /* {{{ proto bool HttpRequest::setSslOptions(array options)
1092 * Set additional SSL options.
1094 PHP_METHOD(HttpRequest
, setSslOptions
)
1096 zval
*opts
, *old_opts
, **ssl_options
;
1097 getObject(http_request_object
, obj
);
1099 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a/", &opts
)) {
1103 old_opts
= GET_PROP(obj
, options
);
1105 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(old_opts
), "ssl", sizeof("ssl"), (void **) &ssl_options
)) {
1106 array_merge(opts
, *ssl_options
);
1108 zval_add_ref(&opts
);
1109 add_assoc_zval(old_opts
, "ssl", opts
);
1116 /* {{{ proto array HttpRequest::getSslOtpions()
1118 * Get previously set SSL options.
1120 PHP_METHOD(HttpRequest
, getSslOptions
)
1122 zval
*opts
, **ssl_options
;
1123 getObject(http_request_object
, obj
);
1127 opts
= GET_PROP(obj
, options
);
1129 array_init(return_value
);
1131 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(opts
), "ssl", sizeof("ssl"), (void **) &ssl_options
)) {
1132 array_copy(*ssl_options
, return_value
);
1137 /* {{{ proto void HttpRequest::unsetSslOptions()
1139 * Unset previously set SSL options.
1141 PHP_METHOD(HttpRequest
, unsetSslOptions
)
1144 getObject(http_request_object
, obj
);
1148 opts
= GET_PROP(obj
, options
);
1149 zend_hash_del(Z_ARRVAL_P(opts
), "ssl", sizeof("ssl"));
1153 /* {{{ proto bool HttpRequest::addHeaders(array headers)
1155 * Add request header name/value pairs.
1157 PHP_METHOD(HttpRequest
, addHeaders
)
1159 zval
*opts
, **headers
, *new_headers
;
1160 getObject(http_request_object
, obj
);
1162 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a/", &new_headers
)) {
1166 opts
= GET_PROP(obj
, options
);
1168 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(opts
), "headers", sizeof("headers"), (void **) &headers
)) {
1169 array_merge(new_headers
, *headers
);
1171 zval_add_ref(&new_headers
);
1172 add_assoc_zval(opts
, "headers", new_headers
);
1179 /* {{{ proto array HttpRequest::getHeaders()
1181 * Get previously set request headers.
1183 PHP_METHOD(HttpRequest
, getHeaders
)
1185 zval
*opts
, **headers
;
1186 getObject(http_request_object
, obj
);
1190 opts
= GET_PROP(obj
, options
);
1192 array_init(return_value
);
1194 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(opts
), "headers", sizeof("headers"), (void **) &headers
)) {
1195 array_copy(*headers
, return_value
);
1200 /* {{{ proto void HttpRequest::unsetHeaders()
1202 * Unset previously set request headers.
1204 PHP_METHOD(HttpRequest
, unsetHeaders
)
1207 getObject(http_request_object
, obj
);
1211 opts
= GET_PROP(obj
, options
);
1212 zend_hash_del(Z_ARRVAL_P(opts
), "headers", sizeof("headers"));
1216 /* {{{ proto bool HttpRequest::addCookies(array cookies)
1220 PHP_METHOD(HttpRequest
, addCookies
)
1222 zval
*opts
, **cookies
, *new_cookies
;
1223 getObject(http_request_object
, obj
);
1225 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a/", &new_cookies
)) {
1229 opts
= GET_PROP(obj
, options
);
1231 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(opts
), "cookies", sizeof("cookies"), (void **) &cookies
)) {
1232 array_merge(new_cookies
, *cookies
);
1234 zval_add_ref(&new_cookies
);
1235 add_assoc_zval(opts
, "cookies", new_cookies
);
1242 /* {{{ proto array HttpRequest::getCookies()
1244 * Get previously set cookies.
1246 PHP_METHOD(HttpRequest
, getCookies
)
1248 zval
*opts
, **cookies
;
1249 getObject(http_request_object
, obj
);
1253 opts
= GET_PROP(obj
, options
);
1255 array_init(return_value
);
1257 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(opts
), "cookies", sizeof("cookies"), (void **) &cookies
)) {
1258 array_copy(*cookies
, return_value
);
1263 /* {{{ proto void HttpRequest::unsetCookies()
1266 PHP_METHOD(HttpRequest
, unsetCookies
)
1269 getObject(http_request_object
, obj
);
1273 opts
= GET_PROP(obj
, options
);
1274 zend_hash_del(Z_ARRVAL_P(opts
), "cookies", sizeof("cookies"));
1278 /* {{{ proto bool HttpRequest::setURL(string url)
1280 * Set the request URL.
1282 PHP_METHOD(HttpRequest
, setURL
)
1286 getObject(http_request_object
, obj
);
1288 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &URL
, &URL_len
)) {
1292 UPD_PROP(obj
, string
, url
, URL
);
1297 /* {{{ proto string HttpRequest::getUrl()
1299 * Get the previously set request URL.
1301 PHP_METHOD(HttpRequest
, getURL
)
1304 getObject(http_request_object
, obj
);
1308 URL
= GET_PROP(obj
, url
);
1309 RETURN_STRINGL(Z_STRVAL_P(URL
), Z_STRLEN_P(URL
), 1);
1313 /* {{{ proto bool HttpRequest::setMethod(long request_method)
1315 * Set the request methods; one of the <tt>HTTP_HEAD</tt>, <tt>HTTP_GET</tt> or
1316 * <tt>HTTP_POST</tt> constants.
1318 PHP_METHOD(HttpRequest
, setMethod
)
1321 getObject(http_request_object
, obj
);
1323 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &meth
)) {
1327 UPD_PROP(obj
, long, method
, meth
);
1332 /* {{{ proto long HttpRequest::getMethod()
1334 * Get the previously set request method.
1336 PHP_METHOD(HttpRequest
, getMethod
)
1339 getObject(http_request_object
, obj
);
1343 meth
= GET_PROP(obj
, method
);
1344 RETURN_LONG(Z_LVAL_P(meth
));
1348 /* {{{ proto bool HttpRequest::setContentType(string content_type)
1350 * Set the content type the post request should have.
1351 * Use this only if you know what you're doing.
1353 PHP_METHOD(HttpRequest
, setContentType
)
1357 getObject(http_request_object
, obj
);
1359 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &ctype
, &ct_len
)) {
1363 if (!strchr(ctype
, '/')) {
1364 http_error_ex(E_WARNING
, HTTP_E_PARAM
, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", ctype
);
1368 UPD_PROP(obj
, string
, contentType
, ctype
);
1373 /* {{{ proto string HttpRequest::getContentType()
1375 * Get the previously content type.
1377 PHP_METHOD(HttpRequest
, getContentType
)
1380 getObject(http_request_object
, obj
);
1384 ctype
= GET_PROP(obj
, contentType
);
1385 RETURN_STRINGL(Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
1389 /* {{{ proto bool HttpRequest::setQueryData(mixed query_data)
1391 * Set the URL query parameters to use.
1392 * Overwrites previously set query parameters.
1393 * Affects any request types.
1395 PHP_METHOD(HttpRequest
, setQueryData
)
1398 char *query_data
= NULL
;
1399 getObject(http_request_object
, obj
);
1401 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z", &qdata
)) {
1405 if ((Z_TYPE_P(qdata
) == IS_ARRAY
) || (Z_TYPE_P(qdata
) == IS_OBJECT
)) {
1406 if (SUCCESS
!= http_urlencode_hash(HASH_OF(qdata
), &query_data
)) {
1409 UPD_PROP(obj
, string
, queryData
, query_data
);
1414 convert_to_string(qdata
);
1415 UPD_PROP(obj
, string
, queryData
, Z_STRVAL_P(qdata
));
1420 /* {{{ proto string HttpRequest::getQueryData()
1422 * Get the current query data in form of an urlencoded query string.
1424 PHP_METHOD(HttpRequest
, getQueryData
)
1427 getObject(http_request_object
, obj
);
1431 qdata
= GET_PROP(obj
, queryData
);
1432 RETURN_STRINGL(Z_STRVAL_P(qdata
), Z_STRLEN_P(qdata
), 1);
1436 /* {{{ proto bool HttpRequest::addQueryData(array query_params)
1438 * Add parameters to the query parameter list.
1439 * Affects any request type.
1441 PHP_METHOD(HttpRequest
, addQueryData
)
1443 zval
*qdata
, *old_qdata
;
1444 char *query_data
= NULL
;
1445 getObject(http_request_object
, obj
);
1447 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a", &qdata
)) {
1451 old_qdata
= GET_PROP(obj
, queryData
);
1453 if (SUCCESS
!= http_urlencode_hash_ex(HASH_OF(qdata
), 1, Z_STRVAL_P(old_qdata
), Z_STRLEN_P(old_qdata
), &query_data
, NULL
)) {
1457 UPD_PROP(obj
, string
, queryData
, query_data
);
1464 /* {{{ proto void HttpRequest::unsetQueryData()
1466 * Clean the query parameters.
1467 * Affects any request type.
1469 PHP_METHOD(HttpRequest
, unsetQueryData
)
1471 getObject(http_request_object
, obj
);
1475 UPD_PROP(obj
, string
, queryData
, "");
1479 /* {{{ proto bool HttpRequest::addPostFields(array post_data)
1481 * Adds POST data entries.
1482 * Affects only POST requests.
1484 PHP_METHOD(HttpRequest
, addPostFields
)
1486 zval
*post
, *post_data
;
1487 getObject(http_request_object
, obj
);
1489 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a", &post_data
)) {
1493 post
= GET_PROP(obj
, postFields
);
1494 array_merge(post_data
, post
);
1500 /* {{{ proto bool HttpRequest::setPostFields(array post_data)
1502 * Set the POST data entries.
1503 * Overwrites previously set POST data.
1504 * Affects only POST requests.
1506 PHP_METHOD(HttpRequest
, setPostFields
)
1508 zval
*post
, *post_data
;
1509 getObject(http_request_object
, obj
);
1511 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a", &post_data
)) {
1515 post
= GET_PROP(obj
, postFields
);
1516 zend_hash_clean(Z_ARRVAL_P(post
));
1517 array_copy(post_data
, post
);
1523 /* {{{ proto array HttpRequest::getPostFields()
1525 * Get previously set POST data.
1527 PHP_METHOD(HttpRequest
, getPostFields
)
1530 getObject(http_request_object
, obj
);
1534 post_data
= GET_PROP(obj
, postFields
);
1535 array_init(return_value
);
1536 array_copy(post_data
, return_value
);
1540 /* {{{ proto void HttpRequest::unsetPostFields()
1542 * Clean POST data entires.
1543 * Affects only POST requests.
1545 PHP_METHOD(HttpRequest
, unsetPostFields
)
1548 getObject(http_request_object
, obj
);
1552 post_data
= GET_PROP(obj
, postFields
);
1553 zend_hash_clean(Z_ARRVAL_P(post_data
));
1557 /* {{{ proto bool HttpRequest::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
1559 * Add a file to the POST request.
1560 * Affects only POST requests.
1562 PHP_METHOD(HttpRequest
, addPostFile
)
1564 zval
*files
, *entry
;
1565 char *name
, *file
, *type
= NULL
;
1566 int name_len
, file_len
, type_len
= 0;
1567 getObject(http_request_object
, obj
);
1569 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss|s", &name
, &name_len
, &file
, &file_len
, &type
, &type_len
)) {
1574 if (!strchr(type
, '/')) {
1575 http_error_ex(E_WARNING
, HTTP_E_PARAM
, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type
);
1579 type
= "application/x-octetstream";
1580 type_len
= sizeof("application/x-octetstream") - 1;
1583 MAKE_STD_ZVAL(entry
);
1586 add_assoc_stringl(entry
, "name", name
, name_len
, 1);
1587 add_assoc_stringl(entry
, "type", type
, type_len
, 1);
1588 add_assoc_stringl(entry
, "file", file
, file_len
, 1);
1590 files
= GET_PROP(obj
, postFiles
);
1591 add_next_index_zval(files
, entry
);
1597 /* {{{ proto array HttpRequest::getPostFiles()
1599 * Get all previously added POST files.
1601 PHP_METHOD(HttpRequest
, getPostFiles
)
1604 getObject(http_request_object
, obj
);
1608 files
= GET_PROP(obj
, postFiles
);
1610 array_init(return_value
);
1611 array_copy(files
, return_value
);
1615 /* {{{ proto void HttpRequest::unsetPostFiles()
1617 * Unset the POST files list.
1618 * Affects only POST requests.
1620 PHP_METHOD(HttpRequest
, unsetPostFiles
)
1623 getObject(http_request_object
, obj
);
1627 files
= GET_PROP(obj
, postFiles
);
1628 zend_hash_clean(Z_ARRVAL_P(files
));
1632 /* {{{ proto array HttpRequest::getResponseData()
1634 * Get all response data after the request has been sent.
1636 PHP_METHOD(HttpRequest
, getResponseData
)
1639 getObject(http_request_object
, obj
);
1643 data
= GET_PROP(obj
, responseData
);
1644 array_init(return_value
);
1645 array_copy(data
, return_value
);
1649 /* {{{ proto mixed HttpRequest::getResponseHeader([string name])
1651 * Get response header(s) after the request has been sent.
1653 PHP_METHOD(HttpRequest
, getResponseHeader
)
1655 zval
*data
, **headers
, **header
;
1656 char *header_name
= NULL
;
1658 getObject(http_response_object
, obj
);
1660 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s", &header_name
, &header_len
)) {
1664 data
= GET_PROP(obj
, responseData
);
1665 if (SUCCESS
!= zend_hash_find(Z_ARRVAL_P(data
), "headers", sizeof("headers"), (void **) &headers
)) {
1669 if (!header_len
|| !header_name
) {
1670 array_init(return_value
);
1671 array_copy(*headers
, return_value
);
1672 } else if (SUCCESS
== zend_hash_find(Z_ARRVAL_PP(headers
), pretty_key(header_name
, header_len
, 1, 1), header_len
+ 1, (void **) &header
)) {
1673 RETURN_STRINGL(Z_STRVAL_PP(header
), Z_STRLEN_PP(header
), 1);
1680 /* {{{ proto array HttpRequest::getResponseCookie([string name])
1682 * Get response cookie(s) after the request has been sent.
1684 PHP_METHOD(HttpRequest
, getResponseCookie
)
1686 zval
*data
, **headers
;
1687 char *cookie_name
= NULL
;
1689 getObject(http_request_object
, obj
);
1691 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s", &cookie_name
, &cookie_len
)) {
1695 array_init(return_value
);
1697 data
= GET_PROP(obj
, responseData
);
1698 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(data
), "headers", sizeof("headers"), (void **) &headers
)) {
1701 zval
**header
= NULL
;
1703 FOREACH_HASH_KEYVAL(Z_ARRVAL_PP(headers
), key
, idx
, header
) {
1704 if (key
&& !strcasecmp(key
, "Set-Cookie")) {
1705 /* several cookies? */
1706 if (Z_TYPE_PP(header
) == IS_ARRAY
) {
1709 FOREACH_HASH_VAL(Z_ARRVAL_PP(header
), cookie
) {
1711 MAKE_STD_ZVAL(cookie_hash
);
1712 array_init(cookie_hash
);
1714 if (SUCCESS
== http_parse_cookie(Z_STRVAL_PP(cookie
), Z_ARRVAL_P(cookie_hash
))) {
1716 add_next_index_zval(return_value
, cookie_hash
);
1720 if ( (SUCCESS
== zend_hash_find(Z_ARRVAL_P(cookie_hash
), "name", sizeof("name"), (void **) &name
)) &&
1721 (!strcmp(Z_STRVAL_PP(name
), cookie_name
))) {
1722 add_next_index_zval(return_value
, cookie_hash
);
1723 return; /* <<< FOUND >>> */
1725 zval_dtor(cookie_hash
);
1730 zval_dtor(cookie_hash
);
1736 MAKE_STD_ZVAL(cookie_hash
);
1737 array_init(cookie_hash
);
1739 if (SUCCESS
== http_parse_cookie(Z_STRVAL_PP(header
), Z_ARRVAL_P(cookie_hash
))) {
1741 add_next_index_zval(return_value
, cookie_hash
);
1745 if ( (SUCCESS
== zend_hash_find(Z_ARRVAL_P(cookie_hash
), "name", sizeof("name"), (void **) &name
)) &&
1746 (!strcmp(Z_STRVAL_PP(name
), cookie_name
))) {
1747 add_next_index_zval(return_value
, cookie_hash
);
1749 zval_dtor(cookie_hash
);
1754 zval_dtor(cookie_hash
);
1767 /* {{{ proto string HttpRequest::getResponseBody()
1769 * Get the response body after the request has been sent.
1771 PHP_METHOD(HttpRequest
, getResponseBody
)
1774 getObject(http_request_object
, obj
);
1778 data
= GET_PROP(obj
, responseData
);
1779 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(data
), "body", sizeof("body"), (void **) &body
)) {
1780 RETURN_STRINGL(Z_STRVAL_PP(body
), Z_STRLEN_PP(body
), 1);
1787 /* {{{ proto int HttpRequest::getResponseCode()
1789 * Get the response code after the request has been sent.
1791 PHP_METHOD(HttpRequest
, getResponseCode
)
1794 getObject(http_request_object
, obj
);
1798 code
= GET_PROP(obj
, responseCode
);
1799 RETURN_LONG(Z_LVAL_P(code
));
1803 /* {{{ proto array HttpRequest::getResponseInfo([string name])
1805 * Get response info after the request has been sent.
1806 * See http_get() for a full list of returned info.
1808 PHP_METHOD(HttpRequest
, getResponseInfo
)
1810 zval
*info
, **infop
;
1811 char *info_name
= NULL
;
1813 getObject(http_request_object
, obj
);
1815 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s", &info_name
, &info_len
)) {
1819 info
= GET_PROP(obj
, responseInfo
);
1821 if (info_len
&& info_name
) {
1822 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(info
), pretty_key(info_name
, info_len
, 0, 0), info_len
+ 1, (void **) &infop
)) {
1823 RETURN_ZVAL(*infop
, 1, ZVAL_PTR_DTOR
);
1825 http_error_ex(E_NOTICE
, HTTP_E_PARAM
, "Could not find response info named %s", info_name
);
1829 array_init(return_value
);
1830 array_copy(info
, return_value
);
1835 /* {{{ proto HttpMessage HttpRequest::getResponseMessage()
1837 * Get the full response as HttpMessage object.
1839 PHP_METHOD(HttpRequest
, getResponseMessage
)
1842 getObject(http_request_object
, obj
);
1846 message
= GET_PROP(obj
, responseMessage
);
1847 Z_TYPE_P(return_value
) = IS_OBJECT
;
1848 return_value
->is_ref
= 1;
1849 return_value
->value
.obj
= message
->value
.obj
;
1850 zval_add_ref(&return_value
);
1853 /* {{{ proto bool HttpRequest::send()
1855 * Send the HTTP request.
1860 * $r = new HttpRequest('http://example.com/feed.rss', HTTP_GET);
1861 * $r->setOptions(array('lastmodified' => filemtime('local.rss')));
1862 * $r->addQueryData(array('category' => 3));
1865 * if ($r->getResponseCode() == 200) {
1866 * file_put_contents('local.rss', $r->getResponseBody());
1868 * } catch (HttpException $ex) {
1877 * $r = new HttpRequest('http://example.com/form.php', HTTP_POST);
1878 * $r->setOptions(array('cookies' => array('lang' => 'de')));
1879 * $r->addpostFields(array('user' => 'mike', 'pass' => 's3c|r3t'));
1880 * $r->addPostFile('image', 'profile.jpg', 'image/jpeg');
1882 * echo $r->getResponseBody();
1887 PHP_METHOD(HttpRequest
, send
)
1889 STATUS status
= FAILURE
;
1890 zval
*meth
, *URL
, *qdata
, *opts
, *info
, *resp
;
1892 getObject(http_request_object
, obj
);
1896 SET_EH_THROW_HTTP();
1898 if ((!obj
->ch
) && (!(obj
->ch
= curl_easy_init()))) {
1899 http_error(E_WARNING
, HTTP_E_CURL
, "Could not initilaize curl");
1903 meth
= GET_PROP(obj
, method
);
1904 URL
= GET_PROP(obj
, url
);
1905 qdata
= GET_PROP(obj
, queryData
);
1906 opts
= GET_PROP(obj
, options
);
1907 info
= GET_PROP(obj
, responseInfo
);
1908 resp
= GET_PROP(obj
, responseData
);
1910 // HTTP_URI_MAXLEN+1 long char *
1911 request_uri
= http_absolute_uri_ex(Z_STRVAL_P(URL
), Z_STRLEN_P(URL
), NULL
, 0, NULL
, 0, 0);
1913 if (Z_STRLEN_P(qdata
) && (strlen(request_uri
) < HTTP_URI_MAXLEN
)) {
1914 if (!strchr(request_uri
, '?')) {
1915 strcat(request_uri
, "?");
1917 strcat(request_uri
, "&");
1919 strncat(request_uri
, Z_STRVAL_P(qdata
), HTTP_URI_MAXLEN
- strlen(request_uri
));
1922 switch (Z_LVAL_P(meth
))
1926 status
= http_request_ex(obj
->ch
, Z_LVAL_P(meth
), request_uri
, NULL
, Z_ARRVAL_P(opts
), Z_ARRVAL_P(info
), &obj
->response
);
1931 http_request_body body
;
1933 php_stream_statbuf ssb
;
1934 zval
*file
= GET_PROP(obj
, putFile
);
1936 if ( (stream
= php_stream_open_wrapper(Z_STRVAL_P(file
), , "rb", REPORT_ERRORS
|ENFORCE_SAFE_MODE
, NULL
)) &&
1937 !php_stream_stat(stream
, &ssb
)) {
1938 body
.type
= HTTP_REQUEST_BODY_UPLOADFILE
;
1940 body
.size
= ssb
.sb
.st_size
;
1942 status
= http_put_ex(obj
->ch
, request_uri
, &body
, Z_ARRVAL_P(opts
), Z_ARRVAL_P(info
), &obj
->response
);
1943 http_request_body_dtor(&body
);
1952 http_request_body body
;
1953 zval
*fields
= GET_PROP(obj
, postFields
), *files
= GET_PROP(obj
, postFiles
);
1955 if (SUCCESS
== (status
= http_request_body_fill(&body
, Z_ARRVAL_P(fields
), Z_ARRVAL_P(files
)))) {
1956 status
= http_post_ex(obj
->ch
, request_uri
, &body
, Z_ARRVAL_P(opts
), Z_ARRVAL_P(info
), &obj
->response
);
1957 http_request_body_dtor(&body
);
1964 http_request_body body
;
1965 zval
*post
= GET_PROP(obj
, postData
);
1967 body
.type
= HTTP_REQUEST_BODY_CSTRING
;
1968 body
.data
= Z_STRVAL_P(post
);
1969 body
.size
= Z_STRLEN_P(post
);
1971 status
= http_request_ex(obj
->ch
, Z_LVAL_P(meth
), request_uri
, &body
, Z_ARRVAL_P(opts
), Z_ARRVAL_P(info
), &obj
->response
);
1978 /* final data handling */
1979 if (status
== SUCCESS
) {
1982 if (msg
= http_message_parse(PHPSTR_VAL(&obj
->response
), PHPSTR_LEN(&obj
->response
))) {
1983 zval
*headers
, *message
;
1987 UPD_PROP(obj
, long, responseCode
, msg
->info
.response
.code
);
1989 MAKE_STD_ZVAL(headers
)
1990 array_init(headers
);
1992 zend_hash_copy(Z_ARRVAL_P(headers
), &msg
->hdrs
, (copy_ctor_func_t
) zval_add_ref
, NULL
, sizeof(zval
*));
1993 phpstr_data(PHPSTR(msg
), &body
, &body_len
);
1995 add_assoc_zval(resp
, "headers", headers
);
1996 add_assoc_stringl(resp
, "body", body
, body_len
, 0);
1998 message
= GET_PROP(obj
, responseMessage
);
2000 Z_TYPE_P(message
) = IS_OBJECT
;
2001 message
->value
.obj
= http_message_object_from_msg(msg
);
2002 SET_PROP(obj
, responseMessage
, message
);
2009 RETURN_SUCCESS(status
);
2013 #endif /* HTTP_HAVE_CURL */
2015 #endif /* ZEND_ENGINE_2 */
2022 * vim600: noet sw=4 ts=4 fdm=marker
2023 * vim<600: noet sw=4 ts=4