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-2014, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
13 #include "php_http_api.h"
14 #include "php_variables.h"
16 PHP_RINIT_FUNCTION(http_env
)
18 /* populate form data on non-POST requests */
19 if (SG(request_info
).request_method
&& strcasecmp(SG(request_info
).request_method
, "POST") && SG(request_info
).content_type
&& *SG(request_info
).content_type
) {
20 uint ct_len
= strlen(SG(request_info
).content_type
);
21 char *ct_str
= estrndup(SG(request_info
).content_type
, ct_len
);
22 php_http_params_opts_t opts
;
25 php_http_params_opts_default_get(&opts
);
26 opts
.input
.str
= ct_str
;
27 opts
.input
.len
= ct_len
;
29 SG(request_info
).content_type_dup
= ct_str
;
31 ZEND_INIT_SYMTABLE(¶ms
);
32 if (php_http_params_parse(¶ms
, &opts TSRMLS_CC
)) {
37 if (HASH_KEY_IS_STRING
== zend_hash_get_current_key_ex(¶ms
, &key_str
, &key_len
, &key_num
, 0, NULL
)) {
38 sapi_post_entry
*post_entry
= NULL
;
40 if (SUCCESS
== zend_hash_find(&SG(known_post_content_types
), key_str
, key_len
, (void *) &post_entry
)) {
41 zval
*files
= PG(http_globals
)[TRACK_VARS_FILES
];
44 SG(request_info
).post_entry
= post_entry
;
46 if (post_entry
->post_reader
) {
47 post_entry
->post_reader(TSRMLS_C
);
51 if (sapi_module
.default_post_reader
) {
52 sapi_module
.default_post_reader(TSRMLS_C
);
55 sapi_handle_post(PG(http_globals
)[TRACK_VARS_POST
] TSRMLS_CC
);
58 * the rfc1867 handler is an awkward buddy
60 if (files
!= PG(http_globals
)[TRACK_VARS_FILES
] && PG(http_globals
)[TRACK_VARS_FILES
]) {
61 Z_ADDREF_P(PG(http_globals
)[TRACK_VARS_FILES
]);
62 zend_hash_update(&EG(symbol_table
), "_FILES", sizeof("_FILES"), &PG(http_globals
)[TRACK_VARS_FILES
], sizeof(zval
*), NULL
);
64 zval_ptr_dtor(&files
);
69 zend_hash_destroy(¶ms
);
73 PTR_SET(SG(request_info
).content_type_dup
, NULL
);
78 PHP_RSHUTDOWN_FUNCTION(http_env
)
80 if (PHP_HTTP_G
->env
.request
.headers
) {
81 zend_hash_destroy(PHP_HTTP_G
->env
.request
.headers
);
82 FREE_HASHTABLE(PHP_HTTP_G
->env
.request
.headers
);
83 PHP_HTTP_G
->env
.request
.headers
= NULL
;
85 if (PHP_HTTP_G
->env
.request
.body
) {
86 php_http_message_body_free(&PHP_HTTP_G
->env
.request
.body
);
89 if (PHP_HTTP_G
->env
.server_var
) {
90 zval_ptr_dtor(&PHP_HTTP_G
->env
.server_var
);
91 PHP_HTTP_G
->env
.server_var
= NULL
;
97 void php_http_env_get_request_headers(HashTable
*headers TSRMLS_DC
)
99 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
100 zval
**hsv
, **header
;
103 if (!PHP_HTTP_G
->env
.request
.headers
) {
104 ALLOC_HASHTABLE(PHP_HTTP_G
->env
.request
.headers
);
105 zend_hash_init(PHP_HTTP_G
->env
.request
.headers
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
107 zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC
);
109 if (SUCCESS
== zend_hash_find(&EG(symbol_table
), "_SERVER", sizeof("_SERVER"), (void *) &hsv
) && Z_TYPE_PP(hsv
) == IS_ARRAY
) {
110 FOREACH_KEY(pos
, *hsv
, key
) {
111 if (key
.type
== HASH_KEY_IS_STRING
&& key
.len
> 6 && *key
.str
== 'H' && !strncmp(key
.str
, "HTTP_", 5)) {
113 key
.str
= php_http_pretty_key(estrndup(key
.str
+ 5, key
.len
- 1), key
.len
- 1, 1, 1);
115 zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv
), (void *) &header
, &pos
);
117 zend_symtable_update(PHP_HTTP_G
->env
.request
.headers
, key
.str
, key
.len
, (void *) header
, sizeof(zval
*), NULL
);
120 } else if (key
.type
== HASH_KEY_IS_STRING
&& key
.len
> 9 && *key
.str
== 'C' && !strncmp(key
.str
, "CONTENT_", 8)) {
121 key
.str
= php_http_pretty_key(estrndup(key
.str
, key
.len
- 1), key
.len
- 1, 1, 1);
123 zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv
), (void *) &header
, &pos
);
125 zend_symtable_update(PHP_HTTP_G
->env
.request
.headers
, key
.str
, key
.len
, (void *) header
, sizeof(zval
*), NULL
);
134 zend_hash_copy(headers
, PHP_HTTP_G
->env
.request
.headers
, (copy_ctor_func_t
) zval_add_ref
, NULL
, sizeof(zval
*));
138 char *php_http_env_get_request_header(const char *name_str
, size_t name_len
, size_t *len
, php_http_message_t
*request TSRMLS_DC
)
140 HashTable
*request_headers
;
141 zval
**zvalue
= NULL
;
142 char *val
= NULL
, *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
145 request_headers
= &request
->hdrs
;
147 php_http_env_get_request_headers(NULL TSRMLS_CC
);
148 request_headers
= PHP_HTTP_G
->env
.request
.headers
;
151 if (SUCCESS
== zend_symtable_find(request_headers
, key
, name_len
+ 1, (void *) &zvalue
)) {
152 zval
*zcopy
= php_http_ztyp(IS_STRING
, *zvalue
);
154 val
= estrndup(Z_STRVAL_P(zcopy
), Z_STRLEN_P(zcopy
));
156 *len
= Z_STRLEN_P(zcopy
);
158 zval_ptr_dtor(&zcopy
);
166 int php_http_env_got_request_header(const char *name_str
, size_t name_len
, php_http_message_t
*request TSRMLS_DC
)
168 HashTable
*request_headers
;
169 char *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
173 request_headers
= &request
->hdrs
;
175 php_http_env_get_request_headers(NULL TSRMLS_CC
);
176 request_headers
= PHP_HTTP_G
->env
.request
.headers
;
178 got
= zend_symtable_exists(request_headers
, key
, name_len
+ 1);
184 zval
*php_http_env_get_superglobal(const char *key
, size_t key_len TSRMLS_DC
)
188 zend_is_auto_global(key
, key_len TSRMLS_CC
);
190 if ((SUCCESS
!= zend_hash_find(&EG(symbol_table
), key
, key_len
+ 1, (void *) &hsv
)) || (Z_TYPE_PP(hsv
) != IS_ARRAY
)) {
197 zval
*php_http_env_get_server_var(const char *key
, size_t key_len
, zend_bool check TSRMLS_DC
)
202 /* if available, this is a lot faster than accessing $_SERVER */
203 if (sapi_module
.getenv
) {
204 if ((!(env
= sapi_module
.getenv((char *) key
, key_len TSRMLS_CC
))) || (check
&& !*env
)) {
207 if (PHP_HTTP_G
->env
.server_var
) {
208 zval_ptr_dtor(&PHP_HTTP_G
->env
.server_var
);
210 MAKE_STD_ZVAL(PHP_HTTP_G
->env
.server_var
);
211 ZVAL_STRING(PHP_HTTP_G
->env
.server_var
, env
, 1);
212 return PHP_HTTP_G
->env
.server_var
;
215 if (!(hsv
= php_http_env_get_superglobal(ZEND_STRL("_SERVER") TSRMLS_CC
))) {
218 if ((SUCCESS
!= zend_symtable_find(Z_ARRVAL_P(hsv
), key
, key_len
+ 1, (void *) &var
))) {
221 if (check
&& !((Z_TYPE_PP(var
) == IS_STRING
) && Z_STRVAL_PP(var
) && Z_STRLEN_PP(var
))) {
227 php_http_message_body_t
*php_http_env_get_request_body(TSRMLS_D
)
229 if (!PHP_HTTP_G
->env
.request
.body
) {
230 php_stream
*s
= php_stream_temp_new();
231 #if PHP_VERSION_ID >= 50600
232 php_stream
*input
= php_stream_open_wrapper("php://input", "r", 0, NULL
);
234 /* php://input does not support stat */
235 php_stream_copy_to_stream_ex(input
, s
, -1, NULL
);
236 php_stream_close(input
);
238 if (SG(request_info
).post_data
|| SG(request_info
).raw_post_data
) {
239 /* php://input does not support seek() in PHP <= 5.5 */
240 if (SG(request_info
).raw_post_data
) {
241 php_stream_write(s
, SG(request_info
).raw_post_data
, SG(request_info
).raw_post_data_length
);
243 php_stream_write(s
, SG(request_info
).post_data
, SG(request_info
).post_data_length
);
245 } else if (sapi_module
.read_post
&& !SG(read_post_bytes
)) {
246 char *buf
= emalloc(4096);
249 while (0 < (len
= sapi_module
.read_post(buf
, 4096 TSRMLS_CC
))) {
250 SG(read_post_bytes
) += len
;
251 php_stream_write(s
, buf
, len
);
260 php_stream_rewind(s
);
261 PHP_HTTP_G
->env
.request
.body
= php_http_message_body_init(NULL
, s TSRMLS_CC
);
264 return PHP_HTTP_G
->env
.request
.body
;
267 const char *php_http_env_get_request_method(php_http_message_t
*request TSRMLS_DC
)
271 if (PHP_HTTP_MESSAGE_TYPE(REQUEST
, request
)) {
272 m
= request
->http
.info
.request
.method
;
274 m
= SG(request_info
).request_method
;
277 return m
? m
: "GET";
280 php_http_range_status_t
php_http_env_get_request_ranges(HashTable
*ranges
, size_t length
, php_http_message_t
*request TSRMLS_DC
)
284 long begin
= -1, end
= -1, *ptr
;
286 if (!(range
= php_http_env_get_request_header(ZEND_STRL("Range"), NULL
, request TSRMLS_CC
))) {
287 return PHP_HTTP_RANGE_NO
;
289 if (strncmp(range
, "bytes=", lenof("bytes="))) {
291 return PHP_HTTP_RANGE_NO
;
294 rp
= range
+ lenof("bytes=");
298 switch (c
= *(rp
++)) {
300 /* allow 000... - shall we? */
306 case '1': case '2': case '3':
307 case '4': case '5': case '6':
308 case '7': case '8': case '9':
310 * If the value of the pointer is already set (non-negative)
311 * then multiply its value by ten and add the current value,
312 * else initialise the pointers value with the current value
314 * This let us recognize empty fields when validating the
315 * ranges, i.e. a "-10" for begin and "12345" for the end
316 * was the following range request: "Range: bytes=0-12345";
317 * While a "-1" for begin and "12345" for the end would
318 * have been: "Range: bytes=-12345".
339 /* validate ranges */
347 return PHP_HTTP_RANGE_NO
;
355 if (length
<= (size_t) end
) {
366 if (end
== -1 || end
== -10) {
368 return PHP_HTTP_RANGE_ERR
;
370 begin
= length
- end
;
376 if (length
<= (size_t) begin
) {
378 return PHP_HTTP_RANGE_ERR
;
384 return PHP_HTTP_RANGE_ERR
;
393 if (length
<= (size_t) end
) {
395 } else if (end
< begin
) {
397 return PHP_HTTP_RANGE_ERR
;
405 MAKE_STD_ZVAL(zentry
);
407 add_index_long(zentry
, 0, begin
);
408 add_index_long(zentry
, 1, end
);
409 zend_hash_next_index_insert(ranges
, &zentry
, sizeof(zval
*), NULL
);
419 return PHP_HTTP_RANGE_NO
;
424 return PHP_HTTP_RANGE_OK
;
427 static void grab_headers(void *data
, void *arg TSRMLS_DC
)
429 php_http_buffer_appendl(PHP_HTTP_BUFFER(arg
), ((sapi_header_struct
*)data
)->header
);
430 php_http_buffer_appends(PHP_HTTP_BUFFER(arg
), PHP_HTTP_CRLF
);
433 STATUS
php_http_env_get_response_headers(HashTable
*headers_ht TSRMLS_DC
)
436 php_http_buffer_t headers
;
438 php_http_buffer_init(&headers
);
439 zend_llist_apply_with_argument(&SG(sapi_headers
).headers
, grab_headers
, &headers TSRMLS_CC
);
440 php_http_buffer_fix(&headers
);
442 status
= php_http_header_parse(headers
.data
, headers
.used
, headers_ht
, NULL
, NULL TSRMLS_CC
);
443 php_http_buffer_dtor(&headers
);
448 char *php_http_env_get_response_header(const char *name_str
, size_t name_len TSRMLS_DC
)
453 zend_hash_init(&headers
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
454 if (SUCCESS
== php_http_env_get_response_headers(&headers TSRMLS_CC
)) {
456 char *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
458 if (SUCCESS
== zend_symtable_find(&headers
, key
, name_len
+ 1, (void *) &zvalue
)) {
459 zval
*zcopy
= php_http_ztyp(IS_STRING
, *zvalue
);
461 val
= estrndup(Z_STRVAL_P(zcopy
), Z_STRLEN_P(zcopy
));
462 zval_ptr_dtor(&zcopy
);
467 zend_hash_destroy(&headers
);
472 long php_http_env_get_response_code(TSRMLS_D
)
474 long code
= SG(sapi_headers
).http_response_code
;
475 return code
? code
: 200;
478 STATUS
php_http_env_set_response_code(long http_code TSRMLS_DC
)
480 return sapi_header_op(SAPI_HEADER_SET_STATUS
, (void *) http_code TSRMLS_CC
);
483 STATUS
php_http_env_set_response_status_line(long code
, php_http_version_t
*v TSRMLS_DC
)
485 sapi_header_line h
= {NULL
, 0, 0};
488 h
.line_len
= spprintf(&h
.line
, 0, "HTTP/%u.%u %ld %s", v
->major
, v
->minor
, code
, php_http_env_get_response_status_for_code(code
));
489 ret
= sapi_header_op(SAPI_HEADER_REPLACE
, (void *) &h TSRMLS_CC
);
495 STATUS
php_http_env_set_response_protocol_version(php_http_version_t
*v TSRMLS_DC
)
497 return php_http_env_set_response_status_line(php_http_env_get_response_code(TSRMLS_C
), v TSRMLS_CC
);
500 STATUS
php_http_env_set_response_header(long http_code
, const char *header_str
, size_t header_len
, zend_bool replace TSRMLS_DC
)
502 sapi_header_line h
= {estrndup(header_str
, header_len
), header_len
, http_code
};
503 STATUS ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h TSRMLS_CC
);
508 STATUS
php_http_env_set_response_header_va(long http_code
, zend_bool replace
, const char *fmt
, va_list argv TSRMLS_DC
)
510 STATUS ret
= FAILURE
;
511 sapi_header_line h
= {NULL
, 0, http_code
};
513 h
.line_len
= vspprintf(&h
.line
, 0, fmt
, argv
);
517 ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h TSRMLS_CC
);
524 STATUS
php_http_env_set_response_header_format(long http_code
, zend_bool replace TSRMLS_DC
, const char *fmt
, ...)
530 ret
= php_http_env_set_response_header_va(http_code
, replace
, fmt
, args TSRMLS_CC
);
536 STATUS
php_http_env_set_response_header_value(long http_code
, const char *name_str
, size_t name_len
, zval
*value
, zend_bool replace TSRMLS_DC
)
539 sapi_header_line h
= {(char *) name_str
, name_len
, http_code
};
541 return sapi_header_op(SAPI_HEADER_DELETE
, (void *) &h TSRMLS_CC
);
544 if(Z_TYPE_P(value
) == IS_ARRAY
|| Z_TYPE_P(value
) == IS_OBJECT
) {
549 FOREACH_HASH_VAL(pos
, HASH_OF(value
), data_ptr
) {
550 if (SUCCESS
!= php_http_env_set_response_header_value(http_code
, name_str
, name_len
, *data_ptr
, first TSRMLS_CC
)) {
558 zval
*data
= php_http_ztyp(IS_STRING
, value
);
560 if (!Z_STRLEN_P(data
)) {
561 zval_ptr_dtor(&data
);
562 return php_http_env_set_response_header_value(http_code
, name_str
, name_len
, NULL
, replace TSRMLS_CC
);
567 if (name_len
> INT_MAX
) {
570 h
.response_code
= http_code
;
571 h
.line_len
= spprintf(&h
.line
, 0, "%.*s: %.*s", (int) name_len
, name_str
, Z_STRLEN_P(data
), Z_STRVAL_P(data
));
573 ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h TSRMLS_CC
);
575 zval_ptr_dtor(&data
);
583 static PHP_HTTP_STRLIST(php_http_env_response_status
) =
584 PHP_HTTP_STRLIST_ITEM("Continue")
585 PHP_HTTP_STRLIST_ITEM("Switching Protocols")
586 PHP_HTTP_STRLIST_ITEM("Processing")
587 PHP_HTTP_STRLIST_NEXT
588 PHP_HTTP_STRLIST_ITEM("OK")
589 PHP_HTTP_STRLIST_ITEM("Created")
590 PHP_HTTP_STRLIST_ITEM("Accepted")
591 PHP_HTTP_STRLIST_ITEM("Non-Authoritative Information")
592 PHP_HTTP_STRLIST_ITEM("No Content")
593 PHP_HTTP_STRLIST_ITEM("Reset Content")
594 PHP_HTTP_STRLIST_ITEM("Partial Content")
595 PHP_HTTP_STRLIST_ITEM("Multi-Status")
596 PHP_HTTP_STRLIST_ITEM("Already Reported")
597 PHP_HTTP_STRLIST_ITEM("(Unused)")
598 PHP_HTTP_STRLIST_ITEM("(Unused)")
599 PHP_HTTP_STRLIST_ITEM("(Unused)")
600 PHP_HTTP_STRLIST_ITEM("(Unused)")
601 PHP_HTTP_STRLIST_ITEM("(Unused)")
602 PHP_HTTP_STRLIST_ITEM("(Unused)")
603 PHP_HTTP_STRLIST_ITEM("(Unused)")
604 PHP_HTTP_STRLIST_ITEM("(Unused)")
605 PHP_HTTP_STRLIST_ITEM("(Unused)")
606 PHP_HTTP_STRLIST_ITEM("(Unused)")
607 PHP_HTTP_STRLIST_ITEM("(Unused)")
608 PHP_HTTP_STRLIST_ITEM("(Unused)")
609 PHP_HTTP_STRLIST_ITEM("(Unused)")
610 PHP_HTTP_STRLIST_ITEM("(Unused)")
611 PHP_HTTP_STRLIST_ITEM("(Unused)")
612 PHP_HTTP_STRLIST_ITEM("(Unused)")
613 PHP_HTTP_STRLIST_ITEM("(Unused)")
614 PHP_HTTP_STRLIST_ITEM("IM Used")
615 PHP_HTTP_STRLIST_NEXT
616 PHP_HTTP_STRLIST_ITEM("Multiple Choices")
617 PHP_HTTP_STRLIST_ITEM("Moved Permanently")
618 PHP_HTTP_STRLIST_ITEM("Found")
619 PHP_HTTP_STRLIST_ITEM("See Other")
620 PHP_HTTP_STRLIST_ITEM("Not Modified")
621 PHP_HTTP_STRLIST_ITEM("Use Proxy")
622 PHP_HTTP_STRLIST_ITEM("(Unused)")
623 PHP_HTTP_STRLIST_ITEM("Temporary Redirect")
624 PHP_HTTP_STRLIST_ITEM("Permanent Redirect")
625 PHP_HTTP_STRLIST_NEXT
626 PHP_HTTP_STRLIST_ITEM("Bad Request")
627 PHP_HTTP_STRLIST_ITEM("Unauthorized")
628 PHP_HTTP_STRLIST_ITEM("Payment Required")
629 PHP_HTTP_STRLIST_ITEM("Forbidden")
630 PHP_HTTP_STRLIST_ITEM("Not Found")
631 PHP_HTTP_STRLIST_ITEM("Method Not Allowed")
632 PHP_HTTP_STRLIST_ITEM("Not Acceptable")
633 PHP_HTTP_STRLIST_ITEM("Proxy Authentication Required")
634 PHP_HTTP_STRLIST_ITEM("Request Timeout")
635 PHP_HTTP_STRLIST_ITEM("Conflict")
636 PHP_HTTP_STRLIST_ITEM("Gone")
637 PHP_HTTP_STRLIST_ITEM("Length Required")
638 PHP_HTTP_STRLIST_ITEM("Precondition Failed")
639 PHP_HTTP_STRLIST_ITEM("Request Entity Too Large")
640 PHP_HTTP_STRLIST_ITEM("Request URI Too Long")
641 PHP_HTTP_STRLIST_ITEM("Unsupported Media Type")
642 PHP_HTTP_STRLIST_ITEM("Requested Range Not Satisfiable")
643 PHP_HTTP_STRLIST_ITEM("Expectation Failed")
644 PHP_HTTP_STRLIST_ITEM("(Unused)")
645 PHP_HTTP_STRLIST_ITEM("(Unused)")
646 PHP_HTTP_STRLIST_ITEM("(Unused)")
647 PHP_HTTP_STRLIST_ITEM("(Unused)")
648 PHP_HTTP_STRLIST_ITEM("Unprocessible Entity")
649 PHP_HTTP_STRLIST_ITEM("Locked")
650 PHP_HTTP_STRLIST_ITEM("Failed Dependency")
651 PHP_HTTP_STRLIST_ITEM("(Reserved)")
652 PHP_HTTP_STRLIST_ITEM("Upgrade Required")
653 PHP_HTTP_STRLIST_ITEM("(Unused)")
654 PHP_HTTP_STRLIST_ITEM("Precondition Required")
655 PHP_HTTP_STRLIST_ITEM("Too Many Requests")
656 PHP_HTTP_STRLIST_ITEM("(Unused)")
657 PHP_HTTP_STRLIST_ITEM("Request Header Fields Too Large")
658 PHP_HTTP_STRLIST_NEXT
659 PHP_HTTP_STRLIST_ITEM("Internal Server Error")
660 PHP_HTTP_STRLIST_ITEM("Not Implemented")
661 PHP_HTTP_STRLIST_ITEM("Bad Gateway")
662 PHP_HTTP_STRLIST_ITEM("Service Unavailable")
663 PHP_HTTP_STRLIST_ITEM("Gateway Timeout")
664 PHP_HTTP_STRLIST_ITEM("HTTP Version Not Supported")
665 PHP_HTTP_STRLIST_ITEM("Variant Also Negotiates")
666 PHP_HTTP_STRLIST_ITEM("Insufficient Storage")
667 PHP_HTTP_STRLIST_ITEM("Loop Detected")
668 PHP_HTTP_STRLIST_ITEM("(Unused)")
669 PHP_HTTP_STRLIST_ITEM("Not Extended")
670 PHP_HTTP_STRLIST_ITEM("Network Authentication Required")
671 PHP_HTTP_STRLIST_STOP
674 const char *php_http_env_get_response_status_for_code(unsigned code
)
676 return php_http_strlist_find(php_http_env_response_status
, 100, code
);
679 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getRequestHeader
, 0, 0, 0)
680 ZEND_ARG_INFO(0, header_name
)
682 static PHP_METHOD(HttpEnv
, getRequestHeader
)
684 char *header_name_str
= NULL
;
685 int header_name_len
= 0;
687 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s!", &header_name_str
, &header_name_len
)) {
690 if (header_name_str
&& header_name_len
) {
691 size_t header_length
;
692 char *header_value
= php_http_env_get_request_header(header_name_str
, header_name_len
, &header_length
, NULL TSRMLS_CC
);
695 RETURN_STRINGL(header_value
, header_length
, 0);
698 array_init(return_value
);
699 php_http_env_get_request_headers(Z_ARRVAL_P(return_value
) TSRMLS_CC
);
703 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getRequestBody
, 0, 0, 0)
704 ZEND_ARG_INFO(0, body_class_name
)
706 static PHP_METHOD(HttpEnv
, getRequestBody
)
708 zend_object_value ov
;
709 php_http_message_body_t
*body
;
710 zend_class_entry
*class_entry
= php_http_message_body_class_entry
;
712 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|C", &class_entry
), invalid_arg
, return);
714 body
= php_http_env_get_request_body(TSRMLS_C
);
715 if (SUCCESS
== php_http_new(&ov
, class_entry
, (php_http_new_t
) php_http_message_body_object_new_ex
, php_http_message_body_class_entry
, body
, NULL TSRMLS_CC
)) {
716 php_http_message_body_addref(body
);
717 RETVAL_OBJVAL(ov
, 0);
721 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseStatusForCode
, 0, 0, 1)
722 ZEND_ARG_INFO(0, code
)
724 static PHP_METHOD(HttpEnv
, getResponseStatusForCode
)
728 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &code
)) {
731 RETURN_STRING(php_http_env_get_response_status_for_code(code
), 1);
734 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseStatusForAllCodes
, 0, 0, 0)
736 static PHP_METHOD(HttpEnv
, getResponseStatusForAllCodes
)
740 php_http_strlist_iterator_t i
;
742 if (SUCCESS
!= zend_parse_parameters_none()) {
746 array_init(return_value
);
747 for ( php_http_strlist_iterator_init(&i
, php_http_env_response_status
, 100);
748 *(s
= php_http_strlist_iterator_this(&i
, &c
));
749 php_http_strlist_iterator_next(&i
)
751 add_index_string(return_value
, c
, s
, 1);
755 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseHeader
, 0, 0, 0)
756 ZEND_ARG_INFO(0, header_name
)
758 static PHP_METHOD(HttpEnv
, getResponseHeader
)
760 char *header_name_str
= NULL
;
761 int header_name_len
= 0;
763 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s!", &header_name_str
, &header_name_len
)) {
766 if (header_name_str
&& header_name_len
) {
767 char *header_value
= php_http_env_get_response_header(header_name_str
, header_name_len TSRMLS_CC
);
770 RETURN_STRING(header_value
, 0);
773 array_init(return_value
);
774 php_http_env_get_response_headers(Z_ARRVAL_P(return_value
) TSRMLS_CC
);
778 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseCode
, 0, 0, 0)
780 static PHP_METHOD(HttpEnv
, getResponseCode
)
782 if (SUCCESS
!= zend_parse_parameters_none()) {
785 RETURN_LONG(php_http_env_get_response_code(TSRMLS_C
));
788 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_setResponseHeader
, 0, 0, 1)
789 ZEND_ARG_INFO(0, header_name
)
790 ZEND_ARG_INFO(0, header_value
)
791 ZEND_ARG_INFO(0, response_code
)
792 ZEND_ARG_INFO(0, replace_header
)
794 static PHP_METHOD(HttpEnv
, setResponseHeader
)
796 char *header_name_str
;
798 zval
*header_value
= NULL
;
800 zend_bool replace_header
= 1;
802 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|z!lb", &header_name_str
, &header_name_len
, &header_value
, &code
, &replace_header
)) {
805 RETURN_BOOL(SUCCESS
== php_http_env_set_response_header_value(code
, header_name_str
, header_name_len
, header_value
, replace_header TSRMLS_CC
));
808 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_setResponseCode
, 0, 0, 1)
809 ZEND_ARG_INFO(0, code
)
811 static PHP_METHOD(HttpEnv
, setResponseCode
)
815 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &code
)) {
818 RETURN_BOOL(SUCCESS
== php_http_env_set_response_code(code TSRMLS_CC
));
821 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateLanguage
, 0, 0, 1)
822 ZEND_ARG_INFO(0, supported
)
823 ZEND_ARG_INFO(1, result_array
)
825 static PHP_METHOD(HttpEnv
, negotiateLanguage
)
827 HashTable
*supported
;
828 zval
*rs_array
= NULL
;
830 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
835 array_init(rs_array
);
838 PHP_HTTP_DO_NEGOTIATE(language
, supported
, rs_array
);
841 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateCharset
, 0, 0, 1)
842 ZEND_ARG_INFO(0, supported
)
843 ZEND_ARG_INFO(1, result_array
)
845 static PHP_METHOD(HttpEnv
, negotiateCharset
)
847 HashTable
*supported
;
848 zval
*rs_array
= NULL
;
850 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
855 array_init(rs_array
);
857 PHP_HTTP_DO_NEGOTIATE(charset
, supported
, rs_array
);
860 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateEncoding
, 0, 0, 1)
861 ZEND_ARG_INFO(0, supported
)
862 ZEND_ARG_INFO(1, result_array
)
864 static PHP_METHOD(HttpEnv
, negotiateEncoding
)
866 HashTable
*supported
;
867 zval
*rs_array
= NULL
;
869 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
874 array_init(rs_array
);
876 PHP_HTTP_DO_NEGOTIATE(encoding
, supported
, rs_array
);
879 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateContentType
, 0, 0, 1)
880 ZEND_ARG_INFO(0, supported
)
881 ZEND_ARG_INFO(1, result_array
)
883 static PHP_METHOD(HttpEnv
, negotiateContentType
)
885 HashTable
*supported
;
886 zval
*rs_array
= NULL
;
888 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
893 array_init(rs_array
);
895 PHP_HTTP_DO_NEGOTIATE(content_type
, supported
, rs_array
);
898 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiate
, 0, 0, 2)
899 ZEND_ARG_INFO(0, params
)
900 ZEND_ARG_INFO(0, supported
)
901 ZEND_ARG_INFO(0, primary_type_separator
)
902 ZEND_ARG_INFO(1, result_array
)
904 static PHP_METHOD(HttpEnv
, negotiate
)
906 HashTable
*supported
, *rs
;
907 zval
*rs_array
= NULL
;
908 char *value_str
, *sep_str
= NULL
;
909 int value_len
, sep_len
= 0;
911 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sH|s!z", &value_str
, &value_len
, &supported
, &sep_str
, &sep_len
, &rs_array
)) {
918 array_init(rs_array
);
921 if ((rs
= php_http_negotiate(value_str
, value_len
, supported
, sep_str
, sep_len TSRMLS_CC
))) {
922 PHP_HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs
, supported
, rs_array
);
924 PHP_HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported
, rs_array
);
928 static zend_function_entry php_http_env_methods
[] = {
929 PHP_ME(HttpEnv
, getRequestHeader
, ai_HttpEnv_getRequestHeader
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
930 PHP_ME(HttpEnv
, getRequestBody
, ai_HttpEnv_getRequestBody
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
932 PHP_ME(HttpEnv
, getResponseStatusForCode
, ai_HttpEnv_getResponseStatusForCode
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
933 PHP_ME(HttpEnv
, getResponseStatusForAllCodes
, ai_HttpEnv_getResponseStatusForAllCodes
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
935 PHP_ME(HttpEnv
, getResponseHeader
, ai_HttpEnv_getResponseHeader
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
936 PHP_ME(HttpEnv
, getResponseCode
, ai_HttpEnv_getResponseCode
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
937 PHP_ME(HttpEnv
, setResponseHeader
, ai_HttpEnv_setResponseHeader
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
938 PHP_ME(HttpEnv
, setResponseCode
, ai_HttpEnv_setResponseCode
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
940 PHP_ME(HttpEnv
, negotiateLanguage
, ai_HttpEnv_negotiateLanguage
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
941 PHP_ME(HttpEnv
, negotiateContentType
, ai_HttpEnv_negotiateContentType
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
942 PHP_ME(HttpEnv
, negotiateEncoding
, ai_HttpEnv_negotiateEncoding
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
943 PHP_ME(HttpEnv
, negotiateCharset
, ai_HttpEnv_negotiateCharset
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
944 PHP_ME(HttpEnv
, negotiate
, ai_HttpEnv_negotiate
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
949 #ifdef PHP_HTTP_HAVE_JSON
950 #include "ext/json/php_json.h"
952 static SAPI_POST_HANDLER_FUNC(php_http_json_post_handler
)
955 char *json_str
= NULL
;
958 #if PHP_VERSION_ID >= 50600
959 if (SG(request_info
).request_body
) {
960 /* FG(stream_wrappers) not initialized yet, so we cannot use php://input */
961 php_stream_rewind(SG(request_info
).request_body
);
962 json_len
= php_stream_copy_to_mem(SG(request_info
).request_body
, &json_str
, PHP_STREAM_COPY_ALL
, 0);
965 json_str
= SG(request_info
).raw_post_data
;
966 json_len
= SG(request_info
).raw_post_data_length
;
973 php_json_decode(&zjson
, json_str
, json_len
, 1, PG(max_input_nesting_level
) TSRMLS_CC
);
974 if (Z_TYPE(zjson
) != IS_NULL
) {
976 ZVAL_COPY_VALUE(zarg
, (&zjson
));
979 #if PHP_VERSION_ID >= 50600
984 static void php_http_env_register_json_handler(TSRMLS_D
)
986 sapi_post_entry entry
= {NULL
, 0, NULL
, NULL
};
988 entry
.post_reader
= sapi_read_standard_form_data
;
989 entry
.post_handler
= php_http_json_post_handler
;
991 entry
.content_type
= "text/json";
992 entry
.content_type_len
= lenof("text/json");
993 sapi_register_post_entry(&entry TSRMLS_CC
);
995 entry
.content_type
= "application/json";
996 entry
.content_type_len
= lenof("application/json");
997 sapi_register_post_entry(&entry TSRMLS_CC
);
1001 zend_class_entry
*php_http_env_class_entry
;
1003 PHP_MINIT_FUNCTION(http_env
)
1005 zend_class_entry ce
= {0};
1007 INIT_NS_CLASS_ENTRY(ce
, "http", "Env", php_http_env_methods
);
1008 php_http_env_class_entry
= zend_register_internal_class(&ce TSRMLS_CC
);
1010 #ifdef PHP_HTTP_HAVE_JSON
1011 php_http_env_register_json_handler(TSRMLS_C
);
1023 * vim600: noet sw=4 ts=4 fdm=marker
1024 * vim<600: noet sw=4 ts=4