1 : /*
2 : +--------------------------------------------------------------------+
3 : | PECL :: http |
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 : +--------------------------------------------------------------------+
11 : */
12 :
13 : /* $Id: http_response_object.c,v 1.95 2007/02/22 11:04:37 mike Exp $ */
14 :
15 : #define HTTP_WANT_SAPI
16 : #define HTTP_WANT_MAGIC
17 : #include "php_http.h"
18 :
19 : /* broken static properties in PHP 5.0 */
20 : #if defined(ZEND_ENGINE_2) && !defined(WONKY)
21 :
22 : #include "php_ini.h"
23 :
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"
30 :
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))
35 :
36 : HTTP_BEGIN_ARGS(setHeader, 1)
37 : HTTP_ARG_VAL(name, 0)
38 : HTTP_ARG_VAL(value, 0)
39 : HTTP_ARG_VAL(replace, 0)
40 : HTTP_END_ARGS;
41 :
42 : HTTP_BEGIN_ARGS(getHeader, 0)
43 : HTTP_ARG_VAL(name, 0)
44 : HTTP_END_ARGS;
45 :
46 : HTTP_EMPTY_ARGS(getETag);
47 : HTTP_BEGIN_ARGS(setETag, 1)
48 : HTTP_ARG_VAL(etag, 0)
49 : HTTP_END_ARGS;
50 :
51 : HTTP_EMPTY_ARGS(getLastModified);
52 : HTTP_BEGIN_ARGS(setLastModified, 1)
53 : HTTP_ARG_VAL(timestamp, 0)
54 : HTTP_END_ARGS;
55 :
56 : HTTP_EMPTY_ARGS(getCache);
57 : HTTP_BEGIN_ARGS(setCache, 1)
58 : HTTP_ARG_VAL(cache, 0)
59 : HTTP_END_ARGS;
60 :
61 : HTTP_EMPTY_ARGS(getGzip);
62 : HTTP_BEGIN_ARGS(setGzip, 1)
63 : HTTP_ARG_VAL(gzip, 0)
64 : HTTP_END_ARGS;
65 :
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)
71 : HTTP_END_ARGS;
72 :
73 : HTTP_EMPTY_ARGS(getContentType);
74 : HTTP_BEGIN_ARGS(setContentType, 1)
75 : HTTP_ARG_VAL(content_type, 0)
76 : HTTP_END_ARGS;
77 :
78 : HTTP_BEGIN_ARGS(guessContentType, 1)
79 : HTTP_ARG_VAL(magic_file, 0)
80 : HTTP_ARG_VAL(magic_mode, 0)
81 : HTTP_END_ARGS;
82 :
83 : HTTP_EMPTY_ARGS(getContentDisposition);
84 : HTTP_BEGIN_ARGS(setContentDisposition, 1)
85 : HTTP_ARG_VAL(filename, 0)
86 : HTTP_ARG_VAL(send_inline, 0)
87 : HTTP_END_ARGS;
88 :
89 : HTTP_EMPTY_ARGS(getThrottleDelay);
90 : HTTP_BEGIN_ARGS(setThrottleDelay, 1)
91 : HTTP_ARG_VAL(seconds, 0)
92 : HTTP_END_ARGS;
93 :
94 : HTTP_EMPTY_ARGS(getBufferSize);
95 : HTTP_BEGIN_ARGS(setBufferSize, 1)
96 : HTTP_ARG_VAL(bytes, 0)
97 : HTTP_END_ARGS;
98 :
99 : HTTP_EMPTY_ARGS(getData);
100 : HTTP_BEGIN_ARGS(setData, 1)
101 : HTTP_ARG_VAL(data, 0)
102 : HTTP_END_ARGS;
103 :
104 : HTTP_EMPTY_ARGS(getStream);
105 : HTTP_BEGIN_ARGS(setStream, 1)
106 : HTTP_ARG_VAL(stream, 0)
107 : HTTP_END_ARGS;
108 :
109 : HTTP_EMPTY_ARGS(getFile);
110 : HTTP_BEGIN_ARGS(setFile, 1)
111 : HTTP_ARG_VAL(filepath, 0)
112 : HTTP_END_ARGS;
113 :
114 : HTTP_BEGIN_ARGS(send, 0)
115 : HTTP_ARG_VAL(clean_ob, 0)
116 : HTTP_END_ARGS;
117 :
118 : HTTP_EMPTY_ARGS(capture);
119 :
120 : HTTP_BEGIN_ARGS(redirect, 0)
121 : HTTP_ARG_VAL(url, 0)
122 : HTTP_ARG_VAL(params, 0)
123 : HTTP_ARG_VAL(session, 0)
124 : HTTP_ARG_VAL(permanent, 0)
125 : HTTP_END_ARGS;
126 :
127 : HTTP_BEGIN_ARGS(status, 1)
128 : HTTP_ARG_VAL(code, 0)
129 : HTTP_END_ARGS;
130 :
131 : HTTP_EMPTY_ARGS(getRequestHeaders);
132 : HTTP_EMPTY_ARGS(getRequestBody);
133 : HTTP_EMPTY_ARGS(getRequestBodyStream);
134 :
135 : #define THIS_CE http_response_object_ce
136 : zend_class_entry *http_response_object_ce;
137 : zend_function_entry http_response_object_fe[] = {
138 :
139 : HTTP_RESPONSE_ME(setHeader, ZEND_ACC_PUBLIC)
140 : HTTP_RESPONSE_ME(getHeader, ZEND_ACC_PUBLIC)
141 :
142 : HTTP_RESPONSE_ME(setETag, ZEND_ACC_PUBLIC)
143 : HTTP_RESPONSE_ME(getETag, ZEND_ACC_PUBLIC)
144 :
145 : HTTP_RESPONSE_ME(setLastModified, ZEND_ACC_PUBLIC)
146 : HTTP_RESPONSE_ME(getLastModified, ZEND_ACC_PUBLIC)
147 :
148 : HTTP_RESPONSE_ME(setContentDisposition, ZEND_ACC_PUBLIC)
149 : HTTP_RESPONSE_ME(getContentDisposition, ZEND_ACC_PUBLIC)
150 :
151 : HTTP_RESPONSE_ME(setContentType, ZEND_ACC_PUBLIC)
152 : HTTP_RESPONSE_ME(getContentType, ZEND_ACC_PUBLIC)
153 :
154 : HTTP_RESPONSE_ME(guessContentType, ZEND_ACC_PUBLIC)
155 :
156 : HTTP_RESPONSE_ME(setCache, ZEND_ACC_PUBLIC)
157 : HTTP_RESPONSE_ME(getCache, ZEND_ACC_PUBLIC)
158 :
159 : HTTP_RESPONSE_ME(setCacheControl, ZEND_ACC_PUBLIC)
160 : HTTP_RESPONSE_ME(getCacheControl, ZEND_ACC_PUBLIC)
161 :
162 : HTTP_RESPONSE_ME(setGzip, ZEND_ACC_PUBLIC)
163 : HTTP_RESPONSE_ME(getGzip, ZEND_ACC_PUBLIC)
164 :
165 : HTTP_RESPONSE_ME(setThrottleDelay, ZEND_ACC_PUBLIC)
166 : HTTP_RESPONSE_ME(getThrottleDelay, ZEND_ACC_PUBLIC)
167 :
168 : HTTP_RESPONSE_ME(setBufferSize, ZEND_ACC_PUBLIC)
169 : HTTP_RESPONSE_ME(getBufferSize, ZEND_ACC_PUBLIC)
170 :
171 : HTTP_RESPONSE_ME(setData, ZEND_ACC_PUBLIC)
172 : HTTP_RESPONSE_ME(getData, ZEND_ACC_PUBLIC)
173 :
174 : HTTP_RESPONSE_ME(setFile, ZEND_ACC_PUBLIC)
175 : HTTP_RESPONSE_ME(getFile, ZEND_ACC_PUBLIC)
176 :
177 : HTTP_RESPONSE_ME(setStream, ZEND_ACC_PUBLIC)
178 : HTTP_RESPONSE_ME(getStream, ZEND_ACC_PUBLIC)
179 :
180 : HTTP_RESPONSE_ME(send, ZEND_ACC_PUBLIC)
181 : HTTP_RESPONSE_ME(capture, ZEND_ACC_PUBLIC)
182 :
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)
188 :
189 : EMPTY_FUNCTION_ENTRY
190 : };
191 :
192 : PHP_MINIT_FUNCTION(http_response_object)
193 220 : {
194 220 : HTTP_REGISTER_CLASS(HttpResponse, http_response_object, NULL, 0);
195 :
196 220 : zend_declare_property_bool(THIS_CE, ZEND_STRS("sent")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
197 220 : zend_declare_property_bool(THIS_CE, ZEND_STRS("catch")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
198 220 : zend_declare_property_long(THIS_CE, ZEND_STRS("mode")-1, -1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
199 220 : zend_declare_property_long(THIS_CE, ZEND_STRS("stream")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
200 220 : zend_declare_property_null(THIS_CE, ZEND_STRS("file")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
201 220 : zend_declare_property_null(THIS_CE, ZEND_STRS("data")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
202 220 : zend_declare_property_bool(THIS_CE, ZEND_STRS("cache")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
203 220 : zend_declare_property_bool(THIS_CE, ZEND_STRS("gzip")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
204 220 : zend_declare_property_null(THIS_CE, ZEND_STRS("eTag")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
205 220 : zend_declare_property_long(THIS_CE, ZEND_STRS("lastModified")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
206 220 : zend_declare_property_null(THIS_CE, ZEND_STRS("cacheControl")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
207 220 : zend_declare_property_null(THIS_CE, ZEND_STRS("contentType")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
208 220 : zend_declare_property_null(THIS_CE, ZEND_STRS("contentDisposition")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
209 220 : zend_declare_property_long(THIS_CE, ZEND_STRS("bufferSize")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
210 220 : zend_declare_property_double(THIS_CE, ZEND_STRS("throttleDelay")-1, 0.0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
211 :
212 : #ifndef WONKY
213 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT")-1, HTTP_REDIRECT TSRMLS_CC);
214 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_PERM")-1, HTTP_REDIRECT_PERM TSRMLS_CC);
215 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_FOUND")-1, HTTP_REDIRECT_FOUND TSRMLS_CC);
216 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_POST")-1, HTTP_REDIRECT_POST TSRMLS_CC);
217 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_PROXY")-1, HTTP_REDIRECT_PROXY TSRMLS_CC);
218 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_TEMP")-1, HTTP_REDIRECT_TEMP TSRMLS_CC);
219 : #endif /* WONKY */
220 :
221 220 : return SUCCESS;
222 : }
223 :
224 : /* ### USERLAND ### */
225 :
226 : /* {{{ proto static bool HttpResponse::setHeader(string name[, mixed value[, bool replace = true]])
227 : Send an HTTP header. */
228 : PHP_METHOD(HttpResponse, setHeader)
229 0 : {
230 0 : zend_bool replace = 1;
231 : char *name;
232 0 : int name_len = 0;
233 0 : zval *value = NULL;
234 :
235 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/!b", &name, &name_len, &value, &replace)) {
236 0 : RETURN_FALSE;
237 : }
238 0 : if (SG(headers_sent)) {
239 0 : http_error(HE_WARNING, HTTP_E_HEADER, "Cannot add another header when headers have already been sent");
240 0 : RETURN_FALSE;
241 : }
242 0 : if (!name_len) {
243 0 : http_error(HE_WARNING, HTTP_E_HEADER, "Cannot send anonymous headers");
244 0 : RETURN_FALSE;
245 : }
246 0 : http_send_header_zval_ex(name, name_len, &value, replace);
247 0 : RETURN_TRUE;
248 : }
249 : /* }}} */
250 :
251 : /* {{{ proto static mixed HttpResponse::getHeader([string name])
252 : Get header(s) about to be sent. */
253 : PHP_METHOD(HttpResponse, getHeader)
254 0 : {
255 0 : char *name = NULL;
256 0 : int name_len = 0;
257 :
258 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len)) {
259 0 : RETURN_FALSE;
260 : }
261 :
262 0 : if (name && name_len) {
263 : zval **header;
264 : HashTable headers_ht;
265 :
266 0 : zend_hash_init(&headers_ht, sizeof(zval *), NULL, ZVAL_PTR_DTOR, 0);
267 0 : if ( (SUCCESS == http_get_response_headers(&headers_ht)) &&
268 : (SUCCESS == zend_hash_find(&headers_ht, name, name_len + 1, (void *) &header))) {
269 0 : RETVAL_ZVAL(*header, 1, 0);
270 : } else {
271 0 : RETVAL_NULL();
272 : }
273 0 : zend_hash_destroy(&headers_ht);
274 : } else {
275 0 : array_init(return_value);
276 0 : http_get_response_headers(Z_ARRVAL_P(return_value));
277 : }
278 : }
279 : /* }}} */
280 :
281 : /* {{{ proto static bool HttpResponse::setCache(bool cache)
282 : Whether it should be attempted to cache the entity. */
283 : PHP_METHOD(HttpResponse, setCache)
284 3 : {
285 3 : zend_bool do_cache = 0;
286 :
287 3 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) {
288 0 : RETURN_FALSE;
289 : }
290 :
291 3 : RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE, ZEND_STRS("cache")-1, do_cache TSRMLS_CC));
292 : }
293 : /* }}} */
294 :
295 : /* {{{ proto static bool HttpResponse::getCache()
296 : Get current caching setting. */
297 : PHP_METHOD(HttpResponse, getCache)
298 0 : {
299 0 : NO_ARGS;
300 :
301 0 : if (return_value_used) {
302 0 : zval *cache_p, *cache = convert_to_type_ex(IS_BOOL, *zend_std_get_static_property(THIS_CE, ZEND_STRS("cache")-1, 0 TSRMLS_CC), &cache_p);
303 :
304 0 : RETVAL_ZVAL(cache, 1, 0);
305 :
306 0 : if (cache_p) {
307 0 : zval_ptr_dtor(&cache_p);
308 : }
309 : }
310 0 : }
311 : /* }}}*/
312 :
313 : /* {{{ proto static bool HttpResponse::setGzip(bool gzip)
314 : Enable on-thy-fly gzipping of the sent entity. */
315 : PHP_METHOD(HttpResponse, setGzip)
316 3 : {
317 3 : zend_bool do_gzip = 0;
318 :
319 3 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) {
320 0 : RETURN_FALSE;
321 : }
322 :
323 3 : RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE, ZEND_STRS("gzip")-1, do_gzip TSRMLS_CC));
324 : }
325 : /* }}} */
326 :
327 : /* {{{ proto static bool HttpResponse::getGzip()
328 : Get current gzipping setting. */
329 : PHP_METHOD(HttpResponse, getGzip)
330 0 : {
331 0 : NO_ARGS;
332 :
333 0 : if (return_value_used) {
334 0 : zval *gzip_p, *gzip = convert_to_type_ex(IS_BOOL, *zend_std_get_static_property(THIS_CE, ZEND_STRS("gzip")-1, 0 TSRMLS_CC), &gzip_p);
335 :
336 0 : RETVAL_ZVAL(gzip, 1, 0);
337 :
338 0 : if (gzip_p) {
339 0 : zval_ptr_dtor(&gzip_p);
340 : }
341 : }
342 0 : }
343 : /* }}} */
344 :
345 : /* {{{ proto static bool HttpResponse::setCacheControl(string control[, int max_age = 0[, bool must_revalidate = true]])
346 : 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. */
347 : PHP_METHOD(HttpResponse, setCacheControl)
348 3 : {
349 : char *ccontrol, *cctl;
350 : int cc_len;
351 3 : long max_age = 0;
352 3 : zend_bool must_revalidate = 1;
353 :
354 3 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &ccontrol, &cc_len, &max_age, &must_revalidate)) {
355 0 : RETURN_FALSE;
356 : }
357 :
358 3 : if (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache")) {
359 0 : http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
360 0 : RETURN_FALSE;
361 : } else {
362 3 : size_t cctl_len = spprintf(&cctl, 0, "%s,%s max-age=%ld", ccontrol, must_revalidate?" must-revalidate,":"", max_age);
363 3 : RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("cacheControl")-1, cctl, cctl_len TSRMLS_CC));
364 3 : efree(cctl);
365 : }
366 : }
367 : /* }}} */
368 :
369 : /* {{{ proto static string HttpResponse::getCacheControl()
370 : Get current Cache-Control header setting. */
371 : PHP_METHOD(HttpResponse, getCacheControl)
372 0 : {
373 0 : NO_ARGS;
374 :
375 0 : if (return_value_used) {
376 0 : zval *ccontrol_p, *ccontrol = convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("cacheControl")-1, 0 TSRMLS_CC), &ccontrol_p);
377 :
378 0 : RETVAL_ZVAL(ccontrol, 1, 0);
379 :
380 0 : if (ccontrol_p) {
381 0 : zval_ptr_dtor(&ccontrol_p);
382 : }
383 : }
384 0 : }
385 : /* }}} */
386 :
387 : /* {{{ proto static bool HttpResponse::setContentType(string content_type)
388 : Set the content-type of the sent entity. */
389 : PHP_METHOD(HttpResponse, setContentType)
390 1 : {
391 : char *ctype;
392 : int ctype_len;
393 :
394 1 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) {
395 0 : RETURN_FALSE;
396 : }
397 :
398 1 : HTTP_CHECK_CONTENT_TYPE(ctype, RETURN_FALSE);
399 1 : RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("contentType")-1, ctype, ctype_len TSRMLS_CC));
400 : }
401 : /* }}} */
402 :
403 : /* {{{ proto static string HttpResponse::getContentType()
404 : Get current Content-Type header setting. */
405 : PHP_METHOD(HttpResponse, getContentType)
406 0 : {
407 0 : NO_ARGS;
408 :
409 0 : if (return_value_used) {
410 0 : zval *ctype_p, *ctype = convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("contentType")-1, 0 TSRMLS_CC), &ctype_p);
411 :
412 0 : RETVAL_ZVAL(ctype, 1, 0);
413 :
414 0 : if (ctype_p) {
415 0 : zval_ptr_dtor(&ctype_p);
416 : }
417 : }
418 0 : }
419 : /* }}} */
420 :
421 : /* {{{ proto static string HttpResponse::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME])
422 : Attempts to guess the content type of supplied payload through libmagic. */
423 : PHP_METHOD(HttpResponse, guessContentType)
424 0 : {
425 : #ifdef HTTP_HAVE_MAGIC
426 : char *magic_file, *ct = NULL;
427 : int magic_file_len;
428 : long magic_mode = MAGIC_MIME;
429 :
430 : RETVAL_FALSE;
431 : SET_EH_THROW_HTTP();
432 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) {
433 : switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 TSRMLS_CC))) {
434 : case SEND_DATA:
435 : {
436 : zval *data = *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 TSRMLS_CC);
437 : ct = http_guess_content_type(magic_file, magic_mode, Z_STRVAL_P(data), Z_STRLEN_P(data), SEND_DATA);
438 : break;
439 : }
440 :
441 : case SEND_RSRC:
442 : {
443 : php_stream *s;
444 : zval *z = *zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 TSRMLS_CC);
445 : z->type = IS_RESOURCE;
446 : php_stream_from_zval(s, &z);
447 : ct = http_guess_content_type(magic_file, magic_mode, s, 0, SEND_RSRC);
448 : break;
449 : }
450 :
451 : default:
452 : 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);
453 : break;
454 : }
455 : if (ct) {
456 : zend_update_static_property_string(THIS_CE, ZEND_STRS("contentType")-1, ct TSRMLS_CC);
457 : RETVAL_STRING(ct, 0);
458 : }
459 : }
460 : SET_EH_NORMAL();
461 : #else
462 0 : http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
463 0 : RETURN_FALSE;
464 : #endif
465 : }
466 : /* }}} */
467 :
468 : /* {{{ proto static bool HttpResponse::setContentDisposition(string filename[, bool inline = false])
469 : Set the Content-Disposition. */
470 : PHP_METHOD(HttpResponse, setContentDisposition)
471 1 : {
472 : char *file, *cd;
473 : int file_len;
474 : size_t cd_len;
475 1 : zend_bool send_inline = 0;
476 :
477 1 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &send_inline)) {
478 0 : RETURN_FALSE;
479 : }
480 :
481 1 : cd_len = spprintf(&cd, 0, "%s; filename=\"%s\"", send_inline ? "inline" : "attachment", file);
482 1 : RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("contentDisposition")-1, cd, cd_len TSRMLS_CC));
483 1 : efree(cd);
484 : }
485 : /* }}} */
486 :
487 : /* {{{ proto static string HttpResponse::getContentDisposition()
488 : Get current Content-Disposition setting. */
489 : PHP_METHOD(HttpResponse, getContentDisposition)
490 0 : {
491 0 : NO_ARGS;
492 :
493 0 : if (return_value_used) {
494 0 : zval *cd_p, *cd = convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("contentDisposition")-1, 0 TSRMLS_CC), &cd_p);
495 :
496 0 : RETVAL_ZVAL(cd, 1, 0);
497 :
498 0 : if (cd_p) {
499 0 : zval_ptr_dtor(&cd_p);
500 : }
501 : }
502 0 : }
503 : /* }}} */
504 :
505 : /* {{{ proto static bool HttpResponse::setETag(string etag)
506 : Set a custom ETag. Use this only if you know what you're doing. */
507 : PHP_METHOD(HttpResponse, setETag)
508 0 : {
509 : char *etag;
510 : int etag_len;
511 :
512 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) {
513 0 : RETURN_FALSE;
514 : }
515 :
516 0 : RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("eTag")-1, etag, etag_len TSRMLS_CC));
517 : }
518 : /* }}} */
519 :
520 : /* {{{ proto static string HttpResponse::getETag()
521 : Get calculated or previously set custom ETag. */
522 : PHP_METHOD(HttpResponse, getETag)
523 0 : {
524 0 : NO_ARGS;
525 :
526 0 : if (return_value_used) {
527 0 : zval *etag_p, *etag = convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 TSRMLS_CC), &etag_p);
528 :
529 0 : RETVAL_ZVAL(etag, 1, 0);
530 :
531 0 : if (etag_p) {
532 0 : zval_ptr_dtor(&etag_p);
533 : }
534 : }
535 0 : }
536 : /* }}} */
537 :
538 : /* {{{ proto static bool HttpResponse::setLastModified(int timestamp)
539 : Set a custom Last-Modified date. */
540 : PHP_METHOD(HttpResponse, setLastModified)
541 0 : {
542 : long lm;
543 :
544 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &lm)) {
545 0 : RETURN_FALSE;
546 : }
547 :
548 0 : RETURN_SUCCESS(zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, lm TSRMLS_CC));
549 : }
550 : /* }}} */
551 :
552 : /* {{{ proto static int HttpResponse::getLastModified()
553 : Get calculated or previously set custom Last-Modified date. */
554 : PHP_METHOD(HttpResponse, getLastModified)
555 0 : {
556 0 : NO_ARGS;
557 :
558 0 : if (return_value_used) {
559 0 : zval *lm_p, *lm = convert_to_type_ex(IS_LONG, *zend_std_get_static_property(THIS_CE, ZEND_STRS("lastModified")-1, 0 TSRMLS_CC), &lm_p);
560 :
561 0 : RETVAL_ZVAL(lm, 1, 0);
562 :
563 0 : if (lm_p) {
564 0 : zval_ptr_dtor(&lm_p);
565 : }
566 : }
567 0 : }
568 : /* }}} */
569 :
570 : /* {{{ proto static bool HttpResponse::setThrottleDelay(double seconds)
571 : Sets the throttle delay for use with HttpResponse::setBufferSize(). */
572 : PHP_METHOD(HttpResponse, setThrottleDelay)
573 0 : {
574 : double seconds;
575 :
576 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &seconds)) {
577 0 : RETURN_FALSE;
578 : }
579 0 : RETURN_SUCCESS(zend_update_static_property_double(THIS_CE, ZEND_STRS("throttleDelay")-1, seconds TSRMLS_CC));
580 : }
581 : /* }}} */
582 :
583 : /* {{{ proto static double HttpResponse::getThrottleDelay()
584 : Get the current throttle delay. */
585 : PHP_METHOD(HttpResponse, getThrottleDelay)
586 0 : {
587 0 : NO_ARGS;
588 :
589 0 : if (return_value_used) {
590 0 : zval *delay_p, *delay = convert_to_type_ex(IS_DOUBLE, *zend_std_get_static_property(THIS_CE, ZEND_STRS("throttleDelay")-1, 0 TSRMLS_CC), &delay_p);
591 :
592 0 : RETVAL_ZVAL(delay, 1, 0);
593 :
594 0 : if (delay_p) {
595 0 : zval_ptr_dtor(&delay_p);
596 : }
597 : }
598 0 : }
599 : /* }}} */
600 :
601 : /* {{{ proto static bool HttpResponse::setBufferSize(int bytes)
602 : Sets the send buffer size for use with HttpResponse::setThrottleDelay(). */
603 : PHP_METHOD(HttpResponse, setBufferSize)
604 0 : {
605 : long bytes;
606 :
607 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bytes)) {
608 0 : RETURN_FALSE;
609 : }
610 0 : RETURN_SUCCESS(zend_update_static_property_long(THIS_CE, ZEND_STRS("bufferSize")-1, bytes TSRMLS_CC));
611 : }
612 : /* }}} */
613 :
614 : /* {{{ proto static int HttpResponse::getBufferSize()
615 : Get current buffer size. */
616 : PHP_METHOD(HttpResponse, getBufferSize)
617 0 : {
618 0 : NO_ARGS;
619 :
620 0 : if (return_value_used) {
621 0 : zval *size_p, *size = convert_to_type_ex(IS_LONG, *zend_std_get_static_property(THIS_CE, ZEND_STRS("bufferSize")-1, 0 TSRMLS_CC), &size_p);
622 :
623 0 : RETVAL_ZVAL(size, 1, 0);
624 :
625 0 : if (size_p) {
626 0 : zval_ptr_dtor(&size_p);
627 : }
628 : }
629 0 : }
630 : /* }}} */
631 :
632 : /* {{{ proto static bool HttpResponse::setData(mixed data)
633 : Set the data to be sent. */
634 : PHP_METHOD(HttpResponse, setData)
635 2 : {
636 : char *etag;
637 : zval *the_data;
638 :
639 2 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &the_data)) {
640 0 : RETURN_FALSE;
641 : }
642 2 : if (Z_TYPE_P(the_data) != IS_STRING) {
643 0 : convert_to_string_ex(&the_data);
644 : }
645 :
646 2 : if ( (SUCCESS != zend_update_static_property(THIS_CE, ZEND_STRS("data")-1, the_data TSRMLS_CC)) ||
647 : (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, SEND_DATA TSRMLS_CC))) {
648 0 : RETURN_FALSE;
649 : }
650 :
651 2 : zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_data, SEND_DATA) TSRMLS_CC);
652 2 : if ((etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA))) {
653 2 : zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
654 2 : efree(etag);
655 : }
656 :
657 2 : RETURN_TRUE;
658 : }
659 : /* }}} */
660 :
661 : /* {{{ proto static string HttpResponse::getData()
662 : Get the previously set data to be sent. */
663 : PHP_METHOD(HttpResponse, getData)
664 0 : {
665 0 : NO_ARGS;
666 :
667 0 : if (return_value_used) {
668 0 : zval *the_data = *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 TSRMLS_CC);
669 :
670 0 : RETURN_ZVAL(the_data, 1, 0);
671 : }
672 : }
673 : /* }}} */
674 :
675 : /* {{{ proto static bool HttpResponse::setStream(resource stream)
676 : Set the resource to be sent. */
677 : PHP_METHOD(HttpResponse, setStream)
678 0 : {
679 : char *etag;
680 : zval *the_stream;
681 : php_stream *the_real_stream;
682 : php_stream_statbuf ssb;
683 :
684 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
685 0 : RETURN_FALSE;
686 : }
687 :
688 0 : php_stream_from_zval(the_real_stream, &the_stream);
689 0 : if (php_stream_stat(the_real_stream, &ssb)) {
690 0 : RETURN_FALSE;
691 : }
692 :
693 0 : if ( (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("stream")-1, Z_LVAL_P(the_stream) TSRMLS_CC)) ||
694 : (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, SEND_RSRC TSRMLS_CC))) {
695 0 : RETURN_FALSE;
696 : }
697 0 : zend_list_addref(Z_LVAL_P(the_stream));
698 :
699 0 : zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_real_stream, SEND_RSRC) TSRMLS_CC);
700 0 : if ((etag = http_etag(the_real_stream, 0, SEND_RSRC))) {
701 0 : zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
702 0 : efree(etag);
703 : }
704 :
705 0 : RETURN_TRUE;
706 : }
707 : /* }}} */
708 :
709 : /* {{{ proto static resource HttpResponse::getStream()
710 : Get the previously set resource to be sent. */
711 : PHP_METHOD(HttpResponse, getStream)
712 0 : {
713 0 : NO_ARGS;
714 :
715 0 : if (return_value_used) {
716 : zval *stream_p;
717 :
718 0 : RETVAL_RESOURCE(Z_LVAL_P(convert_to_type_ex(IS_LONG, *zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 TSRMLS_CC), &stream_p)));
719 :
720 0 : if (stream_p) {
721 0 : zval_ptr_dtor(&stream_p);
722 : }
723 : }
724 0 : }
725 : /* }}} */
726 :
727 : /* {{{ proto static bool HttpResponse::setFile(string file)
728 : Set the file to be sent. */
729 : PHP_METHOD(HttpResponse, setFile)
730 3 : {
731 : char *the_file, *etag;
732 : int file_len;
733 : php_stream_statbuf ssb;
734 :
735 3 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &the_file, &file_len)) {
736 0 : RETURN_FALSE;
737 : }
738 :
739 3 : if (php_stream_stat_path(the_file, &ssb)) {
740 1 : RETURN_FALSE;
741 : }
742 :
743 2 : if ( (SUCCESS != zend_update_static_property_stringl(THIS_CE, ZEND_STRS("file")-1, the_file, file_len TSRMLS_CC)) ||
744 : (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, -1 TSRMLS_CC))) {
745 0 : RETURN_FALSE;
746 : }
747 :
748 2 : zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_file, -1) TSRMLS_CC);
749 2 : if ((etag = http_etag(the_file, 0, -1))) {
750 2 : zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
751 2 : efree(etag);
752 : }
753 :
754 2 : RETURN_TRUE;
755 : }
756 : /* }}} */
757 :
758 : /* {{{ proto static string HttpResponse::getFile()
759 : Get the previously set file to be sent. */
760 : PHP_METHOD(HttpResponse, getFile)
761 0 : {
762 0 : NO_ARGS;
763 :
764 0 : if (return_value_used) {
765 0 : zval *the_file_p, *the_file = convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 TSRMLS_CC), &the_file_p);
766 :
767 0 : RETVAL_ZVAL(the_file, 1, 0);
768 :
769 0 : if (the_file_p) {
770 0 : zval_ptr_dtor(&the_file_p);
771 : }
772 : }
773 0 : }
774 : /* }}} */
775 :
776 : /* {{{ proto static bool HttpResponse::send([bool clean_ob = true])
777 : Finally send the entity. */
778 : PHP_METHOD(HttpResponse, send)
779 5 : {
780 : zval *sent;
781 5 : zend_bool clean_ob = 1;
782 :
783 5 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean_ob)) {
784 0 : RETURN_FALSE;
785 : }
786 :
787 5 : HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
788 :
789 5 : sent = *zend_std_get_static_property(THIS_CE, ZEND_STRS("sent")-1, 0 TSRMLS_CC);
790 5 : if (Z_LVAL_P(sent)) {
791 0 : http_error(HE_WARNING, HTTP_E_RESPONSE, "Cannot send HttpResponse, response has already been sent");
792 0 : RETURN_FALSE;
793 : } else {
794 5 : Z_LVAL_P(sent) = 1;
795 : }
796 :
797 : /* capture mode */
798 5 : if (zval_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("catch")-1, 0 TSRMLS_CC))) {
799 : zval *etag_p, *the_data;
800 :
801 0 : MAKE_STD_ZVAL(the_data);
802 0 : php_ob_get_buffer(the_data TSRMLS_CC);
803 0 : zend_update_static_property(THIS_CE, ZEND_STRS("data")-1, the_data TSRMLS_CC);
804 0 : ZVAL_LONG(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 TSRMLS_CC), SEND_DATA);
805 :
806 0 : if (!Z_STRLEN_P(convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 TSRMLS_CC), &etag_p))) {
807 0 : char *etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA);
808 0 : if (etag) {
809 0 : zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
810 0 : efree(etag);
811 : }
812 : }
813 0 : zval_ptr_dtor(&the_data);
814 :
815 0 : if (etag_p) {
816 0 : zval_ptr_dtor(&etag_p);
817 : }
818 :
819 0 : clean_ob = 1;
820 : }
821 :
822 5 : if (clean_ob) {
823 : /* interrupt on-the-fly etag generation */
824 5 : HTTP_G->etag.started = 0;
825 : /* discard previous output buffers */
826 5 : php_end_ob_buffers(0 TSRMLS_CC);
827 : }
828 :
829 : /* caching */
830 5 : if (zval_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("cache")-1, 0 TSRMLS_CC))) {
831 : zval *cctl, *cctl_p, *etag, *etag_p, *lmod, *lmod_p;
832 :
833 3 : etag = convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 TSRMLS_CC), &etag_p);
834 3 : lmod = convert_to_type_ex(IS_LONG, *zend_std_get_static_property(THIS_CE, ZEND_STRS("lastModified")-1, 0 TSRMLS_CC), &lmod_p);
835 3 : cctl = convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("cacheControl")-1, 0 TSRMLS_CC), &cctl_p);
836 :
837 3 : if (Z_LVAL_P(lmod) || Z_STRLEN_P(etag)) {
838 3 : if (Z_STRLEN_P(cctl)) {
839 3 : http_send_cache_control(Z_STRVAL_P(cctl), Z_STRLEN_P(cctl));
840 : } else {
841 0 : http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL));
842 : }
843 3 : if (Z_STRLEN_P(etag)) {
844 3 : http_send_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag));
845 : }
846 3 : if (Z_LVAL_P(lmod)) {
847 3 : http_send_last_modified(Z_LVAL_P(lmod));
848 : }
849 : }
850 :
851 3 : if (etag_p) zval_ptr_dtor(&etag_p);
852 3 : if (lmod_p) zval_ptr_dtor(&lmod_p);
853 3 : if (cctl_p) zval_ptr_dtor(&cctl_p);
854 : }
855 :
856 : /* content type */
857 : {
858 5 : zval *ctype_p, *ctype = convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("contentType")-1, 0 TSRMLS_CC), &ctype_p);
859 5 : if (Z_STRLEN_P(ctype)) {
860 1 : http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
861 : } else {
862 4 : char *ctypes = INI_STR("default_mimetype");
863 4 : size_t ctlen = ctypes ? strlen(ctypes) : 0;
864 :
865 4 : if (ctlen) {
866 4 : http_send_content_type(ctypes, ctlen);
867 : } else {
868 0 : http_send_content_type("application/x-octetstream", lenof("application/x-octetstream"));
869 : }
870 : }
871 5 : if (ctype_p) {
872 0 : zval_ptr_dtor(&ctype_p);
873 : }
874 : }
875 :
876 : /* content disposition */
877 : {
878 5 : zval *cd_p, *cd = convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("contentDisposition")-1, 0 TSRMLS_CC), &cd_p);
879 5 : if (Z_STRLEN_P(cd)) {
880 1 : http_send_header_ex("Content-Disposition", lenof("Content-Disposition"), Z_STRVAL_P(cd), Z_STRLEN_P(cd), 1, NULL);
881 : }
882 5 : if (cd_p) {
883 0 : zval_ptr_dtor(&cd_p);
884 : }
885 : }
886 :
887 : /* throttling */
888 : {
889 5 : zval *bsize_p, *bsize = convert_to_type_ex(IS_LONG, *zend_std_get_static_property(THIS_CE, ZEND_STRS("bufferSize")-1, 0 TSRMLS_CC), &bsize_p);
890 5 : zval *delay_p, *delay = convert_to_type_ex(IS_DOUBLE, *zend_std_get_static_property(THIS_CE, ZEND_STRS("throttleDelay")-1, 0 TSRMLS_CC), &delay_p);
891 5 : HTTP_G->send.buffer_size = Z_LVAL_P(bsize);
892 5 : HTTP_G->send.throttle_delay = Z_DVAL_P(delay);
893 5 : if (bsize_p) zval_ptr_dtor(&bsize_p);
894 5 : if (delay_p) zval_ptr_dtor(&delay_p);
895 : }
896 :
897 : /* gzip */
898 5 : HTTP_G->send.deflate.response = zval_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("gzip")-1, 0 TSRMLS_CC));
899 :
900 : /* send */
901 5 : switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 TSRMLS_CC))) {
902 : case SEND_DATA:
903 : {
904 2 : zval *zdata_p, *zdata = convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 TSRMLS_CC), &zdata_p);
905 2 : RETVAL_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)));
906 1 : if (zdata_p) zval_ptr_dtor(&zdata_p);
907 1 : return;
908 : }
909 :
910 : case SEND_RSRC:
911 : {
912 : php_stream *the_real_stream;
913 0 : zval *the_stream_p, *the_stream = convert_to_type_ex(IS_LONG, *zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 TSRMLS_CC), &the_stream_p);
914 0 : the_stream->type = IS_RESOURCE;
915 0 : php_stream_from_zval(the_real_stream, &the_stream);
916 0 : RETVAL_SUCCESS(http_send_stream(the_real_stream));
917 0 : if (the_stream_p) zval_ptr_dtor(&the_stream_p);
918 0 : return;
919 : }
920 :
921 : default:
922 : {
923 : zval *file_p;
924 3 : RETVAL_SUCCESS(http_send_file(Z_STRVAL_P(convert_to_type_ex(IS_STRING, *zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 TSRMLS_CC), &file_p))));
925 2 : if (file_p) zval_ptr_dtor(&file_p);
926 2 : return;
927 : }
928 : }
929 : }
930 : /* }}} */
931 :
932 : /* {{{ proto static void HttpResponse::capture()
933 : Capture script output.
934 : */
935 : PHP_METHOD(HttpResponse, capture)
936 0 : {
937 0 : NO_ARGS;
938 :
939 0 : HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
940 :
941 0 : zend_update_static_property_long(THIS_CE, ZEND_STRS("catch")-1, 1 TSRMLS_CC);
942 :
943 0 : php_end_ob_buffers(0 TSRMLS_CC);
944 0 : php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC);
945 :
946 : /* register shutdown function */
947 : {
948 : zval func, retval, arg, *argp[1];
949 :
950 0 : INIT_PZVAL(&arg);
951 0 : INIT_PZVAL(&func);
952 0 : INIT_PZVAL(&retval);
953 0 : ZVAL_STRINGL(&func, "register_shutdown_function", lenof("register_shutdown_function"), 0);
954 :
955 0 : array_init(&arg);
956 0 : add_next_index_stringl(&arg, "HttpResponse", lenof("HttpResponse"), 1);
957 0 : add_next_index_stringl(&arg, "send", lenof("send"), 1);
958 0 : argp[0] = &arg;
959 0 : call_user_function(EG(function_table), NULL, &func, &retval, 1, argp TSRMLS_CC);
960 0 : zval_dtor(&arg);
961 : }
962 : }
963 : /* }}} */
964 :
965 : #endif /* ZEND_ENGINE_2 && !WONKY */
966 :
967 : /*
968 : * Local variables:
969 : * tab-width: 4
970 : * c-basic-offset: 4
971 : * End:
972 : * vim600: noet sw=4 ts=4 fdm=marker
973 : * vim<600: noet sw=4 ts=4
974 : */
975 :
|