예제 #1
0
            EbmlNodeMaster ParseTree(EbmlSig element)
            {
                string err           = null;
                var    contentLenBuf = ReadMTF(Data.fbs, out long contentLen);

                if (contentLen < 0)
                {
                    return(null);
                }
                Data.ValidSize += contentLenBuf.Length;

                var  newMaster = new EbmlNodeMaster(element, contentLenBuf.Length + contentLen);
                var  buf       = new byte[3];
                long stop      = Data.ValidSize + contentLen;

                while (Data.ValidSize < stop)
                {
                    Data.fbs.Position = Data.ValidSize;
                    var got = Data.fbs.Read(buf, 0, 3);
                    if (got < 3)
                    {
                        err = "File corrupt or truncated"; goto FATAL;
                    }

                    EbmlNode newNode;

                    foreach (var item in masterSigs)
                    {
                        if (item.SigIsStartOf(buf))
                        {
                            Data.fbs.Position = Data.ValidSize = Data.ValidSize + item.Signature.Count;
                            newNode           = ParseTree(item);
                            if (IssueModel.Data.HasFatal)
                            {
                                if (newNode != null)
                                {
                                    newMaster.AddNode(newNode);
                                }
                                return(newMaster);
                            }
                            goto NEXT;
                        }
                    }

                    foreach (var item in leafSigs)
                    {
                        if (item.SigIsStartOf(buf))
                        {
                            Data.fbs.Position = Data.ValidSize = Data.ValidSize + item.Signature.Count;

                            byte[] payload    = null;
                            byte[] payloadHdr = ReadMTF(Data.fbs, out long payloadLen);
                            if (payloadHdr == null)
                            {
                                err = "File truncated or corrupt"; goto FATAL;
                            }

                            if ((item.Flag & ParseFlag.Persist) != 0)
                            {
                                payload = new byte[payloadLen];
                                got     = Data.fbs.Read(payload, 0, (int)payloadLen);
                            }

                            if (buf[0] != CrcSig.Sig32)
                            {
                                newNode = new EbmlNodeLeaf(item, payload);
                            }
                            else
                            {
                                ++Data.CrcCount;
                                long hashStart = Data.ValidSize + payloadHdr.Length + payloadLen;
                                long hashCount;
                                if (newMaster.Nodes.Count == 0)
                                {
                                    hashCount = contentLen - 5 - payloadHdr.Length;
                                }
                                else
                                {
                                    IssueModel.Add("Misplaced CRC");
                                    hashCount = 0;
                                }
                                newNode = new EbmlNodeCRC(item, payload, hashStart, hashCount);
                            }

                            Data.ValidSize += payloadHdr.Length + payloadLen;
                            goto NEXT;
                        }
                    }
                    err = $"Unknown element [{buf[0]:X2}][{buf[1]:X2}][{buf[2]:X2}]";
                    goto FATAL;
NEXT:
                    newMaster.AddNode(newNode);
                }
                if (Data.ValidSize == stop)
                {
                    return(newMaster);
                }

                err = "Positional error";
FATAL:
                err += String.Format(" at {0:X}.", Data.ValidSize);
                IssueModel.Add(err, Severity.Fatal);
                return(newMaster);
            }
예제 #2
0
            public Model(Stream stream, string path)
            {
                base._data = Data = new MkvFormat(this, stream, path);
                var bb = new byte[5];

                Data.fbs.Position = Data.ValidSize = 4;

                Data.root = ParseTree(rootSig);
                Data.layout.Add(Data.root);

                if (Data.Issues.HasError)
                {
                    return;
                }

                System.Diagnostics.Debug.Assert(Data.ValidSize == Data.fbs.Position);

                Data.fbs.Position = Data.ValidSize;
                long SegmentLength = ReadMTF(0x18, 0x53, 0x80, 0x67);

                if (SegmentLength < 0)
                {
                    IssueModel.Add("Missing root element.", Severity.Fatal); return;
                }

                System.Diagnostics.Debug.Assert(Data.ValidSize == Data.fbs.Position);

                long segmentStart = Data.ValidSize;

                var diff = Data.ValidSize + SegmentLength - Data.FileSize;

                if (diff > 0)
                {
                    IssueModel.Add($"File appears truncated by {diff} bytes.", Severity.Error);
                }

                Data.segment = new EbmlNodeMaster(segmentSig, SegmentLength);
                Data.layout.Add(Data.segment);

                Data.fbs.Position = Data.ValidSize;

                while (Data.ValidSize < segmentStart + SegmentLength)
                {
                    Data.fbs.Position = Data.ValidSize;
                    int got = Data.fbs.Read(bb, 0, 4);
                    if (got < 3)
                    {
                        break;
                    }

                    if (bb[0] == voidSig.Sig32)
                    {
                        Data.fbs.Position = Data.ValidSize + 1;
                        var voidLenBuf = ReadMTF(Data.fbs, out long voidLen);
                        if (voidLen < 0)
                        {
                            IssueModel.Add("File truncated near void.", Severity.Fatal); return;
                        }

                        Data.ValidSize += 1 + voidLenBuf.Length + voidLen;
                        var voidNode = new EbmlNodeLeaf(voidSig, voidLen);
                        Data.segment.AddNode(voidNode);
                        continue;
                    }

                    if (got < 4)
                    {
                        break;
                    }

                    foreach (var mstr in topSigs)
                    {
                        if (mstr.SigIsStartOf(bb))
                        {
                            Data.fbs.Position = Data.ValidSize = Data.ValidSize + 4;

                            if ((mstr.Flag & ParseFlag.PrunePayload) != 0)
                            {
                                var payloadLenBuf = ReadMTF(Data.fbs, out long payloadLen);
                                if (payloadLen < 0)
                                {
                                    IssueModel.Add("File corrupt or truncated.", Severity.Fatal); return;
                                }

                                Data.ValidSize += payloadLenBuf.Length + payloadLen;
                                Data.segment.AddMaster(mstr, payloadLenBuf.Length + payloadLen);
                            }
                            else
                            {
                                var newNode = ParseTree(mstr);
                                if (IssueModel.Data.HasFatal)
                                {
                                    if (newNode != null)
                                    {
                                        Data.segment.AddNode(newNode);
                                    }
                                    return;
                                }
                                Data.segment.AddNode(newNode);
                            }
                            goto NEXT_SEG;
                        }
                    }

                    string msg = $"Parse fail at 0x{Data.ValidSize:X} on [{bb[0]:X2}][{bb[1]:X2}][{bb[2]:X2}][{bb[3]:X2}].";
                    IssueModel.Add(msg, Severity.Fatal);
                    return;

                    NEXT_SEG :;
                }

                Data.fbs.Position = Data.ValidSize;
                var got2 = Data.fbs.Read(bb, 0, 4);

                if (got2 == 4 && attachSig.SigIsStartOf(bb))
                {
                    // By spec, everything should be within a single Segment.
                    Data.HasMisplacedAttachment = true;
                    IssueModel.Add($"Misplaced attachment at {Data.ValidSize:X}", Severity.Warning);
                }

                Data.fbs.Position = Data.ValidSize;
                CalcMark(true);
                return;
            }