diff options
author | diosmosis <benaka@piwik.pro> | 2015-04-09 08:27:38 +0300 |
---|---|---|
committer | diosmosis <benaka@piwik.pro> | 2015-04-09 08:27:38 +0300 |
commit | 3acd811463c9a8c40775f3d948fe76908554e0e1 (patch) | |
tree | c3b45a0831a1d0be20bb4ac70544ce5901ec3724 | |
parent | 07ead6bfc9abd39d1a526dc81dc785a394fabaca (diff) |
Move Config::encodeValues/Config::decodeValues from Config to IniFileChain since they are vital to correctly storing/loading settings w/o strange bugs.
-rw-r--r-- | core/Config.php | 61 | ||||
-rw-r--r-- | core/Config/IniFileChain.php | 69 | ||||
-rw-r--r-- | tests/PHPUnit/Unit/Config/IniFileChainTest.php | 14 | ||||
-rw-r--r-- | tests/PHPUnit/Unit/Config/test_files/default_settings_1.ini.php | 4 | ||||
-rw-r--r-- | tests/resources/Config/config.written.ini.php | 6 |
5 files changed, 74 insertions, 80 deletions
diff --git a/core/Config.php b/core/Config.php index edc54d6a07..1ceb2594da 100644 --- a/core/Config.php +++ b/core/Config.php @@ -12,9 +12,6 @@ namespace Piwik; use Exception; use Piwik\Application\Kernel\GlobalSettingsProvider; use Piwik\Application\Kernel\GlobalSettingsProvider\IniSettingsProvider; -use Piwik\Config\IniFileChain; -use Piwik\Config\ConfigNotFoundException; -use Piwik\Ini\IniReadingException; /** * Singleton that provides read & write access to Piwik's INI configuration. @@ -337,46 +334,6 @@ class Config extends Singleton } /** - * Decode HTML entities - * - * @param mixed $values - * @return mixed - */ - public static function decodeValues(&$values) - { - if (is_array($values)) { - foreach ($values as &$value) { - $value = self::decodeValues($value); - } - return $values; - } elseif (is_string($values)) { - return html_entity_decode($values, ENT_COMPAT, 'UTF-8'); - } - return $values; - } - - /** - * Encode HTML entities - * - * @param mixed $values - * @return mixed - */ - protected function encodeValues(&$values) - { - if (is_array($values)) { - foreach ($values as &$value) { - $value = $this->encodeValues($value); - } - } elseif (is_float($values)) { - $values = Common::forceDotAsSeparatorForDecimalPoint($values); - } elseif (is_string($values)) { - $values = htmlentities($values, ENT_COMPAT, 'UTF-8'); - $values = str_replace('$', '$', $values); - } - return $values; - } - - /** * Returns a configuration value or section by name. * * @param string $name The value or section name. @@ -429,21 +386,9 @@ class Config extends Singleton { $chain = $this->settings->getIniFileChain(); - $this->encodeValues($chain->getAll()); - - try { - $header = "; <?php exit; ?> DO NOT REMOVE THIS LINE\n"; - $header .= "; file automatically generated or modified by Piwik; you can manually override the default values in global.ini.php by redefining them in this file.\n"; - $dumpedString = $chain->dumpChanges($header); - - $this->decodeValues($chain->getAll()); - } catch (Exception $ex) { - $this->decodeValues($chain->getAll()); - - throw $ex; - } - - return $dumpedString; + $header = "; <?php exit; ?> DO NOT REMOVE THIS LINE\n"; + $header .= "; file automatically generated or modified by Piwik; you can manually override the default values in global.ini.php by redefining them in this file.\n"; + return $chain->dumpChanges($header); } /** diff --git a/core/Config/IniFileChain.php b/core/Config/IniFileChain.php index 4d5c77c52b..4d264b2ec2 100644 --- a/core/Config/IniFileChain.php +++ b/core/Config/IniFileChain.php @@ -7,6 +7,7 @@ */ namespace Piwik\Config; +use Piwik\Common; use Piwik\Config; use Piwik\Ini\IniReader; use Piwik\Ini\IniReadingException; @@ -28,6 +29,10 @@ use Piwik\Piwik; * * The user settings file (for example, config.ini.php) holds the actual setting values. Settings in the * user settings files overwrite other settings. So array settings will not merge w/ previous values. + * + * HTML characters and dollar signs are stored as encoded HTML entities in INI files. This prevents + * several `parse_ini_file` issues, including one where parse_ini_file tries to insert a variable + * into a setting value if a string like `"$varname" is present. */ class IniFileChain { @@ -114,8 +119,7 @@ class IniFileChain */ public function dump($header = '') { - $writer = new IniWriter(); - return $writer->writeToString($this->mergedSettings, $header); + return $this->dumpSettingsArray($header, $this->mergedSettings); } /** @@ -185,8 +189,7 @@ class IniFileChain } }); - $writer = new IniWriter(); - return $writer->writeToString($configToWrite, $header); + return $this->dumpSettingsArray($header, $configToWrite); } else { return null; } @@ -211,15 +214,13 @@ class IniFileChain } catch (IniReadingException $ex) { throw new IniReadingException('Unable to read INI file {' . $file . '}: ' . $ex->getMessage() . "\n Your host may have disabled parse_ini_file()."); } + + $this->decodeValues($this->settingsChain[$file]); } } $this->mergedSettings = $this->mergeFileSettings(); - - // TODO move this method to this class - // decode section data - Config::decodeValues($this->getAll()); - } + } private function resetSettingsChain($defaultSettingsFiles, $userSettingsFile) { @@ -403,4 +404,54 @@ class IniFileChain return array_search($sectionName, $settingsDataSectionNames); } + + + /** + * Decode HTML entities in setting data. + * + * @param mixed $values + * @return mixed + */ + private function decodeValues(&$values) + { + if (is_array($values)) { + foreach ($values as &$value) { + $value = self::decodeValues($value); + } + return $values; + } elseif (is_string($values)) { + return html_entity_decode($values, ENT_COMPAT, 'UTF-8'); + } + return $values; + } + + + /** + * Encode HTML entities + * + * @param mixed $values + * @return mixed + */ + protected function encodeValues(&$values) + { + if (is_array($values)) { + foreach ($values as &$value) { + $value = $this->encodeValues($value); + } + } elseif (is_float($values)) { + $values = Common::forceDotAsSeparatorForDecimalPoint($values); + } elseif (is_string($values)) { + $values = htmlentities($values, ENT_COMPAT, 'UTF-8'); + $values = str_replace('$', '$', $values); + } + return $values; + } + + private function dumpSettingsArray($header, $settings) + { + $writer = new IniWriter(); + + $this->encodeValues($settings); + return $writer->writeToString($settings, $header); + } }
\ No newline at end of file diff --git a/tests/PHPUnit/Unit/Config/IniFileChainTest.php b/tests/PHPUnit/Unit/Config/IniFileChainTest.php index 307aba74cf..ca5e0797a8 100644 --- a/tests/PHPUnit/Unit/Config/IniFileChainTest.php +++ b/tests/PHPUnit/Unit/Config/IniFileChainTest.php @@ -141,7 +141,7 @@ class IniFileChainTest extends PHPUnit_Framework_TestCase ) ), 'Section2' => array( - 'var4' => 'value5' + 'var4' => 'val$ue5' ) ) ), @@ -160,7 +160,7 @@ class IniFileChainTest extends PHPUnit_Framework_TestCase ) ), 'Section2' => array( - 'var4' => 'value5' + 'var4' => 'val$ue5' ) ) ) @@ -194,7 +194,7 @@ class IniFileChainTest extends PHPUnit_Framework_TestCase $data =& $fileChain->get('Section1'); - $this->assertEquals(array('var1' => 'value2', 'var3' => array('value3', 'value4')), $data); + $this->assertEquals(array('var1' => 'val"ue2', 'var3' => array('value3', 'value4')), $data); $data['var1'] = 'changed'; $data['var3'][] = 'newValue'; @@ -241,7 +241,7 @@ class IniFileChainTest extends PHPUnit_Framework_TestCase __DIR__ . '/test_files/default_settings_2.ini.php' ); - $this->assertEquals(array('var1' => 'value2', 'var3' => array('value3', 'value4')), $fileChain->getFrom($defaultSettingsPath, 'Section1')); + $this->assertEquals(array('var1' => 'val"ue2', 'var3' => array('value3', 'value4')), $fileChain->getFrom($defaultSettingsPath, 'Section1')); } public function getTestDataForDumpTest() @@ -253,7 +253,7 @@ class IniFileChainTest extends PHPUnit_Framework_TestCase ), __DIR__ . '/test_files/default_settings_2.ini.php', // user settings "; some header\n", - "; some header\n[Section1]\nvar1 = \"overriddenValue1\"\nvar3[] = \"overriddenValue2\"\nvar3[] = \"overriddenValue3\"\n\n[Section2]\nvar4 = \"value5\"\n\n", + "; some header\n[Section1]\nvar1 = \"overriddenValue1\"\nvar3[] = \"overriddenValue2\"\nvar3[] = \"overriddenValue3\"\n\n[Section2]\nvar4 = \"val$ue5\"\n\n", "; some header\n[Section1]\nvar1 = \"overriddenValue1\"\nvar3[] = \"overriddenValue2\"\nvar3[] = \"overriddenValue3\"\n\n" ) ); @@ -296,12 +296,12 @@ class IniFileChainTest extends PHPUnit_Framework_TestCase array( 'Custom' => array('var' => 'val'), 'Settings0' => array('abc' => 'def2'), - 'Section1' => array('var1' => '5'), + 'Section1' => array('var1' => '5$'), 'Settings3' => array('var1' => '2'), 'Section2' => array('var4' => '9') ), "; some header\n", - "; some header\n[Settings3]\nvar1 = \"2\"\n\n[Settings0]\nabc = \"def2\"\n\n[Section1]\nvar1 = \"5\"\n\n[Section2]\nvar4 = \"9\"\n\n[Custom]\nvar = \"val\"\n\n" + "; some header\n[Settings3]\nvar1 = \"2\"\n\n[Settings0]\nabc = \"def2\"\n\n[Section1]\nvar1 = \"5$\"\n\n[Section2]\nvar4 = \"9\"\n\n[Custom]\nvar = \"val\"\n\n" ) ); } diff --git a/tests/PHPUnit/Unit/Config/test_files/default_settings_1.ini.php b/tests/PHPUnit/Unit/Config/test_files/default_settings_1.ini.php index 2eb4fdd926..20a9acaf60 100644 --- a/tests/PHPUnit/Unit/Config/test_files/default_settings_1.ini.php +++ b/tests/PHPUnit/Unit/Config/test_files/default_settings_1.ini.php @@ -1,9 +1,9 @@ [Section1] -var1 = "value2" +var1 = "val"ue2" var3[] = "value3" var3[] = "value4" [Section2] -var4 = "value5"
\ No newline at end of file +var4 = "val$ue5"
\ No newline at end of file diff --git a/tests/resources/Config/config.written.ini.php b/tests/resources/Config/config.written.ini.php index a412b689db..c66c3c2d43 100644 --- a/tests/resources/Config/config.written.ini.php +++ b/tests/resources/Config/config.written.ini.php @@ -1,10 +1,8 @@ ; <?php exit; ?> DO NOT REMOVE THIS LINE ; file automatically generated or modified by Piwik; you can manually override the default values in global.ini.php by redefining them in this file. -[Development] -disable_merged_assets = 0 - [Category] test = "&6^ geagea'''";;&" -[PluginsInstalled] +[Development] +disable_merged_assets = 0 |