private void WriteArray(IList data) { uint length = 0; if (data == null) { Write(length); return; } length = Convert.ToUInt32(data.Count); Write(length); for (int i = 0; i < data.Count; i++) { AMFData arrayData = data[i] as AMFData; if (arrayData != null) { WriteAMFData(arrayData.DataType, arrayData.Data); } else { if (data[i] == null) { Write((byte)AMFDataType.Null); } else { ProcessUnknownObject(data[i]); } } } }
private void WriteActionScriptObject(ActionScriptObject aso) { if (aso.TypeName != string.Empty && aso.TypeName != null) { Write((byte)AMFDataType.TypedObject); WriteUTF(aso.TypeName); } else { Write((byte)AMFDataType.Object); } foreach (KeyValuePair <string, object> kvp in aso.Properties) { WriteUTF(kvp.Key); AMFData data = kvp.Value as AMFData; if (data == null) { Write((byte)AMFDataType.Null); } else { //this will allow us to have nested objects as properties //on our AMF objects if (data.DataType == AMFDataType.AMFEnabledObject) { if (data.Data != null) { ProcessUnknownObject(data.Data); } else { Write((byte)AMFDataType.Null); } } else { WriteAMFData(data.DataType, data.Data); } } } //write out the end record Write(Convert.ToUInt16(0)); Write((byte)AMFDataType.EndOfObject); }
private static object GetArrayElementValue(AMFData sourceData, Type memberType) { switch (sourceData.DataType) { case AMFDataType.AMFEnabledObject: case AMFDataType.Object: case AMFDataType.TypedObject: case AMFDataType.Reference: return(Deserialize(sourceData.Data as ActionScriptObject, memberType)); case AMFDataType.Number: switch (memberType.Name) { case "Int32": return(Convert.ToInt32(sourceData.Data)); case "Int16": return(Convert.ToInt16(sourceData.Data)); case "Int64": return(Convert.ToInt64(sourceData.Data)); break; case "Decimal": return(Convert.ToDecimal(sourceData.Data)); } break; case AMFDataType.Boolean: case AMFDataType.Date: case AMFDataType.LongString: case AMFDataType.String: case AMFDataType.Xml: return(sourceData.Data); case AMFDataType.Guid: return(new Guid(sourceData.Data.ToString())); } return(null); }
public void WriteResponse() { //output the result to Flex Write(_envelope.Version); Write((byte)_envelope.ClientType); Write(Convert.ToUInt16(_envelope.Headers.Count)); foreach (AMFHeader header in _envelope.Headers) { WriteUTF(header.Name); Write(header.MustUnderstand); Write(-1); WriteAMFData(header.Value.DataType, header.Value.Data); } Write(Convert.ToUInt16(_envelope.Bodies.Count)); foreach (AMFBody body in _envelope.Bodies) { WriteUTF(body.ResponseId + "/onResult"); WriteUTF("null"); Write(-1); if (body.ReturnValue == null) { Write((byte)AMFDataType.Null); } else { //is this AMFDATA if (body.ReturnValue is AMFData) { AMFData amfData = body.ReturnValue as AMFData; WriteAMFData(amfData.DataType, amfData.Data); } else { ProcessUnknownObject(body.ReturnValue); } } } }
private void WriteMixedArray(Dictionary <string, object> properties) { //always let them know we don't have any numeric indexes //this way it is all keyed as strings Write(Convert.ToUInt32(0)); if (properties == null) { Write(Convert.ToUInt16(0)); Write((byte)AMFDataType.EndOfObject); return; } foreach (KeyValuePair <string, object> kvp in properties) { WriteUTF(kvp.Key); AMFData data = kvp.Value as AMFData; if (data == null) { if (kvp.Value == null) { Write((byte)AMFDataType.Null); } else { ProcessUnknownObject(kvp.Value); } } else { WriteAMFData(data.DataType, data.Data); } } Write(Convert.ToUInt16(0)); Write((byte)AMFDataType.EndOfObject); }
public void AddProperty(string name, AMFDataType type, object value) { AMFData data = new AMFData(type, value); Properties[name] = data; }
private static void DeserializeFields(ActionScriptObject aso, Type type, object instance) { //get the custom attributes of the object FieldInfo[] fields = type.GetFields(); if (fields != null) { foreach (FieldInfo field in fields) { object[] attributes = field.GetCustomAttributes(typeof(AMFProperty), true); if (attributes != null) { foreach (AMFProperty propertyAttribute in attributes) { string key = propertyAttribute.Name; AMFDataType propertyType = propertyAttribute.ActionScriptDataType; //if we don't have let default value take over if (!aso.Properties.ContainsKey(key)) { continue; } AMFData data = aso.Properties[key] as AMFData; if (data.Data == null) { continue; } switch (propertyType) { case AMFDataType.AMFEnabledObject: if (field.FieldType.Name == "Object") { field.SetValue(instance, data.Data); } else { field.SetValue(instance, Deserialize(data.Data as ActionScriptObject, field.FieldType)); } break; case AMFDataType.Array: ArrayList al = data.Data as ArrayList; ArrayList alValues = new ArrayList(); if (al != null && al.Count > 0) { object[] arrayItemAttributes = field.GetCustomAttributes(typeof(AMFArrayItem), true); Dictionary <string, Type> itemMap = new Dictionary <string, Type>(); if (arrayItemAttributes != null) { foreach (AMFArrayItem arrayItemAttribute in arrayItemAttributes) { itemMap.Add(arrayItemAttribute.TypeName, arrayItemAttribute.TargetType); } } foreach (AMFData alData in al) { object dataValue = null; if (alData.Data is ActionScriptObject) { ActionScriptObject arrayItemASO = alData.Data as ActionScriptObject; if (itemMap.ContainsKey(arrayItemASO.TypeName)) { dataValue = GetArrayElementValue(alData, itemMap[arrayItemASO.TypeName]); } else { dataValue = GetArrayElementValue(alData, field.FieldType.GetElementType()); } } else { dataValue = GetArrayElementValue(alData, field.FieldType.GetElementType()); } if (dataValue != null) { alValues.Add(dataValue); } } field.SetValue(instance, alValues.ToArray(field.FieldType.GetElementType())); } break; case AMFDataType.Boolean: case AMFDataType.LongString: case AMFDataType.String: case AMFDataType.UTCDate: case AMFDataType.Date: field.SetValue(instance, data.Data); break; case AMFDataType.Guid: field.SetValue(instance, new Guid(data.Data.ToString())); break; case AMFDataType.Number: switch (field.FieldType.Name) { case "Int32": field.SetValue(instance, Convert.ToInt32(data.Data)); break; case "Int16": field.SetValue(instance, Convert.ToInt16(data.Data)); break; case "Int64": field.SetValue(instance, Convert.ToInt64(data.Data)); break; case "Decimal": field.SetValue(instance, Convert.ToDecimal(data.Data)); break; } break; } } } } } }
private AMFData ParseAMFDataForType(AMFDataType dataType) { AMFData data = new AMFData(); data.DataType = dataType; switch (dataType) { case AMFDataType.AMF3: throw new Exception("Flex AMF3 is not supported"); case AMFDataType.Array: data.Data = ReadArrayList(); if (data.Data != null) { _references[_references.Count] = data; } break; case AMFDataType.Boolean: data.Data = ReadBoolean(); break; case AMFDataType.Date: double millisecondsFromGroundZero = ReadDouble(); DateTime adjusted = _groundZero.AddMilliseconds(millisecondsFromGroundZero); data = new AMFDateData(); data.DataType = dataType; data.Data = adjusted; //read the timezone //comes in as minutes off of gmt int tzOffset = Convert.ToInt32(ReadUInt16()); if (tzOffset > 720) //per AMF anything over 12 hours is subtracted from 2^16 { tzOffset = (65536 - tzOffset) * -1; } int totalOffset = tzOffset * 60000 * -1; //gives us total milliseconds offset //use the offset to add milliseconds to the date //adjusted.AddMilliseconds(totalOffset) ((AMFDateData)data).TimezoneOffset = totalOffset; if (adjusted == DateTime.MinValue) { ((AMFDateData)data).ClientDate = DateTime.MinValue; } else { ((AMFDateData)data).ClientDate = adjusted.AddMilliseconds(totalOffset); } //now we need to set the actual data to be represented //as a date for the server timezone data.Data = DateTime.Parse(data.Data.ToString(), null, System.Globalization.DateTimeStyles.AssumeUniversal); break; case AMFDataType.LongString: data.Data = ReadLongUTF(); break; case AMFDataType.MixedArray: data.Data = ReadMixedArray(); if (data.Data != null) { _references[_references.Count] = data; } break; case AMFDataType.Number: data.Data = ReadDouble(); break; case AMFDataType.Object: data.Data = ReadActionScriptObject(false); if (data.Data != null) { _references[_references.Count] = data; } break; case AMFDataType.Reference: int referenceCounter = Convert.ToInt32(ReadUInt16()) - 1; if (!_references.ContainsKey(referenceCounter)) { return(null); } else { data = _references[referenceCounter]; } break; case AMFDataType.String: data.Data = ReadUTF(); break; case AMFDataType.TypedObject: data.Data = ReadActionScriptObject(true); if (data.Data != null) { _references[_references.Count] = data; } break; case AMFDataType.Xml: string xml = ReadLongUTF(); XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); data.Data = doc; break; } return(data); }
private void ProcessUnknownObject(object data) { //if no data, then get out if (data == null) { return; } //could be anything, but we are going to send it back //as a typed object Type t = data.GetType(); object[] attributes = t.GetCustomAttributes(true); bool ok = false; ActionScriptObject aso = new ActionScriptObject(); if (attributes != null) { foreach (Attribute attribute in attributes) { if (attribute is AMFEnabled) { ok = true; aso.TypeName = ((AMFEnabled)attribute).ActionScriptTypeName; break; } } if (ok) { //get the properties and fields for this type and then we can get those attributes //that we need to export FieldInfo[] fields = t.GetFields(); if (fields != null) { foreach (FieldInfo field in fields) { attributes = field.GetCustomAttributes(typeof(AMFProperty), true); if (attributes != null) { foreach (AMFProperty propertyAttribute in attributes) { string key = propertyAttribute.Name; AMFDataType propertyType = propertyAttribute.ActionScriptDataType; //get the value object propertyValue = field.GetValue(data); //save it AMFData amfData = new AMFData(); amfData.DataType = propertyType; amfData.Data = propertyValue; aso.Properties[key] = amfData; } } } } //do the same thing for the props PropertyInfo[] properties = t.GetProperties(); if (properties != null) { foreach (PropertyInfo property in properties) { attributes = property.GetCustomAttributes(typeof(AMFProperty), true); if (attributes != null) { foreach (AMFProperty propertyAttribute in attributes) { string key = propertyAttribute.Name; AMFDataType propertyType = propertyAttribute.ActionScriptDataType; //get the value object propertyValue = property.GetValue(data, null); //save it AMFData amfData = new AMFData(); amfData.DataType = propertyType; amfData.Data = propertyValue; aso.Properties[key] = amfData; } } } } } } if (!ok) { if (data is ActionScriptObject) { WriteActionScriptObject(data as ActionScriptObject); } else if (data is int) { Write((byte)AMFDataType.Number); Write(Convert.ToDouble(data)); } else { throw new Exception("Type returned for Flex was not marked as AMFEnabled: " + t.ToString()); } } else { WriteActionScriptObject(aso); } }