1 : /*
2 : +--------------------------------------------------------------------+
3 : | PECL :: http |
4 : +--------------------------------------------------------------------+
5 : | Redistribution and use in source and binary forms, with or without |
6 : | modification, are permitted provided that the conditions mentioned |
7 : | in the accompanying LICENSE file are met. |
8 : +--------------------------------------------------------------------+
9 : | Copyright (c) 2004-2007, Michael Wallner <mike@php.net> |
10 : +--------------------------------------------------------------------+
11 : */
12 :
13 : /* $Id: http_querystring_api.c,v 1.9 2007/02/22 11:04:37 mike Exp $ */
14 :
15 : #define HTTP_WANT_SAPI
16 : #include "php_http.h"
17 :
18 : #include "php_variables.h"
19 : #ifdef HTTP_HAVE_ICONV
20 : # undef PHP_ATOM_INC
21 : # include "ext/iconv/php_iconv.h"
22 : # include "ext/standard/url.h"
23 : #endif
24 :
25 : #include "php_http_api.h"
26 : #include "php_http_url_api.h"
27 : #include "php_http_querystring_api.h"
28 :
29 : #ifdef ZEND_ENGINE_2
30 : #define THIS_CE http_querystring_object_ce
31 : extern zend_class_entry *http_querystring_object_ce;
32 : #endif
33 :
34 :
35 : #define http_querystring_modify_array_ex(q, t, k, kl, i, pe) _http_querystring_modify_array_ex((q), (t), (k), (kl), (i), (pe) TSRMLS_CC)
36 : static inline int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC);
37 : #define http_querystring_modify_array(q, p) _http_querystring_modify_array((q), (p) TSRMLS_CC)
38 : static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC);
39 :
40 :
41 : #ifdef HTTP_HAVE_ICONV
42 : PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC)
43 6 : {
44 : HashPosition pos;
45 6 : zval **entry = NULL;
46 6 : char *xlate_str = NULL, *xkey;
47 6 : size_t xlate_len = 0, xlen;
48 6 : HashKey key = initHashKey(0);
49 :
50 14 : FOREACH_KEYVAL(pos, param, key, entry) {
51 8 : if (key.type == HASH_KEY_IS_STRING) {
52 6 : if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(key.str, key.len-1, &xkey, &xlen, oe, ie)) {
53 0 : http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", key.len-1, key.str, ie, oe);
54 0 : return FAILURE;
55 : }
56 : }
57 :
58 8 : if (Z_TYPE_PP(entry) == IS_STRING) {
59 4 : if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), &xlate_str, &xlate_len, oe, ie)) {
60 0 : if (key.type == HASH_KEY_IS_STRING) {
61 0 : efree(xkey);
62 : }
63 0 : http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", Z_STRLEN_PP(entry), Z_STRVAL_PP(entry), ie, oe);
64 0 : return FAILURE;
65 : }
66 4 : if (key.type == HASH_KEY_IS_STRING) {
67 2 : add_assoc_stringl_ex(array, xkey, xlen+1, xlate_str, xlate_len, 0);
68 : } else {
69 2 : add_index_stringl(array, key.num, xlate_str, xlate_len, 0);
70 : }
71 4 : } else if (Z_TYPE_PP(entry) == IS_ARRAY) {
72 : zval *subarray;
73 :
74 4 : MAKE_STD_ZVAL(subarray);
75 4 : array_init(subarray);
76 4 : if (key.type == HASH_KEY_IS_STRING) {
77 4 : add_assoc_zval_ex(array, xkey, xlen+1, subarray);
78 : } else {
79 0 : add_index_zval(array, key.num, subarray);
80 : }
81 4 : if (SUCCESS != http_querystring_xlate(subarray, *entry, ie, oe)) {
82 0 : if (key.type == HASH_KEY_IS_STRING) {
83 0 : efree(xkey);
84 : }
85 0 : return FAILURE;
86 : }
87 : }
88 :
89 8 : if (key.type == HASH_KEY_IS_STRING) {
90 6 : efree(xkey);
91 : }
92 : }
93 6 : return SUCCESS;
94 : }
95 : #endif /* HAVE_ICONV */
96 :
97 : PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC)
98 17 : {
99 17 : char *s = NULL;
100 17 : size_t l = 0;
101 :
102 17 : if (Z_TYPE_P(qarray) != IS_ARRAY) {
103 0 : convert_to_array(qarray);
104 : }
105 17 : if (SUCCESS == http_urlencode_hash_ex(Z_ARRVAL_P(qarray), 0, NULL, 0, &s, &l)) {
106 17 : zval_dtor(qstring);
107 17 : ZVAL_STRINGL(qstring, s, l, 0);
108 : } else {
109 0 : http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to update query string");
110 : }
111 17 : }
112 :
113 : PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC)
114 16 : {
115 16 : if (Z_TYPE_P(params) == IS_ARRAY) {
116 7 : return http_querystring_modify_array(qarray, params);
117 9 : } else if (Z_TYPE_P(params) == IS_OBJECT) {
118 : #ifdef ZEND_ENGINE_2
119 4 : if (!instanceof_function(Z_OBJCE_P(params), http_querystring_object_ce TSRMLS_CC)) {
120 : #endif
121 : zval temp_array;
122 3 : INIT_ZARR(temp_array, HASH_OF(params));
123 3 : return http_querystring_modify_array(qarray, &temp_array);
124 : #ifdef ZEND_ENGINE_2
125 : }
126 1 : return http_querystring_modify_array(qarray, zend_read_property(THIS_CE, params, ZEND_STRS("queryArray")-1, 0 TSRMLS_CC));
127 : #endif
128 : } else {
129 : int rv;
130 : zval array;
131 :
132 5 : INIT_PZVAL(&array);
133 5 : array_init(&array);
134 :
135 5 : ZVAL_ADDREF(params);
136 5 : convert_to_string_ex(¶ms);
137 5 : sapi_module.treat_data(PARSE_STRING, estrdup(Z_STRVAL_P(params)), &array TSRMLS_CC);
138 5 : zval_ptr_dtor(¶ms);
139 5 : rv = http_querystring_modify_array(qarray, &array);
140 5 : zval_dtor(&array);
141 5 : return rv;
142 : }
143 : }
144 :
145 : static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC)
146 16 : {
147 16 : int rv = 0;
148 16 : HashKey key = initHashKey(0);
149 : HashPosition pos;
150 16 : zval **params_entry = NULL;
151 :
152 41 : FOREACH_KEYVAL(pos, params, key, params_entry) {
153 : /* only public properties */
154 25 : if ((key.type != HASH_KEY_IS_STRING || *key.str) && http_querystring_modify_array_ex(qarray, key.type, key.str, key.len, key.num, *params_entry)) {
155 21 : rv = 1;
156 : }
157 : }
158 :
159 16 : return rv;
160 : }
161 :
162 : static inline int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC)
163 23 : {
164 : zval **qarray_entry;
165 :
166 : /* delete */
167 23 : if (Z_TYPE_P(params_entry) == IS_NULL) {
168 2 : if (key_type == HASH_KEY_IS_STRING) {
169 2 : return (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), key, keylen));
170 : } else {
171 0 : return (SUCCESS == zend_hash_index_del(Z_ARRVAL_P(qarray), idx));
172 : }
173 : }
174 :
175 : /* update */
176 21 : if ( ((key_type == HASH_KEY_IS_STRING) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), key, keylen, (void *) &qarray_entry))) ||
177 : ((key_type == HASH_KEY_IS_LONG) && (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(qarray), idx, (void *) &qarray_entry)))) {
178 : zval equal;
179 :
180 : /* recursive */
181 6 : if (Z_TYPE_P(params_entry) == IS_ARRAY || Z_TYPE_P(params_entry) == IS_OBJECT) {
182 2 : return http_querystring_modify(*qarray_entry, params_entry);
183 : }
184 : /* equal */
185 4 : if ((SUCCESS == is_equal_function(&equal, *qarray_entry, params_entry TSRMLS_CC)) && Z_BVAL(equal)) {
186 2 : return 0;
187 : }
188 : }
189 :
190 : /* add */
191 17 : ZVAL_ADDREF(params_entry);
192 17 : if (Z_TYPE_P(params_entry) == IS_OBJECT) {
193 1 : convert_to_array_ex(¶ms_entry);
194 : }
195 17 : if (key_type == HASH_KEY_IS_STRING) {
196 15 : add_assoc_zval_ex(qarray, key, keylen, params_entry);
197 : } else {
198 2 : add_index_zval(qarray, idx, params_entry);
199 : }
200 17 : return 1;
201 : }
202 :
203 : /*
204 : * Local variables:
205 : * tab-width: 4
206 : * c-basic-offset: 4
207 : * End:
208 : * vim600: noet sw=4 ts=4 fdm=marker
209 : * vim<600: noet sw=4 ts=4
210 : */
|