Skip to content
This repository was archived by the owner on May 26, 2022. It is now read-only.

Commit ef4a32e

Browse files
madflowadrilo
authored andcommitted
Fix issue 329 (#333)
* Used ENT_DISALLOWED when escaping a string. * Added workaround for environments where ENT_DISALLOWED is not defined
1 parent 4cb30bc commit ef4a32e

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

src/Spout/Common/Escaper/ODS.php

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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
/**
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Box\Spout\Common\Escaper;
4+
5+
/**
6+
* Class ODSTest
7+
*
8+
* @package Box\Spout\Common\Escaper
9+
*/
10+
class ODSTest extends \PHPUnit_Framework_TestCase
11+
{
12+
/**
13+
* @return array
14+
*/
15+
public function dataProviderForTestEscape()
16+
{
17+
return [
18+
['test', 'test'],
19+
['carl\'s "pokemon"', 'carl&#039;s &quot;pokemon&quot;'],
20+
["\n", "\n"],
21+
["\r", "\r"],
22+
["\t", "\t"],
23+
["\v", ""],
24+
["\f", ""],
25+
];
26+
}
27+
28+
/**
29+
* @dataProvider dataProviderForTestEscape
30+
*
31+
* @param string $stringToEscape
32+
* @param string $expectedEscapedString
33+
* @return void
34+
*/
35+
public function testEscape($stringToEscape, $expectedEscapedString)
36+
{
37+
$escaper = \Box\Spout\Common\Escaper\ODS::getInstance();
38+
$escapedString = $escaper->escape($stringToEscape);
39+
40+
$this->assertEquals($expectedEscapedString, $escapedString, 'Incorrect escaped string');
41+
}
42+
}

0 commit comments

Comments
 (0)