Chris@13
|
1 <?php
|
Chris@13
|
2
|
Chris@13
|
3 /*
|
Chris@13
|
4 * This file is part of Psy Shell.
|
Chris@13
|
5 *
|
Chris@13
|
6 * (c) 2012-2018 Justin Hileman
|
Chris@13
|
7 *
|
Chris@13
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@13
|
9 * file that was distributed with this source code.
|
Chris@13
|
10 */
|
Chris@13
|
11
|
Chris@13
|
12 namespace Psy\Util;
|
Chris@13
|
13
|
Chris@13
|
14 /**
|
Chris@13
|
15 * String utility methods.
|
Chris@13
|
16 *
|
Chris@13
|
17 * @author ju1ius
|
Chris@13
|
18 */
|
Chris@13
|
19 class Str
|
Chris@13
|
20 {
|
Chris@13
|
21 const UNVIS_RX = <<<'EOS'
|
Chris@13
|
22 /
|
Chris@13
|
23 \\(?:
|
Chris@13
|
24 ((?:040)|s)
|
Chris@13
|
25 | (240)
|
Chris@13
|
26 | (?: M-(.) )
|
Chris@13
|
27 | (?: M\^(.) )
|
Chris@13
|
28 | (?: \^(.) )
|
Chris@13
|
29 )
|
Chris@13
|
30 /xS
|
Chris@13
|
31 EOS;
|
Chris@13
|
32
|
Chris@13
|
33 /**
|
Chris@13
|
34 * Decodes a string encoded by libsd's strvis.
|
Chris@13
|
35 *
|
Chris@13
|
36 * From `man 3 vis`:
|
Chris@13
|
37 *
|
Chris@13
|
38 * Use an ‘M’ to represent meta characters (characters with the 8th bit set),
|
Chris@13
|
39 * and use a caret ‘^’ to represent control characters (see iscntrl(3)).
|
Chris@13
|
40 * The following formats are used:
|
Chris@13
|
41 *
|
Chris@13
|
42 * \040 Represents ASCII space.
|
Chris@13
|
43 *
|
Chris@13
|
44 * \240 Represents Meta-space (  in HTML).
|
Chris@13
|
45 *
|
Chris@13
|
46 * \M-C Represents character ‘C’ with the 8th bit set.
|
Chris@13
|
47 * Spans characters ‘\241’ through ‘\376’.
|
Chris@13
|
48 *
|
Chris@13
|
49 * \M^C Represents control character ‘C’ with the 8th bit set.
|
Chris@13
|
50 * Spans characters ‘\200’ through ‘\237’, and ‘\377’ (as ‘\M^?’).
|
Chris@13
|
51 *
|
Chris@13
|
52 * \^C Represents the control character ‘C’.
|
Chris@13
|
53 * Spans characters ‘\000’ through ‘\037’, and ‘\177’ (as ‘\^?’).
|
Chris@13
|
54 *
|
Chris@13
|
55 * The other formats are supported by PHP's stripcslashes,
|
Chris@13
|
56 * except for the \s sequence (ASCII space).
|
Chris@13
|
57 *
|
Chris@13
|
58 * @param string $input The string to decode
|
Chris@13
|
59 *
|
Chris@13
|
60 * @return string
|
Chris@13
|
61 */
|
Chris@13
|
62 public static function unvis($input)
|
Chris@13
|
63 {
|
Chris@17
|
64 $output = \preg_replace_callback(self::UNVIS_RX, 'self::unvisReplace', $input);
|
Chris@13
|
65 // other escapes & octal are handled by stripcslashes
|
Chris@17
|
66 return \stripcslashes($output);
|
Chris@13
|
67 }
|
Chris@13
|
68
|
Chris@13
|
69 /**
|
Chris@13
|
70 * Callback for Str::unvis.
|
Chris@13
|
71 *
|
Chris@13
|
72 * @param array $match The matches passed by preg_replace_callback
|
Chris@13
|
73 *
|
Chris@13
|
74 * @return string
|
Chris@13
|
75 */
|
Chris@13
|
76 protected static function unvisReplace($match)
|
Chris@13
|
77 {
|
Chris@13
|
78 // \040, \s
|
Chris@13
|
79 if (!empty($match[1])) {
|
Chris@13
|
80 return "\x20";
|
Chris@13
|
81 }
|
Chris@13
|
82 // \240
|
Chris@13
|
83 if (!empty($match[2])) {
|
Chris@13
|
84 return "\xa0";
|
Chris@13
|
85 }
|
Chris@13
|
86 // \M-(.)
|
Chris@13
|
87 if (isset($match[3]) && $match[3] !== '') {
|
Chris@13
|
88 $chr = $match[3];
|
Chris@13
|
89 // unvis S_META1
|
Chris@13
|
90 $cp = 0200;
|
Chris@17
|
91 $cp |= \ord($chr);
|
Chris@13
|
92
|
Chris@17
|
93 return \chr($cp);
|
Chris@13
|
94 }
|
Chris@13
|
95 // \M^(.)
|
Chris@13
|
96 if (isset($match[4]) && $match[4] !== '') {
|
Chris@13
|
97 $chr = $match[4];
|
Chris@13
|
98 // unvis S_META | S_CTRL
|
Chris@13
|
99 $cp = 0200;
|
Chris@17
|
100 $cp |= ($chr === '?') ? 0177 : \ord($chr) & 037;
|
Chris@13
|
101
|
Chris@17
|
102 return \chr($cp);
|
Chris@13
|
103 }
|
Chris@13
|
104 // \^(.)
|
Chris@13
|
105 if (isset($match[5]) && $match[5] !== '') {
|
Chris@13
|
106 $chr = $match[5];
|
Chris@13
|
107 // unvis S_CTRL
|
Chris@13
|
108 $cp = 0;
|
Chris@17
|
109 $cp |= ($chr === '?') ? 0177 : \ord($chr) & 037;
|
Chris@13
|
110
|
Chris@17
|
111 return \chr($cp);
|
Chris@13
|
112 }
|
Chris@13
|
113 }
|
Chris@13
|
114 }
|