Example #1
0
/*
 * Reads an AMF0 hash, with a configurable key reading function - either
 * des_read_string or des_read_sym
 */
static void des0_read_props(VALUE self, VALUE hash, VALUE(*read_key)(AMF_DESERIALIZER*, unsigned long)) {
    AMF_DESERIALIZER *des;
    Data_Get_Struct(self, AMF_DESERIALIZER, des);

    while(1) {
        int len = des_read_uint16(des);
        if(len == 0) {
            des_read_byte(des); // Read type byte
            return;
        } else {
            VALUE key = read_key(des, len);
            char type = des_read_byte(des);
            rb_hash_aset(hash, key, des0_deserialize(self, type));
        }
    }
}
Example #2
0
/*
 * call-seq:
 *   des.deserialize(str) => obj
 *   des.deserialize(StringIO) => obj
 *
 * Deserialize the string or StringIO from AMF to a ruby object.
 */
static VALUE des0_deserialize_rb(int argc, VALUE *argv, VALUE self) {
    AMF_DESERIALIZER *des;
    Data_Get_Struct(self, AMF_DESERIALIZER, des);
    VALUE ret = des0_deserialize(self, des_read_byte(des));
    rb_funcall(des->src, rb_intern("pos="), 1, LONG2NUM(des->pos)); // Update source StringIO pos
    return ret;
}
Example #3
0
/*
 * Internal C deserialize call. Takes deserializer and a char for the type
 * marker.
 */
static VALUE des0_deserialize(VALUE self, char type) {
    AMF_DESERIALIZER *des;
    Data_Get_Struct(self, AMF_DESERIALIZER, des);

    long tmp;
    VALUE ret = Qnil;
    switch(type) {
        case AMF0_STRING_MARKER:
            ret = des_read_string(des, des_read_uint16(des));
            break;
        case AMF0_AMF3_MARKER:
            ret = des0_read_amf3(self);
            break;
        case AMF0_NUMBER_MARKER:
            ret = rb_float_new(des_read_double(des));
            break;
        case AMF0_BOOLEAN_MARKER:
            ret = des_read_byte(des) == 0 ? Qfalse : Qtrue;
            break;
        case AMF0_NULL_MARKER:
        case AMF0_UNDEFINED_MARKER:
        case AMF0_UNSUPPORTED_MARKER:
            ret = Qnil;
            break;
        case AMF0_OBJECT_MARKER:
            ret = des0_read_object(self);
            break;
        case AMF0_TYPED_OBJECT_MARKER:
            ret = des0_read_typed_object(self);
            break;
        case AMF0_HASH_MARKER:
            ret = des0_read_hash(self);
            break;
        case AMF0_STRICT_ARRAY_MARKER:
            ret = des0_read_array(self);
            break;
        case AMF0_REFERENCE_MARKER:
            tmp = des_read_uint16(des);
            if(tmp >= RARRAY_LEN(des->obj_cache)) rb_raise(rb_eRangeError, "reference index beyond end");
            ret = RARRAY_PTR(des->obj_cache)[tmp];
            break;
        case AMF0_DATE_MARKER:
            ret = des0_read_time(self);
            break;
        case AMF0_XML_MARKER:
        case AMF0_LONG_STRING_MARKER:
            ret = des_read_string(des, des_read_uint32(des));
            break;
        default:
            rb_raise(rb_eRuntimeError, "Not supported: %d", type);
            break;
    }

    return ret;
}
Example #4
0
static VALUE des0_read_array(VALUE self) {
    AMF_DESERIALIZER *des;
    Data_Get_Struct(self, AMF_DESERIALIZER, des);

    // Limit size of pre-allocation to force remote user to actually send data,
    // rather than just sending a size of 2**32-1 and nothing afterwards to
    // crash the server
    unsigned long len = des_read_uint32(des);
    VALUE ary = rb_ary_new2(len < MAX_ARRAY_PREALLOC ? len : MAX_ARRAY_PREALLOC);
    rb_ary_push(des->obj_cache, ary);

    long i;
    for(i = 0; i < len; i++) {
        rb_ary_push(ary, des0_deserialize(self, des_read_byte(des)));
    }

    return ary;
}