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 +----------------------------------------------------------------------+
22 #include "php_http_api.h"
24 #include "ext/standard/url.h"
26 #define URL_DEFAULT_ARG_SEP "&"
28 /* {{{ php_url_encode_hash */
29 PHP_HTTP_API
int php_url_encode_hash_ex(HashTable
*ht
, smart_str
*formstr
,
30 const char *num_prefix
, int num_prefix_len
,
31 const char *key_prefix
, int key_prefix_len
,
32 const char *key_suffix
, int key_suffix_len
,
35 char *arg_sep
= NULL
, *key
= NULL
, *ekey
, *newprefix
, *p
;
36 int arg_sep_len
, key_len
, ekey_len
, key_type
, newprefix_len
;
38 zval
**zdata
= NULL
, *copyzval
;
44 if (ht
->nApplyCount
> 0) {
45 /* Prevent recursion */
49 arg_sep
= INI_STR("arg_separator.output");
50 if (!arg_sep
|| !strlen(arg_sep
)) {
51 arg_sep
= URL_DEFAULT_ARG_SEP
;
53 arg_sep_len
= strlen(arg_sep
);
55 for (zend_hash_internal_pointer_reset(ht
);
56 (key_type
= zend_hash_get_current_key_ex(ht
, &key
, &key_len
, &idx
, 0, NULL
)) != HASH_KEY_NON_EXISTANT
;
57 zend_hash_move_forward(ht
)
59 if (key_type
== HASH_KEY_IS_STRING
&& key_len
&& key
[key_len
-1] == '\0') {
60 /* We don't want that trailing NULL */
65 /* handling for private & protected object properties */
66 if (key
&& *key
== '\0' && type
!= NULL
) {
69 zend_object
*zobj
= zend_objects_get_address(type TSRMLS_CC
);
70 if (zend_check_property_access(zobj
, key TSRMLS_CC
) != SUCCESS
) {
71 /* private or protected property access outside of the class */
74 zend_unmangle_property_name(key
, &tmp
, &key
);
75 key_len
= strlen(key
);
79 if (zend_hash_get_current_data_ex(ht
, (void **)&zdata
, NULL
) == FAILURE
|| !zdata
|| !(*zdata
)) {
80 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Error traversing form data array.");
83 if (Z_TYPE_PP(zdata
) == IS_ARRAY
|| Z_TYPE_PP(zdata
) == IS_OBJECT
) {
84 if (key_type
== HASH_KEY_IS_STRING
) {
85 ekey
= php_url_encode(key
, key_len
, &ekey_len
);
86 newprefix_len
= key_suffix_len
+ ekey_len
+ key_prefix_len
+ 1;
87 newprefix
= emalloc(newprefix_len
+ 1);
91 memcpy(p
, key_prefix
, key_prefix_len
);
95 memcpy(p
, ekey
, ekey_len
);
100 memcpy(p
, key_suffix
, key_suffix_len
);
107 /* Is an integer key */
108 ekey_len
= spprintf(&ekey
, 12, "%ld", idx
);
109 newprefix_len
= key_prefix_len
+ num_prefix_len
+ ekey_len
+ key_suffix_len
+ 1;
110 newprefix
= emalloc(newprefix_len
+ 1);
114 memcpy(p
, key_prefix
, key_prefix_len
);
118 memcpy(p
, num_prefix
, num_prefix_len
);
121 memcpy(p
, ekey
, ekey_len
);
126 memcpy(p
, key_suffix
, key_suffix_len
);
133 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
);
136 } else if (Z_TYPE_PP(zdata
) == IS_NULL
|| Z_TYPE_PP(zdata
) == IS_RESOURCE
) {
137 /* Skip these types */
141 smart_str_appendl(formstr
, arg_sep
, arg_sep_len
);
143 /* Simple key=value */
144 smart_str_appendl(formstr
, key_prefix
, key_prefix_len
);
145 if (key_type
== HASH_KEY_IS_STRING
) {
146 ekey
= php_url_encode(key
, key_len
, &ekey_len
);
147 smart_str_appendl(formstr
, ekey
, ekey_len
);
152 smart_str_appendl(formstr
, num_prefix
, num_prefix_len
);
154 ekey_len
= spprintf(&ekey
, 12, "%ld", idx
);
155 smart_str_appendl(formstr
, ekey
, ekey_len
);
158 smart_str_appendl(formstr
, key_suffix
, key_suffix_len
);
159 smart_str_appendl(formstr
, "=", 1);
160 switch (Z_TYPE_PP(zdata
)) {
162 ekey
= php_url_encode(Z_STRVAL_PP(zdata
), Z_STRLEN_PP(zdata
), &ekey_len
);
166 ekey_len
= spprintf(&ekey
, 12, "%ld", Z_LVAL_PP(zdata
));
169 ekey_len
= spprintf(&ekey
, 48, "%.*G", (int) EG(precision
), Z_DVAL_PP(zdata
));
172 /* fall back on convert to string */
173 MAKE_STD_ZVAL(copyzval
);
175 zval_copy_ctor(copyzval
);
176 convert_to_string_ex(©zval
);
177 ekey
= php_url_encode(Z_STRVAL_P(copyzval
), Z_STRLEN_P(copyzval
), &ekey_len
);
178 zval_ptr_dtor(©zval
);
180 smart_str_appendl(formstr
, ekey
, ekey_len
);
189 /* {{{ proto string http_build_query(mixed formdata [, string prefix])
190 Generates a form-encoded query string from an associative array or object. */
191 PHP_FUNCTION(http_build_query
)
196 smart_str formstr
= {0};
198 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z|s", &formdata
, &prefix
, &prefix_len
) != SUCCESS
) {
202 if (Z_TYPE_P(formdata
) != IS_ARRAY
&& Z_TYPE_P(formdata
) != IS_OBJECT
) {
203 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Parameter 1 expected to be Array or Object. Incorrect value given.");
207 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
) {
218 smart_str_0(&formstr
);
220 RETURN_STRINGL(formstr
.c
, formstr
.len
, 0);
229 * vim600: sw=4 ts=4 fdm=marker