[TASK] Deprecate JavaScriptEncoder class
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Encoder / JavaScriptEncoder.php
1 <?php
2 namespace TYPO3\CMS\Core\Encoder;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * Adopted from OWASP Enterprise Security API (ESAPI) reference implementation for the JavaScript Codec.
19 * Original Author: Mike Boberski
20 *
21 * This class provides encoding for user input that is intended to be used in a JavaScript context.
22 * It encodes all characters except alphanumericals and the immune characters to a hex representation.
23 * @copyright 2009-2010 The OWASP Foundation
24 * @link http://www.owasp.org/index.php/ESAPI
25 * @deprecated since TYPO3 v9.3, will be removed in TYPO3 v10.0
26 */
27 class JavaScriptEncoder implements \TYPO3\CMS\Core\SingletonInterface
28 {
29 /**
30 * A map where the keys are ordinal values of non-alphanumeric single-byte
31 * characters and the values are hexadecimal equivalents as strings.
32 *
33 * @var array
34 */
35 protected $hexMatrix = [];
36
37 /**
38 * Characters that are immune (not dangerous) in the JavaScript context
39 *
40 * @var array
41 */
42 protected $immuneCharacters = [',', '.', '_'];
43
44 /**
45 * TYPO3 charset encoding object
46 *
47 * @var \TYPO3\CMS\Core\Charset\CharsetConverter
48 */
49 protected $charsetConversion = null;
50
51 /**
52 * Populates the $hex map of non-alphanumeric single-byte characters.
53 *
54 * Alphanumerical character are set to NULL in the matrix.
55 * @deprecated since TYPO3 v9.3, will be removed in TYPO3 v10.0
56 */
57 public function __construct()
58 {
59 trigger_error('TYPO3\'s JavaScriptEncoder will be removed in TYPO3 v10.0, use PHPs native json_encode() or GeneralUtility::quoteJSvalue() instead.', E_USER_DEPRECATED);
60 $this->charsetConversion = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Charset\CharsetConverter::class);
61 for ($i = 0; $i < 256; $i++) {
62 if ($i >= ord('0') && $i <= ord('9') || $i >= ord('A') && $i <= ord('Z') || $i >= ord('a') && $i <= ord('z')) {
63 $this->hexMatrix[$i] = null;
64 } else {
65 $this->hexMatrix[$i] = dechex($i);
66 }
67 }
68 }
69
70 /**
71 * Encodes a string for JavaScript.
72 *
73 * @param string $input The string to encode, may be empty.
74 * @return string The encoded string.
75 */
76 public function encode($input)
77 {
78 $stringLength = mb_strlen($input, 'utf-8');
79 $encodedString = '';
80 for ($i = 0; $i < $stringLength; $i++) {
81 $c = mb_substr($input, $i, 1, 'utf-8');
82 $encodedString .= $this->encodeCharacter($c);
83 }
84 return $encodedString;
85 }
86
87 /**
88 * Returns backslash encoded numeric format. Does not use backslash
89 * character escapes such as, \" or \' as these may cause parsing problems.
90 * For example, if a javascript attribute, such as onmouseover, contains
91 * a \" that will close the entire attribute and allow an attacker to inject
92 * another script attribute.
93 *
94 * @param string $character utf-8 character that needs to be encoded
95 * @return string encoded character
96 */
97 protected function encodeCharacter($character)
98 {
99 if ($this->isImmuneCharacter($character)) {
100 return $character;
101 }
102 $ordinalValue = $this->charsetConversion->utf8CharToUnumber($character);
103 // Check for alphanumeric characters
104 $hex = $this->getHexForNonAlphanumeric($ordinalValue);
105 if ($hex === null) {
106 return $character;
107 }
108 // Encode up to 256 with \\xHH
109 if ($ordinalValue < 256) {
110 $pad = substr('00', strlen($hex));
111 return '\\x' . $pad . strtoupper($hex);
112 }
113 // Otherwise encode with \\uHHHH
114 $pad = substr('0000', strlen($hex));
115 return '\\u' . $pad . strtoupper($hex);
116 }
117
118 /**
119 * Checks if the given character is one of the immune characters
120 *
121 * @param string $character utf-8 character to search for, must not be empty
122 * @return bool TRUE if character is immune, FALSE otherwise
123 */
124 protected function isImmuneCharacter($character)
125 {
126 return in_array($character, $this->immuneCharacters, true);
127 }
128
129 /**
130 * Returns the ordinal value as a hex string of any character that is not a
131 * single-byte alphanumeric. The character should be supplied as a string in
132 * the utf-8 character encoding.
133 * If the character is an alphanumeric character with ordinal value below 255,
134 * then this method will return NULL.
135 *
136 * @param int $ordinalValue Ordinal value of the character
137 * @return string hexadecimal ordinal value of non-alphanumeric characters or NULL otherwise.
138 */
139 protected function getHexForNonAlphanumeric($ordinalValue)
140 {
141 if ($ordinalValue <= 255) {
142 return $this->hexMatrix[$ordinalValue];
143 }
144 return dechex($ordinalValue);
145 }
146 }