static void php_xml2array_get_properties (xmlNodePtr cur_node, zval * nodes, char *name) {
	if (cur_node->properties) {
		xmlAttrPtr attr =  NULL;

		zval **tmp;
		if (zend_symtable_find(Z_ARRVAL_P(nodes),  name, strlen(name) + 1, (void**)&tmp) == FAILURE) {
			return;//this should not happen
		}
		zval *target = *tmp;
		if (Z_TYPE_PP(tmp) != IS_ARRAY) {
			zval *value_zval = init_zval_array();
			target = value_zval;
			zval *copy;
			MAKE_STD_ZVAL(copy);
			MAKE_COPY_ZVAL(tmp, copy);
			add_assoc_zval(value_zval, "value", copy);
			zend_symtable_update(Z_ARRVAL_P(nodes), name, strlen(name)+1, (void *) &value_zval, sizeof(zval *), NULL);
		}

		for(attr = cur_node->properties; NULL != attr; attr = attr->next) {
			xmlChar * prop = NULL;
			prop = xmlGetProp(cur_node, attr->name);
			char *attr_name = (char*)attr->name;
			zval *attr_zval;
			MAKE_STD_ZVAL(attr_zval);
			ZVAL_STRING(attr_zval, prop, 1);
			zend_symtable_update(Z_ARRVAL_P(target), attr_name, strlen(attr_name)+1, (void *) &attr_zval, sizeof(zval *), NULL);
			xmlFree(prop);
		}
	}
}
Exemple #2
0
/**
 * @brief Updates value in @a arr at position @a index with @a value
 * @param[in,out] arr Array
 * @param index Index
 * @param[in,out] value Value
 * @param flags Flags
 * @return Whether the operation succeeded
 * @retval @c FAILURE Failure, @a arr is not an array or @a index is of not supported type
 * @retval @c SUCCESS Success
 * @note @c index will be handled as follows: @c NULL is treated as an empty string, @c double values are cast to @c integer, @c bool or @c resource are treated as @c integer
 * @throw @c E_WARNING if @a offset is not a scalar or @c arr is not an array
 *
 * Equivalent to <tt>$arr[$index] = $value</tt> in PHP.
 * Flags may be a bitwise OR of the following values:
 * @arg @c PH_CTOR: create a copy of @a value and work with that copy; @c *value will be updated with the newly constructed value
 * @arg @c PH_SEPARATE: separate @a arr if its reference count is greater than 1; @c *arr will contain the separated version
 * @arg @c PH_COPY: increment the reference count on @c **value
 */
int zephir_array_update_zval(zval **arr, zval *index, zval **value, int flags) {

    HashTable *ht;

    if (Z_TYPE_PP(arr) != IS_ARRAY) {
        zend_error(E_WARNING, "Cannot use a scalar value as an array (2)");
        return FAILURE;
    }

    if ((flags & PH_CTOR) == PH_CTOR) {
        zval *new_zv;
        Z_DELREF_PP(value);
        ALLOC_ZVAL(new_zv);
        INIT_PZVAL_COPY(new_zv, *value);
        *value = new_zv;
        zval_copy_ctor(new_zv);
    }

    if ((flags & PH_SEPARATE) == PH_SEPARATE) {
        SEPARATE_ZVAL_IF_NOT_REF(arr);
    }

    if ((flags & PH_COPY) == PH_COPY) {
        Z_ADDREF_PP(value);
    }

    ht = Z_ARRVAL_PP(arr);

    switch (Z_TYPE_P(index)) {
    case IS_NULL:
        return zend_symtable_update(ht, "", 1, value, sizeof(zval*), NULL);

    case IS_DOUBLE:
        return zend_hash_index_update(ht, (ulong)Z_DVAL_P(index), value, sizeof(zval*), NULL);

    case IS_LONG:
    case IS_BOOL:
    case IS_RESOURCE:
        return zend_hash_index_update(ht, Z_LVAL_P(index), value, sizeof(zval*), NULL);

    case IS_STRING:
        return zend_symtable_update(ht, Z_STRVAL_P(index), Z_STRLEN_P(index)+1, value, sizeof(zval*), NULL);

    default:
        zend_error(E_WARNING, "Illegal offset type");
        return FAILURE;
    }
}
static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements, int objprops)
{
	while (elements-- > 0) {
		zval *key, *data, **old_data;

		ALLOC_INIT_ZVAL(key);

		if (!php_var_unserialize2(&key, p, max, NULL TSRMLS_CC)) {
			zval_dtor(key);
			FREE_ZVAL(key);
			return 0;
		}

		if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
			zval_dtor(key);
			FREE_ZVAL(key);
			return 0;
		}

		ALLOC_INIT_ZVAL(data);

		if (!php_var_unserialize2(&data, p, max, var_hash TSRMLS_CC)) {
			zval_dtor(key);
			FREE_ZVAL(key);
			zval_dtor(data);
			FREE_ZVAL(data);
			return 0;
		}

		switch (Z_TYPE_P(key)) {
		case IS_LONG:
            if (objprops) {
                /* show a warning for not compatible */
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "got integer prop. %d", Z_LVAL_P(key));
            }
			if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)==SUCCESS) {
				var_push_dtor(var_hash, old_data);
			}
			zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL);
			break;
		case IS_STRING:
			if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) {
				var_push_dtor(var_hash, old_data);
			}
			zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL);
			break;
		}
		
		
		zval_dtor(key);
		FREE_ZVAL(key);

		if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
			(*p)--;
			return 0;
		}
	}

	return 1;
}
Exemple #4
0
static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements, int objprops)
{
	while (elements-- > 0) {
		zval *key, *data, **old_data;

		ALLOC_INIT_ZVAL(key);

		if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
            var_push_dtor_no_addref(var_hash, &key);
			return 0;
		}

		if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
            var_push_dtor_no_addref(var_hash, &key);
			return 0;
		}

		ALLOC_INIT_ZVAL(data);

		if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
            var_push_dtor_no_addref(var_hash, &key);
            var_push_dtor_no_addref(var_hash, &data);
			return 0;
		}

		if (!objprops) {
			switch (Z_TYPE_P(key)) {
			case IS_LONG:
				if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)==SUCCESS) {
					var_push_dtor(var_hash, old_data);
				}
				zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL);
				break;
			case IS_STRING:
				if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) {
					var_push_dtor(var_hash, old_data);
				}
				zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL);
				break;
			}
		} else {
			/* object properties should include no integers */
			convert_to_string(key);
			if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) {
				var_push_dtor(var_hash, old_data);
			}
			zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data,
					sizeof data, NULL);
		}
		var_push_dtor(var_hash, &data);
        var_push_dtor_no_addref(var_hash, &key);

		if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
			(*p)--;
			return 0;
		}
	}

	return 1;
}
Exemple #5
0
static int hash_to_zval(VALUE key, VALUE value, VALUE zval_array) {
    zval *v;
    zval *ary;

    if (key == Qundef) {
        return ST_CONTINUE;
    }

    ary = (zval *)zval_array;
    v = value_to_zval(value);

    if (key == Qtrue) {
        zend_hash_index_update(Z_ARRVAL_P(ary), 1, &v, sizeof(zval *), NULL);
        return ST_CONTINUE;
    }

    if (key == Qfalse || key == Qnil) {
        zend_hash_index_update(Z_ARRVAL_P(ary), 0, &v, sizeof(zval *), NULL);
        return ST_CONTINUE;
    }

    if (TYPE(key) == T_FIXNUM) {
        int idx = FIX2INT(key);
        zend_hash_index_update(Z_ARRVAL_P(ary), idx, &v, sizeof(zval *), NULL);
        return ST_CONTINUE;
    }

    switch (TYPE(key)) {
        case T_BIGNUM:
            key = rb_big2str(key, 10);
            break;
        case T_SYMBOL:
            key = rb_sym_to_s(key);
            break;
        case T_STRING:
            key = rb_string_value(&key);
            break;
        default:
            rb_raise(rb_eRuntimeError, "invalid key (%d)", TYPE(key));
    }

    //ZEND_HANDLE_NUMERIC(RSTRING_PTR(key), RSTRING_LEN(key), zend_hash_index_update(Z_ARRVAL_P(ary), idx, &v, sizeof(zval *), NULL));
    zend_symtable_update(Z_ARRVAL_P(ary), RSTRING_PTR(key), RSTRING_LEN(key) + 1, &v, sizeof(zval *), NULL);

    return ST_CONTINUE;
}
Exemple #6
0
static int add_variable_magic_quote( const char * pKey, int keyLen, const char * pValue, int valLen, 
                         void * arg )
{
    zval * gpc_element, **gpc_element_p;
    HashTable * symtable1 = Z_ARRVAL_P((zval * )arg);
    register char * pKey1 = (char *)pKey;

    MAKE_STD_ZVAL(gpc_element);
    Z_STRLEN_P( gpc_element ) = valLen;
    Z_STRVAL_P( gpc_element ) = php_addslashes((char *)pValue, valLen, &Z_STRLEN_P( gpc_element ), 0 );
    Z_TYPE_P( gpc_element ) = IS_STRING;
#if PHP_MAJOR_VERSION > 4
    zend_symtable_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p );
#else
    zend_hash_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p );
#endif
    return 1;
}
/**
 * @ret 父亲zval
 * @name 父亲name
 * @r 子zval
 * @son_name 子name
 */
static void php_xml2array_add_val (zval *ret, const xmlChar *name, zval *r, char *son_key) {
	zval **tmp = NULL;
	char *key = (char *)name;//要插入的node 的key

	int has_tmp = zend_symtable_find(Z_ARRVAL(*ret),  key, strlen(key) + 1, (void**)&tmp);

	if (has_tmp == SUCCESS && tmp != NULL && Z_TYPE_PP(tmp) == IS_ARRAY && son_key == NULL && Z_TYPE_P(r) == IS_STRING) {//avoid <xx></xx>,<xx></xx>
		zval_ptr_dtor(&r);
		return;
	}

	if(son_key != NULL && zend_symtable_find(Z_ARRVAL(*ret),  key, strlen(key) + 1, (void**)&tmp) != FAILURE
		&& Z_TYPE_PP(tmp) == IS_ARRAY) {

		zval **son_val = NULL;
		zend_symtable_find(Z_ARRVAL_P(r),  son_key , strlen(son_key)+1, (void**)&son_val);

		zval *son_val_copy;
		MAKE_STD_ZVAL(son_val_copy);
		MAKE_COPY_ZVAL(son_val, son_val_copy);

		zval **tmp_val = NULL;
		if (zend_symtable_find(Z_ARRVAL_P(*tmp),  son_key , strlen(son_key)+1, (void**)&tmp_val) != FAILURE) {//已经包含同名子元素
			if (Z_TYPE_PP(tmp_val)  == IS_ARRAY && zend_hash_index_exists(Z_ARRVAL_PP(tmp_val), 0)) {
				add_next_index_zval(*tmp_val, son_val_copy);
			} else {
				zval *son_arr = init_zval_array();
				zval *copy;
				MAKE_STD_ZVAL(copy);
				MAKE_COPY_ZVAL(tmp_val, copy);
				add_next_index_zval(son_arr, copy);
				add_next_index_zval(son_arr, son_val_copy);
				zend_symtable_update(Z_ARRVAL_PP(tmp), son_key, strlen(son_key)+1, (void *) &son_arr, sizeof(zval *), NULL);
			}
		} else {
			add_assoc_zval(*tmp, son_key, son_val_copy);
		}
		zval_ptr_dtor(&r);//accept a zval** param
	} else {
		add_assoc_zval(ret, key, r);
	}


}
Exemple #8
0
inline int msgpack_convert_long_to_properties(
    HashTable *ht, HashTable **properties, HashPosition *prop_pos,
    uint key_index, zval *val, HashTable *var)
{
    if (*properties != NULL)
    {
        char *prop_key;
        uint prop_key_len;
        ulong prop_key_index;

        for (;; zend_hash_move_forward_ex(*properties, prop_pos))
        {
            if (zend_hash_get_current_key_ex(
                    *properties, &prop_key, &prop_key_len,
                    &prop_key_index, 0, prop_pos) == HASH_KEY_IS_STRING)
            {
                if (var == NULL ||
                    !zend_hash_exists(var, prop_key, prop_key_len))
                {
                    zend_hash_move_forward_ex(*properties, prop_pos);
                    return zend_symtable_update(
                        ht, prop_key, prop_key_len,
                        &val, sizeof(val), NULL);
                }
            }
            else
            {
                break;
            }
        }

        *properties = NULL;
    }

    return zend_hash_index_update(ht, key_index, &val, sizeof(val), NULL);
}
int msgpack_convert_object(zval *return_value, zval *tpl, zval **value)
{
    zend_class_entry *ce, **pce;
    TSRMLS_FETCH();

    switch (Z_TYPE_P(tpl))
    {
        case IS_STRING:
            if (zend_lookup_class(
                    Z_STRVAL_P(tpl), Z_STRLEN_P(tpl),
                    &pce TSRMLS_CC) != SUCCESS)
            {
                MSGPACK_ERROR("[msgpack] (%s) Class '%s' not found",
                              __FUNCTION__, Z_STRVAL_P(tpl));
                return FAILURE;
            }
            ce = *pce;
            break;
        case IS_OBJECT:
            ce = zend_get_class_entry(tpl TSRMLS_CC);
            break;
        default:
            MSGPACK_ERROR("[msgpack] (%s) object type is unsupported",
                          __FUNCTION__);
            return FAILURE;
    }

    if (Z_TYPE_PP(value) == IS_OBJECT)
    {
        zend_class_entry *vce;

        vce = zend_get_class_entry(*value TSRMLS_CC);
        if (strcmp(ce->name, vce->name) == 0)
        {
            *return_value = **value;
            zval_copy_ctor(return_value);
            zval_ptr_dtor(value);
            return SUCCESS;
        }
    }

    object_init_ex(return_value, ce);

    /* Run the constructor if there is one */
    if (ce->constructor
        && (ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC))
    {
        zval *retval_ptr = NULL;
        zval ***params = NULL;
        int num_args = 0;
        zend_fcall_info fci;
        zend_fcall_info_cache fcc;

#if ZEND_MODULE_API_NO >= 20090626
        fci.size = sizeof(fci);
        fci.function_table = EG(function_table);
        fci.function_name = NULL;
        fci.symbol_table = NULL;
        fci.object_ptr = return_value;
        fci.retval_ptr_ptr = &retval_ptr;
        fci.param_count = num_args;
        fci.params = params;
        fci.no_separation = 1;

        fcc.initialized = 1;
        fcc.function_handler = ce->constructor;
        fcc.calling_scope = EG(scope);
        fcc.called_scope = Z_OBJCE_P(return_value);
        fcc.object_ptr = return_value;
#else
        fci.size = sizeof(fci);
        fci.function_table = EG(function_table);
        fci.function_name = NULL;
        fci.symbol_table = NULL;
        fci.object_pp = &return_value;
        fci.retval_ptr_ptr = &retval_ptr;
        fci.param_count = num_args;
        fci.params = params;
        fci.no_separation = 1;

        fcc.initialized = 1;
        fcc.function_handler = ce->constructor;
        fcc.calling_scope = EG(scope);
        fcc.object_pp = &return_value;
#endif

        if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE)
        {
            if (params)
            {
                efree(params);
            }
            if (retval_ptr)
            {
                zval_ptr_dtor(&retval_ptr);
            }

            MSGPACK_WARNING(
                "[msgpack] (%s) Invocation of %s's constructor failed",
                __FUNCTION__, ce->name);

            return FAILURE;
        }
        if (retval_ptr)
        {
            zval_ptr_dtor(&retval_ptr);
        }
        if (params)
        {
            efree(params);
        }
    }

    switch (Z_TYPE_PP(value))
    {
        case IS_ARRAY:
        {
            char *key;
            uint key_len;
            int key_type;
            ulong key_index;
            zval **data;
            HashPosition pos;
            HashTable *ht, *ret;
            HashTable *var = NULL;
            int num;

            ht = HASH_OF(*value);
            ret = HASH_OF(return_value);

            num = zend_hash_num_elements(ht);
            if (num <= 0)
            {
                zval_ptr_dtor(value);
                break;
            }

            /* string - php_only mode? */
            if (ht->nNumOfElements != ht->nNextFreeElement
                || ht->nNumOfElements != ret->nNumOfElements)
            {
                HashTable *properties = NULL;
                HashPosition prop_pos;

                ALLOC_HASHTABLE(var);
                zend_hash_init(var, num, NULL, NULL, 0);

                zend_hash_internal_pointer_reset_ex(ht, &pos);
                for (;; zend_hash_move_forward_ex(ht, &pos))
                {
                    key_type = zend_hash_get_current_key_ex(
                        ht, &key, &key_len, &key_index, 0, &pos);

                    if (key_type == HASH_KEY_NON_EXISTANT)
                    {
                        break;
                    }

                    if (zend_hash_get_current_data_ex(
                            ht, (void *)&data, &pos) != SUCCESS)
                    {
                        continue;
                    }

                    if (key_type == HASH_KEY_IS_STRING)
                    {
                        zval *val;
                        MSGPACK_CONVERT_COPY_ZVAL(val, data);
                        if (msgpack_convert_string_to_properties(
                                return_value, key, key_len, val, var) != SUCCESS)
                        {
                            zval_ptr_dtor(&val);
                            MSGPACK_WARNING(
                                "[msgpack] (%s) "
                                "illegal offset type, skip this decoding",
                                __FUNCTION__);
                        }
                    }
                }

                /* index */
                properties = Z_OBJ_HT_P(return_value)->get_properties(
                    return_value TSRMLS_CC);

                if (HASH_OF(tpl))
                {
                    properties = HASH_OF(tpl);
                }
                zend_hash_internal_pointer_reset_ex(properties, &prop_pos);

                zend_hash_internal_pointer_reset_ex(ht, &pos);
                for (;; zend_hash_move_forward_ex(ht, &pos))
                {
                    key_type = zend_hash_get_current_key_ex(
                        ht, &key, &key_len, &key_index, 0, &pos);

                    if (key_type == HASH_KEY_NON_EXISTANT)
                    {
                        break;
                    }

                    if (zend_hash_get_current_data_ex(
                            ht, (void *)&data, &pos) != SUCCESS)
                    {
                        continue;
                    }

                    switch (key_type)
                    {
                        case HASH_KEY_IS_LONG:
                        {
                            zval *val;
                            MSGPACK_CONVERT_COPY_ZVAL(val, data);
                            if (msgpack_convert_long_to_properties(
                                    ret, &properties, &prop_pos,
                                    key_index, val, var) != SUCCESS)
                            {
                                zval_ptr_dtor(&val);
                                MSGPACK_WARNING(
                                    "[msgpack] (%s) "
                                    "illegal offset type, skip this decoding",
                                    __FUNCTION__);
                            }
                            break;
                        }
                        case HASH_KEY_IS_STRING:
                            break;
                        default:
                            MSGPACK_WARNING(
                                "[msgpack] (%s) key is not string nor array",
                                __FUNCTION__);
                            break;
                    }
                }

                zend_hash_destroy(var);
                FREE_HASHTABLE(var);
            }
            else
            {
                HashPosition valpos;
                int (*convert_function)(zval *, zval *, zval **) = NULL;
                zval **arydata, *aryval;

                /* index */
                zend_hash_internal_pointer_reset_ex(ret, &pos);
                zend_hash_internal_pointer_reset_ex(ht, &valpos);
                for (;; zend_hash_move_forward_ex(ret, &pos),
                        zend_hash_move_forward_ex(ht, &valpos))
                {
                    key_type = zend_hash_get_current_key_ex(
                        ret, &key, &key_len, &key_index, 0, &pos);

                    if (key_type == HASH_KEY_NON_EXISTANT)
                    {
                        break;
                    }

                    if (zend_hash_get_current_data_ex(
                            ret, (void *)&data, &pos) != SUCCESS)
                    {
                        continue;
                    }

                    switch (Z_TYPE_PP(data))
                    {
                        case IS_ARRAY:
                            convert_function = msgpack_convert_array;
                            break;
                        case IS_OBJECT:
                        //case IS_STRING: -- may have default values of
                        // class members, so it's not wise to allow
                            convert_function = msgpack_convert_object;
                            break;
                        default:
                            break;
                    }

                    if (zend_hash_get_current_data_ex(
                            ht, (void *)&arydata, &valpos) != SUCCESS)
                    {
                        MSGPACK_WARNING(
                            "[msgpack] (%s) can't get data value by index",
                            __FUNCTION__);
                        return FAILURE;
                    }

                    MSGPACK_CONVERT_COPY_ZVAL(aryval, arydata);

                    if (convert_function)
                    {
                        zval *rv;
                        ALLOC_INIT_ZVAL(rv);

                        if (convert_function(rv, *data, &aryval) != SUCCESS)
                        {
                            zval_ptr_dtor(&aryval);
                            MSGPACK_WARNING(
                                "[msgpack] (%s) "
                                "convert failure in convert_object",
                                __FUNCTION__);
                            return FAILURE;
                        }

                        zend_symtable_update(
                            ret, key, key_len, &rv, sizeof(rv), NULL);
                    }
                    else
                    {
                        zend_symtable_update(
                            ret, key, key_len, &aryval, sizeof(aryval), NULL);
                    }
                }
            }

            zval_ptr_dtor(value);
            break;
        }
        default:
        {
            HashTable *properties = NULL;
            HashPosition prop_pos;

            properties = Z_OBJ_HT_P(return_value)->get_properties(
                return_value TSRMLS_CC);
            zend_hash_internal_pointer_reset_ex(properties, &prop_pos);

            if (msgpack_convert_long_to_properties(
                    HASH_OF(return_value), &properties, &prop_pos,
                    0, *value, NULL) != SUCCESS)
            {
                MSGPACK_WARNING(
                    "[msgpack] (%s) illegal offset type, skip this decoding",
                    __FUNCTION__);
            }
            break;
        }
    }

    return SUCCESS;
}
inline int msgpack_convert_long_to_properties(
    HashTable *ht, HashTable **properties, HashPosition *prop_pos,
    uint key_index, zval *val, HashTable *var)
{
    TSRMLS_FETCH();

    if (*properties != NULL)
    {
        char *prop_key;
        uint prop_key_len;
        ulong prop_key_index;
        zval **data = NULL;
        zval *tplval = NULL;
        zval **dataval = NULL;

        for (;; zend_hash_move_forward_ex(*properties, prop_pos))
        {
            if (zend_hash_get_current_key_ex(
                    *properties, &prop_key, &prop_key_len,
                    &prop_key_index, 0, prop_pos) == HASH_KEY_IS_STRING)
            {
                if (var == NULL ||
                    !zend_hash_exists(var, prop_key, prop_key_len))
                {
                    if (zend_hash_find(
                            ht, prop_key, prop_key_len,
                            (void **)&data) == SUCCESS)
                    {
                        switch (Z_TYPE_PP(data))
                        {
                            case IS_ARRAY:
                            {
                                HashTable *dataht;
                                dataht = HASH_OF(val);
                                if (zend_hash_index_find(
                                        dataht, prop_key_index,
                                        (void **)dataval) != SUCCESS)
                                {
                                    MSGPACK_WARNING(
                                        "[msgpack] (%s) "
                                        "can't get data value by index",
                                        __FUNCTION__);
                                    return FAILURE;
                                }

                                ALLOC_INIT_ZVAL(tplval);
                                if (msgpack_convert_array(
                                        tplval, *data, dataval) == SUCCESS)
                                {
                                    zend_hash_move_forward_ex(
                                        *properties, prop_pos);

                                    return zend_symtable_update(
                                        ht, prop_key, prop_key_len,
                                        &tplval, sizeof(tplval), NULL);
                                }
                                // TODO: de we need to call dtor?
                                return FAILURE;
                                break;
                            }
                            case IS_OBJECT:
                            {
                                ALLOC_INIT_ZVAL(tplval);
                                if (msgpack_convert_object(
                                        tplval, *data, &val) == SUCCESS)
                                {
                                    zend_hash_move_forward_ex(
                                        *properties, prop_pos);

                                    return zend_symtable_update(
                                        ht, prop_key, prop_key_len,
                                        &tplval, sizeof(tplval), NULL);
                                }
                                // TODO: de we need to call dtor?
                                return FAILURE;
                                break;
                            }
                            default:
                                zend_hash_move_forward_ex(*properties, prop_pos);
                                return zend_symtable_update(
                                    ht, prop_key, prop_key_len,
                                    &val, sizeof(val), NULL);
                                break;
                        }
                    }
                }
            }
            else
            {
                break;
            }
        }

        *properties = NULL;
    }

    return zend_hash_index_update(ht, key_index, &val, sizeof(val), NULL);
}
Exemple #11
0
/* {{{ php_ini_parser_cb
 */
static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, HashTable *target_hash)
{
	zval *entry;
	HashTable *active_hash;
	char *extension_name;

	if (active_ini_hash) {
		active_hash = active_ini_hash;
	} else {
		active_hash = target_hash;
	}

	switch (callback_type) {
		case ZEND_INI_PARSER_ENTRY: {
				if (!arg2) {
					/* bare string - nothing to do */
					break;
				}

				/* PHP and Zend extensions are not added into configuration hash! */
				if (!is_special_section && !strcasecmp(Z_STRVAL_P(arg1), PHP_EXTENSION_TOKEN)) { /* load PHP extension */
					extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
					zend_llist_add_element(&extension_lists.functions, &extension_name);
				} else if (!is_special_section && !strcasecmp(Z_STRVAL_P(arg1), ZEND_EXTENSION_TOKEN)) { /* load Zend extension */
					extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
					zend_llist_add_element(&extension_lists.engine, &extension_name);

				/* All other entries are added into either configuration_hash or active ini section array */
				} else {
					/* Store in active hash */
					entry = zend_hash_update(active_hash, Z_STR_P(arg1), arg2);
					Z_STR_P(entry) = zend_string_dup(Z_STR_P(entry), 1);
				}
			}
			break;

		case ZEND_INI_PARSER_POP_ENTRY: {
				zval option_arr;
				zval *find_arr;

				if (!arg2) {
					/* bare string - nothing to do */
					break;
				}

/* fprintf(stdout, "ZEND_INI_PARSER_POP_ENTRY: %s[%s] = %s\n",Z_STRVAL_P(arg1), Z_STRVAL_P(arg3), Z_STRVAL_P(arg2)); */

				/* If option not found in hash or is not an array -> create array, otherwise add to existing array */
				if ((find_arr = zend_hash_find(active_hash, Z_STR_P(arg1))) == NULL || Z_TYPE_P(find_arr) != IS_ARRAY) {
					ZVAL_NEW_PERSISTENT_ARR(&option_arr);
					zend_hash_init(Z_ARRVAL(option_arr), 8, NULL, config_zval_dtor, 1);
					find_arr = zend_hash_update(active_hash, Z_STR_P(arg1), &option_arr);
				}

				/* arg3 is possible option offset name */
				if (arg3 && Z_STRLEN_P(arg3) > 0) {
					entry = zend_symtable_update(Z_ARRVAL_P(find_arr), Z_STR_P(arg3), arg2);
				} else {
					entry = zend_hash_next_index_insert(Z_ARRVAL_P(find_arr), arg2);
				}
				Z_STR_P(entry) = zend_string_dup(Z_STR_P(entry), 1);
			}
			break;

		case ZEND_INI_PARSER_SECTION: { /* Create an array of entries of each section */

/* fprintf(stdout, "ZEND_INI_PARSER_SECTION: %s\n",Z_STRVAL_P(arg1)); */

				char *key = NULL;
				size_t key_len;

				/* PATH sections */
				if (!strncasecmp(Z_STRVAL_P(arg1), "PATH", sizeof("PATH") - 1)) {
					key = Z_STRVAL_P(arg1);
					key = key + sizeof("PATH") - 1;
					key_len = Z_STRLEN_P(arg1) - sizeof("PATH") + 1;
					is_special_section = 1;
					has_per_dir_config = 1;

					/* make the path lowercase on Windows, for case insensitivity. Does nothing for other platforms */
					TRANSLATE_SLASHES_LOWER(key);

				/* HOST sections */
				} else if (!strncasecmp(Z_STRVAL_P(arg1), "HOST", sizeof("HOST") - 1)) {
					key = Z_STRVAL_P(arg1);
					key = key + sizeof("HOST") - 1;
					key_len = Z_STRLEN_P(arg1) - sizeof("HOST") + 1;
					is_special_section = 1;
					has_per_host_config = 1;
					zend_str_tolower(key, key_len); /* host names are case-insensitive. */

				} else {
					is_special_section = 0;
				}

				if (key && key_len > 0) {
					/* Strip any trailing slashes */
					while (key_len > 0 && (key[key_len - 1] == '/' || key[key_len - 1] == '\\')) {
						key_len--;
						key[key_len] = 0;
					}

					/* Strip any leading whitespace and '=' */
					while (*key && (
						*key == '=' ||
						*key == ' ' ||
						*key == '\t'
					)) {
						key++;
						key_len--;
					}

					/* Search for existing entry and if it does not exist create one */
					if ((entry = zend_hash_str_find(target_hash, key, key_len)) == NULL) {
						zval section_arr;

						ZVAL_NEW_PERSISTENT_ARR(&section_arr);
						zend_hash_init(Z_ARRVAL(section_arr), 8, NULL, (dtor_func_t) config_zval_dtor, 1);
						entry = zend_hash_str_update(target_hash, key, key_len, &section_arr);
					}
					active_ini_hash = Z_ARRVAL_P(entry);
				}
			}
			break;
	}
}
Exemple #12
0
static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
{
	while (elements-- > 0) {
		zval key, *data, d, *old_data;

		ZVAL_UNDEF(&key);
		if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
			zval_dtor(&key);
			return 0;
		}

		if (Z_TYPE(key) != IS_LONG && Z_TYPE(key) != IS_STRING) {
			zval_dtor(&key);
			return 0;
		}

		data = NULL;
		ZVAL_UNDEF(&d);

		if (!objprops) {
			switch (Z_TYPE(key)) {
			case IS_LONG:
				if ((old_data = zend_hash_index_find(ht, Z_LVAL(key))) != NULL) {
					//??? update hash
					var_push_dtor(var_hash, old_data);
				}
				data = zend_hash_index_update(ht, Z_LVAL(key), &d);
				break;
			case IS_STRING:
				if ((old_data = zend_symtable_find(ht, Z_STR(key))) != NULL) {
					//??? update hash
					var_push_dtor(var_hash, old_data);
				}
				data = zend_symtable_update(ht, Z_STR(key), &d);
				break;
			}
		} else {
			/* object properties should include no integers */
			convert_to_string(&key);
//???
#if 1
			data = zend_hash_update_ind(ht, Z_STR(key), &d);
#else
			if ((data = zend_hash_find(ht, Z_STR(key))) != NULL) {
				if (Z_TYPE_P(data) == IS_INDIRECT) {
					data = Z_INDIRECT_P(data);
				}
				zval_ptr_dtor(data);
//???				var_push_dtor(var_hash, data);
				ZVAL_UNDEF(data);
			} else {
				data = zend_hash_update(ht, Z_STR(key), &d);
			}
#endif
		}
		
		zval_dtor(&key);

		if (!php_var_unserialize(data, p, max, var_hash TSRMLS_CC)) {
			return 0;
		}

		if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
			(*p)--;
			return 0;
		}
	}

	return 1;
}
Exemple #13
0
static inline void hstore_parse(HSParser *state, zval *result) /* {{{ */
{
    #define WKEY  0
    #define WVAL  1
    #define WEQ   2
    #define WDEL  4

    state->error   = 0;

    int st = WKEY;

    smart_str buf = {};
    smart_str_alloc(&buf, 1024, 0);

	zend_string *key;

    while (state->ptr < state->ptr_max) {
        char ch = *(state->ptr);

        if (isspace((unsigned char) ch)) {
            ++state->ptr;
            continue;
        }

		if (st == WKEY) {
            if (!hstore_parse_value(state, &buf, 0)) {
                goto free;
            }
            key = zval_get_string(&state->value);

            st = WEQ;
        } else if (st == WEQ) {
            if (state->ptr + 2 > state->ptr_max) {
                state->error = ERROR_UNEXPECTED_END;
                goto free;
            }

            if ('=' == *(state->ptr) && '>' == *(state->ptr + 1)) {
                st          = WVAL;
                state->ptr += 2;

                continue;
            }

            state->error = ERROR_SYNTAX;
            return;
        } else if (st == WVAL) {
            if (!hstore_parse_value(state, &buf, 1)) {
                goto free;
            }

            zend_symtable_update(Z_ARRVAL_P(result), key, &state->value);
            zend_string_release(key);
            zend_string_release(key);

            st = WDEL;
        } else if (st == WDEL) {
            if (',' == ch) {
                st = WKEY;
            } else {
                state->error = ERROR_SYNTAX;
                goto free;
            }
        } else {
            state->error = ERROR_UNKNOWN_STATE;
            goto free;
        }

        state->ptr++;
    }

    if (st != WKEY && st != WDEL) {
        state->error = ERROR_UNEXPECTED_END;
    }

free:
    smart_str_free(&buf);
}
Exemple #14
0
int msgpack_convert_array(zval *return_value, zval *tpl, zval *value) /* {{{ */ {
    zend_string *key;
    int key_type;
    ulong key_index;
    zval *data;
    HashTable *ht, *htval;

    if (Z_TYPE_P(tpl) != IS_ARRAY) {
        MSGPACK_WARNING("[msgpack] (%s) template is not array", __FUNCTION__);
        return FAILURE;
    }

    if (Z_TYPE_P(value) == IS_INDIRECT) {
        value = Z_INDIRECT_P(value);
    }

    ht = HASH_OF(tpl);
    array_init(return_value);

    if (zend_hash_num_elements(ht) == 0) {
        MSGPACK_WARNING("[msgpack] (%s) template array length is 0", __FUNCTION__);
        return FAILURE;
    }

    /* string */
	if (ht->nNumOfElements != ht->nNextFreeElement) {
		HashPosition valpos;

		htval = HASH_OF(value);

		if (!htval) {
			MSGPACK_WARNING("[msgpack] (%s) input data is not array", __FUNCTION__);
			return FAILURE;
		}

		zend_hash_internal_pointer_reset_ex(htval, &valpos);
		ZEND_HASH_FOREACH_KEY_VAL(ht, key_index, key, data) { 
			if (key) {
				zval *dataval;
				int (*convert_function)(zval *, zval *, zval *) = NULL;
				switch (Z_TYPE_P(data)) {
					case IS_ARRAY:
						convert_function = msgpack_convert_array;
						break;
					case IS_OBJECT:
						// case IS_STRING:
						convert_function = msgpack_convert_object;
						break;
					default:
						break;
				}

				if ((dataval = zend_hash_get_current_data_ex(htval, &valpos)) == NULL) {
					MSGPACK_WARNING("[msgpack] (%s) can't get data", __FUNCTION__);
					return FAILURE;
				}

				if (Z_TYPE_P(dataval) == IS_INDIRECT) {
					dataval = Z_INDIRECT_P(dataval);
				}

				if (convert_function) {
					zval rv;
					if (convert_function(&rv, data, dataval) != SUCCESS) {
						return FAILURE;
					}
					zend_symtable_update(Z_ARRVAL_P(return_value), key, &rv);
				} else {
					Z_TRY_ADDREF_P(dataval);
					zend_symtable_update(Z_ARRVAL_P(return_value), key, dataval);
				}
			}
			zend_hash_move_forward_ex(htval, &valpos);
		} ZEND_HASH_FOREACH_END();

		return SUCCESS;
    } else {
Exemple #15
0
static void
php_jv_dump(zval **return_value, jv x TSRMLS_DC)
{
    switch (jv_get_kind(x)) {
        default:
        case JV_KIND_INVALID:
            if (PHP_JQ_G(display_errors)) {
                PHP_JQ_ERR(E_WARNING, "json parse error");
            }
            break;
        case JV_KIND_NULL:
            INIT_PZVAL(*return_value);
            ZVAL_NULL(*return_value);
            break;
        case JV_KIND_FALSE:
            INIT_PZVAL(*return_value);
            ZVAL_BOOL(*return_value, 0);
            break;
        case JV_KIND_TRUE:
            INIT_PZVAL(*return_value);
            ZVAL_BOOL(*return_value, 1);
            break;
        case JV_KIND_NUMBER: {
            double d = jv_number_value(x);
            INIT_PZVAL(*return_value);
            if (d != d || d > LONG_MAX || d < LONG_MIN) {
                ZVAL_DOUBLE(*return_value, jv_number_value(x));
            } else if (d == (long)d) {
                ZVAL_LONG(*return_value, (long)d);
            } else {
                ZVAL_DOUBLE(*return_value, jv_number_value(x));
            }
            break;
        }
        case JV_KIND_STRING: {
            int len = jv_string_length_bytes(jv_copy(x));
            INIT_PZVAL(*return_value);
            if (len <= 0) {
                ZVAL_EMPTY_STRING(*return_value);
            } else {
                ZVAL_STRINGL(*return_value, jv_string_value(x), len, 1);
            }
            break;
        }
        case JV_KIND_ARRAY: {
            int i, len = jv_array_length(jv_copy(x));
            INIT_PZVAL(*return_value);
            array_init(*return_value);
            if (len == 0) {
                break;
            }

            for (i = 0; i < len; i++) {
                jv value = jv_array_get(jv_copy(x), i);
                if (jv_is_valid(value)) {
                    zval *zv;
                    ALLOC_INIT_ZVAL(zv);
                    php_jv_dump(&zv, value TSRMLS_CC);
                    zend_hash_next_index_insert(Z_ARRVAL_PP(return_value),
                                                &zv, sizeof(zv), NULL);
                } else {
                    jv_free(value);
                }
            }
            break;
        }
        case JV_KIND_OBJECT: {
            int i = 0, first = 1;
            INIT_PZVAL(*return_value);
            array_init(*return_value);
            if (jv_object_length(jv_copy(x)) == 0) {
                break;
            }

            while (1) {
                jv key, value;
                zval *zv;

                if (first) {
                    i = jv_object_iter(x);
                } else {
                    i = jv_object_iter_next(x, i);
                }
                if (!jv_object_iter_valid(x, i)) {
                    break;
                }

                key = jv_object_iter_key(x, i);
                value = jv_object_iter_value(x, i);

                ALLOC_INIT_ZVAL(zv);
                php_jv_dump(&zv, value TSRMLS_CC);
                zend_symtable_update(Z_ARRVAL_PP(return_value),
                                     jv_string_value(key),
                                     jv_string_length_bytes(jv_copy(key)) + 1,
                                     &zv, sizeof(zv), NULL);

                first = 0;
                jv_free(key);
            }
        }
    }

    jv_free(x);
}
Exemple #16
0
static
void binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport, zval* return_value, HashTable* fieldspec) {
  ZVAL_NULL(return_value);

  switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
      RETURN_NULL();
      return;
    case T_STRUCT: {
      zval* val_ptr = zend_hash_str_find(fieldspec, "class", sizeof("class")-1);
      if (val_ptr == nullptr) {
        throw_tprotocolexception("no class type in spec", INVALID_DATA);
        skip_element(T_STRUCT, transport);
        RETURN_NULL();
      }

      char* structType = Z_STRVAL_P(val_ptr);
      // Create an object in PHP userland based on our spec
      createObject(structType, return_value);
      if (Z_TYPE_P(return_value) == IS_NULL) {
        // unable to create class entry
        skip_element(T_STRUCT, transport);
        RETURN_NULL();
      }

      zval* spec = zend_read_static_property(Z_OBJCE_P(return_value), "_TSPEC", sizeof("_TSPEC")-1, false);
      if (Z_TYPE_P(spec) != IS_ARRAY) {
        char errbuf[128];
        snprintf(errbuf, 128, "spec for %s is wrong type: %d\n", structType, Z_TYPE_P(spec));
        throw_tprotocolexception(errbuf, INVALID_DATA);
        RETURN_NULL();
      }
      binary_deserialize_spec(return_value, transport, Z_ARRVAL_P(spec));
      return;
    } break;
    case T_BOOL: {
      uint8_t c;
      transport.readBytes(&c, 1);
      RETURN_BOOL(c != 0);
    }
  //case T_I08: // same numeric value as T_BYTE
    case T_BYTE: {
      uint8_t c;
      transport.readBytes(&c, 1);
      RETURN_LONG((int8_t)c);
    }
    case T_I16: {
      uint16_t c;
      transport.readBytes(&c, 2);
      RETURN_LONG((int16_t)ntohs(c));
    }
    case T_I32: {
      uint32_t c;
      transport.readBytes(&c, 4);
      RETURN_LONG((int32_t)ntohl(c));
    }
    case T_U64:
    case T_I64: {
      uint64_t c;
      transport.readBytes(&c, 8);
      RETURN_LONG((int64_t)ntohll(c));
    }
    case T_DOUBLE: {
      union {
        uint64_t c;
        double d;
      } a;
      transport.readBytes(&(a.c), 8);
      a.c = ntohll(a.c);
      RETURN_DOUBLE(a.d);
    }
    //case T_UTF7: // aliases T_STRING
    case T_UTF8:
    case T_UTF16:
    case T_STRING: {
      uint32_t size = transport.readU32();
      if (size) {
        char strbuf[size+1];
        transport.readBytes(strbuf, size);
        strbuf[size] = '\0';
        ZVAL_STRINGL(return_value, strbuf, size);
      } else {
        ZVAL_EMPTY_STRING(return_value);
      }
      return;
    }
    case T_MAP: { // array of key -> value
      uint8_t types[2];
      transport.readBytes(types, 2);
      uint32_t size = transport.readU32();
      array_init(return_value);

      zval *val_ptr;
      val_ptr = zend_hash_str_find(fieldspec, "key", sizeof("key")-1);
      HashTable* keyspec = Z_ARRVAL_P(val_ptr);
      val_ptr = zend_hash_str_find(fieldspec, "val", sizeof("val")-1);
      HashTable* valspec = Z_ARRVAL_P(val_ptr);

      for (uint32_t s = 0; s < size; ++s) {
        zval key, value;

        binary_deserialize(types[0], transport, &key, keyspec);
        binary_deserialize(types[1], transport, &value, valspec);
        if (Z_TYPE(key) == IS_LONG) {
          zend_hash_index_update(Z_ARR_P(return_value), Z_LVAL(key), &value);
        } else {
          if (Z_TYPE(key) != IS_STRING) convert_to_string(&key);
          zend_symtable_update(Z_ARR_P(return_value), Z_STR(key), &value);
        }
        zval_dtor(&key);
      }
      return; // return_value already populated
    }
    case T_LIST: { // array with autogenerated numeric keys
      int8_t type = transport.readI8();
      uint32_t size = transport.readU32();
      zval *val_ptr = zend_hash_str_find(fieldspec, "elem", sizeof("elem")-1);
      HashTable* elemspec = Z_ARRVAL_P(val_ptr);

      array_init(return_value);
      for (uint32_t s = 0; s < size; ++s) {
        zval value;
        binary_deserialize(type, transport, &value, elemspec);
        zend_hash_next_index_insert(Z_ARR_P(return_value), &value);
      }
      return;
    }
    case T_SET: { // array of key -> TRUE
      uint8_t type;
      uint32_t size;
      transport.readBytes(&type, 1);
      transport.readBytes(&size, 4);
      size = ntohl(size);
      zval *val_ptr = zend_hash_str_find(fieldspec, "elem", sizeof("elem")-1);
      HashTable* elemspec = Z_ARRVAL_P(val_ptr);

      array_init(return_value);

      for (uint32_t s = 0; s < size; ++s) {
        zval key, value;
        ZVAL_TRUE(&value);

        binary_deserialize(type, transport, &key, elemspec);

        if (Z_TYPE(key) == IS_LONG) {
          zend_hash_index_update(Z_ARR_P(return_value), Z_LVAL(key), &value);
        } else {
          if (Z_TYPE(key) != IS_STRING) convert_to_string(&key);
          zend_symtable_update(Z_ARR_P(return_value), Z_STR(key), &value);
        }
        zval_dtor(&key);
      }
      return;
    }
  };

  char errbuf[128];
  sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
  throw_tprotocolexception(errbuf, INVALID_DATA);
}
int msgpack_unserialize_map_item(
    msgpack_unserialize_data *unpack, zval **container, zval *key, zval *val)
{
    long deps;
    TSRMLS_FETCH();

    if (MSGPACK_G(php_only))
    {
        zend_class_entry *ce;
        if (Z_TYPE_P(key) == IS_NULL)
        {
            unpack->type = MSGPACK_SERIALIZE_TYPE_NONE;

            if (Z_TYPE_P(val) == IS_LONG)
            {
                switch (Z_LVAL_P(val))
                {
                    case MSGPACK_SERIALIZE_TYPE_REFERENCE:
                        Z_SET_ISREF_PP(container);
                        break;
                    case MSGPACK_SERIALIZE_TYPE_RECURSIVE:
                        unpack->type = MSGPACK_SERIALIZE_TYPE_RECURSIVE;
                        break;
                    case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT:
                        unpack->type = MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT;
                        break;
                    case MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE:
                        unpack->type = MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE;
                        break;
                    case MSGPACK_SERIALIZE_TYPE_OBJECT:
                        unpack->type = MSGPACK_SERIALIZE_TYPE_OBJECT;
                        break;
                    default:
                        break;
                }
            }
            else if (Z_TYPE_P(val) == IS_STRING)
            {
                ce = msgpack_unserialize_class(
                    container, Z_STRVAL_P(val), Z_STRLEN_P(val));

                if (ce == NULL)
                {
                    MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);

                    return 0;
                }
            }

            MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);

            return 0;
        }
        else
        {
            switch (unpack->type)
            {
                case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT:
                    unpack->type = MSGPACK_SERIALIZE_TYPE_NONE;

                    ce = msgpack_unserialize_class(
                        container, Z_STRVAL_P(key), Z_STRLEN_P(key));
                    if (ce == NULL)
                    {
                        MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);

                        return 0;
                    }

#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
                    /* implementing Serializable */
                    if (ce->unserialize == NULL)
                    {
                        MSGPACK_WARNING(
                            "[msgpack] (%s) Class %s has no unserializer",
                            __FUNCTION__, ce->name);

                        MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);

                        return 0;
                    }

                    ce->unserialize(
                        container, ce,
                        (const unsigned char *)Z_STRVAL_P(val),
                        Z_STRLEN_P(val) + 1, NULL TSRMLS_CC);
#endif

                    MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);

                    return 0;
                case MSGPACK_SERIALIZE_TYPE_RECURSIVE:
                case MSGPACK_SERIALIZE_TYPE_OBJECT:
                case MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE:
                {
                    zval **rval;
                    int type = unpack->type;

                    unpack->type = MSGPACK_SERIALIZE_TYPE_NONE;
                    if (msgpack_var_access(
                            unpack->var_hash,
                            Z_LVAL_P(val) - 1, &rval) != SUCCESS)
                    {
                        MSGPACK_WARNING(
                            "[msgpack] (%s) Invalid references value: %ld",
                            __FUNCTION__, Z_LVAL_P(val) - 1);

                        MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);

                        return 0;
                    }

                    if (container != NULL)
                    {
                        zval_ptr_dtor(container);
                    }

                    *container = *rval;

                    Z_ADDREF_PP(container);

                    if (type == MSGPACK_SERIALIZE_TYPE_OBJECT)
                    {
                        Z_UNSET_ISREF_PP(container);
                    }
                    else if (type == MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE)
                    {
                        Z_SET_ISREF_PP(container);
                    }

                    MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);

                    return 0;
                }
            }
        }
    }

    if (Z_TYPE_PP(container) != IS_ARRAY && Z_TYPE_PP(container) != IS_OBJECT)
    {
        array_init(*container);
    }

    switch (Z_TYPE_P(key))
    {
        case IS_LONG:
            if (zend_hash_index_update(
                    HASH_OF(*container), Z_LVAL_P(key), &val,
                    sizeof(val), NULL) == FAILURE)
            {
                zval_ptr_dtor(&val);
                MSGPACK_WARNING(
                    "[msgpack] (%s) illegal offset type, skip this decoding",
                    __FUNCTION__);
            }
            zval_ptr_dtor(&key);
            break;
        case IS_STRING:
            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);
                MSGPACK_WARNING(
                    "[msgpack] (%s) illegal offset type, skip this decoding",
                    __FUNCTION__);
            }
            zval_ptr_dtor(&key);
            break;
        default:
            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;
    }

    msgpack_stack_pop(unpack->var_hash, 2);

    deps = unpack->deps - 1;
    unpack->stack[deps]--;
    if (unpack->stack[deps] == 0)
    {
        unpack->deps--;

        /* wakeup */
        if (MSGPACK_G(php_only) &&
            Z_TYPE_PP(container) == IS_OBJECT &&
            Z_OBJCE_PP(container) != PHP_IC_ENTRY &&
            zend_hash_exists(
                &Z_OBJCE_PP(container)->function_table,
                "__wakeup", sizeof("__wakeup")))
        {
            zval f, *h = NULL;

            INIT_PZVAL(&f);
            ZVAL_STRINGL(&f, "__wakeup", sizeof("__wakeup") - 1, 0);
            call_user_function_ex(
                CG(function_table), container, &f, &h, 0, 0, 1, NULL TSRMLS_CC);
            if (h)
            {
                zval_ptr_dtor(&h);
            }
        }
    }

    return 0;
}