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 }
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; }
/** * 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; };
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); } } }
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; }
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; }
// 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;
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); }
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); }
/* ***** 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;
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; }