Пример #1
0
        /// <summary>
        /// Write an integer.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="writer">
        /// The writer.
        /// </param>
        /// <param name="input">
        /// The input.
        /// </param>
        private static void WriteReference(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            int          index = Convert.ToInt32(input.GetAttribute(AmfxContent.ReferenceId));
            AmfReference proxy = context.References[index];

            switch (proxy.AmfxType)
            {
            case AmfxContent.Date:
                WriteTypeMarker(writer, Amf3TypeMarker.Date);
                break;

            case AmfxContent.Xml:
                WriteTypeMarker(writer, Amf3TypeMarker.Xml);
                break;

            case AmfxContent.Array:
                WriteTypeMarker(writer, Amf3TypeMarker.Array);
                break;

            case AmfxContent.ByteArray:
                WriteTypeMarker(writer, Amf3TypeMarker.ByteArray);
                break;

            case AmfxContent.Object:
                WriteTypeMarker(writer, Amf3TypeMarker.Object);
                break;

            default:
                throw new InvalidOperationException(
                          string.Format("AMFX type '{0}' cannot be send by reference.", proxy.AmfxType));
            }

            WriteReference(writer, index);
        }
Пример #2
0
        /// <summary>
        /// Read a string reference.
        /// </summary>
        /// <param name="context">
        /// AMF decoding context.
        /// </param>
        /// <param name="reader">
        /// AMF reader.
        /// </param>
        /// <param name="index">
        /// Reference index.
        /// </param>
        /// <param name="reference">
        /// Reference value.
        /// </param>
        /// <returns>
        /// Referenced string or <c>null</c> if value does not contain a reference.
        /// </returns>
        /// <exception cref="SerializationException">
        /// Invalid reference.
        /// </exception>
        private static string ReadStringReference(
            AmfContext context,
            AmfStreamReader reader,
            out int index,
            out int reference)
        {
            reference = reader.ReadAMF3IntegerData(); //ReadUint29(reader);

            // The first bit is a flag with value 0
            if ((reference & 0x1) == 0)
            {
                // The remaining 1 to 28 significant bits are used to encode a string reference table index
                index = reference >> 1;

                if (context.StringReferences.Count <= index)
                {
                    throw new SerializationException("Invalid reference index: " + index);
                }

                return(context.StringReferences[index]);
            }

            index = -1;
            return(null);
        }
Пример #3
0
        /// <summary>
        /// Read object properties map.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <remarks>
        /// Type declaration:
        ///     <c>object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker)</c>
        /// </remarks>
        /// <exception cref="SerializationException">
        /// </exception>
        /// <returns>
        /// The <see cref="IList"/>.
        /// </returns>
        private IList <string> ReadPropertiesMap(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            try
            {
                var    result   = new List <string>();
                string property = ReadString(reader); // Read first property's name

                // An empty property name indicates that object's declaration ends here
                while (property != string.Empty)
                {
                    result.Add(property);

                    this.ReadAmfValue(context, reader, output);
                    property = ReadString(reader);
                }

                // Last byte is always an "ObjectEnd" marker
                var marker = (Amf0TypeMarker)reader.ReadByte();

                // Something goes wrong
                if (marker != Amf0TypeMarker.ObjectEnd)
                {
                    throw new FormatException(Errors.Amf0Decoder_ReadPropertiesMap_UnexpectedObjectEnd);
                }

                return(result);
            }
            catch (Exception e)
            {
                throw new SerializationException(Errors.Amf0Decoder_ReadPropertiesMap_UnableToDeserialize, e);
            }
        }
Пример #4
0
        /// <summary>
        /// Write UTF-8 string.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="writer">
        /// The writer.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        private static void WriteUtf8(AmfContext context, AmfStreamWriter writer, string value)
        {
            if (value == null)
            {
                value = string.Empty;
            }

            // A special case
            if (value == string.Empty)
            {
                writer.Write((byte)0x01);
                return;
            }

            int index = context.StringReferences.IndexOf(value);

            if (index != -1)
            {
                WriteReference(writer, index);
                return;
            }

            context.StringReferences.Add(value);

            byte[] decoded = Encoding.UTF8.GetBytes(value);

            WriteUtf8(writer, decoded);
        }
Пример #5
0
        /// <summary>
        /// The encode.
        /// </summary>
        /// <param name="stream">
        /// The stream.
        /// </param>
        /// <param name="input">
        /// The input.
        /// </param>
        public override void Encode(Stream stream, XmlReader input)
        {
            var        writer  = new AmfStreamWriter(stream);
            AmfContext context = this.CreateDefaultContext();

            this.WriteAmfValue(context, input, writer);
        }
Пример #6
0
        /// <summary>
        /// The read amf value.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <exception cref="FormatException">
        /// </exception>
        protected override void ReadAmfValue(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            // Work in a legacy context
            if (context.AmfVersion == AmfVersion.Amf0)
            {
                base.ReadAmfValue(context, reader, output);
                return;
            }

            Amf3TypeMarker dataType;

            try
            {
                // Read a type marker byte
                dataType = (Amf3TypeMarker)reader.ReadByte();
            }
            catch (Exception e)
            {
#if DEBUG
                Debug.WriteLine(Errors.Amf3Decoder_ReadValue_InvalidMarker, reader.BaseStream.Position);
#endif

                throw new FormatException(
                          string.Format(Errors.Amf3Decoder_ReadValue_TypeMarkerNotFound, reader.BaseStream.Position),
                          e);
            }

            this.ReadValue(context, reader, dataType, output);

#if DEBUG
            Debug.WriteLine(Errors.Amf3Decoder_ReadValue_End, dataType, reader.BaseStream.Position);
#endif
        }
Пример #7
0
        /// <summary>
        /// Write an array.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="writer">
        /// The writer.
        /// </param>
        /// <param name="input">
        /// The input.
        /// </param>
        private void WriteArray(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            context.References.Add(new AmfReference {
                AmfxType = AmfxContent.Array
            });
            WriteTypeMarker(writer, Amf3TypeMarker.Array);

            int length = Convert.ToInt32(input.GetAttribute(AmfxContent.ArrayLength));

            // The first bit is a flag with value 1.
            // The remaining 1 to 28 significant bits
            // are used to encode the count of the dense
            // portion of the Array.
            int size = (length << 1) | 0x1;

            WriteUInt29(writer, size);

            WriteUtf8(context, writer, string.Empty); // No associative values

            if (length == 0)
            {
                return;
            }

            input.Read();

            for (int i = 0; i < length; i++)
            {
                this.WriteAmfValue(context, input, writer);
                input.Read();
            }
        }
Пример #8
0
        /// <summary>
        /// The decode.
        /// </summary>
        /// <param name="stream">
        /// The stream.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        public override void Decode(Stream stream, XmlWriter output)
        {
            var        reader  = new AmfStreamReader(stream);
            AmfContext context = this.CreateDefaultContext();

            this.ReadAmfValue(context, reader, output);
        }
Пример #9
0
        /// <summary>
        /// Read a traits reference.
        /// </summary>
        /// <param name="context">
        /// AMF decoding context.
        /// </param>
        /// <param name="reader">
        /// AMF reader.
        /// </param>
        /// <param name="index">
        /// Reference index.
        /// </param>
        /// <param name="reference">
        /// Reference value.
        /// </param>
        /// <returns>
        /// Referenced traits object or <c>null</c> if value does not contain a reference.
        /// </returns>
        /// <exception cref="SerializationException">
        /// Invalid reference.
        /// </exception>
        private static AmfTypeTraits ReadTraitsReference(
            AmfContext context,
            AmfStreamReader reader,
            out int index,
            out int reference)
        {
            reference = ReadUint29(reader);

            // The first bit is a flag with value 1. The second bit is a flag with value 0 to imply
            // that this objects traits are being sent by reference
            if ((reference & 0x3) == 1)
            {
                // x01 & x11 == x01
                // The remaining 1 to 27 significant bits are used to encode a trait reference index
                index = reference >> 2;

                if (context.TraitsReferences.Count <= index)
                {
                    throw new SerializationException("Invalid reference index: " + index);
                }

                return(context.TraitsReferences[index]);
            }

            index = -1;
            return(null);
        }
Пример #10
0
        /// <summary>
        /// Read an ECMA array.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <remarks>
        /// Type declaration:
        ///     <c>
        ///         associative-count = U32
        ///         ecma-array-type = associative-count *(object-property)
        ///     </c>
        /// </remarks>
        private void ReadEcmaArray(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            context.References.Track();

            reader.ReadUInt32(); // Read properties count
            this.ReadObject(context, reader, output);
        }
Пример #11
0
        /// <summary>
        /// Read a date.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <remarks>
        /// Type declaration:
        ///     <c>
        ///         U29D-value = U29 (The first (low) bit is a flag with value 1.
        ///         The remaining bits are not used).
        ///         date-time = DOUBLE (A 64-bit integer value transported as a double).
        ///         date-type = date-marker (U29O-ref | (U29D-value date-time))
        ///     </c>
        /// </remarks>
        private static void ReadDate(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            int index, reference;

            if (ReadReference(context, reader, out index, out reference))
            {
                if (output != null)
                {
                    WriteReference(index, output);
                }

                return;
            }

            context.References.Track();

            // Dates are represented as an Unix time stamp, but in milliseconds
            double milliseconds = reader.ReadDouble();
            string value        = milliseconds.ToString();

            if (output != null)
            {
                output.WriteStartElement(AmfxContent.Date);
                output.WriteValue(value);
                output.WriteEndElement();
            }
        }
Пример #12
0
        /// <summary>
        /// Read a byte array.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <remarks>
        /// Type declaration:
        ///     <c>
        ///         U29B-value = U29 (The first (low) bit is a flag with value 1.
        ///         The remaining 1 to 28 significant bits are used to encode the
        ///         byte-length of the ByteArray).
        ///         bytearray-type = bytearray-marker (U29O-ref | U29B-value *(U8))
        ///     </c>
        /// </remarks>
        private static void ReadByteArray(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            int index, reference;

            if (ReadReference(context, reader, out index, out reference))
            {
                if (output != null)
                {
                    WriteReference(index, output);
                }

                return;
            }

            context.References.Track();

            // Get array length
            int length = reference >> 1;

            byte[] data  = length == 0 ? new byte[] { } : reader.ReadBytes(length);
            string value = Convert.ToBase64String(data);

            if (output != null)
            {
                output.WriteStartElement(AmfxContent.ByteArray);
                output.WriteValue(value);
                output.WriteEndElement();
            }
        }
Пример #13
0
        /// <summary>
        /// Read an XML document.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <remarks>
        /// Type declaration:
        ///     <c>
        ///         U29X-value = U29 (The first (low) bit is a flag with value 1.
        ///         The remaining 1 to 28 significant bits are used to encode the byte-length
        ///         of the UTF-8 encoded representation of the XML or XMLDocument).
        ///         xml-doc-type = xml-doc-marker (U29O-ref | (U29X-value *(UTF8-char)))
        ///     </c>
        /// </remarks>
        private static void ReadXml(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            int index, reference;

            if (ReadReference(context, reader, out index, out reference))
            {
                if (output != null)
                {
                    WriteReference(index, output);
                }

                return;
            }

            context.References.Track();

            // Get XML string length
            int    length = reference >> 1;
            string value  = ReadUtf8(reader, length);

            if (output != null)
            {
                output.WriteStartElement(AmfxContent.Xml);
                output.WriteValue(value);
                output.WriteEndElement();
            }
        }
Пример #14
0
        /// <summary>
        /// Write a string.
        /// </summary>
        private static void WriteString(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            WriteTypeMarker(writer, Amf3TypeMarker.String);

            string value;

            if (input.IsEmptyElement)
            {
                if (input.AttributeCount > 0)
                {
                    var index = Convert.ToInt32(input.GetAttribute(AmfxContent.StringId), CultureInfo.InvariantCulture);
                    WriteReference(writer, index);
                    return;
                }

                value = string.Empty;
            }
            else
            {
                input.Read();
                value = input.Value;
                input.Read();
            }

            WriteUtf8(context, writer, value);
        }
Пример #15
0
        /// <summary>
        /// Read a string.
        /// </summary>
        /// <remarks>
        /// Type declaration:
        /// <c>U29S-ref = U29 (The first (low) bit is a flag with value 0. The remaining 1 to 28
        /// significant bits are used to encode a string reference table index (an integer)).
        /// U29S-value = U29 (The first (low) bit is a flag with value 1. The remaining 1 to 28 significant
        /// bits are used to encode the byte-length of the UTF-8 encoded representation of the string).
        /// UTF-8-empty = 0x01 (The UTF-8-vr empty string which is never sent by reference).
        /// UTF-8-vr = U29S-ref | (U29S-value *(UTF8-char))
        /// string-type = string-marker UTF-8-vr</c>
        /// </remarks>
        private static string ReadString(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            int    index, reference;
            string cache;

            if ((cache = ReadStringReference(context, reader, out index, out reference)) != null)
            {
                if (output != null)
                {
                    output.WriteStartElement(AmfxContent.String);
                    output.WriteAttributeString(AmfxContent.StringId, index.ToString());
                    output.WriteEndElement();
                }

                return(cache);
            }

            //Get string length
            var length = (reference >> 1);
            var value  = ReadUtf8(reader, length);

            if (value != string.Empty)
            {
                context.StringReferences.Add(value);
            }

            if (output != null)
            {
                output.WriteStartElement(AmfxContent.String);
                output.WriteValue(value);
                output.WriteEndElement();
            }

            return(value);
        }
Пример #16
0
        /// <summary>
        /// Write an array.
        /// </summary>
        private void WriteArray(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            context.References.Add(new AmfReference {
                AmfxType = AmfxContent.Array
            });

            var length = Convert.ToUInt32(input.GetAttribute(AmfxContent.ArrayLength));

            writer.Write(length);

            if (length == 0)
            {
                return;
            }

            input.MoveToContent();

            while (input.Read())
            {
                if (input.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                for (var i = 0; i < length; i++)
                {
                    var itemreader = input.ReadSubtree();
                    itemreader.MoveToContent();
                    WriteAmfValue(context, itemreader, writer);
                }
            }
        }
Пример #17
0
        /// <summary>
        /// The read amf value.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// </exception>
        /// <exception cref="FormatException">
        /// </exception>
        protected override void ReadAmfValue(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            if (context.AmfVersion != AmfVersion.Amf0)
            {
                throw new InvalidOperationException(
                          string.Format(Errors.Amf0Decoder_ReadAmfValue_AmfVersionNotSupported, context.AmfVersion));
            }

            Amf0TypeMarker dataType;

            try
            {
                // Read a type marker byte
                dataType = (Amf0TypeMarker)reader.ReadByte();
            }
            catch (Exception e)
            {
                throw new FormatException(Errors.Amf0Decoder_ReadAmfValue_TypeMarkerMissing, e);
            }

            // Special case
            if (dataType == Amf0TypeMarker.AvmPlusObject)
            {
                var newContext = new AmfContext(AmfVersion.Amf3);
                this.ReadAmfValue(newContext, reader, output);
                return;
            }

            this.ReadValue(context, reader, dataType, output);
        }
Пример #18
0
        /// <summary>
        /// Read an object reference.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <remarks>
        /// Type declaration:
        ///     <c>reference-type = reference-marker U16</c>
        /// </remarks>
        private static void ReadReference(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            ushort index = reader.ReadUInt16();

            if (context.References.Count <= index)
            {
                throw new SerializationException(string.Format(Errors.Amf0Decoder_ReadReference_BadIndex, index));
            }

            WriteReference(index, output);
        }
Пример #19
0
        /// <summary>
        /// Write an XML.
        /// </summary>
        private static void WriteXml(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            context.References.Add(new AmfReference {
                AmfxType = AmfxContent.Xml
            });
            WriteTypeMarker(writer, Amf3TypeMarker.Xml);

            var encoded = input.ReadString();
            var decoded = Encoding.UTF8.GetBytes(encoded);

            WriteUtf8(writer, decoded);
        }
Пример #20
0
        /// <summary>
        /// Write a date.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="writer">
        /// The writer.
        /// </param>
        /// <param name="input">
        /// The input.
        /// </param>
        private static void WriteDate(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            context.References.Add(new AmfReference {
                AmfxType = AmfxContent.Date
            });
            WriteTypeMarker(writer, Amf3TypeMarker.Date);

            double milliseconds = Convert.ToDouble(input.ReadString());

            // The first bit is a flag with value 1.
            // The remaining bits are not used.
            WriteUInt29(writer, 0 | 0x1);

            writer.Write(milliseconds);
        }
Пример #21
0
        /// <summary>
        /// Write a reference value.
        /// </summary>
        private static void WriteReference(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            var index = Convert.ToInt32(input.GetAttribute(AmfxContent.ReferenceId));
            var proxy = context.References[index];

            switch (proxy.AmfxType)
            {
            case AmfxContent.Array:
            case AmfxContent.Object:
                WriteTypeMarker(writer, Amf0TypeMarker.Reference);
                writer.Write((ushort)index);
                break;

            default:
                throw new InvalidOperationException(string.Format("AMFX type '{0}' cannot be send by reference.", proxy.AmfxType));
            }
        }
Пример #22
0
        /// <summary>
        /// Write a byte array.
        /// </summary>
        private static void WriteByteArray(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            context.References.Add(new AmfReference {
                AmfxType = AmfxContent.ByteArray
            });
            WriteTypeMarker(writer, Amf3TypeMarker.ByteArray);

            var encoded = input.ReadString();
            var bytes   = Convert.FromBase64String(encoded);

            //The first bit is a flag with value 1.
            //The remaining 1 to 28 significant bits are used
            //to encode the byte-length of the data
            var flag = (bytes.Length << 1) | 0x1;

            WriteUInt29(writer, flag);

            writer.Write(bytes);
        }
Пример #23
0
        /// <summary>
        /// Read an object reference.
        /// </summary>
        /// <param name="context">
        /// AMF decoding context.
        /// </param>
        /// <param name="reader">
        /// AMF reader.
        /// </param>
        /// <param name="index">
        /// Reference index.
        /// </param>
        /// <param name="reference">
        /// Reference value.
        /// </param>
        /// <returns>
        /// Referenced object or <c>null</c> if value does not contain a reference.
        /// </returns>
        /// <exception cref="SerializationException">
        /// Invalid reference.
        /// </exception>
        private static bool ReadReference(AmfContext context, AmfStreamReader reader, out int index, out int reference)
        {
            reference = ReadUint29(reader);

            // The first bit is a flag with value 0 to imply that this is not an instance but a reference
            if ((reference & 0x1) == 0)
            {
                // The remaining 1 to 28 significant bits are used to encode an object reference index
                index = reference >> 1;

                if (context.References.Count <= index)
                {
                    throw new SerializationException("Invalid reference index: " + index);
                }

                return(true);
            }

            index = -1;
            return(false);
        }
Пример #24
0
        /// <summary>
        /// The read packet body.
        /// </summary>
        /// <param name="stream">
        /// The stream.
        /// </param>
        /// <returns>
        /// The <see cref="AmfMessageDescriptor"/>.
        /// </returns>
        /// <exception cref="FormatException">
        /// </exception>
        public override sealed AmfMessageDescriptor ReadPacketBody(Stream stream)
        {
            var        reader  = new AmfStreamReader(stream);
            AmfContext context = this.CreateDefaultContext();

            try
            {
                var descriptor = new AmfMessageDescriptor {
                    Target = ReadString(reader), Response = ReadString(reader)
                };

                reader.ReadInt32(); // Message length

                context.ResetReferences();
                return(descriptor);
            }
            catch (Exception e)
            {
                throw new FormatException(Errors.Amf0Deserializer_ReadPacketMessages_InvalidFormat, e);
            }
        }
Пример #25
0
        /// <summary>
        /// Read a strict array.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <remarks>
        /// Type declaration:
        ///     <c>
        ///         array-count = U32
        ///         strict-array-type = array-count *(value-type)
        ///     </c>
        /// </remarks>
        private void ReadStrictArray(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            context.References.Track();

            uint length = reader.ReadUInt32();

            if (output != null)
            {
                output.WriteStartElement(AmfxContent.Array);
                output.WriteAttributeString(AmfxContent.ArrayLength, length.ToString());
            }

            for (int i = 0; i < length; i++)
            {
                this.ReadAmfValue(context, reader, output);
            }

            if (output != null)
            {
                output.WriteEndElement();
            }
        }
Пример #26
0
        /// <summary>
        /// The read packet header.
        /// </summary>
        /// <param name="stream">
        /// The stream.
        /// </param>
        /// <returns>
        /// The <see cref="AmfHeaderDescriptor"/>.
        /// </returns>
        /// <exception cref="FormatException">
        /// </exception>
        public override sealed AmfHeaderDescriptor ReadPacketHeader(Stream stream)
        {
            var        reader  = new AmfStreamReader(stream);
            AmfContext context = this.CreateDefaultContext();

            try
            {
                var descriptor = new AmfHeaderDescriptor
                {
                    Name           = ReadString(reader),
                    MustUnderstand = reader.ReadBoolean()
                };

                reader.ReadInt32(); // Header length

                context.ResetReferences();
                return(descriptor);
            }
            catch (Exception e)
            {
                throw new FormatException(Errors.Amf0Deserializer_ReadPacketHeaders_InvalidFormat, e);
            }
        }
Пример #27
0
        /// <summary>
        /// Read an object.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        private void ReadObject(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            int reference = reader.PeekChar();
            int index;

            if ((reference & 0x1) == 0 && ReadReference(context, reader, out index, out reference))
            {
                if (output != null)
                {
                    WriteReference(index, output);
                }

                return;
            }

            context.References.Track();

            int           traitsindex, traitsreference;
            AmfTypeTraits traits;

            if ((traits = ReadTraitsReference(context, reader, out traitsindex, out traitsreference)) == null)
            {
                bool   isExternalizable = (traitsreference & 0x4) == 4;
                bool   isDynamic        = (traitsreference & 0x8) == 8;
                string typeName         = ReadString(context, reader);
                int    count            = traitsreference >> 4;
                var    classMembers     = new string[count];

                for (int i = 0; i < count; i++)
                {
                    classMembers[i] = ReadString(context, reader);
                }

                traits = new AmfTypeTraits
                {
                    IsDynamic        = isDynamic,
                    IsExternalizable = isExternalizable,
                    TypeName         = typeName,

                    // No property names are included for types
                    // that are externizable or dynamic
                    ClassMembers = isDynamic || isExternalizable ? new string[0] : classMembers
                };

                context.TraitsReferences.Add(traits);
            }

#if DEBUG
            Debug.WriteLine(string.Format(Errors.Amf3Decoder_ReadObject_Debug_Name, traits.TypeName));

            if (traits.IsDynamic)
            {
                Debug.WriteLine(Errors.Amf3Decoder_ReadObject_Debug_Dynamic);
            }
            else if (traits.IsExternalizable)
            {
                Debug.WriteLine(Errors.Amf3Decoder_ReadObject_Debug_Externizable);
            }
            else
            {
                Debug.WriteLine(Errors.Amf3Decoder_ReadObject_Debug_Members, traits.ClassMembers.Length);
            }
#endif

            using (var ms = new MemoryStream())
            {
                var members = new List <string>();

                var buffer = new XmlTextWriter(ms, Encoding.UTF8);
                buffer.WriteStartElement("buffer");
                buffer.WriteAttributeString("xmlns", AmfxContent.Namespace);

#if DEBUG
                int memberPosition = 0;
#endif

                // Read object's properties
                foreach (string classMember in traits.ClassMembers)
                {
#if DEBUG
                    Debug.WriteLine(Errors.Amf3Decoder_ReadObject_Debug_ReadingField, memberPosition, classMember);
                    memberPosition++;
#endif

                    this.ReadAmfValue(context, reader, buffer);
                    members.Add(classMember);
                }

                // Read dynamic properties too
                if (traits.IsDynamic)
                {
#if DEBUG
                    Debug.WriteLine(Errors.Amf3Decoder_ReadObject_Debug_ReadingDynamic);
#endif

                    string key = ReadString(context, reader);

                    while (key != string.Empty)
                    {
#if DEBUG
                        Debug.WriteLine(string.Format(Errors.Amf3Decoder_ReadObject_Debug_ReadingDynamicField, key));
#endif

                        this.ReadAmfValue(context, reader, buffer);
                        members.Add(key);

                        key = ReadString(context, reader);
                    }

#if DEBUG
                    Debug.WriteLine(Errors.Amf3Decoder_ReadObject_Debug_DynamicEnd);
#endif
                }

                buffer.WriteEndElement();
                buffer.Flush();



#if DEBUG
                Debug.WriteLine(Errors.Amf3Decoder_ReadObject_Debug_End);
#endif

                #region Writing member values

                if (output != null)
                {
                    output.WriteStartElement(AmfxContent.Object);

                    if (traits.TypeName != AmfTypeTraits.BaseTypeAlias)
                    {
                        output.WriteAttributeString(AmfxContent.ObjectType, traits.TypeName);
                    }

                    output.WriteStartElement(AmfxContent.Traits);

                    // Regular traits object
                    // Always write traits for dynamic objects
                    if (traitsindex == -1 || traits.IsDynamic)
                    {
                        if (traits.IsExternalizable)
                        {
                            output.WriteAttributeString(AmfxContent.TraitsExternizable, AmfxContent.True);
                        }
                        else
                        {
                            // Write object members
                            foreach (string classMember in members)
                            {
                                output.WriteStartElement(AmfxContent.String);
                                output.WriteValue(classMember);
                                output.WriteEndElement();
                            }
                        }
                    }

                    // Traits object reference
                    else
                    {
                        output.WriteAttributeString(AmfxContent.TraitsId, traitsindex.ToString());
                    }

                    output.WriteEndElement(); // End of traits

                    // Write object members
                    if (members.Count > 0)
                    {
                        ms.Position = 0;
                        var bufferreader = new XmlTextReader(ms);
                        bufferreader.Read();
                        bufferreader.ReadStartElement();

                        while (bufferreader.Depth >= 1)
                        {
                            output.WriteNode(bufferreader, false);
                        }
                    }

                    output.WriteEndElement(); // End of object
                }

                #endregion
            }
        }
Пример #28
0
        /// <summary>
        /// Read an array.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <remarks>
        /// Type declaration:
        ///     <c>
        ///         U29A-value = U29 (The first (low) bit is a flag with value 1.
        ///         The remaining 1 to 28 significant bits are used to encode
        ///         the count of the dense portion of the Array).
        ///         assoc-value = UTF-8-vr value-type
        ///         array-type = array-marker (U29O-ref |
        ///         (U29A-value (UTF-8-empty | *(assoc-value) UTF-8-empty) *(value-type)))
        ///     </c>
        /// </remarks>
        private void ReadArray(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            int index, reference;

            if (ReadReference(context, reader, out index, out reference))
            {
                if (output != null)
                {
                    WriteReference(index, output);
                }

                return;
            }

            context.References.Track();

            int    length = reference >> 1;
            string key    = ReadString(context, reader);

            if (output != null)
            {
                output.WriteStartElement(AmfxContent.Array);
                output.WriteAttributeString(AmfxContent.ArrayLength, length.ToString());
            }

            // ECMA array
            if (key != string.Empty)
            {
                if (output != null)
                {
                    output.WriteAttributeString(AmfxContent.ArrayEcma, AmfxContent.True);
                }

                // Read associative values
                do
                {
                    if (output != null)
                    {
                        output.WriteStartElement(AmfxContent.ArrayItem);
                        output.WriteAttributeString(AmfxContent.ArrayKey, key);
                    }

                    this.ReadAmfValue(context, reader, output);
                    key = ReadString(context, reader);

                    if (output != null)
                    {
                        output.WriteEndElement();
                    }
                }while (key != string.Empty);

                // Read array values
                for (int i = 0; i < length; i++)
                {
                    this.ReadAmfValue(context, reader, output);
                }
            }

            // Regular array
            else
            {
                // Read array values
                for (int i = 0; i < length; i++)
                {
                    this.ReadAmfValue(context, reader, output);
                }
            }

            if (output != null)
            {
                output.WriteEndElement();
            }
        }
Пример #29
0
        /// <summary>
        /// Read a value of a given type from current reader's position.
        /// </summary>
        /// <remarks>
        /// Current reader position must be just after a value type marker of a type to read.
        /// </remarks>
        /// <param name="context">
        /// AMF decoding context.
        /// </param>
        /// <param name="reader">
        /// AMF reader.
        /// </param>
        /// <param name="type">
        /// Type of the value to read.
        /// </param>
        /// <param name="output">
        /// AMFX output.
        /// </param>
        /// <exception cref="NotSupportedException">
        /// AMF type is not supported.
        /// </exception>
        /// <exception cref="FormatException">
        /// Unknown data format.
        /// </exception>
        /// <exception cref="SerializationException">
        /// Error during deserialization.
        /// </exception>
        private void ReadValue(AmfContext context, AmfStreamReader reader, Amf3TypeMarker type, XmlWriter output = null)
        {
#if DEBUG
            Debug.WriteLine(Errors.Amf3Decoder_ReadValue_Debug, type, reader.BaseStream.Position);
#endif

            switch (type)
            {
            case Amf3TypeMarker.Null:
            case Amf3TypeMarker.Undefined:
                WriteEmptyElement(type.ToAmfxName(), output);
                break;

            case Amf3TypeMarker.False:
                WriteEmptyElement(type.ToAmfxName(), output);
                break;

            case Amf3TypeMarker.True:
                WriteEmptyElement(type.ToAmfxName(), output);
                break;

            case Amf3TypeMarker.Integer:
                ReadInteger(reader, output);
                break;

            case Amf3TypeMarker.Double:
                ReadDouble(reader, output);
                break;

            case Amf3TypeMarker.String:
                ReadString(context, reader, output);
                break;

            case Amf3TypeMarker.Date:
                ReadDate(context, reader, output);
                break;

            case Amf3TypeMarker.ByteArray:
                ReadByteArray(context, reader, output);
                break;

            case Amf3TypeMarker.Xml:
            case Amf3TypeMarker.XmlDocument:
                ReadXml(context, reader, output);
                break;

            case Amf3TypeMarker.Array:
                this.ReadArray(context, reader, output);
                break;

            case Amf3TypeMarker.Object:
                this.ReadObject(context, reader, output);
                break;

            default:
                throw new NotSupportedException("Type '" + type + "' is not supported.");
            }

            if (output != null)
            {
                output.Flush();
            }
        }
Пример #30
0
        /// <summary>
        /// Read a string.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <remarks>
        /// Type declaration:
        ///     <c>
        ///         U29S-ref = U29 (The first (low) bit is a flag with value 0. The remaining 1 to 28
        ///         significant bits are used to encode a string reference table index (an integer)).
        ///         U29S-value = U29 (The first (low) bit is a flag with value 1. The remaining 1 to 28 significant
        ///         bits are used to encode the byte-length of the UTF-8 encoded representation of the string).
        ///         UTF-8-empty = 0x01 (The UTF-8-vr empty string which is never sent by reference).
        ///         UTF-8-vr = U29S-ref | (U29S-value *(UTF8-char))
        ///         string-type = string-marker UTF-8-vr
        ///     </c>
        /// </remarks>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private static string ReadString(AmfContext context, AmfStreamReader reader, XmlWriter output = null)
        {
            int    index, reference;
            string cache;

            if ((cache = ReadStringReference(context, reader, out index, out reference)) != null)
            {
                if (output != null)
                {
                    output.WriteStartElement(AmfxContent.String);
                    output.WriteValue(cache);
//                    output.WriteStartElement(AmfxContent.String);
//                    output.WriteAttributeString(AmfxContent.StringId, index.ToString());
                    output.WriteEndElement();
                }

                return(cache);
            }

            // Get string length
            int    length2 = reference >> 1;
            string value   = ReadUtf8(reader, length2);

            if (value != string.Empty)
            {
                context.StringReferences.Add(value);
            }

            if (output != null)
            {
                output.WriteStartElement(AmfxContent.String);
                output.WriteValue(value);
                output.WriteEndElement();
            }

            return(value);

            int  handle = reader.ReadAMF3IntegerData();
            bool inline = (handle & 1) != 0;

            handle = handle >> 1;
            if (inline)
            {
                int length = handle;
                if (length == 0)
                {
                    return(string.Empty);
                }

                string str = reader.ReadUTF(length);
                context.StringReferences.Add(str);
                if (output != null)
                {
                    output.WriteStartElement(AmfxContent.String);
                    output.WriteValue(str);
                    output.WriteEndElement();
                }

                return(str);
            }

            if (output != null)
            {
                output.WriteStartElement(AmfxContent.String);
                output.WriteAttributeString(AmfxContent.StringId, handle.ToString());
                output.WriteEndElement();
            }

            return(context.StringReferences[handle]);
        }