Example #1
0
void binary_serialize_spec(const Object& zthis, PHPOutputTransport& transport,
                           const Array& spec) {
  for (ArrayIter key_ptr = spec.begin(); !key_ptr.end(); ++key_ptr) {
    Variant key = key_ptr.first();
    if (!key.isInteger()) {
      throw_tprotocolexception("Bad keytype in TSPEC (expected 'long')", INVALID_DATA);
      return;
    }
    unsigned long fieldno = key.toInt64();
    Array fieldspec = key_ptr.second().toArray();

    // field name
    String varname = fieldspec.rvalAt(PHPTransport::s_var,
                                      AccessFlags::Error_Key).toString();

    // thrift type
    int8_t ttype = fieldspec.rvalAt(PHPTransport::s_type,
                                    AccessFlags::Error_Key).toByte();

    Variant prop = zthis->o_get(varname, true, zthis->getClassName());
    if (!prop.isNull()) {
      transport.writeI8(ttype);
      transport.writeI16(fieldno);
      binary_serialize(ttype, transport, prop, fieldspec);
    }
  }
  transport.writeI8(T_STOP); // struct end
}
Example #2
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
}
Example #3
0
static
void binary_serialize_spec(zval* zthis, PHPOutputTransport& transport, HashTable* spec) {
    HashPosition key_ptr;
    zval* val_ptr;

    for (zend_hash_internal_pointer_reset_ex(spec, &key_ptr);
            (val_ptr = zend_hash_get_current_data_ex(spec, &key_ptr)) != nullptr;
            zend_hash_move_forward_ex(spec, &key_ptr)) {

        zend_ulong fieldno;
        if (zend_hash_get_current_key_ex(spec, nullptr, &fieldno, &key_ptr) != HASH_KEY_IS_LONG) {
            throw_tprotocolexception("Bad keytype in TSPEC (expected 'long')", INVALID_DATA);
            return;
        }
        HashTable* fieldspec = Z_ARRVAL_P(val_ptr);

        // field name
        val_ptr = zend_hash_str_find(fieldspec, "var", sizeof("var")-1);
        char* varname = Z_STRVAL_P(val_ptr);

        // thrift type
        val_ptr = zend_hash_str_find(fieldspec, "type", sizeof("type")-1);
        if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr);
        int8_t ttype = Z_LVAL_P(val_ptr);

        zval rv;
        zval* prop = zend_read_property(Z_OBJCE_P(zthis), zthis, varname, strlen(varname), false, &rv);
        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
}
Example #4
0
void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport,
                      const Variant& value, const Array& 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: {
      if (!value.is(KindOfObject)) {
        throw_tprotocolexception("Attempt to send non-object "
                                 "type as a T_STRUCT", INVALID_DATA);
      }
      binary_serialize_spec(value.toObject(), transport,
                            HHVM_FN(hphp_get_static_property)(value.toObject()->
                                                       getClassName(),
                                                       s_TSPEC,
                                                       false).toArray());
    } return;
    case T_BOOL:
      transport.writeI8(value.toBoolean() ? 1 : 0);
      return;
    case T_BYTE:
      transport.writeI8(value.toByte());
      return;
    case T_I16:
      transport.writeI16(value.toInt16());
      return;
    case T_I32:
      transport.writeI32(value.toInt32());
      return;
    case T_I64:
    case T_U64:
      transport.writeI64(value.toInt64());
      return;
    case T_DOUBLE: {
      union {
        int64_t c;
        double d;
      } a;
      a.d = value.toDouble();
      transport.writeI64(a.c);
    } return;
    case T_FLOAT: {
      union {
        int32_t c;
        float d;
      } a;
      a.d = (float)value.toDouble();
      transport.writeI32(a.c);
    } return;
    //case T_UTF7:
    case T_UTF8:
    case T_UTF16:
    case T_STRING: {
        String sv = value.toString();
        transport.writeString(sv.data(), sv.size());
    } return;
    case T_MAP: {
      Array ht = value.toArray();
      uint8_t keytype = fieldspec.rvalAt(PHPTransport::s_ktype,
                                         AccessFlags::Error_Key).toByte();
      transport.writeI8(keytype);
      uint8_t valtype = fieldspec.rvalAt(PHPTransport::s_vtype,
                                         AccessFlags::Error_Key).toByte();
      transport.writeI8(valtype);

      Array valspec = fieldspec.rvalAt(PHPTransport::s_val,
                                       AccessFlags::Error_Key).toArray();

      transport.writeI32(ht.size());
      for (ArrayIter key_ptr = ht.begin(); !key_ptr.end(); ++key_ptr) {
        binary_serialize_hashtable_key(keytype, transport, key_ptr.first());
        binary_serialize(valtype, transport, key_ptr.second(), valspec);
      }
    } return;
    case T_LIST: {
      Array ht = value.toArray();
      Variant val;

      uint8_t valtype = fieldspec.rvalAt(PHPTransport::s_etype,
                                         AccessFlags::Error_Key).toInt64();
      transport.writeI8(valtype);
      Array valspec = fieldspec.rvalAt(PHPTransport::s_elem,
                                       AccessFlags::Error_Key).toArray();
      transport.writeI32(ht.size());
      for (ArrayIter key_ptr = ht.begin(); !key_ptr.end(); ++key_ptr) {
        binary_serialize(valtype, transport, key_ptr.second(), valspec);
      }
    } return;
    case T_SET: {
      Array ht = value.toArray();

      uint8_t keytype = fieldspec.rvalAt(PHPTransport::s_etype,
                                         AccessFlags::Error_Key).toByte();
      transport.writeI8(keytype);

      transport.writeI32(ht.size());
      for (ArrayIter key_ptr = ht.begin(); !key_ptr.end(); ++key_ptr) {
        binary_serialize_hashtable_key(keytype, transport, key_ptr.first());
      }
    } return;
  };
  char errbuf[128];
  sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
  throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
}
Example #5
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);
}
Example #6
0
static
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: {
      if (Z_TYPE_P(value) != IS_OBJECT) {
        throw_tprotocolexception("Attempt to send non-object type as a T_STRUCT", INVALID_DATA);
      }
      zval* spec = zend_read_static_property(Z_OBJCE_P(value), "_TSPEC", sizeof("_TSPEC")-1, false);
      if (Z_TYPE_P(spec) != IS_ARRAY) {
        throw_tprotocolexception("Attempt to send non-Thrift object as a T_STRUCT", INVALID_DATA);
      }
      binary_serialize_spec(value, transport, Z_ARRVAL_P(spec));
    } return;
    case T_BOOL:
      if (!zval_is_bool(value)) convert_to_boolean(value);
      transport.writeI8(Z_TYPE_INFO_P(value) == IS_TRUE ? 1 : 0);
      return;
    case T_BYTE:
      if (Z_TYPE_P(value) != IS_LONG) convert_to_long(value);
      transport.writeI8(Z_LVAL_P(value));
      return;
    case T_I16:
      if (Z_TYPE_P(value) != IS_LONG) convert_to_long(value);
      transport.writeI16(Z_LVAL_P(value));
      return;
    case T_I32:
      if (Z_TYPE_P(value) != IS_LONG) convert_to_long(value);
      transport.writeI32(Z_LVAL_P(value));
      return;
    case T_I64:
    case T_U64: {
      int64_t l_data;
#if defined(_LP64) || defined(_WIN64)
      if (Z_TYPE_P(value) != IS_LONG) convert_to_long(value);
      l_data = Z_LVAL_P(value);
#else
      if (Z_TYPE_P(value) != IS_DOUBLE) convert_to_double(value);
      l_data = (int64_t)Z_DVAL_P(value);
#endif
      transport.writeI64(l_data);
    } return;
    case T_DOUBLE: {
      union {
        int64_t c;
        double d;
      } a;
      if (Z_TYPE_P(value) != IS_DOUBLE) convert_to_double(value);
      a.d = Z_DVAL_P(value);
      transport.writeI64(a.c);
    } return;
    case T_UTF8:
    case T_UTF16:
    case T_STRING:
      if (Z_TYPE_P(value) != IS_STRING) convert_to_string(value);
      transport.writeString(Z_STRVAL_P(value), Z_STRLEN_P(value));
      return;
    case T_MAP: {
      if (Z_TYPE_P(value) != IS_ARRAY) convert_to_array(value);
      if (Z_TYPE_P(value) != IS_ARRAY) {
        throw_tprotocolexception("Attempt to send an incompatible type as an array (T_MAP)", INVALID_DATA);
      }
      HashTable* ht = Z_ARRVAL_P(value);
      zval* val_ptr;

      val_ptr = zend_hash_str_find(fieldspec, "ktype", sizeof("ktype")-1);
      if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr);
      uint8_t keytype = Z_LVAL_P(val_ptr);
      transport.writeI8(keytype);
      val_ptr = zend_hash_str_find(fieldspec, "vtype", sizeof("vtype")-1);
      if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr);
      uint8_t valtype = Z_LVAL_P(val_ptr);
      transport.writeI8(valtype);

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

      transport.writeI32(zend_hash_num_elements(ht));
      HashPosition key_ptr;
      for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr);
           (val_ptr = zend_hash_get_current_data_ex(ht, &key_ptr)) != nullptr;
           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_P(value) != IS_ARRAY) convert_to_array(value);
      if (Z_TYPE_P(value) != IS_ARRAY) {
        throw_tprotocolexception("Attempt to send an incompatible type as an array (T_LIST)", INVALID_DATA);
      }
      HashTable* ht = Z_ARRVAL_P(value);
      zval* val_ptr;

      val_ptr = zend_hash_str_find(fieldspec, "etype", sizeof("etype")-1);
      if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr);
      uint8_t valtype = Z_LVAL_P(val_ptr);
      transport.writeI8(valtype);

      val_ptr = zend_hash_str_find(fieldspec, "elem", sizeof("elem")-1);
      HashTable* valspec = Z_ARRVAL_P(val_ptr);

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

      val_ptr = zend_hash_str_find(fieldspec, "etype", sizeof("etype")-1);
      if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr);
      uint8_t keytype = Z_LVAL_P(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);
           (val_ptr = zend_hash_get_current_data_ex(ht, &key_ptr)) != nullptr;
           zend_hash_move_forward_ex(ht, &key_ptr)) {
        binary_serialize_hashtable_key(keytype, transport, ht, key_ptr);
      }
    } return;
  };

  char errbuf[128];
  snprintf(errbuf, 128, "Unknown thrift typeID %d", thrift_typeID);
  throw_tprotocolexception(errbuf, INVALID_DATA);
}