예제 #1
0
        /// <summary>
        /// Write a double.
        /// </summary>
        /// <param name="writer">
        /// The writer.
        /// </param>
        /// <param name="input">
        /// The input.
        /// </param>
        private static void WriteDouble(AmfStreamWriter writer, XmlReader input)
        {
            double value = Convert.ToDouble(input.ReadString());

            WriteTypeMarker(writer, Amf3TypeMarker.Double);
            writer.Write(value);
        }
예제 #2
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);
        }
예제 #3
0
        /// <summary>
        /// Write an XML.
        /// </summary>
        /// <param name="writer">
        /// The writer.
        /// </param>
        /// <param name="input">
        /// The input.
        /// </param>
        private static void WriteXml(AmfStreamWriter writer, XmlReader input)
        {
            string value = input.ReadString();

            byte[] data = Encoding.UTF8.GetBytes(value);
            WriteXml(writer, data);
        }
예제 #4
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);
        }
예제 #5
0
        /// <summary>
        /// Write an XML.
        /// </summary>
        private static void WriteXml(AmfStreamWriter writer, XmlReader input)
        {
            var value = input.ReadContentAsString();
            var data  = Encoding.UTF8.GetBytes(value);

            WriteXml(writer, data);
        }
예제 #6
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);
                }
            }
        }
예제 #7
0
        public override void Encode(Stream stream, XmlReader input)
        {
            var writer  = new AmfStreamWriter(stream);
            var context = CreateDefaultContext();

            WriteAmfValue(context, input, writer);
        }
예제 #8
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);
        }
예제 #9
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();
            }
        }
예제 #10
0
        /// <summary>
        /// Write a number.
        /// </summary>
        private static void WriteNumber(AmfStreamWriter writer, XmlReader input)
        {
            WriteTypeMarker(writer, Amf0TypeMarker.Number);

            var value = Convert.ToDouble(input.ReadString());

            writer.Write(value);
        }
예제 #11
0
        /// <summary>
        /// Write a string.
        /// </summary>
        /// <param name="writer">
        /// The writer.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        private static void WriteString(AmfStreamWriter writer, string value)
        {
            byte[] data = Encoding.UTF8.GetBytes(value);

            WriteTypeMarker(writer, data.Length < ShortStringLimit ? Amf0TypeMarker.String : Amf0TypeMarker.LongString);

            WriteUtf8(writer, data);
        }
예제 #12
0
        public override void WritePacketHeader(Stream stream, AmfHeaderDescriptor descriptor)
        {
            var writer = new AmfStreamWriter(stream);

            WriteUtf8(writer, descriptor.Name);
            writer.Write((byte)(descriptor.MustUnderstand ? 1 : 0));
            writer.Write(-1);
        }
예제 #13
0
        public override void WritePacketBody(Stream stream, AmfMessageDescriptor descriptor)
        {
            var writer = new AmfStreamWriter(stream);

            WriteUtf8(writer, descriptor.Target);
            WriteUtf8(writer, descriptor.Response);
            writer.Write(-1);
        }
예제 #14
0
        public override void WritePacketHeader(Stream stream, AmfHeaderDescriptor descriptor)
        {
            var writer = new AmfStreamWriter(stream);

            WriteUtf8(writer, descriptor.Name);
            writer.Write((byte)(descriptor.MustUnderstand ? 1 : 0));
            writer.Write(-1);
        }
예제 #15
0
        public override void WritePacketBody(Stream stream, AmfMessageDescriptor descriptor)
        {
            var writer = new AmfStreamWriter(stream);

            WriteUtf8(writer, descriptor.Target);
            WriteUtf8(writer, descriptor.Response);
            writer.Write(-1);
        }
예제 #16
0
        /// <summary>
        /// Write a number.
        /// </summary>
        private static void WriteNumber(AmfStreamWriter writer, XmlReader input)
        {
            WriteTypeMarker(writer, Amf0TypeMarker.Number);

            var value = input.ReadContentAsDouble();

            writer.Write(value);
        }
예제 #17
0
        /// <summary>
        /// Write a string.
        /// </summary>
        private static void WriteString(AmfStreamWriter writer, XmlReader input)
        {
            var value = input.IsEmptyElement
                ? string.Empty
                : input.ReadContentAsString();

            WriteString(writer, value);
        }
예제 #18
0
        /// <summary>
        /// Write UTF-8 data.
        /// </summary>
        /// <param name="writer">
        /// The writer.
        /// </param>
        /// <param name="data">
        /// The data.
        /// </param>
        private static void WriteUtf8(AmfStreamWriter writer, byte[] data)
        {
            // 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
            int flag = (data.Length << 1) | 0x1;

            WriteUInt29(writer, flag);
            writer.Write(data);
        }
예제 #19
0
        /// <summary>
        /// Write a double.
        /// </summary>
        private static void WriteDouble(AmfStreamWriter writer, XmlReader input)
        {
            input.Read();
            var value = Convert.ToDouble(input.Value, CultureInfo.InvariantCulture);

            input.Read();

            WriteTypeMarker(writer, Amf3TypeMarker.Double);
            writer.Write(value);
        }
예제 #20
0
        /// <summary>
        /// Write a reference.
        /// </summary>
        /// <param name="writer">
        /// The writer.
        /// </param>
        /// <param name="reference">
        /// The reference.
        /// </param>
        private static void WriteReference(AmfStreamWriter writer, int reference)
        {
            reference &= UInt29Mask; // Truncate value to UInt29

            // The first bit is a flag (representing whether an instance follows)
            // with value 0 to imply that this is not an instance but a reference.
            // The remaining 1 to 28 significant bits are used to encode a reference index.
            int flag = reference << 1;

            WriteUInt29(writer, flag);
        }
예제 #21
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);
        }
예제 #22
0
        /// <summary>
        /// Write UTF8 data.
        /// </summary>
        private static void WriteUtf8(AmfStreamWriter writer, byte[] data)
        {
            if (data.Length < ShortStringLimit)
            {
                writer.Write((ushort)data.Length);
            }
            else
            {
                writer.Write((uint)data.Length);
            }

            writer.Write(data);
        }
예제 #23
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);
        }
예제 #24
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));
            }
        }
예제 #25
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);
        }
예제 #26
0
        /// <summary>
        /// Write an 29-bit unsigned integer.
        /// </summary>
        /// <param name="writer">
        /// The writer.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        private static void WriteUInt29(AmfStreamWriter writer, int value)
        {
            // < 128:
            // 0x00000000 - 0x0000007F
            if (value < 0x80)
            {
                writer.Write((byte)value); // 0xxxxxxx
            }

            // < 16,384:
            // 0x00000080 - 0x00003FFF
            else if (value < 0x4000)
            {
                writer.Write((byte)(value >> 7 & 0x7F | 0x80)); // 1xxxxxxx
                writer.Write((byte)(value & 0x7F));             // xxxxxxxx
            }

            // < 2,097,152:
            // 0x00004000 - 0x001FFFFF
            else if (value < 0x200000)
            {
                writer.Write((byte)(value >> 14 & 0x7F | 0x80)); // 1xxxxxxx
                writer.Write((byte)(value >> 7 & 0x7F | 0x80));  // 1xxxxxxx
                writer.Write((byte)(value & 0x7F));              // xxxxxxxx
            }

            // 0x00200000 - 0x3FFFFFFF
            else if (value < 0x40000000)
            {
                writer.Write((byte)(value >> 22 & 0x7F | 0x80)); // 1xxxxxxx
                writer.Write((byte)(value >> 15 & 0x7F | 0x80)); // 1xxxxxxx
                writer.Write((byte)(value >> 8 & 0x7F | 0x80));  // 1xxxxxxx
                writer.Write((byte)(value & 0xFF));              // xxxxxxxx
            }

            // 0x40000000 - 0xFFFFFFFF, out of range
            else
            {
                throw new IndexOutOfRangeException("Integer is out of range: " + value);
            }
        }
예제 #27
0
        /// <summary>
        /// Write an integer.
        /// </summary>
        private static void WriteInteger(AmfStreamWriter writer, XmlReader input)
        {
            var text  = input.ReadString();
            var value = Convert.ToInt64(text);

            //Check if the value fits the Int29 span
            if (value >= MinInt29Value && value <= MaxInt29Value)
            {
                //It should be safe to cast it there
                var integer = UInt29Mask & (int)value; //Truncate the value

                WriteTypeMarker(writer, Amf3TypeMarker.Integer);
                WriteUInt29(writer, integer);
            }
            //Promote the value to a double
            else
            {
                WriteTypeMarker(writer, Amf3TypeMarker.Double);
                writer.Write(Convert.ToDouble(value));
            }
        }
예제 #28
0
        /// <summary>
        /// Write UTF-8 string.
        /// </summary>
        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;
            }

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

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

            context.StringReferences.Add(value);

            var decoded = Encoding.UTF8.GetBytes(value);

            WriteUtf8(writer, decoded);
        }
예제 #29
0
 /// <summary>
 /// Write an 29-bit unsigned integer.
 /// </summary>
 private static void WriteUInt29(AmfStreamWriter writer, int value)
 {
     //< 128:
     //0x00000000 - 0x0000007F
     if (value < 0x80)
     {
         writer.Write((byte)value);                      //0xxxxxxx
     }
     //< 16,384:
     //0x00000080 - 0x00003FFF
     else if (value < 0x4000)
     {
         writer.Write((byte)(value >> 7 & 0x7F | 0x80));   //1xxxxxxx
         writer.Write((byte)(value & 0x7F));               //xxxxxxxx
     }
     //< 2,097,152:
     //0x00004000 - 0x001FFFFF
     else if (value < 0x200000)
     {
         writer.Write((byte)(value >> 14 & 0x7F | 0x80));  //1xxxxxxx
         writer.Write((byte)(value >> 7 & 0x7F | 0x80));   //1xxxxxxx
         writer.Write((byte)(value & 0x7F));               //xxxxxxxx
     }
     //0x00200000 - 0x3FFFFFFF
     else if (value < 0x40000000)
     {
         writer.Write((byte)(value >> 22 & 0x7F | 0x80));  //1xxxxxxx
         writer.Write((byte)(value >> 15 & 0x7F | 0x80));  //1xxxxxxx
         writer.Write((byte)(value >> 8 & 0x7F | 0x80));   //1xxxxxxx
         writer.Write((byte)(value & 0xFF));               //xxxxxxxx
     }
     //0x40000000 - 0xFFFFFFFF, out of range
     else
     {
         throw new IndexOutOfRangeException("Integer is out of range: " + value);
     }
 }
예제 #30
0
 /// <summary>
 /// Write an AMF0 type marker.
 /// </summary>
 private static void WriteTypeMarker(AmfStreamWriter writer, Amf3TypeMarker marker)
 {
     writer.Write((byte)marker);
 }
예제 #31
0
        protected override void WriteAmfValue(AmfContext context, XmlReader input, AmfStreamWriter writer)
        {
            if (context.AmfVersion != AmfVersion.Amf0)
                throw new InvalidOperationException(string.Format(Errors.Amf0Decoder_ReadAmfValue_AmfVersionNotSupported, context.AmfVersion));

            if (input == null) throw new ArgumentNullException("input");
            if (context == null) throw new ArgumentNullException("context");
            if (input.NodeType != XmlNodeType.Element) throw new XmlException(string.Format("Element node expected, {0} found.", input.NodeType));

            #region Primitive values
            switch (input.Name)
            {
                case AmfxContent.Null:
                    WriteNull(writer);
                    return;

                case AmfxContent.True:
                    WriteBoolean(writer, true);
                    return;

                case AmfxContent.False:
                    WriteBoolean(writer, false);
                    return;
            }
            #endregion

            #region Complex values
            var reader = input.ReadSubtree();
            reader.MoveToContent();

            switch (reader.Name)
            {
                case AmfxContent.Integer:
                case AmfxContent.Double:
                    WriteNumber(writer, reader);
                    break;

                case AmfxContent.String:
                    WriteString(writer, reader);
                    break;

                case AmfxContent.Date:
                    WriteDate(writer, reader);
                    break;

                case AmfxContent.Xml:
                    WriteXml(writer, reader);
                    break;

                case AmfxContent.Reference:
                    WriteReference(context, writer, reader);
                    break;

                case AmfxContent.Array:
                    WriteArray(context, writer, reader);
                    break;

                case AmfxContent.Object:
                    WriteObject(context, writer, reader);
                    break;

                default:
                    throw new NotSupportedException("Unexpected AMFX type: " + reader.Name);
            }
            #endregion
        }
예제 #32
0
        /// <summary>
        /// Encode an AMF packet from an AMFX format.
        /// </summary>
        /// <exception cref="FormatException">Error during encoding.</exception>
        public void Encode(Stream stream, XmlReader input)
        {
            if (stream == null) throw new ArgumentNullException("stream");
            if (!stream.CanWrite) throw new ArgumentException(Errors.AmfPacketWriter_Write_StreamNotWriteable, "stream");
            if (input == null) throw new ArgumentNullException("input");

            try
            {
                #region Encode data
                var encoder = CreateEncoder(_options);
                var amfStreamWriter = new AmfStreamWriter(stream);

                WriteAmfVersion(amfStreamWriter, _options.AmfVersion);

                input.MoveToContent();

                var headerCount = Convert.ToInt32(input.GetAttribute(AmfxContent.PacketHeaderCount));
                var bodyCount = Convert.ToInt32(input.GetAttribute(AmfxContent.PacketBodyCount));

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

                    if (headerCount != -1)
                    {
                        WriteHeaderCount(amfStreamWriter, headerCount);
                        headerCount = -1;
                    }

                    #region Read packet header
                    if (input.Name == AmfxContent.PacketHeader)
                    {
                        var header = new AmfHeaderDescriptor
                                         {
                                             Name = input.GetAttribute(AmfxContent.PacketHeaderName),
                                             MustUnderstand =
                                                 (input.GetAttribute(AmfxContent.PacketHeaderMustUnderstand) ==
                                                  AmfxContent.True)
                                         };

                        encoder.WritePacketHeader(stream, header);

                        while (input.Read())
                        {
                            //Skip until header content is found, if any
                            if (input.NodeType != XmlNodeType.Element || input.Name == AmfxContent.PacketHeader)
                                continue;

                            encoder.Encode(stream, input);
                            break;
                        }
                        continue;
                    }
                    #endregion

                    if (bodyCount != -1)
                    {
                        WriteMessageCount(amfStreamWriter, bodyCount);
                        bodyCount = -1;
                    }

                    #region Read packet body
                    if (input.Name == AmfxContent.PacketBody)
                    {
                        var message = new AmfMessageDescriptor
                                          {
                                              Target = input.GetAttribute(AmfxContent.PacketBodyTarget),
                                              Response = input.GetAttribute(AmfxContent.PacketBodyResponse)
                                          };

                        encoder.WritePacketBody(stream, message);

                        while (input.Read())
                        {
                            //Skip until body content is found, if any
                            if (input.NodeType != XmlNodeType.Element || input.Name == AmfxContent.PacketBody)
                                continue;

                            encoder.Encode(stream, input);
                            break;
                        }
                        continue;
                    }
                    #endregion
                }
                #endregion
            }
            catch (Exception e)
            {
                throw new FormatException(Errors.AmfPacketReader_DecodingError, e);
            }
        }
예제 #33
0
 public override void Encode(Stream stream, XmlReader input)
 {
     var writer = new AmfStreamWriter(stream);
     var context = CreateDefaultContext();
     WriteAmfValue(context, input, writer);
 }
예제 #34
0
        /// <summary>
        /// Write an array.
        /// </summary>
        private void WriteArray(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            context.References.Add(new AmfReference { AmfxType = AmfxContent.Array });
            WriteTypeMarker(writer, Amf3TypeMarker.Array);

            var length = Convert.ToInt32(input.GetAttribute(AmfxContent.ArrayLength), CultureInfo.InvariantCulture);

            //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.
            var size = (length << 1) | 0x1;
            WriteUInt29(writer, size);

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

            if (length == 0) return;

            input.Read();

            for (var i = 0; i < length; i++)
            {
                WriteAmfValue(context, input, writer);
                input.Read();
            }
        }
예제 #35
0
        /// <summary>
        /// Write a date.
        /// </summary>
        private static void WriteDate(AmfStreamWriter writer, XmlReader input)
        {
            var value = input.ReadContentAsDouble();

            WriteDate(writer, value);
        }
예제 #36
0
 /// <summary>
 /// Write AMF message version.
 /// </summary>
 private static void WriteAmfVersion(AmfStreamWriter writer, AmfVersion version)
 {
     writer.Write((ushort)version);
 }
예제 #37
0
        /// <summary>
        /// Write UTF8 data.
        /// </summary>
        private static void WriteUtf8(AmfStreamWriter writer, byte[] data)
        {
            if (data.Length < ShortStringLimit)
                writer.Write((ushort)data.Length);
            else
                writer.Write((uint)data.Length);

            writer.Write(data);
        }
예제 #38
0
        /// <summary>
        /// Write an object.
        /// </summary>
        private void WriteObject(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            context.References.Add(new AmfReference { AmfxType = AmfxContent.Object });

            WriteTypeMarker(writer, Amf0TypeMarker.Object);

            var typeName = string.Empty;

            if (input.HasAttributes)
                typeName = input.GetAttribute(AmfxContent.ObjectType);

            #region Read traits
            var traits = new AmfTypeTraits { TypeName = typeName };

            while (input.Read())
            {
                if (input.NodeType != XmlNodeType.Element && input.Name != AmfxContent.Traits) continue;

                if (!input.IsEmptyElement)
                {
                    var traitsReader = input.ReadSubtree();
                    traitsReader.MoveToContent();
                    traitsReader.ReadStartElement();

                    var members = new List<string>();

                    while (input.NodeType != XmlNodeType.EndElement)
                        members.Add(traitsReader.ReadElementContentAsString());

                    traits.ClassMembers = members.ToArray();
                }

                break;
            }
            #endregion

            #region Type name
            //Untyped object
            if(string.IsNullOrEmpty(traits.TypeName))
            {
                WriteTypeMarker(writer, Amf0TypeMarker.Object);
            }
            //Strongly-typed object
            else
            {
                WriteTypeMarker(writer, Amf0TypeMarker.TypedObject);
                var typeNameData = Encoding.UTF8.GetBytes(traits.TypeName);
                writer.Write((ushort)typeNameData.Length);
                writer.Write(typeNameData);
            }
            #endregion

            #region Write members
            var i = 0;

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

                var memberName = traits.ClassMembers[i];
                var memberReader = input.ReadSubtree();
                memberReader.MoveToContent();

                WriteUtf8(writer, memberName);
                WriteAmfValue(context, memberReader, writer);

                i++;
            }
            #endregion

            WriteUtf8(writer, string.Empty);
            WriteTypeMarker(writer, Amf0TypeMarker.ObjectEnd);
        }
예제 #39
0
        /// <summary>
        /// Write UTF-8 data.
        /// </summary>
        private static void WriteUtf8(AmfStreamWriter writer, byte[] data)
        {
            //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 = (data.Length << 1) | 0x1;

            WriteUInt29(writer, flag);
            writer.Write(data);
        }
예제 #40
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);
                }
            }
        }
예제 #41
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);

            input.Read();
            var encoded = input.Value;
            input.Read();

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

            WriteUtf8(writer, decoded);
        }
예제 #42
0
 /// <summary>
 /// Write an XML.
 /// </summary>
 private static void WriteXml(AmfStreamWriter writer, byte[] value)
 {
     WriteTypeMarker(writer, Amf0TypeMarker.XmlDocument);
     writer.Write((uint)value.Length);
     writer.Write(value);
 }
예제 #43
0
        /// <summary>
        /// Write an object.
        /// </summary>
        private void WriteObject(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            context.References.Add(new AmfReference { AmfxType = AmfxContent.Object });
            WriteTypeMarker(writer, Amf3TypeMarker.Object);

            AmfTypeTraits traits;
            var typeName = string.Empty;

            if (input.HasAttributes)
                typeName = input.GetAttribute(AmfxContent.ObjectType);

            #region Write traits
            input.Read();

            //Send traits by value
            if (!input.IsEmptyElement)
            {
                traits = new AmfTypeTraits { TypeName = typeName };
                context.TraitsReferences.Add(traits);

                var traitsReader = input.ReadSubtree();
                traitsReader.MoveToContent();
                traitsReader.ReadStartElement();

                var members = new List<string>();

                while (input.NodeType != XmlNodeType.EndElement)
                    members.Add(traitsReader.ReadElementContentAsString());

                traits.ClassMembers = members.ToArray();

                //The first bit is a flag with value 1.
                //The second bit is a flag with value 1.
                //The third bit is a flag with value 0.
                var flag = 0x3; //00000011

                if (traits.IsExternalizable) flag |= 0x4; //00000111

                //The fourth bit is a flag specifying whether the type is dynamic.
                //A value of 0 implies not dynamic, a value of 1 implies dynamic.
                if (traits.IsDynamic) flag |= 0x8; //00001011

                //The remaining 1 to 25 significant bits are used to encode the number
                //of sealed traits member names that follow after the class name.
                var count = traits.ClassMembers.Count();
                flag |= count << 4;

                WriteUInt29(writer, flag);

                WriteUtf8(context, writer, traits.TypeName);

                //Write member names
                foreach (var member in traits.ClassMembers)
                    WriteUtf8(context, writer, member);
            }
            //Send traits by reference
            else
            {
                var index = Convert.ToInt32(input.GetAttribute(AmfxContent.TraitsId), CultureInfo.InvariantCulture);
                traits = context.TraitsReferences[index];

                var flag = index & UInt29Mask; //Truncate value to UInt29

                //The first bit is a flag with value 1.
                //The second bit is a flag (representing whether a trait
                //reference follows) with value 0 to imply that this objects
                //traits are being sent by reference. The remaining 1 to 27
                //significant bits are used to encode a trait reference index.
                flag = (flag << 2) | 0x1;
                WriteUInt29(writer, flag);
            }

            input.Read();
            #endregion

            #region Write members
            for (var i = 0; i < traits.ClassMembers.Length; i++)
            {
                WriteAmfValue(context, input, writer);
                input.Read();
            }
            #endregion
        }
예제 #44
0
 /// <summary>
 /// Write an XML.
 /// </summary>
 private static void WriteXml(AmfStreamWriter writer, XmlReader input)
 {
     var value = input.ReadContentAsString();
     var data = Encoding.UTF8.GetBytes(value);
     WriteXml(writer, data);
 }
예제 #45
0
        protected override void WriteAmfValue(AmfContext context, XmlReader input, AmfStreamWriter writer)
        {
            if (input == null) throw new ArgumentNullException("input");
            if (context == null) throw new ArgumentNullException("context");
            if (input.NodeType != XmlNodeType.Element) throw new XmlException(string.Format("Element node expected, {0} found.", input.NodeType));

            if (context.AmfVersion != AmfVersion.Amf3)
            {
                context = new AmfContext(AmfVersion.Amf3);
                writer.Write((byte)Amf0TypeMarker.AvmPlusObject);
            }

            #region Primitive values
            switch (input.Name)
            {
                case AmfxContent.Null:
                    WriteTypeMarker(writer, Amf3TypeMarker.Null);
                    return;

                case AmfxContent.True:
                    WriteTypeMarker(writer, Amf3TypeMarker.True);
                    return;

                case AmfxContent.False:
                    WriteTypeMarker(writer, Amf3TypeMarker.False);
                    return;
            }
            #endregion

            #region Complex values
            switch (input.Name)
            {
                case AmfxContent.Integer:
                    WriteInteger(writer, input);
                    break;

                case AmfxContent.Double:
                    WriteDouble(writer, input);
                    break;

                case AmfxContent.String:
                    WriteString(context, writer, input);
                    break;

                case AmfxContent.Reference:
                    WriteReference(context, writer, input);
                    break;

                case AmfxContent.Date:
                    WriteDate(context, writer, input);
                    break;

                case AmfxContent.Xml:
                    WriteXml(context, writer, input);
                    break;

                case AmfxContent.Array:
                    WriteArray(context, writer, input);
                    break;

                case AmfxContent.ByteArray:
                    WriteByteArray(context, writer, input);
                    break;

                case AmfxContent.Object:
                    WriteObject(context, writer, input);
                    break;

                default:
                    throw new NotSupportedException("Unexpected AMFX type: " + input.Name);
            }
            #endregion
        }
예제 #46
0
 /// <summary>
 /// Write AMF message bodies count.
 /// </summary>
 private static void WriteMessageCount(AmfStreamWriter writer, int count)
 {
     writer.Write((ushort)count);
 }
예제 #47
0
        /// <summary>
        /// Write a date.
        /// </summary>
        private static void WriteDate(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            context.References.Add(new AmfReference { AmfxType = AmfxContent.Date });
            WriteTypeMarker(writer, Amf3TypeMarker.Date);

            var milliseconds = input.ReadElementContentAsDouble();

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

            writer.Write(milliseconds);
        }
예제 #48
0
 /// <summary>
 /// Write AMF value from the current position.
 /// </summary>
 /// <param name="context">AMF decoding context.</param>
 /// <param name="input">AMFX input reader.</param>
 /// <param name="writer">AMF stream writer.</param>
 /// <exception cref="NotSupportedException">AMF type is not supported.</exception>
 /// <exception cref="FormatException">Invalid data format.</exception>
 /// <exception cref="SerializationException">Error during serialization.</exception>
 protected abstract void WriteAmfValue(AmfContext context, XmlReader input, AmfStreamWriter writer);
예제 #49
0
        /// <summary>
        /// Write a double.
        /// </summary>
        private static void WriteDouble(AmfStreamWriter writer, XmlReader input)
        {
            input.Read();
            var value = Convert.ToDouble(input.Value, CultureInfo.InvariantCulture);
            input.Read();

            WriteTypeMarker(writer, Amf3TypeMarker.Double);
            writer.Write(value);
        }
예제 #50
0
        /// <summary>
        /// Write an integer.
        /// </summary>
        private static void WriteInteger(AmfStreamWriter writer, XmlReader input)
        {
            input.Read();
            var value = Convert.ToInt32(input.Value, CultureInfo.InvariantCulture);
            input.Read();

            //Check if the value fits the Int29 span
            if (value >= MinInt29Value && value <= MaxInt29Value)
            {
                //It should be safe to cast it there
                var integer = UInt29Mask & (int)value; //Truncate the value

                WriteTypeMarker(writer, Amf3TypeMarker.Integer);
                WriteUInt29(writer, integer);
            }
            //Promote the value to a double
            else
            {
                WriteTypeMarker(writer, Amf3TypeMarker.Double);
                writer.Write(Convert.ToDouble(value, CultureInfo.InvariantCulture));
            }
        }
예제 #51
0
 /// <summary>
 /// Write a date.
 /// </summary>
 private static void WriteDate(AmfStreamWriter writer, double value)
 {
     WriteTypeMarker(writer, Amf0TypeMarker.Date);
     writer.Write(value);
     writer.Write((short)0); //Timezone (not used)
 }
예제 #52
0
        /// <summary>
        /// Write a reference.
        /// </summary>
        private static void WriteReference(AmfStreamWriter writer, int reference)
        {
            reference &= UInt29Mask; //Truncate value to UInt29

            //The first bit is a flag (representing whether an instance follows)
            //with value 0 to imply that this is not an instance but a reference.
            //The remaining 1 to 28 significant bits are used to encode a reference index.
            var flag = reference << 1;

            WriteUInt29(writer, flag);
        }
예제 #53
0
 /// <summary>
 /// Write an XML.
 /// </summary>
 private static void WriteXml(AmfStreamWriter writer, byte[] value)
 {
     WriteTypeMarker(writer, Amf0TypeMarker.XmlDocument);
     writer.Write((uint)value.Length);
     writer.Write(value);
 }
예제 #54
0
        /// <summary>
        /// Write an integer.
        /// </summary>
        private static void WriteReference(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            var index = Convert.ToInt32(input.GetAttribute(AmfxContent.ReferenceId), CultureInfo.InvariantCulture);
            var 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);
        }
예제 #55
0
        /// <summary>
        /// Write an object.
        /// </summary>
        private void WriteObject(AmfContext context, AmfStreamWriter writer, XmlReader input)
        {
            context.References.Add(new AmfReference {
                AmfxType = AmfxContent.Object
            });

            WriteTypeMarker(writer, Amf0TypeMarker.Object);

            var typeName = string.Empty;

            if (input.HasAttributes)
            {
                typeName = input.GetAttribute(AmfxContent.ObjectType);
            }

            #region Read traits
            var traits = new AmfTypeTraits {
                TypeName = typeName
            };

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

                if (!input.IsEmptyElement)
                {
                    var traitsReader = input.ReadSubtree();
                    traitsReader.MoveToContent();
                    traitsReader.ReadStartElement();

                    var members = new List <string>();

                    while (input.NodeType != XmlNodeType.EndElement)
                    {
                        members.Add(traitsReader.ReadElementContentAsString());
                    }

                    traits.ClassMembers = members.ToArray();
                }

                break;
            }
            #endregion

            #region Type name
            //Untyped object
            if (string.IsNullOrEmpty(traits.TypeName))
            {
                WriteTypeMarker(writer, Amf0TypeMarker.Object);
            }
            //Strongly-typed object
            else
            {
                WriteTypeMarker(writer, Amf0TypeMarker.TypedObject);
                var typeNameData = Encoding.UTF8.GetBytes(traits.TypeName);
                writer.Write((ushort)typeNameData.Length);
                writer.Write(typeNameData);
            }
            #endregion

            #region Write members
            var i = 0;

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

                var memberName   = traits.ClassMembers[i];
                var memberReader = input.ReadSubtree();
                memberReader.MoveToContent();

                WriteUtf8(writer, memberName);
                WriteAmfValue(context, memberReader, writer);

                i++;
            }
            #endregion

            WriteUtf8(writer, string.Empty);
            WriteTypeMarker(writer, Amf0TypeMarker.ObjectEnd);
        }
예제 #56
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);
        }
예제 #57
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);

            input.Read();
            var encoded = input.Value;
            input.Read();

            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);
        }
예제 #58
0
 /// <summary>
 /// Write AMF message headers count.
 /// </summary>
 private static void WriteHeaderCount(AmfStreamWriter writer, int count)
 {
     writer.Write((ushort)count);
 }
예제 #59
0
        protected override void WriteAmfValue(AmfContext context, XmlReader input, AmfStreamWriter writer)
        {
            if (context.AmfVersion != AmfVersion.Amf0)
            {
                throw new InvalidOperationException(string.Format(Errors.Amf0Decoder_ReadAmfValue_AmfVersionNotSupported, context.AmfVersion));
            }

            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (input.NodeType != XmlNodeType.Element)
            {
                throw new XmlException(string.Format("Element node expected, {0} found.", input.NodeType));
            }

            #region Primitive values
            switch (input.Name)
            {
            case AmfxContent.Null:
                WriteNull(writer);
                return;

            case AmfxContent.True:
                WriteBoolean(writer, true);
                return;

            case AmfxContent.False:
                WriteBoolean(writer, false);
                return;
            }
            #endregion

            #region Complex values
            var reader = input.ReadSubtree();
            reader.MoveToContent();

            switch (reader.Name)
            {
            case AmfxContent.Integer:
            case AmfxContent.Double:
                WriteNumber(writer, reader);
                break;

            case AmfxContent.String:
                WriteString(writer, reader);
                break;

            case AmfxContent.Date:
                WriteDate(writer, reader);
                break;

            case AmfxContent.Xml:
                WriteXml(writer, reader);
                break;

            case AmfxContent.Reference:
                WriteReference(context, writer, reader);
                break;

            case AmfxContent.Array:
                WriteArray(context, writer, reader);
                break;

            case AmfxContent.Object:
                WriteObject(context, writer, reader);
                break;

            default:
                throw new NotSupportedException("Unexpected AMFX type: " + reader.Name);
            }
            #endregion
        }
예제 #60
0
 /// <summary>
 /// Write UTF8 string.
 /// </summary>
 private static void WriteUtf8(AmfStreamWriter writer, string value)
 {
     var data = Encoding.UTF8.GetBytes(value);
     WriteUtf8(writer, data);
 }