Project

General

Profile

Bug #29461 » typo3-29461-escape_typoscript_key.diff

Alexander Stehlik, 2013-07-24 16:35

View differences:

typo3/sysext/core/Classes/TypoScript/Parser/TypoScriptParser.php
*/
class TypoScriptParser {
/**
* The character that can be used to escape dots in TypoScript keys
*/
const TYPOSCRIPT_KEY_ESCAPE_CHARACTER = '\\';
// If set, then key names cannot contain characters other than [:alnum:]_\.-
/**
* @todo Define visibility
......
*/
public function getVal($string, $setup) {
if ((string) $string != '') {
$keyLen = strcspn($string, '.');
$keyLen = $this->getKeyLengthAndStripEscapeChars($string, '.');
if ($keyLen == strlen($string)) {
// Added 6/6/03. Shouldn't hurt
$retArr = array();
......
*/
public function setVal($string, &$setup, $value, $wipeOut = 0) {
if ((string) $string != '') {
$keyLen = strcspn($string, '.');
$keyLen = $this->getKeyLengthAndStripEscapeChars($string);
if ($keyLen == strlen($string)) {
if ($value == 'UNSET') {
unset($setup[$string]);
......
}
/**
* Determines the string lenght of a TypoScript key and either
* stopps at the end or at the first dot that was found.
*
* Additionally any escape characters in the key are stripped.
*
* @param string $key the key, possibly consisting of multiple keys seperated by dots
* @param int $offset Internal use only! If an escaped dot was found the offset will be used to search for the next dot after the escaped one
* @param int $escapeCharCount Internal use only! Counts the number of escaped dots to correctly determine the key length after the escape chars have been stripped
* @return int The position of the first dot or the last character of the string
*/
public function getKeyLengthAndStripEscapeChars(&$key, $offset = 0, $escapeCharCount = 0) {
$testKey = $key;
if ($offset > 0) {
$testKey = substr($key, $offset);
}
$possibleMatchPosition = strcspn($testKey, '.') + $offset;
if ($key[$possibleMatchPosition - 1] === static::TYPOSCRIPT_KEY_ESCAPE_CHARACTER) {
return $this->getKeyLengthAndStripEscapeChars($key, $possibleMatchPosition + 1, $escapeCharCount + 1);
} else {
$key = str_replace(static::TYPOSCRIPT_KEY_ESCAPE_CHARACTER . '.', '.', $key);
return $possibleMatchPosition - $escapeCharCount;
}
}
/**
* Stacks errors/messages from the TypoScript parser into an internal array, $this->error
* If "TT" is a global object (as it is in the frontend when backend users are logged in) the message will be registered here as well.
*
typo3/sysext/core/Tests/Unit/TypoScript/Parser/TypoScriptParserTest.php
),
),
),
'nested assignment with escaped key' => array(
'lib\.key = value',
array(
'lib.key' => 'value',
),
),
'nested structured assignment' => array(
'lib {' . LF .
'key = value' . LF .
......
),
),
),
'nested structured assignment with escaped key' => array(
'lib {' . LF .
'key\\.nextkey = value' . LF .
'}',
array(
'lib.' => array(
'key.nextkey' => 'value',
),
),
),
'multiline assignment' => array(
'key (' . LF .
'first' . LF .
......
'key' => 'first' . LF . 'second',
),
),
'multiline assignment with escaped key' => array(
'key\\.nextkey (' . LF .
'first' . LF .
'second' . LF .
')',
array(
'key.nextkey' => 'first' . LF . 'second',
),
),
'copying values' => array(
'lib.default = value' . LF .
'lib.copy < lib.default',
......
),
),
),
'copying values with escaped key' => array(
'lib\.default = value' . LF .
'lib.copy < lib\.default',
array(
'lib.default' => 'value',
'lib.' => array(
'copy' => 'value',
),
),
),
'one-line hash comment' => array(
'first = 1' . LF .
'# ignore = me' . LF .
......
);
}
/**
* @test
* @dataProvider keyOffsetDetectionRespectsEscaptedTypoScriptKeysDataProvider
*/
public function keyOffsetDetectionRespectsEscaptedTypoScriptKeys($key, $expectedLength) {
$length = $this->typoScriptParser->getKeyLengthAndStripEscapeChars($key);
$this->assertEquals($expectedLength, $length);
}
/**
* @return array
*/
public function keyOffsetDetectionRespectsEscaptedTypoScriptKeysDataProvider() {
return array(
'key with normal seperator' => array(
'test.key',
4
),
'key without seperator' => array(
'testkey',
7
),
'key with escaped seperator' => array(
'test\\.key',
8
),
);
}
/**
* @test
* @dataProvider typoScriptKeyEscapeCharactersAreStrippedDataProvider
*/
public function typoScriptKeyEscapeCharactersAreStripped($key, $strippedKey) {
$this->typoScriptParser->getKeyLengthAndStripEscapeChars($key);
$this->assertEquals($strippedKey, $key);
}
/**
* @return array
*/
public function typoScriptKeyEscapeCharactersAreStrippedDataProvider() {
return array(
'key with normal seperator' => array(
'test.key',
'test.key',
),
'key without seperator' => array(
'testkey',
'testkey',
),
'key with escaped seperator' => array(
'test\\.key',
'test.key',
),
);
}
}
?>
(3-3/7)