From 279a65eb0969de5c357808a887b4c9447518e43d Mon Sep 17 00:00:00 2001 From: Rui Hirokawa Date: Sat, 8 Jan 2011 02:34:33 +0000 Subject: [PATCH] MFH: added an option to http_build_query for RFC-3986 based url-encoding. --- ext/standard/basic_functions.c | 3 +++ ext/standard/http.c | 36 ++++++++++++++++++++++++---------- ext/standard/php_http.h | 2 +- ext/standard/url.h | 3 +++ 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 02300aee3d..aebc0efc7b 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1516,6 +1516,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_http_build_query, 0, 0, 1) ZEND_ARG_INFO(0, formdata) ZEND_ARG_INFO(0, prefix) ZEND_ARG_INFO(0, arg_separator) + ZEND_ARG_INFO(0, enc_type) ZEND_END_ARG_INFO() /* }}} */ /* {{{ image.c */ @@ -3575,6 +3576,8 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */ REGISTER_LONG_CONSTANT("PHP_URL_PATH", PHP_URL_PATH, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_URL_QUERY", PHP_URL_QUERY, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_URL_FRAGMENT", PHP_URL_FRAGMENT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PHP_QUERY_RFC1738", PHP_QUERY_RFC1738, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PHP_QUERY_RFC3986", PHP_QUERY_RFC3986, CONST_CS | CONST_PERSISTENT); #define REGISTER_MATH_CONSTANT(x) REGISTER_DOUBLE_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT) REGISTER_MATH_CONSTANT(M_E); diff --git a/ext/standard/http.c b/ext/standard/http.c index f1711cc4c2..044284acc6 100644 --- a/ext/standard/http.c +++ b/ext/standard/http.c @@ -29,7 +29,7 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, const char *num_prefix, int num_prefix_len, const char *key_prefix, int key_prefix_len, const char *key_suffix, int key_suffix_len, - zval *type, char *arg_sep TSRMLS_DC) + zval *type, char *arg_sep, int enc_type TSRMLS_DC) { char *key = NULL, *ekey, *newprefix, *p; int arg_sep_len, key_len, ekey_len, key_type, newprefix_len; @@ -81,7 +81,11 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, } if (Z_TYPE_PP(zdata) == IS_ARRAY || Z_TYPE_PP(zdata) == IS_OBJECT) { if (key_type == HASH_KEY_IS_STRING) { - ekey = php_url_encode(key, key_len, &ekey_len); + if (enc_type == PHP_QUERY_RFC3986) { + ekey = php_raw_url_encode(key, key_len, &ekey_len); + } else { + ekey = php_url_encode(key, key_len, &ekey_len); + } newprefix_len = key_suffix_len + ekey_len + key_prefix_len + 3 /* %5B */; newprefix = emalloc(newprefix_len + 1); p = newprefix; @@ -132,7 +136,7 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, *p = '\0'; } ht->nApplyCount++; - php_url_encode_hash_ex(HASH_OF(*zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_PP(zdata) == IS_OBJECT ? *zdata : NULL), arg_sep TSRMLS_CC); + php_url_encode_hash_ex(HASH_OF(*zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_PP(zdata) == IS_OBJECT ? *zdata : NULL), arg_sep, enc_type TSRMLS_CC); ht->nApplyCount--; efree(newprefix); } else if (Z_TYPE_PP(zdata) == IS_NULL || Z_TYPE_PP(zdata) == IS_RESOURCE) { @@ -145,7 +149,11 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, /* Simple key=value */ smart_str_appendl(formstr, key_prefix, key_prefix_len); if (key_type == HASH_KEY_IS_STRING) { - ekey = php_url_encode(key, key_len, &ekey_len); + if (enc_type == PHP_QUERY_RFC3986) { + ekey = php_raw_url_encode(key, key_len, &ekey_len); + } else { + ekey = php_url_encode(key, key_len, &ekey_len); + } smart_str_appendl(formstr, ekey, ekey_len); efree(ekey); } else { @@ -161,7 +169,11 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, smart_str_appendl(formstr, "=", 1); switch (Z_TYPE_PP(zdata)) { case IS_STRING: - ekey = php_url_encode(Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata), &ekey_len); + if (enc_type == PHP_QUERY_RFC3986) { + ekey = php_raw_url_encode(Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata), &ekey_len); + } else { + ekey = php_url_encode(Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata), &ekey_len); + } break; case IS_LONG: case IS_BOOL: @@ -176,7 +188,11 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, *copyzval = **zdata; zval_copy_ctor(copyzval); convert_to_string_ex(©zval); - ekey = php_url_encode(Z_STRVAL_P(copyzval), Z_STRLEN_P(copyzval), &ekey_len); + if (enc_type == PHP_QUERY_RFC3986) { + ekey = php_raw_url_encode(Z_STRVAL_P(copyzval), Z_STRLEN_P(copyzval), &ekey_len); + } else { + ekey = php_url_encode(Z_STRVAL_P(copyzval), Z_STRLEN_P(copyzval), &ekey_len); + } zval_ptr_dtor(©zval); } smart_str_appendl(formstr, ekey, ekey_len); @@ -188,7 +204,7 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, } /* }}} */ -/* {{{ proto string http_build_query(mixed formdata [, string prefix [, string arg_separator]]) +/* {{{ proto string http_build_query(mixed formdata [, string prefix [, string arg_separator [, int enc_type]]]) Generates a form-encoded query string from an associative array or object. */ PHP_FUNCTION(http_build_query) { @@ -196,9 +212,9 @@ PHP_FUNCTION(http_build_query) char *prefix = NULL, *arg_sep=NULL; int arg_sep_len = 0, prefix_len = 0; smart_str formstr = {0}; - + long enc_type = PHP_QUERY_RFC1738; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ss", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ssl", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len, &enc_type) != SUCCESS) { RETURN_FALSE; } @@ -207,7 +223,7 @@ PHP_FUNCTION(http_build_query) RETURN_FALSE; } - if (php_url_encode_hash_ex(HASH_OF(formdata), &formstr, prefix, prefix_len, NULL, 0, NULL, 0, (Z_TYPE_P(formdata) == IS_OBJECT ? formdata : NULL), arg_sep TSRMLS_CC) == FAILURE) { + if (php_url_encode_hash_ex(HASH_OF(formdata), &formstr, prefix, prefix_len, NULL, 0, NULL, 0, (Z_TYPE_P(formdata) == IS_OBJECT ? formdata : NULL), arg_sep, enc_type TSRMLS_CC) == FAILURE) { if (formstr.c) { efree(formstr.c); } diff --git a/ext/standard/php_http.h b/ext/standard/php_http.h index 1492b4e3cb..6b659878f0 100644 --- a/ext/standard/php_http.h +++ b/ext/standard/php_http.h @@ -28,7 +28,7 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, const char *num_prefix, int num_prefix_len, const char *key_prefix, int key_prefix_len, const char *key_suffix, int key_suffix_len, - zval *type, char *arg_sep TSRMLS_DC); + zval *type, char *arg_sep, int enc_type TSRMLS_DC); #define php_url_encode_hash(ht, formstr) php_url_encode_hash_ex((ht), (formstr), NULL, 0, NULL, 0, NULL, 0, NULL TSRMLS_CC) PHP_FUNCTION(http_build_query); diff --git a/ext/standard/url.h b/ext/standard/url.h index 5cffa0ad77..ecedddf619 100644 --- a/ext/standard/url.h +++ b/ext/standard/url.h @@ -55,6 +55,9 @@ PHP_FUNCTION(get_headers); #define PHP_URL_QUERY 6 #define PHP_URL_FRAGMENT 7 +#define PHP_QUERY_RFC1738 1 +#define PHP_QUERY_RFC3986 2 + #endif /* URL_H */ /* -- 2.40.0