Skip to content

Commit

Permalink
Fix issue 329 (box#333)
Browse files Browse the repository at this point in the history
* Used ENT_DISALLOWED when escaping a string.
* Added workaround for environments where ENT_DISALLOWED is not defined
  • Loading branch information
madflow authored and adrilo committed Oct 19, 2016
1 parent 4cb30bc commit ef4a32e
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
37 changes: 36 additions & 1 deletion src/Spout/Common/Escaper/ODS.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,31 @@ class ODS implements EscaperInterface
{
use Singleton;

/** @var string Regex pattern to detect control characters that need to be escaped */
protected $escapableControlCharactersPattern;

/**
* Initializes the singleton instance
*/
protected function init()
{
$this->escapableControlCharactersPattern = $this->getEscapableControlCharactersPattern();
}

/**
* @return string Regex pattern containing all escapable control characters
*/
protected function getEscapableControlCharactersPattern()
{
// control characters values are from 0 to 1F (hex values) in the ASCII table
// some characters should not be escaped though: "\t", "\r" and "\n".
return '[\x00-\x08' .
// skipping "\t" (0x9) and "\n" (0xA)
'\x0B-\x0C' .
// skipping "\r" (0xD)
'\x0E-\x1F]';
}

/**
* Escapes the given string to make it compatible with XLSX
*
Expand All @@ -22,7 +47,17 @@ class ODS implements EscaperInterface
*/
public function escape($string)
{
return htmlspecialchars($string, ENT_QUOTES);
if (defined('ENT_DISALLOWED')) {
// 'ENT_DISALLOWED' ensures that invalid characters in the given document type are replaced.
// Otherwise characters like a vertical tab "\v" will make the XML document unreadable by the XML processor
// @link https://github.com/box/spout/issues/329
return htmlspecialchars($string, ENT_QUOTES | ENT_DISALLOWED);
} else {
// We are on hhvm or any other engine that does not support ENT_DISALLOWED
$escapedString = htmlspecialchars($string, ENT_QUOTES);
$replacedString = preg_replace('/'.$this->escapableControlCharactersPattern.'/', '', $escapedString);
return $replacedString;
}
}

/**
Expand Down
42 changes: 42 additions & 0 deletions tests/Spout/Common/Escaper/ODSTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Box\Spout\Common\Escaper;

/**
* Class ODSTest
*
* @package Box\Spout\Common\Escaper
*/
class ODSTest extends \PHPUnit_Framework_TestCase
{
/**
* @return array
*/
public function dataProviderForTestEscape()
{
return [
['test', 'test'],
['carl\'s "pokemon"', 'carl&#039;s &quot;pokemon&quot;'],
["\n", "\n"],
["\r", "\r"],
["\t", "\t"],
["\v", ""],
["\f", ""],
];
}

/**
* @dataProvider dataProviderForTestEscape
*
* @param string $stringToEscape
* @param string $expectedEscapedString
* @return void
*/
public function testEscape($stringToEscape, $expectedEscapedString)
{
$escaper = \Box\Spout\Common\Escaper\ODS::getInstance();
$escapedString = $escaper->escape($stringToEscape);

$this->assertEquals($expectedEscapedString, $escapedString, 'Incorrect escaped string');
}
}

0 comments on commit ef4a32e

Please sign in to comment.