From 5e651aa1fe9e5648f80708a01a6291c2aac5ca71 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 12 Dec 2012 11:43:58 +0000 Subject: [PATCH] add http\Header::negotiate() add http\Header::parse() --- php_http_headers.c | 114 +++++++++++++++++++++++++++++++++++++++++++++ php_http_headers.h | 2 + 2 files changed, 116 insertions(+) diff --git a/php_http_headers.c b/php_http_headers.c index 51a6997..933952c 100644 --- a/php_http_headers.c +++ b/php_http_headers.c @@ -45,6 +45,16 @@ PHP_HTTP_BEGIN_ARGS(match, 1) PHP_HTTP_ARG_VAL(flags, 0) PHP_HTTP_END_ARGS; +PHP_HTTP_BEGIN_ARGS(negotiate, 1) + PHP_HTTP_ARG_VAL(supported, 0) + PHP_HTTP_ARG_VAL(result, 1) +PHP_HTTP_END_ARGS; + +PHP_HTTP_BEGIN_ARGS(parse, 1) + PHP_HTTP_ARG_VAL(string, 0) + PHP_HTTP_ARG_VAL(flags, 0) +PHP_HTTP_END_ARGS; + static zend_class_entry *php_http_header_class_entry; zend_class_entry *php_http_header_get_class_entry(void) @@ -59,6 +69,8 @@ static zend_function_entry php_http_header_method_entry[] = { ZEND_MALIAS(HttpHeader, toString, serialize, PHP_HTTP_ARGS(HttpHeader, serialize), ZEND_ACC_PUBLIC) PHP_HTTP_HEADER_ME(unserialize, ZEND_ACC_PUBLIC) PHP_HTTP_HEADER_ME(match, ZEND_ACC_PUBLIC) + PHP_HTTP_HEADER_ME(negotiate, ZEND_ACC_PUBLIC) + PHP_HTTP_HEADER_ME(parse, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) EMPTY_FUNCTION_ENTRY }; @@ -156,6 +168,108 @@ PHP_METHOD(HttpHeader, match) zval_ptr_dtor(&zvalue); } +PHP_METHOD(HttpHeader, negotiate) +{ + HashTable *supported, *rs; + zval *zname, *zvalue, *rs_array = NULL; + char *sep_str = NULL; + size_t sep_len = 0; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|z", &supported, &rs_array)) { + if (rs_array) { + zval_dtor(rs_array); + array_init(rs_array); + } + + zname = php_http_ztyp(IS_STRING, zend_read_property(php_http_header_class_entry, getThis(), ZEND_STRL("name"), 0 TSRMLS_CC)); + if (!strcasecmp(Z_STRVAL_P(zname), "Accept")) { + sep_str = "/"; + sep_len = 1; + } else if (!strcasecmp(Z_STRVAL_P(zname), "Accept-Language")) { + sep_str = "-"; + sep_len = 1; + } + zval_ptr_dtor(&zname); + + zvalue = php_http_ztyp(IS_STRING, zend_read_property(php_http_header_class_entry, getThis(), ZEND_STRL("value"), 0 TSRMLS_CC)); + if ((rs = php_http_negotiate(Z_STRVAL_P(zvalue), Z_STRLEN_P(zvalue), supported, sep_str, sep_len TSRMLS_CC))) { + PHP_HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs, supported, rs_array); + } else { + PHP_HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array); + } + zval_ptr_dtor(&zvalue); + } else { + RETURN_FALSE; + } +} + +PHP_METHOD(HttpHeader, parse) +{ + char *header_str; + int header_len; + zend_class_entry *ce = NULL; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|C", &header_str, &header_len, &ce)) { + php_http_header_parser_t *parser = php_http_header_parser_init(NULL TSRMLS_CC); + php_http_buffer_t *buf = php_http_buffer_from_string(header_str, header_len); + + if (parser && buf) { + php_http_header_parser_state_t rs; + + array_init(return_value); + + rs = php_http_header_parser_parse(parser, buf, + PHP_HTTP_HEADER_PARSER_CLEANUP, Z_ARRVAL_P(return_value), NULL, NULL); + + if (rs == PHP_HTTP_HEADER_PARSER_STATE_FAILURE) { + php_http_error(HE_WARNING, PHP_HTTP_E_MALFORMED_HEADERS, "Could not parse headers"); + zval_dtor(return_value); + RETVAL_NULL(); + } else { + if (ce && instanceof_function(ce, php_http_header_class_entry TSRMLS_CC)) { + HashPosition pos; + php_http_array_hashkey_t key = php_http_array_hashkey_init(0); + zval **val; + + FOREACH_KEYVAL(pos, return_value, key, val) { + zval *zho, *zkey, *zvalue; + + Z_ADDREF_PP(val); + zvalue = *val; + + MAKE_STD_ZVAL(zkey); + if (key.type == HASH_KEY_IS_LONG) { + ZVAL_LONG(zkey, key.num); + } else { + ZVAL_STRINGL(zkey, key.str, key.len - 1, 1); + } + + MAKE_STD_ZVAL(zho); + object_init_ex(zho, ce); + zend_call_method_with_2_params(&zho, ce, NULL, "__construct", NULL, zkey, zvalue); + + if (key.type == HASH_KEY_IS_LONG) { + zend_hash_index_update(Z_ARRVAL_P(return_value), key.num, (void *) &zho, sizeof(zval *), NULL); + } else { + zend_hash_update(Z_ARRVAL_P(return_value), key.str, key.len, (void *) &zho, sizeof(zval *), NULL); + } + + zval_ptr_dtor(&zvalue); + zval_ptr_dtor(&zkey); + } + } + } + } + + if (parser) { + php_http_header_parser_free(&parser); + } + if (buf) { + php_http_buffer_free(&buf); + } + } +} + PHP_MINIT_FUNCTION(http_header) { PHP_HTTP_REGISTER_CLASS(http, Header, http_header, php_http_object_get_class_entry(), 0); diff --git a/php_http_headers.h b/php_http_headers.h index 0d67f12..8709574 100644 --- a/php_http_headers.h +++ b/php_http_headers.h @@ -23,6 +23,8 @@ PHP_METHOD(HttpHeader, __construct); PHP_METHOD(HttpHeader, serialize); PHP_METHOD(HttpHeader, unserialize); PHP_METHOD(HttpHeader, match); +PHP_METHOD(HttpHeader, negotiate); +PHP_METHOD(HttpHeader, parse); PHP_MINIT_FUNCTION(http_header); -- 2.30.2