ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
ANSI.php
Go to the documentation of this file.
1 <?php
2 
21 namespace phpseclib\File;
22 
30 class ANSI
31 {
38  var $max_x;
39 
46  var $max_y;
47 
55 
62  var $history;
63 
71 
78  var $x;
79 
86  var $y;
87 
94  var $old_x;
95 
102  var $old_y;
103 
111 
119 
127 
134  var $screen;
135 
142  var $attrs;
143 
150  var $ansi;
151 
159 
166  function __construct()
167  {
168  $attr_cell = new \stdClass();
169  $attr_cell->bold = false;
170  $attr_cell->underline = false;
171  $attr_cell->blink = false;
172  $attr_cell->background = 'black';
173  $attr_cell->foreground = 'white';
174  $attr_cell->reverse = false;
175  $this->base_attr_cell = clone $attr_cell;
176  $this->attr_cell = clone $attr_cell;
177 
178  $this->setHistory(200);
179  $this->setDimensions(80, 24);
180  }
181 
191  function setDimensions($x, $y)
192  {
193  $this->max_x = $x - 1;
194  $this->max_y = $y - 1;
195  $this->x = $this->y = 0;
196  $this->history = $this->history_attrs = array();
197  $this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell);
198  $this->screen = array_fill(0, $this->max_y + 1, '');
199  $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row);
200  $this->ansi = '';
201  }
202 
210  function setHistory($history)
211  {
212  $this->max_history = $history;
213  }
214 
221  function loadString($source)
222  {
223  $this->setDimensions($this->max_x + 1, $this->max_y + 1);
224  $this->appendString($source);
225  }
226 
234  {
235  $this->tokenization = array('');
236  for ($i = 0; $i < strlen($source); $i++) {
237  if (strlen($this->ansi)) {
238  $this->ansi.= $source[$i];
239  $chr = ord($source[$i]);
240  // http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements
241  // single character CSI's not currently supported
242  switch (true) {
243  case $this->ansi == "\x1B=":
244  $this->ansi = '';
245  continue 2;
246  case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['):
247  case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126:
248  break;
249  default:
250  continue 2;
251  }
252  $this->tokenization[] = $this->ansi;
253  $this->tokenization[] = '';
254  // http://ascii-table.com/ansi-escape-sequences-vt-100.php
255  switch ($this->ansi) {
256  case "\x1B[H": // Move cursor to upper left corner
257  $this->old_x = $this->x;
258  $this->old_y = $this->y;
259  $this->x = $this->y = 0;
260  break;
261  case "\x1B[J": // Clear screen from cursor down
262  $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y));
263  $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, ''));
264 
265  $this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y));
266  $this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row));
267 
268  if (count($this->history) == $this->max_history) {
269  array_shift($this->history);
270  array_shift($this->history_attrs);
271  }
272  case "\x1B[K": // Clear screen from cursor right
273  $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x);
274 
275  array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell));
276  break;
277  case "\x1B[2K": // Clear entire line
278  $this->screen[$this->y] = str_repeat(' ', $this->x);
279  $this->attrs[$this->y] = $this->attr_row;
280  break;
281  case "\x1B[?1h": // set cursor key to application
282  case "\x1B[?25h": // show the cursor
283  case "\x1B(B": // set united states g0 character set
284  break;
285  case "\x1BE": // Move to next line
286  $this->_newLine();
287  $this->x = 0;
288  break;
289  default:
290  switch (true) {
291  case preg_match('#\x1B\[(\d+)B#', $this->ansi, $match): // Move cursor down n lines
292  $this->old_y = $this->y;
293  $this->y+= $match[1];
294  break;
295  case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h
296  $this->old_x = $this->x;
297  $this->old_y = $this->y;
298  $this->x = $match[2] - 1;
299  $this->y = $match[1] - 1;
300  break;
301  case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines
302  $this->old_x = $this->x;
303  $this->x+= $match[1];
304  break;
305  case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines
306  $this->old_x = $this->x;
307  $this->x-= $match[1];
308  break;
309  case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
310  break;
311  case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes
312  $attr_cell = &$this->attr_cell;
313  $mods = explode(';', $match[1]);
314  foreach ($mods as $mod) {
315  switch ($mod) {
316  case 0: // Turn off character attributes
317  $attr_cell = clone $this->base_attr_cell;
318  break;
319  case 1: // Turn bold mode on
320  $attr_cell->bold = true;
321  break;
322  case 4: // Turn underline mode on
323  $attr_cell->underline = true;
324  break;
325  case 5: // Turn blinking mode on
326  $attr_cell->blink = true;
327  break;
328  case 7: // Turn reverse video on
329  $attr_cell->reverse = !$attr_cell->reverse;
330  $temp = $attr_cell->background;
331  $attr_cell->background = $attr_cell->foreground;
332  $attr_cell->foreground = $temp;
333  break;
334  default: // set colors
335  //$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground;
336  $front = &$attr_cell->{ $attr_cell->reverse ? 'background' : 'foreground' };
337  //$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background;
338  $back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' };
339  switch ($mod) {
340  // @codingStandardsIgnoreStart
341  case 30: $front = 'black'; break;
342  case 31: $front = 'red'; break;
343  case 32: $front = 'green'; break;
344  case 33: $front = 'yellow'; break;
345  case 34: $front = 'blue'; break;
346  case 35: $front = 'magenta'; break;
347  case 36: $front = 'cyan'; break;
348  case 37: $front = 'white'; break;
349 
350  case 40: $back = 'black'; break;
351  case 41: $back = 'red'; break;
352  case 42: $back = 'green'; break;
353  case 43: $back = 'yellow'; break;
354  case 44: $back = 'blue'; break;
355  case 45: $back = 'magenta'; break;
356  case 46: $back = 'cyan'; break;
357  case 47: $back = 'white'; break;
358  // @codingStandardsIgnoreEnd
359 
360  default:
361  //user_error('Unsupported attribute: ' . $mod);
362  $this->ansi = '';
363  break 2;
364  }
365  }
366  }
367  break;
368  default:
369  //user_error("{$this->ansi} is unsupported\r\n");
370  }
371  }
372  $this->ansi = '';
373  continue;
374  }
375 
376  $this->tokenization[count($this->tokenization) - 1].= $source[$i];
377  switch ($source[$i]) {
378  case "\r":
379  $this->x = 0;
380  break;
381  case "\n":
382  $this->_newLine();
383  break;
384  case "\x08": // backspace
385  if ($this->x) {
386  $this->x--;
387  $this->attrs[$this->y][$this->x] = clone $this->base_attr_cell;
388  $this->screen[$this->y] = substr_replace(
389  $this->screen[$this->y],
390  $source[$i],
391  $this->x,
392  1
393  );
394  }
395  break;
396  case "\x0F": // shift
397  break;
398  case "\x1B": // start ANSI escape code
399  $this->tokenization[count($this->tokenization) - 1] = substr($this->tokenization[count($this->tokenization) - 1], 0, -1);
400  //if (!strlen($this->tokenization[count($this->tokenization) - 1])) {
401  // array_pop($this->tokenization);
402  //}
403  $this->ansi.= "\x1B";
404  break;
405  default:
406  $this->attrs[$this->y][$this->x] = clone $this->attr_cell;
407  if ($this->x > strlen($this->screen[$this->y])) {
408  $this->screen[$this->y] = str_repeat(' ', $this->x);
409  }
410  $this->screen[$this->y] = substr_replace(
411  $this->screen[$this->y],
412  $source[$i],
413  $this->x,
414  1
415  );
416 
417  if ($this->x > $this->max_x) {
418  $this->x = 0;
419  $this->y++;
420  } else {
421  $this->x++;
422  }
423  }
424  }
425  }
426 
434  function _newLine()
435  {
436  //if ($this->y < $this->max_y) {
437  // $this->y++;
438  //}
439 
440  while ($this->y >= $this->max_y) {
441  $this->history = array_merge($this->history, array(array_shift($this->screen)));
442  $this->screen[] = '';
443 
444  $this->history_attrs = array_merge($this->history_attrs, array(array_shift($this->attrs)));
445  $this->attrs[] = $this->attr_row;
446 
447  if (count($this->history) >= $this->max_history) {
448  array_shift($this->history);
449  array_shift($this->history_attrs);
450  }
451 
452  $this->y--;
453  }
454  $this->y++;
455  }
456 
463  function _processCoordinate($last_attr, $cur_attr, $char)
464  {
465  $output = '';
466 
467  if ($last_attr != $cur_attr) {
468  $close = $open = '';
469  if ($last_attr->foreground != $cur_attr->foreground) {
470  if ($cur_attr->foreground != 'white') {
471  $open.= '<span style="color: ' . $cur_attr->foreground . '">';
472  }
473  if ($last_attr->foreground != 'white') {
474  $close = '</span>' . $close;
475  }
476  }
477  if ($last_attr->background != $cur_attr->background) {
478  if ($cur_attr->background != 'black') {
479  $open.= '<span style="background: ' . $cur_attr->background . '">';
480  }
481  if ($last_attr->background != 'black') {
482  $close = '</span>' . $close;
483  }
484  }
485  if ($last_attr->bold != $cur_attr->bold) {
486  if ($cur_attr->bold) {
487  $open.= '<b>';
488  } else {
489  $close = '</b>' . $close;
490  }
491  }
492  if ($last_attr->underline != $cur_attr->underline) {
493  if ($cur_attr->underline) {
494  $open.= '<u>';
495  } else {
496  $close = '</u>' . $close;
497  }
498  }
499  if ($last_attr->blink != $cur_attr->blink) {
500  if ($cur_attr->blink) {
501  $open.= '<blink>';
502  } else {
503  $close = '</blink>' . $close;
504  }
505  }
506  $output.= $close . $open;
507  }
508 
509  $output.= htmlspecialchars($char);
510 
511  return $output;
512  }
513 
520  function _getScreen()
521  {
522  $output = '';
523  $last_attr = $this->base_attr_cell;
524  for ($i = 0; $i <= $this->max_y; $i++) {
525  for ($j = 0; $j <= $this->max_x; $j++) {
526  $cur_attr = $this->attrs[$i][$j];
527  $output.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : '');
528  $last_attr = $this->attrs[$i][$j];
529  }
530  $output.= "\r\n";
531  }
532  $output = substr($output, 0, -2);
533  // close any remaining open tags
534  $output.= $this->_processCoordinate($last_attr, $this->base_attr_cell, '');
535  return rtrim($output);
536  }
537 
544  function getScreen()
545  {
546  return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $this->_getScreen() . '</pre>';
547  }
548 
555  function getHistory()
556  {
557  $scrollback = '';
558  $last_attr = $this->base_attr_cell;
559  for ($i = 0; $i < count($this->history); $i++) {
560  for ($j = 0; $j <= $this->max_x + 1; $j++) {
561  $cur_attr = $this->history_attrs[$i][$j];
562  $scrollback.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : '');
563  $last_attr = $this->history_attrs[$i][$j];
564  }
565  $scrollback.= "\r\n";
566  }
568  $this->base_attr_cell = $last_attr;
569  $scrollback.= $this->_getScreen();
570  $this->base_attr_cell = $base_attr_cell;
571 
572  return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $scrollback . '</span></pre>';
573  }
574 }
getHistory()
Returns the current screen and the x previous lines.
Definition: ANSI.php:555
_getScreen()
Returns the current screen without preformating.
Definition: ANSI.php:520
getScreen()
Returns the current screen.
Definition: ANSI.php:544
_newLine()
Add a new line.
Definition: ANSI.php:434
setDimensions($x, $y)
Set terminal width and height.
Definition: ANSI.php:191
loadString($source)
Load a string.
Definition: ANSI.php:221
_processCoordinate($last_attr, $cur_attr, $char)
Returns the current coordinate without preformating.
Definition: ANSI.php:463
Pure-PHP ANSI Decoder.
setHistory($history)
Set the number of lines that should be logged past the terminal height.
Definition: ANSI.php:210
__construct()
Default Constructor.
Definition: ANSI.php:166
appendString($source)
Appdend a string.
Definition: ANSI.php:233
$i
Definition: disco.tpl.php:19
$source
Definition: linkback.php:22