123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- #include "php_http.h"
- #include "php_ini.h"
- #include "url.h"
- #define URL_DEFAULT_ARG_SEP "&"
- PHPAPI void php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
- const char *num_prefix, size_t num_prefix_len,
- const char *key_prefix, size_t key_prefix_len,
- const char *key_suffix, size_t key_suffix_len,
- zval *type, const char *arg_sep, int enc_type)
- {
- zend_string *key = NULL;
- char *newprefix, *p;
- const char *prop_name;
- size_t arg_sep_len, newprefix_len, prop_len;
- zend_ulong idx;
- zval *zdata = NULL;
- ZEND_ASSERT(ht);
- if (GC_IS_RECURSIVE(ht)) {
-
- return;
- }
- if (!arg_sep) {
- arg_sep = INI_STR("arg_separator.output");
- if (!arg_sep || !strlen(arg_sep)) {
- arg_sep = URL_DEFAULT_ARG_SEP;
- }
- }
- arg_sep_len = strlen(arg_sep);
- ZEND_HASH_FOREACH_KEY_VAL(ht, idx, key, zdata) {
- bool is_dynamic = 1;
- if (Z_TYPE_P(zdata) == IS_INDIRECT) {
- zdata = Z_INDIRECT_P(zdata);
- if (Z_ISUNDEF_P(zdata)) {
- continue;
- }
- is_dynamic = 0;
- }
-
- if (key) {
- prop_name = ZSTR_VAL(key);
- prop_len = ZSTR_LEN(key);
- if (type != NULL && zend_check_property_access(Z_OBJ_P(type), key, is_dynamic) != SUCCESS) {
-
- continue;
- }
- if (ZSTR_VAL(key)[0] == '\0' && type != NULL) {
- const char *tmp;
- zend_unmangle_property_name_ex(key, &tmp, &prop_name, &prop_len);
- } else {
- prop_name = ZSTR_VAL(key);
- prop_len = ZSTR_LEN(key);
- }
- } else {
- prop_name = NULL;
- prop_len = 0;
- }
- ZVAL_DEREF(zdata);
- if (Z_TYPE_P(zdata) == IS_ARRAY || Z_TYPE_P(zdata) == IS_OBJECT) {
- if (key) {
- zend_string *ekey;
- if (enc_type == PHP_QUERY_RFC3986) {
- ekey = php_raw_url_encode(prop_name, prop_len);
- } else {
- ekey = php_url_encode(prop_name, prop_len);
- }
- newprefix_len = key_suffix_len + ZSTR_LEN(ekey) + key_prefix_len + 3 ;
- newprefix = emalloc(newprefix_len + 1);
- p = newprefix;
- if (key_prefix) {
- memcpy(p, key_prefix, key_prefix_len);
- p += key_prefix_len;
- }
- memcpy(p, ZSTR_VAL(ekey), ZSTR_LEN(ekey));
- p += ZSTR_LEN(ekey);
- zend_string_free(ekey);
- if (key_suffix) {
- memcpy(p, key_suffix, key_suffix_len);
- p += key_suffix_len;
- }
- *(p++) = '%';
- *(p++) = '5';
- *(p++) = 'B';
- *p = '\0';
- } else {
- char *ekey;
- size_t ekey_len;
-
- ekey_len = spprintf(&ekey, 0, ZEND_LONG_FMT, idx);
- newprefix_len = key_prefix_len + num_prefix_len + ekey_len + key_suffix_len + 3 ;
- newprefix = emalloc(newprefix_len + 1);
- p = newprefix;
- if (key_prefix) {
- memcpy(p, key_prefix, key_prefix_len);
- p += key_prefix_len;
- }
- if (num_prefix) {
- memcpy(p, num_prefix, num_prefix_len);
- p += num_prefix_len;
- }
- memcpy(p, ekey, ekey_len);
- p += ekey_len;
- efree(ekey);
- if (key_suffix) {
- memcpy(p, key_suffix, key_suffix_len);
- p += key_suffix_len;
- }
- *(p++) = '%';
- *(p++) = '5';
- *(p++) = 'B';
- *p = '\0';
- }
- GC_TRY_PROTECT_RECURSION(ht);
- php_url_encode_hash_ex(HASH_OF(zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_P(zdata) == IS_OBJECT ? zdata : NULL), arg_sep, enc_type);
- GC_TRY_UNPROTECT_RECURSION(ht);
- efree(newprefix);
- } else if (Z_TYPE_P(zdata) == IS_NULL || Z_TYPE_P(zdata) == IS_RESOURCE) {
-
- continue;
- } else {
- if (formstr->s) {
- smart_str_appendl(formstr, arg_sep, arg_sep_len);
- }
-
- if (key_prefix) {
- smart_str_appendl(formstr, key_prefix, key_prefix_len);
- }
- if (key) {
- zend_string *ekey;
- if (enc_type == PHP_QUERY_RFC3986) {
- ekey = php_raw_url_encode(prop_name, prop_len);
- } else {
- ekey = php_url_encode(prop_name, prop_len);
- }
- smart_str_append(formstr, ekey);
- zend_string_free(ekey);
- } else {
-
- if (num_prefix) {
- smart_str_appendl(formstr, num_prefix, num_prefix_len);
- }
- smart_str_append_long(formstr, idx);
- }
- if (key_suffix) {
- smart_str_appendl(formstr, key_suffix, key_suffix_len);
- }
- smart_str_appendl(formstr, "=", 1);
- switch (Z_TYPE_P(zdata)) {
- case IS_STRING: {
- zend_string *ekey;
- if (enc_type == PHP_QUERY_RFC3986) {
- ekey = php_raw_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata));
- } else {
- ekey = php_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata));
- }
- smart_str_append(formstr, ekey);
- zend_string_free(ekey);
- }
- break;
- case IS_LONG:
- smart_str_append_long(formstr, Z_LVAL_P(zdata));
- break;
- case IS_FALSE:
- smart_str_appendl(formstr, "0", sizeof("0")-1);
- break;
- case IS_TRUE:
- smart_str_appendl(formstr, "1", sizeof("1")-1);
- break;
- default:
- {
- zend_string *ekey;
- zend_string *tmp;
- zend_string *str= zval_get_tmp_string(zdata, &tmp);
- if (enc_type == PHP_QUERY_RFC3986) {
- ekey = php_raw_url_encode(ZSTR_VAL(str), ZSTR_LEN(str));
- } else {
- ekey = php_url_encode(ZSTR_VAL(str), ZSTR_LEN(str));
- }
- smart_str_append(formstr, ekey);
- zend_tmp_string_release(tmp);
- zend_string_free(ekey);
- }
- }
- }
- } ZEND_HASH_FOREACH_END();
- }
- PHP_FUNCTION(http_build_query)
- {
- zval *formdata;
- char *prefix = NULL, *arg_sep=NULL;
- size_t arg_sep_len = 0, prefix_len = 0;
- smart_str formstr = {0};
- zend_long enc_type = PHP_QUERY_RFC1738;
- ZEND_PARSE_PARAMETERS_START(1, 4)
- Z_PARAM_ARRAY_OR_OBJECT(formdata)
- Z_PARAM_OPTIONAL
- Z_PARAM_STRING(prefix, prefix_len)
- Z_PARAM_STRING_OR_NULL(arg_sep, arg_sep_len)
- Z_PARAM_LONG(enc_type)
- ZEND_PARSE_PARAMETERS_END();
- 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, (int)enc_type);
- if (!formstr.s) {
- RETURN_EMPTY_STRING();
- }
- smart_str_0(&formstr);
- RETURN_NEW_STR(formstr.s);
- }
|