Exemplo n.º 1
0
        static byte[] get_TTF_digest(OTFile f)
        {
            OTFont         fn     = f.GetFont(0);
            Table_DSIG     tDSIG  = (Table_DSIG)fn.GetTable("DSIG");
            DirectoryEntry deDSIG = null;
            // sort table by offset
            Dictionary <uint, int> offsetlookup = new Dictionary <uint, int>();
            var list = new List <uint>();

            for (ushort i = 0; i < fn.GetNumTables(); i++)
            {
                DirectoryEntry de = fn.GetDirectoryEntry(i);
                offsetlookup.Add(de.offset, i);
                list.Add(de.offset);
                if ((string)de.tag == "DSIG")
                {
                    deDSIG = de;
                }
            }
            list.Sort();

            // New offset table
            var         old_ot = fn.GetOffsetTable();
            OffsetTable ot     = new OffsetTable(old_ot.sfntVersion, (ushort)(old_ot.numTables - 1));

            for (ushort i = 0; i < fn.GetNumTables(); i++)
            {
                DirectoryEntry oldde = fn.GetDirectoryEntry(i);
                if ((string)oldde.tag != "DSIG")
                {
                    DirectoryEntry de = new DirectoryEntry(oldde);
                    de.offset -= 16; // one less entry
                    if (de.offset > deDSIG.offset)
                    {
                        de.offset -= tDSIG.GetBuffer().GetPaddedLength();
                    }
                    ot.DirectoryEntries.Add(de);
                }
            }
            hash.TransformBlock(ot.m_buf.GetBuffer(), 0, (int)ot.m_buf.GetLength(), ot.m_buf.GetBuffer(), 0);

            for (int i = 0; i < ot.DirectoryEntries.Count; i++)
            {
                DirectoryEntry de = (DirectoryEntry)ot.DirectoryEntries[i];
                hash.TransformBlock(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength(), de.m_buf.GetBuffer(), 0);
            }

            Table_head headTable = (Table_head)fn.GetTable("head");

            // calculate the checksum
            uint sum = 0;

            sum += ot.CalcOffsetTableChecksum();
            sum += ot.CalcDirectoryEntriesChecksum();
            foreach (var key in list)
            {
                OTTable table = fn.GetTable((ushort)offsetlookup[key]);

                if ((string)table.GetTag() != "DSIG")
                {
                    sum += table.CalcChecksum();
                }
            }

            Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache();

            // set the checkSumAdujustment field
            headCache.checkSumAdjustment = 0xb1b0afba - sum;
            Table_head newHead = (Table_head)headCache.GenerateTable();

            foreach (var key in list)
            {
                OTTable table = fn.GetTable((ushort)offsetlookup[key]);

                if ((string)table.GetTag() == "head")
                {
                    table = newHead;
                }

                if ((string)table.GetTag() != "DSIG")
                {
                    hash.TransformBlock(table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength(),
                                        table.m_bufTable.GetBuffer(), 0);
                }
            }

            byte[] usFlag = { 0, 1 };
            hash.TransformFinalBlock(usFlag, 0, 2);
            return(hash.Hash);
        }
Exemplo n.º 2
0
        /*****************
         * protected methods
         */

        /*****************
         * public methods
         */

        //meant to avoid code repetition (is called from OTFontVal too)
        public bool ValidateTable(OTTable table, Validator v, DirectoryEntry de, OTFontVal fontOwner)
        {
            String tname = GetTableManager().GetUnaliasedTableName(de.tag);
            bool   bRet  = true;

            // verify the checksum value from the directory entry matches the checksum for the table
            if (!(tname == "DSIG" && IsCollection()))
            {
                uint calcChecksum = 0;
                if (table != null)
                {
                    calcChecksum = table.CalcChecksum();
                }

                if (de.checkSum != calcChecksum)
                {
                    string s = "table '" + de.tag + "', calc: 0x" + calcChecksum.ToString("x8") + ", font: 0x" + de.checkSum.ToString("x8");
                    v.Error(T.T_NULL, E._DE_E_ChecksumError, de.tag, s);
                    bRet = false;
                }
            }

            // verify that table has pad bytes set to zero
            if (table != null)
            {
                uint nBytes = 0;
                try {
                    nBytes = GetNumPadBytesAfterTable(table);
                }
                catch (Exception e)
                {
                    v.ApplicationError(T.T_NULL, E._Table_E_Exception, de.tag, "GetNumPadBytesAfterTable: " + e.Message);
                    bRet = false;
                }

                bool bPadBytesZero = true;

                if (nBytes != 0)
                {
                    long   PadFilePos = table.GetBuffer().GetFilePos() + table.GetBuffer().GetLength();
                    byte[] padbuf     = ReadBytes(PadFilePos, nBytes);
                    for (int iByte = 0; iByte < padbuf.Length; iByte++)
                    {
                        if (padbuf[iByte] != 0)
                        {
                            bPadBytesZero = false;
                            break;
                        }
                    }
                }

                if (bPadBytesZero == false)
                {
                    v.Warning(T.T_NULL, W._DE_W_PadBytesNotZero, de.tag, "after " + de.tag + " table");
                }
            }

            // ask the table object to validate its data
            if (!(tname == "DSIG" && IsCollection()))
            {
                v.OnTableValidationEvent(de, true);
            }
            if (table != null)
            {
                if (v.TestTable(de.tag)) // don't test deselected tables
                {
                    try
                    {
                        ITableValidate valtable = (ITableValidate)table;
                        bRet &= valtable.Validate(v, fontOwner);
                    }
                    catch (InvalidCastException e)
                    {
                        v.ApplicationError(T.T_NULL, E._Table_E_Exception, table.m_tag, e.ToString());
                        bRet = false;
                    }
                }
                else
                {
                    v.Info(I._Table_I_NotSelected, de.tag);
                }
            }
            else
            {
                if (de.length == 0)
                {
                    // check if it's a known OT table type since zero length private tables seem allowable
                    if (TableManager.IsKnownOTTableType(de.tag))
                    {
                        v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The directory entry length is zero");
                        bRet = false;
                    }
                }
                else if (de.offset == 0)
                {
                    v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The directory entry offset is zero");
                    bRet = false;
                }
                else if (de.offset > GetFileLength())
                {
                    v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The table offset points past end of file");
                    bRet = false;
                }
                else if (de.offset + de.length > GetFileLength())
                {
                    v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The table extends past end of file");
                    bRet = false;
                }
                else
                {
                    v.Error(E._Table_E_Invalid, de.tag);
                    bRet = false;
                }
            }
            if (!(tname == "DSIG" && IsCollection()))
            {
                v.OnTableValidationEvent(de, false);
            }

            return(bRet);
        }
Exemplo n.º 3
0
        static byte[] get_TTC_digest(OTFile f)
        {
            TTCHeader ttc = f.GetTTCHeader();

            uint back_shift = 12;

            //if ( ttc.version == 0x00020000 )
            back_shift = 0;

            TTCHBuffer ttcb = new TTCHBuffer(12 + ttc.DirectoryCount * 4 + 12 - back_shift);

            // write the TTC header
            ttcb.FillUint32MBO((uint)ttc.TTCTag);
            ttcb.FillUint32MBO(ttc.version);
            ttcb.FillUint32MBO(ttc.DirectoryCount);

            for (int i = 0; i < f.GetNumFonts(); i++)
            {
                ttcb.FillUint32MBO((uint)ttc.DirectoryOffsets[i] - back_shift);
            }
            //if ( ttc.version == 0x00020000 )
            {
                ttcb.FillUint32MBO(0);
                ttcb.FillUint32MBO(0);
                ttcb.FillUint32MBO(0);
            }
            uint Position = (uint)ttcb.buffer.Length;

            hash.TransformBlock(ttcb.buffer, 0, ttcb.buffer.Length, ttcb.buffer, 0);

            // build an array of offset tables
            OffsetTable[] otArr = new OffsetTable[f.GetNumFonts()];
            for (uint iFont = 0; iFont < f.GetNumFonts(); iFont++)
            {
                otArr[iFont] = new OffsetTable(new OTFixed(1, 0), f.GetFont(iFont).GetNumTables());

                for (ushort i = 0; i < f.GetFont(iFont).GetNumTables(); i++)
                {
                    DirectoryEntry old = f.GetFont(iFont).GetDirectoryEntry(i);
                    DirectoryEntry de  = new DirectoryEntry(old);
                    de.offset -= back_shift;
                    otArr[iFont].DirectoryEntries.Add(de);
                }
            }

            if ((uint)ttc.DirectoryOffsets[(int)f.GetNumFonts() - 1] < f.GetFont(0).GetDirectoryEntry(0).offset)
            {
                // assume directory-contiguous
                for (uint iFont = 0; iFont < f.GetNumFonts(); iFont++)
                {
                    // write the offset table
                    hash.TransformBlock(otArr[iFont].m_buf.GetBuffer(), 0, (int)otArr[iFont].m_buf.GetLength(),
                                        otArr[iFont].m_buf.GetBuffer(), 0);
                    Position += otArr[iFont].m_buf.GetLength();

                    // write the directory entries
                    for (int i = 0; i < f.GetFont(iFont).GetNumTables(); i++)
                    {
                        DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i];
                        hash.TransformBlock(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength(),
                                            de.m_buf.GetBuffer(), 0);
                        Position += de.m_buf.GetLength();
                    }
                }
            }

            // write out each font
            uint max_offset        = 0;
            uint max_padded_length = 0;
            uint PrevPos           = 0;

            for (uint iFont = 0; iFont < f.GetNumFonts(); iFont++)
            {
                ushort numTables = f.GetFont(iFont).GetNumTables();

                if ((uint)ttc.DirectoryOffsets[(int)f.GetNumFonts() - 1] > f.GetFont(0).GetDirectoryEntry(0).offset)
                {
                    // assume font-contiguous
                    // write the offset table
                    hash.TransformBlock(otArr[iFont].m_buf.GetBuffer(), 0, (int)otArr[iFont].m_buf.GetLength(),
                                        otArr[iFont].m_buf.GetBuffer(), 0);
                    Position += otArr[iFont].m_buf.GetLength();

                    // write the directory entries
                    for (int i = 0; i < numTables; i++)
                    {
                        DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i];
                        hash.TransformBlock(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength(),
                                            de.m_buf.GetBuffer(), 0);
                        Position += de.m_buf.GetLength();
                    }
                }

                // write out each table unless a shared version has been written
                for (ushort i = 0; i < numTables; i++)
                {
                    DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i];
                    if (de.offset > max_offset)
                    {
                        max_offset        = de.offset;
                        max_padded_length = f.GetFont(iFont).GetTable(de.tag).GetBuffer().GetPaddedLength();
                    }
                    if (PrevPos < de.offset) //crude
                    {
                        OTTable table = f.GetFont(iFont).GetTable(de.tag);
                        hash.TransformBlock(table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength(),
                                            table.m_bufTable.GetBuffer(), 0);
                        Position += table.GetBuffer().GetPaddedLength();
                        PrevPos   = de.offset;
                    }
                }
            }

            if (max_offset + max_padded_length - Position != 0)
            {
                throw new NotImplementedException("Unusual TTC Directory Layout");
            }
            byte[] usFlag = { 0, 1 };
            hash.TransformFinalBlock(usFlag, 0, 2);
            return(hash.Hash);
        }