Beispiel #1
0
        public void ConstructorWithIndexedValues()
        {
            IASValue[] indexedValues = new IASValue[] { null, null, null };
            ASArray array = new ASArray(indexedValues);

            Assert.AreSame(indexedValues, array.IndexedValues);
            Assert.AreEqual(0, array.DynamicProperties.Count);
        }
        public void Reset()
        {
            classDefinitionCache.Clear();
            objectReferenceCache.Clear();
            stringReferenceCache.Clear();

            currentValue = null;
        }
Beispiel #3
0
        public void ConstructorWithIndexedAndMixedValues()
        {
            IASValue[] indexedValues = new IASValue[] { null, null, null };
            IDictionary<string, IASValue> mixedValues = new Dictionary<string, IASValue>();

            ASArray array = new ASArray(indexedValues, mixedValues);

            Assert.AreSame(indexedValues, array.IndexedValues);
            Assert.AreSame(mixedValues, array.DynamicProperties);
        }
        public void WriteObject(IASValue value)
        {
            if (value == null)
            {
                WriteNull();
                return;
            }

            // Check if we have seen the object reference before.
            CacheItem cacheItem;
            if (objectReferenceCache.TryGetValue(value, out cacheItem))
            {
                WriteCachedValue(cacheItem);
                return;
            }

            // Otherwise write it out fresh.
            currentValue = value;
            value.AcceptVisitor(output.Serializer, this);
            currentValue = null;
        }
        private IASValue ReadArray()
        {
            int bits = input.ReadVWInt29();
            int lengthOrReferenceId = bits >> 1;

            // Handle cached objects.
            if ((bits & 1) == 0)
            {
                return GetObjectFromCache(AMF3ObjectTypeCode.Array, lengthOrReferenceId);
            }

            // Read out the whole array.
            if (lengthOrReferenceId < 0)
                throw new AMFException(String.Format(CultureInfo.CurrentCulture,
                    ExceptionPrefix + "Encountered Array token with invalid length '{0}'.", lengthOrReferenceId));

            // Important: Add the array to the cache before deserializing its properties!
            ASArray result = ASArray.CreateUninitializedInstance();
            AddObjectToCache(AMF3ObjectTypeCode.Array, result);

            // Read mixed values if any.
            IDictionary<string, IASValue> mixedValues;

            string key = ReadStringData();
            if (key.Length != 0)
            {
                mixedValues = new Dictionary<string, IASValue>();

                for (; ; )
                {
                    IASValue value = ReadObject();
                    mixedValues.Add(key, value);

                    key = ReadStringData();
                    if (key.Length == 0)
                        break;
                }
            }
            else
            {
                mixedValues = EmptyDictionary<string, IASValue>.Instance;
            }

            // Read indexed values if any.
            IASValue[] indexedValues;

            if (lengthOrReferenceId != 0)
            {
                indexedValues = new IASValue[lengthOrReferenceId];

                for (int i = 0; i < lengthOrReferenceId; i++)
                    indexedValues[i] = ReadObject();
            }
            else
            {
                indexedValues = EmptyArray<IASValue>.Instance;
            }

            result.SetProperties(indexedValues, mixedValues);
            return result;
        }
Beispiel #6
0
        public void AddResultResponse(string responseTarget, object content)
        {
            IASValue asContent = context.Serializer.ToASValue(content);

            AddBody(new AMFBody(responseTarget + ResultTargetSuffix, "null", asContent));
        }
            /// <summary>
            /// Sets a mapped property or field value using reflection.
            /// </summary>
            /// <param name="serializer"></param>
            /// <param name="instance"></param>
            /// <param name="propertyOrField"></param>
            /// <param name="value"></param>
            private static void SetMappedPropertyOrField(IActionScriptSerializer serializer, object instance, MemberInfo propertyOrField, IASValue value)
            {
                try
                {
                    // Try to set the property.
                    PropertyInfo property = propertyOrField as PropertyInfo;
                    if (property != null)
                    {
                        object propertyValue = serializer.ToNative(value, property.PropertyType);
                        property.SetValue(instance, propertyValue, null);
                        return;
                    }

                    // Oh, it must be a field then.
                    FieldInfo field = (FieldInfo)propertyOrField;
                    object fieldValue = serializer.ToNative(value, field.FieldType);
                    field.SetValue(instance, fieldValue);
                }
                catch (Exception ex)
                {
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                        "Error while setting value of property or field named '{0}' on class '{1}'",
                        propertyOrField.Name, propertyOrField.ReflectedType.FullName), ex);
                }
            }
Beispiel #8
0
 /// <summary>
 /// Converts the ActionScript value to a native value of the specified type.
 /// </summary>
 /// <remarks>
 /// The default implementation visits the <paramref name="asValue"/> and forwards the
 /// data to one of the specialized MapToXXX methods accordingly.
 /// </remarks>
 /// <param name="serializer">The serializer to use</param>
 /// <param name="asValue">The ActionScript value to convert</param>
 /// <param name="nativeType">The native type to produce</param>
 /// <returns>The native value</returns>
 /// <exception cref="ActionScriptException">Thrown if the mapping is not supported</exception>
 public virtual object ToNative(IActionScriptSerializer serializer, IASValue asValue, Type nativeType)
 {
     Visitor visitor = new Visitor(this, nativeType);
     asValue.AcceptVisitor(serializer, visitor);
     return visitor.Result;
 }
Beispiel #9
0
 /// <summary>
 /// Creates an AMF header.
 /// </summary>
 /// <param name="name">The name of the header</param>
 /// <param name="mustUnderstand">A flag that indicates whether the remote host must understand the header</param>
 /// <param name="content">The content of the header</param>
 public AMFHeader(string name, bool mustUnderstand, IASValue content)
 {
     this.name = name;
     this.mustUnderstand = mustUnderstand;
     this.content = content;
 }
        private IASValue ReadArray()
        {
            int length = input.ReadInt();
            if (length < 0)
                throw new AMFException(ExceptionPrefix + "Encountered negative Array length.");

            // Important: Add the array to the cache before deserializing its properties!
            ASArray result = ASArray.CreateUninitializedInstance();
            AddObjectToCache(result);

            IASValue[] indexedValues;

            // Read indexed values, if any.
            if (length != 0)
            {
                indexedValues = new IASValue[length];
                for (int i = 0; i < length; i++)
                    indexedValues[i] = ReadObject();
            }
            else
            {
                indexedValues = EmptyArray<IASValue>.Instance;
            }

            result.SetProperties(indexedValues, EmptyDictionary<string, IASValue>.Instance);
            return result;
        }
 public CacheItem(AMF3ObjectTypeCode objectType, IASValue obj)
 {
     this.ObjectType = objectType;
     this.Object = obj;
 }
Beispiel #12
0
 /// <summary>
 /// Adds the specified object to the reference cache.
 /// </summary>
 /// <param name="objectType">The type of object to cache</param>
 /// <param name="obj">The object to cache</param>
 private void AddObjectToCache(AMF3ObjectTypeCode objectType, IASValue obj)
 {
     objectReferenceCache.Add(new CacheItem(objectType, obj));
 }
Beispiel #13
0
        private IASValue ReadObjectValue()
        {
            int bits = input.ReadVWInt29();

            // Handle cached objects.
            if ((bits & 1) == 0)
            {
                int referenceId = bits >> 1;
                return(GetObjectFromCache(AMF3ObjectTypeCode.Object, referenceId));
            }

            // Handle cached class definitions.
            ASClass classDefinition;

            if ((bits & 2) == 0)
            {
                int referenceId = bits >> 2;

                // Note: Object might be an ASExternalizableObject.
                IASValue obj = GetObjectFromCache(AMF3ObjectTypeCode.Object, referenceId);
                classDefinition = obj.Class;
            }
            else
            {
                // Read the class definition.
                ASClassLayout classLayout = (ASClassLayout)((bits & 0x0c) >> 2);
                if (classLayout > ASClassLayout.Dynamic)
                {
                    throw new AMFException(String.Format(CultureInfo.CurrentCulture,
                                                         ExceptionPrefix + "Encountered Object token with invalid class layout '{0}'.", classLayout));
                }

                int memberCount = bits >> 4;
                if (memberCount < 0)
                {
                    throw new AMFException(String.Format(CultureInfo.CurrentCulture,
                                                         ExceptionPrefix + "Encountered Object token with invalid member count '{0}'.", memberCount));
                }

                if (classLayout == ASClassLayout.Externalizable && memberCount != 0)
                {
                    throw new AMFException(String.Format(CultureInfo.CurrentCulture,
                                                         ExceptionPrefix + "Encountered Object token with Externalizable class layout and non-zero member count '{0}'.", memberCount));
                }

                string classAlias = ReadStringData();

                string[] memberNames;
                if (memberCount != 0)
                {
                    memberNames = new string[memberCount];

                    for (int i = 0; i < memberCount; i++)
                    {
                        memberNames[i] = ReadStringData();
                    }
                }
                else
                {
                    memberNames = EmptyArray <string> .Instance;
                }

                // Look up the class in the cache.
                classDefinition = ASClassCache.GetClass(classAlias, classLayout, memberNames);
            }

            // Read the instance data.
            if (classDefinition.Layout == ASClassLayout.Externalizable)
            {
                // Important: Add the object to the cache before deserializing its properties!
                ASExternalizableObject result = ASExternalizableObject.CreateUninitializedInstance(classDefinition);
                AddObjectToCache(AMF3ObjectTypeCode.Object, result);

                // Use custom serialization for the externalizable object.
                IExternalizable externalizableValue = input.Serializer.CreateExternalizableInstance(classDefinition.ClassAlias);
                externalizableValue.ReadExternal(input);

                result.SetProperties(externalizableValue);
                return(result);
            }
            else
            {
                // Important: Add the object to the cache before deserializing its properties!
                ASObject result = ASObject.CreateUninitializedInstance(classDefinition);
                AddObjectToCache(AMF3ObjectTypeCode.Object, result);

                // Read the member values.
                int        memberCount = classDefinition.MemberNames.Count;
                IASValue[] memberValues;

                if (memberCount != 0)
                {
                    memberValues = new IASValue[memberCount];

                    for (int i = 0; i < memberCount; i++)
                    {
                        memberValues[i] = ReadObject();
                    }
                }
                else
                {
                    memberValues = EmptyArray <IASValue> .Instance;
                }

                // Read the dynamic property values.
                IDictionary <string, IASValue> dynamicProperties;

                if (classDefinition.Layout == ASClassLayout.Dynamic)
                {
                    string key = ReadStringData();
                    if (key.Length != 0)
                    {
                        dynamicProperties = new Dictionary <string, IASValue>();

                        for (; ;)
                        {
                            IASValue value = ReadObject();
                            dynamicProperties.Add(key, value);

                            key = ReadStringData();
                            if (key.Length == 0)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        dynamicProperties = EmptyDictionary <string, IASValue> .Instance;
                    }
                }
                else
                {
                    dynamicProperties = EmptyDictionary <string, IASValue> .Instance;
                }

                result.SetProperties(memberValues, dynamicProperties);
                return(result);
            }
        }
Beispiel #14
0
        private IASValue ReadArray()
        {
            int bits = input.ReadVWInt29();
            int lengthOrReferenceId = bits >> 1;

            // Handle cached objects.
            if ((bits & 1) == 0)
            {
                return(GetObjectFromCache(AMF3ObjectTypeCode.Array, lengthOrReferenceId));
            }

            // Read out the whole array.
            if (lengthOrReferenceId < 0)
            {
                throw new AMFException(String.Format(CultureInfo.CurrentCulture,
                                                     ExceptionPrefix + "Encountered Array token with invalid length '{0}'.", lengthOrReferenceId));
            }

            // Important: Add the array to the cache before deserializing its properties!
            ASArray result = ASArray.CreateUninitializedInstance();

            AddObjectToCache(AMF3ObjectTypeCode.Array, result);

            // Read mixed values if any.
            IDictionary <string, IASValue> mixedValues;

            string key = ReadStringData();

            if (key.Length != 0)
            {
                mixedValues = new Dictionary <string, IASValue>();

                for (; ;)
                {
                    IASValue value = ReadObject();
                    mixedValues.Add(key, value);

                    key = ReadStringData();
                    if (key.Length == 0)
                    {
                        break;
                    }
                }
            }
            else
            {
                mixedValues = EmptyDictionary <string, IASValue> .Instance;
            }

            // Read indexed values if any.
            IASValue[] indexedValues;

            if (lengthOrReferenceId != 0)
            {
                indexedValues = new IASValue[lengthOrReferenceId];

                for (int i = 0; i < lengthOrReferenceId; i++)
                {
                    indexedValues[i] = ReadObject();
                }
            }
            else
            {
                indexedValues = EmptyArray <IASValue> .Instance;
            }

            result.SetProperties(indexedValues, mixedValues);
            return(result);
        }
 public void Reset()
 {
     referenceCache.Clear();
     currentValue = null;
 }
Beispiel #16
0
            /// <summary>
            /// Sets a mapped property or field value using reflection.
            /// </summary>
            /// <param name="serializer"></param>
            /// <param name="instance"></param>
            /// <param name="propertyOrField"></param>
            /// <param name="value"></param>
            private static void SetMappedPropertyOrField(IActionScriptSerializer serializer, object instance, MemberInfo propertyOrField, IASValue value)
            {
                try
                {
                    // Try to set the property.
                    PropertyInfo property = propertyOrField as PropertyInfo;
                    if (property != null)
                    {
                        object propertyValue = serializer.ToNative(value, property.PropertyType);
                        property.SetValue(instance, propertyValue, null);
                        return;
                    }

                    // Oh, it must be a field then.
                    FieldInfo field      = (FieldInfo)propertyOrField;
                    object    fieldValue = serializer.ToNative(value, field.FieldType);
                    field.SetValue(instance, fieldValue);
                }
                catch (Exception ex)
                {
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                                                                  "Error while setting value of property or field named '{0}' on class '{1}'",
                                                                  propertyOrField.Name, propertyOrField.ReflectedType.FullName), ex);
                }
            }
Beispiel #17
0
            /// <summary>
            /// Sets a mapped property or field value or a dynamic property depending on the mapping.
            /// </summary>
            /// <param name="serializer"></param>
            /// <param name="instance"></param>
            /// <param name="dynamic"></param>
            /// <param name="propertyName"></param>
            /// <param name="value"></param>
            private void SetMappedMemberOrDynamicProperty(IActionScriptSerializer serializer, object instance, IDynamic dynamic, string propertyName, IASValue value)
            {
                // Set the mapped property, if there is one.
                ActionScriptPropertyMapping propertyMapping;

                if (propertyMappings.TryGetValue(propertyName, out propertyMapping))
                {
                    SetMappedPropertyOrField(serializer, instance, propertyMapping.NativePropertyOrField, value);

                    // If the property is dynamic then also set it as a dynamic property if possible.
                    if (dynamic != null && propertyMapping.IsDynamic)
                    {
                        SetDynamicProperty(dynamic, serializer, propertyName, value);
                    }
                }
                else if (dynamic != null)
                {
                    SetDynamicProperty(dynamic, serializer, propertyName, value);
                }
                else
                {
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                                                                  "Unable to set value for property '{0}' during ActionScript object deserialization because no suitable mapping is defined and type '{1}' is not dynamic.",
                                                                  propertyName, classMapping.NativeType.FullName));
                }
            }
 private static void SetDynamicProperty(IDynamic dynamic, IActionScriptSerializer serializer,
     string propertyName, IASValue value)
 {
     try
     {
         dynamic.SetDynamicProperty(serializer, propertyName, value);
     }
     catch (Exception ex)
     {
         throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
             "Error while setting value of dynamic property '{0}' on class '{1}'",
             propertyName, dynamic.GetType().FullName), ex);
     }
 }
        private IASValue ReadObjectValue()
        {
            int bits = input.ReadVWInt29();

            // Handle cached objects.
            if ((bits & 1) == 0)
            {
                int referenceId = bits >> 1;
                return GetObjectFromCache(AMF3ObjectTypeCode.Object, referenceId);
            }

            // Handle cached class definitions.
            ASClass classDefinition;

            if ((bits & 2) == 0)
            {
                int referenceId = bits >> 2;

                // Note: Object might be an ASExternalizableObject.
                IASValue obj = GetObjectFromCache(AMF3ObjectTypeCode.Object, referenceId);
                classDefinition = obj.Class;
            }
            else
            {
                // Read the class definition.
                ASClassLayout classLayout = (ASClassLayout) ((bits & 0x0c) >> 2);
                if (classLayout > ASClassLayout.Dynamic)
                    throw new AMFException(String.Format(CultureInfo.CurrentCulture,
                        ExceptionPrefix + "Encountered Object token with invalid class layout '{0}'.", classLayout));

                int memberCount = bits >> 4;
                if (memberCount < 0)
                    throw new AMFException(String.Format(CultureInfo.CurrentCulture,
                        ExceptionPrefix + "Encountered Object token with invalid member count '{0}'.", memberCount));

                if (classLayout == ASClassLayout.Externalizable && memberCount != 0)
                    throw new AMFException(String.Format(CultureInfo.CurrentCulture,
                        ExceptionPrefix + "Encountered Object token with Externalizable class layout and non-zero member count '{0}'.", memberCount));

                string classAlias = ReadStringData();

                string[] memberNames;
                if (memberCount != 0)
                {
                    memberNames = new string[memberCount];

                    for (int i = 0; i < memberCount; i++)
                        memberNames[i] = ReadStringData();
                }
                else
                {
                    memberNames = EmptyArray<string>.Instance;
                }

                // Look up the class in the cache.
                classDefinition = ASClassCache.GetClass(classAlias, classLayout, memberNames);
            }

            // Read the instance data.
            if (classDefinition.Layout == ASClassLayout.Externalizable)
            {
                // Important: Add the object to the cache before deserializing its properties!
                ASExternalizableObject result = ASExternalizableObject.CreateUninitializedInstance(classDefinition);
                AddObjectToCache(AMF3ObjectTypeCode.Object, result);

                // Use custom serialization for the externalizable object.
                IExternalizable externalizableValue = input.Serializer.CreateExternalizableInstance(classDefinition.ClassAlias);
                externalizableValue.ReadExternal(input);

                result.SetProperties(externalizableValue);
                return result;
            }
            else
            {
                // Important: Add the object to the cache before deserializing its properties!
                ASObject result = ASObject.CreateUninitializedInstance(classDefinition);
                AddObjectToCache(AMF3ObjectTypeCode.Object, result);

                // Read the member values.
                int memberCount = classDefinition.MemberNames.Count;
                IASValue[] memberValues;

                if (memberCount != 0)
                {
                    memberValues = new IASValue[memberCount];

                    for (int i = 0; i < memberCount; i++)
                        memberValues[i] = ReadObject();
                }
                else
                {
                    memberValues = EmptyArray<IASValue>.Instance;
                }

                // Read the dynamic property values.
                IDictionary<string, IASValue> dynamicProperties;

                if (classDefinition.Layout == ASClassLayout.Dynamic)
                {
                    string key = ReadStringData();
                    if (key.Length != 0)
                    {
                        dynamicProperties = new Dictionary<string, IASValue>();

                        for (; ; )
                        {
                            IASValue value = ReadObject();
                            dynamicProperties.Add(key, value);

                            key = ReadStringData();
                            if (key.Length == 0)
                                break;
                        }
                    }
                    else
                    {
                        dynamicProperties = EmptyDictionary<string, IASValue>.Instance;
                    }
                }
                else
                {
                    dynamicProperties = EmptyDictionary<string, IASValue>.Instance;
                }

                result.SetProperties(memberValues, dynamicProperties);
                return result;
            }
        }
 /// <summary>
 /// Adds the specified object to the reference cache.
 /// </summary>
 /// <param name="objectType">The type of object to cache</param>
 /// <param name="obj">The object to cache</param>
 private void AddObjectToCache(AMF3ObjectTypeCode objectType, IASValue obj)
 {
     objectReferenceCache.Add(new CacheItem(objectType, obj));
 }
Beispiel #21
0
 public CacheItem(AMF3ObjectTypeCode objectType, IASValue obj)
 {
     this.ObjectType = objectType;
     this.Object     = obj;
 }
 /// <summary>
 /// Writes AMF content.
 /// </summary>
 /// <param name="output">The output stream</param>
 /// <param name="content">The content to write</param>
 private static void WriteAMFContent(AMFDataOutput output, IASValue content)
 {
     output.BeginObjectStream();
     try
     {
         output.WriteObject(content);
     }
     finally
     {
         output.EndObjectStream();
     }
 }
Beispiel #23
0
 protected T ToNative <T>(IASValue asValue)
 {
     return((T)serializer.ToNative(asValue, typeof(T)));
 }
 /// <summary>
 /// Adds the specified object to the reference cache.
 /// </summary>
 /// <param name="obj">The object to cache</param>
 private void AddObjectToCache(IASValue obj)
 {
     objectReferenceCache.Add(obj);
 }
Beispiel #25
0
 /// <summary>
 /// Creates an AMF header.
 /// </summary>
 /// <param name="name">The name of the header</param>
 /// <param name="mustUnderstand">A flag that indicates whether the remote host must understand the header</param>
 /// <param name="content">The content of the header</param>
 public AMFHeader(string name, bool mustUnderstand, IASValue content)
 {
     this.name           = name;
     this.mustUnderstand = mustUnderstand;
     this.content        = content;
 }
Beispiel #26
0
 /// <summary>
 /// Creates an AMF body.
 /// </summary>
 /// <param name="requestTarget">The target of the message body</param>
 /// <param name="responseTarget">The response target of the message body, or the string "null" if none</param>
 /// <param name="content">The content of the body</param>
 public AMFBody(string requestTarget, string responseTarget, IASValue content)
 {
     this.requestTarget = requestTarget;
     this.responseTarget = responseTarget;
     this.content = content;
 }
Beispiel #27
0
        /// <inheritdoc />
        public void WriteObject(IASValue value)
        {
            if (!inObjectStream)
                throw new InvalidOperationException("WriteObject cannot be called except while writing an object stream.");

            objectWriter.WriteObject(value);
        }
Beispiel #28
0
 /// <summary>
 /// Creates an AMF body.
 /// </summary>
 /// <param name="requestTarget">The target of the message body</param>
 /// <param name="responseTarget">The response target of the message body, or the string "null" if none</param>
 /// <param name="content">The content of the body</param>
 public AMFBody(string requestTarget, string responseTarget, IASValue content)
 {
     this.requestTarget  = requestTarget;
     this.responseTarget = responseTarget;
     this.content        = content;
 }
            /// <summary>
            /// Sets a mapped property or field value or a dynamic property depending on the mapping.
            /// </summary>
            /// <param name="serializer"></param>
            /// <param name="instance"></param>
            /// <param name="dynamic"></param>
            /// <param name="propertyName"></param>
            /// <param name="value"></param>
            private void SetMappedMemberOrDynamicProperty(IActionScriptSerializer serializer, object instance, IDynamic dynamic, string propertyName, IASValue value)
            {
                // Set the mapped property, if there is one.
                ActionScriptPropertyMapping propertyMapping;
                if (propertyMappings.TryGetValue(propertyName, out propertyMapping))
                {
                    SetMappedPropertyOrField(serializer, instance, propertyMapping.NativePropertyOrField, value);

                    // If the property is dynamic then also set it as a dynamic property if possible.
                    if (dynamic != null && propertyMapping.IsDynamic)
                    {
                        SetDynamicProperty(dynamic, serializer, propertyName, value);
                    }
                }
                else if (dynamic != null)
                {
                    SetDynamicProperty(dynamic, serializer, propertyName, value);
                }
                else
                {
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                        "Unable to set value for property '{0}' during ActionScript object deserialization because no suitable mapping is defined and type '{1}' is not dynamic.",
                        propertyName, classMapping.NativeType.FullName));
                }
            }