SoFunction
Updated on 2025-03-07

C# implementation of FLV analysis detailed explanation example


using ;
using ;
using ;
using ;

namespace
{
    class ScriptTag : Tag
    {
        public List<KeyValuePair<string, object>> Values { get; private set; }
        public ScriptTag()
        {
            tagType = ;
            Values = new List<KeyValuePair<string, object>>();
        }

        public override void readData(Stream stream)
        {
            offset = 0;
            ();
            byte[] bs = new byte[3];
            while (offset < )
            {
                (bs, 0, 3);
                if (bs[0] == 0 && bs[1] == 0 && bs[2] == 9)
                {
                    offset += 3;
                    break;
                }
                (-3, );
                AddElement("#" + offset, ReadElement(stream));
            }
        }

        private void AddElement(string key, object o)
        {
            (new KeyValuePair<string, object>(key, o));
        }

        private object ReadElement(Stream src)
        {
            int type = ();
            offset++;
            switch (type)
            {
                case 0: // Number - 8
                    return ReadDouble(src);
                case 1: // Boolean - 1
                    return ReadByte(src);
                case 2: // String - 2+n
                    return ReadString(src);
                case 3: // Object
                    return ReadObject(src);
                case 4: // MovieClip
                    return ReadString(src);
                case 5: // Null
                    break;
                case 6: // Undefined
                    break;
                case 7: // Reference - 2
                    return ReadUShort(src);
                case 8: // ECMA array
                    return ReadArray(src);
                case 10: // Strict array
                    return ReadStrictArray(src);
                case 11: // Date - 8+2
                    return ReadDate(src);
                case 12: // Long string - 4+n
                    return ReadLongString(src);
            }
            return null;
        }
        private object ReadObject(Stream src)
        {
            byte[] bs = new byte[3];
            ScriptObject obj = new ScriptObject();
            while (offset < )
            {
                (bs, 0, 3);
                if (bs[0] == 0 && bs[1] == 0 && bs[2] == 9)
                {
                    offset += 3;
                    break;
                }
                (-3, );
                string key = ReadString(src);
                if (key[0] == 0)
                    break;
                obj[key] = ReadElement(src);
            }
            return obj;
        }
        private double ReadDate(Stream src)
        {
            double d = ReadDouble(src);
            (2, );
            offset += 2;
            return d;
        }
        private ScriptObject ReadArray(Stream src)
        {
            byte[] buffer = new byte[4];
            (buffer, 0, 4);
            offset += 4;
            uint count = (buffer, 4);
            ScriptObject array = new ScriptObject();
            for (uint i = 0; i < count; i++)
            {
                string key = ReadString(src);
                array[key] = ReadElement(src);
            }
            (3, ); // 00 00 09
            offset += 3;
            return array;
        }
        private ScriptArray ReadStrictArray(Stream src)
        {
            byte[] bs = new byte[4];
            (bs, 0, 4);
            offset += 4;
            ScriptArray array = new ScriptArray();
            uint count = (bs, 4);
            for (uint i = 0; i < count; i++)
            {
                (ReadElement(src));
            }
            return array;
        }
        private double ReadDouble(Stream src)
        {
            byte[] buffer = new byte[8];
            (buffer, 0, 8);
            offset += 8;
            return (buffer);
        }
        private byte ReadByte(Stream src)
        {
            offset++;
            return (byte)();
        }
        private string ReadString(Stream src)
        {
            byte[] bs = new byte[2];
            (bs, 0, 2);
            offset += 2;
            int n = (int)(bs, 2);
            bs = new byte[n];
            (bs, 0, n);
            offset += n;
            return (bs);
        }
        private string ReadLongString(Stream src)
        {
            byte[] bs = new byte[4];
            (bs, 0, 4);
            offset += 4;
            int n = (int)(bs, 4);
            bs = new byte[n];
            (bs, 0, n);
            offset += n;
            return (bs);
        }
        private ushort ReadUShort(Stream src)
        {
            byte[] buffer = new byte[2];
            (buffer, 0, 2);
            offset += 2;
            return (ushort)(buffer, 2);
        }
    }

    public class ScriptObject
    {
        public static int indent = 0;
        private Dictionary<string, object> values = new Dictionary<string, object>();
        public object this[string key]
        {
            get
            {
                object o;
                (key, out o);
                return o;
            }
            set
            {
                if (!(key))
                {
                    (key, value);
                }
            }
        }
        public override string ToString()
        {
            string str = "{\r\n";
             += 2;
            foreach (KeyValuePair<string, object> kv in values)
            {
                str += new string(' ', )
                          + + ": " + + "\r\n";
            }
             -= 2;
            //if ( > 1)
            //    str = (0, - 1);
            str += "}";
            return str;
        }
    }
    public class ScriptArray
    {
        private List<object> values = new List<object>();
        public object this[int index]
        {
            get
            {
                if (index >= 0 && index < )
                    return values[index];
                return null;
            }
        }
        public void Add(object o)
        {
            (o);
        }
        public override string ToString()
        {
            string str = "[";
            int n = 0;
            foreach (object o in values)
            {
                if (n % 10 == 0)
                    str += "\r\n";
                n++;
                str += o + ",";
            }
            if ( > 1)
                str = (0, - 1);
            str += "\r\n]";
            return str;
        }
    }
}