@@ -14,6 +14,31 @@ class ODS implements EscaperInterface
1414{
1515 use Singleton;
1616
17+ /** @var string Regex pattern to detect control characters that need to be escaped */
18+ protected $ escapableControlCharactersPattern ;
19+
20+ /**
21+ * Initializes the singleton instance
22+ */
23+ protected function init ()
24+ {
25+ $ this ->escapableControlCharactersPattern = $ this ->getEscapableControlCharactersPattern ();
26+ }
27+
28+ /**
29+ * @return string Regex pattern containing all escapable control characters
30+ */
31+ protected function getEscapableControlCharactersPattern ()
32+ {
33+ // control characters values are from 0 to 1F (hex values) in the ASCII table
34+ // some characters should not be escaped though: "\t", "\r" and "\n".
35+ return '[\x00-\x08 ' .
36+ // skipping "\t" (0x9) and "\n" (0xA)
37+ '\x0B-\x0C ' .
38+ // skipping "\r" (0xD)
39+ '\x0E-\x1F] ' ;
40+ }
41+
1742 /**
1843 * Escapes the given string to make it compatible with XLSX
1944 *
@@ -22,7 +47,17 @@ class ODS implements EscaperInterface
2247 */
2348 public function escape ($ string )
2449 {
25- return htmlspecialchars ($ string , ENT_QUOTES );
50+ if (defined ('ENT_DISALLOWED ' )) {
51+ // 'ENT_DISALLOWED' ensures that invalid characters in the given document type are replaced.
52+ // Otherwise characters like a vertical tab "\v" will make the XML document unreadable by the XML processor
53+ // @link https://github.com/box/spout/issues/329
54+ return htmlspecialchars ($ string , ENT_QUOTES | ENT_DISALLOWED );
55+ } else {
56+ // We are on hhvm or any other engine that does not support ENT_DISALLOWED
57+ $ escapedString = htmlspecialchars ($ string , ENT_QUOTES );
58+ $ replacedString = preg_replace ('/ ' .$ this ->escapableControlCharactersPattern .'/ ' , '� ' , $ escapedString );
59+ return $ replacedString ;
60+ }
2661 }
2762
2863 /**
0 commit comments