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-2010, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
17 #include <main/SAPI.h>
19 PHP_RINIT_FUNCTION(http_env
)
21 PHP_HTTP_G
->env
.request
.time
= sapi_get_request_time(TSRMLS_C
);
26 PHP_RSHUTDOWN_FUNCTION(http_env
)
28 if (PHP_HTTP_G
->env
.request
.headers
) {
29 zend_hash_destroy(PHP_HTTP_G
->env
.request
.headers
);
30 FREE_HASHTABLE(PHP_HTTP_G
->env
.request
.headers
);
31 PHP_HTTP_G
->env
.request
.headers
= NULL
;
33 if (PHP_HTTP_G
->env
.request
.body
) {
34 php_http_message_body_free(&PHP_HTTP_G
->env
.request
.body
);
37 if (PHP_HTTP_G
->env
.server_var
) {
38 zval_ptr_dtor(&PHP_HTTP_G
->env
.server_var
);
39 PHP_HTTP_G
->env
.server_var
= NULL
;
45 PHP_HTTP_API
void php_http_env_get_request_headers(HashTable
*headers TSRMLS_DC
)
47 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
51 if (!PHP_HTTP_G
->env
.request
.headers
) {
52 ALLOC_HASHTABLE(PHP_HTTP_G
->env
.request
.headers
);
53 zend_hash_init(PHP_HTTP_G
->env
.request
.headers
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
55 zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC
);
57 if (SUCCESS
== zend_hash_find(&EG(symbol_table
), "_SERVER", sizeof("_SERVER"), (void *) &hsv
) && Z_TYPE_PP(hsv
) == IS_ARRAY
) {
58 FOREACH_KEY(pos
, *hsv
, key
) {
59 if (key
.type
== HASH_KEY_IS_STRING
&& key
.len
> 6 && !strncmp(key
.str
, "HTTP_", 5)) {
61 key
.str
= php_http_pretty_key(estrndup(key
.str
+ 5, key
.len
- 1), key
.len
- 1, 1, 1);
63 zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv
), (void *) &header
, &pos
);
65 zend_hash_add(PHP_HTTP_G
->env
.request
.headers
, key
.str
, key
.len
, (void *) header
, sizeof(zval
*), NULL
);
74 zend_hash_copy(headers
, PHP_HTTP_G
->env
.request
.headers
, (copy_ctor_func_t
) zval_add_ref
, NULL
, sizeof(zval
*));
78 PHP_HTTP_API
char *php_http_env_get_request_header(const char *name_str
, size_t name_len TSRMLS_DC
)
81 char *val
= NULL
, *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
83 php_http_env_get_request_headers(NULL TSRMLS_CC
);
85 if (SUCCESS
== zend_hash_find(PHP_HTTP_G
->env
.request
.headers
, key
, name_len
+ 1, (void *) &zvalue
)) {
86 zval
*zcopy
= php_http_ztyp(IS_STRING
, *zvalue
);
88 val
= estrndup(Z_STRVAL_P(zcopy
), Z_STRLEN_P(zcopy
));
89 zval_ptr_dtor(&zcopy
);
97 PHP_HTTP_API
int php_http_env_got_request_header(const char *name_str
, size_t name_len TSRMLS_DC
)
99 char *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
102 php_http_env_get_request_headers(NULL TSRMLS_CC
);
103 got
= zend_hash_exists(PHP_HTTP_G
->env
.request
.headers
, key
, name_len
+ 1);
109 PHP_HTTP_API zval
*php_http_env_get_server_var(const char *key
, size_t key_len
, zend_bool check TSRMLS_DC
)
114 /* if available, this is a lot faster than accessing $_SERVER */
115 if (sapi_module
.getenv
) {
116 if ((!(env
= sapi_module
.getenv((char *) key
, key_len TSRMLS_CC
))) || (check
&& !*env
)) {
119 if (PHP_HTTP_G
->env
.server_var
) {
120 zval_ptr_dtor(&PHP_HTTP_G
->env
.server_var
);
122 MAKE_STD_ZVAL(PHP_HTTP_G
->env
.server_var
);
123 ZVAL_STRING(PHP_HTTP_G
->env
.server_var
, env
, 1);
124 return PHP_HTTP_G
->env
.server_var
;
127 zend_is_auto_global(ZEND_STRL("_SERVER") TSRMLS_CC
);
129 if ((SUCCESS
!= zend_hash_find(&EG(symbol_table
), ZEND_STRS("_SERVER"), (void *) &hsv
)) || (Z_TYPE_PP(hsv
) != IS_ARRAY
)) {
132 if ((SUCCESS
!= zend_hash_find(Z_ARRVAL_PP(hsv
), key
, key_len
+ 1, (void *) &var
))) {
135 if (check
&& !((Z_TYPE_PP(var
) == IS_STRING
) && Z_STRVAL_PP(var
) && Z_STRLEN_PP(var
))) {
141 PHP_HTTP_API php_http_message_body_t
*php_http_env_get_request_body(TSRMLS_D
)
143 if (!PHP_HTTP_G
->env
.request
.body
) {
144 php_stream
*s
= NULL
;
146 if (SG(request_info
).post_data
|| SG(request_info
).raw_post_data
) {
147 if ((s
= php_stream_temp_new())) {
148 /* php://input does not support seek() */
149 if (SG(request_info
).raw_post_data
) {
150 php_stream_write(s
, SG(request_info
).raw_post_data
, SG(request_info
).raw_post_data_length
);
152 php_stream_write(s
, SG(request_info
).post_data
, SG(request_info
).post_data_length
);
154 php_stream_rewind(s
);
156 } else if (sapi_module
.read_post
&& !SG(read_post_bytes
)) {
157 if ((s
= php_stream_temp_new())) {
158 char *buf
= emalloc(4096);
161 while (0 < (len
= sapi_module
.read_post(buf
, 4096 TSRMLS_CC
))) {
162 SG(read_post_bytes
) += len
;
163 php_stream_write(s
, buf
, len
);
171 php_stream_rewind(s
);
174 PHP_HTTP_G
->env
.request
.body
= php_http_message_body_init(NULL
, s TSRMLS_CC
);
177 return PHP_HTTP_G
->env
.request
.body
;
180 PHP_HTTP_API php_http_range_status_t
php_http_env_get_request_ranges(HashTable
*ranges
, size_t length TSRMLS_DC
)
184 long begin
= -1, end
= -1, *ptr
;
186 if (!(range
= php_http_env_get_request_header(ZEND_STRL("Range") TSRMLS_CC
))) {
187 return PHP_HTTP_RANGE_NO
;
189 if (strncmp(range
, "bytes=", lenof("bytes="))) {
191 return PHP_HTTP_RANGE_NO
;
194 rp
= range
+ lenof("bytes=");
198 switch (c
= *(rp
++)) {
200 /* allow 000... - shall we? */
206 case '1': case '2': case '3':
207 case '4': case '5': case '6':
208 case '7': case '8': case '9':
210 * If the value of the pointer is already set (non-negative)
211 * then multiply its value by ten and add the current value,
212 * else initialise the pointers value with the current value
214 * This let us recognize empty fields when validating the
215 * ranges, i.e. a "-10" for begin and "12345" for the end
216 * was the following range request: "Range: bytes=0-12345";
217 * While a "-1" for begin and "12345" for the end would
218 * have been: "Range: bytes=-12345".
239 /* validate ranges */
247 return PHP_HTTP_RANGE_NO
;
255 if (length
<= (size_t) end
) {
266 if (end
== -1 || end
== -10) {
268 return PHP_HTTP_RANGE_ERR
;
270 begin
= length
- end
;
276 if (length
<= (size_t) begin
) {
278 return PHP_HTTP_RANGE_ERR
;
284 return PHP_HTTP_RANGE_ERR
;
293 if (length
<= (size_t) end
) {
295 } else if (end
< begin
) {
297 return PHP_HTTP_RANGE_ERR
;
305 MAKE_STD_ZVAL(zentry
);
307 add_index_long(zentry
, 0, begin
);
308 add_index_long(zentry
, 1, end
);
309 zend_hash_next_index_insert(ranges
, &zentry
, sizeof(zval
*), NULL
);
319 return PHP_HTTP_RANGE_NO
;
324 return PHP_HTTP_RANGE_OK
;
327 static void grab_headers(void *data
, void *arg TSRMLS_DC
)
329 php_http_buffer_appendl(PHP_HTTP_BUFFER(arg
), ((sapi_header_struct
*)data
)->header
);
330 php_http_buffer_appends(PHP_HTTP_BUFFER(arg
), PHP_HTTP_CRLF
);
333 PHP_HTTP_API STATUS
php_http_env_get_response_headers(HashTable
*headers_ht TSRMLS_DC
)
336 php_http_buffer_t headers
;
338 php_http_buffer_init(&headers
);
339 zend_llist_apply_with_argument(&SG(sapi_headers
).headers
, grab_headers
, &headers TSRMLS_CC
);
340 php_http_buffer_fix(&headers
);
342 status
= php_http_headers_parse(PHP_HTTP_BUFFER_VAL(&headers
), PHP_HTTP_BUFFER_LEN(&headers
), headers_ht
, NULL
, NULL TSRMLS_CC
);
343 php_http_buffer_dtor(&headers
);
348 PHP_HTTP_API
char *php_http_env_get_response_header(const char *name_str
, size_t name_len TSRMLS_DC
)
353 zend_hash_init(&headers
, 0, NULL
, NULL
, 0);
354 if (SUCCESS
== php_http_env_get_response_headers(&headers TSRMLS_CC
)) {
356 char *key
= php_http_pretty_key(estrndup(name_str
, name_len
), name_len
, 1, 1);
358 if (SUCCESS
== zend_hash_find(&headers
, key
, name_len
+ 1, (void *) &zvalue
)) {
359 zval
*zcopy
= php_http_ztyp(IS_STRING
, *zvalue
);
361 val
= estrndup(Z_STRVAL_P(zcopy
), Z_STRLEN_P(zcopy
));
362 zval_ptr_dtor(&zcopy
);
367 zend_hash_destroy(&headers
);
372 PHP_HTTP_API
long php_http_env_get_response_code(TSRMLS_D
)
374 long code
= SG(sapi_headers
).http_response_code
;
375 return code
? code
: 200;
378 PHP_HTTP_API STATUS
php_http_env_set_response_code(long http_code TSRMLS_DC
)
380 return sapi_header_op(SAPI_HEADER_SET_STATUS
, (void *) http_code TSRMLS_CC
);
383 PHP_HTTP_API STATUS
php_http_env_set_response_status_line(long code
, php_http_version_t
*v TSRMLS_DC
)
385 sapi_header_line h
= {0};
388 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
));
389 ret
= sapi_header_op(SAPI_HEADER_REPLACE
, (void *) &h TSRMLS_CC
);
395 PHP_HTTP_API STATUS
php_http_env_set_response_protocol_version(php_http_version_t
*v TSRMLS_DC
)
397 return php_http_env_set_response_status_line(php_http_env_get_response_code(TSRMLS_C
), v TSRMLS_CC
);
400 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
)
402 sapi_header_line h
= {estrndup(header_str
, header_len
), header_len
, http_code
};
403 STATUS ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h TSRMLS_CC
);
408 PHP_HTTP_API STATUS
php_http_env_set_response_header_format(long http_code
, zend_bool replace TSRMLS_DC
, const char *fmt
, ...)
411 STATUS ret
= FAILURE
;
412 sapi_header_line h
= {NULL
, 0, http_code
};
415 h
.line_len
= vspprintf(&h
.line
, 0, fmt
, args
);
420 ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h TSRMLS_CC
);
427 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
)
430 sapi_header_line h
= {(char *) name_str
, name_len
, http_code
};
432 return sapi_header_op(SAPI_HEADER_DELETE
, (void *) &h TSRMLS_CC
);
435 if(Z_TYPE_P(value
) == IS_ARRAY
|| Z_TYPE_P(value
) == IS_OBJECT
) {
440 FOREACH_HASH_VAL(pos
, HASH_OF(value
), data_ptr
) {
441 if (SUCCESS
!= php_http_env_set_response_header_value(http_code
, name_str
, name_len
, *data_ptr
, first TSRMLS_CC
)) {
449 zval
*data
= php_http_ztyp(IS_STRING
, value
);
451 if (!Z_STRLEN_P(data
)) {
452 zval_ptr_dtor(&data
);
453 return php_http_env_set_response_header_value(http_code
, name_str
, name_len
, NULL
, replace TSRMLS_CC
);
458 if (name_len
> INT_MAX
) {
461 h
.response_code
= http_code
;
462 h
.line_len
= spprintf(&h
.line
, 0, "%.*s: %.*s", (int) name_len
, name_str
, Z_STRLEN_P(data
), Z_STRVAL_P(data
));
464 ret
= sapi_header_op(replace
? SAPI_HEADER_REPLACE
: SAPI_HEADER_ADD
, (void *) &h TSRMLS_CC
);
466 zval_ptr_dtor(&data
);
475 static PHP_HTTP_STRLIST(php_http_env_response_status
) =
476 PHP_HTTP_STRLIST_ITEM("Continue")
477 PHP_HTTP_STRLIST_ITEM("Switching Protocols")
478 PHP_HTTP_STRLIST_NEXT
479 PHP_HTTP_STRLIST_ITEM("OK")
480 PHP_HTTP_STRLIST_ITEM("Created")
481 PHP_HTTP_STRLIST_ITEM("Accepted")
482 PHP_HTTP_STRLIST_ITEM("Non-Authoritative Information")
483 PHP_HTTP_STRLIST_ITEM("No Content")
484 PHP_HTTP_STRLIST_ITEM("Reset Content")
485 PHP_HTTP_STRLIST_ITEM("Partial Content")
486 PHP_HTTP_STRLIST_NEXT
487 PHP_HTTP_STRLIST_ITEM("Multiple Choices")
488 PHP_HTTP_STRLIST_ITEM("Moved Permanently")
489 PHP_HTTP_STRLIST_ITEM("Found")
490 PHP_HTTP_STRLIST_ITEM("See Other")
491 PHP_HTTP_STRLIST_ITEM("Not Modified")
492 PHP_HTTP_STRLIST_ITEM("Use Proxy")
493 PHP_HTTP_STRLIST_ITEM("(Unused)")
494 PHP_HTTP_STRLIST_ITEM("Temporary Redirect")
495 PHP_HTTP_STRLIST_NEXT
496 PHP_HTTP_STRLIST_ITEM("Bad Request")
497 PHP_HTTP_STRLIST_ITEM("Unauthorized")
498 PHP_HTTP_STRLIST_ITEM("Payment Required")
499 PHP_HTTP_STRLIST_ITEM("Forbidden")
500 PHP_HTTP_STRLIST_ITEM("Not Found")
501 PHP_HTTP_STRLIST_ITEM("Method Not Allowed")
502 PHP_HTTP_STRLIST_ITEM("Not Acceptable")
503 PHP_HTTP_STRLIST_ITEM("Proxy Authentication Required")
504 PHP_HTTP_STRLIST_ITEM("Request Timeout")
505 PHP_HTTP_STRLIST_ITEM("Conflict")
506 PHP_HTTP_STRLIST_ITEM("Gone")
507 PHP_HTTP_STRLIST_ITEM("Length Required")
508 PHP_HTTP_STRLIST_ITEM("Precondition Failed")
509 PHP_HTTP_STRLIST_ITEM("Request Entity Too Large")
510 PHP_HTTP_STRLIST_ITEM("Request URI Too Long")
511 PHP_HTTP_STRLIST_ITEM("Unsupported Media Type")
512 PHP_HTTP_STRLIST_ITEM("Requested Range Not Satisfiable")
513 PHP_HTTP_STRLIST_ITEM("Expectation Failed")
514 PHP_HTTP_STRLIST_NEXT
515 PHP_HTTP_STRLIST_ITEM("Internal Server Error")
516 PHP_HTTP_STRLIST_ITEM("Not Implemented")
517 PHP_HTTP_STRLIST_ITEM("Bad Gateway")
518 PHP_HTTP_STRLIST_ITEM("Service Unavailable")
519 PHP_HTTP_STRLIST_ITEM("Gateway Timeout")
520 PHP_HTTP_STRLIST_ITEM("HTTP Version Not Supported")
521 PHP_HTTP_STRLIST_STOP
524 PHP_HTTP_API
const char *php_http_env_get_response_status_for_code(unsigned code
)
526 return php_http_strlist_find(php_http_env_response_status
, 100, code
);
529 zend_class_entry
*php_http_env_class_entry
;
531 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpEnv, method, 0, req_args)
532 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpEnv, method, 0)
533 #define PHP_HTTP_ENV_ME(method) PHP_ME(HttpEnv, method, PHP_HTTP_ARGS(HttpEnv, method), ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
535 PHP_HTTP_BEGIN_ARGS(getRequestHeader
, 0)
536 PHP_HTTP_ARG_VAL(header_name
, 0)
539 PHP_HTTP_BEGIN_ARGS(getRequestBody
, 0)
540 PHP_HTTP_ARG_VAL(body_class_name
, 0)
543 PHP_HTTP_BEGIN_ARGS(getResponseStatusForCode
, 1)
544 PHP_HTTP_ARG_VAL(code
, 0)
547 PHP_HTTP_BEGIN_ARGS(getResponseHeader
, 0)
548 PHP_HTTP_ARG_VAL(header_name
, 0)
551 PHP_HTTP_EMPTY_ARGS(getResponseCode
);
553 PHP_HTTP_BEGIN_ARGS(setResponseHeader
, 1)
554 PHP_HTTP_ARG_VAL(header_name
, 0)
555 PHP_HTTP_ARG_VAL(header_value
, 0)
556 PHP_HTTP_ARG_VAL(response_code
, 0)
557 PHP_HTTP_ARG_VAL(replace_header
, 0)
560 PHP_HTTP_BEGIN_ARGS(setResponseCode
, 1)
561 PHP_HTTP_ARG_VAL(code
, 0)
564 PHP_HTTP_BEGIN_ARGS(negotiateLanguage
, 1)
565 PHP_HTTP_ARG_VAL(supported
, 0)
566 PHP_HTTP_ARG_VAL(result_array
, 1)
569 PHP_HTTP_BEGIN_ARGS(negotiateContentType
, 1)
570 PHP_HTTP_ARG_VAL(supported
, 0)
571 PHP_HTTP_ARG_VAL(result_array
, 1)
574 PHP_HTTP_BEGIN_ARGS(negotiateCharset
, 1)
575 PHP_HTTP_ARG_VAL(supported
, 0)
576 PHP_HTTP_ARG_VAL(result_array
, 1)
579 PHP_HTTP_BEGIN_ARGS(negotiate
, 2)
580 PHP_HTTP_ARG_VAL(value
, 0)
581 PHP_HTTP_ARG_VAL(supported
, 0)
582 PHP_HTTP_ARG_VAL(result_array
, 1)
585 PHP_HTTP_EMPTY_ARGS(persistentHandlesStat
);
587 PHP_HTTP_BEGIN_ARGS(persistentHandlesClean
, 0)
588 PHP_HTTP_ARG_VAL(name
, 0)
589 PHP_HTTP_ARG_VAL(ident
, 0)
592 PHP_HTTP_BEGIN_ARGS(persistentHandlesIdent
, 0)
593 PHP_HTTP_ARG_VAL(name
, 0)
596 PHP_HTTP_BEGIN_ARGS(parseParams
, 1)
597 PHP_HTTP_ARG_VAL(params
, 0)
598 PHP_HTTP_ARG_VAL(flags
, 0)
601 zend_function_entry php_http_env_method_entry
[] = {
602 PHP_HTTP_ENV_ME(getRequestHeader
)
603 PHP_HTTP_ENV_ME(getRequestBody
)
605 PHP_HTTP_ENV_ME(getResponseStatusForCode
)
607 PHP_HTTP_ENV_ME(getResponseHeader
)
608 PHP_HTTP_ENV_ME(getResponseCode
)
609 PHP_HTTP_ENV_ME(setResponseHeader
)
610 PHP_HTTP_ENV_ME(setResponseCode
)
612 PHP_HTTP_ENV_ME(negotiateLanguage
)
613 PHP_HTTP_ENV_ME(negotiateContentType
)
614 PHP_HTTP_ENV_ME(negotiateCharset
)
615 PHP_HTTP_ENV_ME(negotiate
)
617 PHP_HTTP_ENV_ME(persistentHandlesStat
)
618 PHP_HTTP_ENV_ME(persistentHandlesClean
)
620 PHP_HTTP_ENV_ME(parseParams
)
625 PHP_METHOD(HttpEnv
, getRequestHeader
)
627 char *header_name_str
;
630 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s!", &header_name_str
, &header_name_len
)) {
631 if (header_name_str
&& header_name_len
) {
632 char *header_value
= php_http_env_get_request_header(header_name_str
, header_name_len TSRMLS_CC
);
635 RETURN_STRING(header_value
, 0);
639 array_init(return_value
);
640 php_http_env_get_request_headers(Z_ARRVAL_P(return_value
) TSRMLS_CC
);
647 PHP_METHOD(HttpEnv
, getRequestBody
)
649 with_error_handling(EH_THROW
, php_http_exception_class_entry
) {
650 zend_class_entry
*class_entry
= php_http_message_body_class_entry
;
652 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|C", &class_entry
)) {
653 zend_object_value ov
;
654 php_http_message_body_t
*body
= php_http_env_get_request_body(TSRMLS_C
);
656 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
)) {
657 RETURN_OBJVAL(ov
, 0);
660 } end_error_handling();
663 PHP_METHOD(HttpEnv
, getResponseStatusForCode
)
667 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &code
)) {
668 RETURN_STRING(php_http_env_get_response_status_for_code(code
), 1);
673 PHP_METHOD(HttpEnv
, getResponseHeader
)
675 char *header_name_str
;
678 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s!", &header_name_str
, &header_name_len
)) {
679 if (header_name_str
&& header_name_len
) {
680 char *header_value
= php_http_env_get_response_header(header_name_str
, header_name_len TSRMLS_CC
);
683 RETURN_STRING(header_value
, 0);
687 array_init(return_value
);
688 php_http_env_get_response_headers(Z_ARRVAL_P(return_value
) TSRMLS_CC
);
695 PHP_METHOD(HttpEnv
, getResponseCode
)
697 if (SUCCESS
== zend_parse_parameters_none()) {
698 RETURN_LONG(php_http_env_get_response_code(TSRMLS_C
));
703 PHP_METHOD(HttpEnv
, setResponseHeader
)
705 char *header_name_str
;
709 zend_bool replace_header
= 1;
711 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|z!lb", &header_name_str
, &header_name_len
, &header_value
, &code
, &replace_header
)) {
712 RETURN_SUCCESS(php_http_env_set_response_header_value(code
, header_name_str
, header_name_len
, header_value
, replace_header TSRMLS_CC
));
717 PHP_METHOD(HttpEnv
, setResponseCode
)
721 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &code
)) {
722 RETURN_SUCCESS(php_http_env_set_response_code(code TSRMLS_CC
));
728 #define PHP_HTTP_DO_NEGOTIATE_DEFAULT(supported) \
732 zend_hash_internal_pointer_reset((supported)); \
733 if (SUCCESS == zend_hash_get_current_data((supported), (void *) &value)) { \
734 RETVAL_ZVAL(*value, 1, 0); \
740 #define PHP_HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array) \
741 PHP_HTTP_DO_NEGOTIATE_DEFAULT(supported); \
746 FOREACH_HASH_VAL(pos, supported, value_ptr) { \
747 zval *value = php_http_ztyp(IS_STRING, *value_ptr); \
748 add_assoc_double(rs_array, Z_STRVAL_P(value), 1.0); \
749 zval_ptr_dtor(&value); \
753 #define PHP_HTTP_DO_NEGOTIATE_HANDLE_RESULT(result, supported, rs_array) \
759 if (zend_hash_num_elements(result) && HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(result, &key, &key_len, &idx, 1, NULL)) { \
760 RETVAL_STRINGL(key, key_len-1, 0); \
762 PHP_HTTP_DO_NEGOTIATE_DEFAULT(supported); \
766 zend_hash_copy(Z_ARRVAL_P(rs_array), result, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); \
769 zend_hash_destroy(result); \
770 FREE_HASHTABLE(result); \
773 #define PHP_HTTP_DO_NEGOTIATE(type, supported, rs_array) \
776 if ((result = php_http_negotiate_ ##type(supported TSRMLS_CC))) { \
777 PHP_HTTP_DO_NEGOTIATE_HANDLE_RESULT(result, supported, rs_array); \
779 PHP_HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array); \
783 PHP_METHOD(HttpEnv
, negotiateLanguage
)
785 HashTable
*supported
;
786 zval
*rs_array
= NULL
;
788 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
791 array_init(rs_array
);
794 PHP_HTTP_DO_NEGOTIATE(language
, supported
, rs_array
);
799 PHP_METHOD(HttpEnv
, negotiateCharset
)
801 HashTable
*supported
;
802 zval
*rs_array
= NULL
;
804 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
807 array_init(rs_array
);
809 PHP_HTTP_DO_NEGOTIATE(charset
, supported
, rs_array
);
814 PHP_METHOD(HttpEnv
, negotiateContentType
)
816 HashTable
*supported
;
817 zval
*rs_array
= NULL
;
819 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "H|z", &supported
, &rs_array
)) {
822 array_init(rs_array
);
824 PHP_HTTP_DO_NEGOTIATE(content_type
, supported
, rs_array
);
829 PHP_METHOD(HttpEnv
, negotiate
)
831 HashTable
*supported
;
832 zval
*rs_array
= NULL
;
836 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sH|z", &value_str
, &value_len
, &supported
, &rs_array
)) {
841 array_init(rs_array
);
844 if ((rs
= php_http_negotiate(value_str
, supported
, php_http_negotiate_default_func TSRMLS_CC
))) {
845 PHP_HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs
, supported
, rs_array
);
847 PHP_HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported
, rs_array
);
853 PHP_METHOD(HttpEnv
, persistentHandlesStat
)
855 if (SUCCESS
== zend_parse_parameters_none()) {
856 object_init(return_value
);
857 if (php_http_persistent_handle_statall(HASH_OF(return_value
) TSRMLS_CC
)) {
860 zval_dtor(return_value
);
865 PHP_METHOD(HttpEnv
, persistentHandlesClean
)
867 char *name_str
= NULL
, *ident_str
= NULL
;
868 int name_len
= 0, ident_len
= 0;
870 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|ss", &name_str
, &name_len
, &ident_str
, &ident_len
)) {
871 php_http_persistent_handle_cleanup(name_str
, name_len
, ident_str
, ident_len TSRMLS_CC
);
875 PHP_METHOD(HttpEnv
, parseParams
)
879 long flags
= PHP_HTTP_PARAMS_DEFAULT
;
881 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|l", ¶m_str
, ¶m_len
, &flags
)) {
885 array_init(return_value
);
886 if (SUCCESS
!= php_http_params_parse(param_str
, flags
, php_http_params_parse_default_func
, Z_ARRVAL_P(return_value
) TSRMLS_CC
)) {
887 zval_dtor(return_value
);
892 zend_class_entry
*php_http_env_request_class_entry
;
894 #undef PHP_HTTP_BEGIN_ARGS
895 #undef PHP_HTTP_EMPTY_ARGS
896 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpEnvRequest, method, 0, req_args)
897 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpEnvRequest, method, 0)
898 #define PHP_HTTP_ENV_REQUEST_ME(method, visibility) PHP_ME(HttpEnvRequest, method, PHP_HTTP_ARGS(HttpEnvRequest, method), visibility)
900 PHP_HTTP_EMPTY_ARGS(__construct
);
902 zend_function_entry php_http_env_request_method_entry
[] = {
903 PHP_HTTP_ENV_REQUEST_ME(__construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
908 PHP_METHOD(HttpEnvRequest
, __construct
)
910 with_error_handling(EH_THROW
, php_http_exception_class_entry
) {
911 if (SUCCESS
== zend_parse_parameters_none()) {
912 php_http_message_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
914 with_error_handling(EH_THROW
, php_http_exception_class_entry
) {
915 obj
->message
= php_http_message_init_env(obj
->message
, PHP_HTTP_REQUEST TSRMLS_CC
);
916 } end_error_handling();
918 } end_error_handling();
921 PHP_MINIT_FUNCTION(http_env
)
923 PHP_HTTP_REGISTER_CLASS(http
, Env
, http_env
, NULL
, 0);
925 zend_declare_class_constant_long(php_http_env_class_entry
, ZEND_STRL("PARAMS_ALLOW_COMMA"), PHP_HTTP_PARAMS_ALLOW_COMMA TSRMLS_CC
);
926 zend_declare_class_constant_long(php_http_env_class_entry
, ZEND_STRL("PARAMS_ALLOW_FAILURE"), PHP_HTTP_PARAMS_ALLOW_FAILURE TSRMLS_CC
);
927 zend_declare_class_constant_long(php_http_env_class_entry
, ZEND_STRL("PARAMS_RAISE_ERROR"), PHP_HTTP_PARAMS_RAISE_ERROR TSRMLS_CC
);
928 zend_declare_class_constant_long(php_http_env_class_entry
, ZEND_STRL("PARAMS_DEFAULT"), PHP_HTTP_PARAMS_DEFAULT TSRMLS_CC
);
929 zend_declare_class_constant_long(php_http_env_class_entry
, ZEND_STRL("PARAMS_COLON_SEPARATOR"), PHP_HTTP_PARAMS_COLON_SEPARATOR TSRMLS_CC
);
931 PHP_HTTP_REGISTER_CLASS(http
\\env
, Request
, http_env_request
, php_http_message_class_entry
, 0);
942 * vim600: noet sw=4 ts=4 fdm=marker
943 * vim<600: noet sw=4 ts=4