Exemplo n.º 1
0
        protected Mp3XingBlock(byte[] frameBuf, int xix, Mp3Header header, string xingString)
        {
            this.buf        = frameBuf;
            this.header     = header;
            this.xingIx     = xix;
            this.XingString = xingString;

            int ix = xingIx + 8;

            if (HasFrameCount)
            {
                this.FrameCount = ConvertTo.FromBig32ToInt32(frameBuf, ix);
                ix += 4;
            }
            if (HasSize)
            {
                this.XingSize = ConvertTo.FromBig32ToInt32(frameBuf, ix);
                ix           += 4;
            }
            if (HasTableOfContents)
            {
                this.tocOffset = ix;
                ix            += 100;
            }
            if (HasQualityIndicator)
            {
                this.QualityIndicator = ConvertTo.FromBig32ToInt32(frameBuf, ix);
            }
        }
Exemplo n.º 2
0
        public void UnitE_Big32ToInt()
        {
            var buf    = new byte[] { 0x12, 0xFF, 0xFF, 0xFF, 0xFE, 0xED };
            var result = ConvertTo.FromBig32ToInt32(buf, 1);

            Assert.AreEqual(result.GetType(), typeof(Int32));
            Assert.AreEqual(-2, result);
        }
Exemplo n.º 3
0
            public Model(Stream stream, string path)
            {
                ChunksModel = new PngChunk.Vector.Model();
                base._data  = Data = new PngFormat(this, stream, path);

                // Arbitrary sanity limit.
                if (Data.FileSize > 100000000)
                {
                    IssueModel.Add("File size insanely huge.", Severity.Fatal);
                    return;
                }

                Data.fBuf = new byte[(int)Data.FileSize];
                var fBuf = Data.fBuf;

                stream.Position = 0;
                int got = stream.Read(fBuf, 0, (int)Data.FileSize);

                if (got < Data.FileSize)
                {
                    IssueModel.Add("Read failed.", Severity.Fatal);
                    return;
                }

                Data.ValidSize = 8;

                if (fBuf[0x0C] != 'I' || fBuf[0x0D] != 'H' || Data.fBuf[0x0E] != 'D' || Data.fBuf[0x0F] != 'R')
                {
                    IssueModel.Add("Missing 'IHDR' chunk.", Severity.Fatal);
                    return;
                }

                Data.Width             = ConvertTo.FromBig32ToInt32(fBuf, 0x10);
                Data.Height            = ConvertTo.FromBig32ToInt32(fBuf, 0x14);
                Data.BitDepth          = fBuf[0x18];
                Data.ColorType         = fBuf[0x19];
                Data.CompressionMethod = fBuf[0x1A];
                Data.FilterMethod      = fBuf[0x1B];
                Data.InterlaceMethod   = fBuf[0x1C];

                do
                {
                    UInt32 chunkSize = ConvertTo.FromBig32ToUInt32(fBuf, (int)Data.ValidSize);
                    if (Data.ValidSize + chunkSize + 12 > Data.FileSize)
                    {
                        IssueModel.Add("File is corrupt or truncated.", Severity.Fatal);
                        return;
                    }

                    string type      = Encoding.ASCII.GetString(fBuf, (int)Data.ValidSize + 4, 4);
                    UInt32 storedCRC = ConvertTo.FromBig32ToUInt32(fBuf, (int)(Data.ValidSize + chunkSize + 8));
                    ChunksModel.Add(type, chunkSize, storedCRC);

                    var typeLow = type.ToLower();
                    switch (typeLow)
                    {
                    case "idat":
                        if (Data.mediaPosition <= 0)
                        {
                            Data.mediaPosition = Data.ValidSize;
                        }
                        break;

                    case "iend":
                        if (Data.MediaCount > 0)
                        {
                            IssueModel.Add("Multiple IEND chunks.");
                        }
                        else
                        {
                            Data.MediaCount = Data.ValidSize - Data.mediaPosition + chunkSize + 0xC;
                        }
                        break;

                    case "text":
                        if (chunkSize > 0x7FFF)
                        {
                            IssueModel.Add("String size too large.");
                        }
                        else
                        {
                            var escaped = new StringBuilder();
                            for (int ix = (int)Data.ValidSize + 8; ix < (int)Data.ValidSize + 8 + chunkSize; ++ix)
                            {
                                if (fBuf[ix] < ' ' || fBuf[ix] > 0x7F)
                                {
                                    escaped.AppendFormat("\\{0:x2}", fBuf[ix]);
                                }
                                else
                                {
                                    escaped.Append((char)fBuf[ix]);
                                }
                            }

                            Data.texts.Add(escaped.ToString());
                        }
                        break;

                    case "gama":
                        if (Data.Gamma != null)
                        {
                            IssueModel.Add("Unexpected multiple gamma chunks.");
                        }
                        else
                        if (chunkSize != 4)
                        {
                            IssueModel.Add($"Bad gamma chunk size '{chunkSize}', expecting '4'.");
                        }
                        else
                        {
                            Data.Gamma = ConvertTo.FromBig32ToUInt32(fBuf, (int)Data.ValidSize + 8) / 100000f;
                        }
                        break;
                    }

                    Data.ValidSize += chunkSize + 0xC;
                }while (Data.ValidSize < Data.FileSize);

                if (Data.Chunks.Items[Data.Chunks.Items.Count - 1].Type != "IEND")
                {
                    IssueModel.Add("Missing 'IEND' chunk.");
                }

                if (Data.Width <= 0 || Data.Height <= 0)
                {
                    IssueModel.Add("Invalid dimensions.");
                }

                if (Data.BitDepth != 1 && Data.BitDepth != 2 && Data.BitDepth != 4 && Data.BitDepth != 8 && Data.BitDepth != 16)
                {
                    IssueModel.Add($"Invalid bit depth '{Data.BitDepth}'.");
                }

                if (Data.CompressionMethod != 0)
                {
                    IssueModel.Add($"Invalid compression '{Data.CompressionMethod}'.");
                }

                if (Data.FilterMethod != 0)
                {
                    IssueModel.Add($"Invalid filter '{Data.FilterMethod}'.");
                }

                if (Data.InterlaceMethod != 0 && Data.InterlaceMethod != 1)
                {
                    IssueModel.Add($"Invalid interlace '{Data.InterlaceMethod}'.");
                }
            }
Exemplo n.º 4
0
            public Model(Stream stream, string path)
            {
                base._data = Data = new IcoFormat(this, stream, path);

                // Arbitrary sanity limit.
                if (Data.FileSize > 50000000)
                {
                    IssueModel.Add("File insanely large", Severity.Fatal);
                    return;
                }

                var buf = new byte[Data.FileSize];

                stream.Position = 0;
                var got = stream.Read(buf, 0, (int)Data.FileSize);

                if (got != Data.FileSize)
                {
                    IssueModel.Add("Read error", Severity.Fatal);
                    return;
                }

                int headerCount = ConvertTo.FromLit16ToInt32(buf, 4);

                if (headerCount <= 0)
                {
                    IssueModel.Add("Corrupt header count", Severity.Fatal);
                    return;
                }

                int pos         = 6;
                int stop        = pos + 16 * headerCount;
                int actualStart = stop;

                for (pos = 6; pos < stop; pos += 16)
                {
                    int width, height, bpp, paletteSize;
                    int storedSize  = ConvertTo.FromLit32ToInt32(buf, pos + 8);
                    int storedStart = ConvertTo.FromLit32ToInt32(buf, pos + 12);

                    if (storedStart != actualStart || storedSize <= 0)
                    {
                        IssueModel.Add($"Corrupt header near byte {Data.ValidSize}", Severity.Fatal);
                        return;
                    }

                    bool isPNG = buf[actualStart] == 0x89 && buf[actualStart + 1] == 'P' && buf[actualStart + 2] == 'N' && buf[actualStart + 3] == 'G';

                    if (isPNG)
                    {
                        width       = ConvertTo.FromBig32ToInt32(buf, actualStart + 16);
                        height      = ConvertTo.FromBig32ToInt32(buf, actualStart + 20);
                        paletteSize = 0;
                        bpp         = buf[actualStart + 24];
                    }
                    else
                    {
                        width = buf[pos];
                        if (width == 0)
                        {
                            width = 256;
                        }

                        height = buf[pos + 1];
                        if (height == 0)
                        {
                            height = 256;
                        }

                        paletteSize = buf[pos + 2];
                        bpp         = buf[pos + 6];
                    }

                    Data.icons.Add(new IconItem(width, height, paletteSize, bpp, storedStart, storedSize, isPNG));

                    actualStart += storedSize;
                }

                if (actualStart != Data.FileSize)
                {
                    IssueModel.Add("Incorrect file size");
                    return;
                }
            }
Exemplo n.º 5
0
 public Mp3Header(byte[] hdr, int ix)
 {
     Bits = ConvertTo.FromBig32ToInt32(hdr, ix);
 }
Exemplo n.º 6
0
            public Model(Stream stream, byte[] hdr, string path)
            {
                base._data = Data = new FlacFormat(this, stream, path);

                Data.MetadataBlockStreamInfoSize = ConvertTo.FromBig24ToInt32(hdr, 5);
                if (Data.MetadataBlockStreamInfoSize < 34)
                {
                    IssueModel.Add($"Bad metablock size of {Data.MetadataBlockStreamInfoSize}", Severity.Fatal);
                    return;
                }

                var bb = new byte[Data.MetadataBlockStreamInfoSize];

                Data.ValidSize = 8;

                Data.fbs.Position = Data.ValidSize;
                var got = Data.fbs.Read(bb, 0, Data.MetadataBlockStreamInfoSize);

                if (got != Data.MetadataBlockStreamInfoSize)
                {
                    IssueModel.Add("File truncated", Severity.Fatal);
                    return;
                }

                Data.MinBlockSize = ConvertTo.FromBig16ToInt32(bb, 0);
                Data.MinBlockSize = ConvertTo.FromBig16ToInt32(bb, 2);
                Data.MinFrameSize = ConvertTo.FromBig24ToInt32(bb, 4);
                Data.MaxFrameSize = ConvertTo.FromBig24ToInt32(bb, 7);

                Data.MetaSampleRate = bb[10] << 12 | bb[11] << 4 | bb[12] >> 4;
                Data.ChannelCount   = ((bb[12] & 0x0E) >> 1) + 1;
                Data.BitsPerSample  = (((bb[12] & 1) << 4) | (bb[13] >> 4)) + 1;
                Data.TotalSamples   = ((bb[13] & 0x0F) << 32) | bb[14] << 24 | bb[15] << 16 | bb[16] << 8 | bb[17];

                Data.mHdr = bb;
                Data.storedAudioDataMD5 = new byte[16];
                Array.Copy(bb, 18, Data.storedAudioDataMD5, 0, 16);

                Data.ValidSize += Data.MetadataBlockStreamInfoSize;

                for (;;)
                {
                    bb = new byte[12];
                    try
                    {
                        Data.fbs.Position = Data.ValidSize;
                    }
                    catch (EndOfStreamException)
                    {
                        IssueModel.Add("File truncated near meta data", Severity.Fatal);
                        return;
                    }

                    Data.fbs.Position = Data.ValidSize;
                    got = Data.fbs.Read(bb, 0, 4);
                    if (got != 4)
                    {
                        IssueModel.Add("File truncated near meta data", Severity.Fatal);
                        return;
                    }

                    var blockSize = ConvertTo.FromBig24ToInt32(bb, 1);
                    Data.ValidSize += 4;

                    switch ((FlacBlockType)(bb[0] & 0x7F))
                    {
                    case FlacBlockType.Padding:
                        Data.Blocks.AddPad(blockSize);
                        break;

                    case FlacBlockType.Application:
                        got = Data.fbs.Read(bb, 0, 4);
                        if (got != 4)
                        {
                            IssueModel.Add("File truncated near tags", Severity.Fatal);
                            return;
                        }
                        int appId = ConvertTo.FromBig32ToInt32(bb, 0);
                        Data.Blocks.AddApp(blockSize, appId);
                        break;

                    case FlacBlockType.SeekTable:
                        var st = new byte[blockSize];
                        got = Data.fbs.Read(st, 0, blockSize);
                        if (got != blockSize)
                        {
                            IssueModel.Add("File truncated near seek table", Severity.Fatal);
                            return;
                        }
                        Data.Blocks.AddSeekTable(blockSize, st);
                        break;

                    case FlacBlockType.Tags:
                        bb = new byte[blockSize];
                        Data.fbs.Position = Data.ValidSize;
                        got = Data.fbs.Read(bb, 0, blockSize);
                        if (got != blockSize)
                        {
                            IssueModel.Add("File truncated near tags", Severity.Fatal);
                            return;
                        }
                        if (Data.Blocks.Tags != null)
                        {
                            IssueModel.Add("Contains multiple tag blocks", Severity.Error);
                        }
                        else
                        {
                            Data.Blocks.AddTags(blockSize, bb);
                        }
                        break;

                    case FlacBlockType.CueSheet:
                        var sb = new byte[284];
                        got = Data.fbs.Read(sb, 0, 284);
                        if (got != 284)
                        {
                            IssueModel.Add("File truncated near cuesheet", Severity.Fatal);
                            return;
                        }
                        var isCD       = (sb[24] & 0x80) != 0;
                        int trackCount = sb[283];
                        Data.Blocks.AddCuesheet(blockSize, isCD, trackCount);
                        break;

                    case FlacBlockType.Picture:
                        var pb = new byte[blockSize];
                        got = Data.fbs.Read(pb, 0, blockSize);
                        if (got != blockSize)
                        {
                            IssueModel.Add("File truncated near picture", Severity.Fatal);
                            return;
                        }
                        var picType = (PicType)ConvertTo.FromBig32ToInt32(pb, 0);
                        var mimeLen = ConvertTo.FromBig32ToInt32(pb, 4);
                        var mime    = Encoding.UTF8.GetString(pb, 8, mimeLen);
                        var descLen = ConvertTo.FromBig32ToInt32(pb, mimeLen + 8);
                        var desc    = Encoding.UTF8.GetString(pb, mimeLen + 12, descLen);
                        var width   = ConvertTo.FromBig32ToInt32(pb, mimeLen + descLen + 12);
                        var height  = ConvertTo.FromBig32ToInt32(pb, mimeLen + descLen + 16);
                        Data.Blocks.AddPic(blockSize, picType, width, height);
                        break;

                    default:
                        IssueModel.Add("Encountered unexpected metadata block type of " + (bb[0] & 0x7F), Severity.Fatal);
                        return;
                    }

                    Data.ValidSize += blockSize;
                    if ((bb[0] & 0x80) != 0)
                    {
                        break;
                    }
                }

                try
                {
                    Data.fbs.Position = Data.ValidSize;
                }
                catch (EndOfStreamException)
                {
                    IssueModel.Add("File truncated near frame header", Severity.Fatal);
                    return;
                }
                got = Data.fbs.Read(bb, 0, 4);
                if (got != 4)
                {
                    IssueModel.Add("File truncated", Severity.Fatal);
                    return;
                }

                // Detect frame header sync code
                if (bb[0] != 0xFF || (bb[1] & 0xFC) != 0xF8)
                {
                    IssueModel.Add("Audio data not found", Severity.Fatal);
                    return;
                }

                Data.mediaPosition = Data.ValidSize;

                Data.SampleOrFrameNumber = Data.fbs.ReadWobbly(out byte[] wtfBuf);
                if (Data.SampleOrFrameNumber < 0)
                {
                    IssueModel.Add("File truncated or badly formed sample/frame number.", Severity.Fatal);
                    return;
                }
                Array.Copy(wtfBuf, 0, bb, 4, wtfBuf.Length);
                int bPos = 4 + wtfBuf.Length;

                Data.RawBlockingStrategy = bb[1] & 1;

                Data.RawBlockSize = bb[2] >> 4;
                if (Data.RawBlockSize == 0)
                {
                    Data.BlockSize = 0;
                }
                else if (Data.RawBlockSize == 1)
                {
                    Data.BlockSize = 192;
                }
                else if (Data.RawBlockSize >= 2 && Data.RawBlockSize <= 5)
                {
                    Data.BlockSize = 576 * (1 << (Data.RawBlockSize - 2));
                }
                else if (Data.RawBlockSize == 6)
                {
                    got            = Data.fbs.Read(bb, bPos, 1);
                    Data.BlockSize = bb[bPos] + 1;
                    bPos          += 1;
                }
                else if (Data.RawBlockSize == 7)
                {
                    got            = Data.fbs.Read(bb, bPos, 2);
                    Data.BlockSize = (bb[bPos] << 8) + bb[bPos + 1] + 1;
                    bPos          += 2;
                }
                else
                {
                    Data.BlockSize = 256 * (1 << (Data.RawBlockSize - 8));
                }


                Data.RawSampleRate = bb[2] & 0xF;
                if (Data.RawSampleRate == 0xC)
                {
                    got = Data.fbs.Read(bb, bPos, 1);
                    Data.SampleRateText = bb[bPos] + "kHz";
                    bPos += 1;
                }
                else if (Data.RawSampleRate == 0xD || Data.RawSampleRate == 0xE)
                {
                    got = Data.fbs.Read(bb, bPos, 2);
                    Data.SampleRateText = (bb[bPos] << 8).ToString() + bb[bPos + 1] + (Data.RawSampleRate == 0xD? " Hz" : " kHz");
                    bPos += 2;
                }
                else if (Data.RawSampleRate == 0)
                {
                    Data.SampleRateText = Data.MetaSampleRate.ToString() + " Hz";
                }
                else
                {
                    Data.SampleRateText = SampleRateMap[Data.RawSampleRate];
                }

                Data.RawChannelAssignment = bb[3] >> 4;

                Data.RawSampleSize = (bb[3] & 0xE) >> 1;
                if (Data.RawSampleSize == 0)
                {
                    Data.SampleSizeText = Data.BitsPerSample.ToString() + " bits";
                }
                else
                {
                    Data.SampleSizeText = SampleSizeMap[Data.RawSampleSize];
                }

                Data.aHdr = new byte[bPos];
                Array.Copy(bb, Data.aHdr, bPos);

                Data.ValidSize   += bPos;
                Data.fbs.Position = Data.ValidSize;
                int octet = Data.fbs.ReadByte();

                if (octet < 0)
                {
                    IssueModel.Add("File truncated near CRC-8", Severity.Fatal);
                    return;
                }
                Data.StoredAudioHeaderCRC8 = (Byte)octet;

                try
                {
                    Data.fbs.Position = Data.mediaPosition;
                }
                catch (EndOfStreamException)
                {
                    IssueModel.Add("File truncated near audio data", Severity.Fatal);
                    return;
                }

                try
                {
                    Data.fbs.Position = Data.FileSize - 2;
                }
                catch (EndOfStreamException)
                {
                    IssueModel.Add("File truncated looking for end", Severity.Fatal);
                    return;
                }

                bb = new byte[2];
                if (Data.fbs.Read(bb, 0, 2) != 2)
                {
                    IssueModel.Add("Read failed on audio block CRC-16", Severity.Fatal);
                    return;
                }

                Data.StoredAudioBlockCRC16 = (UInt16)(bb[0] << 8 | bb[1]);
                Data.MediaCount            = Data.FileSize - Data.mediaPosition;

                GetDiagnostics();
            }