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); } }
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); }
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}'."); } }
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; } }
public Mp3Header(byte[] hdr, int ix) { Bits = ConvertTo.FromBig32ToInt32(hdr, ix); }
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(); }