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
)) {
36 if (HASH_KEY_IS_STRING
== zend_hash_get_current_key(¶ms
, &key_str
, &key_num
)) {
37 sapi_post_entry
*post_entry
= NULL
;
39 if ((post_entry
= zend_hash_find_ptr(&SG(known_post_content_types
), key_str
))) {
40 SG(request_info
).post_entry
= post_entry
;
42 if (post_entry
->post_reader
) {
43 post_entry
->post_reader();
46 if (sapi_module
.default_post_reader
) {
47 sapi_module
.default_post_reader();
50 sapi_handle_post(&PG(http_globals
)[TRACK_VARS_POST
]);
53 * the rfc1867 handler is an awkward buddy
54 * FIXME: this leaks because php_auto_globals_create_files()
55 * as well as the rfc1867_handler call
56 * array_init(&PG(http_globals)[TRACK_VARS_FILES])
58 Z_TRY_ADDREF(PG(http_globals
)[TRACK_VARS_FILES
]);
59 zend_hash_str_update(&EG(symbol_table
).ht
, "_FILES", lenof("_FILES"), &PG(http_globals
)[TRACK_VARS_FILES
]);
62 zend_hash_destroy(¶ms
);
66 PTR_SET(SG(request_info
).content_type_dup
, NULL
);
71 PHP_RSHUTDOWN_FUNCTION(http_env
)
73 if (PHP_HTTP_G
->env
.request
.headers
) {
74 zend_hash_destroy(PHP_HTTP_G
->env
.request
.headers
);
75 FREE_HASHTABLE(PHP_HTTP_G
->env
.request
.headers
);
76 PHP_HTTP_G
->env
.request
.headers
= NULL
;
78 if (PHP_HTTP_G
->env
.request
.body
) {
79 php_http_message_body_free(&PHP_HTTP_G
->env
.request
.body
);
82 if (PHP_HTTP_G
->env
.server_var
) {
83 zval_ptr_dtor(PHP_HTTP_G
->env
.server_var
);
84 PHP_HTTP_G
->env
.server_var
= NULL
;
90 void php_http_env_get_request_headers(HashTable
*headers TSRMLS_DC
)
92 php_http_arrkey_t key
;
95 if (!PHP_HTTP_G
->env
.request
.headers
) {
96 ALLOC_HASHTABLE(PHP_HTTP_G
->env
.request
.headers
);
97 ZEND_INIT_SYMTABLE(PHP_HTTP_G
->env
.request
.headers
);
99 if ((hsv
= php_http_env_get_superglobal(ZEND_STRL("_SERVER")))) {
100 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(hsv
), key
.h
, key
.key
, header
)
102 if (key
.key
&& key
.key
->len
> 5 && *key
.key
->val
== 'H' && !strncmp(key
.key
->val
, "HTTP_", 5)) {
103 size_t key_len
= key
.key
->len
- 5;
104 char *key_str
= php_http_pretty_key(estrndup(&key
.key
->val
[5], key_len
), key_len
, 1, 1);
106 Z_TRY_ADDREF_P(header
);
107 zend_symtable_str_update(PHP_HTTP_G
->env
.request
.headers
, key_str
, key_len
, header
);
110 } else if (key
.key
&& key
.key
->len
> 8 && *key
.key
->val
== 'C' && !strncmp(key
.key
->val
, "CONTENT_", 8)) {
111 char *key_str
= php_http_pretty_key(estrndup(key
.key
->val
, key
.key
->len
), key
.key
->len
, 1, 1);
113 Z_TRY_ADDREF_P(header
);
114 zend_symtable_str_update(PHP_HTTP_G
->env
.request
.headers
, key_str
, key
.key
->len
, header
);
119 ZEND_HASH_FOREACH_END();
124 array_copy(PHP_HTTP_G
->env
.request
.headers
, headers
);
128 char *php_http_env_get_request_header(const char *name_str
, size_t name_len
, size_t *len
, php_http_message_t
*request
)
130 HashTable
*request_headers
;
132 char *val
= NULL
, *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
135 request_headers
= &request
->hdrs
;
137 php_http_env_get_request_headers(NULL
);
138 request_headers
= PHP_HTTP_G
->env
.request
.headers
;
141 if ((zvalue
= zend_symtable_str_find(request_headers
, key
, name_len
))) {
142 zend_string
*zs
= zval_get_string(zvalue
);
144 val
= estrndup(zs
->val
, zs
->len
);
148 zend_string_release(zs
);
156 zend_bool
php_http_env_got_request_header(const char *name_str
, size_t name_len
, php_http_message_t
*request
)
158 HashTable
*request_headers
;
159 char *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
163 request_headers
= &request
->hdrs
;
165 php_http_env_get_request_headers(NULL
);
166 request_headers
= PHP_HTTP_G
->env
.request
.headers
;
168 got
= zend_symtable_str_exists(request_headers
, key
, name_len
);
174 zval
*php_http_env_get_superglobal(const char *key
, size_t key_len
)
177 zend_string
*key_str
= zend_string_init(key
, key_len
, 0);
179 zend_is_auto_global(key_str
);
180 hsv
= zend_hash_find(&EG(symbol_table
).ht
, key_str
);
181 zend_string_release(key_str
);
183 if (Z_TYPE_P(hsv
) != IS_ARRAY
) {
190 zval
*php_http_env_get_server_var(const char *key
, size_t key_len
, zend_bool check
)
194 /* if available, this is a lot faster than accessing $_SERVER * /
195 if (sapi_module.getenv) {
198 if ((!(env = sapi_module.getenv((char *) key, key_len))) || (check && !*env)) {
201 if (PHP_HTTP_G->env.server_var) {
202 zval_ptr_dtor(&PHP_HTTP_G->env.server_var);
204 MAKE_STD_ZVAL(PHP_HTTP_G->env.server_var);
205 ZVAL_STRING(PHP_HTTP_G->env.server_var, env, 1);
206 return PHP_HTTP_G->env.server_var;
210 if (!(hsv
= php_http_env_get_superglobal(ZEND_STRL("_SERVER")))) {
213 if (!(var
= zend_symtable_str_find(Z_ARRVAL_P(hsv
), key
, key_len
))) {
216 if (check
&& !((Z_TYPE_P(var
) == IS_STRING
) && Z_STRVAL_P(var
) && Z_STRLEN_P(var
))) {
222 php_http_message_body_t
*php_http_env_get_request_body(void)
224 if (!PHP_HTTP_G
->env
.request
.body
) {
225 php_stream
*s
= php_stream_temp_new();
226 php_stream
*input
= php_stream_open_wrapper("php://input", "r", 0, NULL
);
228 /* php://input does not support stat */
229 php_stream_copy_to_stream_ex(input
, s
, -1, NULL
);
230 php_stream_close(input
);
232 php_stream_rewind(s
);
233 PHP_HTTP_G
->env
.request
.body
= php_http_message_body_init(NULL
, s
);
236 return PHP_HTTP_G
->env
.request
.body
;
239 const char *php_http_env_get_request_method(php_http_message_t
*request
)
243 if (PHP_HTTP_MESSAGE_TYPE(REQUEST
, request
)) {
244 m
= request
->http
.info
.request
.method
;
246 m
= SG(request_info
).request_method
;
249 return m
? m
: "GET";
252 php_http_range_status_t
php_http_env_get_request_ranges(HashTable
*ranges
, size_t length
, php_http_message_t
*request
)
256 long begin
= -1, end
= -1, *ptr
;
258 if (!(range
= php_http_env_get_request_header(ZEND_STRL("Range"), NULL
, request
))) {
259 return PHP_HTTP_RANGE_NO
;
261 if (strncmp(range
, "bytes=", lenof("bytes="))) {
263 return PHP_HTTP_RANGE_NO
;
266 rp
= range
+ lenof("bytes=");
270 switch (c
= *(rp
++)) {
272 /* allow 000... - shall we? */
278 case '1': case '2': case '3':
279 case '4': case '5': case '6':
280 case '7': case '8': case '9':
282 * If the value of the pointer is already set (non-negative)
283 * then multiply its value by ten and add the current value,
284 * else initialise the pointers value with the current value
286 * This let us recognize empty fields when validating the
287 * ranges, i.e. a "-10" for begin and "12345" for the end
288 * was the following range request: "Range: bytes=0-12345";
289 * While a "-1" for begin and "12345" for the end would
290 * have been: "Range: bytes=-12345".
311 /* validate ranges */
319 return PHP_HTTP_RANGE_NO
;
327 if (length
<= (size_t) end
) {
338 if (end
== -1 || end
== -10) {
340 return PHP_HTTP_RANGE_ERR
;
342 begin
= length
- end
;
348 if (length
<= (size_t) begin
) {
350 return PHP_HTTP_RANGE_ERR
;
356 return PHP_HTTP_RANGE_ERR
;
365 if (length
<= (size_t) end
) {
367 } else if (end
< begin
) {
369 return PHP_HTTP_RANGE_ERR
;
378 add_index_long(&zentry
, 0, begin
);
379 add_index_long(&zentry
, 1, end
);
380 zend_hash_next_index_insert(ranges
, &zentry
);
390 return PHP_HTTP_RANGE_NO
;
395 return PHP_HTTP_RANGE_OK
;
398 static void grab_headers(void *data
, void *arg
)
400 php_http_buffer_appendl(PHP_HTTP_BUFFER(arg
), ((sapi_header_struct
*)data
)->header
);
401 php_http_buffer_appends(PHP_HTTP_BUFFER(arg
), PHP_HTTP_CRLF
);
404 static void grab_header(void *data
, void *arg
)
411 sapi_header_struct
*header
= data
;
413 if ( header
->header_len
> args
->name_len
414 && header
->header
[args
->name_len
] == ':'
415 && !strncmp(header
->header
, args
->name_str
, args
->name_len
)
417 args
->value_ptr
= &header
->header
[args
->name_len
+ 1];
418 while (PHP_HTTP_IS_CTYPE(space
, *args
->value_ptr
)) {
424 ZEND_RESULT_CODE
php_http_env_get_response_headers(HashTable
*headers_ht
)
426 ZEND_RESULT_CODE status
;
427 php_http_buffer_t headers
;
429 php_http_buffer_init(&headers
);
430 zend_llist_apply_with_argument(&SG(sapi_headers
).headers
, grab_headers
, &headers
);
431 php_http_buffer_fix(&headers
);
433 status
= php_http_header_parse(headers
.data
, headers
.used
, headers_ht
, NULL
, NULL
);
434 php_http_buffer_dtor(&headers
);
439 char *php_http_env_get_response_header(const char *name_str
, size_t name_len
)
447 args
.name_str
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
448 args
.name_len
= name_len
;
449 args
.value_ptr
= NULL
;
450 zend_llist_apply_with_argument(&SG(sapi_headers
).headers
, grab_header
, &args
);
451 efree(args
.name_str
);
453 return args
.value_ptr
? estrdup(args
.value_ptr
) : NULL
;
456 long php_http_env_get_response_code(void)
458 long code
= SG(sapi_headers
).http_response_code
;
459 return code
? code
: 200;
462 ZEND_RESULT_CODE
php_http_env_set_response_code(long http_code
)
464 return sapi_header_op(SAPI_HEADER_SET_STATUS
, (void *) (zend_intptr_t
) http_code
);
467 ZEND_RESULT_CODE
php_http_env_set_response_status_line(long code
, php_http_version_t
*v
)
469 sapi_header_line h
= {NULL
, 0, 0};
470 ZEND_RESULT_CODE ret
;
472 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
));
473 ret
= sapi_header_op(SAPI_HEADER_REPLACE
, (void *) &h
);
479 ZEND_RESULT_CODE
php_http_env_set_response_protocol_version(php_http_version_t
*v
)
481 return php_http_env_set_response_status_line(php_http_env_get_response_code(), v
);
484 ZEND_RESULT_CODE
php_http_env_set_response_header(long http_code
, const char *header_str
, size_t header_len
, zend_bool replace
)
486 sapi_header_line h
= {estrndup(header_str
, header_len
), header_len
, http_code
};
487 ZEND_RESULT_CODE ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h
);
492 ZEND_RESULT_CODE
php_http_env_set_response_header_va(long http_code
, zend_bool replace
, const char *fmt
, va_list argv
)
494 ZEND_RESULT_CODE ret
= FAILURE
;
495 sapi_header_line h
= {NULL
, 0, http_code
};
497 h
.line_len
= vspprintf(&h
.line
, 0, fmt
, argv
);
501 ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h
);
508 ZEND_RESULT_CODE
php_http_env_set_response_header_format(long http_code
, zend_bool replace
, const char *fmt
, ...)
510 ZEND_RESULT_CODE ret
;
514 ret
= php_http_env_set_response_header_va(http_code
, replace
, fmt
, args
);
520 ZEND_RESULT_CODE
php_http_env_set_response_header_value(long http_code
, const char *name_str
, size_t name_len
, zval
*value
, zend_bool replace
)
523 sapi_header_line h
= {(char *) name_str
, name_len
, http_code
};
525 return sapi_header_op(SAPI_HEADER_DELETE
, (void *) &h
);
528 if (Z_TYPE_P(value
) == IS_ARRAY
|| Z_TYPE_P(value
) == IS_OBJECT
) {
531 HashTable
*ht
= HASH_OF(value
);
533 ZEND_HASH_FOREACH_VAL(ht
, data_ptr
)
535 if (SUCCESS
!= php_http_env_set_response_header_value(http_code
, name_str
, name_len
, data_ptr
, first
)) {
540 ZEND_HASH_FOREACH_END();
544 zend_string
*data
= zval_get_string(value
);
547 zend_string_release(data
);
548 return php_http_env_set_response_header_value(http_code
, name_str
, name_len
, NULL
, replace
);
551 ZEND_RESULT_CODE ret
;
553 if (name_len
> INT_MAX
) {
556 h
.response_code
= http_code
;
557 h
.line_len
= spprintf(&h
.line
, 0, "%.*s: %.*s", (int) name_len
, name_str
, data
->len
, data
->val
);
559 ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h
);
561 zend_string_release(data
);
569 static PHP_HTTP_STRLIST(php_http_env_response_status
) =
570 PHP_HTTP_STRLIST_ITEM("Continue")
571 PHP_HTTP_STRLIST_ITEM("Switching Protocols")
572 PHP_HTTP_STRLIST_ITEM("Processing")
573 PHP_HTTP_STRLIST_NEXT
574 PHP_HTTP_STRLIST_ITEM("OK")
575 PHP_HTTP_STRLIST_ITEM("Created")
576 PHP_HTTP_STRLIST_ITEM("Accepted")
577 PHP_HTTP_STRLIST_ITEM("Non-Authoritative Information")
578 PHP_HTTP_STRLIST_ITEM("No Content")
579 PHP_HTTP_STRLIST_ITEM("Reset Content")
580 PHP_HTTP_STRLIST_ITEM("Partial Content")
581 PHP_HTTP_STRLIST_ITEM("Multi-Status")
582 PHP_HTTP_STRLIST_ITEM("Already Reported")
583 PHP_HTTP_STRLIST_ITEM("(Unused)")
584 PHP_HTTP_STRLIST_ITEM("(Unused)")
585 PHP_HTTP_STRLIST_ITEM("(Unused)")
586 PHP_HTTP_STRLIST_ITEM("(Unused)")
587 PHP_HTTP_STRLIST_ITEM("(Unused)")
588 PHP_HTTP_STRLIST_ITEM("(Unused)")
589 PHP_HTTP_STRLIST_ITEM("(Unused)")
590 PHP_HTTP_STRLIST_ITEM("(Unused)")
591 PHP_HTTP_STRLIST_ITEM("(Unused)")
592 PHP_HTTP_STRLIST_ITEM("(Unused)")
593 PHP_HTTP_STRLIST_ITEM("(Unused)")
594 PHP_HTTP_STRLIST_ITEM("(Unused)")
595 PHP_HTTP_STRLIST_ITEM("(Unused)")
596 PHP_HTTP_STRLIST_ITEM("(Unused)")
597 PHP_HTTP_STRLIST_ITEM("(Unused)")
598 PHP_HTTP_STRLIST_ITEM("(Unused)")
599 PHP_HTTP_STRLIST_ITEM("(Unused)")
600 PHP_HTTP_STRLIST_ITEM("IM Used")
601 PHP_HTTP_STRLIST_NEXT
602 PHP_HTTP_STRLIST_ITEM("Multiple Choices")
603 PHP_HTTP_STRLIST_ITEM("Moved Permanently")
604 PHP_HTTP_STRLIST_ITEM("Found")
605 PHP_HTTP_STRLIST_ITEM("See Other")
606 PHP_HTTP_STRLIST_ITEM("Not Modified")
607 PHP_HTTP_STRLIST_ITEM("Use Proxy")
608 PHP_HTTP_STRLIST_ITEM("(Unused)")
609 PHP_HTTP_STRLIST_ITEM("Temporary Redirect")
610 PHP_HTTP_STRLIST_ITEM("Permanent Redirect")
611 PHP_HTTP_STRLIST_NEXT
612 PHP_HTTP_STRLIST_ITEM("Bad Request")
613 PHP_HTTP_STRLIST_ITEM("Unauthorized")
614 PHP_HTTP_STRLIST_ITEM("Payment Required")
615 PHP_HTTP_STRLIST_ITEM("Forbidden")
616 PHP_HTTP_STRLIST_ITEM("Not Found")
617 PHP_HTTP_STRLIST_ITEM("Method Not Allowed")
618 PHP_HTTP_STRLIST_ITEM("Not Acceptable")
619 PHP_HTTP_STRLIST_ITEM("Proxy Authentication Required")
620 PHP_HTTP_STRLIST_ITEM("Request Timeout")
621 PHP_HTTP_STRLIST_ITEM("Conflict")
622 PHP_HTTP_STRLIST_ITEM("Gone")
623 PHP_HTTP_STRLIST_ITEM("Length Required")
624 PHP_HTTP_STRLIST_ITEM("Precondition Failed")
625 PHP_HTTP_STRLIST_ITEM("Request Entity Too Large")
626 PHP_HTTP_STRLIST_ITEM("Request URI Too Long")
627 PHP_HTTP_STRLIST_ITEM("Unsupported Media Type")
628 PHP_HTTP_STRLIST_ITEM("Requested Range Not Satisfiable")
629 PHP_HTTP_STRLIST_ITEM("Expectation Failed")
630 PHP_HTTP_STRLIST_ITEM("(Unused)")
631 PHP_HTTP_STRLIST_ITEM("(Unused)")
632 PHP_HTTP_STRLIST_ITEM("(Unused)")
633 PHP_HTTP_STRLIST_ITEM("(Unused)")
634 PHP_HTTP_STRLIST_ITEM("Unprocessible Entity")
635 PHP_HTTP_STRLIST_ITEM("Locked")
636 PHP_HTTP_STRLIST_ITEM("Failed Dependency")
637 PHP_HTTP_STRLIST_ITEM("(Reserved)")
638 PHP_HTTP_STRLIST_ITEM("Upgrade Required")
639 PHP_HTTP_STRLIST_ITEM("(Unused)")
640 PHP_HTTP_STRLIST_ITEM("Precondition Required")
641 PHP_HTTP_STRLIST_ITEM("Too Many Requests")
642 PHP_HTTP_STRLIST_ITEM("(Unused)")
643 PHP_HTTP_STRLIST_ITEM("Request Header Fields Too Large")
644 PHP_HTTP_STRLIST_NEXT
645 PHP_HTTP_STRLIST_ITEM("Internal Server Error")
646 PHP_HTTP_STRLIST_ITEM("Not Implemented")
647 PHP_HTTP_STRLIST_ITEM("Bad Gateway")
648 PHP_HTTP_STRLIST_ITEM("Service Unavailable")
649 PHP_HTTP_STRLIST_ITEM("Gateway Timeout")
650 PHP_HTTP_STRLIST_ITEM("HTTP Version Not Supported")
651 PHP_HTTP_STRLIST_ITEM("Variant Also Negotiates")
652 PHP_HTTP_STRLIST_ITEM("Insufficient Storage")
653 PHP_HTTP_STRLIST_ITEM("Loop Detected")
654 PHP_HTTP_STRLIST_ITEM("(Unused)")
655 PHP_HTTP_STRLIST_ITEM("Not Extended")
656 PHP_HTTP_STRLIST_ITEM("Network Authentication Required")
657 PHP_HTTP_STRLIST_STOP
660 const char *php_http_env_get_response_status_for_code(unsigned code
)
662 return php_http_strlist_find(php_http_env_response_status
, 100, code
);
665 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getRequestHeader
, 0, 0, 0)
666 ZEND_ARG_INFO(0, header_name
)
668 static PHP_METHOD(HttpEnv
, getRequestHeader
)
670 char *header_name_str
= NULL
;
671 size_t header_name_len
= 0;
673 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS(), "|s!", &header_name_str
, &header_name_len
)) {
676 if (header_name_str
&& header_name_len
) {
677 size_t header_length
;
678 char *header_value
= php_http_env_get_request_header(header_name_str
, header_name_len
, &header_length
, NULL
);
681 RETURN_STR(php_http_cs2zs(header_value
, header_length
));
684 array_init(return_value
);
685 php_http_env_get_request_headers(Z_ARRVAL_P(return_value
));
689 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getRequestBody
, 0, 0, 0)
690 ZEND_ARG_INFO(0, body_class_name
)
692 static PHP_METHOD(HttpEnv
, getRequestBody
)
694 php_http_message_body_t
*body
;
695 php_http_message_body_object_t
*body_obj
;
696 zend_class_entry
*class_entry
= php_http_message_body_class_entry
;
698 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &class_entry
), invalid_arg
, return);
700 body
= php_http_env_get_request_body();
701 if (SUCCESS
== php_http_new((void *) &body_obj
, class_entry
, (php_http_new_t
) php_http_message_body_object_new_ex
, php_http_message_body_class_entry
, body
)) {
702 php_http_message_body_addref(body
);
703 RETVAL_OBJ(&body_obj
->zo
);
707 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseStatusForCode
, 0, 0, 1)
708 ZEND_ARG_INFO(0, code
)
710 static PHP_METHOD(HttpEnv
, getResponseStatusForCode
)
714 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &code
)) {
717 RETURN_STRING(php_http_env_get_response_status_for_code(code
));
720 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseStatusForAllCodes
, 0, 0, 0)
722 static PHP_METHOD(HttpEnv
, getResponseStatusForAllCodes
)
726 php_http_strlist_iterator_t i
;
728 if (SUCCESS
!= zend_parse_parameters_none()) {
732 array_init(return_value
);
733 for ( php_http_strlist_iterator_init(&i
, php_http_env_response_status
, 100);
734 *(s
= php_http_strlist_iterator_this(&i
, &c
));
735 php_http_strlist_iterator_next(&i
)
737 add_index_string(return_value
, c
, s
);
741 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseHeader
, 0, 0, 0)
742 ZEND_ARG_INFO(0, header_name
)
744 static PHP_METHOD(HttpEnv
, getResponseHeader
)
746 char *header_name_str
= NULL
;
747 size_t header_name_len
= 0;
749 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS(), "|s!", &header_name_str
, &header_name_len
)) {
752 if (header_name_str
&& header_name_len
) {
753 char *header_value
= php_http_env_get_response_header(header_name_str
, header_name_len
);
756 RETURN_STR(php_http_cs2zs(header_value
, strlen(header_value
)));
759 array_init(return_value
);
760 php_http_env_get_response_headers(Z_ARRVAL_P(return_value
));
764 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseCode
, 0, 0, 0)
766 static PHP_METHOD(HttpEnv
, getResponseCode
)
768 if (SUCCESS
!= zend_parse_parameters_none()) {
771 RETURN_LONG(php_http_env_get_response_code());
774 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_setResponseHeader
, 0, 0, 1)
775 ZEND_ARG_INFO(0, header_name
)
776 ZEND_ARG_INFO(0, header_value
)
777 ZEND_ARG_INFO(0, response_code
)
778 ZEND_ARG_INFO(0, replace_header
)
780 static PHP_METHOD(HttpEnv
, setResponseHeader
)
782 char *header_name_str
;
783 size_t header_name_len
;
784 zval
*header_value
= NULL
;
786 zend_bool replace_header
= 1;
788 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS(), "s|z!lb", &header_name_str
, &header_name_len
, &header_value
, &code
, &replace_header
)) {
791 RETURN_BOOL(SUCCESS
== php_http_env_set_response_header_value(code
, header_name_str
, header_name_len
, header_value
, replace_header
));
794 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_setResponseCode
, 0, 0, 1)
795 ZEND_ARG_INFO(0, code
)
797 static PHP_METHOD(HttpEnv
, setResponseCode
)
801 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS(), "l", &code
)) {
804 RETURN_BOOL(SUCCESS
== php_http_env_set_response_code(code
));
807 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateLanguage
, 0, 0, 1)
808 ZEND_ARG_INFO(0, supported
)
809 ZEND_ARG_INFO(1, result_array
)
811 static PHP_METHOD(HttpEnv
, negotiateLanguage
)
813 HashTable
*supported
;
814 zval
*rs_array
= NULL
;
816 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
820 ZVAL_DEREF(rs_array
);
822 array_init(rs_array
);
825 PHP_HTTP_DO_NEGOTIATE(language
, supported
, rs_array
);
828 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateCharset
, 0, 0, 1)
829 ZEND_ARG_INFO(0, supported
)
830 ZEND_ARG_INFO(1, result_array
)
832 static PHP_METHOD(HttpEnv
, negotiateCharset
)
834 HashTable
*supported
;
835 zval
*rs_array
= NULL
;
837 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS(), "H|z", &supported
, &rs_array
)) {
841 ZVAL_DEREF(rs_array
);
843 array_init(rs_array
);
845 PHP_HTTP_DO_NEGOTIATE(charset
, supported
, rs_array
);
848 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateEncoding
, 0, 0, 1)
849 ZEND_ARG_INFO(0, supported
)
850 ZEND_ARG_INFO(1, result_array
)
852 static PHP_METHOD(HttpEnv
, negotiateEncoding
)
854 HashTable
*supported
;
855 zval
*rs_array
= NULL
;
857 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS(), "H|z", &supported
, &rs_array
)) {
861 ZVAL_DEREF(rs_array
);
863 array_init(rs_array
);
865 PHP_HTTP_DO_NEGOTIATE(encoding
, supported
, rs_array
);
868 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateContentType
, 0, 0, 1)
869 ZEND_ARG_INFO(0, supported
)
870 ZEND_ARG_INFO(1, result_array
)
872 static PHP_METHOD(HttpEnv
, negotiateContentType
)
874 HashTable
*supported
;
875 zval
*rs_array
= NULL
;
877 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS(), "H|z", &supported
, &rs_array
)) {
881 ZVAL_DEREF(rs_array
);
883 array_init(rs_array
);
885 PHP_HTTP_DO_NEGOTIATE(content_type
, supported
, rs_array
);
888 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiate
, 0, 0, 2)
889 ZEND_ARG_INFO(0, params
)
890 ZEND_ARG_INFO(0, supported
)
891 ZEND_ARG_INFO(0, primary_type_separator
)
892 ZEND_ARG_INFO(1, result_array
)
894 static PHP_METHOD(HttpEnv
, negotiate
)
896 HashTable
*supported
, *rs
;
897 zval
*rs_array
= NULL
;
898 char *value_str
, *sep_str
= NULL
;
899 size_t value_len
, sep_len
= 0;
901 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sH|s!z", &value_str
, &value_len
, &supported
, &sep_str
, &sep_len
, &rs_array
)) {
906 ZVAL_DEREF(rs_array
);
908 array_init(rs_array
);
911 if ((rs
= php_http_negotiate(value_str
, value_len
, supported
, sep_str
, sep_len
))) {
912 PHP_HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs
, supported
, rs_array
);
914 PHP_HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported
, rs_array
);
918 static zend_function_entry php_http_env_methods
[] = {
919 PHP_ME(HttpEnv
, getRequestHeader
, ai_HttpEnv_getRequestHeader
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
920 PHP_ME(HttpEnv
, getRequestBody
, ai_HttpEnv_getRequestBody
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
922 PHP_ME(HttpEnv
, getResponseStatusForCode
, ai_HttpEnv_getResponseStatusForCode
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
923 PHP_ME(HttpEnv
, getResponseStatusForAllCodes
, ai_HttpEnv_getResponseStatusForAllCodes
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
925 PHP_ME(HttpEnv
, getResponseHeader
, ai_HttpEnv_getResponseHeader
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
926 PHP_ME(HttpEnv
, getResponseCode
, ai_HttpEnv_getResponseCode
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
927 PHP_ME(HttpEnv
, setResponseHeader
, ai_HttpEnv_setResponseHeader
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
928 PHP_ME(HttpEnv
, setResponseCode
, ai_HttpEnv_setResponseCode
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
930 PHP_ME(HttpEnv
, negotiateLanguage
, ai_HttpEnv_negotiateLanguage
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
931 PHP_ME(HttpEnv
, negotiateContentType
, ai_HttpEnv_negotiateContentType
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
932 PHP_ME(HttpEnv
, negotiateEncoding
, ai_HttpEnv_negotiateEncoding
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
933 PHP_ME(HttpEnv
, negotiateCharset
, ai_HttpEnv_negotiateCharset
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
934 PHP_ME(HttpEnv
, negotiate
, ai_HttpEnv_negotiate
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
939 #ifdef PHP_HTTP_HAVE_JSON
940 #include "ext/json/php_json.h"
942 static SAPI_POST_HANDLER_FUNC(php_http_json_post_handler
)
945 zend_string
*json
= NULL
;
947 if (SG(request_info
).request_body
) {
948 /* FG(stream_wrappers) not initialized yet, so we cannot use php://input */
949 php_stream_rewind(SG(request_info
).request_body
);
950 json
= php_stream_copy_to_mem(SG(request_info
).request_body
, PHP_STREAM_COPY_ALL
, 0);
958 php_json_decode(&zjson
, json
->val
, json
->len
, 1, PG(max_input_nesting_level
));
959 if (Z_TYPE(zjson
) != IS_NULL
) {
961 ZVAL_COPY_VALUE(zarg
, (&zjson
));
964 zend_string_release(json
);
968 static void php_http_env_register_json_handler(void)
970 sapi_post_entry entry
= {NULL
, 0, NULL
, NULL
};
972 entry
.post_reader
= sapi_read_standard_form_data
;
973 entry
.post_handler
= php_http_json_post_handler
;
975 entry
.content_type
= "text/json";
976 entry
.content_type_len
= lenof("text/json");
977 sapi_register_post_entry(&entry
);
979 entry
.content_type
= "application/json";
980 entry
.content_type_len
= lenof("application/json");
981 sapi_register_post_entry(&entry
);
985 zend_class_entry
*php_http_env_class_entry
;
987 PHP_MINIT_FUNCTION(http_env
)
989 zend_class_entry ce
= {0};
991 INIT_NS_CLASS_ENTRY(ce
, "http", "Env", php_http_env_methods
);
992 php_http_env_class_entry
= zend_register_internal_class(&ce
);
994 #ifdef PHP_HTTP_HAVE_JSON
995 php_http_env_register_json_handler();
1007 * vim600: noet sw=4 ts=4 fdm=marker
1008 * vim<600: noet sw=4 ts=4