2 +--------------------------------------------------------------------+
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2007, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
15 #define HTTP_WANT_SAPI
16 #define HTTP_WANT_MAGIC
19 /* broken static properties in PHP 5.0 */
20 #if defined(ZEND_ENGINE_2) && !defined(WONKY)
24 #include "php_http_api.h"
25 #include "php_http_cache_api.h"
26 #include "php_http_exception_object.h"
27 #include "php_http_headers_api.h"
28 #include "php_http_response_object.h"
29 #include "php_http_send_api.h"
31 #define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpResponse, method, 0, req_args)
32 #define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpResponse, method, 0)
33 #define HTTP_RESPONSE_ME(method, visibility) PHP_ME(HttpResponse, method, HTTP_ARGS(HttpResponse, method), visibility|ZEND_ACC_STATIC)
34 #define HTTP_RESPONSE_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpResponse, method))
36 HTTP_BEGIN_ARGS(setHeader
, 1)
38 HTTP_ARG_VAL(value
, 0)
39 HTTP_ARG_VAL(replace
, 0)
42 HTTP_BEGIN_ARGS(getHeader
, 0)
46 HTTP_EMPTY_ARGS(getETag
);
47 HTTP_BEGIN_ARGS(setETag
, 1)
51 HTTP_EMPTY_ARGS(getLastModified
);
52 HTTP_BEGIN_ARGS(setLastModified
, 1)
53 HTTP_ARG_VAL(timestamp
, 0)
56 HTTP_EMPTY_ARGS(getCache
);
57 HTTP_BEGIN_ARGS(setCache
, 1)
58 HTTP_ARG_VAL(cache
, 0)
61 HTTP_EMPTY_ARGS(getGzip
);
62 HTTP_BEGIN_ARGS(setGzip
, 1)
66 HTTP_EMPTY_ARGS(getCacheControl
);
67 HTTP_BEGIN_ARGS(setCacheControl
, 1)
68 HTTP_ARG_VAL(cache_control
, 0)
69 HTTP_ARG_VAL(max_age
, 0)
70 HTTP_ARG_VAL(must_revalidate
, 0)
73 HTTP_EMPTY_ARGS(getContentType
);
74 HTTP_BEGIN_ARGS(setContentType
, 1)
75 HTTP_ARG_VAL(content_type
, 0)
78 HTTP_BEGIN_ARGS(guessContentType
, 1)
79 HTTP_ARG_VAL(magic_file
, 0)
80 HTTP_ARG_VAL(magic_mode
, 0)
83 HTTP_EMPTY_ARGS(getContentDisposition
);
84 HTTP_BEGIN_ARGS(setContentDisposition
, 1)
85 HTTP_ARG_VAL(filename
, 0)
86 HTTP_ARG_VAL(send_inline
, 0)
89 HTTP_EMPTY_ARGS(getThrottleDelay
);
90 HTTP_BEGIN_ARGS(setThrottleDelay
, 1)
91 HTTP_ARG_VAL(seconds
, 0)
94 HTTP_EMPTY_ARGS(getBufferSize
);
95 HTTP_BEGIN_ARGS(setBufferSize
, 1)
96 HTTP_ARG_VAL(bytes
, 0)
99 HTTP_EMPTY_ARGS(getData
);
100 HTTP_BEGIN_ARGS(setData
, 1)
101 HTTP_ARG_VAL(data
, 0)
104 HTTP_EMPTY_ARGS(getStream
);
105 HTTP_BEGIN_ARGS(setStream
, 1)
106 HTTP_ARG_VAL(stream
, 0)
109 HTTP_EMPTY_ARGS(getFile
);
110 HTTP_BEGIN_ARGS(setFile
, 1)
111 HTTP_ARG_VAL(filepath
, 0)
114 HTTP_BEGIN_ARGS(send
, 0)
115 HTTP_ARG_VAL(clean_ob
, 0)
118 HTTP_EMPTY_ARGS(capture
);
120 HTTP_BEGIN_ARGS(redirect
, 0)
122 HTTP_ARG_VAL(params
, 0)
123 HTTP_ARG_VAL(session
, 0)
124 HTTP_ARG_VAL(permanent
, 0)
127 HTTP_BEGIN_ARGS(status
, 1)
128 HTTP_ARG_VAL(code
, 0)
131 HTTP_EMPTY_ARGS(getRequestHeaders
);
132 HTTP_EMPTY_ARGS(getRequestBody
);
133 HTTP_EMPTY_ARGS(getRequestBodyStream
);
135 #define THIS_CE http_response_object_ce
136 zend_class_entry
*http_response_object_ce
;
137 zend_function_entry http_response_object_fe
[] = {
139 HTTP_RESPONSE_ME(setHeader
, ZEND_ACC_PUBLIC
)
140 HTTP_RESPONSE_ME(getHeader
, ZEND_ACC_PUBLIC
)
142 HTTP_RESPONSE_ME(setETag
, ZEND_ACC_PUBLIC
)
143 HTTP_RESPONSE_ME(getETag
, ZEND_ACC_PUBLIC
)
145 HTTP_RESPONSE_ME(setLastModified
, ZEND_ACC_PUBLIC
)
146 HTTP_RESPONSE_ME(getLastModified
, ZEND_ACC_PUBLIC
)
148 HTTP_RESPONSE_ME(setContentDisposition
, ZEND_ACC_PUBLIC
)
149 HTTP_RESPONSE_ME(getContentDisposition
, ZEND_ACC_PUBLIC
)
151 HTTP_RESPONSE_ME(setContentType
, ZEND_ACC_PUBLIC
)
152 HTTP_RESPONSE_ME(getContentType
, ZEND_ACC_PUBLIC
)
154 HTTP_RESPONSE_ME(guessContentType
, ZEND_ACC_PUBLIC
)
156 HTTP_RESPONSE_ME(setCache
, ZEND_ACC_PUBLIC
)
157 HTTP_RESPONSE_ME(getCache
, ZEND_ACC_PUBLIC
)
159 HTTP_RESPONSE_ME(setCacheControl
, ZEND_ACC_PUBLIC
)
160 HTTP_RESPONSE_ME(getCacheControl
, ZEND_ACC_PUBLIC
)
162 HTTP_RESPONSE_ME(setGzip
, ZEND_ACC_PUBLIC
)
163 HTTP_RESPONSE_ME(getGzip
, ZEND_ACC_PUBLIC
)
165 HTTP_RESPONSE_ME(setThrottleDelay
, ZEND_ACC_PUBLIC
)
166 HTTP_RESPONSE_ME(getThrottleDelay
, ZEND_ACC_PUBLIC
)
168 HTTP_RESPONSE_ME(setBufferSize
, ZEND_ACC_PUBLIC
)
169 HTTP_RESPONSE_ME(getBufferSize
, ZEND_ACC_PUBLIC
)
171 HTTP_RESPONSE_ME(setData
, ZEND_ACC_PUBLIC
)
172 HTTP_RESPONSE_ME(getData
, ZEND_ACC_PUBLIC
)
174 HTTP_RESPONSE_ME(setFile
, ZEND_ACC_PUBLIC
)
175 HTTP_RESPONSE_ME(getFile
, ZEND_ACC_PUBLIC
)
177 HTTP_RESPONSE_ME(setStream
, ZEND_ACC_PUBLIC
)
178 HTTP_RESPONSE_ME(getStream
, ZEND_ACC_PUBLIC
)
180 HTTP_RESPONSE_ME(send
, ZEND_ACC_PUBLIC
)
181 HTTP_RESPONSE_ME(capture
, ZEND_ACC_PUBLIC
)
183 HTTP_RESPONSE_ALIAS(redirect
, http_redirect
)
184 HTTP_RESPONSE_ALIAS(status
, http_send_status
)
185 HTTP_RESPONSE_ALIAS(getRequestHeaders
, http_get_request_headers
)
186 HTTP_RESPONSE_ALIAS(getRequestBody
, http_get_request_body
)
187 HTTP_RESPONSE_ALIAS(getRequestBodyStream
, http_get_request_body_stream
)
192 PHP_MINIT_FUNCTION(http_response_object
)
194 HTTP_REGISTER_CLASS(HttpResponse
, http_response_object
, NULL
, 0);
196 zend_declare_property_bool(THIS_CE
, ZEND_STRS("sent")-1, 0, (ZEND_ACC_STATIC
|ZEND_ACC_PRIVATE
) TSRMLS_CC
);
197 zend_declare_property_bool(THIS_CE
, ZEND_STRS("catch")-1, 0, (ZEND_ACC_STATIC
|ZEND_ACC_PRIVATE
) TSRMLS_CC
);
198 zend_declare_property_long(THIS_CE
, ZEND_STRS("mode")-1, -1, (ZEND_ACC_STATIC
|ZEND_ACC_PRIVATE
) TSRMLS_CC
);
199 zend_declare_property_long(THIS_CE
, ZEND_STRS("stream")-1, 0, (ZEND_ACC_STATIC
|ZEND_ACC_PRIVATE
) TSRMLS_CC
);
200 zend_declare_property_null(THIS_CE
, ZEND_STRS("file")-1, (ZEND_ACC_STATIC
|ZEND_ACC_PRIVATE
) TSRMLS_CC
);
201 zend_declare_property_null(THIS_CE
, ZEND_STRS("data")-1, (ZEND_ACC_STATIC
|ZEND_ACC_PRIVATE
) TSRMLS_CC
);
202 zend_declare_property_bool(THIS_CE
, ZEND_STRS("cache")-1, 0, (ZEND_ACC_STATIC
|ZEND_ACC_PROTECTED
) TSRMLS_CC
);
203 zend_declare_property_bool(THIS_CE
, ZEND_STRS("gzip")-1, 0, (ZEND_ACC_STATIC
|ZEND_ACC_PROTECTED
) TSRMLS_CC
);
204 zend_declare_property_null(THIS_CE
, ZEND_STRS("eTag")-1, (ZEND_ACC_STATIC
|ZEND_ACC_PROTECTED
) TSRMLS_CC
);
205 zend_declare_property_long(THIS_CE
, ZEND_STRS("lastModified")-1, 0, (ZEND_ACC_STATIC
|ZEND_ACC_PROTECTED
) TSRMLS_CC
);
206 zend_declare_property_null(THIS_CE
, ZEND_STRS("cacheControl")-1, (ZEND_ACC_STATIC
|ZEND_ACC_PROTECTED
) TSRMLS_CC
);
207 zend_declare_property_null(THIS_CE
, ZEND_STRS("contentType")-1, (ZEND_ACC_STATIC
|ZEND_ACC_PROTECTED
) TSRMLS_CC
);
208 zend_declare_property_null(THIS_CE
, ZEND_STRS("contentDisposition")-1, (ZEND_ACC_STATIC
|ZEND_ACC_PROTECTED
) TSRMLS_CC
);
209 zend_declare_property_long(THIS_CE
, ZEND_STRS("bufferSize")-1, 0, (ZEND_ACC_STATIC
|ZEND_ACC_PROTECTED
) TSRMLS_CC
);
210 zend_declare_property_double(THIS_CE
, ZEND_STRS("throttleDelay")-1, 0.0, (ZEND_ACC_STATIC
|ZEND_ACC_PROTECTED
) TSRMLS_CC
);
213 zend_declare_class_constant_long(THIS_CE
, ZEND_STRS("REDIRECT")-1, HTTP_REDIRECT TSRMLS_CC
);
214 zend_declare_class_constant_long(THIS_CE
, ZEND_STRS("REDIRECT_PERM")-1, HTTP_REDIRECT_PERM TSRMLS_CC
);
215 zend_declare_class_constant_long(THIS_CE
, ZEND_STRS("REDIRECT_FOUND")-1, HTTP_REDIRECT_FOUND TSRMLS_CC
);
216 zend_declare_class_constant_long(THIS_CE
, ZEND_STRS("REDIRECT_POST")-1, HTTP_REDIRECT_POST TSRMLS_CC
);
217 zend_declare_class_constant_long(THIS_CE
, ZEND_STRS("REDIRECT_PROXY")-1, HTTP_REDIRECT_PROXY TSRMLS_CC
);
218 zend_declare_class_constant_long(THIS_CE
, ZEND_STRS("REDIRECT_TEMP")-1, HTTP_REDIRECT_TEMP TSRMLS_CC
);
224 /* ### USERLAND ### */
226 /* {{{ proto static bool HttpResponse::setHeader(string name[, mixed value[, bool replace = true]])
227 Send an HTTP header. */
228 PHP_METHOD(HttpResponse
, setHeader
)
230 zend_bool replace
= 1;
235 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|z/!b", &name
, &name_len
, &value
, &replace
)) {
238 if (SG(headers_sent
)) {
239 http_error(HE_WARNING
, HTTP_E_HEADER
, "Cannot add another header when headers have already been sent");
243 http_error(HE_WARNING
, HTTP_E_HEADER
, "Cannot send anonymous headers");
246 http_send_header_zval_ex(name
, name_len
, &value
, replace
);
251 /* {{{ proto static mixed HttpResponse::getHeader([string name])
252 Get header(s) about to be sent. */
253 PHP_METHOD(HttpResponse
, getHeader
)
258 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s", &name
, &name_len
)) {
262 if (name
&& name_len
) {
264 HashTable headers_ht
;
266 zend_hash_init(&headers_ht
, sizeof(zval
*), NULL
, ZVAL_PTR_DTOR
, 0);
267 if ( (SUCCESS
== http_get_response_headers(&headers_ht
)) &&
268 (SUCCESS
== zend_hash_find(&headers_ht
, name
, name_len
+ 1, (void *) &header
))) {
269 RETVAL_ZVAL(*header
, 1, 0);
273 zend_hash_destroy(&headers_ht
);
275 array_init(return_value
);
276 http_get_response_headers(Z_ARRVAL_P(return_value
));
281 /* {{{ proto static bool HttpResponse::setCache(bool cache)
282 Whether it should be attempted to cache the entity. */
283 PHP_METHOD(HttpResponse
, setCache
)
285 zend_bool do_cache
= 0;
287 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "b", &do_cache
)) {
291 RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE
, ZEND_STRS("cache")-1, do_cache TSRMLS_CC
));
295 /* {{{ proto static bool HttpResponse::getCache()
296 Get current caching setting. */
297 PHP_METHOD(HttpResponse
, getCache
)
301 if (return_value_used
) {
302 zval
*cache
= http_zsep(IS_BOOL
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("cache")-1, 0 TSRMLS_CC
)));
303 RETVAL_ZVAL(cache
, 1, 1);
308 /* {{{ proto static bool HttpResponse::setGzip(bool gzip)
309 Enable on-thy-fly gzipping of the sent entity. */
310 PHP_METHOD(HttpResponse
, setGzip
)
312 zend_bool do_gzip
= 0;
314 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "b", &do_gzip
)) {
318 RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE
, ZEND_STRS("gzip")-1, do_gzip TSRMLS_CC
));
322 /* {{{ proto static bool HttpResponse::getGzip()
323 Get current gzipping setting. */
324 PHP_METHOD(HttpResponse
, getGzip
)
328 if (return_value_used
) {
329 zval
*gzip
= http_zsep(IS_BOOL
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("gzip")-1, 0 TSRMLS_CC
)));
330 RETVAL_ZVAL(gzip
, 1, 1);
335 /* {{{ proto static bool HttpResponse::setCacheControl(string control[, int max_age = 0[, bool must_revalidate = true]])
336 Set a custom cache-control header, usually being "private" or "public"; The max_age parameter controls how long the cache entry is valid on the client side. */
337 PHP_METHOD(HttpResponse
, setCacheControl
)
339 char *ccontrol
, *cctl
;
342 zend_bool must_revalidate
= 1;
344 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|lb", &ccontrol
, &cc_len
, &max_age
, &must_revalidate
)) {
348 if (strcmp(ccontrol
, "public") && strcmp(ccontrol
, "private") && strcmp(ccontrol
, "no-cache")) {
349 http_error_ex(HE_WARNING
, HTTP_E_INVALID_PARAM
, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol
);
352 size_t cctl_len
= spprintf(&cctl
, 0, "%s,%s max-age=%ld", ccontrol
, must_revalidate
?" must-revalidate,":"", max_age
);
353 RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE
, ZEND_STRS("cacheControl")-1, cctl
, cctl_len TSRMLS_CC
));
359 /* {{{ proto static string HttpResponse::getCacheControl()
360 Get current Cache-Control header setting. */
361 PHP_METHOD(HttpResponse
, getCacheControl
)
365 if (return_value_used
) {
366 zval
*cctl
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("cacheControl")-1, 0 TSRMLS_CC
)));
367 RETVAL_ZVAL(cctl
, 1, 1);
372 /* {{{ proto static bool HttpResponse::setContentType(string content_type)
373 Set the content-type of the sent entity. */
374 PHP_METHOD(HttpResponse
, setContentType
)
379 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &ctype
, &ctype_len
)) {
383 HTTP_CHECK_CONTENT_TYPE(ctype
, RETURN_FALSE
);
384 RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE
, ZEND_STRS("contentType")-1, ctype
, ctype_len TSRMLS_CC
));
388 /* {{{ proto static string HttpResponse::getContentType()
389 Get current Content-Type header setting. */
390 PHP_METHOD(HttpResponse
, getContentType
)
394 if (return_value_used
) {
395 zval
*ctype
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("contentType")-1, 0 TSRMLS_CC
)));
396 RETVAL_ZVAL(ctype
, 1, 1);
401 /* {{{ proto static string HttpResponse::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME])
402 Attempts to guess the content type of supplied payload through libmagic. */
403 PHP_METHOD(HttpResponse
, guessContentType
)
405 #ifdef HTTP_HAVE_MAGIC
406 char *magic_file
, *ct
= NULL
;
408 long magic_mode
= MAGIC_MIME
;
412 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|l", &magic_file
, &magic_file_len
, &magic_mode
)) {
413 switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE
, ZEND_STRS("mode")-1, 0 TSRMLS_CC
))) {
416 zval
*data
= *zend_std_get_static_property(THIS_CE
, ZEND_STRS("data")-1, 0 TSRMLS_CC
);
417 ct
= http_guess_content_type(magic_file
, magic_mode
, Z_STRVAL_P(data
), Z_STRLEN_P(data
), SEND_DATA
);
424 zval
*z
= *zend_std_get_static_property(THIS_CE
, ZEND_STRS("stream")-1, 0 TSRMLS_CC
);
425 z
->type
= IS_RESOURCE
;
426 php_stream_from_zval(s
, &z
);
427 ct
= http_guess_content_type(magic_file
, magic_mode
, s
, 0, SEND_RSRC
);
432 ct
= http_guess_content_type(magic_file
, magic_mode
, Z_STRVAL_P(*zend_std_get_static_property(THIS_CE
, ZEND_STRS("file")-1, 0 TSRMLS_CC
)), 0, -1);
436 zend_update_static_property_string(THIS_CE
, ZEND_STRS("contentType")-1, ct TSRMLS_CC
);
437 RETVAL_STRING(ct
, 0);
442 http_error(HE_THROW
, HTTP_E_RUNTIME
, "Cannot guess Content-Type; libmagic not available");
448 /* {{{ proto static bool HttpResponse::setContentDisposition(string filename[, bool inline = false])
449 Set the Content-Disposition. */
450 PHP_METHOD(HttpResponse
, setContentDisposition
)
455 zend_bool send_inline
= 0;
457 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|b", &file
, &file_len
, &send_inline
)) {
461 cd_len
= spprintf(&cd
, 0, "%s; filename=\"%s\"", send_inline
? "inline" : "attachment", file
);
462 RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE
, ZEND_STRS("contentDisposition")-1, cd
, cd_len TSRMLS_CC
));
467 /* {{{ proto static string HttpResponse::getContentDisposition()
468 Get current Content-Disposition setting. */
469 PHP_METHOD(HttpResponse
, getContentDisposition
)
473 if (return_value_used
) {
474 zval
*cdisp
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("contentDisposition")-1, 0 TSRMLS_CC
)));
475 RETVAL_ZVAL(cdisp
, 1, 1);
480 /* {{{ proto static bool HttpResponse::setETag(string etag)
481 Set a custom ETag. Use this only if you know what you're doing. */
482 PHP_METHOD(HttpResponse
, setETag
)
487 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &etag
, &etag_len
)) {
491 RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE
, ZEND_STRS("eTag")-1, etag
, etag_len TSRMLS_CC
));
495 /* {{{ proto static string HttpResponse::getETag()
496 Get calculated or previously set custom ETag. */
497 PHP_METHOD(HttpResponse
, getETag
)
501 if (return_value_used
) {
502 zval
*etag
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("eTag")-1, 0 TSRMLS_CC
)));
503 RETVAL_ZVAL(etag
, 1, 1);
508 /* {{{ proto static bool HttpResponse::setLastModified(int timestamp)
509 Set a custom Last-Modified date. */
510 PHP_METHOD(HttpResponse
, setLastModified
)
514 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &lm
)) {
518 RETURN_SUCCESS(zend_update_static_property_long(THIS_CE
, ZEND_STRS("lastModified")-1, lm TSRMLS_CC
));
522 /* {{{ proto static int HttpResponse::getLastModified()
523 Get calculated or previously set custom Last-Modified date. */
524 PHP_METHOD(HttpResponse
, getLastModified
)
528 if (return_value_used
) {
529 zval
*lmod
= http_zsep(IS_LONG
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("lastModified")-1, 0 TSRMLS_CC
)));
530 RETVAL_ZVAL(lmod
, 1, 1);
535 /* {{{ proto static bool HttpResponse::setThrottleDelay(double seconds)
536 Sets the throttle delay for use with HttpResponse::setBufferSize(). */
537 PHP_METHOD(HttpResponse
, setThrottleDelay
)
541 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "d", &seconds
)) {
544 RETURN_SUCCESS(zend_update_static_property_double(THIS_CE
, ZEND_STRS("throttleDelay")-1, seconds TSRMLS_CC
));
548 /* {{{ proto static double HttpResponse::getThrottleDelay()
549 Get the current throttle delay. */
550 PHP_METHOD(HttpResponse
, getThrottleDelay
)
554 if (return_value_used
) {
555 zval
*tdel
= http_zsep(IS_DOUBLE
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("throttleDelay")-1, 0 TSRMLS_CC
)));
556 RETVAL_ZVAL(tdel
, 1, 1);
561 /* {{{ proto static bool HttpResponse::setBufferSize(int bytes)
562 Sets the send buffer size for use with HttpResponse::setThrottleDelay(). */
563 PHP_METHOD(HttpResponse
, setBufferSize
)
567 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &bytes
)) {
570 RETURN_SUCCESS(zend_update_static_property_long(THIS_CE
, ZEND_STRS("bufferSize")-1, bytes TSRMLS_CC
));
574 /* {{{ proto static int HttpResponse::getBufferSize()
575 Get current buffer size. */
576 PHP_METHOD(HttpResponse
, getBufferSize
)
580 if (return_value_used
) {
581 zval
*bsize
= http_zsep(IS_LONG
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("bufferSize")-1, 0 TSRMLS_CC
)));
582 RETVAL_ZVAL(bsize
, 1, 1);
587 /* {{{ proto static bool HttpResponse::setData(mixed data)
588 Set the data to be sent. */
589 PHP_METHOD(HttpResponse
, setData
)
594 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z/", &the_data
)) {
597 if (Z_TYPE_P(the_data
) != IS_STRING
) {
598 convert_to_string(the_data
);
601 if ( (SUCCESS
!= zend_update_static_property(THIS_CE
, ZEND_STRS("data")-1, the_data TSRMLS_CC
)) ||
602 (SUCCESS
!= zend_update_static_property_long(THIS_CE
, ZEND_STRS("mode")-1, SEND_DATA TSRMLS_CC
))) {
606 zend_update_static_property_long(THIS_CE
, ZEND_STRS("lastModified")-1, http_last_modified(the_data
, SEND_DATA
) TSRMLS_CC
);
607 if ((etag
= http_etag(Z_STRVAL_P(the_data
), Z_STRLEN_P(the_data
), SEND_DATA
))) {
608 zend_update_static_property_string(THIS_CE
, ZEND_STRS("eTag")-1, etag TSRMLS_CC
);
616 /* {{{ proto static string HttpResponse::getData()
617 Get the previously set data to be sent. */
618 PHP_METHOD(HttpResponse
, getData
)
622 if (return_value_used
) {
623 zval
*the_data
= *zend_std_get_static_property(THIS_CE
, ZEND_STRS("data")-1, 0 TSRMLS_CC
);
625 RETURN_ZVAL(the_data
, 1, 0);
630 /* {{{ proto static bool HttpResponse::setStream(resource stream)
631 Set the resource to be sent. */
632 PHP_METHOD(HttpResponse
, setStream
)
636 php_stream
*the_real_stream
;
637 php_stream_statbuf ssb
;
639 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "r", &the_stream
)) {
643 php_stream_from_zval(the_real_stream
, &the_stream
);
644 if (php_stream_stat(the_real_stream
, &ssb
)) {
648 if ( (SUCCESS
!= zend_update_static_property_long(THIS_CE
, ZEND_STRS("stream")-1, Z_LVAL_P(the_stream
) TSRMLS_CC
)) ||
649 (SUCCESS
!= zend_update_static_property_long(THIS_CE
, ZEND_STRS("mode")-1, SEND_RSRC TSRMLS_CC
))) {
652 zend_list_addref(Z_LVAL_P(the_stream
));
654 zend_update_static_property_long(THIS_CE
, ZEND_STRS("lastModified")-1, http_last_modified(the_real_stream
, SEND_RSRC
) TSRMLS_CC
);
655 if ((etag
= http_etag(the_real_stream
, 0, SEND_RSRC
))) {
656 zend_update_static_property_string(THIS_CE
, ZEND_STRS("eTag")-1, etag TSRMLS_CC
);
664 /* {{{ proto static resource HttpResponse::getStream()
665 Get the previously set resource to be sent. */
666 PHP_METHOD(HttpResponse
, getStream
)
670 if (return_value_used
) {
671 zval
*stream
= http_zsep(IS_LONG
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("stream")-1, 0 TSRMLS_CC
)));
672 RETVAL_RESOURCE(Z_LVAL_P(stream
));
673 zval_ptr_dtor(&stream
);
678 /* {{{ proto static bool HttpResponse::setFile(string file)
679 Set the file to be sent. */
680 PHP_METHOD(HttpResponse
, setFile
)
682 char *the_file
, *etag
;
684 php_stream_statbuf ssb
;
686 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &the_file
, &file_len
)) {
690 if (php_stream_stat_path(the_file
, &ssb
)) {
694 if ( (SUCCESS
!= zend_update_static_property_stringl(THIS_CE
, ZEND_STRS("file")-1, the_file
, file_len TSRMLS_CC
)) ||
695 (SUCCESS
!= zend_update_static_property_long(THIS_CE
, ZEND_STRS("mode")-1, -1 TSRMLS_CC
))) {
699 zend_update_static_property_long(THIS_CE
, ZEND_STRS("lastModified")-1, http_last_modified(the_file
, -1) TSRMLS_CC
);
700 if ((etag
= http_etag(the_file
, 0, -1))) {
701 zend_update_static_property_string(THIS_CE
, ZEND_STRS("eTag")-1, etag TSRMLS_CC
);
709 /* {{{ proto static string HttpResponse::getFile()
710 Get the previously set file to be sent. */
711 PHP_METHOD(HttpResponse
, getFile
)
715 if (return_value_used
) {
716 zval
*file
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("file")-1, 0 TSRMLS_CC
)));
717 RETVAL_ZVAL(file
, 1, 1);
722 /* {{{ proto static bool HttpResponse::send([bool clean_ob = true])
723 Finally send the entity. */
724 PHP_METHOD(HttpResponse
, send
)
727 zend_bool clean_ob
= 1;
729 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|b", &clean_ob
)) {
733 HTTP_CHECK_HEADERS_SENT(RETURN_FALSE
);
735 sent
= *zend_std_get_static_property(THIS_CE
, ZEND_STRS("sent")-1, 0 TSRMLS_CC
);
736 if (Z_LVAL_P(sent
)) {
737 http_error(HE_WARNING
, HTTP_E_RESPONSE
, "Cannot send HttpResponse, response has already been sent");
744 if (i_zend_is_true(*zend_std_get_static_property(THIS_CE
, ZEND_STRS("catch")-1, 0 TSRMLS_CC
))) {
745 zval
*zetag
, *the_data
;
747 MAKE_STD_ZVAL(the_data
);
748 php_ob_get_buffer(the_data TSRMLS_CC
);
749 zend_update_static_property(THIS_CE
, ZEND_STRS("data")-1, the_data TSRMLS_CC
);
750 ZVAL_LONG(*zend_std_get_static_property(THIS_CE
, ZEND_STRS("mode")-1, 0 TSRMLS_CC
), SEND_DATA
);
752 zetag
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("eTag")-1, 0 TSRMLS_CC
)));
753 if (!Z_STRLEN_P(zetag
)) {
754 char *etag
= http_etag(Z_STRVAL_P(the_data
), Z_STRLEN_P(the_data
), SEND_DATA
);
756 zend_update_static_property_string(THIS_CE
, ZEND_STRS("eTag")-1, etag TSRMLS_CC
);
760 zval_ptr_dtor(&the_data
);
761 zval_ptr_dtor(&zetag
);
767 /* interrupt on-the-fly etag generation */
768 HTTP_G
->etag
.started
= 0;
769 /* discard previous output buffers */
770 php_end_ob_buffers(0 TSRMLS_CC
);
774 if (i_zend_is_true(*zend_std_get_static_property(THIS_CE
, ZEND_STRS("cache")-1, 0 TSRMLS_CC
))) {
775 zval
*cctl
, *etag
, *lmod
;
777 lmod
= http_zsep(IS_LONG
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("lastModified")-1, 0 TSRMLS_CC
)));
778 etag
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("eTag")-1, 0 TSRMLS_CC
)));
779 cctl
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("cacheControl")-1, 0 TSRMLS_CC
)));
781 if (Z_LVAL_P(lmod
) || Z_STRLEN_P(etag
)) {
782 if (Z_STRLEN_P(cctl
)) {
783 http_send_cache_control(Z_STRVAL_P(cctl
), Z_STRLEN_P(cctl
));
785 http_send_cache_control(HTTP_DEFAULT_CACHECONTROL
, lenof(HTTP_DEFAULT_CACHECONTROL
));
787 if (Z_STRLEN_P(etag
)) {
788 http_send_etag(Z_STRVAL_P(etag
), Z_STRLEN_P(etag
));
790 if (Z_LVAL_P(lmod
)) {
791 http_send_last_modified(Z_LVAL_P(lmod
));
795 zval_ptr_dtor(&etag
);
796 zval_ptr_dtor(&lmod
);
797 zval_ptr_dtor(&cctl
);
802 zval
*ctype
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("contentType")-1, 0 TSRMLS_CC
)));
803 if (Z_STRLEN_P(ctype
)) {
804 http_send_content_type(Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
));
806 char *ctypes
= INI_STR("default_mimetype");
807 size_t ctlen
= ctypes
? strlen(ctypes
) : 0;
810 http_send_content_type(ctypes
, ctlen
);
812 http_send_content_type("application/x-octetstream", lenof("application/x-octetstream"));
815 zval_ptr_dtor(&ctype
);
818 /* content disposition */
820 zval
*cd
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("contentDisposition")-1, 0 TSRMLS_CC
)));
821 if (Z_STRLEN_P(cd
)) {
822 http_send_header_ex("Content-Disposition", lenof("Content-Disposition"), Z_STRVAL_P(cd
), Z_STRLEN_P(cd
), 1, NULL
);
829 zval
*bsize
= http_zsep(IS_LONG
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("bufferSize")-1, 0 TSRMLS_CC
)));
830 zval
*delay
= http_zsep(IS_DOUBLE
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("throttleDelay")-1, 0 TSRMLS_CC
)));
831 HTTP_G
->send
.buffer_size
= Z_LVAL_P(bsize
);
832 HTTP_G
->send
.throttle_delay
= Z_DVAL_P(delay
);
833 zval_ptr_dtor(&bsize
);
834 zval_ptr_dtor(&delay
);
838 HTTP_G
->send
.deflate
.response
= i_zend_is_true(*zend_std_get_static_property(THIS_CE
, ZEND_STRS("gzip")-1, 0 TSRMLS_CC
));
841 switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE
, ZEND_STRS("mode")-1, 0 TSRMLS_CC
))) {
844 zval
*zdata
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("data")-1, 0 TSRMLS_CC
)));
845 RETVAL_SUCCESS(http_send_data(Z_STRVAL_P(zdata
), Z_STRLEN_P(zdata
)));
846 zval_ptr_dtor(&zdata
);
852 php_stream
*the_real_stream
;
853 zval
*the_stream
= http_zsep(IS_LONG
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("stream")-1, 0 TSRMLS_CC
)));
854 the_stream
->type
= IS_RESOURCE
;
855 php_stream_from_zval(the_real_stream
, &the_stream
);
856 RETVAL_SUCCESS(http_send_stream(the_real_stream
));
857 zval_ptr_dtor(&the_stream
);
863 zval
*file
= http_zsep(IS_STRING
, *(zend_std_get_static_property(THIS_CE
, ZEND_STRS("file")-1, 0 TSRMLS_CC
)));
864 RETVAL_SUCCESS(http_send_file(Z_STRVAL_P(file
)));
865 zval_ptr_dtor(&file
);
872 /* {{{ proto static void HttpResponse::capture()
873 Capture script output.
875 PHP_METHOD(HttpResponse
, capture
)
879 HTTP_CHECK_HEADERS_SENT(RETURN_FALSE
);
881 zend_update_static_property_long(THIS_CE
, ZEND_STRS("catch")-1, 1 TSRMLS_CC
);
883 php_end_ob_buffers(0 TSRMLS_CC
);
884 php_start_ob_buffer(NULL
, 0, 0 TSRMLS_CC
);
886 /* register shutdown function */
888 zval func
, retval
, arg
, *argp
[1];
893 ZVAL_STRINGL(&func
, "register_shutdown_function", lenof("register_shutdown_function"), 0);
896 add_next_index_stringl(&arg
, "HttpResponse", lenof("HttpResponse"), 1);
897 add_next_index_stringl(&arg
, "send", lenof("send"), 1);
899 call_user_function(EG(function_table
), NULL
, &func
, &retval
, 1, argp TSRMLS_CC
);
905 #endif /* ZEND_ENGINE_2 && !WONKY */
912 * vim600: noet sw=4 ts=4 fdm=marker
913 * vim<600: noet sw=4 ts=4