Hello, I made a patch to add the RFC-3984 based url-encoding support into http_build_query().
The http_build_query() is quite useful, but, it isn't based on the official url-encoding scheme (RFC-3984) for ~ (tilde) and ' '(space). I added an optional (the 4th) parameter 'is_rfc3984'. If it is true (false by default, now), RFC3984 based url-encoding scheme (it is same as rawurlencode() ) is used. A simple example shown as bellow, $v = array('foo'=>'m o','boo'=>'[^~]'); // result: foo=m+p&boo=%5B%5E%7E5D echo http_build_query($v, null, '&'); // result: foo=m%20p&boo=%5B%5E~5D (RFC-3986 compatible) echo http_build_query($v, null, '&', true); // result: foo=m%20p&boo=%5B%5E~5D (RFC-3986 compatible) echo rawurlencode($v['foo']).'&'.rawurlencode($v['boo']); I'm going to commit the patch if it is accepted. Rui
Index: ext/standard/basic_functions.c =================================================================== --- ext/standard/basic_functions.c (revision 307112) +++ ext/standard/basic_functions.c (working copy) @@ -1513,6 +1513,7 @@ ZEND_ARG_INFO(0, formdata) ZEND_ARG_INFO(0, prefix) ZEND_ARG_INFO(0, arg_separator) + ZEND_ARG_INFO(0, is_rfc3986) ZEND_END_ARG_INFO() /* }}} */ /* {{{ image.c */ Index: ext/standard/php_http.h =================================================================== --- ext/standard/php_http.h (revision 307112) +++ ext/standard/php_http.h (working copy) @@ -28,7 +28,7 @@ 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 is_rfc3986 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); Index: ext/standard/http.c =================================================================== --- ext/standard/http.c (revision 307112) +++ ext/standard/http.c (working copy) @@ -29,7 +29,7 @@ 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 is_rfc3986 TSRMLS_DC) { char *key = NULL, *ekey, *newprefix, *p; int arg_sep_len, key_len, ekey_len, key_type, newprefix_len; @@ -81,7 +81,11 @@ } 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 (is_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 @@ *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, is_rfc3986 TSRMLS_CC); ht->nApplyCount--; efree(newprefix); } else if (Z_TYPE_PP(zdata) == IS_NULL || Z_TYPE_PP(zdata) == IS_RESOURCE) { @@ -145,7 +149,11 @@ /* 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 (is_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 @@ 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 (is_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 @@ *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 (is_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 @@ } /* }}} */ -/* {{{ proto string http_build_query(mixed formdata [, string prefix [, string arg_separator]]) +/* {{{ proto string http_build_query(mixed formdata [, string prefix [, string arg_separator [, bool is_rfc3986]]]) Generates a form-encoded query string from an associative array or object. */ PHP_FUNCTION(http_build_query) { @@ -196,9 +212,9 @@ char *prefix = NULL, *arg_sep=NULL; int arg_sep_len = 0, prefix_len = 0; smart_str formstr = {0}; - + long is_rfc3986 = 0; - 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, &is_rfc3986) != SUCCESS) { RETURN_FALSE; } @@ -207,7 +223,7 @@ 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, is_rfc3986 TSRMLS_CC) == FAILURE) { if (formstr.c) { efree(formstr.c); }
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php