2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2004 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.0 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_0.txt. |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Sara Golemon <pollita@php.net> |
16 +----------------------------------------------------------------------+
23 #include "ext/standard/url.h"
25 #define URL_DEFAULT_ARG_SEP "&"
27 /* {{{ php_url_encode_hash */
28 PHPAPI
int php_url_encode_hash_ex(HashTable
*ht
, smart_str
*formstr
,
29 const char *num_prefix
, int num_prefix_len
,
30 const char *key_prefix
, int key_prefix_len
,
31 const char *key_suffix
, int key_suffix_len
,
34 char *arg_sep
= NULL
, *key
= NULL
, *ekey
, *newprefix
, *p
;
35 int arg_sep_len
, key_len
, ekey_len
, key_type
, newprefix_len
;
37 zval
**zdata
= NULL
, *copyzval
;
43 if (ht
->nApplyCount
> 0) {
44 /* Prevent recursion */
48 arg_sep
= INI_STR("arg_separator.output");
49 if (!arg_sep
|| !strlen(arg_sep
)) {
50 arg_sep
= URL_DEFAULT_ARG_SEP
;
52 arg_sep_len
= strlen(arg_sep
);
54 for (zend_hash_internal_pointer_reset(ht
);
55 (key_type
= zend_hash_get_current_key_ex(ht
, &key
, &key_len
, &idx
, 0, NULL
)) != HASH_KEY_NON_EXISTANT
;
56 zend_hash_move_forward(ht
)
58 if (key_type
== HASH_KEY_IS_STRING
&& key_len
&& key
[key_len
-1] == '\0') {
59 /* We don't want that trailing NULL */
64 /* handling for private & protected object properties */
65 if (key
&& *key
== '\0' && type
!= NULL
) {
68 zend_object
*zobj
= zend_objects_get_address(type TSRMLS_CC
);
69 if (zend_check_property_access(zobj
, key TSRMLS_CC
) != SUCCESS
) {
70 /* private or protected property access outside of the class */
73 zend_unmangle_property_name(key
, &tmp
, &key
);
74 key_len
= strlen(key
);
78 if (zend_hash_get_current_data_ex(ht
, (void **)&zdata
, NULL
) == FAILURE
|| !zdata
|| !(*zdata
)) {
79 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Error traversing form data array.");
82 if (Z_TYPE_PP(zdata
) == IS_ARRAY
|| Z_TYPE_PP(zdata
) == IS_OBJECT
) {
83 if (key_type
== HASH_KEY_IS_STRING
) {
84 ekey
= php_url_encode(key
, key_len
, &ekey_len
);
85 newprefix_len
= key_suffix_len
+ ekey_len
+ key_prefix_len
+ 1;
86 newprefix
= emalloc(newprefix_len
+ 1);
90 memcpy(p
, key_prefix
, key_prefix_len
);
94 memcpy(p
, ekey
, ekey_len
);
99 memcpy(p
, key_suffix
, key_suffix_len
);
106 /* Is an integer key */
107 ekey_len
= spprintf(&ekey
, 12, "%ld", idx
);
108 newprefix_len
= key_prefix_len
+ num_prefix_len
+ ekey_len
+ key_suffix_len
+ 1;
109 newprefix
= emalloc(newprefix_len
+ 1);
113 memcpy(p
, key_prefix
, key_prefix_len
);
117 memcpy(p
, num_prefix
, num_prefix_len
);
120 memcpy(p
, ekey
, ekey_len
);
125 memcpy(p
, key_suffix
, key_suffix_len
);
132 php_url_encode_hash_ex(HASH_OF(*zdata
), formstr
, NULL
, 0, newprefix
, newprefix_len
, "]", 1, (Z_TYPE_PP(zdata
) == IS_OBJECT
? *zdata
: NULL
) TSRMLS_CC
);
135 } else if (Z_TYPE_PP(zdata
) == IS_NULL
|| Z_TYPE_PP(zdata
) == IS_RESOURCE
) {
136 /* Skip these types */
140 smart_str_appendl(formstr
, arg_sep
, arg_sep_len
);
142 /* Simple key=value */
143 smart_str_appendl(formstr
, key_prefix
, key_prefix_len
);
144 if (key_type
== HASH_KEY_IS_STRING
) {
145 ekey
= php_url_encode(key
, key_len
, &ekey_len
);
146 smart_str_appendl(formstr
, ekey
, ekey_len
);
151 smart_str_appendl(formstr
, num_prefix
, num_prefix_len
);
153 ekey_len
= spprintf(&ekey
, 12, "%ld", idx
);
154 smart_str_appendl(formstr
, ekey
, ekey_len
);
157 smart_str_appendl(formstr
, key_suffix
, key_suffix_len
);
158 smart_str_appendl(formstr
, "=", 1);
159 switch (Z_TYPE_PP(zdata
)) {
161 ekey
= php_url_encode(Z_STRVAL_PP(zdata
), Z_STRLEN_PP(zdata
), &ekey_len
);
165 ekey_len
= spprintf(&ekey
, 12, "%ld", Z_LVAL_PP(zdata
));
168 ekey_len
= spprintf(&ekey
, 48, "%.*G", (int) EG(precision
), Z_DVAL_PP(zdata
));
171 /* fall back on convert to string */
172 MAKE_STD_ZVAL(copyzval
);
174 zval_copy_ctor(copyzval
);
175 convert_to_string_ex(©zval
);
176 ekey
= php_url_encode(Z_STRVAL_P(copyzval
), Z_STRLEN_P(copyzval
), &ekey_len
);
177 zval_ptr_dtor(©zval
);
179 smart_str_appendl(formstr
, ekey
, ekey_len
);
188 /* {{{ proto string http_build_query(mixed formdata [, string prefix])
189 Generates a form-encoded query string from an associative array or object. */
190 PHP_FUNCTION(http_build_query
)
195 smart_str formstr
= {0};
197 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z|s", &formdata
, &prefix
, &prefix_len
) != SUCCESS
) {
201 if (Z_TYPE_P(formdata
) != IS_ARRAY
&& Z_TYPE_P(formdata
) != IS_OBJECT
) {
202 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Parameter 1 expected to be Array or Object. Incorrect value given.");
206 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
) TSRMLS_CC
) == FAILURE
) {
217 smart_str_0(&formstr
);
219 RETURN_STRINGL(formstr
.c
, formstr
.len
, 0);
228 * vim600: sw=4 ts=4 fdm=marker