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-2011, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
13 #include "php_http_api.h"
14 #include "php_variables.h"
16 PHP_RINIT_FUNCTION(http_env
)
18 PHP_HTTP_G
->env
.request
.time
= sapi_get_request_time(TSRMLS_C
);
20 /* populate form data on non-POST requests */
21 if (SG(request_info
).request_method
&& strcasecmp(SG(request_info
).request_method
, "POST") && SG(request_info
).content_type
&& *SG(request_info
).content_type
) {
22 uint ct_len
= strlen(SG(request_info
).content_type
);
23 char *ct_str
= estrndup(SG(request_info
).content_type
, ct_len
);
24 php_http_params_opts_t opts
;
27 php_http_params_opts_default_get(&opts
);
28 opts
.input
.str
= ct_str
;
29 opts
.input
.len
= ct_len
;
31 SG(request_info
).content_type_dup
= ct_str
;
33 ZEND_INIT_SYMTABLE(¶ms
);
34 if (php_http_params_parse(¶ms
, &opts TSRMLS_CC
)) {
39 if (HASH_KEY_IS_STRING
== zend_hash_get_current_key_ex(¶ms
, &key_str
, &key_len
, &key_num
, 0, NULL
)) {
40 sapi_post_entry
*post_entry
= NULL
;
42 if (SUCCESS
== zend_hash_find(&SG(known_post_content_types
), key_str
, key_len
, (void *) &post_entry
)) {
43 zval
*files
= PG(http_globals
)[TRACK_VARS_FILES
];
45 zend_is_auto_global(ZEND_STRL("_POST") TSRMLS_CC
);
48 SG(request_info
).post_entry
= post_entry
;
50 if (post_entry
->post_reader
) {
51 post_entry
->post_reader(TSRMLS_C
);
55 if (sapi_module
.default_post_reader
) {
56 sapi_module
.default_post_reader(TSRMLS_C
);
59 sapi_handle_post(PG(http_globals
)[TRACK_VARS_POST
] TSRMLS_CC
);
62 * the rfc1867 handler is an awkward buddy
64 if (files
!= PG(http_globals
)[TRACK_VARS_FILES
] && PG(http_globals
)[TRACK_VARS_FILES
]) {
65 Z_ADDREF_P(PG(http_globals
)[TRACK_VARS_FILES
]);
66 zend_hash_update(&EG(symbol_table
), "_FILES", sizeof("_FILES"), &PG(http_globals
)[TRACK_VARS_FILES
], sizeof(zval
*), NULL
);
68 zval_ptr_dtor(&files
);
73 zend_hash_destroy(¶ms
);
77 STR_SET(SG(request_info
).content_type_dup
, NULL
);
82 PHP_RSHUTDOWN_FUNCTION(http_env
)
84 if (PHP_HTTP_G
->env
.request
.headers
) {
85 zend_hash_destroy(PHP_HTTP_G
->env
.request
.headers
);
86 FREE_HASHTABLE(PHP_HTTP_G
->env
.request
.headers
);
87 PHP_HTTP_G
->env
.request
.headers
= NULL
;
89 if (PHP_HTTP_G
->env
.request
.body
) {
90 php_http_message_body_free(&PHP_HTTP_G
->env
.request
.body
);
93 if (PHP_HTTP_G
->env
.server_var
) {
94 zval_ptr_dtor(&PHP_HTTP_G
->env
.server_var
);
95 PHP_HTTP_G
->env
.server_var
= NULL
;
101 PHP_HTTP_API
void php_http_env_get_request_headers(HashTable
*headers TSRMLS_DC
)
103 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
104 zval
**hsv
, **header
;
107 if (!PHP_HTTP_G
->env
.request
.headers
) {
108 ALLOC_HASHTABLE(PHP_HTTP_G
->env
.request
.headers
);
109 zend_hash_init(PHP_HTTP_G
->env
.request
.headers
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
111 zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC
);
113 if (SUCCESS
== zend_hash_find(&EG(symbol_table
), "_SERVER", sizeof("_SERVER"), (void *) &hsv
) && Z_TYPE_PP(hsv
) == IS_ARRAY
) {
114 FOREACH_KEY(pos
, *hsv
, key
) {
115 if (key
.type
== HASH_KEY_IS_STRING
&& key
.len
> 6 && *key
.str
== 'H' && !strncmp(key
.str
, "HTTP_", 5)) {
117 key
.str
= php_http_pretty_key(estrndup(key
.str
+ 5, key
.len
- 1), key
.len
- 1, 1, 1);
119 zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv
), (void *) &header
, &pos
);
121 zend_symtable_update(PHP_HTTP_G
->env
.request
.headers
, key
.str
, key
.len
, (void *) header
, sizeof(zval
*), NULL
);
124 } else if (key
.type
== HASH_KEY_IS_STRING
&& key
.len
> 9 && *key
.str
== 'C' && !strncmp(key
.str
, "CONTENT_", 8)) {
125 key
.str
= php_http_pretty_key(estrndup(key
.str
, key
.len
- 1), key
.len
- 1, 1, 1);
127 zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv
), (void *) &header
, &pos
);
129 zend_symtable_update(PHP_HTTP_G
->env
.request
.headers
, key
.str
, key
.len
, (void *) header
, sizeof(zval
*), NULL
);
138 zend_hash_copy(headers
, PHP_HTTP_G
->env
.request
.headers
, (copy_ctor_func_t
) zval_add_ref
, NULL
, sizeof(zval
*));
142 PHP_HTTP_API
char *php_http_env_get_request_header(const char *name_str
, size_t name_len
, size_t *len TSRMLS_DC
)
145 char *val
= NULL
, *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
147 php_http_env_get_request_headers(NULL TSRMLS_CC
);
149 if (SUCCESS
== zend_symtable_find(PHP_HTTP_G
->env
.request
.headers
, key
, name_len
+ 1, (void *) &zvalue
)) {
150 zval
*zcopy
= php_http_ztyp(IS_STRING
, *zvalue
);
152 val
= estrndup(Z_STRVAL_P(zcopy
), Z_STRLEN_P(zcopy
));
154 *len
= Z_STRLEN_P(zcopy
);
156 zval_ptr_dtor(&zcopy
);
164 PHP_HTTP_API
int php_http_env_got_request_header(const char *name_str
, size_t name_len TSRMLS_DC
)
166 char *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
169 php_http_env_get_request_headers(NULL TSRMLS_CC
);
170 got
= zend_symtable_exists(PHP_HTTP_G
->env
.request
.headers
, key
, name_len
+ 1);
176 PHP_HTTP_API zval
*php_http_env_get_superglobal(const char *key
, size_t key_len TSRMLS_DC
)
180 zend_is_auto_global(key
, key_len TSRMLS_CC
);
182 if ((SUCCESS
!= zend_hash_find(&EG(symbol_table
), key
, key_len
+ 1, (void *) &hsv
)) || (Z_TYPE_PP(hsv
) != IS_ARRAY
)) {
189 PHP_HTTP_API zval
*php_http_env_get_server_var(const char *key
, size_t key_len
, zend_bool check TSRMLS_DC
)
194 /* if available, this is a lot faster than accessing $_SERVER */
195 if (sapi_module
.getenv
) {
196 if ((!(env
= sapi_module
.getenv((char *) key
, key_len TSRMLS_CC
))) || (check
&& !*env
)) {
199 if (PHP_HTTP_G
->env
.server_var
) {
200 zval_ptr_dtor(&PHP_HTTP_G
->env
.server_var
);
202 MAKE_STD_ZVAL(PHP_HTTP_G
->env
.server_var
);
203 ZVAL_STRING(PHP_HTTP_G
->env
.server_var
, env
, 1);
204 return PHP_HTTP_G
->env
.server_var
;
207 if (!(hsv
= php_http_env_get_superglobal(ZEND_STRL("_SERVER") TSRMLS_CC
))) {
210 if ((SUCCESS
!= zend_symtable_find(Z_ARRVAL_P(hsv
), key
, key_len
+ 1, (void *) &var
))) {
213 if (check
&& !((Z_TYPE_PP(var
) == IS_STRING
) && Z_STRVAL_PP(var
) && Z_STRLEN_PP(var
))) {
219 PHP_HTTP_API php_http_message_body_t
*php_http_env_get_request_body(TSRMLS_D
)
221 if (!PHP_HTTP_G
->env
.request
.body
) {
222 php_stream
*s
= NULL
;
224 if (SG(request_info
).post_data
|| SG(request_info
).raw_post_data
) {
225 if ((s
= php_stream_temp_new())) {
226 /* php://input does not support seek() */
227 if (SG(request_info
).raw_post_data
) {
228 php_stream_write(s
, SG(request_info
).raw_post_data
, SG(request_info
).raw_post_data_length
);
230 php_stream_write(s
, SG(request_info
).post_data
, SG(request_info
).post_data_length
);
232 php_stream_rewind(s
);
234 } else if (sapi_module
.read_post
&& !SG(read_post_bytes
)) {
235 if ((s
= php_stream_temp_new())) {
236 char *buf
= emalloc(4096);
239 while (0 < (len
= sapi_module
.read_post(buf
, 4096 TSRMLS_CC
))) {
240 SG(read_post_bytes
) += len
;
241 php_stream_write(s
, buf
, len
);
249 php_stream_rewind(s
);
252 PHP_HTTP_G
->env
.request
.body
= php_http_message_body_init(NULL
, s TSRMLS_CC
);
255 return PHP_HTTP_G
->env
.request
.body
;
258 PHP_HTTP_API php_http_range_status_t
php_http_env_get_request_ranges(HashTable
*ranges
, size_t length TSRMLS_DC
)
262 long begin
= -1, end
= -1, *ptr
;
264 if (!(range
= php_http_env_get_request_header(ZEND_STRL("Range"), NULL TSRMLS_CC
))) {
265 return PHP_HTTP_RANGE_NO
;
267 if (strncmp(range
, "bytes=", lenof("bytes="))) {
269 return PHP_HTTP_RANGE_NO
;
272 rp
= range
+ lenof("bytes=");
276 switch (c
= *(rp
++)) {
278 /* allow 000... - shall we? */
284 case '1': case '2': case '3':
285 case '4': case '5': case '6':
286 case '7': case '8': case '9':
288 * If the value of the pointer is already set (non-negative)
289 * then multiply its value by ten and add the current value,
290 * else initialise the pointers value with the current value
292 * This let us recognize empty fields when validating the
293 * ranges, i.e. a "-10" for begin and "12345" for the end
294 * was the following range request: "Range: bytes=0-12345";
295 * While a "-1" for begin and "12345" for the end would
296 * have been: "Range: bytes=-12345".
317 /* validate ranges */
325 return PHP_HTTP_RANGE_NO
;
333 if (length
<= (size_t) end
) {
344 if (end
== -1 || end
== -10) {
346 return PHP_HTTP_RANGE_ERR
;
348 begin
= length
- end
;
354 if (length
<= (size_t) begin
) {
356 return PHP_HTTP_RANGE_ERR
;
362 return PHP_HTTP_RANGE_ERR
;
371 if (length
<= (size_t) end
) {
373 } else if (end
< begin
) {
375 return PHP_HTTP_RANGE_ERR
;
383 MAKE_STD_ZVAL(zentry
);
385 add_index_long(zentry
, 0, begin
);
386 add_index_long(zentry
, 1, end
);
387 zend_hash_next_index_insert(ranges
, &zentry
, sizeof(zval
*), NULL
);
397 return PHP_HTTP_RANGE_NO
;
402 return PHP_HTTP_RANGE_OK
;
405 static void grab_headers(void *data
, void *arg TSRMLS_DC
)
407 php_http_buffer_appendl(PHP_HTTP_BUFFER(arg
), ((sapi_header_struct
*)data
)->header
);
408 php_http_buffer_appends(PHP_HTTP_BUFFER(arg
), PHP_HTTP_CRLF
);
411 PHP_HTTP_API STATUS
php_http_env_get_response_headers(HashTable
*headers_ht TSRMLS_DC
)
414 php_http_buffer_t headers
;
416 php_http_buffer_init(&headers
);
417 zend_llist_apply_with_argument(&SG(sapi_headers
).headers
, grab_headers
, &headers TSRMLS_CC
);
418 php_http_buffer_fix(&headers
);
420 status
= php_http_headers_parse(headers
.data
, headers
.used
, headers_ht
, NULL
, NULL TSRMLS_CC
);
421 php_http_buffer_dtor(&headers
);
426 PHP_HTTP_API
char *php_http_env_get_response_header(const char *name_str
, size_t name_len TSRMLS_DC
)
431 zend_hash_init(&headers
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
432 if (SUCCESS
== php_http_env_get_response_headers(&headers TSRMLS_CC
)) {
434 char *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
436 if (SUCCESS
== zend_symtable_find(&headers
, key
, name_len
+ 1, (void *) &zvalue
)) {
437 zval
*zcopy
= php_http_ztyp(IS_STRING
, *zvalue
);
439 val
= estrndup(Z_STRVAL_P(zcopy
), Z_STRLEN_P(zcopy
));
440 zval_ptr_dtor(&zcopy
);
445 zend_hash_destroy(&headers
);
450 PHP_HTTP_API
long php_http_env_get_response_code(TSRMLS_D
)
452 long code
= SG(sapi_headers
).http_response_code
;
453 return code
? code
: 200;
456 PHP_HTTP_API STATUS
php_http_env_set_response_code(long http_code TSRMLS_DC
)
458 return sapi_header_op(SAPI_HEADER_SET_STATUS
, (void *) http_code TSRMLS_CC
);
461 PHP_HTTP_API STATUS
php_http_env_set_response_status_line(long code
, php_http_version_t
*v TSRMLS_DC
)
463 sapi_header_line h
= {NULL
, 0, 0};
466 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
));
467 ret
= sapi_header_op(SAPI_HEADER_REPLACE
, (void *) &h TSRMLS_CC
);
473 PHP_HTTP_API STATUS
php_http_env_set_response_protocol_version(php_http_version_t
*v TSRMLS_DC
)
475 return php_http_env_set_response_status_line(php_http_env_get_response_code(TSRMLS_C
), v TSRMLS_CC
);
478 PHP_HTTP_API STATUS
php_http_env_set_response_header(long http_code
, const char *header_str
, size_t header_len
, zend_bool replace TSRMLS_DC
)
480 sapi_header_line h
= {estrndup(header_str
, header_len
), header_len
, http_code
};
481 STATUS ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h TSRMLS_CC
);
486 PHP_HTTP_API STATUS
php_http_env_set_response_header_format(long http_code
, zend_bool replace TSRMLS_DC
, const char *fmt
, ...)
489 STATUS ret
= FAILURE
;
490 sapi_header_line h
= {NULL
, 0, http_code
};
493 h
.line_len
= vspprintf(&h
.line
, 0, fmt
, args
);
498 ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h TSRMLS_CC
);
505 PHP_HTTP_API 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
)
508 sapi_header_line h
= {(char *) name_str
, name_len
, http_code
};
510 return sapi_header_op(SAPI_HEADER_DELETE
, (void *) &h TSRMLS_CC
);
513 if(Z_TYPE_P(value
) == IS_ARRAY
|| Z_TYPE_P(value
) == IS_OBJECT
) {
518 FOREACH_HASH_VAL(pos
, HASH_OF(value
), data_ptr
) {
519 if (SUCCESS
!= php_http_env_set_response_header_value(http_code
, name_str
, name_len
, *data_ptr
, first TSRMLS_CC
)) {
527 zval
*data
= php_http_ztyp(IS_STRING
, value
);
529 if (!Z_STRLEN_P(data
)) {
530 zval_ptr_dtor(&data
);
531 return php_http_env_set_response_header_value(http_code
, name_str
, name_len
, NULL
, replace TSRMLS_CC
);
536 if (name_len
> INT_MAX
) {
539 h
.response_code
= http_code
;
540 h
.line_len
= spprintf(&h
.line
, 0, "%.*s: %.*s", (int) name_len
, name_str
, Z_STRLEN_P(data
), Z_STRVAL_P(data
));
542 ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h TSRMLS_CC
);
544 zval_ptr_dtor(&data
);
553 static PHP_HTTP_STRLIST(php_http_env_response_status
) =
554 PHP_HTTP_STRLIST_ITEM("Continue")
555 PHP_HTTP_STRLIST_ITEM("Switching Protocols")
556 PHP_HTTP_STRLIST_ITEM("Processing")
557 PHP_HTTP_STRLIST_NEXT
558 PHP_HTTP_STRLIST_ITEM("OK")
559 PHP_HTTP_STRLIST_ITEM("Created")
560 PHP_HTTP_STRLIST_ITEM("Accepted")
561 PHP_HTTP_STRLIST_ITEM("Non-Authoritative Information")
562 PHP_HTTP_STRLIST_ITEM("No Content")
563 PHP_HTTP_STRLIST_ITEM("Reset Content")
564 PHP_HTTP_STRLIST_ITEM("Partial Content")
565 PHP_HTTP_STRLIST_ITEM("Multi-Status")
566 PHP_HTTP_STRLIST_ITEM("Already Reported")
567 PHP_HTTP_STRLIST_ITEM("(Unused)")
568 PHP_HTTP_STRLIST_ITEM("(Unused)")
569 PHP_HTTP_STRLIST_ITEM("(Unused)")
570 PHP_HTTP_STRLIST_ITEM("(Unused)")
571 PHP_HTTP_STRLIST_ITEM("(Unused)")
572 PHP_HTTP_STRLIST_ITEM("(Unused)")
573 PHP_HTTP_STRLIST_ITEM("(Unused)")
574 PHP_HTTP_STRLIST_ITEM("(Unused)")
575 PHP_HTTP_STRLIST_ITEM("(Unused)")
576 PHP_HTTP_STRLIST_ITEM("(Unused)")
577 PHP_HTTP_STRLIST_ITEM("(Unused)")
578 PHP_HTTP_STRLIST_ITEM("(Unused)")
579 PHP_HTTP_STRLIST_ITEM("(Unused)")
580 PHP_HTTP_STRLIST_ITEM("(Unused)")
581 PHP_HTTP_STRLIST_ITEM("(Unused)")
582 PHP_HTTP_STRLIST_ITEM("(Unused)")
583 PHP_HTTP_STRLIST_ITEM("(Unused)")
584 PHP_HTTP_STRLIST_ITEM("IM Used")
585 PHP_HTTP_STRLIST_NEXT
586 PHP_HTTP_STRLIST_ITEM("Multiple Choices")
587 PHP_HTTP_STRLIST_ITEM("Moved Permanently")
588 PHP_HTTP_STRLIST_ITEM("Found")
589 PHP_HTTP_STRLIST_ITEM("See Other")
590 PHP_HTTP_STRLIST_ITEM("Not Modified")
591 PHP_HTTP_STRLIST_ITEM("Use Proxy")
592 PHP_HTTP_STRLIST_ITEM("(Unused)")
593 PHP_HTTP_STRLIST_ITEM("Temporary Redirect")
594 PHP_HTTP_STRLIST_ITEM("Permanent Redirect")
595 PHP_HTTP_STRLIST_NEXT
596 PHP_HTTP_STRLIST_ITEM("Bad Request")
597 PHP_HTTP_STRLIST_ITEM("Unauthorized")
598 PHP_HTTP_STRLIST_ITEM("Payment Required")
599 PHP_HTTP_STRLIST_ITEM("Forbidden")
600 PHP_HTTP_STRLIST_ITEM("Not Found")
601 PHP_HTTP_STRLIST_ITEM("Method Not Allowed")
602 PHP_HTTP_STRLIST_ITEM("Not Acceptable")
603 PHP_HTTP_STRLIST_ITEM("Proxy Authentication Required")
604 PHP_HTTP_STRLIST_ITEM("Request Timeout")
605 PHP_HTTP_STRLIST_ITEM("Conflict")
606 PHP_HTTP_STRLIST_ITEM("Gone")
607 PHP_HTTP_STRLIST_ITEM("Length Required")
608 PHP_HTTP_STRLIST_ITEM("Precondition Failed")
609 PHP_HTTP_STRLIST_ITEM("Request Entity Too Large")
610 PHP_HTTP_STRLIST_ITEM("Request URI Too Long")
611 PHP_HTTP_STRLIST_ITEM("Unsupported Media Type")
612 PHP_HTTP_STRLIST_ITEM("Requested Range Not Satisfiable")
613 PHP_HTTP_STRLIST_ITEM("Expectation Failed")
614 PHP_HTTP_STRLIST_ITEM("(Unused)")
615 PHP_HTTP_STRLIST_ITEM("(Unused)")
616 PHP_HTTP_STRLIST_ITEM("(Unused)")
617 PHP_HTTP_STRLIST_ITEM("(Unused)")
618 PHP_HTTP_STRLIST_ITEM("Unprocessible Entity")
619 PHP_HTTP_STRLIST_ITEM("Locked")
620 PHP_HTTP_STRLIST_ITEM("Failed Dependency")
621 PHP_HTTP_STRLIST_ITEM("(Reserved)")
622 PHP_HTTP_STRLIST_ITEM("Upgrade Required")
623 PHP_HTTP_STRLIST_ITEM("(Unused)")
624 PHP_HTTP_STRLIST_ITEM("Precondition Required")
625 PHP_HTTP_STRLIST_ITEM("Too Many Requests")
626 PHP_HTTP_STRLIST_ITEM("(Unused)")
627 PHP_HTTP_STRLIST_ITEM("Request Header Fields Too Large")
628 PHP_HTTP_STRLIST_NEXT
629 PHP_HTTP_STRLIST_ITEM("Internal Server Error")
630 PHP_HTTP_STRLIST_ITEM("Not Implemented")
631 PHP_HTTP_STRLIST_ITEM("Bad Gateway")
632 PHP_HTTP_STRLIST_ITEM("Service Unavailable")
633 PHP_HTTP_STRLIST_ITEM("Gateway Timeout")
634 PHP_HTTP_STRLIST_ITEM("HTTP Version Not Supported")
635 PHP_HTTP_STRLIST_ITEM("Variant Also Negotiates")
636 PHP_HTTP_STRLIST_ITEM("Insufficient Storage")
637 PHP_HTTP_STRLIST_ITEM("Loop Detected")
638 PHP_HTTP_STRLIST_ITEM("(Unused)")
639 PHP_HTTP_STRLIST_ITEM("Not Extended")
640 PHP_HTTP_STRLIST_ITEM("Network Authentication Required")
641 PHP_HTTP_STRLIST_STOP
644 PHP_HTTP_API
const char *php_http_env_get_response_status_for_code(unsigned code
)
646 return php_http_strlist_find(php_http_env_response_status
, 100, code
);
650 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpEnv, method, 0, req_args)
651 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpEnv, method, 0)
652 #define PHP_HTTP_ENV_ME(method) PHP_ME(HttpEnv, method, PHP_HTTP_ARGS(HttpEnv, method), ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
654 PHP_HTTP_BEGIN_ARGS(getRequestHeader
, 0)
655 PHP_HTTP_ARG_VAL(header_name
, 0)
658 PHP_HTTP_BEGIN_ARGS(getRequestBody
, 0)
659 PHP_HTTP_ARG_VAL(body_class_name
, 0)
662 PHP_HTTP_BEGIN_ARGS(getResponseStatusForCode
, 1)
663 PHP_HTTP_ARG_VAL(code
, 0)
666 PHP_HTTP_EMPTY_ARGS(getResponseStatusForAllCodes
);
668 PHP_HTTP_BEGIN_ARGS(getResponseHeader
, 0)
669 PHP_HTTP_ARG_VAL(header_name
, 0)
672 PHP_HTTP_EMPTY_ARGS(getResponseCode
);
674 PHP_HTTP_BEGIN_ARGS(setResponseHeader
, 1)
675 PHP_HTTP_ARG_VAL(header_name
, 0)
676 PHP_HTTP_ARG_VAL(header_value
, 0)
677 PHP_HTTP_ARG_VAL(response_code
, 0)
678 PHP_HTTP_ARG_VAL(replace_header
, 0)
681 PHP_HTTP_BEGIN_ARGS(setResponseCode
, 1)
682 PHP_HTTP_ARG_VAL(code
, 0)
685 PHP_HTTP_BEGIN_ARGS(negotiateLanguage
, 1)
686 PHP_HTTP_ARG_VAL(supported
, 0)
687 PHP_HTTP_ARG_VAL(result_array
, 1)
690 PHP_HTTP_BEGIN_ARGS(negotiateContentType
, 1)
691 PHP_HTTP_ARG_VAL(supported
, 0)
692 PHP_HTTP_ARG_VAL(result_array
, 1)
695 PHP_HTTP_BEGIN_ARGS(negotiateCharset
, 1)
696 PHP_HTTP_ARG_VAL(supported
, 0)
697 PHP_HTTP_ARG_VAL(result_array
, 1)
700 PHP_HTTP_BEGIN_ARGS(negotiateEncoding
, 1)
701 PHP_HTTP_ARG_VAL(supported
, 0)
702 PHP_HTTP_ARG_VAL(result_array
, 1)
705 PHP_HTTP_BEGIN_ARGS(negotiate
, 2)
706 PHP_HTTP_ARG_VAL(value
, 0)
707 PHP_HTTP_ARG_VAL(supported
, 0)
708 PHP_HTTP_ARG_VAL(primary_type_separator
, 0)
709 PHP_HTTP_ARG_VAL(result_array
, 1)
712 PHP_HTTP_EMPTY_ARGS(statPersistentHandles
);
714 PHP_HTTP_BEGIN_ARGS(cleanPersistentHandles
, 0)
715 PHP_HTTP_ARG_VAL(name
, 0)
716 PHP_HTTP_ARG_VAL(ident
, 0)
719 static zend_class_entry
*php_http_env_class_entry
;
721 zend_class_entry
*php_http_env_get_class_entry(void)
723 return php_http_env_class_entry
;
726 static zend_function_entry php_http_env_method_entry
[] = {
727 PHP_HTTP_ENV_ME(getRequestHeader
)
728 PHP_HTTP_ENV_ME(getRequestBody
)
730 PHP_HTTP_ENV_ME(getResponseStatusForCode
)
731 PHP_HTTP_ENV_ME(getResponseStatusForAllCodes
)
733 PHP_HTTP_ENV_ME(getResponseHeader
)
734 PHP_HTTP_ENV_ME(getResponseCode
)
735 PHP_HTTP_ENV_ME(setResponseHeader
)
736 PHP_HTTP_ENV_ME(setResponseCode
)
738 PHP_HTTP_ENV_ME(negotiateLanguage
)
739 PHP_HTTP_ENV_ME(negotiateContentType
)
740 PHP_HTTP_ENV_ME(negotiateEncoding
)
741 PHP_HTTP_ENV_ME(negotiateCharset
)
742 PHP_HTTP_ENV_ME(negotiate
)
744 PHP_HTTP_ENV_ME(statPersistentHandles
)
745 PHP_HTTP_ENV_ME(cleanPersistentHandles
)
750 PHP_METHOD(HttpEnv
, getRequestHeader
)
752 char *header_name_str
= NULL
;
753 int header_name_len
= 0;
755 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s!", &header_name_str
, &header_name_len
)) {
756 if (header_name_str
&& header_name_len
) {
757 size_t header_length
;
758 char *header_value
= php_http_env_get_request_header(header_name_str
, header_name_len
, &header_length TSRMLS_CC
);
761 RETURN_STRINGL(header_value
, header_length
, 0);
765 array_init(return_value
);
766 php_http_env_get_request_headers(Z_ARRVAL_P(return_value
) TSRMLS_CC
);
773 PHP_METHOD(HttpEnv
, getRequestBody
)
775 with_error_handling(EH_THROW
, php_http_exception_get_class_entry()) {
776 zend_class_entry
*class_entry
= php_http_message_body_get_class_entry();
778 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|C", &class_entry
)) {
779 zend_object_value ov
;
780 php_http_message_body_t
*body
= php_http_env_get_request_body(TSRMLS_C
);
782 if (SUCCESS
== php_http_new(&ov
, class_entry
, (php_http_new_t
) php_http_message_body_object_new_ex
, php_http_message_body_get_class_entry(), php_http_message_body_copy(body
, NULL
, 0), NULL TSRMLS_CC
)) {
783 RETVAL_OBJVAL(ov
, 0);
786 } end_error_handling();
789 PHP_METHOD(HttpEnv
, getResponseStatusForCode
)
793 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &code
)) {
794 RETURN_STRING(php_http_env_get_response_status_for_code(code
), 1);
799 PHP_METHOD(HttpEnv
, getResponseStatusForAllCodes
)
803 php_http_strlist_iterator_t i
;
805 if (SUCCESS
!= zend_parse_parameters_none()) {
809 array_init(return_value
);
810 for ( php_http_strlist_iterator_init(&i
, php_http_env_response_status
, 100);
811 *(s
= php_http_strlist_iterator_this(&i
, &c
));
812 php_http_strlist_iterator_next(&i
)
814 add_index_string(return_value
, c
, s
, 1);
818 PHP_METHOD(HttpEnv
, getResponseHeader
)
820 char *header_name_str
= NULL
;
821 int header_name_len
= 0;
823 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s!", &header_name_str
, &header_name_len
)) {
824 if (header_name_str
&& header_name_len
) {
825 char *header_value
= php_http_env_get_response_header(header_name_str
, header_name_len TSRMLS_CC
);
828 RETURN_STRING(header_value
, 0);
832 array_init(return_value
);
833 php_http_env_get_response_headers(Z_ARRVAL_P(return_value
) TSRMLS_CC
);
840 PHP_METHOD(HttpEnv
, getResponseCode
)
842 if (SUCCESS
== zend_parse_parameters_none()) {
843 RETURN_LONG(php_http_env_get_response_code(TSRMLS_C
));
848 PHP_METHOD(HttpEnv
, setResponseHeader
)
850 char *header_name_str
;
852 zval
*header_value
= NULL
;
854 zend_bool replace_header
= 1;
856 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|z!lb", &header_name_str
, &header_name_len
, &header_value
, &code
, &replace_header
)) {
857 RETURN_SUCCESS(php_http_env_set_response_header_value(code
, header_name_str
, header_name_len
, header_value
, replace_header TSRMLS_CC
));
862 PHP_METHOD(HttpEnv
, setResponseCode
)
866 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &code
)) {
867 RETURN_SUCCESS(php_http_env_set_response_code(code TSRMLS_CC
));
872 PHP_METHOD(HttpEnv
, negotiateLanguage
)
874 HashTable
*supported
;
875 zval
*rs_array
= NULL
;
877 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
880 array_init(rs_array
);
883 PHP_HTTP_DO_NEGOTIATE(language
, supported
, rs_array
);
889 PHP_METHOD(HttpEnv
, negotiateCharset
)
891 HashTable
*supported
;
892 zval
*rs_array
= NULL
;
894 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
897 array_init(rs_array
);
899 PHP_HTTP_DO_NEGOTIATE(charset
, supported
, rs_array
);
905 PHP_METHOD(HttpEnv
, negotiateEncoding
)
907 HashTable
*supported
;
908 zval
*rs_array
= NULL
;
910 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
913 array_init(rs_array
);
915 PHP_HTTP_DO_NEGOTIATE(encoding
, supported
, rs_array
);
921 PHP_METHOD(HttpEnv
, negotiateContentType
)
923 HashTable
*supported
;
924 zval
*rs_array
= NULL
;
926 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
929 array_init(rs_array
);
931 PHP_HTTP_DO_NEGOTIATE(content_type
, supported
, rs_array
);
937 PHP_METHOD(HttpEnv
, negotiate
)
939 HashTable
*supported
;
940 zval
*rs_array
= NULL
;
941 char *value_str
, *sep_str
= NULL
;
942 int value_len
, sep_len
= 0;
944 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sH|s!z", &value_str
, &value_len
, &supported
, &sep_str
, &sep_len
, &rs_array
)) {
949 array_init(rs_array
);
952 if ((rs
= php_http_negotiate(value_str
, value_len
, supported
, sep_str
, sep_len TSRMLS_CC
))) {
953 PHP_HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs
, supported
, rs_array
);
955 PHP_HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported
, rs_array
);
962 PHP_METHOD(HttpEnv
, statPersistentHandles
)
964 if (SUCCESS
== zend_parse_parameters_none()) {
965 object_init(return_value
);
966 if (php_http_persistent_handle_statall(HASH_OF(return_value
) TSRMLS_CC
)) {
969 zval_dtor(return_value
);
974 PHP_METHOD(HttpEnv
, cleanPersistentHandles
)
976 char *name_str
= NULL
, *ident_str
= NULL
;
977 int name_len
= 0, ident_len
= 0;
979 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s!s!", &name_str
, &name_len
, &ident_str
, &ident_len
)) {
980 php_http_persistent_handle_cleanup(name_str
, name_len
, ident_str
, ident_len TSRMLS_CC
);
984 #ifdef PHP_HTTP_HAVE_JSON
985 #include "ext/json/php_json.h"
987 static SAPI_POST_HANDLER_FUNC(php_http_json_post_handler
)
989 if (SG(request_info
).raw_post_data
) {
990 php_json_decode(arg
, SG(request_info
).raw_post_data
, SG(request_info
).raw_post_data_length
, 1, PG(max_input_nesting_level
) TSRMLS_CC
);
996 PHP_MINIT_FUNCTION(http_env
)
998 #ifdef PHP_HTTP_HAVE_JSON
999 sapi_post_entry entry
= {NULL
, 0, NULL
, NULL
};
1001 entry
.post_reader
= sapi_read_standard_form_data
;
1002 entry
.post_handler
= php_http_json_post_handler
;
1004 entry
.content_type
= "text/json";
1005 entry
.content_type_len
= lenof("text/json");
1006 sapi_register_post_entry(&entry TSRMLS_CC
);
1008 entry
.content_type
= "application/json";
1009 entry
.content_type_len
= lenof("application/json");
1010 sapi_register_post_entry(&entry TSRMLS_CC
);
1013 PHP_HTTP_REGISTER_CLASS(http
, Env
, http_env
, NULL
, 0);
1024 * vim600: noet sw=4 ts=4 fdm=marker
1025 * vim<600: noet sw=4 ts=4