Merge branch '77-unit-tests-for-the-core' into 'master'

Core Unit Tests

The first tests have been added: 
- Layout
- Core
- Events
- Helpers
- Factory
- Config
- Libraries

Please wait until more of the list is handled. 

Some of the events mentioned in #77 are fixed. However not all of them are done yet.

> Closes #84

> Closes #88

> Closes #93

See merge request !44
This commit is contained in:
Abel Hoogeveen 2016-06-04 14:10:01 +02:00
commit 0ed6d8dd30
72 changed files with 4145 additions and 808 deletions

View File

@ -21,7 +21,7 @@ build:composer:
test:5.4:
image: php:5.4
script:
- vendor/bin/phpunit -c phpunit.xml --coverage-text
- vendor/bin/phpunit -c tests/phpunit.xml --coverage-text
cache:
key: "$CI_BUILD_REF/$CI_BUILD_REF_NAME"
paths:
@ -31,7 +31,7 @@ test:5.4:
test:5.5:
image: php:5.5
script:
- vendor/bin/phpunit -c phpunit.xml --coverage-text
- vendor/bin/phpunit -c tests/phpunit.xml --coverage-text
cache:
key: "$CI_BUILD_REF/$CI_BUILD_REF_NAME"
paths:
@ -42,7 +42,7 @@ test:5.6:
stage: test
image: php:5.6
script:
- vendor/bin/phpunit -c phpunit.xml --coverage-text
- vendor/bin/phpunit -c tests/phpunit.xml --coverage-text
cache:
key: "$CI_BUILD_REF/$CI_BUILD_REF_NAME"
paths:
@ -52,7 +52,7 @@ test:7.0:
stage: test
image: php:7.0
script:
- vendor/bin/phpunit -c phpunit.xml --coverage-text
- vendor/bin/phpunit -c tests/phpunit.xml --coverage-text
cache:
key: "$CI_BUILD_REF/$CI_BUILD_REF_NAME"
paths:
@ -64,7 +64,7 @@ release:
only:
- master
script:
- vendor/bin/phpunit -c phpunit.xml --coverage-text
- vendor/bin/phpunit -c tests/phpunit.xml --coverage-text
- vendor/bin/apigen generate -s . -d 'build/phpdoc' --todo --title 'FuzeWorks Build' --exclude 'tests/*','build/*','vendor/*','CI/*'
artifacts:
name: "${CI_BUILD_NAME}_${CI_BUILD_REF_NAME}"

View File

@ -1,6 +1,6 @@
<?php
return array(
<?php return array (
'debug' => false,
'error_reporting' => true,
);
'log_to_file' => false,
'logger_template' => 'logger_default',
) ;

View File

@ -12,7 +12,7 @@ return array(
'default_function' => 'index',
'application_prefix' => 'MY_',
'charset' => 'utf-8',
'charset' => 'UTF-8',
'language' => 'english',
/*

View File

@ -33,7 +33,6 @@
namespace Application\Controller;
use FuzeWorks\ControllerAbstract;
use FuzeWorks\Layout;
/**
* The default controller of FuzeWorks.
@ -55,6 +54,6 @@ class Standard extends ControllerAbstract
*/
public function index($path = null)
{
Layout::view('home');
$this->layout->view('home');
}
}

View File

@ -30,8 +30,8 @@
* @version Version 0.0.1
*/
use FuzeWorks\Helpers;
use FuzeWorks\Logger;
use Fuzeworks\Factory;
/**
* Database Cache Class
@ -64,6 +64,13 @@ class FW_DB_Cache {
*/
public $db;
/**
* The FuzeWorks factory class
*
* @var Fuzeworks\Factory;
*/
private $factory;
// --------------------------------------------------------------------
/**
@ -75,7 +82,8 @@ class FW_DB_Cache {
public function __construct(&$db)
{
// Assign the main CI object to $this->CI and load the file helper since we use it a lot
Helpers::load('file');
$this->factory = Factory::getInstance();
$this->factory->helpers->load('file');
$this->check_path();
}

View File

@ -32,7 +32,7 @@
use FuzeWorks\Logger;
use FuzeWorks\DatabaseException;
use FuzeWorks\Helpers;
use FuzeWorks\Utf8;
use FuzeWorks\Language;
/**
@ -373,6 +373,8 @@ abstract class FW_DB_driver {
}
}
$this->factory = Factory::getInstance();
Logger::log('Database Driver Class Initialized');
}
@ -1181,8 +1183,7 @@ abstract class FW_DB_driver {
*/
protected function _escape_str($str)
{
Helpers::load('common');
return str_replace("'", "''", remove_invisible_characters($str));
return str_replace("'", "''", Utf8::remove_invisible_characters($str));
}
// --------------------------------------------------------------------

View File

@ -78,6 +78,13 @@ abstract class FW_DB_utility {
*/
protected $_repair_table = FALSE;
/**
* The FuzeWorks factory class
*
* @var Fuzeworks\Factory;
*/
private $factory;
// --------------------------------------------------------------------
/**
@ -89,6 +96,7 @@ abstract class FW_DB_utility {
public function __construct(&$db)
{
$this->db =& $db;
$this->factory = Factory::getInstance();
Logger::log('Database Utility Class Initialized');
}
@ -296,7 +304,7 @@ abstract class FW_DB_utility {
extract($params);
// Load the xml helper
Helpers::load('xml');
$this->factory->helpers->load('xml');
// Generate the result
$xml = '<'.$root.'>'.$newline;

View File

@ -30,7 +30,7 @@
* @version Version 0.0.1
*/
use FuzeWorks\Helpers;
use FuzeWorks\Utf8;
/**
* ODBC Database Adapter Class
@ -212,8 +212,7 @@ class FW_DB_odbc_driver extends FW_DB {
*/
protected function _escape_str($str)
{
Helpers::load('common');
return remove_invisible_characters($str);
return Utf8::remove_invisible_characters($str);
}
// --------------------------------------------------------------------

View File

@ -339,8 +339,8 @@ if ( ! function_exists('get_mime_by_extension'))
if ( ! is_array($mimes))
{
FuzeWorks\Helpers::load('common');
$mimes = get_mimes();
$factory = FuzeWorks\Factory::getInstance();
$mimes = $factory->config->get('mimes')->toArray();
if (empty($mimes))
{

View File

@ -31,8 +31,7 @@
*/
namespace FuzeWorks\Library;
use FuzeWorks\Helpers;
use FuzeWorks\Config;
use FuzeWorks\Factory;
/**
* FuzeWorks File Caching Class
@ -55,6 +54,13 @@ class FW_Cache_file extends FW_Driver {
*/
protected $_cache_path;
/**
* The FuzeWorks factory class
*
* @var Fuzeworks\Factory;
*/
private $factory;
/**
* Initialize file-based cache
*
@ -62,10 +68,13 @@ class FW_Cache_file extends FW_Driver {
*/
public function __construct()
{
// Load the required helpers
Helpers::load('file');
// Load the factory
$this->factory = Factory::getInstance();
$path = Config::get('cache')->cache_file_path;
// Load the required helpers
$this->factory->helpers->load('file');
$path = $this->factory->config->get('cache')->cache_file_path;
$this->_cache_path = ($path === '') ? 'Application'.DS.'Cache/' : $path;
}

View File

@ -31,8 +31,7 @@
*/
namespace FuzeWorks\Library;
use FuzeWorks\Logger;
use FuzeWorks\Helpers;
use Fuzeworks\Factory;
/**
* FuzeWorks Zip Compression Class
@ -105,6 +104,13 @@ class FW_Zip {
*/
public $compression_level = 2;
/**
* The FuzeWorks factory class
*
* @var Fuzeworks\Factory;
*/
private $factory;
/**
* Initialize zip compression class
*
@ -113,7 +119,8 @@ class FW_Zip {
public function __construct()
{
$this->now = time();
Logger::log('Zip Compression Class Initialized');
$this->factory = Factory::getInstance();
$this->factory->logger->log('Zip Compression Class Initialized');
}
// --------------------------------------------------------------------
@ -454,7 +461,7 @@ class FW_Zip {
$filename .= '.zip';
}
Helpers::load('download');
$this->factory->helpers->load('download');
$get_zip = $this->get_zip();
$zip_content =& $get_zip;
@ -469,7 +476,7 @@ class FW_Zip {
* Lets you clear current zip data. Useful if you need to create
* multiple zips with different data.
*
* @return CI_Zip
* @return FW_Zip
*/
public function clear_data()
{

View File

@ -0,0 +1,164 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
namespace FuzeWorks\ConfigORM;
use Iterator;
/**
* Abstract ConfigORM class.
*
* This class implements the iterator, so a config file can be accessed using foreach.
* A file can also be returned using toArray(), so it will be converted to an array
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @todo Implement unit tests
*/
abstract class ConfigORMAbstract implements Iterator
{
/**
* The original state of a config file. Can be reverted to using revert().
*
* @var StdObject Config file
*/
protected $originalCfg;
/**
* The current state of a config file.
*
* @var StdObject Config file
*/
protected $cfg;
/**
* Revert to the original conditions of the config file.
*/
public function revert()
{
$this->cfg = $this->originalCfg;
}
/**
* Checks if a requested key is set in the config file.
*
* @param string $name Parameter name
*
* @return bool true on isset, false on not
*/
public function __isset($name)
{
return isset($this->cfg[$name]);
}
/**
* Return a value from a config file.
*
* @param string $name Key of the requested entry
*
* @return mixed Value of the requested entry
*/
public function __get($name)
{
return $this->cfg[$name];
}
/**
* Sets an entry in the config file.
*
* @param string $name Key of the entry
* @param mixed $value Value of the entry
*/
public function __set($name, $value)
{
$this->cfg[$name] = $value;
}
/**
* Unset a value in a config file.
*
* @param string Key of the entry
*/
public function __unset($name)
{
unset($this->cfg[$name]);
}
/**
* Iterator method.
*/
public function rewind()
{
return reset($this->cfg);
}
/**
* Iterator method.
*/
public function current()
{
return current($this->cfg);
}
/**
* Iterator method.
*/
public function key()
{
return key($this->cfg);
}
/**
* Iterator method.
*/
public function next()
{
return next($this->cfg);
}
/**
* Iterator method.
*/
public function valid()
{
return key($this->cfg) !== null;
}
/**
* Returns the config file as an array.
*
* @return array Config file
*/
public function toArray()
{
return $this->cfg;
}
}

View File

@ -40,6 +40,6 @@ namespace FuzeWorks;
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
abstract class ControllerAbstract
abstract class ControllerAbstract extends Factory
{
}

View File

@ -31,452 +31,150 @@
*/
namespace FuzeWorks;
use PDOException;
use FuzeWorks\ORM\ConfigFileORM;
use FuzeWorks\ORM\ConfigDatabaseORM;
use FuzeWorks\ConfigORM\ConfigORM;
/**
* Config Class.
*
* This class gives access to the config files. It allows you to open configurations and edit them.
* This class is extensible, but not yet from the outside
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @todo Implement config extensions
*/
class Config
{
/**
* whether or not the database is active at the moment.
*
* @var bool true on active database
*/
public static $dbActive = false;
/**
* All loaded Config files.
*
* @var array of ConfigORM
* Array where all config files are saved while FuzeWorks runs
*
* @var array Array of all loaded config file ORM's
*/
private static $cfg = array();
protected $cfg = array();
/**
* Loads a config file and returns it as an object.
*
* @param string config file name
* @param string directory, default is Application/Config
*
* @throws \Exception on file not found
*
* @return \FuzeWorks\ORM\ConfigORM of config
* Paths where Helpers can be found.
*
* Libraries will only be loaded if either a directory is supplied or it is in one of the helperPaths
*
* @var array Array of paths where helpers can be found
*/
public static function loadConfigFile($name, $directory = null)
protected $configPaths = array('Application'.DS.'Config');
/**
* Temporary variable to remain compatible with old FuzeWorks code
*
* @deprecated
* @var FuzeWorks\Factory Shared Factory instance
*/
protected static $factory;
/**
* Retrieve a config file object
*
* @param string $configName Name of the config file. Eg. 'main'
* @param array $configPaths Optional array of where to look for the config files
* @return FuzeWorks\ConfigORM\ConfigORM ORM of the config file. Allows for easy reading and editing of the file
* @throws ConfigException
*/
public function getConfig($configName, array $configPaths = array())
{
$dir = (isset($directory) ? $directory : 'Application/Config/');
$file = $dir.'config.'.strtolower($name).'.php';
// First determine what directories to use
$directories = (empty($configPaths) ? $this->configPaths : $configPaths);
// If already loaded, return a reference to the ORM
if (isset(self::$cfg[$name])) {
return $cfg = self::$cfg[$name];
// Determine the config name
$configName = strtolower($configName);
// If it's already loaded, return the existing object
if (isset($this->cfg[$configName]))
{
return $this->cfg[$configName];
}
// Is this the real file?
if (file_exists($file)) {
// Is it just reference?
return $cfg = self::$cfg[$name] = new ConfigFileORM($file);
} else {
// Caught in a datastream
/*$module = Modules::get('core/database');
// No escape from dbactive
if (self::$dbActive) {
// Open your stream
$dborm = new ConfigDatabaseORM($module, $name);
// Lookup for success
if ($dborm->success) {
// And see
return $cfg = self::$cfg[$name] = $dborm;
}
}*/
// I'm just a poor exception
throw new ConfigException("Config file '".strtolower($name)."' was not found", 1);
}
// Otherwise try and load a new one
$this->cfg[$configName] = $this->loadConfigFile($configName, $directories);
return $this->cfg[$configName];
}
/**
* Retrieves a config file from the Application folder
*
* @param string config file name
*
* @return \FuzeWorks\ORM\ConfigORM of config
* Determine whether the file exists and, if so, load the ConfigORM
*
* @param string $configName Name of the config file. Eg. 'main'
* @param array $configPaths Required array of where to look for the config files
* @return FuzeWorks\ConfigORM\ConfigORM ORM of the config file. Allows for easy reading and editing of the file
* @throws ConfigException
*/
public static function get($name)
protected function loadConfigFile($configName, array $configPaths)
{
return self::loadConfigFile($name);
}
}
namespace FuzeWorks\ORM;
use Iterator;
/**
* Abstract ConfigORM class.
*
* This class implements the iterator, so a config file can be accessed using foreach.
* A file can also be returned using toArray(), so it will be converted to an array
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
abstract class ConfigORM implements Iterator
{
/**
* The original state of a config file. Can be reverted to using revert().
*
* @var StdObject Config file
*/
protected $originalCfg;
/**
* The current state of a config file.
*
* @var StdObject Config file
*/
protected $cfg;
/**
* Revert to the original conditions of the config file.
*/
public function revert()
{
$this->cfg = $this->originalCfg;
}
/**
* Checks if a requested key is set in the config file.
*
* @param string $name Parameter name
*
* @return bool true on isset, false on not
*/
public function __isset($name)
{
return isset($this->cfg[$name]);
}
/**
* Return a value from a config file.
*
* @param string $name Key of the requested entry
*
* @return mixed Value of the requested entry
*/
public function __get($name)
{
return $this->cfg[$name];
}
/**
* Sets an entry in the config file.
*
* @param string $name Key of the entry
* @param mixed $value Value of the entry
*/
public function __set($name, $value)
{
$this->cfg[$name] = $value;
}
/**
* Unset a value in a config file.
*
* @param string Key of the entry
*/
public function __unset($name)
{
unset($this->cfg[$name]);
}
/**
* Iterator method.
*/
public function rewind()
{
return reset($this->cfg);
}
/**
* Iterator method.
*/
public function current()
{
return current($this->cfg);
}
/**
* Iterator method.
*/
public function key()
{
return key($this->cfg);
}
/**
* Iterator method.
*/
public function next()
{
return next($this->cfg);
}
/**
* Iterator method.
*/
public function valid()
{
return key($this->cfg) !== null;
}
/**
* Returns the config file as an array.
*
* @return array Config file
*/
public function toArray()
{
return $this->cfg;
}
}
/**
* ORM class for config files in a database.
*
* Handles entries in the database of FuzeWorks and is able to dynamically update them when requested
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
class ConfigDatabaseORM extends ConfigORM
{
/**
* The current connection to the database.
*
* @var \FuzeWorks\Database Database Connection
*/
private $dbh;
/**
* whether the database connection has been successfully established.
*
* @var bool true on success
*/
public $success = false;
/**
* The current filename.
*
* @var string filename
*/
private $file;
/**
* Sets up the class and the connection to the database.
*
* @param \FuzeWorks\Database $db The Database connection
* @param string $filename The current filename
*
* @throws ConfigException on fatal error
*/
public function __construct($db, $filename)
{
$this->dbh = $db;
$this->cfg = $this->openDb($filename);
$this->originalCfg = $this->cfg;
$this->file = $filename;
}
/**
* Opens up a database connection with the requested filename.
*
* @param string $name Name of the file
*
* @return array Content of the file
*
* @throws ConfigException on fatal error
*/
private function openDb($name)
{
$prefix = $this->dbh->getPrefix();
try {
$stmnt = $this->dbh->prepare('SELECT * FROM '.$prefix.'config WHERE `file` = ?');
$stmnt->execute(array($name));
} catch (PDOException $e) {
throw new ConfigException('Could not execute SQL-query due PDO-exception '.$e->getMessage());
}
// Fetch results
$result = $stmnt->fetchAll(\PDO::FETCH_ASSOC);
$return = array();
for ($i = 0; $i < count($result); ++$i) {
$return[ $result[$i]['key'] ] = $result[$i]['value'];
}
// Return if found in DB
if (!empty($return)) {
$this->success = true;
return (array) $return;
}
}
/**
* Write config updates to the database.
*
* @throws ConfigException on fatal error
*/
private function writeDb()
{
// First arrays of all the fields that need to change
$changed_fields = array();
$removed_fields = array();
$new_fields = array();
// First check for changed and new feeds
foreach ($this->cfg as $key => $value) {
if (isset($this->originalCfg[$key])) {
if ($this->originalCfg[$key] != $value) {
// Changed field
$changed_fields[$key] = $value;
}
} else {
// New field
$new_fields[$key] = $value;
// Cycle through all directories
foreach ($configPaths as $directory)
{
// If file exists, load it and break the loop
if (file_exists($directory . DS . 'config.'.$configName.'.php'))
{
// Load object
return new ConfigORM($directory . DS . 'config.'.$configName.'.php');
break;
}
}
// Then check for removed fields
foreach ($this->originalCfg as $key => $value) {
if (!isset($this->cfg[$key])) {
$removed_fields[$key] = $value;
}
}
// First for the removed values
$prefix = $this->dbh->getPrefix();
try {
$stmnt = $this->dbh->prepare('DELETE FROM '.$prefix.'config WHERE `file` = :file AND `key` = :key');
foreach ($removed_fields as $key => $value) {
$stmnt->execute(array('file' => $this->file, 'key' => $key));
}
} catch (PDOException $e) {
throw new ConfigException('Could not change config due to PDOException: '.$e->getMessage(), 1);
}
// Then for the changed values
try {
$stmnt = $this->dbh->prepare('UPDATE '.$prefix.'config SET `value` = :value WHERE `file` = :file AND `key` = :key');
foreach ($changed_fields as $key => $value) {
$stmnt->execute(array('file' => $this->file, 'key' => $key, 'value' => $value));
}
} catch (PDOException $e) {
throw new ConfigException('Could not change config due to PDOException: '.$e->getMessage(), 1);
}
// And finally for the new values
try {
$stmnt = $this->dbh->prepare('INSERT INTO '.$prefix.'config (`file`,`key`,`value`) VALUES (:file,:key,:value)');
foreach ($new_fields as $key => $value) {
$stmnt->execute(array('file' => $this->file, 'key' => $key, 'value' => $value));
}
} catch (PDOException $e) {
throw new ConfigException('Could not change config due to PDOException: '.$e->getMessage(), 1);
}
throw new ConfigException("Could not load config. File not found", 1);
}
/**
* Write updates of the config file to the database.
*
* @throws ConfigException on fatal error
* Load a config file in a static environment.
*
* @deprecated
* @param string $configName Name of the config file. Eg. 'main'
* @return FuzeWorks\ConfigORM\ConfigORM ORM of the config file. Allows for easy reading and editing of the file
* @throws ConfigException
*/
public function commit()
public static function get($configName)
{
$this->writeDb();
if (!is_object(self::$factory))
{
self::$factory = Factory::getInstance();
}
$config = self::$factory->config;
return $config->getConfig($configName);
}
}
/**
* ORM class for config files in PHP files.
*
* Handles entries in the config directory of FuzeWorks and is able to dynamically update them when requested
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
class ConfigFileORM extends ConfigORM
{
/**
* The current filename.
*
* @var string filename
*/
private $file;
/**
* Sets up the class and the connection to the PHP file.
*
* @param string $filename The current filename
*
* @throws ConfigException on fatal error
* Add a path where config files can be found
*
* @param string $directory The directory
* @return void
*/
public function __construct($file)
public function addConfigPath($directory)
{
if (file_exists($file)) {
$this->file = $file;
$this->openFile($file);
$this->originalCfg = $this->cfg;
} else {
throw new ConfigException('Could not load config file. Config file does not exist', 1);
if (!in_array($directory, $this->configPaths))
{
$this->configPaths[] = $directory;
}
}
/**
* Opens the file and returns the data.
*
* @param string $file Name of the config file
*
* @return array Content of the file
*/
private function openFile($file)
* Remove a path where config files can be found
*
* @param string $directory The directory
* @return void
*/
public function removeConfigPath($directory)
{
$this->cfg = (array) include $file;
}
/**
* Updates the config file and writes it to the database.
*
* @throws ConfigException on fatal error
*/
private function writeFile()
{
// Implement writing here
if (is_writable($this->file)) {
$config = var_export($this->cfg, true);
file_put_contents($this->file, "<?php return $config ;");
return true;
if (($key = array_search($directory, $this->configPaths)) !== false)
{
unset($this->configPaths[$key]);
}
throw new ConfigException("Could not write config file. $file is not writable", 1);
}
/**
* Updates the config file and writes it.
*
* @throws ConfigException on fatal error
* Get a list of all current configPaths
*
* @return array Array of paths where config files can be found
*/
public function commit()
public function getConfigPaths()
{
$this->writeFile();
return $this->configPaths;
}
}
}

View File

@ -0,0 +1,95 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
namespace FuzeWorks\ConfigORM;
use ConfigException;
/**
* ORM class for config files in PHP files.
*
* Handles entries in the config directory of FuzeWorks and is able to dynamically update them when requested
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @todo Implement unit tests
*/
class ConfigORM extends ConfigORMAbstract
{
/**
* The current filename.
*
* @var string filename
*/
private $file;
/**
* Sets up the class and the connection to the PHP file.
*
* @param string $filename The current filename
*
* @throws ConfigException on fatal error
*/
public function __construct($file = null)
{
if (is_null($file))
{
throw new ConfigException('Could not load config file. No file provided', 1);
}
elseif (file_exists($file))
{
$this->file = $file;
$this->cfg = (array) include $file;
$this->originalCfg = $this->cfg;
}
else
{
throw new ConfigException('Could not load config file. Config file does not exist', 1);
}
}
/**
* Updates the config file and writes it.
*
* @throws ConfigException on fatal error
*/
public function commit()
{
// Write the changes
if (is_writable($this->file)) {
$config = var_export($this->cfg, true);
file_put_contents($this->file, "<?php return $config ;");
return true;
}
throw new ConfigException("Could not write config file. $file is not writable", 1);
}
}

View File

@ -127,11 +127,14 @@ class Core
}
// Load core abstracts
include_once 'Core/System/class.factory.php';
include_once 'Core/System/class.exceptions.php';
include_once 'Core/System/class.abstract.event.php';
// Load the core classes
include_once 'Core/System/class.config.php';
include_once 'Core/System/class.abstract.configOrmAbstract.php';
include_once 'Core/System/class.configOrm.php';
include_once 'Core/System/class.abstract.eventPriority.php';
include_once 'Core/System/class.events.php';
include_once 'Core/System/class.logger.php';
@ -151,25 +154,8 @@ class Core
include_once 'Core/System/class.security.php';
include_once 'Core/System/class.input.php';
include_once 'Core/System/class.output.php';
include_once 'Core/System/class.factory.php';
// Load the core classes
new Config();
new Logger();
new Events();
new Models();
new Layout();
new Modules();
new Libraries();
new Helpers();
new Database();
new Language();
new Utf8();
new URI();
new Security();
new Input();
new Router();
new Output();
new Factory();
self::$loaded = true;

View File

@ -144,6 +144,8 @@ class Events
* The Event gets created, passed around and then returned to the issuer.
*
* @param mixed $input Object for direct event, string for system event or notifierEvent
* @todo Implement Application Events
* @todo Implement Directory input for Events from other locations (like Modules)
*
* @return \FuzeWorks\Event The Event
*/

View File

@ -180,4 +180,14 @@ class UriException extends Exception
*/
class SecurityException extends Exception
{
}
/**
* Class FactoryException.
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
class FactoryException extends Exception
{
}

View File

@ -33,119 +33,268 @@
namespace FuzeWorks;
/**
*
* Factory Class.
*
* The Factory class is the central point for class communication in FuzeWorks.
* When someone needs to load, for instance, the layout class, one has to do the following:
* $factory = Factory::getInstance();
* $layout = $factory->layout;
*
* The Factory class allows the user to replace dependencies on the fly. It is possible for a class
* to replace a dependency, like Logger, on the fly by calling the $factory->newInstance('Logger'); or the
* $factory->setInstance('Logger', $object); This allows for creative ways to do dependency injection, or keep classes
* separated.
*
* It is also possible to load a cloned instance of the Factory class, so that all properties are independant as well,
* all to suit your very needs.
*
* The Factory class is also extendible. This allows classes that extend Factory to access all it's properties.
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
class Factory
{
/**
* The Factory instance that is shared by default when calling Factory::getInstance();
*
* @var FuzeWorks\Factory Default shared instance
*/
private static $sharedFactoryInstance;
private $instances = array();
/**
* Whether to clone all Factory instances upon calling Factory::getInstance()
*
* @var bool Clone all Factory instances.
*/
protected static $cloneInstances = false;
/**
* Array of all the classes loaded by this specific instance of the Factory
*
* @var array Array of all loaded classes in THIS Factory
*/
protected $instances = array();
/**
* Factory instance constructor. Should only really be called once
* @return void
*/
public function __construct()
{
$this->instances['Layout'] = new Layout();
self::$sharedFactoryInstance = $this;
// If there is no sharedFactoryInstance, prepare it
if (is_null(self::$sharedFactoryInstance))
{
self::$sharedFactoryInstance = $this;
$this->instances['Config'] = new Config();
$this->instances['Logger'] = new Logger();
$this->instances['Events'] = new Events();
$this->instances['Models'] = new Models();
$this->instances['Layout'] = new Layout();
$this->instances['Modules'] = new Modules();
$this->instances['Libraries'] = new Libraries();
$this->instances['Helpers'] = new Helpers();
$this->instances['Database'] = new Database();
$this->instances['Language'] = new Language();
$this->instances['Utf8'] = new Utf8();
$this->instances['URI'] = new URI();
$this->instances['Security'] = new Security();
$this->instances['Input'] = new Input();
$this->instances['Router'] = new Router();
$this->instances['Output'] = new Output();
return true;
}
// Otherwise, copy the existing instances
$this->instances = self::getInstance()->getClassInstances();
return true;
}
/**
* Get a new instance of the Factory class.
*
* @param bool $cloneInstance Whether to get a cloned instance (true) or exactly the same instance (false)
* @return FuzeWorks\Factory Factory Instance
*/
public static function getInstance($cloneInstance = false)
{
if ($cloneInstance === true || self::$cloneInstances === true)
{
return clone self::$sharedFactoryInstance;
}
return self::$sharedFactoryInstance;
}
/**
* Enable cloning all Factory instances upon calling Factory::getInstance()
*
* @return void
*/
public static function enableCloneInstances()
{
self::$cloneInstances = true;
}
/**
* Disable cloning all Factory instances upon calling Factory::getInstance()
*
* @return void
*/
public static function disableCloneInstances()
{
self::$cloneInstances = false;
}
/**
* Return the instance array where all the instances are loaded
*
* @return array Array of all loaded classes in THIS Factory
*/
public function getClassInstances()
{
return $this->instances;
}
/**
* Create a new instance of one of the loaded classes.
* It reloads the class. It does NOT clone it.
*
* @param string $className The name of the loaded class, WITHOUT the namespace
* @param string $namespace Optional namespace. Defaults to 'FuzeWorks\'
* @return FuzeWorks\Factory Factory Instance
*/
public function newInstance($className, $namespace = 'FuzeWorks\\')
{
// Determine the class to load
$instanceName = ucfirst($className);
$className = $namespace.$instanceName;
if (!isset($this->instances[$instanceName]))
{
throw new FactoryException("Could not load new instance of '".$instanceName."'. Instance was not found.", 1);
}
elseif (!class_exists($className, false))
{
throw new FactoryException("Could not load new instance of '".$instanceName."'. Class not found.", 1);
}
// Remove the current instance
unset($this->instances[$instanceName]);
// And set the new one
$this->instances[$instanceName] = new $className();
// Return itself
return $this;
}
public static function getInstance()
/**
* Clone an instance of one of the loaded classes.
* It clones the class. It does NOT re-create it.
*
* @param string $className The name of the loaded class, WITHOUT the namespace
* @return FuzeWorks\Factory Factory Instance
*/
public function cloneInstance($className)
{
return clone self::$sharedFactoryInstance;
// Determine the class to load
$instanceName = ucfirst($className);
if (!isset($this->instances[$instanceName]))
{
throw new FactoryException("Could not clone instance of '".$instanceName."'. Instance was not found.", 1);
}
// Clone the instance
$this->instances[$instanceName] = clone $this->instances[$instanceName];
// Return itself
return $this;
}
public function getConfig()
/**
* Set an instance of one of the loaded classes with your own $object.
* Replace the existing class with one of your own.
*
* @param string $className The name of the loaded class, WITHOUT the namespace
* @param mixed $object Object to replace the class with
* @return FuzeWorks\Factory Factory Instance
*/
public function setInstance($className, $object)
{
return new Config();
// Determine the instance name
$instanceName = ucfirst($className);
// Unset and set
unset($this->instances[$instanceName]);
$this->instances[$instanceName] = $object;
// Return itself
return $this;
}
public function getCore()
/**
* Remove an instance of one of the loaded classes.
*
* @param string $className The name of the loaded class, WITHOUT the namespace
* @return FuzeWorks\Factory Factory Instance
*/
public function removeInstance($className)
{
// Determine the instance name
$instanceName = ucfirst($className);
if (!isset($this->instances[$instanceName]))
{
throw new FactoryException("Could not remove instance of '".$instanceName."'. Instance was not found.", 1);
}
// Unset
unset($this->instances[$instanceName]);
// Return itself
return $this;
}
public function getDatabase()
/**
* Get one of the loaded classes. Overloading method.
*
* @param string $objectName Name of the class to get
* @return mixed The class requested
*/
public function __get($objectName)
{
if (isset($this->instances[ucfirst($objectName)]))
{
return $this->instances[ucfirst($objectName)];
}
return null;
}
public function getEvents()
/**
* Test if a class is set to the Factory instance
*
* @param string $objectName Name of the class to get
* @return bool Whether the class is set
*/
public function __isset($objectName)
{
return isset($this->instances[ucfirst($objectName)]);
}
public function getHelpers()
/**
* Unset a class set to the Factory instance
*
* @param string $objectName Name of the class to get
* @return void
*/
public function __unset($objectName)
{
unset($this->instances[ucfirst($objectName)]);
}
public function getInput()
{
}
public function getLanguage()
{
}
public function getLayout()
{
return $this->instances['Layout'];
}
public function getLibraries()
{
}
public function getLogger()
{
}
public function getModels()
{
}
public function getModules()
{
}
public function getOutput()
{
}
public function getRouter()
{
}
public function getSecurity()
{
}
public function getUri()
{
}
public function getUtf8()
{
}
}

View File

@ -35,7 +35,18 @@ namespace FuzeWorks;
/**
* Helpers Class.
*
* @todo Add documentation
* Helpers, as the name suggests, help you with tasks.
*
* Each helper file is simply a collection of functions in a particular category.
* There are URL Helpers, that assist in creating links, there are Form Helpers that help you create form elements,
* Text Helpers perform various text formatting routines, Cookie Helpers set and read cookies,
* File Helpers help you deal with files, etc.
*
* Unlike most other systems in FuzeWorks, Helpers are not written in an Object Oriented format.
* They are simple, procedural functions. Each helper function performs one specific task, with no dependence on other functions.
*
* FuzeWorks does not load Helper Files by default, so the first step in using a Helper is to load it. Once loaded,
* it becomes globally available to everything.
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
@ -43,20 +54,42 @@ namespace FuzeWorks;
class Helpers
{
protected static $helpers = array();
/**
* Array of loadedHelpers, so that they won't be reloaded
*
* @var array Array of loaded helperNames
*/
protected $helpers = array();
protected static $helperPaths = array('Application'.DS.'Helpers', 'Core'.DS.'Helpers');
/**
* Paths where Helpers can be found.
*
* Libraries will only be loaded if either a directory is supplied or it is in one of the helperPaths
*
* @var array Array of paths where helpers can be found
*/
protected $helperPaths = array('Application'.DS.'Helpers', 'Core'.DS.'Helpers');
public static function load($helperName, $directory = null)
/**
* Load a helper.
*
* Supply the name and the helper will be loaded from the supplied directory,
* or from one of the helperPaths (which you can add).
*
* @param string $helperName Name of the helper
* @param string|null $directory Directory to load the helper from, will ignore $helperPaths
* @return bool Whether the helper was succesfully loaded (true if yes)
*/
public function load($helperName, $directory = null)
{
// First determine the name of the helper
$helperName = strtolower(str_replace(array('_helper', '.php'), '', $helperName).'_helper');
// Determine what directories should be checked
$directories = (is_null($directory) ? self::$helperPaths : array($directory));
$directories = (is_null($directory) ? $this->helperPaths : array($directory));
// Check it is already loaded
if (isset($helpers[$helperName]))
if (isset($this->helpers[$helperName]))
{
Logger::log("Helper '".$helperName."' is already loaded. Skipping");
return false;
@ -94,7 +127,7 @@ class Helpers
include_once($event->extendedHelperFile);
include_once($event->helperFile);
self::$helpers[$event->helperName] = true;
$this->helpers[$event->helperName] = true;
Logger::log("Loading base helper '".$event->helperName."' and extended helper '".$event->extendedHelperName."'");
return true;
}
@ -115,7 +148,7 @@ class Helpers
}
include_once($event->helperFile);
self::$helpers[$event->helperName] = true;
$this->helpers[$event->helperName] = true;
Logger::log("Loading helper '".$event->helperName."'");
return true;
}
@ -124,29 +157,54 @@ class Helpers
throw new HelperException("Could not load helper. Helper not found.", 1);
}
public static function get($helperName, $directory = null)
/**
* Alias for load
* @see load
*
* @param string $helperName Name of the helper
* @param string|null $directory Directory to load the helper from, will ignore $helperPaths
* @return bool Whether the helper was succesfully loaded (true if yes)
*/
public function get($helperName, $directory = null)
{
return self::load($helperName, $directory);
return $this->load($helperName, $directory);
}
public static function addHelperPath($directory)
/**
* Add a path where helpers can be found
*
* @param string $directory The directory
* @return void
*/
public function addHelperPath($directory)
{
if (!in_array($directory, $directories))
if (!in_array($directory, $this->helperPaths))
{
$directories[] = $directory;
$this->helperPaths[] = $directory;
}
}
public static function removeHelperPath($directory)
/**
* Remove a path where helpers can be found
*
* @param string $directory The directory
* @return void
*/
public function removeHelperPath($directory)
{
if (($key = array_search($directory, $directories)) !== false)
if (($key = array_search($directory, $this->helperPaths)) !== false)
{
unset($directories[$key]);
unset($this->helperPaths[$key]);
}
}
public static function getHelperPaths()
/**
* Get a list of all current helperPaths
*
* @return array Array of paths where helpers can be found
*/
public function getHelperPaths()
{
return $directories;
return $this->helperPaths;
}
}

View File

@ -115,6 +115,13 @@ class Input {
*/
protected $_input_stream;
/**
* Factory object, allows this class to communicate with everything in FuzeWorks
*
* @var Factory
*/
protected $factory;
// --------------------------------------------------------------------
/**
@ -127,6 +134,9 @@ class Input {
*/
public function __construct()
{
// First load the factory so contact can be made with everything in FuzeWorks
$this->factory = Factory::getInstance();
$this->_allow_get_array = (Config::get('routing')->allow_get_array === TRUE);
$this->_enable_xss = (Config::get('security')->global_xss_filtering === TRUE);
$this->_enable_csrf = (Config::get('security')->csrf_protection === TRUE);
@ -138,7 +148,7 @@ class Input {
// CSRF Protection check
if ($this->_enable_csrf === TRUE && ! $this->is_cli_request())
{
Security::csrf_verify();
$this->factory->security->csrf_verify();
}
}
@ -204,7 +214,7 @@ class Input {
}
return ($xss_clean === TRUE)
? Security::xss_clean($value)
? $this->factory->security->xss_clean($value)
: $value;
}
@ -801,7 +811,7 @@ class Input {
}
return ($xss_clean === TRUE)
? Security::xss_clean($headers[$index])
? $this->factory->security->xss_clean($headers[$index])
: $headers[$index];
}

View File

@ -228,6 +228,11 @@ class Layout
{
$directory = preg_replace('#/+#', '/', (!is_null($directory) ? $directory : self::$directory).'/');
if (strpbrk($directory, "\\/?%*:|\"<>") === TRUE || strpbrk($string, "\\/?%*:|\"<>") === TRUE)
{
throw new LayoutException('Could not get file. Invalid file string', 1);
}
if (!file_exists($directory)) {
throw new LayoutException('Could not get file. Directory does not exist', 1);
}
@ -363,6 +368,10 @@ class Layout
*/
public static function getTitle()
{
if (!isset(self::$assigned_variables['title']))
{
return false;
}
return self::$assigned_variables['title'];
}
@ -494,6 +503,12 @@ class Layout
if (!is_null(self::$current_engine)) {
self::$current_engine->reset();
}
// Unload the engines
self::$engines = array();
self::$engines_loaded = false;
self::$file_extensions = array();
self::$current_engine = null;
self::$assigned_variables = array();
self::$directory = 'Application/Views';
@ -800,7 +815,7 @@ class JSONEngine implements TemplateEngine
public function reset()
{
$this->assigned_variables = array();
$this->string_return = true;
self::$string_return = true;
}
public function test($param1, $param2, $param3)

View File

@ -33,30 +33,99 @@
namespace FuzeWorks;
/**
* @todo add documentation
* @todo Add configuration load if no config parameter provided
* Libraries Class.
*
* FuzeWorks allows the user to use the built-in libraries as-is, and use it's functionality to get jobs done.
*
* If a user wants to make their own libraries, they have, in general, 3 options:
* 1. Create a completely new library
* 2. Extend an existing library
* 3. Replace an existing library
*
* The first option is done by adding a new library to the Application/Libraries folder. If the library name is 'Example' then the
* file should be 'Application/Libraries/Example.php' and the classname should be Example. Code can be added and it can be
* loaded through Libraries->get('example');.
*
* The second option allows the user to extend an existing core library. All functionality will be inherited in that situation. Let's take
* the 'Zip' library as an example. The user needs to create a file in Application/Libraries. The name of the file and the class depend on
* the configuration of FuzeWorks. The extended class needs to get a prefix, which is defined in config.main.php. By default, this is 'MY_'.
* The user needs to create the file 'Application/Libraries/MY_Zip.php' with the classname MY_Zip. It can be loaded through Libraries->get('zip');.
*
* The third option allows the user to replace a system library with their own. Doing so could potentially break systems, so be careful.
* If, for example we want to replace the Zip library, we need to create the file 'Application/Libraries/Zip.php' with the classname FW_Zip.
* 'FW_' is the prefix for all FuzeWorks core libraries. And that's it. It can be loaded through Libraries->get('zip');.
*
* @todo Implement events
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
class Libraries
{
protected static $libraryPaths = array('Core'.DS.'Libraries', 'Application'.DS.'Libraries');
/**
* Factory object for interaction with FuzeWorks
*
* @var Factory
*/
protected $factory;
protected static $libraries = array();
/**
* Array of all the paths where libraries can be found
*
* @var array Library paths
*/
protected $libraryPaths = array('Core'.DS.'Libraries', 'Application'.DS.'Libraries');
public static function get($libraryName, array $parameters = null, $directory = null, $keepInstance = false)
/**
* Array of all the loaded library objects
*
* @var array All the loaded library objects, so they can be returned when reloading
*/
protected $libraries = array();
/**
* Attach the Factory to this class
*/
public function __construct()
{
$this->factory = Factory::getInstance();
}
/**
* Library Loader
*
* Loads, instantiates and returns libraries.
*
* @param string $library Library name
* @param array $params Optional parameters to pass to the library class constructor
* @param array $directory Optional list of directories where the library can be found. Overrides default list
* @param bool $newInstance Whether to return a new instance of the library or the same one
* @return object
* @throws LibraryException
*/
public function get($libraryName, array $parameters = null, array $directory = null, $newInstance = false)
{
if (empty($libraryName))
{
throw new LibraryException("Could not load library. No name provided", 1);
}
return self::loadLibrary($libraryName, $parameters, $directory, $keepInstance);
return $this->loadLibrary($libraryName, $parameters, $directory, $newInstance);
}
public static function getDriver($libraryName, array $parameters = null, $directory = null, $keepInstance = false)
/**
* Driver Library Loader
*
* Loads, instantiates and returns driver libraries.
*
* @param string $library Driver Library name
* @param array $params Optional parameters to pass to the library class constructor
* @param array $directory Optional list of directories where the library can be found. Overrides default list
* @param bool $newInstance Whether to return a new instance of the library or the same one
* @return object
* @throws LibraryException
*/
public function getDriver($libraryName, array $parameters = null, array $directory = null, $newInstance = false)
{
if (empty($libraryName))
{
@ -70,13 +139,25 @@ class Libraries
}
// And then load and return the library
return self::loadLibrary($libraryName, $parameters, $directory, $keepInstance);
return $this->loadLibrary($libraryName, $parameters, $directory, $newInstance);
}
private static function loadLibrary($libraryName, $parameters = null, $directory = null, $keepInstance = false)
/**
* Internal Library Loader
*
* Determines what type of library needs to be loaded
*
* @param string $library Library name
* @param array $params Optional parameters to pass to the library class constructor
* @param array $directory Optional list of directories where the library can be found. Overrides default list
* @param bool $newInstance Whether to return a new instance of the library or the same one
* @return object
* @throws LibraryException
*/
protected function loadLibrary($libraryName, $parameters = null, array $directory = null, $newInstance = false)
{
// First get the directories where the library can be located
$directories = (is_null($directory) ? self::$libraryPaths : array($directory));
$directories = (is_null($directory) ? $this->libraryPaths : $directory);
// Now figure out the className and subdir
$class = trim($libraryName, '/');
@ -99,14 +180,27 @@ class Libraries
if (file_exists('Core'.DS.'Libraries'.DS.$subdir.$class.'.php'))
{
// Load base library
return self::loadCoreLibrary($class, $subdir, $parameters, $directories, $keepInstance);
return $this->loadCoreLibrary($class, $subdir, $parameters, $directories, $newInstance);
}
// Otherwise try and load an Application Library
return self::loadAppLibrary($class, $subdir, $parameters, $directories, $keepInstance);
return $this->loadAppLibrary($class, $subdir, $parameters, $directories, $newInstance);
}
private static function loadCoreLibrary($class, $subdir, $parameters, array $directories, $keepInstance = false)
/**
* Core Library Loader
*
* Loads, instantiates and returns a core library.
*
* @param string $class Classname
* @param string $subdir Sub directory in which the final class can be found
* @param array $params Optional parameters to pass to the library class constructor
* @param array $directory Optional list of directories where the library can be found. Overrides default list
* @param bool $newInstance Whether to return a new instance of the library or the same one
* @return object
* @throws LibraryException
*/
protected function loadCoreLibrary($class, $subdir, array $parameters = null, array $directories, $newInstance = false)
{
// First check if the input is correct
if (!is_array($directories))
@ -128,25 +222,28 @@ class Libraries
$prefix = $appPrefix;
}
if (!isset(self::$libraries[$prefix.$class]))
if (!isset($this->libraries[$prefix.$class]))
{
return self::initLibrary($prefix.$class, $parameters);
return $this->initLibrary($prefix.$class, $parameters);
}
// If required to do so, return the existing instance or load a new one
if ($keepInstance)
if ($newInstance)
{
Logger::log("Library '".$prefix.$class."' already loaded. Returning existing instance");
return self::$libraries[$prefix.$class];
$this->factory->logger->log("Library '".$prefix.$class."' already loaded. Returning existing instance");
return $this->libraries[$prefix.$class];
}
Logger::log("Library '".$prefix.$class."' already loaded. Returning new instance");
return self::initLibrary($prefix.$class, $parameters);
$this->factory->logger->log("Library '".$prefix.$class."' already loaded. Returning new instance");
return $this->initLibrary($prefix.$class, $parameters);
}
// Remove the core directory from the checklist
array_shift($directories);
if (in_array('Core'.DS.'Libraries', $directories))
{
array_shift($directories);
}
// First check the directories for the core library (the FW_ class)
foreach ($directories as $directory)
{
@ -159,12 +256,12 @@ class Libraries
include_once($file);
if (class_exists($prefix.$class, false))
{
return self::initLibrary($prefix.$class, $parameters);
return $this->initLibrary($prefix.$class, $parameters);
}
else
{
// Otherwise log a message
Logger::logWarning("File ".$file." exists but does not declare $prefix$class");
$this->factory->logger->logWarning("File ".$file." exists but does not declare $prefix$class");
}
}
}
@ -173,7 +270,7 @@ class Libraries
include_once('Core'.DS.'Libraries'.DS.$subdir.$class.'.php');
// Now let's check for extensions
$subclass = Config::get('main')->application_prefix . $class;
$subclass = $this->factory->config->getConfig('main')->application_prefix . $class;
foreach ($directories as $directory)
{
$file = $directory . DS . $subdir . $subclass . '.php';
@ -184,11 +281,11 @@ class Libraries
include_once($file);
if (class_exists($appPrefix.$class, false))
{
return self::initLibrary($appPrefix.$class, $parameters);
return $this->initLibrary($appPrefix.$class, $parameters);
}
else
{
Logger::logWarning("File ".$file." exists but does not declare $prefix$class");
$this->factory->logger->logWarning("File ".$file." exists but does not declare $prefix$class");
}
}
}
@ -196,13 +293,27 @@ class Libraries
// Third and last base; just load the FW_ core class
if (class_exists('\FuzeWorks\Library\FW_'.$class, false))
{
return self::initLibrary('\FuzeWorks\Library\FW_'.$class, $parameters);
return $this->initLibrary('\FuzeWorks\Library\FW_'.$class, $parameters);
}
throw new LibraryException("Could not load library. File ".'Core'.DS.'Libraries'.DS.$subdir.$class.'.php'." exists but does not declare \FuzeWorks\Library\FW_$class", 1);
}
private static function loadAppLibrary($class, $subdir, $parameters, array $directories, $keepInstance = false)
/**
* Application Library Loader
*
* Loads, instantiates and returns an application library.
* Could possibly extend a core library if requested.
*
* @param string $class Classname
* @param string $subdir Sub directory in which the final class can be found
* @param array $params Optional parameters to pass to the library class constructor
* @param array $directory Optional list of directories where the library can be found. Overrides default list
* @param bool $newInstance Whether to return a new instance of the library or the same one
* @return object
* @throws LibraryException
*/
protected function loadAppLibrary($class, $subdir, array $parameters = null, array $directories, $newInstance = false)
{
// First check if the input is correct
if (!is_array($directories))
@ -227,40 +338,51 @@ class Libraries
if (class_exists($className, false))
{
// Return existing instance
if (!isset(self::$libraries[$className]))
if (!isset($this->libraries[$className]))
{
return self::initLibrary($className, $parameters);
return $this->initLibrary($className, $parameters);
}
// If required to do so, return the existing instance or load a new one
if ($keepInstance)
if ($newInstance)
{
Logger::log("Library '".$className."' already loaded. Returning existing instance");
return self::$libraries[$prefix.$class];
$this->factory->logger->log("Library '".$className."' already loaded. Returning existing instance");
return $this->libraries[$prefix.$class];
}
Logger::log("Library '".$className."' already loaded. Returning new instance");
return self::initLibrary($className, $parameters);
$this->factory->logger->log("Library '".$className."' already loaded. Returning new instance");
return $this->initLibrary($className, $parameters);
}
// Otherwise load the file first
if (file_exists($file))
{
include_once($file);
return self::initLibrary($className, $parameters);
return $this->initLibrary($className, $parameters);
}
}
// Maybe it's in a subdirectory with the same name as the class
if ($subdir === '')
{
return self::loadLibrary($class."/".$class, $parameters, $directories, $keepInstance);
}
// Maybe it's in a subdirectory with the same name as the class
if ($subdir === '')
{
return $this->loadLibrary($class."/".$class, $parameters, $directories, $newInstance);
}
throw new LibraryException("Could not load library. Library was not found", 1);
}
private static function initLibrary($class, $parameters)
/**
* Library Initializer
*
* Instantiates and returns a library.
* Determines whether to use the parameters array or a config file
*
* @param string $class Classname
* @param array $params Optional parameters to pass to the library class constructor
* @return object
* @throws LibraryException
*/
protected function initLibrary($class, array $parameters = null)
{
// First check to see if the library is already loaded
if (!class_exists($class, false))
@ -268,42 +390,69 @@ class Libraries
throw new LibraryException("Could not initiate library. Class not found", 1);
}
// Check if the adress is already reserved
if (isset(self::$libraries[$class]))
// Determine what parameters to use
if (is_null($parameters) || empty($parameters))
{
try {
$parameters = $this->factory->config->getConfig(strtolower($class))->toArray();
} catch (ConfigException $e) {
// No problem, just use an empty array instead
$parameters = array();
}
}
// Check if the adress is already reserved, if it is, we can presume that a new instance is requested.
// Otherwise this code would not be reached
if (isset($this->libraries[$class]))
{
$parameters = (is_null($parameters) ? array() : $parameters);
$classObject = new $class($parameters);
Logger::log("Loaded new Library instance of: ".$class);
$this->factory->logger->log("Loaded new Library instance of: ".$class);
return $classObject;
}
else
{
// Now load the class
$parameters = (is_null($parameters) ? array() : $parameters);
self::$libraries[$class] = new $class($parameters);
Logger::log("Loaded Library: ".$class);
return $c = self::$libraries[$class];
$this->libraries[$class] = new $class($parameters);
$this->factory->logger->log("Loaded Library: ".$class);
return $this->libraries[$class];
}
}
public static function addLibraryPath($directory)
/**
* Add a path where libraries can be found
*
* @param string $directory The directory
* @return void
*/
public function addLibraryPath($directory)
{
if (!in_array($directory, self::$libraryPaths))
if (!in_array($directory, $this->libraryPaths))
{
self::$libraryPaths[] = $directory;
$this->libraryPaths[] = $directory;
}
}
public static function removeLibraryPath($directory)
/**
* Remove a path where libraries can be found
*
* @param string $directory The directory
* @return void
*/
public function removeLibraryPath($directory)
{
if (($key = array_search($directory, self::$libraryPaths)) !== false)
if (($key = array_search($directory, $this->libraryPaths)) !== false)
{
unset(self::$libraryPaths[$key]);
unset($this->libraryPaths[$key]);
}
}
public static function getLibraryPaths()
/**
* Get a list of all current libraryPaths
*
* @return array Array of paths where libraries can be found
*/
public function getLibraryPaths()
{
return self::$libraryPaths;
return $this->libraryPaths;
}
}

View File

@ -87,6 +87,20 @@ class Logger {
*/
private static $print_to_screen = false;
/**
* whether to output the log to a file after FuzeWorks has run.
*
* @var bool
*/
private static $log_to_file = false;
/**
* The template to use when parsing the debug log
*
* @var string Template name
*/
private static $logger_template = 'logger_default';
/**
* whether to output the log after FuzeWorks has run, regardless of conditions.
*
@ -114,6 +128,8 @@ class Logger {
error_reporting(false);
}
self::$debug = Config::get('error')->debug;
self::$log_to_file = Config::get('error')->log_to_file;
self::$logger_template = Config::get('error')->logger_template;
self::newLevel('Logger Initiated');
}
@ -145,7 +161,12 @@ class Logger {
if (self::$debug == true || self::$print_to_screen) {
self::log('Parsing debug log');
echo self::logToScreen();
self::logToScreen();
}
if (self::$log_to_file == true)
{
self::logToFile();
}
}
@ -187,6 +208,16 @@ class Logger {
self::logError('Exception thrown: ' . $message . ' | ' . $code, null, $file, $line);
}
/**
* Set the template that FuzeWorks should use to parse debug logs
*
* @var string Name of the template file
*/
public static function setLoggerTemplate($templateName)
{
self::$logger_template = $templateName;
}
/**
* Output the entire log to the screen. Used for debugging problems with your code.
*
@ -199,33 +230,21 @@ class Logger {
return false;
}
// Otherwise just load it
$string = '<h3>FuzeWorks debug log</h3>';
$layer = 0;
for ($i = 0; $i < count(self::$Logs); ++$i) {
$log = self::$Logs[$i];
if ($log['type'] == 'LEVEL_START') {
++$layer;
$color = 255 - ($layer * 25);
$string .= '<div style="background: rgb(188 , 232 ,' . $color . ');border: 1px black solid;margin: 5px 0;padding: 5px 20px;">';
$string .= '<div style="font-weight: bold; font-size: 11pt;">' . $log['message'] . '<span style="float: right">' . (!empty($log['runtime']) ? '(' . round($log['runtime'] * 1000, 4) . 'ms)' : '') . '</span></div>';
} elseif ($log['type'] == 'LEVEL_STOP') {
--$layer;
$string .= '</div>';
} elseif ($log['type'] == 'ERROR') {
$string .= '<div style="' . ($layer == 0 ? 'padding-left: 21px;' : '') . 'font-size: 11pt; background-color:#f56954;">[' . $log['type'] . ']' . (!empty($log['context']) && is_string($log['context']) ? '<u>[' . $log['context'] . ']</u>' : '') . ' ' . $log['message'] . '
<span style="float: right">' . (!empty($log['logFile']) ? $log['logFile'] : '') . ' : ' . (!empty($log['logLine']) ? $log['logLine'] : '') . '(' . round($log['runtime'] * 1000, 4) . ' ms)</span></div>';
} elseif ($log['type'] == 'WARNING') {
$string .= '<div style="' . ($layer == 0 ? 'padding-left: 21px;' : '') . 'font-size: 11pt; background-color:#f39c12;">[' . $log['type'] . ']' . (!empty($log['context']) && is_string($log['context']) ? '<u>[' . $log['context'] . ']</u>' : '') . ' ' . $log['message'] . '
<span style="float: right">' . (!empty($log['logFile']) ? $log['logFile'] : '') . ' : ' . (!empty($log['logLine']) ? $log['logLine'] : '') . '(' . round($log['runtime'] * 1000, 4) . ' ms)</span></div>';
} elseif ($log['type'] == 'INFO') {
$string .= '<div style="' . ($layer == 0 ? 'padding-left: 21px;' : '') . 'font-size: 11pt;">' . (!empty($log['context']) ? '<u>[' . $log['context'] . ']</u>' : '') . ' ' . $log['message'] . '<span style="float: right">(' . round($log['runtime'] * 1000, 4) . ' ms)</span></div>';
} elseif ($log['type'] == 'DEBUG') {
$string .= '<div style="' . ($layer == 0 ? 'padding-left: 21px;' : '') . 'font-size: 11pt; background-color:#CCCCCC;">[' . $log['type'] . ']' . (!empty($log['context']) ? '<u>[' . $log['context'] . ']</u>' : '') . ' ' . $log['message'] . '<span style="float: right">(' . round($log['runtime'] * 1000, 4) . ' ms)</span></div>';
}
}
Layout::reset();
Layout::assign('Logs', self::$Logs);
Layout::view(self::$logger_template, 'Core'.DS.'Views');
}
return $string;
public static function logToFile()
{
Layout::reset();
Layout::assign('Logs', self::$Logs);
$contents = Layout::get('logger_cli', 'Core'.DS.'Views');
$file = 'Application'.DS.'Logs'.DS.'log_latest.php';
if (is_writable($file))
{
file_put_contents($file, '<?php ' . $contents);
}
}
/**

View File

@ -46,7 +46,7 @@ class Security {
*
* @var array
*/
public static $filename_bad_chars = array(
public $filename_bad_chars = array(
'../', '<!--', '-->', '<', '>',
"'", '"', '&', '$', '#',
'{', '}', '[', ']', '=',
@ -72,7 +72,7 @@ class Security {
*
* @var string
*/
public static $charset = 'UTF-8';
public $charset = 'UTF-8';
/**
* XSS Hash
@ -81,7 +81,7 @@ class Security {
*
* @var string
*/
protected static $_xss_hash;
protected $_xss_hash;
/**
* CSRF Hash
@ -90,7 +90,7 @@ class Security {
*
* @var string
*/
protected static $_csrf_hash;
protected $_csrf_hash;
/**
* CSRF Expire time
@ -100,7 +100,7 @@ class Security {
*
* @var int
*/
protected static $_csrf_expire = 7200;
protected $_csrf_expire = 7200;
/**
* CSRF Token name
@ -109,7 +109,7 @@ class Security {
*
* @var string
*/
protected static $_csrf_token_name = 'ci_csrf_token';
protected $_csrf_token_name = 'fw_csrf_token';
/**
* CSRF Cookie name
@ -118,14 +118,14 @@ class Security {
*
* @var string
*/
protected static $_csrf_cookie_name = 'ci_csrf_token';
protected $_csrf_cookie_name = 'fw_csrf_token';
/**
* List of never allowed strings
*
* @var array
*/
protected static $_never_allowed_str = array(
protected $_never_allowed_str = array(
'document.cookie' => '[removed]',
'document.write' => '[removed]',
'.parentNode' => '[removed]',
@ -142,7 +142,7 @@ class Security {
*
* @var array
*/
protected static $_never_allowed_regex = array(
protected $_never_allowed_regex = array(
'javascript\s*:',
'(document|(document\.)?window)\.(location|on\w*)',
'expression\s*(\(|&\#40;)', // CSS and IE
@ -159,7 +159,7 @@ class Security {
*
* @var ConfigORM
*/
private static $config;
private $config;
/**
* Class constructor
@ -168,31 +168,31 @@ class Security {
*/
public function __construct()
{
self::$config = Config::get('security');
$this->config = Config::get('security');
// Is CSRF protection enabled?
if (self::$config->csrf_protection)
if ($this->config->csrf_protection)
{
// CSRF config
foreach (array('csrf_expire', 'csrf_token_name', 'csrf_cookie_name') as $key)
{
if (NULL !== ($val = self::$config->$key))
if (NULL !== ($val = $this->config->$key))
{
self::${'_'.$key} = $val;
$this->{'_'.$key} = $val;
}
}
// Append application specific cookie prefix
if ($cookie_prefix = Config::get('main')->cookie_prefix)
{
self::$_csrf_cookie_name = $cookie_prefix.self::$_csrf_cookie_name;
$this->_csrf_cookie_name = $cookie_prefix.$this->_csrf_cookie_name;
}
// Set the CSRF hash
self::_csrf_set_hash();
$this->_csrf_set_hash();
}
self::$charset = strtoupper(Config::get('main')->charset);
$this->charset = strtoupper(Config::get('main')->charset);
}
// --------------------------------------------------------------------
@ -200,51 +200,51 @@ class Security {
/**
* CSRF Verify
*
* @return CI_Security
* @return Security
*/
public static function csrf_verify()
public function csrf_verify()
{
// If it's not a POST request we will set the CSRF cookie
if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST')
{
return self::csrf_set_cookie();
return $this->csrf_set_cookie();
}
// Check if URI has been whitelisted from CSRF checks
if ($exclude_uris = self::$config->csrf_exclude_uris)
if ($exclude_uris = $this->config->csrf_exclude_uris)
{
foreach ($exclude_uris as $excluded)
{
if (preg_match('#^'.$excluded.'$#i'.(UTF8_ENABLED ? 'u' : ''), URI::uri_string()))
{
return true;
return $this;
}
}
}
// Do the tokens exist in both the _POST and _COOKIE arrays?
if ( ! isset($_POST[self::$_csrf_token_name], $_COOKIE[self::$_csrf_cookie_name])
OR $_POST[self::$_csrf_token_name] !== $_COOKIE[self::$_csrf_cookie_name]) // Do the tokens match?
if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
OR $_POST[$this->_csrf_token_name] !== $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match?
{
self::csrf_show_error();
$this->csrf_show_error();
}
// We kill this since we're done and we don't want to polute the _POST array
unset($_POST[self::$_csrf_token_name]);
unset($_POST[$this->_csrf_token_name]);
// Regenerate on every submission?
if (self::$config->csrf_regenerate)
if ($this->config->csrf_regenerate)
{
// Nothing should last forever
unset($_COOKIE[self::$_csrf_cookie_name]);
self::$_csrf_hash = NULL;
unset($_COOKIE[$this->_csrf_cookie_name]);
$this->_csrf_hash = NULL;
}
self::_csrf_set_hash();
self::csrf_set_cookie();
$this->_csrf_set_hash();
$this->csrf_set_cookie();
Logger::log('CSRF token verified');
return true;
return $this;
}
// --------------------------------------------------------------------
@ -253,22 +253,22 @@ class Security {
* CSRF Set Cookie
*
* @codeCoverageIgnore
* @return CI_Security
* @return Security
*/
public static function csrf_set_cookie()
public function csrf_set_cookie()
{
$expire = time() + self::$_csrf_expire;
$expire = time() + $this->_csrf_expire;
$cfg = Config::get('main');
$secure_cookie = (bool) $cfg->cookie_secure;
if ($secure_cookie && ! is_https())
{
return FALSE;
return $this;
}
setcookie(
self::$_csrf_cookie_name,
self::$_csrf_hash,
$this->_csrf_cookie_name,
$this->_csrf_hash,
$expire,
$cfg->cookie_path,
$cfg->cookie_domain,
@ -276,8 +276,7 @@ class Security {
$cfg->cookie_httponly
);
Logger::log('CSRF cookie sent');
return true;
return $this;
}
// --------------------------------------------------------------------
@ -287,7 +286,7 @@ class Security {
*
* @return void
*/
public static function csrf_show_error()
public function csrf_show_error()
{
throw new SecurityException('The action you have requested is not allowed.', 1);
}
@ -297,12 +296,12 @@ class Security {
/**
* Get CSRF Hash
*
* @see CI_Security::$_csrf_hash
* @see Security::$_csrf_hash
* @return string CSRF hash
*/
public static function get_csrf_hash()
public function get_csrf_hash()
{
return self::$_csrf_hash;
return $this->_csrf_hash;
}
// --------------------------------------------------------------------
@ -310,12 +309,12 @@ class Security {
/**
* Get CSRF Token Name
*
* @see CI_Security::$_csrf_token_name
* @see Security::$_csrf_token_name
* @return string CSRF token name
*/
public static function get_csrf_token_name()
public function get_csrf_token_name()
{
return self::$_csrf_token_name;
return $this->_csrf_token_name;
}
// --------------------------------------------------------------------
@ -346,14 +345,14 @@ class Security {
* @param bool $is_image Whether the input is an image
* @return string
*/
public static function xss_clean($str, $is_image = FALSE)
public function xss_clean($str, $is_image = FALSE)
{
// Is the string an array?
if (is_array($str))
{
while (list($key) = each($str))
{
$str[$key] = self::xss_clean($str[$key]);
$str[$key] = $this->xss_clean($str[$key]);
}
return $str;
@ -404,7 +403,7 @@ class Security {
$converted_string = $str;
// Remove Strings that are never allowed
$str = self::_do_never_allowed($str);
$str = $this->_do_never_allowed($str);
/*
* Makes PHP tags safe
@ -536,7 +535,7 @@ class Security {
// Final clean up
// This adds a bit of extra precaution in case
// something got through the above filters
$str = self::_do_never_allowed($str);
$str = $this->_do_never_allowed($str);
/*
* Images are Handled in a Special Way
@ -562,20 +561,20 @@ class Security {
*
* Generates the XSS hash if needed and returns it.
*
* @see CI_Security::$_xss_hash
* @see Security::$_xss_hash
* @return string XSS hash
*/
public static function xss_hash()
public function xss_hash()
{
if (self::$_xss_hash === NULL)
if ($this->_xss_hash === NULL)
{
$rand = self::get_random_bytes(16);
self::$_xss_hash = ($rand === FALSE)
$rand = $this->get_random_bytes(16);
$this->_xss_hash = ($rand === FALSE)
? md5(uniqid(mt_rand(), TRUE))
: bin2hex($rand);
}
return self::$_xss_hash;
return $this->_xss_hash;
}
// --------------------------------------------------------------------
@ -586,7 +585,7 @@ class Security {
* @param int $length Output length
* @return string
*/
public static function get_random_bytes($length)
public function get_random_bytes($length)
{
if (empty($length) OR ! ctype_digit((string) $length))
{
@ -655,7 +654,7 @@ class Security {
* @param string $charset Character set
* @return string
*/
public static function entity_decode($str, $charset = NULL)
public function entity_decode($str, $charset = NULL)
{
if (strpos($str, '&') === FALSE)
{
@ -664,7 +663,7 @@ class Security {
static $_entities;
isset($charset) OR $charset = self::$charset;
isset($charset) OR $charset = $this->charset;
$flag = Core::isPHP('5.4')
? ENT_COMPAT | ENT_HTML5
: ENT_COMPAT;
@ -730,9 +729,9 @@ class Security {
* @param bool $relative_path Whether to preserve paths
* @return string
*/
public static function sanitize_filename($str, $relative_path = FALSE)
public function sanitize_filename($str, $relative_path = FALSE)
{
$bad = self::$filename_bad_chars;
$bad = $this->filename_bad_chars;
if ( ! $relative_path)
{
@ -760,7 +759,7 @@ class Security {
* @param string $str
* @return string
*/
public static function strip_image_tags($str)
public function strip_image_tags($str)
{
return preg_replace(
array(
@ -780,11 +779,11 @@ class Security {
* Callback method for xss_clean() to remove whitespace from
* things like 'j a v a s c r i p t'.
*
* @used-by CI_Security::xss_clean()
* @used-by Security::xss_clean()
* @param array $matches
* @return string
*/
protected static function _compact_exploded_words($matches)
protected function _compact_exploded_words($matches)
{
return preg_replace('/\s+/s', '', $matches[1]).$matches[2];
}
@ -796,11 +795,11 @@ class Security {
*
* Callback method for xss_clean() to remove naughty HTML elements.
*
* @used-by CI_Security::xss_clean()
* @used-by Security::xss_clean()
* @param array $matches
* @return string
*/
protected static function _sanitize_naughty_html($matches)
protected function _sanitize_naughty_html($matches)
{
static $naughty_tags = array(
'alert', 'prompt', 'confirm', 'applet', 'audio', 'basefont', 'base', 'behavior', 'bgsound',
@ -891,18 +890,18 @@ class Security {
* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in
* PHP 5.2+ on link-heavy strings.
*
* @used-by CI_Security::xss_clean()
* @used-by Security::xss_clean()
* @param array $match
* @return string
*/
protected static function _js_link_removal($match)
protected function _js_link_removal($match)
{
return str_replace(
$match[1],
preg_replace(
'#href=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
'',
self::_filter_attributes($match[1])
$this->_filter_attributes($match[1])
),
$match[0]
);
@ -919,18 +918,18 @@ class Security {
* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in
* PHP 5.2+ on image tag heavy strings.
*
* @used-by CI_Security::xss_clean()
* @used-by Security::xss_clean()
* @param array $match
* @return string
*/
protected static function _js_img_removal($match)
protected function _js_img_removal($match)
{
return str_replace(
$match[1],
preg_replace(
'#src=.*?(?:(?:alert|prompt|confirm|eval)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
'',
self::_filter_attributes($match[1])
$this->_filter_attributes($match[1])
),
$match[0]
);
@ -941,11 +940,11 @@ class Security {
/**
* Attribute Conversion
*
* @used-by CI_Security::xss_clean()
* @used-by Security::xss_clean()
* @param array $match
* @return string
*/
protected static function _convert_attribute($match)
protected function _convert_attribute($match)
{
return str_replace(array('>', '<', '\\'), array('&gt;', '&lt;', '\\\\'), $match[0]);
}
@ -957,12 +956,12 @@ class Security {
*
* Filters tag attributes for consistency and safety.
*
* @used-by CI_Security::_js_img_removal()
* @used-by CI_Security::_js_link_removal()
* @used-by Security::_js_img_removal()
* @used-by Security::_js_link_removal()
* @param string $str
* @return string
*/
protected static function _filter_attributes($str)
protected function _filter_attributes($str)
{
$out = '';
if (preg_match_all('#\s*[a-z\-]+\s*=\s*(\042|\047)([^\\1]*?)\\1#is', $str, $matches))
@ -981,21 +980,21 @@ class Security {
/**
* HTML Entity Decode Callback
*
* @used-by CI_Security::xss_clean()
* @used-by Security::xss_clean()
* @param array $match
* @return string
*/
protected static function _decode_entity($match)
protected function _decode_entity($match)
{
// Protect GET variables in URLs
// 901119URL5918AMP18930PROTECT8198
$match = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-/]+)|i', self::xss_hash().'\\1=\\2', $match[0]);
$match = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-/]+)|i', $this->xss_hash().'\\1=\\2', $match[0]);
// Decode, then un-protect URL GET vars
return str_replace(
self::xss_hash(),
$this->xss_hash(),
'&',
self::entity_decode($match, self::$charset)
$this->entity_decode($match, $this->charset)
);
}
@ -1004,15 +1003,15 @@ class Security {
/**
* Do Never Allowed
*
* @used-by CI_Security::xss_clean()
* @used-by Security::xss_clean()
* @param string
* @return string
*/
protected static function _do_never_allowed($str)
protected function _do_never_allowed($str)
{
$str = str_replace(array_keys(self::$_never_allowed_str), self::$_never_allowed_str, $str);
$str = str_replace(array_keys($this->_never_allowed_str), $this->_never_allowed_str, $str);
foreach (self::$_never_allowed_regex as $regex)
foreach ($this->_never_allowed_regex as $regex)
{
$str = preg_replace('#'.$regex.'#is', '[removed]', $str);
}
@ -1027,27 +1026,27 @@ class Security {
*
* @return string
*/
protected static function _csrf_set_hash()
protected function _csrf_set_hash()
{
if (self::$_csrf_hash === NULL)
if ($this->_csrf_hash === NULL)
{
// If the cookie exists we will use its value.
// We don't necessarily want to regenerate it with
// each page load since a page could contain embedded
// sub-pages causing this feature to fail
if (isset($_COOKIE[self::$_csrf_cookie_name]) && is_string($_COOKIE[self::$_csrf_cookie_name])
&& preg_match('#^[0-9a-f]{32}$#iS', $_COOKIE[self::$_csrf_cookie_name]) === 1)
if (isset($_COOKIE[$this->_csrf_cookie_name]) && is_string($_COOKIE[$this->_csrf_cookie_name])
&& preg_match('#^[0-9a-f]{32}$#iS', $_COOKIE[$this->_csrf_cookie_name]) === 1)
{
return self::$_csrf_hash = $_COOKIE[self::$_csrf_cookie_name];
return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name];
}
$rand = self::get_random_bytes(16);
self::$_csrf_hash = ($rand === FALSE)
$rand = $this->get_random_bytes(16);
$this->_csrf_hash = ($rand === FALSE)
? md5(uniqid(mt_rand(), TRUE))
: bin2hex($rand);
}
return self::$_csrf_hash;
return $this->_csrf_hash;
}
}

View File

@ -166,8 +166,7 @@ class Utf8 {
*/
public static function safe_ascii_for_xml($str)
{
Helpers::load('common');
return remove_invisible_characters($str, FALSE);
return self::remove_invisible_characters($str, FALSE);
}
// --------------------------------------------------------------------

View File

@ -0,0 +1,91 @@
<?php
if (!function_exists('getColoredString'))
{
function getColoredString($string, $foreground_color, $background_color) {
// Determine the color system
$foreground_colors = array();
$background_colors = array();
$foreground_colors['black'] = '0;30';
$foreground_colors['dark_gray'] = '1;30';
$foreground_colors['blue'] = '0;34';
$foreground_colors['light_blue'] = '1;34';
$foreground_colors['green'] = '0;32';
$foreground_colors['light_green'] = '1;32';
$foreground_colors['cyan'] = '0;36';
$foreground_colors['light_cyan'] = '1;36';
$foreground_colors['red'] = '0;31';
$foreground_colors['light_red'] = '1;31';
$foreground_colors['purple'] = '0;35';
$foreground_colors['light_purple'] = '1;35';
$foreground_colors['brown'] = '0;33';
$foreground_colors['yellow'] = '1;33';
$foreground_colors['light_gray'] = '0;37';
$foreground_colors['white'] = '1;37';
$background_colors['black'] = '40';
$background_colors['red'] = '41';
$background_colors['green'] = '42';
$background_colors['yellow'] = '43';
$background_colors['blue'] = '44';
$background_colors['magenta'] = '45';
$background_colors['cyan'] = '46';
$background_colors['light_gray'] = '47';
$colored_string = "";
// Check if given foreground color found
if (isset($foreground_colors[$foreground_color])) {
$colored_string .= "\033[" . $foreground_colors[$foreground_color] . "m";
}
// Check if given background color found
if (isset($background_colors[$background_color])) {
$colored_string .= "\033[" . $background_colors[$background_color] . "m";
}
// Add string and end coloring
$colored_string .= $string . "\033[0m";
return $colored_string;
}
}
$mask = "|%5s |%-90s | %10s |\n";
$id = 1;
printf($mask, 'Id', 'Title', 'Runtime');
printf($mask, $id, getColoredString('FuzeWorks debug log', 'black', 'light_gray'), '0 ms');
foreach ($this->assigned_variables['Logs'] as $log) {
$id++;
$string = '';
if ($log['type'] == 'WARNING')
{
$string .= getColoredString('[WARNING]', 'black', 'yellow') . ' - ';
$string .= getColoredString($log['message'], 'black', 'yellow');
}
elseif ($log['type'] == 'ERROR')
{
$string .= getColoredString('[ERROR]', 'black', 'red') . ' - ';
$string .= getColoredString($log['message'], 'black', 'red');
}
elseif ($log['type'] == "LEVEL_STOP")
{
continue;
}
else
{
$string .= getColoredString($log['message'], 'green', 'black');
}
printf($mask,
$id,
$string,
(!empty($log['runtime']) ?
round($log['runtime'] * 1000, 4) . 'ms' :
''));
}

View File

@ -0,0 +1,27 @@
<?php
$string = '<h3>FuzeWorks debug log</h3>';
$layer = 0;
foreach ($this->assigned_variables['Logs'] as $log) {
if ($log['type'] == 'LEVEL_START') {
++$layer;
$color = 255 - ($layer * 25);
$string .= '<div style="background: rgb(188 , 232 ,' . $color . ');border: 1px black solid;margin: 5px 0;padding: 5px 20px;">';
$string .= '<div style="font-weight: bold; font-size: 11pt;">' . $log['message'] . '<span style="float: right">' . (!empty($log['runtime']) ? '(' . round($log['runtime'] * 1000, 4) . 'ms)' : '') . '</span></div>';
} elseif ($log['type'] == 'LEVEL_STOP') {
--$layer;
$string .= '</div>';
} elseif ($log['type'] == 'ERROR') {
$string .= '<div style="' . ($layer == 0 ? 'padding-left: 21px;' : '') . 'font-size: 11pt; background-color:#f56954;">[' . $log['type'] . ']' . (!empty($log['context']) && is_string($log['context']) ? '<u>[' . $log['context'] . ']</u>' : '') . ' ' . $log['message'] . '
<span style="float: right">' . (!empty($log['logFile']) ? $log['logFile'] : '') . ' : ' . (!empty($log['logLine']) ? $log['logLine'] : '') . '(' . round($log['runtime'] * 1000, 4) . ' ms)</span></div>';
} elseif ($log['type'] == 'WARNING') {
$string .= '<div style="' . ($layer == 0 ? 'padding-left: 21px;' : '') . 'font-size: 11pt; background-color:#f39c12;">[' . $log['type'] . ']' . (!empty($log['context']) && is_string($log['context']) ? '<u>[' . $log['context'] . ']</u>' : '') . ' ' . $log['message'] . '
<span style="float: right">' . (!empty($log['logFile']) ? $log['logFile'] : '') . ' : ' . (!empty($log['logLine']) ? $log['logLine'] : '') . '(' . round($log['runtime'] * 1000, 4) . ' ms)</span></div>';
} elseif ($log['type'] == 'INFO') {
$string .= '<div style="' . ($layer == 0 ? 'padding-left: 21px;' : '') . 'font-size: 11pt;">' . (!empty($log['context']) ? '<u>[' . $log['context'] . ']</u>' : '') . ' ' . $log['message'] . '<span style="float: right">(' . round($log['runtime'] * 1000, 4) . ' ms)</span></div>';
} elseif ($log['type'] == 'DEBUG') {
$string .= '<div style="' . ($layer == 0 ? 'padding-left: 21px;' : '') . 'font-size: 11pt; background-color:#CCCCCC;">[' . $log['type'] . ']' . (!empty($log['context']) ? '<u>[' . $log['context'] . ']</u>' : '') . ' ' . $log['message'] . '<span style="float: right">(' . round($log['runtime'] * 1000, 4) . ' ms)</span></div>';
}
}
echo $string;

View File

@ -6,7 +6,8 @@
"smarty/smarty": "~3.1"
},
"require-dev": {
"phpunit/phpunit": "4.7.*",
"apigen/apigen": "^4.1"
"phpunit/phpunit": "5.3.*",
"apigen/apigen": "^4.1",
"mikey179/vfsStream": "1.1.*"
}
}

View File

@ -1,32 +0,0 @@
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.5/phpunit.xsd"
bootstrap="tests/autoload.php"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
forceCoversAnnotation="false"
mapTestClassNameToCoveredClassName="false"
printerClass="PHPUnit_TextUI_ResultPrinter"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
timeoutForSmallTests="1"
timeoutForMediumTests="10"
timeoutForLargeTests="60"
verbose="true">
<testsuites>
<testsuite name="Core Functionality">
<directory>tests</directory>
</testsuite>
</testsuites>
<logging>
<log type="json" target="build/phpunit/logfile.json"/>
<log type="junit" target="build/phpunit/logfile.xml" logIncompleteSkipped="false"/>
<log type="testdox-html" target="build/phpunit/testdox.html"/>
<log type="testdox-text" target="build/phpunit/testdox.txt"/>
</logging>
</phpunit>

View File

@ -48,5 +48,6 @@ abstract class CoreTestAbstract extends PHPUnit_Framework_TestCase
{
Events::$listeners = array();
Layout::reset();
Events::enable();
}
}

View File

@ -31,8 +31,9 @@
*/
// Load the abstract
use \FuzeWorks\Config;
use \FuzeWorks\Core;
use FuzeWorks\Config;
use FuzeWorks\Core;
use FuzeWorks\Logger;
require_once 'abstract.coreTestAbstract.php';
require_once 'Core/System/class.core.php';
@ -44,4 +45,29 @@ Core::init();
$cfg = Config::get('error');
$cfg->debug = false;
$cfg->error_reporting = false;
$cfg->log_to_file = false;
$cfg->commit();
restore_error_handler();
restore_exception_handler();
// Display all errors
ini_set('display_errors', 1);
error_reporting(E_ALL | E_STRICT);
// Set localhost "remote" IP
isset($_SERVER['REMOTE_ADDR']) OR $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
// Load the vfsStream class either through PEAR installed library or through composer
if ( ! class_exists('vfsStream') && file_exists('vendor/autoload.php'))
{
include_once 'vendor/autoload.php';
class_alias('org\bovigo\vfs\vfsStream', 'vfsStream');
class_alias('org\bovigo\vfs\vfsStreamDirectory', 'vfsStreamDirectory');
class_alias('org\bovigo\vfs\vfsStreamWrapper', 'vfsStreamWrapper');
}
Logger::setLoggerTemplate('logger_cli');
require_once('mocks/autoloader.php');
spl_autoload_register('autoload');

View File

@ -0,0 +1,5 @@
<?php
return array(
'key' => 'value'
);

View File

@ -0,0 +1,5 @@
<?php
return array(
'key' => 'value'
);

127
tests/core_configTest.php Normal file
View File

@ -0,0 +1,127 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class ConfigTest.
*
* Config testing suite, will test basic config functionality while also testing default ORM's
*/
class configTest extends CoreTestAbstract
{
protected $config;
public function setUp()
{
$factory = Factory::getInstance();
$this->config = $factory->config;
}
public function testGetConfigClass()
{
$this->assertInstanceOf('FuzeWorks\Config', $this->config);
}
/**
* @depends testGetConfigClass
*/
public function testLoadConfig()
{
$this->assertInstanceOf('FuzeWorks\ConfigORM\ConfigORM', $this->config->getConfig('main'));
}
/**
* @depends testLoadConfig
* @expectedException FuzeWorks\ConfigException
*/
public function testFileNotFound()
{
$this->config->getConfig('notFound');
}
/**
* @expectedException FuzeWorks\ConfigException
*/
public function testAddConfigPathFail()
{
// Now test if the config can be loaded (hint: it can not)
$this->config->getConfig('testAddConfigPath');
}
/**
* @depends testAddConfigPathFail
*/
public function testAddConfigPath()
{
// Add the configPath
$this->config->addConfigPath('tests/config/testAddConfigPath');
// And try to load it again
$this->assertInstanceOf('FuzeWorks\ConfigORM\ConfigORM', $this->config->getConfig('testAddConfigPath'));
}
public function testRemoveConfigPath()
{
// Test if the path does NOT exist
$this->assertFalse(in_array('tests/config/testRemoveConfigPath', $this->config->getConfigPaths()));
// Add it
$this->config->addConfigPath('tests/config/testRemoveConfigPath');
// Assert if it's there
$this->assertTrue(in_array('tests/config/testRemoveConfigPath', $this->config->getConfigPaths()));
// Remove it
$this->config->removeConfigPath('tests/config/testRemoveConfigPath');
// And test if it's gone again
$this->assertFalse(in_array('tests/config/testRemoveConfigPath', $this->config->getConfigPaths()));
}
public function testSameConfigObject()
{
$config = $this->config->getConfig('testsameconfigobject', array('tests/config/testSameConfigObject'));
$config2 = $this->config->getConfig('testsameconfigobject', array('tests/config/testSameConfigObject'));
// First test if the objects are the same instance
$this->assertSame($config, $config2);
// First test the existing key
$this->assertEquals($config->key, 'value');
// Change it and test if it's different now
$config->key = 'other_value';
$this->assertEquals($config2->key, 'other_value');
}
}

View File

@ -30,6 +30,8 @@
* @version Version 0.0.1
*/
use FuzeWorks\Core;
/**
* Class CoreTest.
*
@ -39,13 +41,29 @@ class coreTest extends CoreTestAbstract
{
public function testCanLoadStartupFiles()
{
// Assert
$this->assertTrue(class_exists('\FuzeWorks\Config'));
$this->assertTrue(class_exists('\FuzeWorks\Logger'));
$this->assertTrue(class_exists('\FuzeWorks\Events'));
$this->assertTrue(class_exists('\FuzeWorks\Router'));
$this->assertTrue(class_exists('\FuzeWorks\Layout'));
$this->assertTrue(class_exists('\FuzeWorks\Models'));
$this->assertTrue(class_exists('FuzeWorks\Core'));
$this->assertTrue(class_exists('FuzeWorks\Config'));
$this->assertTrue(class_exists('FuzeWorks\Logger'));
$this->assertTrue(class_exists('FuzeWorks\Events'));
$this->assertTrue(class_exists('FuzeWorks\Router'));
$this->assertTrue(class_exists('FuzeWorks\Layout'));
$this->assertTrue(class_exists('FuzeWorks\Models'));
$this->assertTrue(class_exists('FuzeWorks\Database'));
$this->assertTrue(class_exists('FuzeWorks\Factory'));
$this->assertTrue(class_exists('FuzeWorks\Helpers'));
$this->assertTrue(class_exists('FuzeWorks\Input'));
$this->assertTrue(class_exists('FuzeWorks\Language'));
$this->assertTrue(class_exists('FuzeWorks\Libraries'));
$this->assertTrue(class_exists('FuzeWorks\Output'));
$this->assertTrue(class_exists('FuzeWorks\Security'));
$this->assertTrue(class_exists('FuzeWorks\URI'));
$this->assertTrue(class_exists('FuzeWorks\UTF8'));
}
public function testIsPHP()
{
$this->assertTrue(Core::isPHP('1.2.0'));
$this->assertFalse(Core::isphp('9999.9.9'));
}
}

166
tests/core_eventsTest.php Normal file
View File

@ -0,0 +1,166 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Router;
use FuzeWorks\Events;
use FuzeWorks\EventPriority;
/**
* Class EventTest.
*
* This test will test Events
*/
class eventsTest extends CoreTestAbstract
{
public function testFireEvent()
{
$mock = $this->getMock('MockEventListener', array('mockMethod'));
$mock->expects($this->once())->method('mockMethod');
Events::addListener(array($mock, 'mockMethod'), 'mockEvent', EventPriority::NORMAL);
Events::fireEvent('mockEvent');
}
/**
* @depends testFireEvent
*/
public function testObjectEvent()
{
$event = $this->getMock('MockEvent');
$listener = $this->getMock('MockEventListener', array('mockListener'));
$listener->expects($this->once())->method('mockListener')->with($this->equalTo($event));
Events::addListener(array($listener, 'mockListener'), get_class($event), EventPriority::NORMAL);
Events::fireEvent($event);
}
/**
* @depends testObjectEvent
*/
public function testVariablePassing()
{
$event = $this->getMock('MockEvent');
$event->key = 'value';
$eventName = get_class($event);
Events::addListener(function($event) {
$this->assertEquals('value', $event->key);
}, $eventName, EventPriority::NORMAL);
Events::fireEvent($event);
}
/**
* @depends testVariablePassing
*/
public function testVariableChanging()
{
// First prepare the event
$event = $this->getMock('MockEvent');
$event->key = 1;
$eventName = get_class($event);
// The first listener, should be called first due to HIGH priority
Events::addListener(function($event) {
$this->assertEquals(1, $event->key);
$event->key = 2;
return $event;
}, $eventName, EventPriority::HIGH);
// The second listener, should be called second due to LOW priority
Events::addListener(function($event) {
$this->assertEquals(2, $event->key);
$event->key = 3;
return $event;
}, $eventName, EventPriority::LOW);
// Fire the event and test if the key is the result of the last listener
Events::fireEvent($event);
$this->assertEquals(3, $event->key);
}
/**
* @depends testFireEvent
*/
public function testRemoveListener()
{
// First add the listener, expect it to be never called
$listener = $this->getMock('MockEventListener', array('mockListener'));
$listener->expects($this->never())->method('mockListener');
Events::addListener(array($listener, 'mockListener'), 'mockEvent', EventPriority::NORMAL);
// Now try and remove it
Events::removeListener(array($listener, 'mockListener'), 'mockEvent', EventPriority::NORMAL);
// And now fire the event
Events::fireEvent('mockEvent');
}
public function testDisable()
{
// First add the listener, expect it to be never called
$listener = $this->getMock('MockEventListener', array('mockListener'));
$listener->expects($this->never())->method('mockListener');
Events::addListener(array($listener, 'mockListener'), 'mockEvent', EventPriority::NORMAL);
// Disable the event syste,
Events::disable();
// And now fire the event
Events::fireEvent('mockEvent');
}
public function testReEnable()
{
// First add the listener, expect it to be never called
$listener = $this->getMock('MockEventListener', array('mockListener'));
$listener->expects($this->once())->method('mockListener');
Events::addListener(array($listener, 'mockListener'), 'mockEvent', EventPriority::NORMAL);
// Disable the event syste,
Events::disable();
// And now fire the event
Events::fireEvent('mockEvent');
// Re-enable it
Events::enable();
// And fire it again, this time expecting to hit the listener
Events::fireEvent('mockEvent');
}
}

177
tests/core_factoryTest.php Normal file
View File

@ -0,0 +1,177 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class FactoryTest.
*
* Will test the FuzeWorks Factory.
*/
class factoryTest extends CoreTestAbstract
{
public function testCanLoadFactory()
{
$this->assertInstanceOf('FuzeWorks\Factory', Factory::getInstance());
}
/**
* @depends testCanLoadFactory
*/
public function testLoadSameInstance()
{
$this->assertSame(Factory::getInstance(), Factory::getInstance());
}
/**
* @depends testCanLoadFactory
*/
public function testLoadDifferentInstance()
{
// First a situation where one is the shared instance and one is a cloned instance
$this->assertNotSame(Factory::getInstance(), Factory::getInstance(true));
// And a situation where both are cloned instances
$this->assertNotSame(Factory::getInstance(true), Factory::getInstance(true));
}
/**
* @depends testCanLoadFactory
*/
public function testObjectsSameInstance()
{
// Create mock
$mock = $this->getMock('MockInstance');
// Test not set
$this->assertNull(Factory::getInstance()->mock);
// Same instance factories
$factory1 = Factory::getInstance()->setInstance('Mock', $mock);
$factory2 = Factory::getInstance()->setInstance('Mock', $mock);
// Return the mocks
$this->assertSame($factory1->mock, $factory2->mock);
// Different instance factories
$factory3 = Factory::getInstance(true)->setInstance('Mock', $mock);
$factory4 = Factory::getInstance(true)->setInstance('Mock', $mock);
// Return the mocks
$this->assertSame($factory3->mock, $factory4->mock);
}
/**
* @depends testObjectsSameInstance
*/
public function testObjectsDifferentInstance()
{
// Create mock
$mock = $this->getMock('MockInstance');
// Test not set
$this->assertNull(Factory::getInstance()->mock);
// Same instance factories
$factory1 = Factory::getInstance()->setInstance('Mock', $mock);
$factory2 = Factory::getInstance()->setInstance('Mock', $mock);
// Clone the instance in factory2
$factory2->cloneInstance('Mock');
// Should be true, since both Factories use the same Mock instance
$this->assertSame($factory1->mock, $factory2->mock);
// Different instance factories
$factory3 = Factory::getInstance(true)->setInstance('Mock', $mock);
$factory4 = Factory::getInstance(true)->setInstance('Mock', $mock);
// Clone the instance in factory4
$factory4->cloneInstance('Mock');
// Should be false, since both Factories use a different Mock instance
$this->assertNotSame($factory3->mock, $factory4->mock);
}
public function testGlobalCloneInstance()
{
// First test without global cloning
$this->assertSame(Factory::getInstance(), Factory::getInstance());
// Now enable global cloning
Factory::enableCloneInstances();
// Now test without global cloning
$this->assertNotSame(Factory::getInstance(), Factory::getInstance());
// Disable global cloning
Factory::disableCloneInstances();
// And test again without global cloning
$this->assertSame(Factory::getInstance(), Factory::getInstance());
}
public function testNewFactoryInstance()
{
// Load the different factories
$factory = new Factory();
$factory2 = Factory::getInstance();
// Test if the objects are different factory instances
$this->assertNotSame($factory, $factory2);
// Fetch the instances
$instances1 = $factory->getClassInstances();
$instances2 = $factory2->getClassInstances();
// And test if all ClassInstances are the same
foreach ($instances1 as $className => $object) {
$this->assertSame($object, $instances2[$className]);
}
// And test when changing one classInstance
$factory->newInstance('Layout');
$this->assertNotSame($factory->layout, $factory2->layout);
}
public function tearDown()
{
Factory::disableCloneInstances();
$factory = Factory::getInstance();
if (isset($factory->Mock))
{
$factory->removeInstance('Mock');
}
}
}

112
tests/core_helperTest.php Normal file
View File

@ -0,0 +1,112 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class HelperTest.
*
* Helpers testing suite, will test basic loading of Helpers
*/
class helperTest extends CoreTestAbstract
{
protected $helpers;
public function setUp()
{
$factory = Factory::getInstance();
$this->helpers = $factory->helpers;
}
public function testGetHelpersClass()
{
$this->assertInstanceOf('FuzeWorks\Helpers', $this->helpers);
}
public function testLoadHelper()
{
// First test if the function/helper is not loaded yet
$this->assertFalse(function_exists('testHelperFunction'));
// Test if the helper is properly loaded
$this->assertTrue($this->helpers->load('test', 'tests/helpers/testLoadHelper/'));
// Test if the function exists now
$this->assertTrue(function_exists('testHelperFunction'));
}
/**
* @expectedException FuzeWorks\HelperException
*/
public function testAddHelperPathFail()
{
// First test if the function is not loaded yet
$this->assertFalse(function_exists('testAddHelperPathFunction'));
// Now test if the helper can be loaded (hint: it can not)
$this->helpers->load('testAddHelperPath');
}
/**
* @depends testAddHelperPathFail
*/
public function testAddHelperPath()
{
// Add the helperPath
$this->helpers->addHelperPath('tests/helpers/testAddHelperPath');
// And try to load it again
$this->assertTrue($this->helpers->load('testAddHelperPath'));
// And test if the function is loaded
$this->assertTrue(function_exists('testAddHelperPathFunction'));
}
public function testRemoveHelperPath()
{
// Test if the path does NOT exist
$this->assertFalse(in_array('tests/helpers/testRemoveHelperPath', $this->helpers->getHelperPaths()));
// Add it
$this->helpers->addHelperPath('tests/helpers/testRemoveHelperPath');
// Assert if it's there
$this->assertTrue(in_array('tests/helpers/testRemoveHelperPath', $this->helpers->getHelperPaths()));
// Remove it
$this->helpers->removeHelperPath('tests/helpers/testRemoveHelperPath');
// And test if it's gone again
$this->assertFalse(in_array('tests/helpers/testRemoveHelperPath', $this->helpers->getHelperPaths()));
}
}

297
tests/core_inputTest.php Normal file
View File

@ -0,0 +1,297 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class InputTest.
*
* Core testing suite, will test basic input class functionality
*/
class inputTest extends CoreTestAbstract
{
protected $factory;
public function setUp()
{
// Load the factory first
$this->factory = Factory::getInstance();
// Set server variable to GET as default, since this will leave unset in STDIN env
$_SERVER['REQUEST_METHOD'] = 'GET';
// Set config for Input class
$this->factory->config->getConfig('routing')->allow_get_array = TRUE;
$this->factory->config->getConfig('security')->global_xss_filtering = FALSE;
$this->factory->config->getConfig('security')->csrf_protection = FALSE;
$security = new Mock_Core_Security();
$this->factory->config->getConfig('main')->charset = 'UTF-8';
$utf8 = new Mock_Core_Utf8();
$this->input = new Mock_Core_Input($security, $utf8);
}
// --------------------------------------------------------------------
public function test_get_not_exists()
{
$this->assertTrue($this->input->get() === array());
$this->assertTrue($this->input->get('foo') === NULL);
}
// --------------------------------------------------------------------
public function test_get_exist()
{
$_SERVER['REQUEST_METHOD'] = 'GET';
$_GET['foo'] = 'bar';
$this->assertArrayHasKey('foo', $this->input->get());
$this->assertEquals('bar', $this->input->get('foo'));
}
// --------------------------------------------------------------------
public function test_get_exist_with_xss_clean()
{
$_SERVER['REQUEST_METHOD'] = 'GET';
$_GET['harm'] = "Hello, i try to <script>alert('Hack');</script> your site";
$this->assertArrayHasKey('harm', $this->input->get());
$this->assertEquals("Hello, i try to <script>alert('Hack');</script> your site", $this->input->get('harm'));
$this->assertEquals("Hello, i try to [removed]alert&#40;'Hack'&#41;;[removed] your site", $this->input->get('harm', TRUE));
}
// --------------------------------------------------------------------
public function test_post_not_exists()
{
$this->assertTrue($this->input->post() === array());
$this->assertTrue($this->input->post('foo') === NULL);
}
// --------------------------------------------------------------------
public function test_post_exist()
{
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['foo'] = 'bar';
$this->assertArrayHasKey('foo', $this->input->post());
$this->assertEquals('bar', $this->input->post('foo'));
}
// --------------------------------------------------------------------
public function test_post_exist_with_xss_clean()
{
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['harm'] = "Hello, i try to <script>alert('Hack');</script> your site";
$this->assertArrayHasKey('harm', $this->input->post());
$this->assertEquals("Hello, i try to <script>alert('Hack');</script> your site", $this->input->post('harm'));
$this->assertEquals("Hello, i try to [removed]alert&#40;'Hack'&#41;;[removed] your site", $this->input->post('harm', TRUE));
}
// --------------------------------------------------------------------
public function test_post_get()
{
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['foo'] = 'bar';
$this->assertEquals('bar', $this->input->post_get('foo'));
}
// --------------------------------------------------------------------
public function test_get_post()
{
$_SERVER['REQUEST_METHOD'] = 'GET';
$_GET['foo'] = 'bar';
$this->assertEquals('bar', $this->input->get_post('foo'));
}
// --------------------------------------------------------------------
public function test_cookie()
{
$_COOKIE['foo'] = 'bar';
$this->assertEquals('bar', $this->input->cookie('foo'));
$this->assertNull($this->input->cookie('bar'));
}
// --------------------------------------------------------------------
public function test_server()
{
$this->assertEquals('GET', $this->input->server('REQUEST_METHOD'));
}
// --------------------------------------------------------------------
public function test_fetch_from_array()
{
$data = array(
'foo' => 'bar',
'harm' => 'Hello, i try to <script>alert(\'Hack\');</script> your site',
);
$foo = $this->input->fetch_from_array($data, 'foo');
$harm = $this->input->fetch_from_array($data, 'harm');
$harmless = $this->input->fetch_from_array($data, 'harm', TRUE);
$this->assertEquals('bar', $foo);
$this->assertEquals("Hello, i try to <script>alert('Hack');</script> your site", $harm);
$this->assertEquals("Hello, i try to [removed]alert&#40;'Hack'&#41;;[removed] your site", $harmless);
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['foo']['bar'] = 'baz';
$barArray = array('bar' => 'baz');
$this->assertEquals('baz', $this->input->post('foo[bar]'));
$this->assertEquals($barArray, $this->input->post('foo[]'));
$this->assertNull($this->input->post('foo[baz]'));
}
// --------------------------------------------------------------------
public function test_valid_ip()
{
$this->assertTrue($this->input->valid_ip('192.18.0.1'));
$this->assertTrue($this->input->valid_ip('192.18.0.1', 'ipv4'));
$this->assertFalse($this->input->valid_ip('555.0.0.0'));
$this->assertFalse($this->input->valid_ip('2001:db8:0:85a3::ac1f:8001', 'ipv4'));
// v6 tests
$this->assertFalse($this->input->valid_ip('192.18.0.1', 'ipv6'));
$ip_v6 = array(
'2001:0db8:0000:85a3:0000:0000:ac1f:8001',
'2001:db8:0:85a3:0:0:ac1f:8001',
'2001:db8:0:85a3::ac1f:8001'
);
foreach ($ip_v6 as $ip)
{
$this->assertTrue($this->input->valid_ip($ip));
$this->assertTrue($this->input->valid_ip($ip, 'ipv6'));
}
}
// --------------------------------------------------------------------
public function test_method()
{
$_SERVER['REQUEST_METHOD'] = 'GET';
$this->assertEquals('get', $this->input->method());
$this->assertEquals('GET', $this->input->method(TRUE));
$_SERVER['REQUEST_METHOD'] = 'POST';
$this->assertEquals('post', $this->input->method());
$this->assertEquals('POST', $this->input->method(TRUE));
}
// --------------------------------------------------------------------
public function test_is_ajax_request()
{
$this->assertFalse($this->input->is_ajax_request());
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'test';
$this->assertFalse($this->input->is_ajax_request());
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
$this->assertTrue($this->input->is_ajax_request());
}
// --------------------------------------------------------------------
public function test_ip_address()
{
$this->input->ip_address = '127.0.0.1';
$this->assertEquals('127.0.0.1', $this->input->ip_address());
// 127.0.0.1 is set in our Bootstrap file
$this->input->ip_address = FALSE;
$this->assertEquals('127.0.0.1', $this->input->ip_address());
// Invalid
$_SERVER['REMOTE_ADDR'] = 'invalid_ip_address';
$this->input->ip_address = FALSE; // reset cached value
$this->assertEquals('0.0.0.0', $this->input->ip_address());
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
// Proxy_ips tests
$this->input->ip_address = FALSE;
$this->factory->config->getConfig('security')->proxy_ips = array('127.0.0.3', '127.0.0.4', '127.0.0.2');
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.2';
$this->assertEquals('127.0.0.1', $this->input->ip_address());
// Invalid spoof
$this->input->ip_address = FALSE;
$this->factory->config->getConfig('security')->proxy_ips = 'invalid_ip_address';
$_SERVER['HTTP_CLIENT_IP'] = 'invalid_ip_address';
$this->assertEquals('127.0.0.1', $this->input->ip_address());
$this->input->ip_address = FALSE;
$this->factory->config->getConfig('security')->proxy_ips = array('http://foo/bar/baz', '127.0.0.1/1');
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.1';
$this->assertEquals('127.0.0.1', $this->input->ip_address());
$this->input->ip_address = FALSE;
$this->factory->config->getConfig('security')->proxy_ips = array('http://foo/bar/baz', '127.0.0.2');
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.2';
$_SERVER['REMOTE_ADDR'] = '127.0.0.2';
$this->assertEquals('127.0.0.2', $this->input->ip_address());
//IPv6
$this->input->ip_address = FALSE;
$this->factory->config->getConfig('security')->proxy_ips = array('FE80:0000:0000:0000:0202:B3FF:FE1E:8329/1', 'FE80:0000:0000:0000:0202:B3FF:FE1E:8300/2');
$_SERVER['HTTP_CLIENT_IP'] = 'FE80:0000:0000:0000:0202:B3FF:FE1E:8300';
$_SERVER['REMOTE_ADDR'] = 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329';
$this->assertEquals('FE80:0000:0000:0000:0202:B3FF:FE1E:8300', $this->input->ip_address());
$this->input->ip_address = FALSE;
$_SERVER['REMOTE_ADDR'] = '127.0.0.1'; // back to reality
}
// --------------------------------------------------------------------
public function test_user_agent()
{
$_SERVER['HTTP_USER_AGENT'] = 'test';
$this->assertEquals('test', $this->input->user_agent());
}
}

View File

@ -29,7 +29,7 @@
*
* @version Version 0.0.1
*/
use \FuzeWorks\Layout;
use FuzeWorks\Layout;
/**
* Class LayoutTest.
@ -43,16 +43,14 @@ class layoutTest extends CoreTestAbstract
// Test getting php files
$this->assertEquals('php', Layout::getExtensionFromFile('class.test.php'));
$this->assertEquals('php', Layout::getExtensionFromFile('class.test.org.php'));
$this->assertEquals('random', Layout::getExtensionFromFile('class.test.something.random'));
}
/**
* @depends testGetFileExtensions
*
* @todo Add malformed paths
*/
public function testGetFilePath()
{
// Extensions to be used in this test
$extensions = array('php', 'json');
@ -73,7 +71,19 @@ class layoutTest extends CoreTestAbstract
}
/**
* @expectedException \FuzeWorks\LayoutException
* @depends testGetFilePath
* @expectedException FuzeWorks\LayoutException
*/
public function testMalformedPaths()
{
// Extensions to be used in this test
$extensions = array('php', 'json');
Layout::setFileFromString('test?\/<>', 'test|?/*<>', $extensions);
}
/**
* @expectedException FuzeWorks\LayoutException
*/
public function testMissingDirectory()
{
@ -82,7 +92,7 @@ class layoutTest extends CoreTestAbstract
}
/**
* @expectedException \FuzeWorks\LayoutException
* @expectedException FuzeWorks\LayoutException
*/
public function testMissingFile()
{
@ -90,26 +100,65 @@ class layoutTest extends CoreTestAbstract
}
/**
* @expectedException \FuzeWorks\LayoutException
* @expectedException FuzeWorks\LayoutException
*/
public function testUnknownFileExtension()
{
Layout::setFileFromString('test', 'tests/layout/testUnknownFileExtension/', array('php'));
}
public function testLayoutGet()
{
// Directory of these tests
$directory = 'tests/layout/testLayoutGet/';
$this->assertEquals('Retrieved Data', Layout::get('test', $directory));
}
public function testLayoutView()
{
// Directory of these tests
$directory = 'tests/layout/testLayoutGet/';
ob_start();
Layout::view('test', $directory);
$output = ob_get_contents();
ob_end_clean();
$this->assertEquals('Retrieved Data', $output);
}
public function testReset()
{
// First the the variables
Layout::setTitle('Test Title');
Layout::setDirectory('tests/layout/testLayoutGet');
// Test if they are actually set
$this->assertEquals('Test Title', Layout::getTitle());
$this->assertEquals('tests/layout/testLayoutGet', Layout::getDirectory());
// Reset the layout system
Layout::reset();
// Test for default values
$this->assertFalse(Layout::getTitle());
$this->assertEquals('Application/Views', Layout::getDirectory());
}
public function testGetEngineFromExtension()
{
Layout::loadTemplateEngines();
// Test all the default engines
$this->assertInstanceOf('\FuzeWorks\TemplateEngine\PHPEngine', Layout::getEngineFromExtension('php'));
$this->assertInstanceOf('\FuzeWorks\TemplateEngine\JSONEngine', Layout::getEngineFromExtension('json'));
$this->assertInstanceOf('\FuzeWorks\TemplateEngine\SmartyEngine', Layout::getEngineFromExtension('tpl'));
$this->assertInstanceOf('FuzeWorks\TemplateEngine\PHPEngine', Layout::getEngineFromExtension('php'));
$this->assertInstanceOf('FuzeWorks\TemplateEngine\JSONEngine', Layout::getEngineFromExtension('json'));
$this->assertInstanceOf('FuzeWorks\TemplateEngine\SmartyEngine', Layout::getEngineFromExtension('tpl'));
}
/**
* @depends testGetEngineFromExtension
* @expectedException \FuzeWorks\LayoutException
* @expectedException FuzeWorks\LayoutException
*/
public function testGetEngineFromExtensionFail()
{
@ -121,9 +170,8 @@ class layoutTest extends CoreTestAbstract
*/
public function testCustomEngine()
{
// Create the engine
$mock = $this->getMockBuilder('\FuzeWorks\TemplateEngine\TemplateEngine')->getMock();
$mock = $this->getMockBuilder('FuzeWorks\TemplateEngine\TemplateEngine')->getMock();
// Add the methods
$mock->method('get')->willReturn('output');
@ -138,21 +186,52 @@ class layoutTest extends CoreTestAbstract
$this->assertEquals('output', Layout::get('test', 'tests/layout/testCustomEngine/'));
}
public function testPHPEngine()
/**
* @depends testCustomEngine
* @expectedException FuzeWorks\LayoutException
*/
public function testInvalidCustomEngine()
{
$mock = $this->getMock('MockEngine');
// Directory of these tests
$directory = 'tests/layout/testEngines/';
$this->assertEquals('PHP Template Check', Layout::get('php', $directory));
// Does not implement FuzeWorks\TemplateEngine\TemplateEngine, this should fail
Layout::registerEngine($mock, 'Custom', array('test'));
}
public function testJSONEngine()
public function testEnginesLoadView()
{
// Directory of these tests
$directory = 'tests/layout/testEngines/';
$directory = 'tests/layout/testEngines/';
// First the PHP Engine
$this->assertEquals('PHP Template Check', Layout::get('php', $directory));
Layout::reset();
// Then the JSON Engine
$this->assertEquals('JSON Template Check', json_decode(Layout::get('json', $directory), true)[0]);
Layout::reset();
// And the Smarty Engine
$this->assertEquals('Smarty Template Check', Layout::get('smarty', $directory));
}
public function testEngineVariables()
{
// Directory of these tests
$directory = 'tests/layout/testEngineVariables/';
// First the PHP Engine
Layout::assign('key', 'value');
$this->assertEquals('value', Layout::get('php', $directory));
Layout::reset();
// Then the JSON Engine
Layout::assign('key', 'value');
$this->assertEquals('value', json_decode(Layout::get('json', $directory), true)['data']['key']);
Layout::reset();
// And the Smarty Engine
Layout::assign('key', 'value');
$this->assertEquals('value', Layout::get('smarty', $directory));
}
}

151
tests/core_libraryTest.php Normal file
View File

@ -0,0 +1,151 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class LibraryTest.
*
* Libraries testing suite, will test basic loading of and management of Libraries
*/
class libraryTest extends CoreTestAbstract
{
protected $libraries;
public function setUp()
{
$factory = Factory::getInstance();
$this->libraries = $factory->libraries;
}
public function testGetLibrariesClass()
{
$this->assertInstanceOf('FuzeWorks\Libraries', $this->libraries);
}
/**
* @depends testGetLibrariesClass
*/
public function testLoadBasicLibrary()
{
// Simple test of loading a library and checking if it exists
$this->assertInstanceOf('Application\Library\TestLoadBasicLibrary',
$this->libraries->get('TestLoadBasicLibrary', null, array('tests/libraries/testLoadBasicLibrary')));
}
/**
* @depends testLoadBasicLibrary
*/
public function testLoadExtendedLibrary()
{
// Load an extended library Zip class
$library = $this->libraries->get('Zip', null, array('tests/libraries/testLoadExtendedLibrary'));
$this->assertInstanceOf('Application\Library\MY_Zip', $library);
// Test if it's also an instance of the parent class
$this->assertInstanceOf('FuzeWorks\Library\FW_Zip', $library);
}
/**
* @depends testLoadBasicLibrary
* @expectedException FuzeWorks\LibraryException
*/
public function testFailLoadLibrary()
{
$library = $this->libraries->get('FailLoadLibrary');
}
/**
* @depends testLoadExtendedLibrary
*/
public function testDifferentPrefix()
{
// Test if the prefix can be changed
Factory::getInstance()->config->getConfig('main')->application_prefix = 'unit_test_';
// Let's extend the Encryption class
$library = $this->libraries->get('Encryption', null, array('tests/libraries/testDifferentPrefix'));
// Test if it has both instances
$this->assertInstanceOf('FuzeWorks\Library\FW_Encryption', $library);
$this->assertInstanceOf('Application\Library\unit_test_Encryption', $library);
}
/**
* @expectedException FuzeWorks\LibraryException
*/
public function testAddLibraryPathFail()
{
// First test if the library is not loaded yet
$this->assertFalse(class_exists('TestAddLibraryPath', false));
// Now test if the library can be loaded (hint: it can not)
$this->libraries->get('TestAddLibraryPath');
}
/**
* @depends testAddLibraryPathFail
*/
public function testAddLibraryPath()
{
// Add the libraryPath
$this->libraries->addLibraryPath('tests/libraries/testAddLibraryPath');
// And try to load it again
$this->assertInstanceOf('Application\Library\TestAddLibraryPath', $this->libraries->get('TestAddLibraryPath'));
}
public function testRemoveLibraryPath()
{
// Test if the path does NOT exist
$this->assertFalse(in_array('tests/libraries/testRemoveLibraryPath', $this->libraries->getLibraryPaths()));
// Add it
$this->libraries->addLibraryPath('tests/libraries/testRemoveLibraryPath');
// Assert if it's there
$this->assertTrue(in_array('tests/libraries/testRemoveLibraryPath', $this->libraries->getLibraryPaths()));
// Remove it
$this->libraries->removeLibraryPath('tests/libraries/testRemoveLibraryPath');
// And test if it's gone again
$this->assertFalse(in_array('tests/libraries/testRemoveLibraryPath', $this->libraries->getLibraryPaths()));
}
public function tearDown()
{
Factory::getInstance()->config->getConfig('main')->revert();
}
}

View File

@ -29,7 +29,7 @@
*
* @version Version 0.0.1
*/
use \FuzeWorks\Router;
use FuzeWorks\Router;
/**
* Class RouterTest.

385
tests/core_securityTest.php Normal file
View File

@ -0,0 +1,385 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class SecurityTest.
*
* Core testing suite, will test security class functionality
*/
class securityTest extends CoreTestAbstract
{
public function setUp()
{
// Set cookie for security test
$_COOKIE['fw_csrf_cookie'] = md5(uniqid(mt_rand(), TRUE));
// Set config for Security class
$config = Factory::getInstance()->config->getConfig('security');
$config->csrf_protection = true;
$config->csrf_token_name = 'fw_csrf_token';
$config->csrf_cookie_name = 'fw_csrf_cookie';
$this->security = new Mock_Core_Security();
}
// --------------------------------------------------------------------
public function test_csrf_verify()
{
$_SERVER['REQUEST_METHOD'] = 'GET';
$this->assertInstanceOf('FuzeWorks\Security', $this->security->csrf_verify());
}
// --------------------------------------------------------------------
/**
* @expectedException FuzeWorks\SecurityException
*/
public function test_csrf_verify_invalid()
{
// Without issuing $_POST[csrf_token_name], this request will triggering CSRF error
$_SERVER['REQUEST_METHOD'] = 'POST';
$this->security->csrf_verify();
}
// --------------------------------------------------------------------
public function test_csrf_verify_valid()
{
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST[$this->security->csrf_token_name] = $this->security->csrf_hash;
$this->assertInstanceOf('FuzeWorks\Security', $this->security->csrf_verify());
}
// --------------------------------------------------------------------
public function test_get_csrf_hash()
{
$this->assertEquals($this->security->csrf_hash, $this->security->get_csrf_hash());
}
// --------------------------------------------------------------------
public function test_get_csrf_token_name()
{
$this->assertEquals('fw_csrf_token', $this->security->get_csrf_token_name());
}
// --------------------------------------------------------------------
public function test_xss_clean()
{
$harm_string = "Hello, i try to <script>alert('Hack');</script> your site";
$harmless_string = $this->security->xss_clean($harm_string);
$this->assertEquals("Hello, i try to [removed]alert&#40;'Hack'&#41;;[removed] your site", $harmless_string);
}
// --------------------------------------------------------------------
public function test_xss_clean_string_array()
{
$harm_strings = array(
"Hello, i try to <script>alert('Hack');</script> your site",
"Simple clean string",
"Hello, i try to <script>alert('Hack');</script> your site"
);
$harmless_strings = $this->security->xss_clean($harm_strings);
$this->assertEquals("Hello, i try to [removed]alert&#40;'Hack'&#41;;[removed] your site", $harmless_strings[0]);
$this->assertEquals("Simple clean string", $harmless_strings[1]);
$this->assertEquals("Hello, i try to [removed]alert&#40;'Hack'&#41;;[removed] your site", $harmless_strings[2]);
}
// --------------------------------------------------------------------
public function test_xss_clean_image_valid()
{
$harm_string = '<img src="test.png">';
$xss_clean_return = $this->security->xss_clean($harm_string, TRUE);
// $this->assertTrue($xss_clean_return);
}
// --------------------------------------------------------------------
public function test_xss_clean_image_invalid()
{
$harm_string = '<img src=javascript:alert(String.fromCharCode(88,83,83))>';
$xss_clean_return = $this->security->xss_clean($harm_string, TRUE);
$this->assertFalse($xss_clean_return);
}
// --------------------------------------------------------------------
public function test_xss_clean_entity_double_encoded()
{
$input = '<a href="&#38&#35&#49&#48&#54&#38&#35&#57&#55&#38&#35&#49&#49&#56&#38&#35&#57&#55&#38&#35&#49&#49&#53&#38&#35&#57&#57&#38&#35&#49&#49&#52&#38&#35&#49&#48&#53&#38&#35&#49&#49&#50&#38&#35&#49&#49&#54&#38&#35&#53&#56&#38&#35&#57&#57&#38&#35&#49&#49&#49&#38&#35&#49&#49&#48&#38&#35&#49&#48&#50&#38&#35&#49&#48&#53&#38&#35&#49&#49&#52&#38&#35&#49&#48&#57&#38&#35&#52&#48&#38&#35&#52&#57&#38&#35&#52&#49">Clickhere</a>';
$this->assertEquals('<a>Clickhere</a>', $this->security->xss_clean($input));
}
// --------------------------------------------------------------------
public function text_xss_clean_js_link_removal()
{
// This one is to prevent a false positive
$this->assertEquals(
"<a href=\"javascrip\n<t\n:alert\n&#40;1&#41;\"\n>",
$this->security->xss_clean("<a href=\"javascrip\n<t\n:alert\n(1)\"\n>")
);
}
// --------------------------------------------------------------------
public function test_xss_clean_js_img_removal()
{
$input = '<img src="&#38&#35&#49&#48&#54&#38&#35&#57&#55&#38&#35&#49&#49&#56&#38&#35&#57&#55&#38&#35&#49&#49&#53&#38&#35&#57&#57&#38&#35&#49&#49&#52&#38&#35&#49&#48&#53&#38&#35&#49&#49&#50&#38&#35&#49&#49&#54&#38&#35&#53&#56&#38&#35&#57&#57&#38&#35&#49&#49&#49&#38&#35&#49&#49&#48&#38&#35&#49&#48&#50&#38&#35&#49&#48&#53&#38&#35&#49&#49&#52&#38&#35&#49&#48&#57&#38&#35&#52&#48&#38&#35&#52&#57&#38&#35&#52&#49">Clickhere';
$this->assertEquals('<img>', $this->security->xss_clean($input));
}
// --------------------------------------------------------------------
public function test_xss_clean_sanitize_naughty_html_tags()
{
$this->assertEquals('&lt;unclosedTag', $this->security->xss_clean('<unclosedTag'));
$this->assertEquals('&lt;blink&gt;', $this->security->xss_clean('<blink>'));
$this->assertEquals('<fubar>', $this->security->xss_clean('<fubar>'));
$this->assertEquals(
'<img svg=""> src="x">',
$this->security->xss_clean('<img <svg=""> src="x">')
);
$this->assertEquals(
'<img src="b on=">on=">"x onerror="alert&#40;1&#41;">',
$this->security->xss_clean('<img src="b on="<x">on=">"x onerror="alert(1)">')
);
}
// --------------------------------------------------------------------
public function test_xss_clean_sanitize_naughty_html_attributes()
{
$this->assertEquals('<foo xss=removed>', $this->security->xss_clean('<foo onAttribute="bar">'));
$this->assertEquals('<foo xss=removed>', $this->security->xss_clean('<foo onAttributeNoQuotes=bar>'));
$this->assertEquals('<foo xss=removed>', $this->security->xss_clean('<foo onAttributeWithSpaces = bar>'));
$this->assertEquals('<foo prefixOnAttribute="bar">', $this->security->xss_clean('<foo prefixOnAttribute="bar">'));
$this->assertEquals('<foo>onOutsideOfTag=test</foo>', $this->security->xss_clean('<foo>onOutsideOfTag=test</foo>'));
$this->assertEquals('onNoTagAtAll = true', $this->security->xss_clean('onNoTagAtAll = true'));
$this->assertEquals('<foo xss=removed>', $this->security->xss_clean('<foo fscommand=case-insensitive>'));
$this->assertEquals('<foo xss=removed>', $this->security->xss_clean('<foo seekSegmentTime=whatever>'));
$this->assertEquals(
'<foo bar=">" baz=\'>\' xss=removed>',
$this->security->xss_clean('<foo bar=">" baz=\'>\' onAfterGreaterThan="quotes">')
);
$this->assertEquals(
'<foo bar=">" baz=\'>\' xss=removed>',
$this->security->xss_clean('<foo bar=">" baz=\'>\' onAfterGreaterThan=noQuotes>')
);
$this->assertEquals(
'<img src="x" on=""> on=&lt;svg&gt; onerror=alert&#40;1&#41;>',
$this->security->xss_clean('<img src="x" on=""> on=<svg> onerror=alert(1)>')
);
$this->assertEquals(
'<img src="on=\'">"&lt;svg&gt; onerror=alert&#40;1&#41; onmouseover=alert&#40;1&#41;>',
$this->security->xss_clean('<img src="on=\'">"<svg> onerror=alert(1) onmouseover=alert(1)>')
);
$this->assertEquals(
'<img src="x"> on=\'x\' onerror=``,alert&#40;1&#41;>',
$this->security->xss_clean('<img src="x"> on=\'x\' onerror=``,alert(1)>')
);
$this->assertEquals(
'<a xss=removed>',
$this->security->xss_clean('<a< onmouseover="alert(1)">')
);
$this->assertEquals(
'<img src="x"> on=\'x\' onerror=,xssm()>',
$this->security->xss_clean('<img src="x"> on=\'x\' onerror=,xssm()>')
);
$this->assertEquals(
'<image src="<>" xss=removed>',
$this->security->xss_clean('<image src="<>" onerror=\'alert(1)\'>')
);
$this->assertEquals(
'<b xss=removed>',
$this->security->xss_clean('<b "=<= onmouseover=alert(1)>')
);
$this->assertEquals(
'<b xss=removed xss=removed>1">',
$this->security->xss_clean('<b a=<=" onmouseover="alert(1),1>1">')
);
$this->assertEquals(
'<b x=" onmouseover=alert&#40;1&#41;//">',
$this->security->xss_clean('<b "="< x=" onmouseover=alert(1)//">')
);
}
// --------------------------------------------------------------------
/**
* @depends test_xss_clean_sanitize_naughty_html_tags
* @depends test_xss_clean_sanitize_naughty_html_attributes
*/
public function test_naughty_html_plus_evil_attributes()
{
$this->assertEquals(
'&lt;svg<img src="x" xss=removed>',
$this->security->xss_clean('<svg<img > src="x" onerror="location=/javascript/.source+/:alert/.source+/(1)/.source">')
);
}
// --------------------------------------------------------------------
public function test_xss_hash()
{
$this->assertEmpty($this->security->xss_hash);
// Perform hash
$this->security->xss_hash();
$this->assertTrue(preg_match('#^[0-9a-f]{32}$#iS', $this->security->xss_hash) === 1);
}
// --------------------------------------------------------------------
public function test_get_random_bytes()
{
$length = "invalid";
$this->assertFalse($this->security->get_random_bytes($length));
$length = 10;
$this->assertNotEmpty($this->security->get_random_bytes($length));
}
// --------------------------------------------------------------------
public function test_entity_decode()
{
$encoded = '&lt;div&gt;Hello &lt;b&gt;Booya&lt;/b&gt;&lt;/div&gt;';
$decoded = $this->security->entity_decode($encoded);
$this->assertEquals('<div>Hello <b>Booya</b></div>', $decoded);
// Issue #3057 (https://github.com/bcit-ci/CodeIgniter/issues/3057)
$this->assertEquals(
'&foo should not include a semicolon',
$this->security->entity_decode('&foo should not include a semicolon')
);
}
// --------------------------------------------------------------------
public function test_sanitize_filename()
{
$filename = './<!--foo-->';
$safe_filename = $this->security->sanitize_filename($filename);
$this->assertEquals('foo', $safe_filename);
}
// --------------------------------------------------------------------
public function test_strip_image_tags()
{
$imgtags = array(
'<img src="smiley.gif" alt="Smiley face" height="42" width="42">',
'<img alt="Smiley face" height="42" width="42" src="smiley.gif">',
'<img src="http://www.w3schools.com/images/w3schools_green.jpg">',
'<img src="/img/sunset.gif" height="100%" width="100%">',
'<img src="mdn-logo-sm.png" alt="MD Logo" srcset="mdn-logo-HD.png 2x, mdn-logo-small.png 15w, mdn-banner-HD.png 100w 2x" />',
'<img sqrc="/img/sunset.gif" height="100%" width="100%">',
'<img srqc="/img/sunset.gif" height="100%" width="100%">',
'<img srcq="/img/sunset.gif" height="100%" width="100%">',
'<img src=non-quoted.attribute foo="bar">'
);
$urls = array(
'smiley.gif',
'smiley.gif',
'http://www.w3schools.com/images/w3schools_green.jpg',
'/img/sunset.gif',
'mdn-logo-sm.png',
'<img sqrc="/img/sunset.gif" height="100%" width="100%">',
'<img srqc="/img/sunset.gif" height="100%" width="100%">',
'<img srcq="/img/sunset.gif" height="100%" width="100%">',
'non-quoted.attribute'
);
for ($i = 0; $i < count($imgtags); $i++)
{
$this->assertEquals($urls[$i], $this->security->strip_image_tags($imgtags[$i]));
}
}
// --------------------------------------------------------------------
public function test_csrf_set_hash()
{
// Set cookie for security test
$_COOKIE['fw_csrf_cookie'] = md5(uniqid(mt_rand(), TRUE));
// Set config for Security class
$config = Factory::getInstance()->config->getConfig('security');
$config->csrf_protection = true;
$config->csrf_token_name = 'fw_csrf_token';
// leave csrf_cookie_name as blank to test _csrf_set_hash function
$config->csrf_cookie_name = '';
$this->security = new Mock_Core_Security();
$this->assertNotEmpty($this->security->get_csrf_hash());
}
}

132
tests/core_utf8Test.php Normal file
View File

@ -0,0 +1,132 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class Utf8Test.
*
* Core testing suite, will test UTF8 class functionality
*/
class utf8Test extends CoreTestAbstract
{
protected $factory;
public function setUp()
{
$this->factory = Factory::getInstance();
$this->factory->config->getConfig('main')->charset = 'UTF-8';
$this->utf8 = new Mock_Core_Utf8();
}
// --------------------------------------------------------------------
/**
* __construct() test
*
* @covers Utf8::__construct
*/
public function test___construct()
{
if (defined('PREG_BAD_UTF8_ERROR') && (ICONV_ENABLED === TRUE OR MB_ENABLED === TRUE) && strtoupper($this->factory->config->getConfig('main')->charset) === 'UTF-8')
{
$this->assertTrue(UTF8_ENABLED);
}
else
{
$this->assertFalse(UTF8_ENABLED);
}
}
// --------------------------------------------------------------------
/**
* is_ascii() test
*
* Note: DO NOT move this below test_clean_string()
*/
public function test_is_ascii()
{
$this->assertTrue($this->utf8->is_ascii('foo bar'));
$this->assertFalse($this->utf8->is_ascii('тест'));
}
// --------------------------------------------------------------------
/**
* clean_string() test
*
* @depends test_is_ascii
* @covers Utf8::clean_string
*/
public function test_clean_string()
{
$this->assertEquals('foo bar', $this->utf8->clean_string('foo bar'));
$illegal_utf8 = "\xc0тест";
if (MB_ENABLED)
{
$this->assertEquals('тест', $this->utf8->clean_string($illegal_utf8));
}
elseif (ICONV_ENABLED)
{
// This is a known issue, iconv doesn't always work with //IGNORE
$this->assertTrue(in_array($this->utf8->clean_string($illegal_utf8), array('тест', ''), TRUE));
}
else
{
$this->assertEquals($illegal_utf8, $this->utf8->clean_string($illegal_utf8));
}
}
// --------------------------------------------------------------------
/**
* convert_to_utf8() test
*
* @covers Utf8::convert_to_utf8
*/
public function test_convert_to_utf8()
{
$this->markTestSkipped("Does not work properly yet. See issue #95");
if (MB_ENABLED OR ICONV_ENABLED)
{
$this->assertEquals('тест', $this->utf8->convert_to_utf8('<27><><EFBFBD><EFBFBD>', 'WINDOWS-1251'));
}
else
{
$this->assertFalse($this->utf8->convert_to_utf8('<27><><EFBFBD><EFBFBD>', 'WINDOWS-1251'));
}
}
}

View File

@ -29,9 +29,9 @@
*
* @version Version 0.0.1
*/
use \FuzeWorks\Core;
use \FuzeWorks\Events;
use \FuzeWorks\EventPriority;
use FuzeWorks\Core;
use FuzeWorks\Events;
use FuzeWorks\EventPriority;
/**
* Class CoreStartEventTest.

View File

@ -29,9 +29,9 @@
*
* @version Version 0.0.1
*/
use \FuzeWorks\Events;
use \FuzeWorks\Layout;
use \FuzeWorks\EventPriority;
use FuzeWorks\Events;
use FuzeWorks\Layout;
use FuzeWorks\EventPriority;
/**
* Class LayoutLoadViewEventTest.
@ -55,7 +55,7 @@ class layoutLoadViewEventTest extends CoreTestAbstract
/**
* Intercept and change the event.
*
* @expectedException \FuzeWorks\LayoutException
* @expectedException FuzeWorks\LayoutException
*/
public function test_change()
{

View File

@ -29,9 +29,9 @@
*
* @version Version 0.0.1
*/
use \FuzeWorks\Events;
use \FuzeWorks\Router;
use \FuzeWorks\EventPriority;
use FuzeWorks\Events;
use FuzeWorks\Router;
use FuzeWorks\EventPriority;
/**
* Class RouterRouteEventTest.

View File

@ -29,9 +29,9 @@
*
* @version Version 0.0.1
*/
use \FuzeWorks\Events;
use \FuzeWorks\Router;
use \FuzeWorks\EventPriority;
use FuzeWorks\Events;
use FuzeWorks\Router;
use FuzeWorks\EventPriority;
/**
* Class RouterSetPathEventTest.

View File

@ -0,0 +1,83 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class ArrayHelperTest.
*
* Helpers testing suite, will test specific helper
*/
class arrayHelperTest extends CoreTestAbstract
{
public $my_array = array(
'foo' => 'bar',
'sally' => 'jim',
'maggie' => 'bessie',
'herb' => 'cook'
);
public function setUp()
{
// Load Helper
Factory::getInstance()->helpers->load('array');
}
// ------------------------------------------------------------------------
public function test_element_with_existing_item()
{
$this->assertEquals(FALSE, element('testing', $this->my_array));
$this->assertEquals('not set', element('testing', $this->my_array, 'not set'));
$this->assertEquals('bar', element('foo', $this->my_array));
}
// ------------------------------------------------------------------------
public function test_random_element()
{
// Send a string, not an array to random_element
$this->assertEquals('my string', random_element('my string'));
// Test sending an array
$this->assertEquals(TRUE, in_array(random_element($this->my_array), $this->my_array));
}
// ------------------------------------------------------------------------
public function test_elements()
{
$this->assertEquals(TRUE, is_array(elements('test', $this->my_array)));
$this->assertEquals(TRUE, is_array(elements('foo', $this->my_array)));
}
}

View File

@ -0,0 +1,92 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class CommonHelperTest.
*
* Helpers testing suite, will test specific helper
*/
class commonHelperTest extends CoreTestAbstract
{
public function setUp()
{
// Load Helper
Factory::getInstance()->helpers->load('common');
}
public function test_stringify_attributes()
{
$this->assertEquals(' class="foo" id="bar"', _stringify_attributes(array('class' => 'foo', 'id' => 'bar')));
$atts = new stdClass;
$atts->class = 'foo';
$atts->id = 'bar';
$this->assertEquals(' class="foo" id="bar"', _stringify_attributes($atts));
$atts = new stdClass;
$this->assertEquals('', _stringify_attributes($atts));
$this->assertEquals(' class="foo" id="bar"', _stringify_attributes('class="foo" id="bar"'));
$this->assertEquals('', _stringify_attributes(array()));
}
// ------------------------------------------------------------------------
public function test_stringify_js_attributes()
{
$this->assertEquals('width=800,height=600', _stringify_attributes(array('width' => '800', 'height' => '600'), TRUE));
$atts = new stdClass;
$atts->width = 800;
$atts->height = 600;
$this->assertEquals('width=800,height=600', _stringify_attributes($atts, TRUE));
}
// ------------------------------------------------------------------------
public function test_html_escape()
{
$this->assertEquals(
html_escape('Here is a string containing "quoted" text.'),
'Here is a string containing &quot;quoted&quot; text.'
);
$this->assertEquals(
html_escape(array('associative' => 'and', array('multi' => 'dimentional'))),
array('associative' => 'and', array('multi' => 'dimentional'))
);
}
}

View File

@ -0,0 +1,185 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class FileHelperTest.
*
* Helpers testing suite, will test specific helper
*/
class fileHelperTest extends CoreTestAbstract
{
public function setUp()
{
// Load Helper
Factory::getInstance()->helpers->load('file');
vfsStreamWrapper::register();
vfsStreamWrapper::setRoot(new vfsStreamDirectory('testDir'));
$this->_test_dir = vfsStreamWrapper::getRoot();
}
// --------------------------------------------------------------------
public function test_read_file()
{
$this->assertFalse(read_file('does_not_exist'));
$content = 'Jack and Jill went up the mountain to fight a billy goat.';
$file = vfsStream::newFile('my_file.txt')->withContent($content)->at($this->_test_dir);
$this->assertEquals($content, read_file(vfsStream::url('my_file.txt')));
}
// --------------------------------------------------------------------
public function test_octal_permissions()
{
$content = 'Jack and Jill went up the mountain to fight a billy goat.';
$file = vfsStream::newFile('my_file.txt', 0777)
->withContent($content)
->lastModified(time() - 86400)
->at($this->_test_dir);
$this->assertEquals('777', octal_permissions($file->getPermissions()));
}
// --------------------------------------------------------------------
/**
* More tests should happen here, since I'm not hitting the whole function.
*/
public function test_symbolic_permissions()
{
$content = 'Jack and Jill went up the mountain to fight a billy goat.';
$file = vfsStream::newFile('my_file.txt', 0777)
->withContent($content)
->lastModified(time() - 86400)
->at($this->_test_dir);
$this->assertEquals('urwxrwxrwx', symbolic_permissions($file->getPermissions()));
}
// --------------------------------------------------------------------
public function test_get_mime_by_extension()
{
$content = 'Jack and Jill went up the mountain to fight a billy goat.';
$file = vfsStream::newFile('my_file.txt', 0777)
->withContent($content)
->lastModified(time() - 86400)
->at($this->_test_dir);
$this->assertEquals('text/plain', get_mime_by_extension(vfsStream::url('my_file.txt')));
// Test a mime with an array, such as png
$file = vfsStream::newFile('foo.png')->at($this->_test_dir);
$this->assertEquals('image/png', get_mime_by_extension(vfsStream::url('foo.png')));
// Test a file not in the mimes array
$file = vfsStream::newFile('foo.blarfengar')->at($this->_test_dir);
$this->assertFalse(get_mime_by_extension(vfsStream::url('foo.blarfengar')));
}
// --------------------------------------------------------------------
public function test_get_file_info()
{
// Test Bad File
$this->assertFalse(get_file_info('i_am_bad_boo'));
// Test the rest
// First pass in an array
$vals = array(
'name', 'server_path', 'size', 'date',
'readable', 'writable', 'executable', 'fileperms'
);
$this->_test_get_file_info($vals);
// Test passing in vals as a string.
$this->_test_get_file_info(implode(', ', $vals));
}
private function _test_get_file_info($vals)
{
$content = 'Jack and Jill went up the mountain to fight a billy goat.';
$last_modified = time() - 86400;
$file = vfsStream::newFile('my_file.txt', 0777)
->withContent($content)
->lastModified($last_modified)
->at($this->_test_dir);
$ret_values = array(
'name' => 'my_file.txt',
'server_path' => 'vfs://my_file.txt',
'size' => 57,
'date' => $last_modified,
'readable' => TRUE,
'writable' => TRUE,
'executable' => TRUE,
'fileperms' => 33279
);
$info = get_file_info(vfsStream::url('my_file.txt'), $vals);
foreach ($info as $k => $v)
{
$this->assertEquals($ret_values[$k], $v);
}
}
// --------------------------------------------------------------------
public function test_write_file()
{
$content = 'Jack and Jill went up the mountain to fight a billy goat.';
$file = vfsStream::newFile('write.txt', 0777)
->withContent('')
->lastModified(time() - 86400)
->at($this->_test_dir);
$this->assertTrue(write_file(vfsStream::url('write.txt'), $content));
}
}

View File

@ -0,0 +1,52 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class XmlHelperTest.
*
* Helpers testing suite, will test specific helper
*/
class xmlHelperTest extends CoreTestAbstract
{
public function setUp()
{
// Load Helper
Factory::getInstance()->helpers->load('xml');
}
public function test_xml_convert()
{
$this->assertEquals('&lt;tag&gt;my &amp; test &#45; &lt;/tag&gt;', xml_convert('<tag>my & test - </tag>'));
}
}

View File

@ -0,0 +1,10 @@
<?php
if ( ! function_exists('testAddHelperPathFunction'))
{
function testAddHelperPathFunction($someParameter)
{
return 'SomeResult';
}
}

View File

@ -0,0 +1,10 @@
<?php
if ( ! function_exists('testHelperFunction'))
{
function testHelperFunction($someParameter)
{
return 'SomeResult';
}
}

View File

@ -0,0 +1,2 @@
<?php
echo $vars['key'];

View File

@ -0,0 +1 @@
{$key}

View File

@ -0,0 +1 @@
Smarty Template Check

View File

@ -0,0 +1 @@
Retrieved Data

View File

@ -0,0 +1,41 @@
<?php
use FuzeWorks\Library\FW_Encryption;
class Mock_Libraries_Encryption extends FW_Encryption {
/**
* __get_params()
*
* Allows public calls to the otherwise protected _get_params().
*/
public function __get_params($params)
{
return $this->_get_params($params);
}
// --------------------------------------------------------------------
/**
* get_key()
*
* Allows checking for key changes.
*/
public function get_key()
{
return $this->_key;
}
// --------------------------------------------------------------------
/**
* __driver_get_handle()
*
* Allows checking for _mcrypt_get_handle(), _openssl_get_handle()
*/
public function __driver_get_handle($driver, $cipher, $mode)
{
return $this->{'_'.$driver.'_get_handle'}($cipher, $mode);
}
}

View File

@ -0,0 +1,423 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
*
* @link http://fuzeworks.techfuze.net
* @since Version 0.0.1
*
* @version Version 0.0.1
*/
use FuzeWorks\Factory;
/**
* Class FactoryTest.
*
* Will test the FuzeWorks Factory.
*/
class encryptionTest extends CoreTestAbstract
{
protected $factory;
public function setUp()
{
$this->factory = Factory::getInstance();
$this->factory->libraries->get('encryption');
require_once('encryption/mock_encryption.php');
$this->encryption = new Mock_Libraries_Encryption();
}
// --------------------------------------------------------------------
/**
* __construct test
*
* Covers behavior with $config['encryption_key'] set or not
*/
public function test___construct()
{
// Assume no configuration from set_up()
$this->assertNull($this->encryption->get_key());
// Try with an empty value
$this->factory->config->getConfig('encryption')->encryption_key = '';
$this->encrypt = new Mock_Libraries_Encryption();
$this->assertNull($this->encrypt->get_key());
$this->factory->config->getConfig('encryption')->encryption_key = str_repeat("\x0", 16);
$this->encrypt = new Mock_Libraries_Encryption();
$this->assertEquals(str_repeat("\x0", 16), $this->encrypt->get_key());
}
// --------------------------------------------------------------------
/**
* hkdf() test
*
* Applies test vectors described in Appendix A(1-3) RFC5869.
* Described vectors 4-7 SHA-1, which we don't support and are
* therefore excluded.
*
* Because our implementation is a single method instead of being
* split into hkdf_extract() and hkdf_expand(), we cannot test for
* the PRK value. As long as the OKM is correct though, it's fine.
*
* @link https://tools.ietf.org/rfc/rfc5869.txt
*/
public function test_hkdf()
{
$vectors = array(
// A.1: Basic test case with SHA-256
array(
'digest' => 'sha256',
'ikm' => "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
'salt' => "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c",
'length' => 42,
'info' => "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
// 'prk' => "\x07\x77\x09\x36\x2c\x2e\x32\xdf\x0d\xdc\x3f\x0d\xc4\x7b\xba\x63\x90\xb6\xc7\x3b\xb5\x0f\x9c\x31\x22\xec\x84\x4a\xd7\xc2\xb3\xe5",
'okm' => "\x3c\xb2\x5f\x25\xfa\xac\xd5\x7a\x90\x43\x4f\x64\xd0\x36\x2f\x2a\x2d\x2d\x0a\x90\xcf\x1a\x5a\x4c\x5d\xb0\x2d\x56\xec\xc4\xc5\xbf\x34\x00\x72\x08\xd5\xb8\x87\x18\x58\x65"
),
// A.2: Test with SHA-256 and longer inputs/outputs
array(
'digest' => 'sha256',
'ikm' => "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
'salt' => "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
'length' => 82,
'info' => "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
// 'prk' => "\x06\xa6\xb8\x8c\x58\x53\x36\x1a\x06\x10\x4c\x9c\xeb\x35\xb4\x5c\xef\x76\x00\x14\x90\x46\x71\x01\x4a\x19\x3f\x40\xc1\x5f\xc2\x44",
'okm' => "\xb1\x1e\x39\x8d\xc8\x03\x27\xa1\xc8\xe7\xf7\x8c\x59\x6a\x49\x34\x4f\x01\x2e\xda\x2d\x4e\xfa\xd8\xa0\x50\xcc\x4c\x19\xaf\xa9\x7c\x59\x04\x5a\x99\xca\xc7\x82\x72\x71\xcb\x41\xc6\x5e\x59\x0e\x09\xda\x32\x75\x60\x0c\x2f\x09\xb8\x36\x77\x93\xa9\xac\xa3\xdb\x71\xcc\x30\xc5\x81\x79\xec\x3e\x87\xc1\x4c\x01\xd5\xc1\xf3\x43\x4f\x1d\x87",
),
// A.3: Test with SHA-256 and zero-length salt/info
array(
'digest' => 'sha256',
'ikm' => "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
'salt' => '',
'length' => 42,
'info' => '',
// 'prk' => "\x19\xef\x24\xa3\x2c\x71\x7b\x16\x7f\x33\xa9\x1d\x6f\x64\x8b\xdf\x96\x59\x67\x76\xaf\xdb\x63\x77\xac\x43\x4c\x1c\x29\x3c\xcb\x04",
'okm' => "\x8d\xa4\xe7\x75\xa5\x63\xc1\x8f\x71\x5f\x80\x2a\x06\x3c\x5a\x31\xb8\xa1\x1f\x5c\x5e\xe1\x87\x9e\xc3\x45\x4e\x5f\x3c\x73\x8d\x2d\x9d\x20\x13\x95\xfa\xa4\xb6\x1a\x96\xc8",
)
);
foreach ($vectors as $test)
{
$this->assertEquals(
$test['okm'],
$this->encryption->hkdf(
$test['ikm'],
$test['digest'],
$test['salt'],
$test['length'],
$test['info']
)
);
}
// Test default length, it must match the digest size
$this->assertEquals(64, strlen($this->encryption->hkdf('foobar', 'sha512')));
// Test maximum length (RFC5869 says that it must be up to 255 times the digest size)
$this->assertEquals(12240, strlen($this->encryption->hkdf('foobar', 'sha384', NULL, 48 * 255)));
$this->assertFalse($this->encryption->hkdf('foobar', 'sha224', NULL, 28 * 255 + 1));
// CI-specific test for an invalid digest
$this->assertFalse($this->encryption->hkdf('fobar', 'sha1'));
}
// --------------------------------------------------------------------
/**
* _get_params() test
*/
public function test__get_params()
{
$key = str_repeat("\x0", 16);
// Invalid custom parameters
$params = array(
// No cipher, mode or key
array('cipher' => 'aes-128', 'mode' => 'cbc'),
array('cipher' => 'aes-128', 'key' => $key),
array('mode' => 'cbc', 'key' => $key),
// No HMAC key or not a valid digest
array('cipher' => 'aes-128', 'mode' => 'cbc', 'key' => $key),
array('cipher' => 'aes-128', 'mode' => 'cbc', 'key' => $key, 'hmac_digest' => 'sha1', 'hmac_key' => $key),
// Invalid mode
array('cipher' => 'aes-128', 'mode' => 'foo', 'key' => $key, 'hmac_digest' => 'sha256', 'hmac_key' => $key)
);
for ($i = 0, $c = count($params); $i < $c; $i++)
{
$this->assertFalse($this->encryption->__get_params($params[$i]));
}
// Valid parameters
$params = array(
'cipher' => 'aes-128',
'mode' => 'cbc',
'key' => str_repeat("\x0", 16),
'hmac_key' => str_repeat("\x0", 16)
);
$this->assertTrue(is_array($this->encryption->__get_params($params)));
$params['base64'] = TRUE;
$params['hmac_digest'] = 'sha512';
// Including all parameters
$params = array(
'cipher' => 'aes-128',
'mode' => 'cbc',
'key' => str_repeat("\x0", 16),
'raw_data' => TRUE,
'hmac_key' => str_repeat("\x0", 16),
'hmac_digest' => 'sha256'
);
$output = $this->encryption->__get_params($params);
unset($output['handle'], $output['cipher'], $params['raw_data'], $params['cipher']);
$params['base64'] = FALSE;
$this->assertEquals($params, $output);
// HMAC disabled
unset($params['hmac_key'], $params['hmac_digest']);
$params['hmac'] = $params['raw_data'] = FALSE;
$params['cipher'] = 'aes-128';
$output = $this->encryption->__get_params($params);
unset($output['handle'], $output['cipher'], $params['hmac'], $params['raw_data'], $params['cipher']);
$params['base64'] = TRUE;
$params['hmac_digest'] = $params['hmac_key'] = NULL;
$this->assertEquals($params, $output);
}
// --------------------------------------------------------------------
/**
* initialize(), encrypt(), decrypt() test
*
* Testing the three methods separately is not realistic as they are
* designed to work together. A more thorough test for initialize()
* though is the OpenSSL/MCrypt compatibility test.
*
* @depends test_hkdf
* @depends test__get_params
*/
public function test_initialize_encrypt_decrypt()
{
$message = 'This is a plain-text message.';
$key = "\xd0\xc9\x08\xc4\xde\x52\x12\x6e\xf8\xcc\xdb\x03\xea\xa0\x3a\x5c";
// Default state (AES-128/Rijndael-128 in CBC mode)
$this->encryption->initialize(array('key' => $key));
// Was the key properly set?
$this->assertEquals($key, $this->encryption->get_key());
$this->assertEquals($message, $this->encryption->decrypt($this->encryption->encrypt($message)));
// Try DES in ECB mode, just for the sake of changing stuff
$this->encryption->initialize(array('cipher' => 'des', 'mode' => 'ecb', 'key' => substr($key, 0, 8)));
$this->assertEquals($message, $this->encryption->decrypt($this->encryption->encrypt($message)));
}
// --------------------------------------------------------------------
/**
* encrypt(), decrypt test with custom parameters
*
* @depends test__get_params
*/
public function test_encrypt_decrypt_custom()
{
$message = 'Another plain-text message.';
// A random invalid parameter
$this->assertFalse($this->encryption->encrypt($message, array('foo')));
$this->assertFalse($this->encryption->decrypt($message, array('foo')));
// No HMAC, binary output
$params = array(
'cipher' => 'tripledes',
'mode' => 'cfb',
'key' => str_repeat("\x1", 16),
'base64' => FALSE,
'hmac' => FALSE
);
$ciphertext = $this->encryption->encrypt($message, $params);
$this->assertEquals($message, $this->encryption->decrypt($ciphertext, $params));
}
// --------------------------------------------------------------------
/**
* _mcrypt_get_handle() test
*/
public function test__mcrypt_get_handle()
{
if ($this->encryption->drivers['mcrypt'] === FALSE)
{
return $this->markTestSkipped('Cannot test MCrypt because it is not available.');
}
$this->assertTrue(is_resource($this->encryption->__driver_get_handle('mcrypt', 'rijndael-128', 'cbc')));
}
// --------------------------------------------------------------------
/**
* _openssl_get_handle() test
*/
public function test__openssl_mcrypt_get_handle()
{
if ($this->encryption->drivers['openssl'] === FALSE)
{
return $this->markTestSkipped('Cannot test OpenSSL because it is not available.');
}
$this->assertEquals('aes-128-cbc', $this->encryption->__driver_get_handle('openssl', 'aes-128', 'cbc'));
$this->assertEquals('rc4-40', $this->encryption->__driver_get_handle('openssl', 'rc4-40', 'stream'));
}
// --------------------------------------------------------------------
/**
* OpenSSL/MCrypt portability test
*
* Amongst the obvious stuff, _cipher_alias() is also tested here.
*/
public function test_portability()
{
if ( ! $this->encryption->drivers['mcrypt'] OR ! $this->encryption->drivers['openssl'])
{
$this->markTestSkipped('Both MCrypt and OpenSSL support are required for portability tests.');
return;
}
$message = 'This is a message encrypted via MCrypt and decrypted via OpenSSL, or vice-versa.';
// Format is: <Cipher name>, <Cipher mode>, <Key size>
$portable = array(
array('aes-128', 'cbc', 16),
array('aes-128', 'cfb', 16),
array('aes-128', 'cfb8', 16),
array('aes-128', 'ofb', 16),
array('aes-128', 'ecb', 16),
array('aes-128', 'ctr', 16),
array('aes-192', 'cbc', 24),
array('aes-192', 'cfb', 24),
array('aes-192', 'cfb8', 24),
array('aes-192', 'ofb', 24),
array('aes-192', 'ecb', 24),
array('aes-192', 'ctr', 24),
array('aes-256', 'cbc', 32),
array('aes-256', 'cfb', 32),
array('aes-256', 'cfb8', 32),
array('aes-256', 'ofb', 32),
array('aes-256', 'ecb', 32),
array('aes-256', 'ctr', 32),
array('des', 'cbc', 7),
array('des', 'cfb', 7),
array('des', 'cfb8', 7),
array('des', 'ofb', 7),
array('des', 'ecb', 7),
array('tripledes', 'cbc', 7),
array('tripledes', 'cfb', 7),
array('tripledes', 'cfb8', 7),
array('tripledes', 'ofb', 7),
array('tripledes', 'cbc', 14),
array('tripledes', 'cfb', 14),
array('tripledes', 'cfb8', 14),
array('tripledes', 'ofb', 14),
array('tripledes', 'cbc', 21),
array('tripledes', 'cfb', 21),
array('tripledes', 'cfb8', 21),
array('tripledes', 'ofb', 21),
array('blowfish', 'cbc', 16),
array('blowfish', 'cfb', 16),
array('blowfish', 'ofb', 16),
array('blowfish', 'ecb', 16),
array('blowfish', 'cbc', 56),
array('blowfish', 'cfb', 56),
array('blowfish', 'ofb', 56),
array('blowfish', 'ecb', 56),
array('cast5', 'cbc', 11),
array('cast5', 'cfb', 11),
array('cast5', 'ofb', 11),
array('cast5', 'ecb', 11),
array('cast5', 'cbc', 16),
array('cast5', 'cfb', 16),
array('cast5', 'ofb', 16),
array('cast5', 'ecb', 16),
array('rc4', 'stream', 5),
array('rc4', 'stream', 8),
array('rc4', 'stream', 16),
array('rc4', 'stream', 32),
array('rc4', 'stream', 64),
array('rc4', 'stream', 128),
array('rc4', 'stream', 256)
);
$driver_index = array('mcrypt', 'openssl');
foreach ($portable as &$test)
{
// Add some randomness to the selected driver
$driver = mt_rand(0,1);
$params = array(
'driver' => $driver_index[$driver],
'cipher' => $test[0],
'mode' => $test[1],
'key' => openssl_random_pseudo_bytes($test[2])
);
$this->encryption->initialize($params);
$ciphertext = $this->encryption->encrypt($message);
$driver = (int) ! $driver;
$params['driver'] = $driver_index[$driver];
$this->encryption->initialize($params);
$this->assertEquals($message, $this->encryption->decrypt($ciphertext));
}
}
// --------------------------------------------------------------------
/**
* __get() test
*/
public function test_magic_get()
{
$this->assertNull($this->encryption->foo);
$this->assertEquals(array('mcrypt', 'openssl'), array_keys($this->encryption->drivers));
// 'stream' mode is translated into an empty string for OpenSSL
$this->encryption->initialize(array('cipher' => 'rc4', 'mode' => 'stream'));
$this->assertEquals('stream', $this->encryption->mode);
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace Application\Library;
class TestAddLibraryPath {
}

View File

@ -0,0 +1,8 @@
<?php
namespace Application\Library;
use FuzeWorks\Library\FW_Encryption;
class unit_test_Encryption extends FW_Encryption {
public $child = 'someValue';
}

View File

@ -0,0 +1,7 @@
<?php
namespace Application\Library;
class TestLoadBasicLibrary {
}

View File

@ -0,0 +1,8 @@
<?php
namespace Application\Library;
use FuzeWorks\Library\FW_Zip;
class MY_Zip extends FW_Zip {
public $child = 'someValue';
}

119
tests/mocks/autoloader.php Normal file
View File

@ -0,0 +1,119 @@
<?php
// This autoloader provide convinient way to working with mock object
// make the test looks natural. This autoloader support cascade file loading as well
// within mocks directory.
//
// Prototype :
//
// $mock_table = new Mock_Libraries_Table(); // Will load ./mocks/libraries/table.php
// $mock_database_driver = new Mock_Database_Driver(); // Will load ./mocks/database/driver.php
// and so on...
function autoload($class)
{
$dir = realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR;
$fw_core = array(
'Benchmark',
'Config',
'Controller',
'Exceptions',
'Hooks',
'Input',
'Lang',
'Loader',
'Log',
'Model',
'Output',
'Router',
'Security',
'URI',
'Utf8'
);
$fw_libraries = array(
'Calendar',
'Cart',
'Driver_Library',
'Email',
'Encrypt',
'Encryption',
'Form_validation',
'Ftp',
'Image_lib',
'Javascript',
'Migration',
'Pagination',
'Parser',
'Profiler',
'Table',
'Trackback',
'Typography',
'Unit_test',
'Upload',
'User_agent',
'Xmlrpc',
'Zip'
);
$fw_drivers = array('Session', 'Cache');
if (strpos($class, 'Mock_') === 0)
{
$class = strtolower(str_replace(array('Mock_', '_'), array('', DIRECTORY_SEPARATOR), $class));
}
elseif (strpos($class, 'FW_') === 0)
{
$subclass = substr($class, 3);
if (in_array($subclass, $fw_core))
{
$dir = 'Core'.DIRECTORY_SEPARATOR.'System'.DIRECTORY_SEPARATOR;
$class = $subclass;
}
elseif (in_array($subclass, $fw_libraries))
{
$dir = 'Core'.DIRECTORY_SEPARATOR.'Libraries'.DIRECTORY_SEPARATOR;
$class = ($subclass === 'Driver_Library') ? 'Driver' : $subclass;
}
elseif (in_array($subclass, $fw_drivers))
{
$dir = 'Core'.DIRECTORY_SEPARATOR.'Libraries'.DIRECTORY_SEPARATOR.$subclass.DIRECTORY_SEPARATOR;
$class = $subclass;
}
elseif (in_array(($parent = strtok($subclass, '_')), $fw_drivers)) {
$dir = 'Core'.DIRECTORY_SEPARATOR.'Libraries'.DIRECTORY_SEPARATOR.$parent.DIRECTORY_SEPARATOR.'drivers'.DIRECTORY_SEPARATOR;
$class = $subclass;
}
elseif (preg_match('/^FW_DB_(.+)_(.+)_(driver|forge|result|utility)$/', $class, $m) && count($m) === 4)
{
$driver_path = 'Core'.DIRECTORY_SEPARATOR.'Database'.DIRECTORY_SEPARATOR.'drivers'.DIRECTORY_SEPARATOR;
$dir = $driver_path.$m[1].DIRECTORY_SEPARATOR.'subdrivers'.DIRECTORY_SEPARATOR;
$file = $dir.$m[1].'_'.$m[2].'_'.$m[3].'.php';
}
elseif (preg_match('/^FW_DB_(.+)_(driver|forge|result|utility)$/', $class, $m) && count($m) === 3)
{
$driver_path = 'Core'.DIRECTORY_SEPARATOR.'Database'.DIRECTORY_SEPARATOR.'drivers'.DIRECTORY_SEPARATOR;
$dir = $driver_path.$m[1].DIRECTORY_SEPARATOR;
$file = $dir.$m[1].'_'.$m[2].'.php';
}
elseif (strpos($class, 'FW_DB') === 0)
{
$dir = 'Core'.DIRECTORY_SEPARATOR.'Database'.DIRECTORY_SEPARATOR;
$file = $dir.str_replace(array('FW_DB','active_record'), array('DB', 'active_rec'), $subclass).'.php';
}
else
{
$class = strtolower($class);
}
}
$file = isset($file) ? $file : $dir.$class.'.php';
if ( ! file_exists($file))
{
return FALSE;
}
include_once($file);
}

View File

@ -0,0 +1,53 @@
<?php
use FuzeWorks\Input;
use FuzeWorks\Factory;
class Mock_Core_Input extends Input {
/**
* Since we use GLOBAL to fetch Security and Utf8 classes,
* we need to use inversion of control to mock up
* the same process within CI_Input class constructor.
*
* @covers CI_Input::__construct()
*/
public function __construct($security, $utf8)
{
parent::__construct();
$this->_allow_get_array = ($this->factory->config->getConfig('routing')->allow_get_array === TRUE);
$this->_enable_xss = ($this->factory->config->getConfig('security')->global_xss_filtering === TRUE);
$this->_enable_csrf = ($this->factory->config->getConfig('security')->csrf_protection === TRUE);
// Assign Security and Utf8 classes
$this->security = $security;
$this->uni = $utf8;
// Sanitize global arrays
$this->_sanitize_globals();
}
public function fetch_from_array($array, $index = '', $xss_clean = FALSE)
{
return parent::_fetch_from_array($array, $index, $xss_clean);
}
/**
* Lie about being a CLI request
*
* We take advantage of this in libraries/Session_test
*/
public function is_cli_request()
{
return FALSE;
}
public function __set($name, $value)
{
if ($name === 'ip_address')
{
$this->ip_address = $value;
}
}
}

View File

@ -0,0 +1,37 @@
<?php
use FuzeWorks\Security;
class Mock_Core_Security extends Security {
public function csrf_set_cookie()
{
// We cannot set cookie in CLI mode, so for csrf test, who rely on $_COOKIE,
// we superseded set_cookie with directly set the cookie variable,
// @see : ./tests/codeigniter/core/Security_test.php, line 8
return $this;
}
// Override inaccessible protected properties
public function __get($property)
{
return isset($this->{'_'.$property}) ? $this->{'_'.$property} : NULL;
}
public function remove_evil_attributes($str, $is_image)
{
return $this->_remove_evil_attributes($str, $is_image);
}
// Override inaccessible protected method
public function __call($method, $params)
{
if (is_callable(array($this, '_'.$method)))
{
return call_user_func_array(array($this, '_'.$method), $params);
}
throw new BadMethodCallException('Method '.$method.' was not found');
}
}

21
tests/mocks/core/utf8.php Normal file
View File

@ -0,0 +1,21 @@
<?php
use FuzeWorks\Utf8;
class Mock_Core_Utf8 extends Utf8 {
/**
* We need to define UTF8_ENABLED the same way that
* CI_Utf8 constructor does.
*/
public function __construct()
{
if (defined('UTF8_ENABLED'))
{
return;
}
parent::__construct();
}
}

24
tests/phpunit.xml Normal file
View File

@ -0,0 +1,24 @@
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.5/phpunit.xsd"
bootstrap="autoload.php"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
colors="true">
<testsuites>
<testsuite name="Core Functionality">
<directory>.</directory>
</testsuite>
</testsuites>
<logging>
<log type="json" target="../build/phpunit/logfile.json"/>
<log type="junit" target="../build/phpunit/logfile.xml" logIncompleteSkipped="false"/>
<log type="testdox-html" target="../build/phpunit/testdox.html"/>
<log type="testdox-text" target="../build/phpunit/testdox.txt"/>
</logging>
</phpunit>