예제 #1
0
void binary_serialize_spec(zval* zthis, PHPOutputTransport& transport, HashTable* spec) {
    HashPosition key_ptr;
    zval** val_ptr;

    TSRMLS_FETCH();
    zend_class_entry* ce = zend_get_class_entry(zthis TSRMLS_CC);

    for (zend_hash_internal_pointer_reset_ex(spec, &key_ptr); zend_hash_get_current_data_ex(spec, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(spec, &key_ptr)) {
        ulong fieldno;
        if (zend_hash_get_current_key_ex(spec, NULL, NULL, &fieldno, 0, &key_ptr) != HASH_KEY_IS_LONG) {
            throw_tprotocolexception("Bad keytype in TSPEC (expected 'long')", INVALID_DATA);
            return;
        }
        HashTable* fieldspec = Z_ARRVAL_PP(val_ptr);

        // field name
        zend_hash_find(fieldspec, "var", 4, (void**)&val_ptr);
        char* varname = Z_STRVAL_PP(val_ptr);

        // thrift type
        zend_hash_find(fieldspec, "type", 5, (void**)&val_ptr);
        if (Z_TYPE_PP(val_ptr) != IS_LONG) convert_to_long(*val_ptr);
        int8_t ttype = Z_LVAL_PP(val_ptr);

        zval* prop = zend_read_property(ce, zthis, varname, strlen(varname), false TSRMLS_CC);
        if (Z_TYPE_P(prop) != IS_NULL) {
            transport.writeI8(ttype);
            transport.writeI16(fieldno);
            binary_serialize(ttype, transport, &prop, fieldspec);
        }
    }
    transport.writeI8(T_STOP); // struct end
}
예제 #2
0
zend_function *ClassBase::getMethod(zval **object_ptr, char *method_name, int method_len, const struct _zend_literal *key)
#endif
{
    // something strange about the Zend engine (once more). The structure with
    // object-handlers has a get_method and call_method member. When a function is
    // called, the get_method function is called first, to retrieve information
    // about the method (like the handler that should be called to execute it),
    // after that, this returned handler is also called. The call_method property
    // of the object_handlers structure however, never gets called. Typical.
    
    // first we'll check if the default handler does not have an implementation,
    // in that case the method is probably already implemented as a regular method
#if PHP_VERSION_ID < 50399
    auto *defaultFunction = std_object_handlers.get_method(object_ptr, method_name, method_len);
#else
    auto *defaultFunction = std_object_handlers.get_method(object_ptr, method_name, method_len, key);
#endif

    // did the default implementation do anything?
    if (defaultFunction) return defaultFunction;
    
    // retrieve the class entry linked to this object
    auto *entry = zend_get_class_entry(*object_ptr);

    // this is peculiar behavior of the zend engine, we first are going to dynamically 
    // allocate memory holding all the properties of the __call method (we initially
    // had an implementation here that used a static variable, and that worked too,
    // but we'll follow thread safe implementation of the Zend engine here, although
    // it is strange to allocate and free memory in one and the same method call (free()
    // call happens in call_method())
    auto *function = (zend_internal_function *)emalloc(sizeof(zend_internal_function));
    
    // we're going to set all properties
    function->type = ZEND_INTERNAL_FUNCTION;
    function->module = nullptr;
    function->handler = call_method;
    function->arg_info = nullptr;
    function->num_args = 0;
    function->scope = entry;
    function->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
    function->function_name = method_name;
    
    // done (cast to zend_function* is allowed, because a zend_function is a union
    // that has one member being a zend_internal_function)
    return (zend_function *)function;
}
예제 #3
0
/**
 *  Method that returns the closure -- this is the __invoke handler!
 *  @param  object
 *  @param  entry_ptr
 *  @param  func
 *  @param  object_ptr
 *  @return int
 */
int ClassBase::getClosure(zval *object, zend_class_entry **entry_ptr, zend_function **func, zval **object_ptr)
{
    // it is really unbelievable how the Zend engine manages to implement every feature
    // in a complete different manner. You would expect the __invoke() and the
    // __call() functions not to be very different from each other. However, they
    // both have a completely different API. This getClosure method is supposed
    // to fill the function parameter with all information about the invoke()
    // method that is going to get called
    
    // retrieve the class entry linked to this object
    auto *entry = zend_get_class_entry(object);

    // just like we did for getMethod(), we're going to dynamically allocate memory
    // with all information about the function
    auto *function = (zend_internal_function *)emalloc(sizeof(zend_internal_function));
    
    // we're going to set all properties
    function->type = ZEND_INTERNAL_FUNCTION;
    function->module = nullptr;
    function->handler = call_invoke;
    function->arg_info = nullptr;
    function->num_args = 0;
    function->scope = entry;
    function->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
    function->function_name = nullptr;
    
    // assign this dynamically allocated variable to the func parameter
    // the case is ok, because zend_internal_function is a member of the
    // zend_function union
    *func = (zend_function *)function;
 
    // the object_ptr should be filled with the object on which the method is 
    // called (otherwise the Zend engine tries to call the method statically)
    *object_ptr = object;
    
    // done
    return SUCCESS;
};
예제 #4
0
void binary_deserialize_spec(zval* zthis, PHPInputTransport& transport, HashTable* spec) {
    // SET and LIST have 'elem' => array('type', [optional] 'class')
    // MAP has 'val' => array('type', [optiona] 'class')
    TSRMLS_FETCH();
    zend_class_entry* ce = zend_get_class_entry(zthis TSRMLS_CC);
    while (true) {
        zval** val_ptr = NULL;

        int8_t ttype = transport.readI8();
        if (ttype == T_STOP) return;
        int16_t fieldno = transport.readI16();
        if (zend_hash_index_find(spec, fieldno, (void**)&val_ptr) == SUCCESS) {
            HashTable* fieldspec = Z_ARRVAL_PP(val_ptr);
            // pull the field name
            // zend hash tables use the null at the end in the length... so strlen(hash key) + 1.
            zend_hash_find(fieldspec, "var", 4, (void**)&val_ptr);
            char* varname = Z_STRVAL_PP(val_ptr);

            // and the type
            zend_hash_find(fieldspec, "type", 5, (void**)&val_ptr);
            if (Z_TYPE_PP(val_ptr) != IS_LONG) convert_to_long(*val_ptr);
            int8_t expected_ttype = Z_LVAL_PP(val_ptr);

            if (ttypes_are_compatible(ttype, expected_ttype)) {
                zval* rv = NULL;
                MAKE_STD_ZVAL(rv);
                binary_deserialize(ttype, transport, rv, fieldspec);
                zend_update_property(ce, zthis, varname, strlen(varname), rv TSRMLS_CC);
                zval_ptr_dtor(&rv);
            } else {
                skip_element(ttype, transport);
            }
        } else {
            skip_element(ttype, transport);
        }
    }
}
예제 #5
0
inline int msgpack_convert_string_to_properties(
    zval *object, char *key, uint key_len, zval *val, HashTable *var)
{
    zval **data = NULL;
    HashTable *ht;
    zend_class_entry *ce;
    char *prot_name, *priv_name;
    int prop_name_len;
    TSRMLS_FETCH();

    ht = HASH_OF(object);
    ce = zend_get_class_entry(object TSRMLS_CC);

    /* private */
    zend_mangle_property_name(
        &priv_name, &prop_name_len, ce->name, ce->name_length, key, key_len, 1);
    if (zend_hash_find(
            ht, priv_name, prop_name_len, (void **)&data) == SUCCESS)
    {
        MSGPACK_CONVERT_UPDATE_PROPERTY(ht, priv_name, prop_name_len, val, var);
    }

    /* protected */
    zend_mangle_property_name(
        &prot_name, &prop_name_len, "*", 1, key, key_len, 1);
    if (zend_hash_find(
            ht, prot_name, prop_name_len, (void **)&data) == SUCCESS)
    {
        MSGPACK_CONVERT_UPDATE_PROPERTY(ht, prot_name, prop_name_len, val, var);
    }

    /* public */
    MSGPACK_CONVERT_UPDATE_PROPERTY(ht, key, key_len, val, var);

    return FAILURE;
}
예제 #6
0
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;
}
예제 #7
0
    // remember that object is now initialized
    initialized = true;
    
    // done
    return &handlers;
}
    
/**
 *  Function that is called to create space for a cloned object
 *  @param  val                     The object to be cloned
 *  @return zend_obejct_value       The object to be created
 */
zend_object_value ClassBase::cloneObject(zval *val TSRMLS_DC)
{
    // retrieve the class entry linked to this object
    auto *entry = zend_get_class_entry(val);

    // we need the C++ class meta-information object
    ClassBase *meta = cpp_class(entry);

    // retrieve the old object, which we are going to copy
    MixedObject *old_object = (MixedObject *)zend_object_store_get_object(val);

    // create a new base c++ object
    auto *cpp = meta->clone(old_object->cpp);
    
    // report error on failure
    if (!cpp) throw Php::Exception(std::string("Unable to clone ") + entry->name);

    // the thing we're going to return
    zend_object_value result;
예제 #8
0
void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval** value, HashTable* fieldspec) {
    // At this point the typeID (and field num, if applicable) should've already been written to the output so all we need to do is write the payload.
    switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
        return;
    case T_STRUCT: {
        TSRMLS_FETCH();
        if (Z_TYPE_PP(value) != IS_OBJECT) {
            throw_tprotocolexception("Attempt to send non-object type as a T_STRUCT", INVALID_DATA);
        }
        zval* spec = zend_read_static_property(zend_get_class_entry(*value TSRMLS_CC), "_TSPEC", 6, false TSRMLS_CC);
        binary_serialize_spec(*value, transport, Z_ARRVAL_P(spec));
    }
    return;
    case T_BOOL:
        if (Z_TYPE_PP(value) != IS_BOOL) convert_to_boolean(*value);
        transport.writeI8(Z_BVAL_PP(value) ? 1 : 0);
        return;
    case T_BYTE:
        if (Z_TYPE_PP(value) != IS_LONG) convert_to_long(*value);
        transport.writeI8(Z_LVAL_PP(value));
        return;
    case T_I16:
        if (Z_TYPE_PP(value) != IS_LONG) convert_to_long(*value);
        transport.writeI16(Z_LVAL_PP(value));
        return;
    case T_I32:
        if (Z_TYPE_PP(value) != IS_LONG) convert_to_long(*value);
        transport.writeI32(Z_LVAL_PP(value));
        return;
    case T_I64:
    case T_U64:
        if (Z_TYPE_PP(value) != IS_LONG) convert_to_long(*value);
        transport.writeI64(Z_LVAL_PP(value));
        return;
    case T_DOUBLE: {
        union {
            int64_t c;
            double d;
        } a;
        if (Z_TYPE_PP(value) != IS_DOUBLE) convert_to_double(*value);
        a.d = Z_DVAL_PP(value);
        transport.writeI64(a.c);
    }
    return;
    //case T_UTF7:
    case T_UTF8:
    case T_UTF16:
    case T_STRING:
        if (Z_TYPE_PP(value) != IS_STRING) convert_to_string(*value);
        transport.writeString(Z_STRVAL_PP(value), Z_STRLEN_PP(value));
        return;
    case T_MAP: {
        if (Z_TYPE_PP(value) != IS_ARRAY) convert_to_array(*value);
        if (Z_TYPE_PP(value) != IS_ARRAY) {
            throw_tprotocolexception("Attempt to send an incompatible type as an array (T_MAP)", INVALID_DATA);
        }
        HashTable* ht = Z_ARRVAL_PP(value);
        zval** val_ptr;

        zend_hash_find(fieldspec, "ktype", 6, (void**)&val_ptr);
        if (Z_TYPE_PP(val_ptr) != IS_LONG) convert_to_long(*val_ptr);
        uint8_t keytype = Z_LVAL_PP(val_ptr);
        transport.writeI8(keytype);
        zend_hash_find(fieldspec, "vtype", 6, (void**)&val_ptr);
        if (Z_TYPE_PP(val_ptr) != IS_LONG) convert_to_long(*val_ptr);
        uint8_t valtype = Z_LVAL_PP(val_ptr);
        transport.writeI8(valtype);

        zend_hash_find(fieldspec, "val", 4, (void**)&val_ptr);
        HashTable* valspec = Z_ARRVAL_PP(val_ptr);

        transport.writeI32(zend_hash_num_elements(ht));
        HashPosition key_ptr;
        for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) {
            binary_serialize_hashtable_key(keytype, transport, ht, key_ptr);
            binary_serialize(valtype, transport, val_ptr, valspec);
        }
    }
    return;
    case T_LIST: {
        if (Z_TYPE_PP(value) != IS_ARRAY) convert_to_array(*value);
        if (Z_TYPE_PP(value) != IS_ARRAY) {
            throw_tprotocolexception("Attempt to send an incompatible type as an array (T_LIST)", INVALID_DATA);
        }
        HashTable* ht = Z_ARRVAL_PP(value);
        zval** val_ptr;

        zend_hash_find(fieldspec, "etype", 6, (void**)&val_ptr);
        if (Z_TYPE_PP(val_ptr) != IS_LONG) convert_to_long(*val_ptr);
        uint8_t valtype = Z_LVAL_PP(val_ptr);
        transport.writeI8(valtype);

        zend_hash_find(fieldspec, "elem", 5, (void**)&val_ptr);
        HashTable* valspec = Z_ARRVAL_PP(val_ptr);

        transport.writeI32(zend_hash_num_elements(ht));
        HashPosition key_ptr;
        for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) {
            binary_serialize(valtype, transport, val_ptr, valspec);
        }
    }
    return;
    case T_SET: {
        if (Z_TYPE_PP(value) != IS_ARRAY) convert_to_array(*value);
        if (Z_TYPE_PP(value) != IS_ARRAY) {
            throw_tprotocolexception("Attempt to send an incompatible type as an array (T_SET)", INVALID_DATA);
        }
        HashTable* ht = Z_ARRVAL_PP(value);
        zval** val_ptr;

        zend_hash_find(fieldspec, "etype", 6, (void**)&val_ptr);
        if (Z_TYPE_PP(val_ptr) != IS_LONG) convert_to_long(*val_ptr);
        uint8_t keytype = Z_LVAL_PP(val_ptr);
        transport.writeI8(keytype);

        transport.writeI32(zend_hash_num_elements(ht));
        HashPosition key_ptr;
        for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) {
            binary_serialize_hashtable_key(keytype, transport, ht, key_ptr);
        }
    }
    return;
    };
    char errbuf[128];
    sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
    throw_tprotocolexception(errbuf, INVALID_DATA);
}
예제 #9
0
void binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport, zval* return_value, HashTable* fieldspec) {
    zval** val_ptr;
    Z_TYPE_P(return_value) = IS_NULL; // just in case

    switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
        RETURN_NULL();
        return;
    case T_STRUCT: {
        if (zend_hash_find(fieldspec, "class", 6, (void**)&val_ptr) != SUCCESS) {
            throw_tprotocolexception("no class type in spec", INVALID_DATA);
            skip_element(T_STRUCT, transport);
            RETURN_NULL();
        }
        char* structType = Z_STRVAL_PP(val_ptr);
        createObject(structType, return_value);
        if (Z_TYPE_P(return_value) == IS_NULL) {
            // unable to create class entry
            skip_element(T_STRUCT, transport);
            RETURN_NULL();
        }
        TSRMLS_FETCH();
        zval* spec = zend_read_static_property(zend_get_class_entry(return_value TSRMLS_CC), "_TSPEC", 6, false TSRMLS_CC);
        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(c);
    }
    case T_I16: {
        uint16_t c;
        transport.readBytes(&c, 2);
        RETURN_LONG(ntohs(c));
    }
    case T_I32: {
        uint32_t c;
        transport.readBytes(&c, 4);
        RETURN_LONG(ntohl(c));
    }
    case T_U64:
    case T_I64: {
        uint64_t c;
        transport.readBytes(&c, 8);
        RETURN_LONG(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 = (char*) emalloc(size + 1);
            transport.readBytes(strbuf, size);
            strbuf[size] = '\0';
            ZVAL_STRINGL(return_value, strbuf, size, 0);
        } 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);

        zend_hash_find(fieldspec, "key", 4, (void**)&val_ptr);
        HashTable* keyspec = Z_ARRVAL_PP(val_ptr);
        zend_hash_find(fieldspec, "val", 4, (void**)&val_ptr);
        HashTable* valspec = Z_ARRVAL_PP(val_ptr);

        for (uint32_t s = 0; s < size; ++s) {
            zval *value;
            MAKE_STD_ZVAL(value);

            zval* key;
            MAKE_STD_ZVAL(key);

            binary_deserialize(types[0], transport, key, keyspec);
            binary_deserialize(types[1], transport, value, valspec);
            if (Z_TYPE_P(key) == IS_LONG) {
                zend_hash_index_update(return_value->value.ht, Z_LVAL_P(key), &value, sizeof(zval *), NULL);
            }
            else {
                if (Z_TYPE_P(key) != IS_STRING) convert_to_string(key);
                zend_hash_update(return_value->value.ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
            }
            zval_ptr_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();
        zend_hash_find(fieldspec, "elem", 5, (void**)&val_ptr);
        HashTable* elemspec = Z_ARRVAL_PP(val_ptr);

        array_init(return_value);
        for (uint32_t s = 0; s < size; ++s) {
            zval *value;
            MAKE_STD_ZVAL(value);
            binary_deserialize(type, transport, value, elemspec);
            zend_hash_next_index_insert(return_value->value.ht, &value, sizeof(zval *), NULL);
        }
        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);
        zend_hash_find(fieldspec, "elem", 5, (void**)&val_ptr);
        HashTable* elemspec = Z_ARRVAL_PP(val_ptr);

        array_init(return_value);

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

            binary_deserialize(type, transport, key, elemspec);

            if (Z_TYPE_P(key) == IS_LONG) {
                zend_hash_index_update(return_value->value.ht, Z_LVAL_P(key), &value, sizeof(zval *), NULL);
            }
            else {
                if (Z_TYPE_P(key) != IS_STRING) convert_to_string(key);
                zend_hash_update(return_value->value.ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
            }
            zval_ptr_dtor(&key);
        }
        return;
    }
    };

    char errbuf[128];
    sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
    throw_tprotocolexception(errbuf, INVALID_DATA);
}
예제 #10
0
/* ***** AUTH PARAMS IN 1.4 API
 * SVN_AUTH_PARAM_DEFAULT_USERNAME y
 * SVN_AUTH_PARAM_DEFAULT_PASSWORD y
 * SVN_AUTH_PARAM_NON_INTERACTIVE y
 * SVN_AUTH_PARAM_DONT_STORE_PASSWORDS y
 * SVN_AUTH_PARAM_NO_AUTH_CACHE y
 * SVN_AUTH_PARAM_SSL_SERVER_FAILURES
 * SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO
 * SVN_AUTH_PARAM_CONFIG
 * SVN_AUTH_PARAM_SERVER_GROUP y
 * SVN_AUTH_PARAM_CONFIG_DIR y
 */

zend_bool svn_auth_baton_is_instance(zval *obj TSRMLS_DC) /* {{{ */
{
	zend_class_entry *ce = zend_get_class_entry(obj TSRMLS_CC);
	return instanceof_function(ce, svn_auth_baton_object_ce TSRMLS_CC);
}
/* }}} */

static void _svn_auth_baton_object_free_storage(void *object TSRMLS_DC) /* {{{ */
{
	svn_auth_baton_object *intern = (svn_auth_baton_object *) object;

	if (!intern) {
		return;
	}

	if (intern->pool) {
		apr_pool_destroy(intern->pool);
		intern->pool = NULL;
예제 #11
0
int msgpack_convert_object(zval *return_value, zval *object, zval **value)
{
    zend_class_entry *ce, **pce;
    HashTable *properties = NULL;
    HashPosition prop_pos;
    TSRMLS_FETCH();

    switch (Z_TYPE_P(object))
    {
        case IS_STRING:
            if (zend_lookup_class(
                    Z_STRVAL_P(object), Z_STRLEN_P(object),
                    &pce TSRMLS_CC) != SUCCESS)
            {
                MSGPACK_ERROR("[msgpack] (%s) Class '%s' not found",
                              __FUNCTION__, Z_STRVAL_P(object));
                return FAILURE;
            }
            ce = *pce;
            break;
        case IS_OBJECT:
            ce = zend_get_class_entry(object 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);
    properties = Z_OBJ_HT_P(return_value)->get_properties(
        return_value TSRMLS_CC);
    if (HASH_OF(object))
    {
        properties = HASH_OF(object);
    }
    zend_hash_internal_pointer_reset_ex(properties, &prop_pos);

    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;
            }

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

            /* string */
            if (ht->nNumOfElements != ht->nNextFreeElement)
            {
                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 */
            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);

            zval_ptr_dtor(value);
            break;
        }
        default:
            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;
}