From 9dd0a6eb86536c367b1903c83fb3f693c6d7f64e Mon Sep 17 00:00:00 2001 From: advect Date: Fri, 20 Apr 2012 15:29:20 +0900 Subject: [PATCH] php: supported 5.4.x version --- php/ChangeLog | 4 + php/msgpack.c | 25 ++++-- php/msgpack_class.c | 24 ++++-- php/msgpack_pack.c | 178 ++++++++++++++++++++++++++----------------- php/msgpack_pack.h | 8 +- php/msgpack_unpack.c | 63 +++++++++++---- php/msgpack_unpack.h | 8 +- php/php_msgpack.h | 3 +- php/tests/029.phpt | 1 + 9 files changed, 215 insertions(+), 99 deletions(-) diff --git a/php/ChangeLog b/php/ChangeLog index b3b1cd76..1583f1e9 100644 --- a/php/ChangeLog +++ b/php/ChangeLog @@ -1,5 +1,9 @@ msgpack extension changelog +Version 0.5.2 +------------- + * Support PHP 5.4.x version. + Version 0.5.1 ------------- * Fixed include path for version check. diff --git a/php/msgpack.c b/php/msgpack.c index 1cc3dc05..3ba11332 100644 --- a/php/msgpack.c +++ b/php/msgpack.c @@ -40,6 +40,9 @@ STD_PHP_INI_BOOLEAN( STD_PHP_INI_BOOLEAN( "msgpack.php_only", "1", PHP_INI_ALL, OnUpdateBool, php_only, zend_msgpack_globals, msgpack_globals) +STD_PHP_INI_BOOLEAN( + "msgpack.illegal_key_insert", "0", PHP_INI_ALL, OnUpdateBool, + illegal_key_insert, zend_msgpack_globals, msgpack_globals) PHP_INI_END() PS_SERIALIZER_FUNCS(msgpack); @@ -66,6 +69,8 @@ static void msgpack_init_globals(zend_msgpack_globals *msgpack_globals) } msgpack_globals->php_only = 1; + + msgpack_globals->illegal_key_insert = 0; } static ZEND_MINIT_FUNCTION(msgpack) @@ -136,11 +141,15 @@ ZEND_GET_MODULE(msgpack) PS_SERIALIZER_ENCODE_FUNC(msgpack) { smart_str buf = {0}; - php_serialize_data_t var_hash; + msgpack_serialize_data_t var_hash; PHP_VAR_SERIALIZE_INIT(var_hash); +#if PHP_API_VERSION < 20100412 msgpack_serialize_zval(&buf, PS(http_session_vars), &var_hash TSRMLS_CC); +#else + msgpack_serialize_zval(&buf, PS(http_session_vars), var_hash TSRMLS_CC); +#endif if (newlen) { @@ -167,7 +176,7 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) zval **value; size_t off = 0; msgpack_unpack_t mp; - php_unserialize_data_t var_hash; + msgpack_unserialize_data_t var_hash; ALLOC_INIT_ZVAL(tmp); @@ -176,7 +185,7 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) msgpack_unserialize_var_init(&var_hash); mp.user.retval = (zval *)tmp; - mp.user.var_hash = (php_unserialize_data_t *)&var_hash; + mp.user.var_hash = (msgpack_unserialize_data_t *)&var_hash; ret = template_execute(&mp, (char *)val, (size_t)vallen, &off); @@ -219,11 +228,15 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) PHP_MSGPACK_API void php_msgpack_serialize(smart_str *buf, zval *val TSRMLS_DC) { - php_serialize_data_t var_hash; + msgpack_serialize_data_t var_hash; PHP_VAR_SERIALIZE_INIT(var_hash); +#if PHP_API_VERSION < 20100412 msgpack_serialize_zval(buf, val, &var_hash TSRMLS_CC); +#else + msgpack_serialize_zval(buf, val, var_hash TSRMLS_CC); +#endif PHP_VAR_SERIALIZE_DESTROY(var_hash); } @@ -234,7 +247,7 @@ PHP_MSGPACK_API void php_msgpack_unserialize( int ret; size_t off = 0; msgpack_unpack_t mp; - php_unserialize_data_t var_hash; + msgpack_unserialize_data_t var_hash; if (str_len <= 0) { @@ -246,7 +259,7 @@ PHP_MSGPACK_API void php_msgpack_unserialize( msgpack_unserialize_var_init(&var_hash); mp.user.retval = (zval *)return_value; - mp.user.var_hash = (php_unserialize_data_t *)&var_hash; + mp.user.var_hash = (msgpack_unserialize_data_t *)&var_hash; ret = template_execute(&mp, str, (size_t)str_len, &off); diff --git a/php/msgpack_class.c b/php/msgpack_class.c index f90d6d2d..383ffda5 100644 --- a/php/msgpack_class.c +++ b/php/msgpack_class.c @@ -19,7 +19,7 @@ typedef struct { zval *retval; long offset; msgpack_unpack_t mp; - php_unserialize_data_t var_hash; + msgpack_unserialize_data_t var_hash; long php_only; zend_bool finished; int error; @@ -188,8 +188,10 @@ static void php_msgpack_base_free(php_msgpack_base_t *base TSRMLS_DC) static zend_object_value php_msgpack_base_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; - zval *tmp; php_msgpack_base_t *base; +#if PHP_API_VERSION < 20100412 + zval *tmp; +#endif base = emalloc(sizeof(php_msgpack_base_t)); @@ -201,9 +203,13 @@ static zend_object_value php_msgpack_base_new(zend_class_entry *ce TSRMLS_DC) base->object.ce = ce; #endif +#if PHP_API_VERSION < 20100412 zend_hash_copy( base->object.properties, &ce->default_properties, (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *)); +#else + object_properties_init(&base->object, ce); +#endif retval.handle = zend_objects_store_put( base, (zend_objects_store_dtor_t)zend_objects_destroy_object, @@ -233,8 +239,10 @@ static zend_object_value php_msgpack_unpacker_new( zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; - zval *tmp; php_msgpack_unpacker_t *unpacker; +#if PHP_API_VERSION < 20100412 + zval *tmp; +#endif unpacker = emalloc(sizeof(php_msgpack_unpacker_t)); @@ -246,9 +254,13 @@ static zend_object_value php_msgpack_unpacker_new( unpacker->object.ce = ce; #endif +#if PHP_API_VERSION < 20100412 zend_hash_copy( unpacker->object.properties, &ce->default_properties, (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *)); +#else + object_properties_init(&unpacker->object, ce); +#endif retval.handle = zend_objects_store_put( unpacker, (zend_objects_store_dtor_t)zend_objects_destroy_object, @@ -410,7 +422,7 @@ static ZEND_METHOD(msgpack_unpacker, __construct) msgpack_unserialize_var_init(&unpacker->var_hash); (&unpacker->mp)->user.var_hash = - (php_unserialize_data_t *)&unpacker->var_hash; + (msgpack_unserialize_data_t *)&unpacker->var_hash; } static ZEND_METHOD(msgpack_unpacker, __destruct) @@ -533,7 +545,7 @@ static ZEND_METHOD(msgpack_unpacker, execute) msgpack_unserialize_var_init(&unpacker->var_hash); (&unpacker->mp)->user.var_hash = - (php_unserialize_data_t *)&unpacker->var_hash; + (msgpack_unserialize_data_t *)&unpacker->var_hash; } (&unpacker->mp)->user.retval = (zval *)unpacker->retval; @@ -649,7 +661,7 @@ static ZEND_METHOD(msgpack_unpacker, reset) msgpack_unserialize_var_init(&unpacker->var_hash); (&unpacker->mp)->user.var_hash = - (php_unserialize_data_t *)&unpacker->var_hash; + (msgpack_unserialize_data_t *)&unpacker->var_hash; } void msgpack_init_class() diff --git a/php/msgpack_pack.c b/php/msgpack_pack.c index a6dee566..728f2c8c 100644 --- a/php/msgpack_pack.c +++ b/php/msgpack_pack.c @@ -255,27 +255,34 @@ inline static void msgpack_serialize_array( if (object) { - if (MSGPACK_G(php_only)) + if (n == 0) { - if (Z_ISREF_P(val)) - { - msgpack_pack_map(buf, n + 2); - msgpack_pack_nil(buf); - msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_REFERENCE); - } - else - { - msgpack_pack_map(buf, n + 1); - } - - msgpack_pack_nil(buf); - - msgpack_serialize_string(buf, class_name, name_len); + msgpack_pack_map(buf, n); } else { - msgpack_pack_array(buf, n); - hash = 0; + if (MSGPACK_G(php_only)) + { + if (Z_ISREF_P(val)) + { + msgpack_pack_map(buf, n + 2); + msgpack_pack_nil(buf); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_REFERENCE); + } + else + { + msgpack_pack_map(buf, n + 1); + } + + msgpack_pack_nil(buf); + + msgpack_serialize_string(buf, class_name, name_len); + } + else + { + msgpack_pack_array(buf, n); + hash = 0; + } } } else if (n == 0) @@ -301,67 +308,100 @@ inline static void msgpack_serialize_array( if (n > 0) { - char *key; - uint key_len; - int key_type; - ulong key_index; - zval **data; - HashPosition pos; - - zend_hash_internal_pointer_reset_ex(ht, &pos); - for (;; zend_hash_move_forward_ex(ht, &pos)) + if (object || hash) { - key_type = zend_hash_get_current_key_ex( - ht, &key, &key_len, &key_index, 0, &pos); + char *key; + uint key_len; + int key_type; + ulong key_index; + zval **data; + HashPosition pos; - if (key_type == HASH_KEY_NON_EXISTANT) + zend_hash_internal_pointer_reset_ex(ht, &pos); + for (;; zend_hash_move_forward_ex(ht, &pos)) { - break; - } - if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) - { - continue; - } + key_type = zend_hash_get_current_key_ex( + ht, &key, &key_len, &key_index, 0, &pos); - if (hash) - { - switch (key_type) + if (key_type == HASH_KEY_NON_EXISTANT) { - case HASH_KEY_IS_LONG: - msgpack_pack_long(buf, key_index); - break; - case HASH_KEY_IS_STRING: - msgpack_serialize_string(buf, key, key_len - 1); - break; - default: - msgpack_serialize_string(buf, "", sizeof("")); - MSGPACK_WARNING( - "[msgpack] (%s) key is not string nor array", - __FUNCTION__); - break; + break; } - } - - if (zend_hash_get_current_data_ex( - ht, (void *)&data, &pos) != SUCCESS || - !data || data == &val || - (Z_TYPE_PP(data) == IS_ARRAY && - Z_ARRVAL_PP(data)->nApplyCount > 1)) - { - msgpack_pack_nil(buf); - } - else - { - if (Z_TYPE_PP(data) == IS_ARRAY) + if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) { - Z_ARRVAL_PP(data)->nApplyCount++; + continue; } - msgpack_serialize_zval(buf, *data, var_hash TSRMLS_CC); - - if (Z_TYPE_PP(data) == IS_ARRAY) + if (hash) { - Z_ARRVAL_PP(data)->nApplyCount--; + switch (key_type) + { + case HASH_KEY_IS_LONG: + msgpack_pack_long(buf, key_index); + break; + case HASH_KEY_IS_STRING: + msgpack_serialize_string(buf, key, key_len - 1); + break; + default: + msgpack_serialize_string(buf, "", sizeof("")); + MSGPACK_WARNING( + "[msgpack] (%s) key is not string nor array", + __FUNCTION__); + break; + } + } + + if (zend_hash_get_current_data_ex( + ht, (void *)&data, &pos) != SUCCESS || + !data || data == &val || + (Z_TYPE_PP(data) == IS_ARRAY && + Z_ARRVAL_PP(data)->nApplyCount > 1)) + { + msgpack_pack_nil(buf); + } + else + { + if (Z_TYPE_PP(data) == IS_ARRAY) + { + Z_ARRVAL_PP(data)->nApplyCount++; + } + + msgpack_serialize_zval(buf, *data, var_hash TSRMLS_CC); + + if (Z_TYPE_PP(data) == IS_ARRAY) + { + Z_ARRVAL_PP(data)->nApplyCount--; + } + } + } + } + else + { + zval **data; + uint i; + + for (i = 0; i < n; i++) + { + if (zend_hash_index_find(ht, i, (void *)&data) != SUCCESS || + !data || data == &val || + (Z_TYPE_PP(data) == IS_ARRAY && + Z_ARRVAL_PP(data)->nApplyCount > 1)) + { + msgpack_pack_nil(buf); + } + else + { + if (Z_TYPE_PP(data) == IS_ARRAY) + { + Z_ARRVAL_PP(data)->nApplyCount++; + } + + msgpack_serialize_zval(buf, *data, var_hash TSRMLS_CC); + + if (Z_TYPE_PP(data) == IS_ARRAY) + { + Z_ARRVAL_PP(data)->nApplyCount--; + } } } } @@ -399,7 +439,7 @@ inline static void msgpack_serialize_object( msgpack_pack_nil(buf); msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT); - msgpack_serialize_string(buf, ce->name, ce->name_length); + msgpack_serialize_string(buf, (char *)ce->name, ce->name_length); msgpack_pack_raw(buf, serialized_length); msgpack_pack_raw_body(buf, serialized_data, serialized_length); } diff --git a/php/msgpack_pack.h b/php/msgpack_pack.h index 0d65b01a..99af6819 100644 --- a/php/msgpack_pack.h +++ b/php/msgpack_pack.h @@ -2,7 +2,13 @@ #ifndef MSGPACK_PACK_H #define MSGPACK_PACK_H -#include "ext/standard/php_smart_str.h" +#include "ext/standard/php_var.h" + +#if PHP_API_VERSION < 20100412 +#define msgpack_serialize_data_t HashTable +#else +typedef HashTable* msgpack_serialize_data_t; +#endif enum msgpack_serialize_type { diff --git a/php/msgpack_unpack.c b/php/msgpack_unpack.c index a6c3c297..44a33f06 100644 --- a/php/msgpack_unpack.c +++ b/php/msgpack_unpack.c @@ -54,7 +54,7 @@ typedef struct MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack, 2); inline static void msgpack_var_push( - php_unserialize_data_t *var_hashx, zval **rval) + msgpack_unserialize_data_t *var_hashx, zval **rval) { var_entries *var_hash, *prev = NULL; @@ -91,7 +91,7 @@ inline static void msgpack_var_push( } inline static int msgpack_var_access( - php_unserialize_data_t *var_hashx, long id, zval ***store) + msgpack_unserialize_data_t *var_hashx, long id, zval ***store) { var_entries *var_hash = var_hashx->first; @@ -118,7 +118,7 @@ inline static int msgpack_var_access( } inline static void msgpack_stack_push( - php_unserialize_data_t *var_hashx, zval **rval, zend_bool save) + msgpack_unserialize_data_t *var_hashx, zval **rval, zend_bool save) { var_entries *var_hash, *prev = NULL; @@ -162,7 +162,7 @@ inline static void msgpack_stack_push( } inline static void msgpack_stack_pop( - php_unserialize_data_t *var_hashx, long count) + msgpack_unserialize_data_t *var_hashx, long count) { long i; var_entries *var_hash = var_hashx->first_dtor; @@ -280,14 +280,14 @@ inline static zend_class_entry* msgpack_unserialize_class( return ce; } -void msgpack_unserialize_var_init(php_unserialize_data_t *var_hashx) +void msgpack_unserialize_var_init(msgpack_unserialize_data_t *var_hashx) { var_hashx->first = 0; var_hashx->first_dtor = 0; } void msgpack_unserialize_var_destroy( - php_unserialize_data_t *var_hashx, zend_bool err) + msgpack_unserialize_data_t *var_hashx, zend_bool err) { void *next; long i; @@ -487,7 +487,7 @@ int msgpack_unserialize_array( array_init(*obj); - if (count) unpack->stack[unpack->deps++] = count; + unpack->stack[unpack->deps++] = count; return 0; } @@ -505,12 +505,25 @@ int msgpack_unserialize_array_item( int msgpack_unserialize_map( msgpack_unserialize_data *unpack, unsigned int count, zval **obj) { + TSRMLS_FETCH(); MSGPACK_UNSERIALIZE_ALLOC_VALUE(unpack); - if (count) unpack->stack[unpack->deps++] = count; + unpack->stack[unpack->deps++] = count; unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; + if (count == 0) + { + if (MSGPACK_G(php_only)) + { + object_init(*obj); + } + else + { + array_init(*obj); + } + } + return 0; } @@ -669,6 +682,7 @@ int msgpack_unserialize_map_item( "[msgpack] (%s) illegal offset type, skip this decoding", __FUNCTION__); } + zval_ptr_dtor(&key); break; case IS_STRING: if (zend_symtable_update( @@ -680,16 +694,39 @@ int msgpack_unserialize_map_item( "[msgpack] (%s) illegal offset type, skip this decoding", __FUNCTION__); } + zval_ptr_dtor(&key); break; default: - zval_ptr_dtor(&val); - MSGPACK_WARNING( - "[msgpack] (%s) illegal offset type, skip this decoding", - __FUNCTION__); + MSGPACK_WARNING("[msgpack] (%s) illegal key type", __FUNCTION__); + + if (MSGPACK_G(illegal_key_insert)) + { + if (zend_hash_next_index_insert( + HASH_OF(*container), &key, sizeof(key), NULL) == FAILURE) + { + zval_ptr_dtor(&val); + } + if (zend_hash_next_index_insert( + HASH_OF(*container), &val, sizeof(val), NULL) == FAILURE) + { + zval_ptr_dtor(&val); + } + } + else + { + convert_to_string(key); + if (zend_symtable_update( + HASH_OF(*container), + Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, + &val, sizeof(val), NULL) == FAILURE) + { + zval_ptr_dtor(&val); + } + zval_ptr_dtor(&key); + } break; } - zval_ptr_dtor(&key); msgpack_stack_pop(unpack->var_hash, 2); deps = unpack->deps - 1; diff --git a/php/msgpack_unpack.h b/php/msgpack_unpack.h index 1f7b05e8..2ffa7904 100644 --- a/php/msgpack_unpack.h +++ b/php/msgpack_unpack.h @@ -16,17 +16,19 @@ typedef enum MSGPACK_UNPACK_PARSE_ERROR = -1, } msgpack_unpack_return; +typedef struct php_unserialize_data msgpack_unserialize_data_t; + typedef struct { zval *retval; long deps; - php_unserialize_data_t *var_hash; + msgpack_unserialize_data_t *var_hash; long stack[MSGPACK_EMBED_STACK_SIZE]; int type; } msgpack_unserialize_data; -void msgpack_unserialize_var_init(php_unserialize_data_t *var_hashx); +void msgpack_unserialize_var_init(msgpack_unserialize_data_t *var_hashx); void msgpack_unserialize_var_destroy( - php_unserialize_data_t *var_hashx, zend_bool err); + msgpack_unserialize_data_t *var_hashx, zend_bool err); void msgpack_unserialize_init(msgpack_unserialize_data *unpack); diff --git a/php/php_msgpack.h b/php/php_msgpack.h index bcd64996..c7db4d42 100644 --- a/php/php_msgpack.h +++ b/php/php_msgpack.h @@ -2,7 +2,7 @@ #ifndef PHP_MSGPACK_H #define PHP_MSGPACK_H -#define MSGPACK_EXTENSION_VERSION "0.5.1" +#define MSGPACK_EXTENSION_VERSION "0.5.2" #include "ext/standard/php_smart_str.h" @@ -24,6 +24,7 @@ extern zend_module_entry msgpack_module_entry; ZEND_BEGIN_MODULE_GLOBALS(msgpack) zend_bool error_display; zend_bool php_only; + zend_bool illegal_key_insert; ZEND_END_MODULE_GLOBALS(msgpack) ZEND_EXTERN_MODULE_GLOBALS(msgpack) diff --git a/php/tests/029.phpt b/php/tests/029.phpt index 686abb92..fe71e145 100644 --- a/php/tests/029.phpt +++ b/php/tests/029.phpt @@ -44,4 +44,5 @@ header Version => %s Directive => Local Value => Master Value msgpack.error_display => On => On +msgpack.illegal_key_insert => Off => Off msgpack.php_only => On => On