2018-12-13 13:02:42 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Classes\Parser;
|
|
|
|
|
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
|
|
|
|
use App\Classes\FrameFields;
|
|
|
|
use App\Classes\Parser as AbstractParser;
|
|
|
|
use App\Classes\Frame\Ansi as AnsiFrame;
|
|
|
|
|
|
|
|
class Ansi extends AbstractParser {
|
|
|
|
/**
|
|
|
|
* Parse a string and look for the next character that is not $char
|
|
|
|
*
|
|
|
|
* @param string $char
|
|
|
|
* @param int $start
|
|
|
|
* @return bool|int
|
|
|
|
*/
|
2019-07-12 03:42:01 +00:00
|
|
|
private function findEOF(string $char,int $start,string $content)
|
2018-12-13 13:02:42 +00:00
|
|
|
{
|
2019-07-12 03:42:01 +00:00
|
|
|
for ($c=$start;$c <= strlen($content);$c++)
|
2018-12-13 13:02:42 +00:00
|
|
|
{
|
2019-07-12 03:42:01 +00:00
|
|
|
if ($content{$c} != $char)
|
2018-12-13 13:02:42 +00:00
|
|
|
return $c-$start;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $startline
|
|
|
|
* @param int $offset
|
|
|
|
* @return string
|
|
|
|
*/
|
2019-07-12 03:42:01 +00:00
|
|
|
protected function parse(int $startline,string $content,int $width): string
|
2018-12-13 13:02:42 +00:00
|
|
|
{
|
|
|
|
// Our starting coordinates
|
|
|
|
$x = 1;
|
|
|
|
$y = $startline;
|
|
|
|
$output = '';
|
|
|
|
|
2019-07-31 12:19:41 +00:00
|
|
|
// Default Attributes
|
|
|
|
$f = 39;
|
|
|
|
$b = 49;
|
|
|
|
$i = 0;
|
|
|
|
|
2018-12-13 13:02:42 +00:00
|
|
|
// Scan the frame for a field start
|
2019-07-12 03:42:01 +00:00
|
|
|
for ($c=0; $c<=strlen($content); $c++)
|
2018-12-13 13:02:42 +00:00
|
|
|
{
|
|
|
|
// If the frame is not big enough, fill it with spaces.
|
2019-07-12 03:42:01 +00:00
|
|
|
$byte = isset($content{$c}) ? $content{$c} : ' ';
|
2018-12-13 13:02:42 +00:00
|
|
|
$advance = 0;
|
|
|
|
|
|
|
|
switch ($byte) {
|
|
|
|
case CR:
|
|
|
|
$x = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LF:
|
|
|
|
$y++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ESC:
|
|
|
|
$advance = 1;
|
|
|
|
// Is the next byte something we know about
|
2019-07-12 03:42:01 +00:00
|
|
|
$nextbyte = isset($content{$c+$advance}) ? $content{$c+$advance} : ' ';
|
2018-12-13 13:02:42 +00:00
|
|
|
|
|
|
|
switch ($nextbyte) {
|
|
|
|
case '[':
|
|
|
|
$advance++;
|
|
|
|
$chars = $nextbyte;
|
|
|
|
|
|
|
|
// Find our end CSI param
|
|
|
|
$matches = [];
|
|
|
|
|
2019-07-12 03:42:01 +00:00
|
|
|
$a = preg_match('/([0-9]+[;]?)+([a-zA-Z])/',$content,$matches,NULL,$c+$advance);
|
2018-12-13 13:02:42 +00:00
|
|
|
|
|
|
|
if (! $a)
|
|
|
|
break;
|
|
|
|
|
|
|
|
$advance += strlen($matches[0])-1;
|
|
|
|
$chars .= $matches[0];
|
|
|
|
|
|
|
|
switch ($matches[2]) {
|
2019-07-31 12:19:41 +00:00
|
|
|
// Color CSIs
|
|
|
|
case 'm':
|
|
|
|
foreach (explode(';',chop($matches[0],'m')) as $num)
|
|
|
|
{
|
|
|
|
if ($num >= 0 AND $num <= 8)
|
|
|
|
{
|
|
|
|
$i = $num;
|
|
|
|
$f = 39;
|
|
|
|
$b = 49;
|
|
|
|
} elseif ($num >= 30 AND $num <= 39)
|
|
|
|
$f = $num;
|
|
|
|
|
|
|
|
elseif ($num >= 40 AND $num <= 49)
|
|
|
|
$b = $num;
|
|
|
|
}
|
|
|
|
break;
|
2018-12-13 13:02:42 +00:00
|
|
|
|
2019-07-31 12:19:41 +00:00
|
|
|
// Advance characters
|
2018-12-13 13:02:42 +00:00
|
|
|
case 'C':
|
|
|
|
$x += $matches[1]; // Advance our position
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
dump('Unhandled CSI: '.$matches[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ' ':
|
|
|
|
dump(['l'=>__LINE__,'LOOSE ESC?']);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2019-07-12 03:42:01 +00:00
|
|
|
// Allow for the original ESC
|
|
|
|
$c--;
|
2018-12-13 13:02:42 +00:00
|
|
|
$advance++;
|
2019-07-12 03:42:01 +00:00
|
|
|
$fieldtype = ord($nextbyte);
|
|
|
|
$fieldlength = $this->findEOF(chr($fieldtype),$c+2,$content)+1;
|
2018-12-13 13:02:42 +00:00
|
|
|
|
|
|
|
$byte = '';
|
|
|
|
|
|
|
|
$this->fields->push(new FrameFields([
|
|
|
|
'type'=>chr($fieldtype),
|
|
|
|
'length'=>$fieldlength,
|
|
|
|
'x'=>$x, // Adjust for the ESC char
|
|
|
|
'y'=>$y,
|
|
|
|
]));
|
|
|
|
|
|
|
|
Log::debug(sprintf('Field found at [%s,%s], Type: %s, Length: %s',$x-1,$y,$fieldtype,$fieldlength));
|
|
|
|
$advance += $fieldlength-2;
|
|
|
|
$x += $fieldlength;
|
|
|
|
$chars = $this->fields->last()->output(AnsiFrame::$if_filler);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2019-07-31 12:19:41 +00:00
|
|
|
$this->frame_data[$y][$x] = ['i'=>$i,'f'=>$f,'b'=>$b];
|
|
|
|
$this->frame_content[$y][$x] = $byte;
|
2018-12-13 13:02:42 +00:00
|
|
|
$x++;
|
|
|
|
}
|
|
|
|
|
|
|
|
$output .= $byte;
|
|
|
|
|
|
|
|
if ($advance) {
|
|
|
|
$output .= $chars;
|
|
|
|
$c += $advance;
|
|
|
|
}
|
|
|
|
|
2019-07-12 03:42:01 +00:00
|
|
|
if ($x > $width) {
|
2018-12-13 13:02:42 +00:00
|
|
|
$x = 1;
|
|
|
|
$y++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
}
|