Add plugin support to IniReader, and harden tests.

The actual config file must always have .ini extension.
For backwards compatibility, acl.ini.php will be treated specially until 3.0.
This commit is contained in:
Ber Clausen 2012-08-26 21:02:09 -03:00
parent a553142a0a
commit bdac857293
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.'));
}
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);
}
$contents = parse_ini_file($filename, true);
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