From b8e107f69fcd64811e2dd428b6980412749cbc7b Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 30 Jan 2006 14:28:33 +0000 Subject: [PATCH] - fix some typos - add HttpQueryString class and tests --- config.m4 | 4 +- config.w32 | 2 +- http.c | 2 + http_exception_object.c | 4 + http_querystring_object.c | 469 +++++++++++++++++++++++++++++++++ php_http_api.h | 4 +- php_http_querystring_object.h | 61 +++++ php_http_std_defs.h | 3 +- tests/HttpQueryString_001.phpt | 116 ++++++++ tests/HttpQueryString_002.phpt | 99 +++++++ 10 files changed, 758 insertions(+), 6 deletions(-) create mode 100644 http_querystring_object.c create mode 100644 php_http_querystring_object.h create mode 100644 tests/HttpQueryString_001.phpt create mode 100644 tests/HttpQueryString_002.phpt diff --git a/config.m4 b/config.m4 index 53cde18..f8ae079 100644 --- a/config.m4 +++ b/config.m4 @@ -231,7 +231,7 @@ dnl ---- http_api.c http_cache_api.c http_request_api.c http_date_api.c \ http_headers_api.c http_message_api.c http_send_api.c http_url_api.c \ http_info_api.c http_request_method_api.c http_encoding_api.c \ - http_filter_api.c http_request_body_api.c \ + http_filter_api.c http_request_body_api.c http_querystring_object.c \ http_deflatestream_object.c http_inflatestream_object.c" PHP_NEW_EXTENSION([http], $PHP_HTTP_SOURCES, $ext_shared) PHP_ADD_BUILD_DIR($ext_builddir/phpstr, 1) @@ -243,7 +243,7 @@ dnl ---- php_http_encoding_api.h phpstr/phpstr.h missing.h php_http_request_body_api.h \ php_http_exception_object.h php_http_message_object.h php_http_request_object.h \ php_http_requestpool_object.h php_http_response_object.h php_http_util_object.h \ - php_http_deflatestream_object.h php_http_inflatestream_object.h" + php_http_querystring_object.h php_http_deflatestream_object.h php_http_inflatestream_object.h" ifdef([PHP_INSTALL_HEADERS], [ PHP_INSTALL_HEADERS(ext/http, $PHP_HTTP_HEADERS) ], [ diff --git a/config.w32 b/config.w32 index af583c2..049ac07 100644 --- a/config.w32 +++ b/config.w32 @@ -54,7 +54,7 @@ if (PHP_HTTP != "no") { "http_request_api.c http_date_api.c http_headers_api.c "+ "http_message_api.c http_send_api.c http_url_api.c "+ "http_info_api.c http_request_method_api.c http_encoding_api.c "+ - "http_filter_api.c http_request_body_api.c "+ + "http_filter_api.c http_request_body_api.c http_querystring_object.c"+ "http_deflatestream_object.c http_inflatestream_object.c", null, "/I\"" + configure_module_dirname + "/phpstr\""); diff --git a/http.c b/http.c index 4c285ef..899083f 100644 --- a/http.c +++ b/http.c @@ -39,6 +39,7 @@ # include "php_http_filter_api.h" # include "php_http_util_object.h" # include "php_http_message_object.h" +# include "php_http_querystring_object.h" # ifndef WONKY # include "php_http_response_object.h" # endif @@ -251,6 +252,7 @@ PHP_MINIT_FUNCTION(http) if ( (SUCCESS != PHP_MINIT_CALL(http_filter)) || (SUCCESS != PHP_MINIT_CALL(http_util_object)) || (SUCCESS != PHP_MINIT_CALL(http_message_object)) || + (SUCCESS != PHP_MINIT_CALL(http_querystring_object))|| # ifndef WONKY (SUCCESS != PHP_MINIT_CALL(http_response_object)) || # endif /* WONKY */ diff --git a/http_exception_object.c b/http_exception_object.c index 294239f..422f6ce 100644 --- a/http_exception_object.c +++ b/http_exception_object.c @@ -31,6 +31,7 @@ zend_class_entry *HTTP_EX_CE(request_pool); zend_class_entry *HTTP_EX_CE(socket); zend_class_entry *HTTP_EX_CE(response); zend_class_entry *HTTP_EX_CE(url); +zend_class_entry *HTTP_EX_CE(querystring); PHP_MINIT_FUNCTION(http_exception_object) { @@ -47,6 +48,7 @@ PHP_MINIT_FUNCTION(http_exception_object) HTTP_REGISTER_EXCEPTION(HttpSocketException, HTTP_EX_CE(socket), HTTP_EX_DEF_CE); HTTP_REGISTER_EXCEPTION(HttpResponseException, HTTP_EX_CE(response), HTTP_EX_DEF_CE); HTTP_REGISTER_EXCEPTION(HttpUrlException, HTTP_EX_CE(url), HTTP_EX_DEF_CE); + HTTP_REGISTER_EXCEPTION(HttpQueryStringException, HTTP_EX_CE(querystring), HTTP_EX_DEF_CE); zend_declare_property_null(HTTP_EX_CE(request_pool), "exceptionStack", lenof("exceptionStack"), ZEND_ACC_PUBLIC TSRMLS_CC); @@ -62,6 +64,7 @@ PHP_MINIT_FUNCTION(http_exception_object) HTTP_LONG_CONSTANT("HTTP_E_SOCKET", HTTP_E_SOCKET); HTTP_LONG_CONSTANT("HTTP_E_RESPONSE", HTTP_E_RESPONSE); HTTP_LONG_CONSTANT("HTTP_E_URL", HTTP_E_URL); + HTTP_LONG_CONSTANT("HTTP_E_QUERYSTRING", HTTP_E_QUERYSTRING); return SUCCESS; } @@ -89,6 +92,7 @@ zend_class_entry *_http_exception_get_for_code(long code) case HTTP_E_SOCKET: ex = HTTP_EX_CE(socket); break; case HTTP_E_RESPONSE: ex = HTTP_EX_CE(response); break; case HTTP_E_URL: ex = HTTP_EX_CE(url); break; + case HTTP_E_QUERYSTRING: ex = HTTP_EX_CE(querystring); break; } return ex; diff --git a/http_querystring_object.c b/http_querystring_object.c new file mode 100644 index 0000000..7195459 --- /dev/null +++ b/http_querystring_object.c @@ -0,0 +1,469 @@ +/* + +--------------------------------------------------------------------+ + | PECL :: http | + +--------------------------------------------------------------------+ + | Redistribution and use in source and binary forms, with or without | + | modification, are permitted provided that the conditions mentioned | + | in the accompanying LICENSE file are met. | + +--------------------------------------------------------------------+ + | Copyright (c) 2004-2006, Michael Wallner | + +--------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#include "php_http.h" + +#ifdef ZEND_ENGINE_2 + +#include "zend_interfaces.h" + +#include "php_http_api.h" +#include "php_http_url_api.h" +#include "php_http_querystring_object.h" +#include "php_http_exception_object.h" + +#define HTTP_BEGIN_ARGS(method, ret_ref, req_args) HTTP_BEGIN_ARGS_EX(HttpQueryString, method, ret_ref, req_args) +#define HTTP_EMPTY_ARGS(method, ret_ref) HTTP_EMPTY_ARGS_EX(HttpQueryString, method, ret_ref) +#define HTTP_QUERYSTRING_ME(method, visibility) PHP_ME(HttpQueryString, method, HTTP_ARGS(HttpQueryString, method), visibility) + +HTTP_BEGIN_ARGS(__construct, 0, 0) + HTTP_ARG_VAL(global, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(getInstance, 0, 0) + HTTP_ARG_VAL(global, 0) +HTTP_END_ARGS; + +HTTP_EMPTY_ARGS(__toString, 0); + +HTTP_BEGIN_ARGS(get, 0, 0) + HTTP_ARG_VAL(name, 0) + HTTP_ARG_VAL(type, 0) + HTTP_ARG_VAL(defval, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(set, 0, 2) + HTTP_ARG_VAL(name, 0) + HTTP_ARG_VAL(value, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(del, 0, 1) + HTTP_ARG_VAL(params, 0) +HTTP_END_ARGS; + +HTTP_BEGIN_ARGS(mod, 0, 1) + HTTP_ARG_VAL(params, 0) +HTTP_END_ARGS; + +#define http_querystring_object_declare_default_properties() _http_querystring_object_declare_default_properties(TSRMLS_C) +static inline void _http_querystring_object_declare_default_properties(TSRMLS_D); + +#define GET_STATIC_PROP(n) *GET_STATIC_PROP_EX(http_querystring_object_ce, n) +#define SET_STATIC_PROP(n, v) SET_STATIC_PROP_EX(http_querystring_object_ce, n, v) +#define OBJ_PROP_CE http_querystring_object_ce +zend_class_entry *http_querystring_object_ce; +zend_function_entry http_querystring_object_fe[] = { + HTTP_QUERYSTRING_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR|ZEND_ACC_FINAL) + HTTP_QUERYSTRING_ME(__toString, ZEND_ACC_PUBLIC) + HTTP_QUERYSTRING_ME(get, ZEND_ACC_PUBLIC) + HTTP_QUERYSTRING_ME(set, ZEND_ACC_PUBLIC) + HTTP_QUERYSTRING_ME(del, ZEND_ACC_PUBLIC) + HTTP_QUERYSTRING_ME(mod, ZEND_ACC_PUBLIC) + HTTP_QUERYSTRING_ME(getInstance, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + + EMPTY_FUNCTION_ENTRY +}; +static zend_object_handlers http_querystring_object_handlers; + +PHP_MINIT_FUNCTION(http_querystring_object) +{ + HTTP_REGISTER_CLASS_EX(HttpQueryString, http_querystring_object, NULL, 0); + + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_BOOL", HTTP_QUERYSTRING_TYPE_BOOL); + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_INT", HTTP_QUERYSTRING_TYPE_INT); + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_FLOAT", HTTP_QUERYSTRING_TYPE_FLOAT); + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_STRING", HTTP_QUERYSTRING_TYPE_STRING); + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_ARRAY", HTTP_QUERYSTRING_TYPE_ARRAY); + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_OBJECT", HTTP_QUERYSTRING_TYPE_OBJECT); + + return SUCCESS; +} + +zend_object_value _http_querystring_object_new(zend_class_entry *ce TSRMLS_DC) +{ + return http_querystring_object_new_ex(ce, NULL); +} + +zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, http_querystring_object **ptr TSRMLS_DC) +{ + zend_object_value ov; + http_querystring_object *o; + + o = ecalloc(1, sizeof(http_querystring_object)); + o->zo.ce = ce; + + if (ptr) { + *ptr = o; + } + + ALLOC_HASHTABLE(OBJ_PROP(o)); + zend_hash_init(OBJ_PROP(o), 0, 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); + ov.handlers = &http_querystring_object_handlers; + + return ov; +} + +static inline void _http_querystring_object_declare_default_properties(TSRMLS_D) +{ + zend_class_entry *ce = http_querystring_object_ce; + + DCL_STATIC_PROP_N(PRIVATE, instance); + + DCL_PROP_N(PRIVATE, queryArray); + DCL_PROP(PRIVATE, string, queryString, ""); + +#ifndef WONKY + DCL_CONST(long, "TYPE_BOOL", HTTP_QUERYSTRING_TYPE_BOOL); + DCL_CONST(long, "TYPE_INT", HTTP_QUERYSTRING_TYPE_INT); + DCL_CONST(long, "TYPE_FLOAT", HTTP_QUERYSTRING_TYPE_FLOAT); + DCL_CONST(long, "TYPE_STRING", HTTP_QUERYSTRING_TYPE_STRING); + DCL_CONST(long, "TYPE_ARRAY", HTTP_QUERYSTRING_TYPE_ARRAY); + DCL_CONST(long, "TYPE_OBJECT", HTTP_QUERYSTRING_TYPE_OBJECT); +#endif +} + +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); +} + +#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) +{ + 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"); + } +} + +#define http_querystring_modify_array(a, k, l, v) _http_querystring_modify_array((a), (k), (l), (v) TSRMLS_CC) +static inline int _http_querystring_modify_array(zval *qarray, char *key, uint keylen, zval *data TSRMLS_DC) +{ + if (Z_TYPE_P(data) == IS_NULL) { + if (SUCCESS != zend_hash_del(Z_ARRVAL_P(qarray), key, keylen + 1)) { + return 0; + } + } else { + ZVAL_ADDREF(data); + add_assoc_zval(qarray, key, data); + } + return 1; +} + +#define http_querystring_instantiate(g) _http_querystring_instantiate((g) TSRMLS_CC) +static inline zval *_http_querystring_instantiate(zend_bool global TSRMLS_DC) +{ + zval *zobj, *zglobal; + + MAKE_STD_ZVAL(zglobal); + ZVAL_BOOL(zglobal, global); + + MAKE_STD_ZVAL(zobj); + Z_TYPE_P(zobj) = IS_OBJECT; + Z_OBJVAL_P(zobj) = 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; +} + +/* {{{ proto void HttpQueryString::__construct([bool global = true]) + * + * Creates a new HttpQueryString object instance. + * Operates on and modifies $_GET and $_SERVER['QUERY_STRING'] if global is TRUE. + */ +PHP_METHOD(HttpQueryString, __construct) +{ + zend_bool global = 1; + zval *qarray = NULL, *qstring = NULL, **_GET, **_SERVER, **QUERY_STRING; + + SET_EH_THROW_HTTP(); + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global)) { + if (global) { + if ( (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &_SERVER)) && + (Z_TYPE_PP(_SERVER) == IS_ARRAY) && + (SUCCESS == zend_hash_find(Z_ARRVAL_PP(_SERVER), "QUERY_STRING", sizeof("QUERY_STRING"), (void **) &QUERY_STRING))) { + + qstring = *QUERY_STRING; + + if ((SUCCESS == zend_hash_find(&EG(symbol_table), "_GET", sizeof("_GET"), (void **) &_GET)) && (Z_TYPE_PP(_GET) == IS_ARRAY)) { + qarray = *_GET; + } else { + http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Could not acquire reference to superglobal GET array"); + } + } else { + http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Could not acquire reference to QUERY_STRING"); + } + + if (qarray && qstring) { + if (Z_TYPE_P(qstring) != IS_STRING) { + convert_to_string(qstring); + } + + SET_PROP(queryArray, qarray); + SET_PROP(queryString, qstring); + GET_PROP(queryArray)->is_ref = 1; + GET_PROP(queryString)->is_ref = 1; + } + } else { + qarray = ecalloc(1, sizeof(zval)); + array_init(qarray); + SET_PROP(queryArray, qarray); + UPD_STRL(queryString, "", 0); + } + } + SET_EH_NORMAL(); +} +/* }}} */ + +/* {{{ proto string HttpQueryString::__toString() + * + * Returns the string representation. + */ +PHP_METHOD(HttpQueryString, __toString) +{ + NO_ARGS; + RETURN_PROP(queryString); +} +/* }}} */ + +/* {{{ proto mixed HttpQueryString::get([string key[, mixed type = 0[, mixed defval = NULL[, bool delete = false]]]]) + * + * Get (part of) the query string. + * + * The type parameter is either one of the HttpQueryString::TYPE_* constants or a type abbreviation like + * "b" for bool, "i" for int, "f" for float, "s" for string, "a" for array and "o" for a stdClass object. + */ +PHP_METHOD(HttpQueryString, get) +{ + char *name = NULL; + int name_len = 0; + long type = 0; + zend_bool del = 0; + zval *ztype = NULL, *defval = NULL; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szzb", &name, &name_len, &ztype, &defval, &del)) { + if (name && name_len) { + zval **arrval, *qarray = GET_PROP(queryArray); + + if (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), name, name_len + 1, (void **) &arrval)) { + RETVAL_ZVAL(*arrval, 1, 0); + + if (ztype) { + if (Z_TYPE_P(ztype) == IS_LONG) { + type = Z_LVAL_P(ztype); + } else if(Z_TYPE_P(ztype) == IS_STRING) { + switch (tolower(Z_STRVAL_P(ztype)[0])) + { + case 'b': + type = HTTP_QUERYSTRING_TYPE_BOOL; + break; + case 'i': + type = HTTP_QUERYSTRING_TYPE_INT; + break; + case 'f': + type = HTTP_QUERYSTRING_TYPE_FLOAT; + break; + case 's': + type = HTTP_QUERYSTRING_TYPE_STRING; + break; + case 'a': + type = HTTP_QUERYSTRING_TYPE_ARRAY; + break; + case 'o': + type = HTTP_QUERYSTRING_TYPE_OBJECT; + break; + } + } + if (type) { + convert_to_type(type, return_value); + } + } + + if (del && (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), name, name_len + 1))) { + http_querystring_update(qarray, GET_PROP(queryString)); + } + } else if(defval) { + RETURN_ZVAL(defval, 1, 0); + } + } else { + RETURN_PROP(queryString); + } + } +} +/* }}} */ + +/* {{{ proto string HttpQueryString::set(string name, mixed value) + * + * Set a query string entry. + */ +PHP_METHOD(HttpQueryString, set) +{ + char *name; + int name_len; + zval *value; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, &value)) { + zval *qarray = GET_PROP(queryArray); + + if (http_querystring_modify_array(qarray, name, name_len, value)) { + http_querystring_update(qarray, GET_PROP(queryString)); + } + } + + IF_RETVAL_USED { + RETURN_PROP(queryString); + } +} +/* }}} */ + +/* {{{ proto string HttpQueryString::del(mixed param) + * + * Deletes entry/entries from the query string. + */ +PHP_METHOD(HttpQueryString, del) +{ + zval *params; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶ms)) { + zval *qarray = GET_PROP(queryArray); + + if (Z_TYPE_P(params) == IS_ARRAY) { + HashPosition pos; + zval **name; + + FOREACH_VAL(pos, params, name) { + ZVAL_ADDREF(*name); + convert_to_string_ex(name); + zend_hash_del(Z_ARRVAL_P(qarray), Z_STRVAL_PP(name), Z_STRLEN_PP(name) + 1); + zval_ptr_dtor(name); + } + + http_querystring_update(qarray, GET_PROP(queryString)); + } else { + ZVAL_ADDREF(params); + convert_to_string_ex(¶ms); + if (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), Z_STRVAL_P(params), Z_STRLEN_P(params) + 1)) { + http_querystring_update(qarray, GET_PROP(queryString)); + } + zval_ptr_dtor(¶ms); + } + } + IF_RETVAL_USED { + RETURN_PROP(queryString); + } +} +/* }}} */ + +/* {{{ proto string HttpQueryString::mod(array params) + * + * Modifies the query string according to params. NULL values will unset the variable. + */ +PHP_METHOD(HttpQueryString, mod) +{ + zval *params; + + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", ¶ms)) { + zval **value, *qarray = GET_PROP(queryArray); + HashPosition pos; + char *key = NULL; + uint keylen = 0; + ulong idx = 0; + + FOREACH_KEYLENVAL(pos, params, key, keylen, idx, value) { + if (key) { + http_querystring_modify_array(qarray, key, keylen, *value); + } else { + keylen = spprintf(&key, 0, "%lu", idx); + http_querystring_modify_array(qarray, key, keylen, *value); + efree(key); + } + key = NULL; + } + + http_querystring_update(qarray, GET_PROP(queryString)); + } + + IF_RETVAL_USED { + RETURN_PROP(queryString); + } +} +/* }}} */ + +/* {{{ proto HttpQueryString HttpQueryString::getInstance([bool global = true]) + * + * Get a single instance (differentiates between the global setting). + */ +PHP_METHOD(HttpQueryString, getInstance) +{ + zend_bool global = 1; + zval *instance = GET_STATIC_PROP(instance); + + SET_EH_THROW_HTTP(); + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global)) { + zval **zobj_ptr = NULL, *zobj = NULL; + + if (Z_TYPE_P(instance) == IS_ARRAY) { + if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(instance), global, (void **) &zobj_ptr)) { + RETVAL_ZVAL(*zobj_ptr, 1, 0); + } else { + zobj = http_querystring_instantiate(global); + add_index_zval(instance, global, zobj); + RETVAL_OBJECT(zobj, 1); + } + } else { + MAKE_STD_ZVAL(instance); + array_init(instance); + + zobj = http_querystring_instantiate(global); + add_index_zval(instance, global, zobj); + RETVAL_OBJECT(zobj, 1); + + SET_STATIC_PROP(instance, instance); + zval_ptr_dtor(&instance); + } + } + SET_EH_NORMAL(); +} +/* }}} */ + +#endif /* ZEND_ENGINE_2 */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ + diff --git a/php_http_api.h b/php_http_api.h index 2c54e2b..171ed2e 100644 --- a/php_http_api.h +++ b/php_http_api.h @@ -162,7 +162,7 @@ static inline zval *_convert_to_type(int type, zval *z) case IS_NULL: convert_to_null(z); break; case IS_BOOL: convert_to_boolean(z); break; case IS_LONG: convert_to_long(z); break; - case IS_DOUBLE: convert_to_array(z); break; + case IS_DOUBLE: convert_to_double(z); break; case IS_STRING: convert_to_string(z); break; case IS_ARRAY: convert_to_array(z); break; case IS_OBJECT: convert_to_object(z); break; @@ -180,7 +180,7 @@ static inline zval *_convert_to_type_ex(int type, zval *z, zval **p) case IS_NULL: convert_to_null_ex(&z); break; case IS_BOOL: convert_to_boolean_ex(&z); break; case IS_LONG: convert_to_long_ex(&z); break; - case IS_DOUBLE: convert_to_array_ex(&z); break; + case IS_DOUBLE: convert_to_double_ex(&z); break; case IS_STRING: convert_to_string_ex(&z); break; case IS_ARRAY: convert_to_array_ex(&z); break; case IS_OBJECT: convert_to_object_ex(&z); break; diff --git a/php_http_querystring_object.h b/php_http_querystring_object.h new file mode 100644 index 0000000..a92149d --- /dev/null +++ b/php_http_querystring_object.h @@ -0,0 +1,61 @@ +/* + +--------------------------------------------------------------------+ + | PECL :: http | + +--------------------------------------------------------------------+ + | Redistribution and use in source and binary forms, with or without | + | modification, are permitted provided that the conditions mentioned | + | in the accompanying LICENSE file are met. | + +--------------------------------------------------------------------+ + | Copyright (c) 2004-2006, Michael Wallner | + +--------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef PHP_HTTP_QUERYSTRING_OBJECT_H +#define PHP_HTTP_QUERYSTRING_OBJECT_H +#ifdef ZEND_ENGINE_2 + +typedef struct { + zend_object zo; +} http_querystring_object; + +#define HTTP_QUERYSTRING_TYPE_BOOL IS_BOOL +#define HTTP_QUERYSTRING_TYPE_INT IS_LONG +#define HTTP_QUERYSTRING_TYPE_FLOAT IS_DOUBLE +#define HTTP_QUERYSTRING_TYPE_STRING IS_STRING +#define HTTP_QUERYSTRING_TYPE_ARRAY IS_ARRAY +#define HTTP_QUERYSTRING_TYPE_OBJECT IS_OBJECT + +extern zend_class_entry *http_querystring_object_ce; +extern zend_function_entry http_querystring_object_fe[]; + +extern PHP_MINIT_FUNCTION(http_querystring_object); + +#define http_querystring_object_new(ce) _http_querystring_object_new((ce) TSRMLS_CC) +extern zend_object_value _http_querystring_object_new(zend_class_entry *ce TSRMLS_DC); +#define http_querystring_object_new_ex(ce, ptr) _http_querystring_object_new_ex((ce), (ptr) TSRMLS_CC) +extern zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, http_querystring_object **ptr TSRMLS_DC); +#define http_querystring_object_free(o) _http_querystring_object_free((o) TSRMLS_CC) +extern void _http_querystring_object_free(zend_object *object TSRMLS_DC); + +PHP_METHOD(HttpQueryString, __construct); +PHP_METHOD(HttpQueryString, __toString); +PHP_METHOD(HttpQueryString, get); +PHP_METHOD(HttpQueryString, set); +PHP_METHOD(HttpQueryString, del); +PHP_METHOD(HttpQueryString, mod); +PHP_METHOD(HttpQueryString, getInstance); + +#endif +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ + diff --git a/php_http_std_defs.h b/php_http_std_defs.h index 51b9a51..92defa0 100644 --- a/php_http_std_defs.h +++ b/php_http_std_defs.h @@ -165,7 +165,7 @@ typedef int STATUS; zend_hash_get_current_data_ex(hash, (void **) &val, &pos) == SUCCESS; \ zend_hash_move_forward_ex(hash, &pos)) -#define FOREACH_KEYLENVAL(pos, array, strkey, keylen, numkey, val) FOREACH_HASH_KEYVAL(pos, Z_ARRVAL_P(array), strkey, keylen, numkey, val) +#define FOREACH_KEYLENVAL(pos, array, strkey, keylen, numkey, val) FOREACH_HASH_KEYLENVAL(pos, Z_ARRVAL_P(array), strkey, keylen, numkey, val) #define FOREACH_HASH_KEYLENVAL(pos, hash, strkey, keylen, numkey, val) \ for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \ zend_hash_get_current_key_ex(hash, &strkey, &keylen, &numkey, 0, &pos) != HASH_KEY_NON_EXISTANT && \ @@ -310,6 +310,7 @@ typedef int STATUS; #define HTTP_E_SOCKET 10L #define HTTP_E_RESPONSE 11L #define HTTP_E_URL 12L +#define HTTP_E_QUERYSTRING 13L #ifdef ZEND_ENGINE_2 # define HTTP_BEGIN_ARGS_EX(class, method, ret_ref, req_args) static ZEND_BEGIN_ARG_INFO_EX(args_for_ ##class## _ ##method , 0, ret_ref, req_args) diff --git a/tests/HttpQueryString_001.phpt b/tests/HttpQueryString_001.phpt new file mode 100644 index 0000000..a61e605 --- /dev/null +++ b/tests/HttpQueryString_001.phpt @@ -0,0 +1,116 @@ +--TEST-- +HttpQueryString global +--SKIPIF-- + +--FILE-- +'b','c'=>'3.4','r'=>array(1,2,3)); +$_SERVER['QUERY_STRING'] = 'a=b&c=3.4&r[0]=1&r[1]=2&r[2]=3'; + +var_dump(HttpQueryString::getInstance()->get()); +var_dump(HttpQueryString::getInstance()->get('n')); +var_dump(HttpQueryString::getInstance()->get('a')); +var_dump(HttpQueryString::getInstance()->get('a', "i", 0, true)); +var_dump(HttpQueryString::getInstance()->get('a', "string", 'hi!')); +var_dump(HttpQueryString::getInstance()->get('c')); +var_dump(HttpQueryString::getInstance()->get('c', HttpQueryString::TYPE_INT)); +var_dump(HttpQueryString::getInstance()->get('c', HttpQueryString::TYPE_FLOAT)); +var_dump(HttpQueryString::getInstance()->get('c', HttpQueryString::TYPE_BOOL)); +var_dump(HttpQueryString::getInstance()->get('r')); +var_dump(HttpQueryString::getInstance()->get('r', HttpQueryString::TYPE_ARRAY)); +var_dump(HttpQueryString::getInstance()->get('r', HttpQueryString::TYPE_OBJECT)); + +HttpQueryString::getInstance()->set('z', array(2)); + +HttpQueryString::getInstance()->mod(array('a'=>'b', 'c'=> "3.4")); +HttpQueryString::getInstance()->del('a'); + +var_dump(HttpQueryString::getInstance()); +var_dump($_GET); +var_dump($_SERVER['QUERY_STRING']); + +echo "Done\n"; +?> +--EXPECTF-- +%sTEST +string(30) "a=b&c=3.4&r[0]=1&r[1]=2&r[2]=3" +NULL +string(1) "b" +int(0) +string(3) "hi!" +string(3) "3.4" +int(3) +float(3.4) +bool(true) +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +object(stdClass)#%d (%d) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +object(HttpQueryString)#1 (2) { + ["queryArray:private"]=> + &array(3) { + ["c"]=> + string(3) "3.4" + ["r"]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + ["z"]=> + array(1) { + [0]=> + int(2) + } + } + ["queryString:private"]=> + &string(33) "c=3.4&r[0]=1&r[1]=2&r[2]=3&z[0]=2" +} +array(3) { + ["c"]=> + string(3) "3.4" + ["r"]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + ["z"]=> + array(1) { + [0]=> + int(2) + } +} +string(33) "c=3.4&r[0]=1&r[1]=2&r[2]=3&z[0]=2" +Done \ No newline at end of file diff --git a/tests/HttpQueryString_002.phpt b/tests/HttpQueryString_002.phpt new file mode 100644 index 0000000..944f2a0 --- /dev/null +++ b/tests/HttpQueryString_002.phpt @@ -0,0 +1,99 @@ +--TEST-- +HttpQueryString local +--SKIPIF-- + +--FILE-- +mod(array('a'=>'b','c'=>'3.4','r'=>array(1,2,3))); +var_dump($q->get()); +var_dump($q->get('n')); +var_dump($q->get('a')); +var_dump($q->get('a', "i", 0, true)); +var_dump($q->get('a', "string", 'hi!')); +var_dump($q->get('c')); +var_dump($q->get('c', HttpQueryString::TYPE_INT)); +var_dump($q->get('c', HttpQueryString::TYPE_FLOAT)); +var_dump($q->get('c', HttpQueryString::TYPE_BOOL)); +var_dump($q->get('r')); +var_dump($q->get('r', HttpQueryString::TYPE_ARRAY)); +var_dump($q->get('r', HttpQueryString::TYPE_OBJECT)); + +$q->set('z', array(2)); + +$q->mod(array('a'=>'b', 'c'=> "3.4")); +$q->del('a'); + +var_dump($q); +var_dump($_GET); +var_dump($_SERVER['QUERY_STRING']); + +echo "Done\n"; +?> +--EXPECTF-- +%sTEST +string(30) "a=b&c=3.4&r[0]=1&r[1]=2&r[2]=3" +NULL +string(1) "b" +int(0) +string(3) "hi!" +string(3) "3.4" +int(3) +float(3.4) +bool(true) +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +object(stdClass)#%d (%d) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +object(HttpQueryString)#1 (2) { + ["queryArray:private"]=> + array(3) { + ["c"]=> + string(3) "3.4" + ["r"]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + ["z"]=> + array(1) { + [0]=> + int(2) + } + } + ["queryString:private"]=> + string(33) "c=3.4&r[0]=1&r[1]=2&r[2]=3&z[0]=2" +} +array(0) { +} +NULL +Done \ No newline at end of file -- 2.30.2