Merge pull request #773 from bar/master-fix-inireader

Add plugin support to IniReader, and harden tests.
This commit is contained in:
Mark Story 2012-08-27 12:36:57 -07:00
commit 7135ff29fb
7 changed files with 286 additions and 34 deletions

View file

@ -84,20 +84,41 @@ class IniReader implements ConfigReaderInterface {
/**
* Read an ini file and return the results as an array.
*
* @param string $file Name of the file to read. The chosen file
* must be on the reader's path.
* @return array
* For backwards compatibility, acl.ini.php will be treated specially until 3.0.
*
* @param string $key The identifier to read from. If the key has a . it will be treated
* as a plugin prefix. The chosen file must be on the reader's path.
* @return array Parsed configuration values.
* @throws ConfigureException when files don't exist.
* Or when files contain '..' as this could lead to abusive reads.
* @throws ConfigureException
*/
public function read($file) {
$filename = $this->_path . $file;
if (!file_exists($filename)) {
$filename .= '.ini';
if (!file_exists($filename)) {
throw new ConfigureException(__d('cake_dev', 'Could not load configuration files: %s or %s', substr($filename, 0, -4), $filename));
}
public function read($key) {
if (strpos($key, '..') !== false) {
throw new ConfigureException(__d('cake_dev', 'Cannot load configuration files with ../ in them.'));
}
$contents = parse_ini_file($filename, true);
if (substr($key, -8) === '.ini.php') {
$key = substr($key, 0, -8);
list($plugin, $key) = pluginSplit($key);
$key .= '.ini.php';
} else {
if (substr($key, -4) === '.ini') {
$key = substr($key, 0, -4);
}
list($plugin, $key) = pluginSplit($key);
$key .= '.ini';
}
if ($plugin) {
$file = App::pluginPath($plugin) . 'Config' . DS . $key;
} else {
$file = $this->_path . $key;
}
if (!is_file($file)) {
throw new ConfigureException(__d('cake_dev', 'Could not load configuration file: %s', $file));
}
$contents = parse_ini_file($file, true);
if (!empty($this->_section) && isset($contents[$this->_section])) {
$values = $this->_parseNestedValues($contents[$this->_section]);
} else {

View file

@ -56,6 +56,47 @@ class IniReaderTest extends CakeTestCase {
* @return void
*/
public function testConstruct() {
$reader = new IniReader($this->path);
$config = $reader->read('acl.ini');
$this->assertTrue(isset($config['admin']));
$this->assertTrue(isset($config['paul']['groups']));
$this->assertEquals('ads', $config['admin']['deny']);
}
/**
* Test reading files.
*
* @return void
*/
public function testRead() {
$reader = new IniReader($this->path);
$config = $reader->read('nested');
$this->assertTrue($config['bools']['test_on']);
$config = $reader->read('nested.ini');
$this->assertTrue($config['bools']['test_on']);
}
/**
* No other sections should exist.
*
* @return void
*/
public function testReadOnlyOneSection() {
$reader = new IniReader($this->path, 'admin');
$config = $reader->read('acl.ini');
$this->assertTrue(isset($config['groups']));
$this->assertEquals('administrators', $config['groups']);
}
/**
* Test reading acl.ini.php.
*
* @return void
*/
public function testReadSpecialAclIniPhp() {
$reader = new IniReader($this->path);
$config = $reader->read('acl.ini.php');
@ -65,24 +106,11 @@ class IniReaderTest extends CakeTestCase {
}
/**
* no other sections should exist.
* Test without section.
*
* @return void
*/
public function testReadingOnlyOneSection() {
$reader = new IniReader($this->path, 'admin');
$config = $reader->read('acl.ini.php');
$this->assertTrue(isset($config['groups']));
$this->assertEquals('administrators', $config['groups']);
}
/**
* test without section
*
* @return void
*/
public function testReadingWithoutSection() {
public function testReadWithoutSection() {
$reader = new IniReader($this->path);
$config = $reader->read('no_section.ini');
@ -94,11 +122,11 @@ class IniReaderTest extends CakeTestCase {
}
/**
* test that names with .'s get exploded into arrays.
* Test that names with .'s get exploded into arrays.
*
* @return void
*/
public function testReadingValuesWithDots() {
public function testReadValuesWithDots() {
$reader = new IniReader($this->path);
$config = $reader->read('nested.ini');
@ -110,7 +138,7 @@ class IniReaderTest extends CakeTestCase {
}
/**
* test boolean reading
* Test boolean reading.
*
* @return void
*/
@ -131,18 +159,93 @@ class IniReaderTest extends CakeTestCase {
}
/**
* test read file without extension
* Test an exception is thrown by reading files that exist without .ini extension.
*
* @expectedException ConfigureException
* @return void
*/
public function testReadingWithoutExtension() {
public function testReadWithExistentFileWithoutExtension() {
$reader = new IniReader($this->path);
$config = $reader->read('nested');
$this->assertTrue($config['bools']['test_on']);
$reader->read('no_ini_extension');
}
/**
* test dump method.
* Test an exception is thrown by reading files that don't exist.
*
* @expectedException ConfigureException
* @return void
*/
public function testReadWithNonExistentFile() {
$reader = new IniReader($this->path);
$reader->read('fake_values');
}
/**
* Test reading an empty file.
*
* @return void
*/
public function testReadEmptyFile() {
$reader = new IniReader($this->path);
$config = $reader->read('empty');
$this->assertEquals(array(), $config);
}
/**
* Test reading keys with ../ doesn't work.
*
* @expectedException ConfigureException
* @return void
*/
public function testReadWithDots() {
$reader = new IniReader($this->path);
$reader->read('../empty');
}
/**
* Test reading from plugins.
*
* @return void
*/
public function testReadPluginValue() {
App::build(array(
'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
), App::RESET);
CakePlugin::load('TestPlugin');
$reader = new IniReader($this->path);
$result = $reader->read('TestPlugin.nested');
$this->assertTrue(isset($result['database']['db']['username']));
$this->assertEquals('bar', $result['database']['db']['username']);
$this->assertFalse(isset($result['database.db.username']));
$this->assertFalse(isset($result['database']['db.username']));
$result = $reader->read('TestPlugin.nested.ini');
$this->assertEquals('foo', $result['database']['db']['password']);
CakePlugin::unload();
}
/**
* Test reading acl.ini.php from plugins.
*
* @return void
*/
public function testReadPluginSpecialAclIniPhpValue() {
App::build(array(
'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
), App::RESET);
CakePlugin::load('TestPlugin');
$reader = new IniReader($this->path);
$result = $reader->read('TestPlugin.acl.ini.php');
$this->assertTrue(isset($result['admin']));
$this->assertTrue(isset($result['paul']['groups']));
$this->assertEquals('ads', $result['admin']['deny']);
CakePlugin::unload();
}
/**
* Test dump method.
*
* @return void
*/

View file

@ -0,0 +1,60 @@
;<?php exit() ?>
; SVN FILE: $Id$
;/**
; * Test App Ini Based Acl Config File
; *
; *
; * PHP 5
; *
; * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
; * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
; *
; * Licensed under The MIT License
; * Redistributions of files must retain the above copyright notice.
; *
; * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
; * @link http://cakephp.org CakePHP(tm) Project
;; * @package Cake.Test.test_app.Config
; * @since CakePHP(tm) v 0.10.0.1076
; * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
; */
;-------------------------------------
;Users
;-------------------------------------
[admin]
groups = administrators
allow =
deny = ads
[paul]
groups = users
allow =
deny =
[jenny]
groups = users
allow = ads
deny = images, files
[nobody]
groups = anonymous
allow =
deny =
;-------------------------------------
;Groups
;-------------------------------------
[administrators]
deny =
allow = posts, comments, images, files, stats, ads
[users]
allow = posts, comments, images, files
deny = stats, ads
[anonymous]
allow =
deny = posts, comments, images, files, stats, ads

View file

@ -0,0 +1 @@
; do nothing this is an empty file.

View file

@ -0,0 +1,3 @@
; Test file for testing config file without .ini extension.
some_key = some_value
bool_key = 1

View file

@ -0,0 +1,60 @@
;<?php exit() ?>
; SVN FILE: $Id$
;/**
; * Test App Ini Based Acl Config File
; *
; *
; * PHP 5
; *
; * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
; * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
; *
; * Licensed under The MIT License
; * Redistributions of files must retain the above copyright notice.
; *
; * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
; * @link http://cakephp.org CakePHP(tm) Project
;; * @package Cake.Test.test_app.Config
; * @since CakePHP(tm) v 0.10.0.1076
; * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
; */
;-------------------------------------
;Users
;-------------------------------------
[admin]
groups = administrators
allow =
deny = ads
[paul]
groups = users
allow =
deny =
[jenny]
groups = users
allow = ads
deny = images, files
[nobody]
groups = anonymous
allow =
deny =
;-------------------------------------
;Groups
;-------------------------------------
[administrators]
deny =
allow = posts, comments, images, files, stats, ads
[users]
allow = posts, comments, images, files
deny = stats, ads
[anonymous]
allow =
deny = posts, comments, images, files, stats, ads

View file

@ -0,0 +1,4 @@
; Test file for testing ini files with . syntax
[database]
db.username = bar
db.password = foo