]> git.mxchange.org Git - friendica-addons.git/blob - securemail/vendor/phpseclib/phpseclib/phpseclib/File/ANSI.php
securemail: update pgp library
[friendica-addons.git] / securemail / vendor / phpseclib / phpseclib / phpseclib / File / ANSI.php
1 <?php
2
3 /**
4  * Pure-PHP ANSI Decoder
5  *
6  * PHP versions 4 and 5
7  *
8  * If you call read() in Net_SSH2 you may get {@link http://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape codes} back.
9  * They'd look like chr(0x1B) . '[00m' or whatever (0x1B = ESC).  They tell a
10  * {@link http://en.wikipedia.org/wiki/Terminal_emulator terminal emulator} how to format the characters, what
11  * color to display them in, etc. File_ANSI is a {@link http://en.wikipedia.org/wiki/VT100 VT100} terminal emulator.
12  *
13  * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
14  * of this software and associated documentation files (the "Software"), to deal
15  * in the Software without restriction, including without limitation the rights
16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  * copies of the Software, and to permit persons to whom the Software is
18  * furnished to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included in
21  * all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29  * THE SOFTWARE.
30  *
31  * @category  File
32  * @package   File_ANSI
33  * @author    Jim Wigginton <terrafrost@php.net>
34  * @copyright 2012 Jim Wigginton
35  * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
36  * @link      http://phpseclib.sourceforge.net
37  */
38
39 /**
40  * Pure-PHP ANSI Decoder
41  *
42  * @package File_ANSI
43  * @author  Jim Wigginton <terrafrost@php.net>
44  * @access  public
45  */
46 class File_ANSI
47 {
48     /**
49      * Max Width
50      *
51      * @var Integer
52      * @access private
53      */
54     var $max_x;
55
56     /**
57      * Max Height
58      *
59      * @var Integer
60      * @access private
61      */
62     var $max_y;
63
64     /**
65      * Max History
66      *
67      * @var Integer
68      * @access private
69      */
70     var $max_history;
71
72     /**
73      * History
74      *
75      * @var Array
76      * @access private
77      */
78     var $history;
79
80     /**
81      * History Attributes
82      *
83      * @var Array
84      * @access private
85      */
86     var $history_attrs;
87
88     /**
89      * Current Column
90      *
91      * @var Integer
92      * @access private
93      */
94     var $x;
95
96     /**
97      * Current Row
98      *
99      * @var Integer
100      * @access private
101      */
102     var $y;
103
104     /**
105      * Old Column
106      *
107      * @var Integer
108      * @access private
109      */
110     var $old_x;
111
112     /**
113      * Old Row
114      *
115      * @var Integer
116      * @access private
117      */
118     var $old_y;
119
120     /**
121      * An empty attribute row
122      *
123      * @var Array
124      * @access private
125      */
126     var $attr_row;
127
128     /**
129      * The current screen text
130      *
131      * @var Array
132      * @access private
133      */
134     var $screen;
135
136     /**
137      * The current screen attributes
138      *
139      * @var Array
140      * @access private
141      */
142     var $attrs;
143
144     /**
145      * The current foreground color
146      *
147      * @var String
148      * @access private
149      */
150     var $foreground;
151
152     /**
153      * The current background color
154      *
155      * @var String
156      * @access private
157      */
158     var $background;
159
160     /**
161      * Bold flag
162      *
163      * @var Boolean
164      * @access private
165      */
166     var $bold;
167
168     /**
169      * Underline flag
170      *
171      * @var Boolean
172      * @access private
173      */
174     var $underline;
175
176     /**
177      * Blink flag
178      *
179      * @var Boolean
180      * @access private
181      */
182     var $blink;
183
184     /**
185      * Reverse flag
186      *
187      * @var Boolean
188      * @access private
189      */
190     var $reverse;
191
192     /**
193      * Color flag
194      *
195      * @var Boolean
196      * @access private
197      */
198     var $color;
199
200     /**
201      * Current ANSI code
202      *
203      * @var String
204      * @access private
205      */
206     var $ansi;
207
208     /**
209      * Default Constructor.
210      *
211      * @return File_ANSI
212      * @access public
213      */
214     function File_ANSI()
215     {
216         $this->setHistory(200);
217         $this->setDimensions(80, 24);
218     }
219
220     /**
221      * Set terminal width and height
222      *
223      * Resets the screen as well
224      *
225      * @param Integer $x
226      * @param Integer $y
227      * @access public
228      */
229     function setDimensions($x, $y)
230     {
231         $this->max_x = $x - 1;
232         $this->max_y = $y - 1;
233         $this->x = $this->y = 0;
234         $this->history = $this->history_attrs = array();
235         $this->attr_row = array_fill(0, $this->max_x + 1, '');
236         $this->screen = array_fill(0, $this->max_y + 1, '');
237         $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row);
238         $this->foreground = 'white';
239         $this->background = 'black';
240         $this->bold = false;
241         $this->underline = false;
242         $this->blink = false;
243         $this->reverse = false;
244         $this->color = false;
245
246         $this->ansi = '';
247     }
248
249     /**
250      * Set the number of lines that should be logged past the terminal height
251      *
252      * @param Integer $x
253      * @param Integer $y
254      * @access public
255      */
256     function setHistory($history)
257     {
258         $this->max_history = $history;
259     }
260
261     /**
262      * Load a string
263      *
264      * @param String $source
265      * @access public
266      */
267     function loadString($source)
268     {
269         $this->setDimensions($this->max_x + 1, $this->max_y + 1);
270         $this->appendString($source);
271     }
272
273     /**
274      * Appdend a string
275      *
276      * @param String $source
277      * @access public
278      */
279     function appendString($source)
280     {
281         for ($i = 0; $i < strlen($source); $i++) {
282             if (strlen($this->ansi)) {
283                 $this->ansi.= $source[$i];
284                 $chr = ord($source[$i]);
285                 // http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements
286                 // single character CSI's not currently supported
287                 switch (true) {
288                     case $this->ansi == "\x1B=":
289                         $this->ansi = '';
290                         continue 2;
291                     case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['):
292                     case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126:
293                         break;
294                     default:
295                         continue 2;
296                 }
297                 // http://ascii-table.com/ansi-escape-sequences-vt-100.php
298                 switch ($this->ansi) {
299                     case "\x1B[H": // Move cursor to upper left corner
300                         $this->old_x = $this->x;
301                         $this->old_y = $this->y;
302                         $this->x = $this->y = 0;
303                         break;
304                     case "\x1B[J": // Clear screen from cursor down
305                         $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y));
306                         $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, ''));
307
308                         $this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y));
309                         $this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row));
310
311                         if (count($this->history) == $this->max_history) {
312                             array_shift($this->history);
313                             array_shift($this->history_attrs);
314                         }
315                     case "\x1B[K": // Clear screen from cursor right
316                         $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x);
317
318                         array_splice($this->attrs[$this->y], $this->x + 1);
319                         break;
320                     case "\x1B[2K": // Clear entire line
321                         $this->screen[$this->y] = str_repeat(' ', $this->x);
322                         $this->attrs[$this->y] = $this->attr_row;
323                         break;
324                     case "\x1B[?1h": // set cursor key to application
325                     case "\x1B[?25h": // show the cursor
326                         break;
327                     case "\x1BE": // Move to next line
328                         $this->_newLine();
329                         $this->x = 0;
330                         break;
331                     default:
332                         switch (true) {
333                             case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h
334                                 $this->old_x = $this->x;
335                                 $this->old_y = $this->y;
336                                 $this->x = $match[2] - 1;
337                                 $this->y = $match[1] - 1;
338                                 break;
339                             case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines
340                                 $this->old_x = $this->x;
341                                 $x = $match[1] - 1;
342                                 break;
343                             case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
344                                 break;
345                             case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes
346                                 $mods = explode(';', $match[1]);
347                                 foreach ($mods as $mod) {
348                                     switch ($mod) {
349                                         case 0: // Turn off character attributes
350                                             $this->attrs[$this->y][$this->x] = '';
351
352                                             if ($this->bold) $this->attrs[$this->y][$this->x].= '</b>';
353                                             if ($this->underline) $this->attrs[$this->y][$this->x].= '</u>';
354                                             if ($this->blink) $this->attrs[$this->y][$this->x].= '</blink>';
355                                             if ($this->color) $this->attrs[$this->y][$this->x].= '</span>';
356
357                                             if ($this->reverse) {
358                                                 $temp = $this->background;
359                                                 $this->background = $this->foreground;
360                                                 $this->foreground = $temp;
361                                             }
362
363                                             $this->bold = $this->underline = $this->blink = $this->color = $this->reverse = false;
364                                             break;
365                                         case 1: // Turn bold mode on
366                                             if (!$this->bold) {
367                                                 $this->attrs[$this->y][$this->x] = '<b>';
368                                                 $this->bold = true;
369                                             }
370                                             break;
371                                         case 4: // Turn underline mode on
372                                             if (!$this->underline) {
373                                                 $this->attrs[$this->y][$this->x] = '<u>';
374                                                 $this->underline = true;
375                                             }
376                                             break;
377                                         case 5: // Turn blinking mode on
378                                             if (!$this->blink) {
379                                                 $this->attrs[$this->y][$this->x] = '<blink>';
380                                                 $this->blink = true;
381                                             }
382                                             break;
383                                         case 7: // Turn reverse video on
384                                             $this->reverse = !$this->reverse;
385                                             $temp = $this->background;
386                                             $this->background = $this->foreground;
387                                             $this->foreground = $temp;
388                                             $this->attrs[$this->y][$this->x] = '<span style="color: ' . $this->foreground . '; background: ' . $this->background . '">';
389                                             if ($this->color) {
390                                                 $this->attrs[$this->y][$this->x] = '</span>' . $this->attrs[$this->y][$this->x];
391                                             }
392                                             $this->color = true;
393                                             break;
394                                         default: // set colors
395                                             //$front = $this->reverse ? &$this->background : &$this->foreground;
396                                             $front = &$this->{ $this->reverse ? 'background' : 'foreground' };
397                                             //$back = $this->reverse ? &$this->foreground : &$this->background;
398                                             $back = &$this->{ $this->reverse ? 'foreground' : 'background' };
399                                             switch ($mod) {
400                                                 case 30: $front = 'black'; break;
401                                                 case 31: $front = 'red'; break;
402                                                 case 32: $front = 'green'; break;
403                                                 case 33: $front = 'yellow'; break;
404                                                 case 34: $front = 'blue'; break;
405                                                 case 35: $front = 'magenta'; break;
406                                                 case 36: $front = 'cyan'; break;
407                                                 case 37: $front = 'white'; break;
408
409                                                 case 40: $back = 'black'; break;
410                                                 case 41: $back = 'red'; break;
411                                                 case 42: $back = 'green'; break;
412                                                 case 43: $back = 'yellow'; break;
413                                                 case 44: $back = 'blue'; break;
414                                                 case 45: $back = 'magenta'; break;
415                                                 case 46: $back = 'cyan'; break;
416                                                 case 47: $back = 'white'; break;
417
418                                                 default:
419                                                     user_error('Unsupported attribute: ' . $mod);
420                                                     $this->ansi = '';
421                                                     break 2;
422                                             }
423
424                                             unset($temp);
425                                             $this->attrs[$this->y][$this->x] = '<span style="color: ' . $this->foreground . '; background: ' . $this->background . '">';
426                                             if ($this->color) {
427                                                 $this->attrs[$this->y][$this->x] = '</span>' . $this->attrs[$this->y][$this->x];
428                                             }
429                                             $this->color = true;
430                                     }
431                                 }
432                                 break;
433                             default:
434                                 user_error("{$this->ansi} unsupported\r\n");
435                         }
436                 }
437                 $this->ansi = '';
438                 continue;
439             }
440
441             switch ($source[$i]) {
442                 case "\r":
443                     $this->x = 0;
444                     break;
445                 case "\n":
446                     $this->_newLine();
447                     break;
448                 case "\x0F": // shift
449                     break;
450                 case "\x1B": // start ANSI escape code
451                     $this->ansi.= "\x1B";
452                     break;
453                 default:
454                     $this->screen[$this->y] = substr_replace(
455                         $this->screen[$this->y],
456                         $source[$i],
457                         $this->x,
458                         1
459                     );
460
461                     if ($this->x > $this->max_x) {
462                         $this->x = 0;
463                         $this->y++;
464                     } else {
465                         $this->x++;
466                     }
467             }
468         }
469     }
470
471     /**
472      * Add a new line
473      *
474      * Also update the $this->screen and $this->history buffers
475      *
476      * @access private
477      */
478     function _newLine()
479     {
480         //if ($this->y < $this->max_y) {
481         //    $this->y++;
482         //}
483
484         while ($this->y >= $this->max_y) {
485             $this->history = array_merge($this->history, array(array_shift($this->screen)));
486             $this->screen[] = '';
487
488             $this->history_attrs = array_merge($this->history_attrs, array(array_shift($this->attrs)));
489             $this->attrs[] = $this->attr_row;
490
491             if (count($this->history) >= $this->max_history) {
492                 array_shift($this->history);
493                 array_shift($this->history_attrs);
494             }
495
496             $this->y--;
497         }
498         $this->y++;
499     }
500
501     /**
502      * Returns the current screen without preformating
503      *
504      * @access private
505      * @return String
506      */
507     function _getScreen()
508     {
509         $output = '';
510         for ($i = 0; $i <= $this->max_y; $i++) {
511             for ($j = 0; $j <= $this->max_x + 1; $j++) {
512                 if (isset($this->attrs[$i][$j])) {
513                     $output.= $this->attrs[$i][$j];
514                 }
515                 if (isset($this->screen[$i][$j])) {
516                     $output.= htmlspecialchars($this->screen[$i][$j]);
517                 }
518             }
519             $output.= "\r\n";
520         }
521         return rtrim($output);
522     }
523
524     /**
525      * Returns the current screen
526      *
527      * @access public
528      * @return String
529      */
530     function getScreen()
531     {
532         return '<pre style="color: white; background: black" width="' . ($this->max_x + 1) . '">' . $this->_getScreen() . '</pre>';
533     }
534
535     /**
536      * Returns the current screen and the x previous lines
537      *
538      * @access public
539      * @return String
540      */
541     function getHistory()
542     {
543         $scrollback = '';
544         for ($i = 0; $i < count($this->history); $i++) {
545             for ($j = 0; $j <= $this->max_x + 1; $j++) {
546                 if (isset($this->history_attrs[$i][$j])) {
547                     $scrollback.= $this->history_attrs[$i][$j];
548                 }
549                 if (isset($this->history[$i][$j])) {
550                     $scrollback.= htmlspecialchars($this->history[$i][$j]);
551                 }
552             }
553             $scrollback.= "\r\n";
554         }
555         $scrollback.= $this->_getScreen();
556
557         return '<pre style="color: white; background: black" width="' . ($this->max_x + 1) . '">' . $scrollback . '</pre>';
558     }
559 }