X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=http_querystring_object.c;h=d629df045f2d93628b4ef65fc547293dcd836ef1;hp=55d355d8e480bc6840de2d2c74aaf11c61717020;hb=c8dff7011092296f9fcc12e68ad8eef18b19cdf4;hpb=669d2e6a8bdc642b6b52693f4593f199ddd7e8d2 diff --git a/http_querystring_object.c b/http_querystring_object.c index 55d355d..d629df0 100644 --- a/http_querystring_object.c +++ b/http_querystring_object.c @@ -20,14 +20,8 @@ #include "php_variables.h" #include "zend_interfaces.h" -#ifdef HAVE_ICONV -# undef PHP_ATOM_INC -# include "ext/iconv/php_iconv.h" -# include "ext/standard/url.h" -#endif - #include "php_http_api.h" -#include "php_http_url_api.h" +#include "php_http_querystring_api.h" #include "php_http_querystring_object.h" #include "php_http_exception_object.h" @@ -61,13 +55,17 @@ HTTP_BEGIN_ARGS(set, 1) HTTP_ARG_VAL(params, 0) HTTP_END_ARGS; +HTTP_BEGIN_ARGS(mod, 0) + HTTP_ARG_VAL(params, 0) +HTTP_END_ARGS; + HTTP_BEGIN_ARGS(__getter, 1) HTTP_ARG_VAL(name, 0) HTTP_ARG_VAL(defval, 0) HTTP_ARG_VAL(delete, 0) HTTP_END_ARGS; -#ifdef HAVE_ICONV +#ifdef HTTP_HAVE_ICONV HTTP_BEGIN_ARGS(xlate, 2) HTTP_ARG_VAL(from_encoding, 0) HTTP_ARG_VAL(to_encoding, 0) @@ -79,6 +77,24 @@ HTTP_BEGIN_ARGS(unserialize, 1) HTTP_ARG_VAL(serialized, 0) HTTP_END_ARGS; +HTTP_BEGIN_ARGS(offsetGet, 1) + HTTP_ARG_VAL(offset, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(offsetSet, 2) + HTTP_ARG_VAL(offset, 0) + HTTP_ARG_VAL(value, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(offsetExists, 1) + HTTP_ARG_VAL(offset, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(offsetUnset, 1) + HTTP_ARG_VAL(offset, 0) +HTTP_END_ARGS; + + #define OBJ_PROP_CE http_querystring_object_ce zend_class_entry *http_querystring_object_ce; zend_function_entry http_querystring_object_fe[] = { @@ -90,6 +106,7 @@ zend_function_entry http_querystring_object_fe[] = { HTTP_QUERYSTRING_ME(get, ZEND_ACC_PUBLIC) HTTP_QUERYSTRING_ME(set, ZEND_ACC_PUBLIC) + HTTP_QUERYSTRING_ME(mod, ZEND_ACC_PUBLIC) HTTP_QUERYSTRING_GME(getBool, ZEND_ACC_PUBLIC) HTTP_QUERYSTRING_GME(getInt, ZEND_ACC_PUBLIC) @@ -101,7 +118,7 @@ zend_function_entry http_querystring_object_fe[] = { #ifndef WONKY HTTP_QUERYSTRING_ME(singleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) #endif -#ifdef HAVE_ICONV +#ifdef HTTP_HAVE_ICONV HTTP_QUERYSTRING_ME(xlate, ZEND_ACC_PUBLIC) #endif @@ -109,6 +126,12 @@ zend_function_entry http_querystring_object_fe[] = { HTTP_QUERYSTRING_ME(serialize, ZEND_ACC_PUBLIC) HTTP_QUERYSTRING_ME(unserialize, ZEND_ACC_PUBLIC) + /* Implements ArrayAccess */ + HTTP_QUERYSTRING_ME(offsetGet, ZEND_ACC_PUBLIC) + HTTP_QUERYSTRING_ME(offsetSet, ZEND_ACC_PUBLIC) + HTTP_QUERYSTRING_ME(offsetExists, ZEND_ACC_PUBLIC) + HTTP_QUERYSTRING_ME(offsetUnset, ZEND_ACC_PUBLIC) + EMPTY_FUNCTION_ENTRY }; static zend_object_handlers http_querystring_object_handlers; @@ -118,7 +141,7 @@ PHP_MINIT_FUNCTION(http_querystring_object) HTTP_REGISTER_CLASS_EX(HttpQueryString, http_querystring_object, NULL, 0); #ifndef WONKY - zend_class_implements(http_querystring_object_ce TSRMLS_CC, 1, zend_ce_serializable); + zend_class_implements(http_querystring_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_arrayaccess); #endif DCL_STATIC_PROP_N(PRIVATE, instance); @@ -162,7 +185,7 @@ zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, http_que } ALLOC_HASHTABLE(OBJ_PROP(o)); - zend_hash_init(OBJ_PROP(o), 0, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); ov.handle = putObject(http_querystring_object, o); @@ -175,83 +198,10 @@ void _http_querystring_object_free(zend_object *object TSRMLS_DC) { http_querystring_object *o = (http_querystring_object *) object; - if (OBJ_PROP(o)) { - zend_hash_destroy(OBJ_PROP(o)); - FREE_HASHTABLE(OBJ_PROP(o)); - } - efree(o); + freeObject(o); } /* {{{ querystring helpers */ -#define http_querystring_update(qa, qs) _http_querystring_update((qa), (qs) TSRMLS_CC) -static inline void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC); -#define http_querystring_modify_array_ex(q, k, kl, pe) _http_querystring_modify_array_ex((q), (k), (kl), (pe) TSRMLS_CC) -static inline int _http_querystring_modify_array_ex(zval *qarray, char *key, int keylen, zval *params_entry TSRMLS_DC); -#define http_querystring_modify_array(q, p) _http_querystring_modify_array((q), (p) TSRMLS_CC) -static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC); -#define http_querystring_modify(q, p) _http_querystring_modify((q), (p) TSRMLS_CC) -static inline int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC); -#define http_querystring_get(o, t, n, l, def, del, r) _http_querystring_get((o), (t), (n), (l), (def), (del), (r) TSRMLS_CC) -static inline void _http_querystring_get(zval *this_ptr, int type, char *name, uint name_len, zval *defval, zend_bool del, zval *return_value TSRMLS_DC); -#ifdef HAVE_ICONV -#define http_querystring_xlate(a, p, ie, oe) _http_querystring_xlate((a), (p), (ie), (oe) TSRMLS_CC) -static inline int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC) -{ - HashPosition pos; - zval **entry = NULL; - char *xlate_str = NULL, *xkey, *kstr = NULL; - size_t xlate_len = 0, xlen; - uint klen = 0; - ulong kidx = 0; - - FOREACH_KEYLENVAL(pos, param, kstr, klen, kidx, entry) { - if (kstr) { - if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(kstr, klen-1, &xkey, &xlen, oe, ie)) { - http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", klen-1, kstr, ie, oe); - return FAILURE; - } - } - - if (Z_TYPE_PP(entry) == IS_STRING) { - if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), &xlate_str, &xlate_len, oe, ie)) { - if (kstr) { - efree(xkey); - } - 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); - return FAILURE; - } - if (kstr) { - add_assoc_stringl_ex(array, xkey, xlen+1, xlate_str, xlate_len, 0); - } else { - add_index_stringl(array, kidx, xlate_str, xlate_len, 0); - } - } else if (Z_TYPE_PP(entry) == IS_ARRAY) { - zval *subarray; - - MAKE_STD_ZVAL(subarray); - array_init(subarray); - if (kstr) { - add_assoc_zval_ex(array, xkey, xlen+1, subarray); - } else { - add_index_zval(array, kidx, subarray); - } - if (SUCCESS != http_querystring_xlate(subarray, *entry, ie, oe)) { - if (kstr) { - efree(xkey); - } - return FAILURE; - } - } - - if (kstr) { - kstr = NULL; - efree(xkey); - } - } - return SUCCESS; -} -#endif /* HAVE_ICONV */ -#ifndef WONKY #define http_querystring_instantiate(g) _http_querystring_instantiate((g) TSRMLS_CC) static inline zval *_http_querystring_instantiate(zend_bool global TSRMLS_DC) { @@ -262,110 +212,15 @@ static inline zval *_http_querystring_instantiate(zend_bool global TSRMLS_DC) MAKE_STD_ZVAL(zobj); Z_TYPE_P(zobj) = IS_OBJECT; - Z_OBJVAL_P(zobj) = http_querystring_object_new(http_querystring_object_ce); + zobj->value.obj = http_querystring_object_new(http_querystring_object_ce); zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj), NULL, "__construct", NULL, zglobal); zval_ptr_dtor(&zglobal); return zobj; } -#endif /* WONKY */ -static inline void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC) -{ - char *s = NULL; - size_t l = 0; - - if (Z_TYPE_P(qarray) != IS_ARRAY) { - convert_to_array(qarray); - } - if (SUCCESS == http_urlencode_hash_ex(Z_ARRVAL_P(qarray), 0, NULL, 0, &s, &l)) { - zval_dtor(qstring); - ZVAL_STRINGL(qstring, s, l, 0); - } else { - http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to update query string"); - } -} -static inline int _http_querystring_modify_array_ex(zval *qarray, char *key, int keylen, zval *params_entry TSRMLS_DC) -{ - zval **qarray_entry; - - /* delete */ - if (Z_TYPE_P(params_entry) == IS_NULL) { - return (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), key, keylen)); - } - - /* update */ - if (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), key, keylen, (void *) &qarray_entry)) { - zval equal; - - /* recursive */ - if (Z_TYPE_P(params_entry) == IS_ARRAY) { - return http_querystring_modify_array(*qarray_entry, params_entry); - } - /* equal */ - if ((SUCCESS == is_equal_function(&equal, *qarray_entry, params_entry TSRMLS_CC)) && Z_BVAL(equal)) { - return 0; - } - } - - /* add */ - ZVAL_ADDREF(params_entry); - add_assoc_zval_ex(qarray, key, keylen, params_entry); - return 1; -} -static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC) -{ - int rv = 0; - char *key; - uint keylen; - ulong idx; - HashPosition pos; - zval **params_entry; - - FOREACH_KEYLENVAL(pos, params, key, keylen, idx, params_entry) { - if (key) { - if (http_querystring_modify_array_ex(qarray, key, keylen, *params_entry)) { - rv = 1; - } - } else { - keylen = spprintf(&key, 0, "%lu", idx); - if (http_querystring_modify_array_ex(qarray, key, keylen, *params_entry)) { - rv = 1; - } - efree(key); - } - key = NULL; - } - - return rv; -} -static inline int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC) -{ - if (Z_TYPE_P(params) == IS_ARRAY) { - return http_querystring_modify_array(qarray, params); - } else if (Z_TYPE_P(params) == IS_OBJECT) { - if (!instanceof_function(Z_OBJCE_P(params), http_querystring_object_ce TSRMLS_CC)) { - zval temp_array; - INIT_ZARR(temp_array, HASH_OF(params)); - return http_querystring_modify_array(qarray, &temp_array); - } - return http_querystring_modify_array(qarray, GET_PROP_EX(params, queryArray)); - } else { - int rv; - zval array; - - INIT_PZVAL(&array); - array_init(&array); - - ZVAL_ADDREF(params); - convert_to_string_ex(¶ms); - sapi_module.treat_data(PARSE_STRING, estrdup(Z_STRVAL_P(params)), &array TSRMLS_CC); - zval_ptr_dtor(¶ms); - rv = http_querystring_modify_array(qarray, &array); - zval_dtor(&array); - return rv; - } -} + +#define http_querystring_get(o, t, n, l, def, del, r) _http_querystring_get((o), (t), (n), (l), (def), (del), (r) TSRMLS_CC) static inline void _http_querystring_get(zval *this_ptr, int type, char *name, uint name_len, zval *defval, zend_bool del, zval *return_value TSRMLS_DC) { zval **arrval, *qarray = GET_PROP(queryArray); @@ -495,8 +350,7 @@ PHP_METHOD(HttpQueryString, get) if (Z_TYPE_P(ztype) == IS_LONG) { type = Z_LVAL_P(ztype); } else if(Z_TYPE_P(ztype) == IS_STRING) { - switch (Z_STRVAL_P(ztype)[0]) - { + switch (Z_STRVAL_P(ztype)[0]) { case 'B': case 'b': type = HTTP_QUERYSTRING_TYPE_BOOL; break; case 'I': @@ -535,12 +389,42 @@ PHP_METHOD(HttpQueryString, set) } } - IF_RETVAL_USED { + if (return_value_used) { RETURN_PROP(queryString); } } /* }}} */ +/* {{{ proto HttpQueryString HttpQueryString::mod(mixed params) + * + * Copies the query string object and sets provided params at the clone. + * This is basically shorthand for: + *
+ * set($other_params);
+ * ?>
+ * 
+ */ +PHP_METHOD(HttpQueryString, mod) +{ + zval *orig, *zobj, *qarr, *qstr, *params; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶ms)) { + zobj = http_querystring_instantiate(0); + orig = GET_PROP(queryArray); + qarr = GET_PROP_EX(zobj, queryArray); + qstr = GET_PROP_EX(zobj, queryString); + + http_querystring_modify(qarr, orig); + http_querystring_modify(qarr, params); + http_querystring_update(qarr, qstr); + + RETURN_ZVAL(zobj, 1, 1); + } +} +/* }}} */ + #ifndef WONKY /* {{{ proto static HttpQueryString HttpQueryString::singleton([bool global = true]) * @@ -600,7 +484,7 @@ HTTP_QUERYSTRING_GETTER(getArray, IS_ARRAY); HTTP_QUERYSTRING_GETTER(getObject, IS_OBJECT); /* }}} */ -#ifdef HAVE_ICONV +#ifdef HTTP_HAVE_ICONV /* {{{ proto bool HttpQueryString::xlate(string ie, string oe) * * Converts the query string from the source encoding ie to the target encoding oe. @@ -671,6 +555,78 @@ PHP_METHOD(HttpQueryString, unserialize) } /* }}} */ +/* {{{ proto mixed HttpQueryString::offsetGet(string offset) + * + * Implements ArrayAccess. + */ +PHP_METHOD(HttpQueryString, offsetGet) +{ + char *offset_str; + int offset_len; + zval **value; + + if ( (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) && + (SUCCESS == zend_hash_find(Z_ARRVAL_P(GET_PROP(queryArray)), offset_str, offset_len + 1, (void *) &value))) { + RETVAL_ZVAL(*value, 1, 0); + } +} +/* }}} */ + +/* {{{ proto void HttpQueryString::offsetSet(string offset, mixed value) + * + * Implements ArrayAccess. + */ +PHP_METHOD(HttpQueryString, offsetSet) +{ + char *offset_str; + int offset_len; + zval *value; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &offset_str, &offset_len, &value)) { + zval *qarr = GET_PROP(queryArray), *qstr = GET_PROP(queryString); + + ZVAL_ADDREF(value); + add_assoc_zval_ex(qarr, offset_str, offset_len + 1, value); + http_querystring_update(qarr, qstr); + } +} +/* }}} */ + +/* {{{ proto bool HttpQueryString::offsetExists(string offset) + * + * Implements ArrayAccess. + */ +PHP_METHOD(HttpQueryString, offsetExists) +{ + char *offset_str; + int offset_len; + zval **value; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) { + RETURN_BOOL((SUCCESS == zend_hash_find(Z_ARRVAL_P(GET_PROP(queryArray)), offset_str, offset_len + 1, (void *) &value)) && (Z_TYPE_PP(value) != IS_NULL)); + } +} +/* }}} */ + +/* {{{ proto void HttpQueryString::offsetUnset(string offset) + * + * Implements ArrayAccess. + */ +PHP_METHOD(HttpQueryString, offsetUnset) +{ + char *offset_str; + int offset_len; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) { + zval *qarr = GET_PROP(queryArray); + + if (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarr), offset_str, offset_len + 1)) { + http_querystring_update(qarr, GET_PROP(queryString)); + } + } +} +/* }}} */ + #endif /* ZEND_ENGINE_2 */ /*