Kohana v3.3.5
This commit is contained in:
37
system/.travis.yml
Normal file
37
system/.travis.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
sudo: false
|
||||
|
||||
language: php
|
||||
|
||||
# Only build the main develop/master branches - feature branches will be covered by PRs
|
||||
branches:
|
||||
only:
|
||||
- /^[0-9\.]+\/(develop|master)$/
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache/files
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- php: 5.3
|
||||
env: 'COMPOSER_PHPUNIT="lowest"'
|
||||
|
||||
before_script:
|
||||
- composer self-update
|
||||
- COMPOSER_ROOT_VERSION=3.3.x-dev composer install --prefer-dist --no-interaction
|
||||
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then COMPOSER_ROOT_VERSION=3.3.x-dev composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
|
||||
- vendor/bin/koharness
|
||||
|
||||
script:
|
||||
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
|
||||
|
||||
notifications:
|
||||
email: false
|
1
system/CONTRIBUTING.md
Normal file
1
system/CONTRIBUTING.md
Normal file
@@ -0,0 +1 @@
|
||||
Please refer to the CONTRIBUTING file located under the [kohana](https://github.com/kohana/kohana) repo.
|
33
system/README.md
Normal file
33
system/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Kohana PHP Framework - core
|
||||
|
||||
| ver | Stable | Develop |
|
||||
|-------|------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
|
||||
| 3.3.x | [](https://travis-ci.org/kohana/core) | [](https://travis-ci.org/kohana/core) |
|
||||
| 3.4.x | [](https://travis-ci.org/kohana/core) | [](https://travis-ci.org/kohana/core) |
|
||||
|
||||
This is the core package for the [Kohana](http://kohanaframework.org/) object oriented HMVC framework built using PHP5.
|
||||
It aims to be swift, secure, and small.
|
||||
|
||||
Released under a [BSD license](http://kohanaframework.org/license), Kohana can be used legally for any open source,
|
||||
commercial, or personal project.
|
||||
|
||||
## Documentation and installation
|
||||
|
||||
See the [sample application repository](https://github.com/kohana/kohana) for full readme and contributing information.
|
||||
You will usually add `kohana/core` as a dependency in your own project's composer.json to install and work with this
|
||||
package.
|
||||
|
||||
## Installation for development
|
||||
|
||||
To work on this package, you'll want to install it with composer to get the required dependencies. Note that there are
|
||||
currently circular dependencies between this module and kohana/unittest. These may cause you problems if you are working
|
||||
on a feature branch, because composer may not be able to figure out which version of kohana core you have.
|
||||
|
||||
To work around this, run composer like: `COMPOSER_ROOT_VERSION=3.3.x-dev composer install`. This tells composer that the
|
||||
current checkout is a 3.3.* development version. Obviously change the argument if your branch is based on a different
|
||||
version.
|
||||
|
||||
After installing the dependencies, you'll need a skeleton Kohana application before you can run the unit tests etc. The
|
||||
simplest way to do this is to use kohana/koharness to build a bare project in `/tmp/koharness`.
|
||||
|
||||
If in doubt, check the install and test steps in the [.travis.yml](.travis.yml) file.
|
@@ -279,7 +279,13 @@ class Kohana_Arr {
|
||||
*/
|
||||
public static function get($array, $key, $default = NULL)
|
||||
{
|
||||
return isset($array[$key]) ? $array[$key] : $default;
|
||||
if ($array instanceof ArrayObject) {
|
||||
// This is a workaround for inconsistent implementation of isset between PHP and HHVM
|
||||
// See https://github.com/facebook/hhvm/issues/3437
|
||||
return $array->offsetExists($key) ? $array->offsetGet($key) : $default;
|
||||
} else {
|
||||
return isset($array[$key]) ? $array[$key] : $default;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -387,7 +393,7 @@ class Kohana_Arr {
|
||||
{
|
||||
if (is_array($val))
|
||||
{
|
||||
$array[$key] = Arr::map($callbacks, $array[$key]);
|
||||
$array[$key] = Arr::map($callbacks, $array[$key], $keys);
|
||||
}
|
||||
elseif ( ! is_array($keys) OR in_array($key, $keys))
|
||||
{
|
||||
|
@@ -71,14 +71,14 @@ class Kohana_Cookie {
|
||||
// Separate the salt and the value
|
||||
list ($hash, $value) = explode('~', $cookie, 2);
|
||||
|
||||
if (Cookie::salt($key, $value) === $hash)
|
||||
if (Security::slow_equals(Cookie::salt($key, $value), $hash))
|
||||
{
|
||||
// Cookie signature is valid
|
||||
return $value;
|
||||
}
|
||||
|
||||
// The cookie signature is invalid, delete it
|
||||
Cookie::delete($key);
|
||||
static::delete($key);
|
||||
}
|
||||
|
||||
return $default;
|
||||
@@ -88,33 +88,38 @@ class Kohana_Cookie {
|
||||
* Sets a signed cookie. Note that all cookie values must be strings and no
|
||||
* automatic serialization will be performed!
|
||||
*
|
||||
* [!!] By default, Cookie::$expiration is 0 - if you skip/pass NULL for the optional
|
||||
* lifetime argument your cookies will expire immediately unless you have separately
|
||||
* configured Cookie::$expiration.
|
||||
*
|
||||
*
|
||||
* // Set the "theme" cookie
|
||||
* Cookie::set('theme', 'red');
|
||||
*
|
||||
* @param string $name name of cookie
|
||||
* @param string $value value of cookie
|
||||
* @param integer $expiration lifetime in seconds
|
||||
* @param integer $lifetime lifetime in seconds
|
||||
* @return boolean
|
||||
* @uses Cookie::salt
|
||||
*/
|
||||
public static function set($name, $value, $expiration = NULL)
|
||||
public static function set($name, $value, $lifetime = NULL)
|
||||
{
|
||||
if ($expiration === NULL)
|
||||
if ($lifetime === NULL)
|
||||
{
|
||||
// Use the default expiration
|
||||
$expiration = Cookie::$expiration;
|
||||
$lifetime = Cookie::$expiration;
|
||||
}
|
||||
|
||||
if ($expiration !== 0)
|
||||
if ($lifetime !== 0)
|
||||
{
|
||||
// The expiration is expected to be a UNIX timestamp
|
||||
$expiration += time();
|
||||
$lifetime += static::_time();
|
||||
}
|
||||
|
||||
// Add the salt to the cookie value
|
||||
$value = Cookie::salt($name, $value).'~'.$value;
|
||||
|
||||
return setcookie($name, $value, $expiration, Cookie::$path, Cookie::$domain, Cookie::$secure, Cookie::$httponly);
|
||||
return static::_setcookie($name, $value, $lifetime, Cookie::$path, Cookie::$domain, Cookie::$secure, Cookie::$httponly);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +136,7 @@ class Kohana_Cookie {
|
||||
unset($_COOKIE[$name]);
|
||||
|
||||
// Nullify the cookie and make it expire
|
||||
return setcookie($name, NULL, -86400, Cookie::$path, Cookie::$domain, Cookie::$secure, Cookie::$httponly);
|
||||
return static::_setcookie($name, NULL, -86400, Cookie::$path, Cookie::$domain, Cookie::$secure, Cookie::$httponly);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,8 +144,10 @@ class Kohana_Cookie {
|
||||
*
|
||||
* $salt = Cookie::salt('theme', 'red');
|
||||
*
|
||||
* @param string $name name of cookie
|
||||
* @param string $value value of cookie
|
||||
* @param string $name name of cookie
|
||||
* @param string $value value of cookie
|
||||
*
|
||||
* @throws Kohana_Exception if Cookie::$salt is not configured
|
||||
* @return string
|
||||
*/
|
||||
public static function salt($name, $value)
|
||||
@@ -154,7 +161,38 @@ class Kohana_Cookie {
|
||||
// Determine the user agent
|
||||
$agent = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : 'unknown';
|
||||
|
||||
return sha1($agent.$name.$value.Cookie::$salt);
|
||||
return hash_hmac('sha1', $agent.$name.$value.Cookie::$salt, Cookie::$salt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy for the native setcookie function - to allow mocking in unit tests so that they do not fail when headers
|
||||
* have been sent.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param integer $expire
|
||||
* @param string $path
|
||||
* @param string $domain
|
||||
* @param boolean $secure
|
||||
* @param boolean $httponly
|
||||
*
|
||||
* @return bool
|
||||
* @see setcookie
|
||||
*/
|
||||
protected static function _setcookie($name, $value, $expire, $path, $domain, $secure, $httponly)
|
||||
{
|
||||
return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy for the native time function - to allow mocking of time-related logic in unit tests
|
||||
*
|
||||
* @return int
|
||||
* @see time
|
||||
*/
|
||||
protected static function _time()
|
||||
{
|
||||
return time();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,8 +16,8 @@
|
||||
class Kohana_Core {
|
||||
|
||||
// Release version and codename
|
||||
const VERSION = '3.3.1';
|
||||
const CODENAME = 'peregrinus';
|
||||
const VERSION = '3.3.5';
|
||||
const CODENAME = 'pharrell';
|
||||
|
||||
// Common environment type constants for consistency and convenience
|
||||
const PRODUCTION = 10;
|
||||
@@ -322,7 +322,7 @@ class Kohana_Core {
|
||||
}
|
||||
|
||||
// Determine if the extremely evil magic quotes are enabled
|
||||
Kohana::$magic_quotes = (version_compare(PHP_VERSION, '5.4') < 0 AND get_magic_quotes_gpc());
|
||||
Kohana::$magic_quotes = (bool) get_magic_quotes_gpc();
|
||||
|
||||
// Sanitize all request variables
|
||||
$_GET = Kohana::sanitize($_GET);
|
||||
|
@@ -592,10 +592,10 @@ class Kohana_Date {
|
||||
$tz = new DateTimeZone($timezone ? $timezone : date_default_timezone_get());
|
||||
$time = new DateTime($datetime_str, $tz);
|
||||
|
||||
if ($time->getTimeZone()->getName() !== $tz->getName())
|
||||
{
|
||||
$time->setTimeZone($tz);
|
||||
}
|
||||
// Convert the time back to the expected timezone if required (in case the datetime_str provided a timezone,
|
||||
// offset or unix timestamp. This also ensures that the timezone reported by the object is correct on HHVM
|
||||
// (see https://github.com/facebook/hhvm/issues/2302).
|
||||
$time->setTimeZone($tz);
|
||||
|
||||
return $time->format($timestamp_format);
|
||||
}
|
||||
|
@@ -133,8 +133,8 @@ class Kohana_Debug {
|
||||
|
||||
if ($marker === NULL)
|
||||
{
|
||||
// Make a unique marker
|
||||
$marker = uniqid("\x00");
|
||||
// Make a unique marker - force it to be alphanumeric so that it is always treated as a string array key
|
||||
$marker = uniqid("\x00")."x";
|
||||
}
|
||||
|
||||
if (empty($var))
|
||||
|
@@ -36,10 +36,33 @@ class Kohana_Encrypt {
|
||||
public static $instances = array();
|
||||
|
||||
/**
|
||||
* @var string OS-dependent RAND type to use
|
||||
* @var string RAND type to use
|
||||
*
|
||||
* Only MCRYPT_DEV_URANDOM and MCRYPT_DEV_RANDOM are considered safe.
|
||||
* Using MCRYPT_RAND will silently revert to MCRYPT_DEV_URANDOM
|
||||
*/
|
||||
protected static $_rand;
|
||||
protected static $_rand = MCRYPT_DEV_URANDOM;
|
||||
|
||||
/**
|
||||
* @var string Encryption key
|
||||
*/
|
||||
protected $_key;
|
||||
|
||||
/**
|
||||
* @var string mcrypt mode
|
||||
*/
|
||||
protected $_mode;
|
||||
|
||||
/**
|
||||
* @var string mcrypt cipher
|
||||
*/
|
||||
protected $_cipher;
|
||||
|
||||
/**
|
||||
* @var int the size of the Initialization Vector (IV) in bytes
|
||||
*/
|
||||
protected $_iv_size;
|
||||
|
||||
/**
|
||||
* Returns a singleton instance of Encrypt. An encryption key must be
|
||||
* provided in your "encrypt" configuration file.
|
||||
@@ -105,6 +128,10 @@ class Kohana_Encrypt {
|
||||
// Shorten the key to the maximum size
|
||||
$key = substr($key, 0, $size);
|
||||
}
|
||||
else if (version_compare(PHP_VERSION, '5.6.0', '>='))
|
||||
{
|
||||
$key = $this->_normalize_key($key, $cipher, $mode);
|
||||
}
|
||||
|
||||
// Store the key, mode, and cipher
|
||||
$this->_key = $key;
|
||||
@@ -129,43 +156,8 @@ class Kohana_Encrypt {
|
||||
*/
|
||||
public function encode($data)
|
||||
{
|
||||
// Set the rand type if it has not already been set
|
||||
if (Encrypt::$_rand === NULL)
|
||||
{
|
||||
if (Kohana::$is_windows)
|
||||
{
|
||||
// Windows only supports the system random number generator
|
||||
Encrypt::$_rand = MCRYPT_RAND;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (defined('MCRYPT_DEV_URANDOM'))
|
||||
{
|
||||
// Use /dev/urandom
|
||||
Encrypt::$_rand = MCRYPT_DEV_URANDOM;
|
||||
}
|
||||
elseif (defined('MCRYPT_DEV_RANDOM'))
|
||||
{
|
||||
// Use /dev/random
|
||||
Encrypt::$_rand = MCRYPT_DEV_RANDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the system random number generator
|
||||
Encrypt::$_rand = MCRYPT_RAND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Encrypt::$_rand === MCRYPT_RAND)
|
||||
{
|
||||
// The system random number generator must always be seeded each
|
||||
// time it is used, or it will not produce true random results
|
||||
mt_srand();
|
||||
}
|
||||
|
||||
// Create a random initialization vector of the proper size for the current cipher
|
||||
$iv = mcrypt_create_iv($this->_iv_size, Encrypt::$_rand);
|
||||
// Get an initialization vector
|
||||
$iv = $this->_create_iv();
|
||||
|
||||
// Encrypt the data using the configured options and generated iv
|
||||
$data = mcrypt_encrypt($this->_cipher, $this->_key, $data, $this->_mode, $iv);
|
||||
@@ -210,4 +202,54 @@ class Kohana_Encrypt {
|
||||
return rtrim(mcrypt_decrypt($this->_cipher, $this->_key, $data, $this->_mode, $iv), "\0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy for the mcrypt_create_iv function - to allow mocking and testing against KAT vectors
|
||||
*
|
||||
* @return string the initialization vector or FALSE on error
|
||||
*/
|
||||
protected function _create_iv()
|
||||
{
|
||||
/*
|
||||
* Silently use MCRYPT_DEV_URANDOM when the chosen random number generator
|
||||
* is not one of those that are considered secure.
|
||||
*
|
||||
* Also sets Encrypt::$_rand to MCRYPT_DEV_URANDOM when it's not already set
|
||||
*/
|
||||
if ((Encrypt::$_rand !== MCRYPT_DEV_URANDOM) AND ( Encrypt::$_rand !== MCRYPT_DEV_RANDOM))
|
||||
{
|
||||
Encrypt::$_rand = MCRYPT_DEV_URANDOM;
|
||||
}
|
||||
|
||||
// Create a random initialization vector of the proper size for the current cipher
|
||||
return mcrypt_create_iv($this->_iv_size, Encrypt::$_rand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize key for PHP 5.6 for backwards compatibility
|
||||
*
|
||||
* This method is a shim to make PHP 5.6 behave in a B/C way for
|
||||
* legacy key padding when shorter-than-supported keys are used
|
||||
*
|
||||
* @param string $key encryption key
|
||||
* @param string $cipher mcrypt cipher
|
||||
* @param string $mode mcrypt mode
|
||||
*/
|
||||
protected function _normalize_key($key, $cipher, $mode)
|
||||
{
|
||||
// open the cipher
|
||||
$td = mcrypt_module_open($cipher, '', $mode, '');
|
||||
|
||||
// loop through the supported key sizes
|
||||
foreach (mcrypt_enc_get_supported_key_sizes($td) as $supported) {
|
||||
// if key is short, needs padding
|
||||
if (strlen($key) <= $supported)
|
||||
{
|
||||
return str_pad($key, $supported, "\0");
|
||||
}
|
||||
}
|
||||
|
||||
// at this point key must be greater than max supported size, shorten it
|
||||
return substr($key, 0, mcrypt_get_key_size($cipher, $mode));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ class Kohana_Form {
|
||||
* @param mixed $action form action, defaults to the current request URI, or [Request] class to use
|
||||
* @param array $attributes html attributes
|
||||
* @return string
|
||||
* @uses Request::instance
|
||||
* @uses Request
|
||||
* @uses URL::site
|
||||
* @uses HTML::attributes
|
||||
*/
|
||||
|
@@ -126,9 +126,9 @@ class Kohana_HTML {
|
||||
$attributes['target'] = '_blank';
|
||||
}
|
||||
}
|
||||
elseif ($uri[0] !== '#')
|
||||
elseif ($uri[0] !== '#' AND $uri[0] !== '?')
|
||||
{
|
||||
// Make the URI absolute for non-id anchors
|
||||
// Make the URI absolute for non-fragment and non-query anchors
|
||||
$uri = URL::site($uri, $protocol, $index);
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,7 @@ class Kohana_HTML {
|
||||
*/
|
||||
public static function style($file, array $attributes = NULL, $protocol = NULL, $index = FALSE)
|
||||
{
|
||||
if (strpos($file, '://') === FALSE)
|
||||
if (strpos($file, '://') === FALSE AND strpos($file, '//') !== 0)
|
||||
{
|
||||
// Add the base URL
|
||||
$file = URL::site($file, $protocol, $index);
|
||||
@@ -239,7 +239,7 @@ class Kohana_HTML {
|
||||
*/
|
||||
public static function script($file, array $attributes = NULL, $protocol = NULL, $index = FALSE)
|
||||
{
|
||||
if (strpos($file, '://') === FALSE)
|
||||
if (strpos($file, '://') === FALSE AND strpos($file, '//') !== 0)
|
||||
{
|
||||
// Add the base URL
|
||||
$file = URL::site($file, $protocol, $index);
|
||||
|
@@ -95,7 +95,10 @@ abstract class Kohana_HTTP {
|
||||
if (extension_loaded('http'))
|
||||
{
|
||||
// Use the fast method to parse header string
|
||||
return new HTTP_Header(http_parse_headers($header_string));
|
||||
$headers = version_compare(phpversion('http'), '2.0.0', '>=') ?
|
||||
\http\Header::parse($header_string) :
|
||||
http_parse_headers($header_string);
|
||||
return new HTTP_Header($headers);
|
||||
}
|
||||
|
||||
// Otherwise we use the slower PHP parsing
|
||||
@@ -160,7 +163,10 @@ abstract class Kohana_HTTP {
|
||||
elseif (extension_loaded('http'))
|
||||
{
|
||||
// Return the much faster method
|
||||
return new HTTP_Header(http_get_request_headers());
|
||||
$headers = version_compare(phpversion('http'), '2.0.0', '>=') ?
|
||||
\http\Env::getRequestHeader() :
|
||||
http_get_request_headers();
|
||||
return new HTTP_Header($headers);
|
||||
}
|
||||
|
||||
// Setup the output
|
||||
@@ -186,8 +192,8 @@ abstract class Kohana_HTTP {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is a dirty hack to ensure HTTP_X_FOO_BAR becomes x-foo-bar
|
||||
$headers[str_replace(array('HTTP_', '_'), array('', '-'), $key)] = $value;
|
||||
// This is a dirty hack to ensure HTTP_X_FOO_BAR becomes X-FOO-BAR
|
||||
$headers[str_replace('_', '-', substr($key, 5))] = $value;
|
||||
}
|
||||
|
||||
return new HTTP_Header($headers);
|
||||
|
@@ -217,6 +217,16 @@ class Kohana_Kohana_Exception extends Exception {
|
||||
$frame['type'] = '??';
|
||||
}
|
||||
|
||||
// Xdebug returns the words 'dynamic' and 'static' instead of using '->' and '::' symbols
|
||||
if ('dynamic' === $frame['type'])
|
||||
{
|
||||
$frame['type'] = '->';
|
||||
}
|
||||
elseif ('static' === $frame['type'])
|
||||
{
|
||||
$frame['type'] = '::';
|
||||
}
|
||||
|
||||
// XDebug also has a different name for the parameters array
|
||||
if (isset($frame['params']) AND ! isset($frame['args']))
|
||||
{
|
||||
@@ -238,7 +248,13 @@ class Kohana_Kohana_Exception extends Exception {
|
||||
* The error view ends up several GB in size, taking
|
||||
* serveral minutes to render.
|
||||
*/
|
||||
if (defined('PHPUnit_MAIN_METHOD'))
|
||||
if (
|
||||
defined('PHPUnit_MAIN_METHOD')
|
||||
OR
|
||||
defined('PHPUNIT_COMPOSER_INSTALL')
|
||||
OR
|
||||
defined('__PHPUNIT_PHAR__')
|
||||
)
|
||||
{
|
||||
$trace = array_slice($trace, 0, 2);
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ class Kohana_Request implements HTTP_Request {
|
||||
|
||||
/**
|
||||
* Creates a new request object for the given URI. New requests should be
|
||||
* created using the [Request::instance] or [Request::factory] methods.
|
||||
* Created using the [Request::factory] method.
|
||||
*
|
||||
* $request = Request::factory($uri);
|
||||
*
|
||||
@@ -462,6 +462,12 @@ class Kohana_Request implements HTTP_Request {
|
||||
|
||||
foreach ($routes as $name => $route)
|
||||
{
|
||||
// Use external routes for reverse routing only
|
||||
if ($route->is_external())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// We found something suitable
|
||||
if ($params = $route->matches($request))
|
||||
{
|
||||
@@ -631,7 +637,7 @@ class Kohana_Request implements HTTP_Request {
|
||||
|
||||
/**
|
||||
* Creates a new request object for the given URI. New requests should be
|
||||
* created using the [Request::instance] or [Request::factory] methods.
|
||||
* Created using the [Request::factory] method.
|
||||
*
|
||||
* $request = new Request($uri);
|
||||
*
|
||||
@@ -662,7 +668,7 @@ class Kohana_Request implements HTTP_Request {
|
||||
$uri = array_shift($split_uri);
|
||||
|
||||
// Initial request has global $_GET already applied
|
||||
if (Request::$initial !== NULL)
|
||||
if (Request::$initial === NULL)
|
||||
{
|
||||
if ($split_uri)
|
||||
{
|
||||
@@ -675,7 +681,7 @@ class Kohana_Request implements HTTP_Request {
|
||||
// being able to proxy external pages.
|
||||
if ( ! $allow_external OR strpos($uri, '://') === FALSE)
|
||||
{
|
||||
// Remove trailing slashes from the URI
|
||||
// Remove leading and trailing slashes from the URI
|
||||
$this->_uri = trim($uri, '/');
|
||||
|
||||
// Apply the client
|
||||
@@ -726,7 +732,7 @@ class Kohana_Request implements HTTP_Request {
|
||||
if ($uri === NULL)
|
||||
{
|
||||
// Act as a getter
|
||||
return empty($this->_uri) ? '/' : $this->_uri;
|
||||
return ($this->_uri === '') ? '/' : $this->_uri;
|
||||
}
|
||||
|
||||
// Act as a setter
|
||||
@@ -740,7 +746,6 @@ class Kohana_Request implements HTTP_Request {
|
||||
*
|
||||
* echo URL::site($this->request->uri(), $protocol);
|
||||
*
|
||||
* @param array $params URI parameters
|
||||
* @param mixed $protocol protocol string or Request object
|
||||
* @return string
|
||||
* @since 3.0.7
|
||||
@@ -748,7 +753,13 @@ class Kohana_Request implements HTTP_Request {
|
||||
*/
|
||||
public function url($protocol = NULL)
|
||||
{
|
||||
// Create a URI with the current route and convert it to a URL
|
||||
if ($this->is_external())
|
||||
{
|
||||
// If it's an external request return the URI
|
||||
return $this->uri();
|
||||
}
|
||||
|
||||
// Create a URI with the current route, convert to a URL and returns
|
||||
return URL::site($this->uri(), $protocol);
|
||||
}
|
||||
|
||||
@@ -1219,9 +1230,9 @@ class Kohana_Request implements HTTP_Request {
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->headers('content-type',
|
||||
'application/x-www-form-urlencoded; charset='.Kohana::$charset);
|
||||
$body = http_build_query($post, NULL, '&');
|
||||
$this->body($body)
|
||||
->headers('content-type', 'application/x-www-form-urlencoded; charset='.Kohana::$charset);
|
||||
}
|
||||
|
||||
// Set the content length
|
||||
|
@@ -26,7 +26,7 @@ abstract class Kohana_Request_Client {
|
||||
/**
|
||||
* @var array Headers to preserve when following a redirect
|
||||
*/
|
||||
protected $_follow_headers = array('Authorization');
|
||||
protected $_follow_headers = array('authorization');
|
||||
|
||||
/**
|
||||
* @var bool Follow 302 redirect with original request method?
|
||||
@@ -205,7 +205,7 @@ abstract class Kohana_Request_Client {
|
||||
if ($follow_headers === NULL)
|
||||
return $this->_follow_headers;
|
||||
|
||||
$this->_follow_headers = $follow_headers;
|
||||
$this->_follow_headers = array_map('strtolower', $follow_headers);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -407,7 +407,8 @@ abstract class Kohana_Request_Client {
|
||||
|
||||
// Prepare the additional request, copying any follow_headers that were present on the original request
|
||||
$orig_headers = $request->headers()->getArrayCopy();
|
||||
$follow_headers = array_intersect_assoc($orig_headers, array_fill_keys($client->follow_headers(), TRUE));
|
||||
$follow_header_keys = array_intersect(array_keys($orig_headers), $client->follow_headers());
|
||||
$follow_headers = \Arr::extract($orig_headers, $follow_header_keys);
|
||||
|
||||
$follow_request = Request::factory($response->headers('Location'))
|
||||
->method($follow_method)
|
||||
|
@@ -34,7 +34,10 @@ class Kohana_Request_Client_Curl extends Request_Client_External {
|
||||
// if using a request other than POST. PUT does support this method
|
||||
// and DOES NOT require writing data to disk before putting it, if
|
||||
// reading the PHP docs you may have got that impression. SdF
|
||||
$options[CURLOPT_POSTFIELDS] = $request->body();
|
||||
// This will also add a Content-Type: application/x-www-form-urlencoded header unless you override it
|
||||
if ($body = $request->body()) {
|
||||
$options[CURLOPT_POSTFIELDS] = $body;
|
||||
}
|
||||
|
||||
// Process headers
|
||||
if ($headers = $request->headers())
|
||||
|
@@ -127,6 +127,8 @@ abstract class Kohana_Request_Client_External extends Request_Client {
|
||||
->headers('content-type', 'application/x-www-form-urlencoded; charset='.Kohana::$charset);
|
||||
}
|
||||
|
||||
$request->headers('content-length', (string) $request->content_length());
|
||||
|
||||
// If Kohana expose, set the user-agent
|
||||
if (Kohana::$expose)
|
||||
{
|
||||
|
@@ -604,7 +604,10 @@ class Kohana_Response implements HTTP_Response {
|
||||
{
|
||||
if (extension_loaded('http'))
|
||||
{
|
||||
$this->_header['set-cookie'] = http_build_cookie($this->_cookies);
|
||||
$cookies = version_compare(phpversion('http'), '2.0.0', '>=') ?
|
||||
(string) new \http\Cookie($this->_cookies) :
|
||||
http_build_cookie($this->_cookies);
|
||||
$this->_header['set-cookie'] = $cookies;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -509,6 +509,14 @@ class Kohana_Route {
|
||||
*/
|
||||
public function uri(array $params = NULL)
|
||||
{
|
||||
if ($params)
|
||||
{
|
||||
// @issue #4079 rawurlencode parameters
|
||||
$params = array_map('rawurlencode', $params);
|
||||
// decode slashes back, see Apache docs about AllowEncodedSlashes and AcceptPathInfo
|
||||
$params = str_replace(array('%2F', '%5C'), array('/', '\\'), $params);
|
||||
}
|
||||
|
||||
$defaults = $this->_defaults;
|
||||
|
||||
/**
|
||||
|
@@ -28,8 +28,8 @@ class Kohana_Security {
|
||||
* And then check it when using [Validation]:
|
||||
*
|
||||
* $array->rules('csrf', array(
|
||||
* 'not_empty' => NULL,
|
||||
* 'Security::check' => NULL,
|
||||
* array('not_empty'),
|
||||
* array('Security::check'),
|
||||
* ));
|
||||
*
|
||||
* This provides a basic, but effective, method of preventing CSRF attacks.
|
||||
@@ -81,8 +81,29 @@ class Kohana_Security {
|
||||
*/
|
||||
public static function check($token)
|
||||
{
|
||||
return Security::token() === $token;
|
||||
return Security::slow_equals(Security::token(), $token);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compare two hashes in a time-invariant manner.
|
||||
* Prevents cryptographic side-channel attacks (timing attacks, specifically)
|
||||
*
|
||||
* @param string $a cryptographic hash
|
||||
* @param string $b cryptographic hash
|
||||
* @return boolean
|
||||
*/
|
||||
public static function slow_equals($a, $b)
|
||||
{
|
||||
$diff = strlen($a) ^ strlen($b);
|
||||
for($i = 0; $i < strlen($a) AND $i < strlen($b); $i++)
|
||||
{
|
||||
$diff |= ord($a[$i]) ^ ord($b[$i]);
|
||||
}
|
||||
return $diff === 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove image tags from a string.
|
||||
|
@@ -24,8 +24,31 @@ class Kohana_Session_Native extends Session {
|
||||
*/
|
||||
protected function _read($id = NULL)
|
||||
{
|
||||
/**
|
||||
* session_set_cookie_params will override php ini settings
|
||||
* If Cookie::$domain is NULL or empty and is passed, PHP
|
||||
* will override ini and sent cookies with the host name
|
||||
* of the server which generated the cookie
|
||||
*
|
||||
* see issue #3604
|
||||
*
|
||||
* see http://www.php.net/manual/en/function.session-set-cookie-params.php
|
||||
* see http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-domain
|
||||
*
|
||||
* set to Cookie::$domain if available, otherwise default to ini setting
|
||||
*/
|
||||
$session_cookie_domain = empty(Cookie::$domain)
|
||||
? ini_get('session.cookie_domain')
|
||||
: Cookie::$domain;
|
||||
|
||||
// Sync up the session cookie with Cookie parameters
|
||||
session_set_cookie_params($this->_lifetime, Cookie::$path, Cookie::$domain, Cookie::$secure, Cookie::$httponly);
|
||||
session_set_cookie_params(
|
||||
$this->_lifetime,
|
||||
Cookie::$path,
|
||||
$session_cookie_domain,
|
||||
Cookie::$secure,
|
||||
Cookie::$httponly
|
||||
);
|
||||
|
||||
// Do not allow PHP to send Cache-Control headers
|
||||
session_cache_limiter(FALSE);
|
||||
|
@@ -240,12 +240,13 @@ class Kohana_Text {
|
||||
*
|
||||
* @param string $string string to transform
|
||||
* @param string $delimiter delimiter to use
|
||||
* @uses UTF8::ucfirst
|
||||
* @return string
|
||||
*/
|
||||
public static function ucfirst($string, $delimiter = '-')
|
||||
{
|
||||
// Put the keys back the Case-Convention expected
|
||||
return implode($delimiter, array_map('ucfirst', explode($delimiter, $string)));
|
||||
return implode($delimiter, array_map('UTF8::ucfirst', explode($delimiter, $string)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,12 +294,15 @@ class Kohana_Text {
|
||||
|
||||
$regex = '!'.$regex.'!ui';
|
||||
|
||||
// if $replacement is a single character: replace each of the characters of the badword with $replacement
|
||||
if (UTF8::strlen($replacement) == 1)
|
||||
{
|
||||
$regex .= 'e';
|
||||
return preg_replace($regex, 'str_repeat($replacement, UTF8::strlen(\'$1\'))', $str);
|
||||
return preg_replace_callback($regex, function($matches) use ($replacement) {
|
||||
return str_repeat($replacement, UTF8::strlen($matches[1]));
|
||||
}, $str);
|
||||
}
|
||||
|
||||
// if $replacement is not a single character, fully replace the badword with $replacement
|
||||
return preg_replace($regex, $replacement, $str);
|
||||
}
|
||||
|
||||
@@ -587,35 +591,40 @@ class Kohana_Text {
|
||||
*
|
||||
* echo Text::widont($text);
|
||||
*
|
||||
* regex courtesy of the Typogrify project
|
||||
* @link http://code.google.com/p/typogrify/
|
||||
*
|
||||
* @param string $str text to remove widows from
|
||||
* @return string
|
||||
*/
|
||||
public static function widont($str)
|
||||
{
|
||||
$str = rtrim($str);
|
||||
$space = strrpos($str, ' ');
|
||||
|
||||
if ($space !== FALSE)
|
||||
{
|
||||
$str = substr($str, 0, $space).' '.substr($str, $space + 1);
|
||||
}
|
||||
|
||||
return $str;
|
||||
// use '%' as delimiter and 'x' as modifier
|
||||
$widont_regex = "%
|
||||
((?:</?(?:a|em|span|strong|i|b)[^>]*>)|[^<>\s]) # must be proceeded by an approved inline opening or closing tag or a nontag/nonspace
|
||||
\s+ # the space to replace
|
||||
([^<>\s]+ # must be flollowed by non-tag non-space characters
|
||||
\s* # optional white space!
|
||||
(</(a|em|span|strong|i|b)>\s*)* # optional closing inline tags with optional white space after each
|
||||
((</(p|h[1-6]|li|dt|dd)>)|$)) # end with a closing p, h1-6, li or the end of the string
|
||||
%x";
|
||||
return preg_replace($widont_regex, '$1 $2', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the client user agent.
|
||||
*
|
||||
* // Returns "Chrome" when using Google Chrome
|
||||
* $browser = Text::user_agent('browser');
|
||||
* $browser = Text::user_agent($agent, 'browser');
|
||||
*
|
||||
* Multiple values can be returned at once by using an array:
|
||||
*
|
||||
* // Get the browser and platform with a single call
|
||||
* $info = Text::user_agent(array('browser', 'platform'));
|
||||
* $info = Text::user_agent($agent, array('browser', 'platform'));
|
||||
*
|
||||
* When using an array for the value, an associative array will be returned.
|
||||
*
|
||||
* @param string $agent user_agent
|
||||
* @param mixed $value array or string to return: browser, version, robot, mobile, platform
|
||||
* @return mixed requested information, FALSE if nothing is found
|
||||
* @uses Kohana::$config
|
||||
@@ -649,7 +658,7 @@ class Kohana_Text {
|
||||
// Set the browser name
|
||||
$info['browser'] = $name;
|
||||
|
||||
if (preg_match('#'.preg_quote($search).'[^0-9.]*+([0-9.][0-9.a-z]*)#i', Request::$user_agent, $matches))
|
||||
if (preg_match('#'.preg_quote($search).'[^0-9.]*+([0-9.][0-9.a-z]*)#i', $agent, $matches))
|
||||
{
|
||||
// Set the version number
|
||||
$info['version'] = $matches[1];
|
||||
|
@@ -2,6 +2,8 @@
|
||||
/**
|
||||
* URL helper class.
|
||||
*
|
||||
* [!!] You need to setup the list of trusted hosts in the `url.php` config file, before starting using this helper class.
|
||||
*
|
||||
* @package Kohana
|
||||
* @category Helpers
|
||||
* @author Kohana Team
|
||||
@@ -14,7 +16,9 @@ class Kohana_URL {
|
||||
* Gets the base URL to the application.
|
||||
* To specify a protocol, provide the protocol as a string or request object.
|
||||
* If a protocol is used, a complete URL will be generated using the
|
||||
* `$_SERVER['HTTP_HOST']` variable.
|
||||
* `$_SERVER['HTTP_HOST']` variable, which will be validated against RFC 952
|
||||
* and RFC 2181, as well as against the list of trusted hosts you have set
|
||||
* in the `url.php` config file.
|
||||
*
|
||||
* // Absolute URL path with no host or protocol
|
||||
* echo URL::base();
|
||||
@@ -75,7 +79,7 @@ class Kohana_URL {
|
||||
$port = ':'.$port;
|
||||
}
|
||||
|
||||
if ($domain = parse_url($base_url, PHP_URL_HOST))
|
||||
if ($host = parse_url($base_url, PHP_URL_HOST))
|
||||
{
|
||||
// Remove everything but the path from the URL
|
||||
$base_url = parse_url($base_url, PHP_URL_PATH);
|
||||
@@ -83,11 +87,32 @@ class Kohana_URL {
|
||||
else
|
||||
{
|
||||
// Attempt to use HTTP_HOST and fallback to SERVER_NAME
|
||||
$domain = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
|
||||
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
|
||||
|
||||
// make $host lowercase
|
||||
$host = strtolower($host);
|
||||
|
||||
// check that host does not contain forbidden characters (see RFC 952 and RFC 2181)
|
||||
// use preg_replace() instead of preg_match() to prevent DoS attacks with long host names
|
||||
if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) {
|
||||
throw new Kohana_Exception(
|
||||
'Invalid host :host',
|
||||
array(':host' => $host)
|
||||
);
|
||||
}
|
||||
|
||||
// Validate $host, see if it matches trusted hosts
|
||||
if ( ! static::is_trusted_host($host))
|
||||
{
|
||||
throw new Kohana_Exception(
|
||||
'Untrusted host :host. If you trust :host, add it to the trusted hosts in the `url` config file.',
|
||||
array(':host' => $host)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the protocol and domain to the base URL
|
||||
$base_url = $protocol.'://'.$domain.$port.$base_url;
|
||||
$base_url = $protocol.'://'.$host.$port.$base_url;
|
||||
}
|
||||
|
||||
return $base_url;
|
||||
@@ -210,4 +235,41 @@ class Kohana_URL {
|
||||
return trim($title, $separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if given $host should be trusted.
|
||||
*
|
||||
* Tests against given $trusted_hosts
|
||||
* or looks for key `trusted_hosts` in `url` config
|
||||
*
|
||||
* @param string $host
|
||||
* @param array $trusted_hosts
|
||||
* @return boolean TRUE if $host is trustworthy
|
||||
*/
|
||||
public static function is_trusted_host($host, array $trusted_hosts = NULL)
|
||||
{
|
||||
|
||||
// If list of trusted hosts is not directly provided read from config
|
||||
if (empty($trusted_hosts))
|
||||
{
|
||||
$trusted_hosts = (array) Kohana::$config->load('url')->get('trusted_hosts');
|
||||
}
|
||||
|
||||
// loop through the $trusted_hosts array for a match
|
||||
foreach ($trusted_hosts as $trusted_host)
|
||||
{
|
||||
|
||||
// make sure we fully match the trusted hosts
|
||||
$pattern = '#^'.$trusted_host.'$#uD';
|
||||
|
||||
// return TRUE if there is match
|
||||
if (preg_match($pattern, $host)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// return FALSE as nothing is matched
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -70,13 +70,17 @@ class Kohana_UTF8 {
|
||||
|
||||
if ( ! UTF8::is_ascii($var))
|
||||
{
|
||||
// Disable notices
|
||||
$error_reporting = error_reporting(~E_NOTICE);
|
||||
// Temporarily save the mb_substitute_character() value into a variable
|
||||
$mb_substitute_character = mb_substitute_character();
|
||||
|
||||
// Disable substituting illegal characters with the default '?' character
|
||||
mb_substitute_character('none');
|
||||
|
||||
// convert encoding, this is expensive, used when $var is not ASCII
|
||||
$var = mb_convert_encoding($var, $charset, $charset);
|
||||
|
||||
// Turn notices back on
|
||||
error_reporting($error_reporting);
|
||||
// Reset mb_substitute_character() value back to the original setting
|
||||
mb_substitute_character($mb_substitute_character);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -219,7 +219,7 @@ class Kohana_Validation implements ArrayAccess {
|
||||
if ($field !== TRUE AND ! isset($this->_labels[$field]))
|
||||
{
|
||||
// Set the field label to the field name
|
||||
$this->_labels[$field] = preg_replace('/[^\pL]+/u', ' ', $field);
|
||||
$this->_labels[$field] = $field;
|
||||
}
|
||||
|
||||
// Store the rule and params for this rule
|
||||
@@ -430,6 +430,13 @@ class Kohana_Validation implements ArrayAccess {
|
||||
}
|
||||
}
|
||||
|
||||
// Unbind all the automatic bindings to avoid memory leaks.
|
||||
unset($this->_bound[':validation']);
|
||||
unset($this->_bound[':data']);
|
||||
unset($this->_bound[':field']);
|
||||
unset($this->_bound[':value']);
|
||||
|
||||
|
||||
// Restore the data to its original form
|
||||
$this->_data = $original;
|
||||
|
||||
|
@@ -40,6 +40,7 @@ class Kohana_View {
|
||||
* @param string $kohana_view_filename filename
|
||||
* @param array $kohana_view_data variables
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
protected static function capture($kohana_view_filename, array $kohana_view_data)
|
||||
{
|
||||
@@ -79,17 +80,25 @@ class Kohana_View {
|
||||
*
|
||||
* View::set_global($name, $value);
|
||||
*
|
||||
* @param string $key variable name or an array of variables
|
||||
* @param mixed $value value
|
||||
* You can also use an array or Traversable object to set several values at once:
|
||||
*
|
||||
* // Create the values $food and $beverage in the view
|
||||
* View::set_global(array('food' => 'bread', 'beverage' => 'water'));
|
||||
*
|
||||
* [!!] Note: When setting with using Traversable object we're not attaching the whole object to the view,
|
||||
* i.e. the object's standard properties will not be available in the view context.
|
||||
*
|
||||
* @param string|array|Traversable $key variable name or an array of variables
|
||||
* @param mixed $value value
|
||||
* @return void
|
||||
*/
|
||||
public static function set_global($key, $value = NULL)
|
||||
{
|
||||
if (is_array($key))
|
||||
if (is_array($key) OR $key instanceof Traversable)
|
||||
{
|
||||
foreach ($key as $key2 => $value)
|
||||
foreach ($key as $name => $value)
|
||||
{
|
||||
View::$_global_data[$key2] = $value;
|
||||
View::$_global_data[$name] = $value;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -127,7 +136,6 @@ class Kohana_View {
|
||||
*
|
||||
* @param string $file view filename
|
||||
* @param array $data array of values
|
||||
* @return void
|
||||
* @uses View::set_filename
|
||||
*/
|
||||
public function __construct($file = NULL, array $data = NULL)
|
||||
@@ -272,18 +280,21 @@ class Kohana_View {
|
||||
* // This value can be accessed as $foo within the view
|
||||
* $view->set('foo', 'my value');
|
||||
*
|
||||
* You can also use an array to set several values at once:
|
||||
* You can also use an array or Traversable object to set several values at once:
|
||||
*
|
||||
* // Create the values $food and $beverage in the view
|
||||
* $view->set(array('food' => 'bread', 'beverage' => 'water'));
|
||||
*
|
||||
* @param string $key variable name or an array of variables
|
||||
* @param mixed $value value
|
||||
* [!!] Note: When setting with using Traversable object we're not attaching the whole object to the view,
|
||||
* i.e. the object's standard properties will not be available in the view context.
|
||||
*
|
||||
* @param string|array|Traversable $key variable name or an array of variables
|
||||
* @param mixed $value value
|
||||
* @return $this
|
||||
*/
|
||||
public function set($key, $value = NULL)
|
||||
{
|
||||
if (is_array($key))
|
||||
if (is_array($key) OR $key instanceof Traversable)
|
||||
{
|
||||
foreach ($key as $name => $value)
|
||||
{
|
||||
|
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"_readme": "NOTE: see readme for COMPOSER_ROOT_VERSION instructions if you have dependency issues",
|
||||
"name": "kohana/core",
|
||||
"description": "Core system classes for the Kohana application framework",
|
||||
"homepage": "http://kohanaframework.org",
|
||||
@@ -21,12 +22,19 @@
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"kohana/unittest": "3.3.*@dev",
|
||||
"kohana/koharness": "*@dev"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-http": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-mcrypt": "*"
|
||||
},
|
||||
"extra": {
|
||||
"installer-paths": {
|
||||
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-3.3/develop": "3.3.x-dev",
|
||||
"dev-3.4/develop": "3.4.x-dev"
|
||||
|
@@ -192,6 +192,7 @@ return array(
|
||||
'wav' => array('audio/x-wav'),
|
||||
'wax' => array('audio/x-ms-wax'),
|
||||
'wbxml' => array('application/wbxml'),
|
||||
'webapp' => array('application/x-web-app-manifest+json'),
|
||||
'webm' => array('video/webm'),
|
||||
'wm' => array('video/x-ms-wm'),
|
||||
'wma' => array('audio/x-ms-wma'),
|
||||
|
18
system/config/url.php
Normal file
18
system/config/url.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php defined('SYSPATH') OR die('No direct script access.');
|
||||
|
||||
return array(
|
||||
|
||||
'trusted_hosts' => array(
|
||||
// Set up your hostnames here
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// 'example\.org',
|
||||
// '.*\.example\.org',
|
||||
//
|
||||
// Do not forget to escape your dots (.) as these are regex patterns.
|
||||
// These patterns should always fully match,
|
||||
// as they are prepended with `^` and appended with `$`
|
||||
),
|
||||
|
||||
);
|
@@ -3,6 +3,8 @@
|
||||
return array(
|
||||
|
||||
'platform' => array(
|
||||
'windows nt 10.0'=> 'Windows 10',
|
||||
'windows nt 6.3' => 'Windows 8.1',
|
||||
'windows nt 6.2' => 'Windows 8',
|
||||
'windows nt 6.1' => 'Windows 7',
|
||||
'windows nt 6.0' => 'Windows Vista',
|
||||
@@ -47,6 +49,7 @@ return array(
|
||||
|
||||
'browser' => array(
|
||||
'Opera' => 'Opera',
|
||||
'Edge/12' => 'Edge',
|
||||
'MSIE' => 'Internet Explorer',
|
||||
'Internet Explorer' => 'Internet Explorer',
|
||||
'Shiira' => 'Shiira',
|
||||
|
@@ -52,7 +52,7 @@ You can add conditional statements to make the bootstrap have different values b
|
||||
/**
|
||||
* Set the environment status by the domain.
|
||||
*/
|
||||
if (strpos($_SERVER['HTTP_HOST'], 'kohanaphp.com') !== FALSE)
|
||||
if (strpos($_SERVER['HTTP_HOST'], 'kohanaframework.org') !== FALSE)
|
||||
{
|
||||
// We are live!
|
||||
Kohana::$environment = Kohana::PRODUCTION;
|
||||
@@ -66,7 +66,7 @@ if (strpos($_SERVER['HTTP_HOST'], 'kohanaphp.com') !== FALSE)
|
||||
... [trimmed]
|
||||
*/
|
||||
Kohana::init(array(
|
||||
'base_url' => Kohana::$environment === Kohana::PRODUCTION ? '/' : '/kohanaphp.com/',
|
||||
'base_url' => Kohana::$environment === Kohana::PRODUCTION ? '/' : '/kohanaframework.org/',
|
||||
'caching' => Kohana::$environment === Kohana::PRODUCTION,
|
||||
'profile' => Kohana::$environment !== Kohana::PRODUCTION,
|
||||
'index_file' => FALSE,
|
||||
|
@@ -16,7 +16,7 @@ Every application follows the same flow:
|
||||
* Includes each module's `init.php` file, if it exists.
|
||||
* The `init.php` file can perform additional environment setup, including adding routes.
|
||||
10. [Route::set] is called multiple times to define the [application routes](routing).
|
||||
11. [Request::instance] is called to start processing the request.
|
||||
11. [Request::factory] is called to start processing the request.
|
||||
1. Checks each route that has been set until a match is found.
|
||||
2. Creates the controller instance and passes the request to it.
|
||||
3. Calls the [Controller::before] method.
|
||||
@@ -24,4 +24,4 @@ Every application follows the same flow:
|
||||
5. Calls the [Controller::after] method.
|
||||
* The above 5 steps can be repeated multiple times when using [HMVC sub-requests](requests).
|
||||
3. Application flow returns to index.php
|
||||
12. The main [Request] response is displayed
|
||||
12. The main [Request] response is displayed
|
||||
|
@@ -34,15 +34,27 @@ Kohana::init(array(
|
||||
));
|
||||
~~~
|
||||
|
||||
- Make sure the `application/cache` and `application/logs` directories are writable by the web server.
|
||||
- List your trusted hosts. Open `application/config/url.php` and add regex patterns of the hosts you expect your application to be accessible from.
|
||||
|
||||
[!!] Do not forget to escape your dots (.) as these are regex patterns. These patterns should always fully match, as they are prepended with `^` and appended with `$`.
|
||||
~~~
|
||||
sudo chmod -R a+rwx application/cache
|
||||
sudo chmod -R a+rwx application/logs
|
||||
return array(
|
||||
'trusted_hosts' => array(
|
||||
'example\.org',
|
||||
'.*\.example\.org',
|
||||
),
|
||||
);
|
||||
~~~
|
||||
|
||||
- Define a salt for the `Cookie` class.
|
||||
~~~
|
||||
Cookie::$salt = [really-long-cookie-salt-here]
|
||||
Cookie::$salt = 'some-really-long-cookie-salt-here';
|
||||
~~~
|
||||
|
||||
- Make sure the `application/cache` and `application/logs` directories are writable by the web server.
|
||||
~~~
|
||||
sudo chmod -R a+rwx application/cache
|
||||
sudo chmod -R a+rwx application/logs
|
||||
~~~
|
||||
|
||||
[!!] Make sure to use a unique salt for your application and never to share it. Take a look at the [Cookies](cookies) page for more information on how cookies work in Kohana. If you do not define a `Cookie::$salt` value, Kohana will throw an exception when it encounters any cookie on your domain.
|
||||
|
@@ -20,6 +20,7 @@
|
||||
- [Error Handling](errors)
|
||||
- [Tips & Common Mistakes](tips)
|
||||
- [Upgrading from v3.2](upgrading)
|
||||
- [Upgrading from v3.3.3.1](upgrading-from-3-3-3-1)
|
||||
- Basic Usage
|
||||
- [Debugging](debugging)
|
||||
- [Loading Classes](autoloading)
|
||||
|
@@ -55,7 +55,7 @@ You can also have a controller extend another controller to share common things,
|
||||
|
||||
Every controller has the `$this->request` property which is the [Request] object that called the controller. You can use this to get information about the current request, as well as set the response body via `$this->response->body($ouput)`.
|
||||
|
||||
Here is a partial list of the properties and methods available to `$this->request`. These can also be accessed via `Request::instance()`, but `$this->request` is provided as a shortcut. See the [Request] class for more information on any of these.
|
||||
Here is a partial list of the properties and methods available to `$this->request`. See the [Request] class for more information on any of these.
|
||||
|
||||
Property/method | What it does
|
||||
--- | ---
|
||||
|
@@ -182,6 +182,7 @@ First, we need a [View] that contains the HTML form, which will be placed in `ap
|
||||
<?php foreach ($errors as $message): ?>
|
||||
<li><?php echo $message ?></li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
|
||||
<dl>
|
||||
|
@@ -1,17 +0,0 @@
|
||||
# Tutorials
|
||||
|
||||
## Tutorials in this guide
|
||||
|
||||
## Tutorials written elsewhere
|
||||
|
||||
### Ellisgl's KO3 tutorial on dealtaker.com:
|
||||
|
||||
1. [Install and Basic Usage](http://www.dealtaker.com/blog/2009/11/20/kohana-php-3-0-ko3-tutorial-part-1/)
|
||||
2. [Views](http://www.dealtaker.com/blog/2009/12/07/kohana-php-3-0-ko3-tutorial-part-2/)
|
||||
3. [Controllers](http://www.dealtaker.com/blog/2009/12/30/kohana-php-3-0-ko3-tutorial-part-3/)
|
||||
4. [Models](http://www.dealtaker.com/blog/2010/02/01/kohana-php-3-0-ko3-tutorial-part-4/)
|
||||
5. [Subrequests](http://www.dealtaker.com/blog/2010/02/25/kohana-php-3-0-ko3-tutorial-part-5/)
|
||||
6. [Routes](http://www.dealtaker.com/blog/2010/03/03/kohana-php-3-0-ko3-tutorial-part-6/)
|
||||
7. [Helpers](http://www.dealtaker.com/blog/2010/03/26/kohana-php-3-0-ko3-tutorial-part-7/)
|
||||
8. [Modules](http://www.dealtaker.com/blog/2010/04/30/kohana-php-3-0-ko3-tutorial-part-8/)
|
||||
9. [Vendor Libraries](http://www.dealtaker.com/blog/2010/06/02/kohana-php-3-0-ko3-tutorial-part-9/)
|
@@ -1,7 +0,0 @@
|
||||
Making a template driven site.
|
||||
|
||||
<http://kerkness.ca/wiki/doku.php?id=template-site:create_the_template>
|
||||
|
||||
<http://kerkness.ca/wiki/doku.php?id=template-site:extending_the_template_controller>
|
||||
|
||||
<http://kerkness.ca/wiki/doku.php?id=template-site:basic_page_controller>
|
@@ -1,5 +0,0 @@
|
||||
|
||||
|
||||
<http://kerkness.ca/wiki/doku.php?id=routing:static_pages>
|
||||
|
||||
<http://kerkness.ca/wiki/doku.php?id=routing:multi-language_with_a_route>
|
23
system/guide/kohana/upgrading-from-3-3-3-1.md
Normal file
23
system/guide/kohana/upgrading-from-3-3-3-1.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Upgrading from 3.3.3.1
|
||||
|
||||
Minor version upgrades are usually done in a drop-in fashion. Unfortunately, however, upgrading from 3.3.3.1 to 3.3.4 needs a little configuration. This is because a [security disclosure from HP Fortify](https://github.com/kohana/kohana/issues/74), that unveiled a serious [host header attack](https://github.com/kohana/core/issues/613) vulnerability.
|
||||
|
||||
[!!] You *might* still be able to have a drop-in upgrade, in case you have set the `base_url` in the [Kohana::init] call to an absolute URL. We advise you however that you follow the step below to make your application secure, in case some day you decide to change your `base_url` to a relative URL.
|
||||
|
||||
## Trusted Hosts
|
||||
|
||||
You need to setup a list of trusted hosts. Trusted hosts are hosts that you expect your application to be accessible from.
|
||||
|
||||
Open `application/config/url.php` and add regex patterns of these hosts. An example is given hereunder:
|
||||
|
||||
~~~
|
||||
return array(
|
||||
'trusted_hosts' => array(
|
||||
'example\.org',
|
||||
'.*\.example\.org',
|
||||
),
|
||||
);
|
||||
~~~
|
||||
|
||||
[!!] Do not forget to escape your dots (.) as these are regex patterns. These patterns should always fully match, as they are prepended with `^` and appended with `$`.
|
||||
|
8
system/koharness.php
Normal file
8
system/koharness.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
|
||||
return array(
|
||||
'modules' => array(
|
||||
'unittest' => __DIR__ . '/vendor/kohana/unittest'
|
||||
),
|
||||
'syspath' => __DIR__,
|
||||
);
|
@@ -655,6 +655,22 @@ class Kohana_ArrTest extends Unittest_TestCase
|
||||
'bar' => 'foobar',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'strip_tags',
|
||||
array(
|
||||
array(
|
||||
'foo' => '<p>foobar</p>',
|
||||
'bar' => '<p>foobar</p>',
|
||||
),
|
||||
),
|
||||
array('foo'),
|
||||
array(
|
||||
array(
|
||||
'foo' => 'foobar',
|
||||
'bar' => '<p>foobar</p>',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -11,13 +11,15 @@
|
||||
* @category Tests
|
||||
* @author Kohana Team
|
||||
* @author Jeremy Bush <contractfrombelow@gmail.com>
|
||||
* @copyright (c) 2008-2012 Kohana Team
|
||||
* @author Andrew Coulton <andrew@ingenerator.com>
|
||||
* @copyright (c) 2008-2014 Kohana Team
|
||||
* @license http://kohanaframework.org/license
|
||||
*/
|
||||
class Kohana_CookieTest extends Unittest_TestCase
|
||||
{
|
||||
const UNIX_TIMESTAMP = 1411040141;
|
||||
const COOKIE_EXPIRATION = 60;
|
||||
|
||||
protected $_default_salt = 'AdaoidadnA£ASDNadnaoiwdnawd';
|
||||
/**
|
||||
* Sets up the environment
|
||||
*/
|
||||
@@ -26,152 +28,298 @@ class Kohana_CookieTest extends Unittest_TestCase
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
parent::setUp();
|
||||
Kohana_CookieTest_TestableCookie::$_mock_cookies_set = array();
|
||||
|
||||
Cookie::$salt = $this->_default_salt;
|
||||
$this->setEnvironment(array(
|
||||
'Cookie::$salt' => 'some-random-salt',
|
||||
'HTTP_USER_AGENT' => 'cli'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the environment
|
||||
* Tests that cookies are set with the global path, domain, etc options.
|
||||
*
|
||||
* @covers Cookie::set
|
||||
*/
|
||||
public function test_set_creates_cookie_with_configured_cookie_options()
|
||||
{
|
||||
$this->setEnvironment(array(
|
||||
'Cookie::$path' => '/path',
|
||||
'Cookie::$domain' => 'my.domain',
|
||||
'Cookie::$secure' => TRUE,
|
||||
'Cookie::$httponly' => FALSE,
|
||||
));
|
||||
|
||||
Kohana_CookieTest_TestableCookie::set('cookie', 'value');
|
||||
|
||||
$this->assertSetCookieWith(array(
|
||||
'path' => '/path',
|
||||
'domain' => 'my.domain',
|
||||
'secure' => TRUE,
|
||||
'httponly' => FALSE
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for test_set_calculates_expiry_from_lifetime
|
||||
*
|
||||
* @return array of $lifetime, $expect_expiry
|
||||
*/
|
||||
public function provider_set_calculates_expiry_from_lifetime()
|
||||
{
|
||||
return array(
|
||||
array(NULL, self::COOKIE_EXPIRATION + self::UNIX_TIMESTAMP),
|
||||
array(0, 0),
|
||||
array(10, 10 + self::UNIX_TIMESTAMP),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $expiration
|
||||
* @param int $expect_expiry
|
||||
*
|
||||
* @dataProvider provider_set_calculates_expiry_from_lifetime
|
||||
* @covers Cookie::set
|
||||
*/
|
||||
public function test_set_calculates_expiry_from_lifetime($expiration, $expect_expiry)
|
||||
{
|
||||
$this->setEnvironment(array('Cookie::$expiration' => self::COOKIE_EXPIRATION));
|
||||
Kohana_CookieTest_TestableCookie::set('foo', 'bar', $expiration);
|
||||
$this->assertSetCookieWith(array('expire' => $expect_expiry));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Cookie::get
|
||||
*/
|
||||
public function test_get_returns_default_if_cookie_missing()
|
||||
{
|
||||
unset($_COOKIE['missing_cookie']);
|
||||
$this->assertEquals('default', Cookie::get('missing_cookie', 'default'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Cookie::get
|
||||
*/
|
||||
public function test_get_returns_value_if_cookie_present_and_signed()
|
||||
{
|
||||
Kohana_CookieTest_TestableCookie::set('cookie', 'value');
|
||||
$cookie = Kohana_CookieTest_TestableCookie::$_mock_cookies_set[0];
|
||||
$_COOKIE[$cookie['name']] = $cookie['value'];
|
||||
$this->assertEquals('value', Cookie::get('cookie', 'default'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for test_get_returns_default_without_deleting_if_cookie_unsigned
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_get_returns_default_without_deleting_if_cookie_unsigned()
|
||||
{
|
||||
return array(
|
||||
array('unsalted'),
|
||||
array('un~salted'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that unsigned cookies are not available to the kohana application, but are not affected for other
|
||||
* consumers.
|
||||
*
|
||||
* @param string $unsigned_value
|
||||
*
|
||||
* @dataProvider provider_get_returns_default_without_deleting_if_cookie_unsigned
|
||||
* @covers Cookie::get
|
||||
*/
|
||||
public function test_get_returns_default_without_deleting_if_cookie_unsigned($unsigned_value)
|
||||
{
|
||||
$_COOKIE['cookie'] = $unsigned_value;
|
||||
$this->assertEquals('default', Kohana_CookieTest_TestableCookie::get('cookie', 'default'));
|
||||
$this->assertEquals($unsigned_value, $_COOKIE['cookie'], '$_COOKIE not affected');
|
||||
$this->assertEmpty(Kohana_CookieTest_TestableCookie::$_mock_cookies_set, 'No cookies set or changed');
|
||||
}
|
||||
|
||||
/**
|
||||
* If a cookie looks like a signed cookie but the signature no longer matches, it should be deleted.
|
||||
*
|
||||
* @covers Cookie::get
|
||||
*/
|
||||
public function test_get_returns_default_and_deletes_tampered_signed_cookie()
|
||||
{
|
||||
$_COOKIE['cookie'] = Cookie::salt('cookie', 'value').'~tampered';
|
||||
$this->assertEquals('default', Kohana_CookieTest_TestableCookie::get('cookie', 'default'));
|
||||
$this->assertDeletedCookie('cookie');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Cookie::delete
|
||||
*/
|
||||
public function test_delete_removes_cookie_from_globals_and_expires_cookie()
|
||||
{
|
||||
$_COOKIE['cookie'] = Cookie::salt('cookie', 'value').'~tampered';
|
||||
$this->assertTrue(Kohana_CookieTest_TestableCookie::delete('cookie'));
|
||||
$this->assertDeletedCookie('cookie');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Cookie::delete
|
||||
* @link http://dev.kohanaframework.org/issues/3501
|
||||
* @link http://dev.kohanaframework.org/issues/3020
|
||||
*/
|
||||
public function test_delete_does_not_require_configured_salt()
|
||||
{
|
||||
Cookie::$salt = NULL;
|
||||
$this->assertTrue(Kohana_CookieTest_TestableCookie::delete('cookie'));
|
||||
$this->assertDeletedCookie('cookie');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Cookie::salt
|
||||
* @expectedException Kohana_Exception
|
||||
*/
|
||||
public function test_salt_throws_with_no_configured_salt()
|
||||
{
|
||||
Cookie::$salt = NULL;
|
||||
Cookie::salt('key', 'value');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Cookie::salt
|
||||
*/
|
||||
public function test_salt_creates_same_hash_for_same_values_and_state()
|
||||
{
|
||||
$name = 'cookie';
|
||||
$value = 'value';
|
||||
$this->assertEquals(Cookie::salt($name, $value), Cookie::salt($name, $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for test_salt_creates_different_hash_for_different_data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_salt_creates_different_hash_for_different_data()
|
||||
{
|
||||
return array(
|
||||
array(array('name' => 'foo', 'value' => 'bar', 'salt' => 'our-salt', 'user-agent' => 'Chrome'), array('name' => 'changed')),
|
||||
array(array('name' => 'foo', 'value' => 'bar', 'salt' => 'our-salt', 'user-agent' => 'Chrome'), array('value' => 'changed')),
|
||||
array(array('name' => 'foo', 'value' => 'bar', 'salt' => 'our-salt', 'user-agent' => 'Chrome'), array('salt' => 'changed-salt')),
|
||||
array(array('name' => 'foo', 'value' => 'bar', 'salt' => 'our-salt', 'user-agent' => 'Chrome'), array('user-agent' => 'Firefox')),
|
||||
array(array('name' => 'foo', 'value' => 'bar', 'salt' => 'our-salt', 'user-agent' => 'Chrome'), array('user-agent' => NULL)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $first_args
|
||||
* @param array $changed_args
|
||||
*
|
||||
* @dataProvider provider_salt_creates_different_hash_for_different_data
|
||||
* @covers Cookie::salt
|
||||
*/
|
||||
public function test_salt_creates_different_hash_for_different_data($first_args, $changed_args)
|
||||
{
|
||||
$second_args = array_merge($first_args, $changed_args);
|
||||
$hashes = array();
|
||||
foreach (array($first_args, $second_args) as $args)
|
||||
{
|
||||
Cookie::$salt = $args['salt'];
|
||||
$this->set_or_remove_http_user_agent($args['user-agent']);
|
||||
|
||||
$hashes[] = Cookie::salt($args['name'], $args['value']);
|
||||
}
|
||||
|
||||
$this->assertNotEquals($hashes[0], $hashes[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a cookie was deleted from the global $_COOKIE array, and that a setcookie call was made to remove it
|
||||
* from the client.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function tearDown()
|
||||
protected function assertDeletedCookie($name)
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
Cookie::$salt = NULL;
|
||||
$this->assertArrayNotHasKey($name, $_COOKIE);
|
||||
// To delete the client-side cookie, Cookie::delete should send a new cookie with value NULL and expiry in the past
|
||||
$this->assertSetCookieWith(array(
|
||||
'name' => $name,
|
||||
'value' => NULL,
|
||||
'expire' => -86400,
|
||||
'path' => Cookie::$path,
|
||||
'domain' => Cookie::$domain,
|
||||
'secure' => Cookie::$secure,
|
||||
'httponly' => Cookie::$httponly
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_set()
|
||||
* Verify that there was a single call to setcookie including the provided named arguments
|
||||
*
|
||||
* @return array
|
||||
* @param array $expected
|
||||
*/
|
||||
public function provider_set()
|
||||
// @codingStandardsIgnoreStart
|
||||
protected function assertSetCookieWith($expected)
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
return array(
|
||||
array('foo', 'bar', NULL, TRUE),
|
||||
array('foo', 'bar', 10, TRUE),
|
||||
);
|
||||
$this->assertCount(1, Kohana_CookieTest_TestableCookie::$_mock_cookies_set);
|
||||
$relevant_values = array_intersect_key(Kohana_CookieTest_TestableCookie::$_mock_cookies_set[0], $expected);
|
||||
$this->assertEquals($expected, $relevant_values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests cookie::set()
|
||||
* Configure the $_SERVER[HTTP_USER_AGENT] environment variable for the test
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_set
|
||||
* @covers cookie::set
|
||||
* @param mixed $key key to use
|
||||
* @param mixed $value value to set
|
||||
* @param mixed $exp exp to set
|
||||
* @param boolean $expected Output for cookie::set()
|
||||
* @param string $user_agent
|
||||
*/
|
||||
public function test_set($key, $value, $exp, $expected)
|
||||
protected function set_or_remove_http_user_agent($user_agent)
|
||||
{
|
||||
if (headers_sent()) {
|
||||
$this->markTestSkipped('Cannot test setting cookies as headers have already been sent');
|
||||
}
|
||||
|
||||
$this->assertSame($expected, cookie::set($key, $value, $exp));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_get()
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_get()
|
||||
{
|
||||
// setUp is called after the provider so we need to specify a
|
||||
// salt here in order to use it in the provider
|
||||
Cookie::$salt = $this->_default_salt;
|
||||
|
||||
return array(
|
||||
array('foo', Cookie::salt('foo', 'bar').'~bar', 'bar'),
|
||||
array('bar', Cookie::salt('foo', 'bar').'~bar', NULL),
|
||||
array(NULL, Cookie::salt('foo', 'bar').'~bar', NULL),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests cookie::set()
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_get
|
||||
* @covers cookie::get
|
||||
* @param mixed $key key to use
|
||||
* @param mixed $value value to set
|
||||
* @param boolean $expected Output for cookie::get()
|
||||
*/
|
||||
public function test_get($key, $value, $expected)
|
||||
{
|
||||
if (headers_sent()) {
|
||||
$this->markTestSkipped('Cannot test setting cookies as headers have already been sent');
|
||||
}
|
||||
|
||||
// Force $_COOKIE
|
||||
if ($key !== NULL)
|
||||
if ($user_agent === NULL)
|
||||
{
|
||||
$_COOKIE[$key] = $value;
|
||||
unset($_SERVER['HTTP_USER_AGENT']);
|
||||
}
|
||||
|
||||
$this->assertSame($expected, cookie::get($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_delete()
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_delete()
|
||||
{
|
||||
return array(
|
||||
array('foo', TRUE),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests cookie::delete()
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_delete
|
||||
* @covers cookie::delete
|
||||
* @param mixed $key key to use
|
||||
* @param boolean $expected Output for cookie::delete()
|
||||
*/
|
||||
public function test_delete($key, $expected)
|
||||
{
|
||||
if (headers_sent()) {
|
||||
$this->markTestSkipped('Cannot test setting cookies as headers have already been sent');
|
||||
else
|
||||
{
|
||||
$_SERVER['HTTP_USER_AGENT'] = $user_agent;
|
||||
}
|
||||
|
||||
$this->assertSame($expected, cookie::delete($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_salt()
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_salt()
|
||||
{
|
||||
return array(
|
||||
array('foo', 'bar', 'b5773a6255d1deefc23f9f69bcc40fdc998e5802'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests cookie::salt()
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_salt
|
||||
* @covers cookie::salt
|
||||
* @param mixed $key key to use
|
||||
* @param mixed $value value to salt with
|
||||
* @param boolean $expected Output for cookie::delete()
|
||||
*/
|
||||
public function test_salt($key, $value, $expected)
|
||||
{
|
||||
$this->assertSame($expected, cookie::salt($key, $value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Kohana_CookieTest_TestableCookie wraps the cookie class to mock out the actual setcookie and time calls for
|
||||
* unit testing.
|
||||
*/
|
||||
class Kohana_CookieTest_TestableCookie extends Cookie {
|
||||
|
||||
/**
|
||||
* @var array setcookie calls that were made
|
||||
*/
|
||||
public static $_mock_cookies_set = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static function _setcookie($name, $value, $expire, $path, $domain, $secure, $httponly)
|
||||
{
|
||||
self::$_mock_cookies_set[] = array(
|
||||
'name' => $name,
|
||||
'value' => $value,
|
||||
'expire' => $expire,
|
||||
'path' => $path,
|
||||
'domain' => $domain,
|
||||
'secure' => $secure,
|
||||
'httponly' => $httponly
|
||||
);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
protected static function _time()
|
||||
{
|
||||
return Kohana_CookieTest::UNIX_TIMESTAMP;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -18,6 +18,32 @@
|
||||
*/
|
||||
class Kohana_CoreTest extends Unittest_TestCase
|
||||
{
|
||||
protected $old_modules = array();
|
||||
|
||||
/**
|
||||
* Captures the module list as it was before this test
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function setUp()
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
parent::setUp();
|
||||
$this->old_modules = Kohana::modules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the module list
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function tearDown()
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
Kohana::modules($this->old_modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_sanitize()
|
||||
@@ -107,33 +133,15 @@ class Kohana_CoreTest extends Unittest_TestCase
|
||||
*/
|
||||
public function test_globals_removes_user_def_globals()
|
||||
{
|
||||
// Store the globals
|
||||
$temp_globals = array(
|
||||
'cookie' => $_COOKIE,
|
||||
'get' => $_GET,
|
||||
'files' => $_FILES,
|
||||
'post' => $_POST,
|
||||
'request' => $_REQUEST,
|
||||
'server' => $_SERVER,
|
||||
'session' => $_SESSION,
|
||||
'globals' => $GLOBALS,
|
||||
);
|
||||
|
||||
$GLOBALS = array('hackers' => 'foobar','name' => array('','',''), '_POST' => array());
|
||||
$GLOBALS['hackers'] = 'foobar';
|
||||
$GLOBALS['name'] = array('','','');
|
||||
$GLOBALS['_POST'] = array();
|
||||
|
||||
Kohana::globals();
|
||||
|
||||
$this->assertEquals(array('_POST' => array()), $GLOBALS);
|
||||
|
||||
// Reset the globals for other tests
|
||||
$_COOKIE = $temp_globals['cookie'];
|
||||
$_GET = $temp_globals['get'];
|
||||
$_FILES = $temp_globals['files'];
|
||||
$_POST = $temp_globals['post'];
|
||||
$_REQUEST = $temp_globals['request'];
|
||||
$_SERVER = $temp_globals['server'];
|
||||
$_SESSION = $temp_globals['session'];
|
||||
$GLOBALS = $temp_globals['globals'];
|
||||
$this->assertFalse(isset($GLOBALS['hackers']));
|
||||
$this->assertFalse(isset($GLOBALS['name']));
|
||||
$this->assertTrue(isset($GLOBALS['_POST']));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,35 +183,18 @@ class Kohana_CoreTest extends Unittest_TestCase
|
||||
public function provider_message()
|
||||
{
|
||||
return array(
|
||||
// $value, $result
|
||||
array(':field must not be empty', 'validation', 'not_empty'),
|
||||
array(
|
||||
array('no_message_file', 'anything', 'default', 'default'),
|
||||
array('no_message_file', NULL, 'anything', array()),
|
||||
array('kohana_core_message_tests', 'bottom_only', 'anything', 'inherited bottom message'),
|
||||
array('kohana_core_message_tests', 'cfs_replaced', 'anything', 'overriding cfs_replaced message'),
|
||||
array('kohana_core_message_tests', 'top_only', 'anything', 'top only message'),
|
||||
array('kohana_core_message_tests', 'missing', 'default', 'default'),
|
||||
array('kohana_core_message_tests', NULL, 'anything',
|
||||
array(
|
||||
'alpha' => ':field must contain only letters',
|
||||
'alpha_dash' => ':field must contain only numbers, letters and dashes',
|
||||
'alpha_numeric' => ':field must contain only letters and numbers',
|
||||
'color' => ':field must be a color',
|
||||
'credit_card' => ':field must be a credit card number',
|
||||
'date' => ':field must be a date',
|
||||
'decimal' => ':field must be a decimal with :param2 places',
|
||||
'digit' => ':field must be a digit',
|
||||
'email' => ':field must be a email address',
|
||||
'email_domain' => ':field must contain a valid email domain',
|
||||
'equals' => ':field must equal :param2',
|
||||
'exact_length' => ':field must be exactly :param2 characters long',
|
||||
'in_array' => ':field must be one of the available options',
|
||||
'ip' => ':field must be an ip address',
|
||||
'matches' => ':field must be the same as :param2',
|
||||
'min_length' => ':field must be at least :param2 characters long',
|
||||
'max_length' => ':field must not exceed :param2 characters long',
|
||||
'not_empty' => ':field must not be empty',
|
||||
'numeric' => ':field must be numeric',
|
||||
'phone' => ':field must be a phone number',
|
||||
'range' => ':field must be within the range of :param2 to :param3',
|
||||
'regex' => ':field does not match the required format',
|
||||
'url' => ':field must be a url',
|
||||
),
|
||||
'validation', NULL,
|
||||
'bottom_only' => 'inherited bottom message',
|
||||
'cfs_replaced' => 'overriding cfs_replaced message',
|
||||
'top_only' => 'top only message'
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -213,15 +204,18 @@ class Kohana_CoreTest extends Unittest_TestCase
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_message
|
||||
* @covers Kohana::message
|
||||
* @param boolean $expected Output for Kohana::message
|
||||
* @param boolean $file File to look in for Kohana::message
|
||||
* @param boolean $key Key for Kohana::message
|
||||
* @covers Kohana::message
|
||||
* @param string $file to pass to Kohana::message
|
||||
* @param string $key to pass to Kohana::message
|
||||
* @param string $default to pass to Kohana::message
|
||||
* @param string $expected Output for Kohana::message
|
||||
*/
|
||||
public function test_message($expected, $file, $key)
|
||||
public function test_message($file, $key, $default, $expected)
|
||||
{
|
||||
$this->markTestSkipped('This test is incredibly fragile and needs to be re-done');
|
||||
$this->assertEquals($expected, Kohana::message($file, $key));
|
||||
$test_path = realpath(dirname(__FILE__).'/../test_data/message_tests');
|
||||
Kohana::modules(array('top' => "$test_path/top_module", 'bottom' => "$test_path/bottom_module"));
|
||||
|
||||
$this->assertEquals($expected, Kohana::message($file, $key, $default, $expected));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,7 +308,7 @@ class Kohana_CoreTest extends Unittest_TestCase
|
||||
{
|
||||
return array(
|
||||
array(array(), array()),
|
||||
array(array('unittest' => MODPATH.'unittest'), array('unittest' => $this->dirSeparator(MODPATH.'unittest/'))),
|
||||
array(array('module' => __DIR__), array('module' => $this->dirSeparator(__DIR__.'/'))),
|
||||
);
|
||||
}
|
||||
|
||||
|
747
system/tests/kohana/EncryptTest.php
Normal file
747
system/tests/kohana/EncryptTest.php
Normal file
@@ -0,0 +1,747 @@
|
||||
<?php defined('SYSPATH') OR die('Kohana bootstrap needs to be included before tests run');
|
||||
|
||||
/**
|
||||
* Tests the encrypt class
|
||||
*
|
||||
* @group kohana
|
||||
* @group kohana.core
|
||||
* @group kohana.core.encrypt
|
||||
*
|
||||
* @package Kohana
|
||||
* @category Tests
|
||||
* @author Kohana Team
|
||||
* @author Samuel Demirdjian <sam@enov.ws>
|
||||
* @copyright (c) 2014 Kohana Team
|
||||
* @license http://kohanaframework.org/license
|
||||
*/
|
||||
class Kohana_EncryptTest extends Unittest_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Provider for test_encode
|
||||
* AES Multiblock Message Test (MMT) Sample Vectors - Known Answer Test (KAT)
|
||||
* @link http://csrc.nist.gov/groups/STM/cavp/index.html NIST - Cryptographic Algorithm Validation Program
|
||||
* @link http://csrc.nist.gov/groups/STM/cavp/documents/aes/aesmmt.zip file used CBCMMT128.rsp
|
||||
*
|
||||
* @return array of $mode, $cipher, $key, $iv, $txt_plain, $txt_encoded
|
||||
*/
|
||||
public function provider_encode()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "1f8e4973953f3fb0bd6b16662e9a3c17"),
|
||||
// IV
|
||||
pack("H*", "2fe2b333ceda8f98f4a99b40d2cd34a8"),
|
||||
// txt_plain
|
||||
pack("H*", "45cf12964fc824ab76616ae2f4bf0822"),
|
||||
// txt_encoded
|
||||
pack("H*", "0f61c4d44c5147c03c195ad7e2cc12b2"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "1f8e4973953f3fb0bd6b16662e9a3c17"),
|
||||
// IV
|
||||
pack("H*", "2fe2b333ceda8f98f4a99b40d2cd34a8"),
|
||||
// txt_plain
|
||||
pack("H*", "45cf12964fc824ab76616ae2f4bf0822"),
|
||||
// txt_encoded
|
||||
pack("H*", "0f61c4d44c5147c03c195ad7e2cc12b2"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "0700d603a1c514e46b6191ba430a3a0c"),
|
||||
// IV
|
||||
pack("H*", "aad1583cd91365e3bb2f0c3430d065bb"),
|
||||
// txt_plain
|
||||
pack("H*", "068b25c7bfb1f8bdd4cfc908f69dffc5ddc726a197f0e5f720f730393279be91"),
|
||||
// txt_encoded
|
||||
pack("H*", "c4dc61d9725967a3020104a9738f23868527ce839aab1752fd8bdb95a82c4d00"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "3348aa51e9a45c2dbe33ccc47f96e8de"),
|
||||
// IV
|
||||
pack("H*", "19153c673160df2b1d38c28060e59b96"),
|
||||
// txt_plain
|
||||
pack("H*", "9b7cee827a26575afdbb7c7a329f887238052e3601a7917456ba61251c214763d5e1847a6ad5d54127a399ab07ee3599"),
|
||||
// txt_encoded
|
||||
pack("H*", "d5aed6c9622ec451a15db12819952b6752501cf05cdbf8cda34a457726ded97818e1f127a28d72db5652749f0c6afee5"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "b7f3c9576e12dd0db63e8f8fac2b9a39"),
|
||||
// IV
|
||||
pack("H*", "c80f095d8bb1a060699f7c19974a1aa0"),
|
||||
// txt_plain
|
||||
pack("H*", "9ac19954ce1319b354d3220460f71c1e373f1cd336240881160cfde46ebfed2e791e8d5a1a136ebd1dc469dec00c4187722b841cdabcb22c1be8a14657da200e"),
|
||||
// txt_encoded
|
||||
pack("H*", "19b9609772c63f338608bf6eb52ca10be65097f89c1e0905c42401fd47791ae2c5440b2d473116ca78bd9ff2fb6015cfd316524eae7dcb95ae738ebeae84a467"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "b6f9afbfe5a1562bba1368fc72ac9d9c"),
|
||||
// IV
|
||||
pack("H*", "3f9d5ebe250ee7ce384b0d00ee849322"),
|
||||
// txt_plain
|
||||
pack("H*", "db397ec22718dbffb9c9d13de0efcd4611bf792be4fce0dc5f25d4f577ed8cdbd4eb9208d593dda3d4653954ab64f05676caa3ce9bfa795b08b67ceebc923fdc89a8c431188e9e482d8553982cf304d1"),
|
||||
// txt_encoded
|
||||
pack("H*", "10ea27b19e16b93af169c4a88e06e35c99d8b420980b058e34b4b8f132b13766f72728202b089f428fecdb41c79f8aa0d0ef68f5786481cca29e2126f69bc14160f1ae2187878ba5c49cf3961e1b7ee9"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "bbe7b7ba07124ff1ae7c3416fe8b465e"),
|
||||
// IV
|
||||
pack("H*", "7f65b5ee3630bed6b84202d97fb97a1e"),
|
||||
// txt_plain
|
||||
pack("H*", "2aad0c2c4306568bad7447460fd3dac054346d26feddbc9abd9110914011b4794be2a9a00a519a51a5b5124014f4ed2735480db21b434e99a911bb0b60fe0253763725b628d5739a5117b7ee3aefafc5b4c1bf446467e7bf5f78f31ff7caf187"),
|
||||
// txt_encoded
|
||||
pack("H*", "3b8611bfc4973c5cd8e982b073b33184cd26110159172e44988eb5ff5661a1e16fad67258fcbfee55469267a12dc374893b4e3533d36f5634c3095583596f135aa8cd1138dc898bc5651ee35a92ebf89ab6aeb5366653bc60a70e0074fc11efe"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "89a553730433f7e6d67d16d373bd5360"),
|
||||
// IV
|
||||
pack("H*", "f724558db3433a523f4e51a5bea70497"),
|
||||
// txt_plain
|
||||
pack("H*", "807bc4ea684eedcfdcca30180680b0f1ae2814f35f36d053c5aea6595a386c1442770f4d7297d8b91825ee7237241da8925dd594ccf676aecd46ca2068e8d37a3a0ec8a7d5185a201e663b5ff36ae197110188a23503763b8218826d23ced74b31e9f6e2d7fbfa6cb43420c7807a8625"),
|
||||
// txt_encoded
|
||||
pack("H*", "406af1429a478c3d07e555c5287a60500d37fc39b68e5bbb9bafd6ddb223828561d6171a308d5b1a4551e8a5e7d572918d25c968d3871848d2f16635caa9847f38590b1df58ab5efb985f2c66cfaf86f61b3f9c0afad6c963c49cee9b8bc81a2ddb06c967f325515a4849eec37ce721a"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "c491ca31f91708458e29a925ec558d78"),
|
||||
// IV
|
||||
pack("H*", "9ef934946e5cd0ae97bd58532cb49381"),
|
||||
// txt_plain
|
||||
pack("H*", "cb6a787e0dec56f9a165957f81af336ca6b40785d9e94093c6190e5152649f882e874d79ac5e167bd2a74ce5ae088d2ee854f6539e0a94796b1e1bd4c9fcdbc79acbef4d01eeb89776d18af71ae2a4fc47dd66df6c4dbe1d1850e466549a47b636bcc7c2b3a62495b56bb67b6d455f1eebd9bfefecbca6c7f335cfce9b45cb9d"),
|
||||
// txt_encoded
|
||||
pack("H*", "7b2931f5855f717145e00f152a9f4794359b1ffcb3e55f594e33098b51c23a6c74a06c1d94fded7fd2ae42c7db7acaef5844cb33aeddc6852585ed0020a6699d2cb53809cefd169148ce42292afab063443978306c582c18b9ce0da3d084ce4d3c482cfd8fcf1a85084e89fb88b40a084d5e972466d07666126fb761f84078f2"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "f6e87d71b0104d6eb06a68dc6a71f498"),
|
||||
// IV
|
||||
pack("H*", "1c245f26195b76ebebc2edcac412a2f8"),
|
||||
// txt_plain
|
||||
pack("H*", "f82bef3c73a6f7f80db285726d691db6bf55eec25a859d3ba0e0445f26b9bb3b16a3161ed1866e4dd8f2e5f8ecb4e46d74a7a78c20cdfc7bcc9e479ba7a0caba9438238ad0c01651d5d98de37f03ddce6e6b4bd4ab03cf9e8ed818aedfa1cf963b932067b97d776dce1087196e7e913f7448e38244509f0caf36bd8217e15336d35c149fd4e41707893fdb84014f8729"),
|
||||
// txt_encoded
|
||||
pack("H*", "b09512f3eff9ed0d85890983a73dadbb7c3678d52581be64a8a8fc586f490f2521297a478a0598040ebd0f5509fafb0969f9d9e600eaef33b1b93eed99687b167f89a5065aac439ce46f3b8d22d30865e64e45ef8cd30b6984353a844a11c8cd60dba0e8866b3ee30d24b3fa8a643b328353e06010fa8273c8fd54ef0a2b6930e5520aae5cd5902f9b86a33592ca4365"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "2c14413751c31e2730570ba3361c786b"),
|
||||
// IV
|
||||
pack("H*", "1dbbeb2f19abb448af849796244a19d7"),
|
||||
// txt_plain
|
||||
pack("H*", "40d930f9a05334d9816fe204999c3f82a03f6a0457a8c475c94553d1d116693adc618049f0a769a2eed6a6cb14c0143ec5cccdbc8dec4ce560cfd206225709326d4de7948e54d603d01b12d7fed752fb23f1aa4494fbb00130e9ded4e77e37c079042d828040c325b1a5efd15fc842e44014ca4374bf38f3c3fc3ee327733b0c8aee1abcd055772f18dc04603f7b2c1ea69ff662361f2be0a171bbdcea1e5d3f"),
|
||||
// txt_encoded
|
||||
pack("H*", "6be8a12800455a320538853e0cba31bd2d80ea0c85164a4c5c261ae485417d93effe2ebc0d0a0b51d6ea18633d210cf63c0c4ddbc27607f2e81ed9113191ef86d56f3b99be6c415a4150299fb846ce7160b40b63baf1179d19275a2e83698376d28b92548c68e06e6d994e2c1501ed297014e702cdefee2f656447706009614d801de1caaf73f8b7fa56cf1ba94b631933bbe577624380850f117435a0355b2b"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode
|
||||
* @param string $cipher
|
||||
* @param string $key Encryption key
|
||||
* @param string $iv Initialization vector
|
||||
* @param string $txt_plain Plain text to be encrypted
|
||||
* @param string $txt_encoded Known ecrypted text
|
||||
*
|
||||
* @dataProvider provider_encode
|
||||
* @covers Encrypt::encode
|
||||
*/
|
||||
public function test_encode($mode, $cipher, $key, $iv, $txt_plain, $txt_encoded)
|
||||
{
|
||||
// initialize
|
||||
$e = new Kohana_EncryptTest_IvStubbed($key, $iv, $mode, $cipher);
|
||||
|
||||
// prepare data
|
||||
$expected = base64_encode($iv . $txt_encoded);
|
||||
$actual = $e->encode($txt_plain);
|
||||
|
||||
// assert
|
||||
$this->assertSame($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for test_decode
|
||||
* AES Multiblock Message Test (MMT) Sample Vectors - Known Answer Test (KAT)
|
||||
* @link http://csrc.nist.gov/groups/STM/cavp/index.html NIST - Cryptographic Algorithm Validation Program
|
||||
* @link http://csrc.nist.gov/groups/STM/cavp/documents/aes/aesmmt.zip file used CBCMMT128.rsp
|
||||
*
|
||||
* @return array of $mode, $cipher, $key, $iv, $txt_encoded, $txt_plain
|
||||
*/
|
||||
public function provider_decode()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "6a7082cf8cda13eff48c8158dda206ae"),
|
||||
// IV
|
||||
pack("H*", "bd4172934078c2011cb1f31cffaf486e"),
|
||||
// txt_encoded
|
||||
pack("H*", "f8eb31b31e374e960030cd1cadb0ef0c"),
|
||||
// txt_plain
|
||||
pack("H*", "940bc76d61e2c49dddd5df7f37fcf105"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "625eefa18a4756454e218d8bfed56e36"),
|
||||
// IV
|
||||
pack("H*", "73d9d0e27c2ec568fbc11f6a0998d7c8"),
|
||||
// txt_encoded
|
||||
pack("H*", "5d6fed86f0c4fe59a078d6361a142812514b295dc62ff5d608a42ea37614e6a1"),
|
||||
// txt_plain
|
||||
pack("H*", "360dc1896ce601dfb2a949250067aad96737847a4580ede2654a329b842fe81e"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "fd6e0b954ae2e3b723d6c9fcae6ab09b"),
|
||||
// IV
|
||||
pack("H*", "f08b65c9f4dd950039941da2e8058c4e"),
|
||||
// txt_encoded
|
||||
pack("H*", "e29e3114c8000eb484395b256b1b3267894f290d3999819ff35da03e6463c186c4d7ebb964941f1986a2d69572fcaba8"),
|
||||
// txt_plain
|
||||
pack("H*", "a206385945b21f812a9475f47fddbb7fbdda958a8d14c0dbcdaec36e8b28f1f6ececa1ceae4ce17721d162c1d42a66c1"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "7b1ab9144b0239315cd5eec6c75663bd"),
|
||||
// IV
|
||||
pack("H*", "0b1e74f45c17ff304d99c059ce5cde09"),
|
||||
// txt_encoded
|
||||
pack("H*", "d3f89b71e033070f9d7516a6cb4ea5ef51d6fb63d4f0fea089d0a60e47bbb3c2e10e9ba3b282c7cb79aefe3068ce228377c21a58fe5a0f8883d0dbd3d096beca"),
|
||||
// txt_plain
|
||||
pack("H*", "b968aeb199ad6b3c8e01f26c2edad444538c78bfa36ed68ca76123b8cdce615a01f6112bb80bfc3f17490578fb1f909a52e162637b062db04efee291a1f1af60"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "36466b6bd25ea3857ea42f0cac1919b1"),
|
||||
// IV
|
||||
pack("H*", "7186fb6bdfa98a16189544b228f3bcd3"),
|
||||
// txt_encoded
|
||||
pack("H*", "9ed957bd9bc52bba76f68cfbcde52157a8ca4f71ac050a3d92bdebbfd7c78316b4c9f0ba509fad0235fdafe90056ad115dfdbf08338b2acb1c807a88182dd2a882d1810d4302d598454e34ef2b23687d"),
|
||||
// txt_plain
|
||||
pack("H*", "999983467c47bb1d66d7327ab5c58f61ddb09b93bd2460cb78cbc12b5fa1ea0c5f759ccc5e478697687012ff4673f6e61eecaeda0ccad2d674d3098c7d17f887b62b56f56b03b4d055bf3a4460e83efa"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "89373ee6e28397640d5082eed4123239"),
|
||||
// IV
|
||||
pack("H*", "1a74d7c859672c804b82472f7e6d3c6b"),
|
||||
// txt_encoded
|
||||
pack("H*", "1bcba44ddff503db7c8c2ec4c4eea0e827957740cce125c1e11769842fa97e25f1b89269e6d77923a512a358312f4ba1cd33f2d111280cd83e1ef9e7cf7036d55048d5c273652afa611cc81b4e9dac7b5078b7c4716062e1032ead1e3329588a"),
|
||||
// txt_plain
|
||||
pack("H*", "45efd00daa4cdc8273ef785cae9e944a7664a2391e1e2c449f475acec0124bbc22944331678617408a1702917971f4654310ffb9229bec6173715ae512d37f93aaa6abf009f7e30d65669d1db0366b5bce4c7b00f871014f5753744a1878dc57"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "bab0cceddc0abd63e3f82e9fbff7b8aa"),
|
||||
// IV
|
||||
pack("H*", "68b9140f300490c5c942f66e777eb806"),
|
||||
// txt_encoded
|
||||
pack("H*", "c65b94b1f291fa9f0600f22c3c0432c895ad5d177bcccc9ea44e8ec339c9adf43855b326179d6d81aa36ef59462fd86127e9d81b0f286f93306bf74d4c79e47c1b3d4b74edd3a16290e3c63b742e41f20d66ceee794316bb63d3bd002712a1b136ba6185bd5c1dab81b07db90d2af5e5"),
|
||||
// txt_plain
|
||||
pack("H*", "c5585ff215bbb73ba5393440852fb199436de0d15e55c631f877670aa3eda9f672eb1f876f09544e63558436b8928000db2f02a5ad90f95b05ac4cf49e198e617e7678480fdf0efacc6aae691271e6cdd3541ebf719a1ccaedb24e2f80f92455dd5910cb5086b0960a3942ec182dcbd7"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "9c702898efa44557b29ed283f5bc0293"),
|
||||
// IV
|
||||
pack("H*", "cec6e1b82e8b2a591a9fa5ff1cf5cc51"),
|
||||
// txt_encoded
|
||||
pack("H*", "ba9f646755dacc22911f51d7de2f7e7cb0bc0b75257ea44fe883edb055c7c28ede04c3a0adcb10128ad4517d0093fa16bb0bcd2635e7a0ba92c7609bc8d8568002a7a983473724d256513aa7d51b477aabec1975ab5faf2872a6407e922180eff02f1ef86a4591c8bd3d143da6f0ef0e4806f94ace0d5b0151c99640fccbc843"),
|
||||
// txt_plain
|
||||
pack("H*", "1d1f8d81bdc3e2c7cb057f408e6450000c5aaed3260ff1e87fbb6f324df6887ffd8f78d7e2a04c9ed9deda9d64482d2b002f4a2b78d8b4f691875c8295d4a64b22257ceaf713ed2f4b92530d7ad7151d629acda882b4829577a43990b0948c1149c22fe4273656d1b08833930e8b06709a94579a78fc220f7057bbc1fa9f6563"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "5674636dbdb38f705f0b08c372ef4785"),
|
||||
// IV
|
||||
pack("H*", "3f20ce0509b57420d53b6be4d0b7f0a9"),
|
||||
// txt_encoded
|
||||
pack("H*", "198351f453103face6655666fe90bdbd9630e3733b2d66c013a634e91f2bf015bd2d975d71b26322e44defa32d4e9dce50363557046ece08ba38f258dae5fd3e5049c647476c81e73482e40c171d89f9fea29452caf995733589b0061464fbd5dabe27dc5ea463a3deeb7dcb43664ae6a65c498c143883ab8e83b51e5410b181647602443dc3cfffe86f0205398fa83c"),
|
||||
// txt_plain
|
||||
pack("H*", "6d40fd2f908f48ce19241b6b278b1b1676dffd4a97ce9f8a1574c33bc59237deb536bee376fd6c381e6987700e39283aa111cf1a59f26fae6fb6700bf012646a2ab80239bf5e1632329043aa87d7911978b36523a2bc0bed9a9737ccf7a00baa2f3822b4e9e742e168e7069290705fed2eb63aa044b78f97dd33a8d6b24741ec1fd8c8db79d93b884e762dba0f406961"),
|
||||
),
|
||||
array(
|
||||
// mode
|
||||
MCRYPT_MODE_CBC,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// key
|
||||
pack("H*", "97a1025529b9925e25bbe78770ca2f99"),
|
||||
// IV
|
||||
pack("H*", "d4b4eab92aa9637e87d366384ed6915c"),
|
||||
// txt_encoded
|
||||
pack("H*", "22cdc3306fcd4d31ccd32720cbb61bad28d855670657c48c7b88c31f4fa1f93c01b57da90be63ead67d6a325525e6ed45083e6fb70a53529d1fa0f55653b942af59d78a2660361d63a7290155ac5c43312a25b235dacbbc863faf00940c99624076dfa44068e7c554c9038176953e571751dfc0954d41d113771b06466b1c8d13e0d4cb675ed58d1a619e1540970983781dc11d2dd8525ab5745958d615defda"),
|
||||
// txt_plain
|
||||
pack("H*", "e8b89150d8438bf5b17449d6ed26bd72127e10e4aa57cad85283e8359e089208e84921649f5b60ea21f7867cbc9620560c4c6238db021216db453c9943f1f1a60546173daef2557c3cdd855031b353d4bf176f28439e48785c37d38f270aa4a6faad2baabcb0c0b2d1dd5322937498ce803ba1148440a52e227ddba4872fe4d81d2d76a939d24755adb8a7b8452ceed2d179e1a5848f316f5c016300a390bfa7"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode
|
||||
* @param string $cipher
|
||||
* @param string $key Encryption key
|
||||
* @param string $iv Initialization vector
|
||||
* @param string $txt_encoded ecrypted text
|
||||
* @param string $txt_plain Known plain text that is decripted
|
||||
*
|
||||
* @dataProvider provider_decode
|
||||
* @covers Encrypt::decode
|
||||
*/
|
||||
public function test_decode($mode, $cipher, $key, $iv, $txt_encoded, $txt_plain)
|
||||
{
|
||||
// initialize
|
||||
$e = new Encrypt($key, $mode, $cipher);
|
||||
|
||||
// prepare data
|
||||
$expected = $txt_plain;
|
||||
$actual = $e->decode(base64_encode($iv . $txt_encoded));
|
||||
|
||||
// assert
|
||||
$this->assertSame($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for test_encode_decode, test_consecutive_encode_different_results
|
||||
*
|
||||
* @return array of $key, $mode, $cipher, $txt_plain
|
||||
*/
|
||||
public function provider_encode_decode()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
// key
|
||||
"Some super secret key",
|
||||
// mode
|
||||
MCRYPT_MODE_NOFB,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// txt_plain
|
||||
"The quick brown fox jumps over the lazy dog",
|
||||
),
|
||||
array(
|
||||
// key
|
||||
"De finibus bonorum et malorum",
|
||||
// mode
|
||||
MCRYPT_MODE_NOFB,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// txt_plain
|
||||
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type $key Encryption Key
|
||||
* @param type $mode Encryption Mode
|
||||
* @param type $cipher Encryption Cipher
|
||||
* @param type $txt_plain Plain text to encode and then decode back
|
||||
*
|
||||
* @dataProvider provider_encode_decode
|
||||
* @covers Encrypt::encode
|
||||
* @covers Encrypt::decode
|
||||
*/
|
||||
public function test_encode_decode($key, $mode, $cipher, $txt_plain)
|
||||
{
|
||||
// initialize, encode
|
||||
$e = new Encrypt($key, $mode, $cipher);
|
||||
$txt_encoded = $e->encode($txt_plain);
|
||||
|
||||
// prepare data
|
||||
$expected = $txt_plain;
|
||||
$actual = $e->decode($txt_encoded);
|
||||
|
||||
// assert
|
||||
$this->assertSame($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for test_decode_invalid_data
|
||||
*
|
||||
* @return array of $key, $mode, $cipher, $txt_invalid_encoded
|
||||
*/
|
||||
public function provider_decode_invalid_data()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
// key
|
||||
"Some super secret key",
|
||||
// mode
|
||||
MCRYPT_MODE_NOFB,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// txt_invalid_encoded
|
||||
".:This data is not a valid base 64 string:.",
|
||||
),
|
||||
array(
|
||||
// key
|
||||
"Some super secret key",
|
||||
// mode
|
||||
MCRYPT_MODE_NOFB,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// txt_invalid_encoded
|
||||
base64_encode("too short"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for decode when the string is not valid base64,
|
||||
* or is too short to contain a valid IV
|
||||
*
|
||||
* @param type $key
|
||||
* @param type $mode
|
||||
* @param type $cipher
|
||||
* @param type $txt_encoded
|
||||
*
|
||||
* @dataProvider provider_decode_invalid_data
|
||||
*/
|
||||
public function test_decode_invalid_data($key, $mode, $cipher, $txt_invalid_encoded)
|
||||
{
|
||||
// initialize
|
||||
$e = new Encrypt($key, $mode, $cipher);
|
||||
|
||||
// assert
|
||||
$this->AssertFalse($e->decode($txt_invalid_encoded));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type $key Encryption Key
|
||||
* @param type $mode Encryption Mode
|
||||
* @param type $cipher Encryption Cipher
|
||||
* @param type $txt_plain Plain text to encode and then decode back
|
||||
*
|
||||
* @dataProvider provider_encode_decode
|
||||
* @covers Encrypt::encode
|
||||
*/
|
||||
public function test_consecutive_encode_produce_different_results($key, $mode, $cipher, $txt_plain)
|
||||
{
|
||||
// initialize, encode twice
|
||||
$e = new Encrypt($key, $mode, $cipher);
|
||||
$txt_encoded_first = $e->encode($txt_plain);
|
||||
$txt_encoded_second = $e->encode($txt_plain);
|
||||
|
||||
// assert
|
||||
$this->assertNotEquals($txt_encoded_first, $txt_encoded_second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for test_key_normalization
|
||||
*
|
||||
* @return array of $key, $iv, $mode, $cipher, $txt_plain
|
||||
*/
|
||||
public function provider_key_normalization()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
// key
|
||||
"Some super secret key",
|
||||
// IV
|
||||
pack("H*", "2fe2b333ceda8f98f4a99b40d2cd34a8"),
|
||||
// mode
|
||||
MCRYPT_MODE_NOFB,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// txt_plain
|
||||
"The quick brown fox jumps over the lazy dog",
|
||||
),
|
||||
array(
|
||||
// key
|
||||
"De finibus bonorum et malorum",
|
||||
// IV
|
||||
pack("H*", "2fe2b333ceda8f98f4a99b40d2cd34a8"),
|
||||
// mode
|
||||
MCRYPT_MODE_NOFB,
|
||||
// cypher
|
||||
MCRYPT_RIJNDAEL_128,
|
||||
// txt_plain
|
||||
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if key normalization logic behaves well
|
||||
* Encrypt::_normalize_key was ment for PHP > 5.6.0
|
||||
*
|
||||
* We are testing our key normalization only against lower versions of PHP
|
||||
* (PHP < 5.6.0) to see if it matches the internal key padding those
|
||||
* PHP versions already have
|
||||
*
|
||||
* @param type $key Encryption Key
|
||||
* @param type $mode Encryption Mode
|
||||
* @param type $cipher Encryption Cipher
|
||||
* @param type $txt_plain Plain text to encode and then decode back
|
||||
*
|
||||
* @dataProvider provider_key_normalization
|
||||
* @covers Encrypt::_normalize_key
|
||||
*/
|
||||
public function test_key_normalization($key, $iv, $mode, $cipher, $txt_plain)
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.6.0', '>='))
|
||||
{
|
||||
$this->markTestSkipped('Starting from PHP 5.6.0, mcrypt does not pad encryption keys with null bytes.');
|
||||
}
|
||||
|
||||
// initialize, encode twice
|
||||
$e1 = new Kohana_EncryptTest_IvStubbed($key, $iv, $mode, $cipher);
|
||||
$e2 = new Kohana_EncryptTest_KeyNormalized($key, $iv, $mode, $cipher);
|
||||
|
||||
$txt_encoded_1 = $e1->encode($txt_plain);
|
||||
$txt_encoded_2 = $e2->encode($txt_plain);
|
||||
|
||||
// assert
|
||||
$this->assertSame($txt_encoded_1, $txt_encoded_2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Kohana_Exception
|
||||
* @expectedExceptionMessage No encryption key is defined in the encryption configuration group
|
||||
*/
|
||||
public function test_instance_throw_exception_when_no_key_provided()
|
||||
{
|
||||
Encrypt::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for test_instance_returns_singleton
|
||||
*
|
||||
* @return array of $instance_name, $missing_config
|
||||
*/
|
||||
public function provider_instance_returns_singleton()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'default',
|
||||
array(
|
||||
'key' => 'trwQwVXX96TIJoKxyBHB9AJkwAOHixuV1ENZmIWyanI0j1zNgSVvqywy044Agaj',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'blowfish',
|
||||
array(
|
||||
'key' => '7bZJJkmNrelj5NaKoY6h6rMSRSmeUlJuTeOd5HHka5XknyMX4uGSfeVolTz4IYy',
|
||||
'cipher' => MCRYPT_BLOWFISH,
|
||||
'mode' => MCRYPT_MODE_ECB,
|
||||
)
|
||||
),
|
||||
array(
|
||||
'tripledes',
|
||||
array(
|
||||
'key' => 'a9hcSLRvA3LkFc7EJgxXIKQuz1ec91J7P6WNq1IaxMZp4CTj5m31gZLARLxI1jD',
|
||||
'cipher' => MCRYPT_3DES,
|
||||
'mode' => MCRYPT_MODE_CBC,
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to multiple calls to the instance() method returns same instance
|
||||
* also test if the instances are appropriately configured.
|
||||
*
|
||||
* @param string $instance_name instance name
|
||||
* @param array $config_array array of config variables missing from config
|
||||
*
|
||||
* @dataProvider provider_instance_returns_singleton
|
||||
*/
|
||||
public function test_instance_returns_singleton($instance_name, array $config_array)
|
||||
{
|
||||
// load config
|
||||
$config = Kohana::$config->load('encrypt');
|
||||
// if instance name is NULL the config group should be the default
|
||||
$config_group = $instance_name ? : Encrypt::$default;
|
||||
// if config group does not exists, create
|
||||
if (!array_key_exists($config_group, $config))
|
||||
{
|
||||
$config[$config_group] = array();
|
||||
}
|
||||
// fill in the missing config variables
|
||||
$config[$config_group] = $config[$config_group] + $config_array;
|
||||
|
||||
// call instance twice
|
||||
$e = Encrypt::instance($instance_name);
|
||||
$e2 = Encrypt::instance($instance_name);
|
||||
|
||||
// assert instances
|
||||
$this->assertInstanceOf('Encrypt', $e);
|
||||
$this->assertInstanceOf('Encrypt', $e2);
|
||||
$this->assertSame($e, $e2);
|
||||
|
||||
// test if instances are well configured
|
||||
// prepare expected variables
|
||||
$expected_cipher = $config[$config_group]['cipher'];
|
||||
$expected_mode = $config[$config_group]['mode'];
|
||||
$expected_key_size = mcrypt_get_key_size($expected_cipher, $expected_mode);
|
||||
$expected_key = substr($config[$config_group]['key'], 0, $expected_key_size);
|
||||
|
||||
// assert
|
||||
$this->assertSameProtectedProperty($expected_key, $e, '_key');
|
||||
$this->assertSameProtectedProperty($expected_cipher, $e, '_cipher');
|
||||
$this->assertSameProtectedProperty($expected_mode, $e, '_mode');
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to test for private/protected properties
|
||||
*
|
||||
* @param mixed $expect Expected value
|
||||
* @param mixed $object object that holds the private/protected property
|
||||
* @param string $name the name of the private/protected property
|
||||
*/
|
||||
protected function assertSameProtectedProperty($expect, $object, $name)
|
||||
{
|
||||
$refl = new ReflectionClass($object);
|
||||
$property = $refl->getProperty($name);
|
||||
$property->setAccessible(TRUE);
|
||||
$this->assertSame($expect, $property->getValue($object));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Kohana_EncryptTest_IvStubbed wraps the Encrypt class to mock out
|
||||
* the actual mcrypt_create_iv calls for unit testing.
|
||||
*/
|
||||
class Kohana_EncryptTest_IvStubbed extends Encrypt
|
||||
{
|
||||
|
||||
/**
|
||||
* override constructor to force class use known IVs
|
||||
*
|
||||
* @param string $key encryption key
|
||||
* @param string $iv feed a known IV
|
||||
* @param string $mode mcrypt mode
|
||||
* @param string $cipher mcrypt cipher
|
||||
*/
|
||||
public function __construct($key, $iv, $mode, $cipher)
|
||||
{
|
||||
parent::__construct($key, $mode, $cipher);
|
||||
|
||||
$this->_iv = $iv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake a random initialization vector by returning a known one
|
||||
*
|
||||
* @return string a known IV
|
||||
*/
|
||||
protected function _create_iv()
|
||||
{
|
||||
return isset($this->_iv) ? $this->_iv : FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Kohana_EncryptTest_KeyNormalized wraps the Encrypt class to mock out
|
||||
* the actual mcrypt_create_iv calls for unit testing, as well as to always
|
||||
* normalize keys
|
||||
*/
|
||||
class Kohana_EncryptTest_KeyNormalized extends Kohana_EncryptTest_IvStubbed
|
||||
{
|
||||
|
||||
/**
|
||||
* override constructor to force key normalization
|
||||
*
|
||||
* @param string $key encryption key
|
||||
* @param string $mode mcrypt mode
|
||||
* @param string $cipher mcrypt cipher
|
||||
*/
|
||||
public function __construct($key, $iv, $mode, $cipher)
|
||||
{
|
||||
parent::__construct($key, $iv, $mode, $cipher);
|
||||
|
||||
$this->_key = $this->_normalize_key($this->_key, $this->_cipher, $this->_mode);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -16,6 +16,18 @@
|
||||
*/
|
||||
class Kohana_FeedTest extends Unittest_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the environment
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function setUp()
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
parent::setUp();
|
||||
Kohana::$config->load('url')->set('trusted_hosts', array('localhost'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_parse()
|
||||
*
|
||||
@@ -25,7 +37,8 @@ class Kohana_FeedTest extends Unittest_TestCase
|
||||
{
|
||||
return array(
|
||||
// $source, $expected
|
||||
array('http://dev.kohanaframework.org/projects/kohana3/activity.atom', 15),
|
||||
array(realpath(__DIR__.'/../test_data/feeds/activity.atom'), array('Proposals (Political/Workflow) #4839 (New)', 'Proposals (Political/Workflow) #4782')),
|
||||
array(realpath(__DIR__.'/../test_data/feeds/example.rss20'), array('Example entry')),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,11 +51,15 @@ class Kohana_FeedTest extends Unittest_TestCase
|
||||
* @param string $source URL to test
|
||||
* @param integer $expected Count of items
|
||||
*/
|
||||
public function test_parse($source, $expected)
|
||||
public function test_parse($source, $expected_titles)
|
||||
{
|
||||
$this->markTestSkipped('We don\'t go to the internet for tests.');
|
||||
$titles = array();
|
||||
foreach (Feed::parse($source) as $item)
|
||||
{
|
||||
$titles[] = $item['title'];
|
||||
}
|
||||
|
||||
$this->assertEquals($expected, count(Feed::parse($source)));
|
||||
$this->assertSame($expected_titles, $titles);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @group kohana
|
||||
* @group kohana.core
|
||||
* @group kohana.core.url
|
||||
* @group kohana.core.file
|
||||
*
|
||||
* @package Kohana
|
||||
* @category Tests
|
||||
@@ -25,8 +25,7 @@ class Kohana_FileTest extends Unittest_TestCase
|
||||
{
|
||||
return array(
|
||||
// $value, $result
|
||||
array(Kohana::find_file('classes', 'File')),
|
||||
array(Kohana::find_file('tests', 'test_data/github', 'png')),
|
||||
array(Kohana::find_file('tests', 'test_data/github', 'png'), 'image/png'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,12 +37,10 @@ class Kohana_FileTest extends Unittest_TestCase
|
||||
* @param boolean $input Input for File::mime
|
||||
* @param boolean $expected Output for File::mime
|
||||
*/
|
||||
public function test_mime($input)
|
||||
public function test_mime($input, $expected)
|
||||
{
|
||||
$this->markTestSkipped(
|
||||
'This test doesn\'t do anything useful!'
|
||||
);
|
||||
$this->assertSame(1, preg_match('/^(?:application|audio|image|message|multipart|text|video)\/[a-z.+0-9-]+$/i', File::mime($input)));
|
||||
//@todo: File::mime coverage needs significant improvement or to be dropped for a composer package - it's a "horribly unreliable" method with very little testing
|
||||
$this->assertSame($expected, File::mime($input));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -16,6 +16,18 @@
|
||||
*/
|
||||
class Kohana_HTMLTest extends Unittest_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the environment
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function setUp()
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
parent::setUp();
|
||||
Kohana::$config->load('url')->set('trusted_hosts', array('www\.kohanaframework\.org'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Defaults for this test
|
||||
* @var array
|
||||
@@ -117,6 +129,10 @@ class Kohana_HTMLTest extends Unittest_TestCase
|
||||
'https',
|
||||
FALSE
|
||||
),
|
||||
array(
|
||||
'<script type="text/javascript" src="//google.com/script.js"></script>',
|
||||
'//google.com/script.js',
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
@@ -193,6 +209,13 @@ class Kohana_HTMLTest extends Unittest_TestCase
|
||||
'https',
|
||||
TRUE
|
||||
),
|
||||
array(
|
||||
'<link type="text/css" href="//google.com/style.css" rel="stylesheet" />',
|
||||
'//google.com/style.css',
|
||||
array(),
|
||||
NULL,
|
||||
FALSE
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -223,6 +246,20 @@ class Kohana_HTMLTest extends Unittest_TestCase
|
||||
public function provider_anchor()
|
||||
{
|
||||
return array(
|
||||
// a fragment-only anchor
|
||||
array(
|
||||
'<a href="#go-to-section-kohana">Kohana</a>',
|
||||
array(),
|
||||
'#go-to-section-kohana',
|
||||
'Kohana',
|
||||
),
|
||||
// a query-only anchor
|
||||
array(
|
||||
'<a href="?cat=a">Category A</a>',
|
||||
array(),
|
||||
'?cat=a',
|
||||
'Category A',
|
||||
),
|
||||
array(
|
||||
'<a href="http://kohanaframework.org">Kohana</a>',
|
||||
array(),
|
||||
|
@@ -15,6 +15,33 @@
|
||||
*/
|
||||
class Kohana_HTTPTest extends Unittest_TestCase {
|
||||
|
||||
protected $_inital_request;
|
||||
|
||||
/**
|
||||
* Sets up the environment
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function setUp()
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
parent::setUp();
|
||||
Kohana::$config->load('url')->set('trusted_hosts', array('www\.example\.com'));
|
||||
$this->_initial_request = Request::$initial;
|
||||
Request::$initial = new Request('/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down whatever is setUp
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function tearDown()
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
Request::$initial = $this->_initial_request;
|
||||
parent::tearDown();
|
||||
}
|
||||
// @codingStandardsIgnoreStart
|
||||
|
||||
/**
|
||||
* Defaults for this test
|
||||
* @var array
|
||||
@@ -84,4 +111,70 @@ class Kohana_HTTPTest extends Unittest_TestCase {
|
||||
|
||||
$this->fail('HTTP_Exception_Redirect not thrown');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_request_headers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_request_headers()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'CONTENT_TYPE' => 'text/html; charset=utf-8',
|
||||
'CONTENT_LENGTH' => '3547',
|
||||
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
||||
'HTTP_ACCEPT_ENCODING' => 'gzip, deflate, sdch',
|
||||
'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8,fr;q=0.6,hy;q=0.4',
|
||||
),
|
||||
array(
|
||||
'content-type' => 'text/html; charset=utf-8',
|
||||
'content-length' => '3547',
|
||||
'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
||||
'accept-encoding'=>'gzip, deflate, sdch',
|
||||
'accept-language'=>'en-US,en;q=0.8,fr;q=0.6,hy;q=0.4',
|
||||
)
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'HTTP_WEIRD_HTTP_HEADER' => 'A weird value for a weird header',
|
||||
),
|
||||
array(
|
||||
'weird-http-header' => 'A weird value for a weird header',
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests HTTP::request_headers()
|
||||
*
|
||||
* HTTP::request_headers relies on the $_SERVER superglobal if the function
|
||||
* `apache_request_headers` or the PECL `http` extension are not available.
|
||||
*
|
||||
* The test feeds the $_SERVER superglobal with the test cases' datasets
|
||||
* and then restores the $_SERVER superglobal so that it does not affect
|
||||
* other tests.
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_request_headers
|
||||
* @param array $server_globals globals to feed $_SERVER
|
||||
* @param array $expected_headers Expected, cleaned HTTP headers
|
||||
*/
|
||||
public function test_request_headers(array $server_globals, array $expected_headers)
|
||||
{
|
||||
// save the $_SERVER super-global into temporary local var
|
||||
$tmp_server = $_SERVER;
|
||||
|
||||
$_SERVER = array_replace_recursive($_SERVER, $server_globals);
|
||||
$headers = HTTP::request_headers();
|
||||
|
||||
$actual_headers = array_intersect_key($headers->getArrayCopy(), $expected_headers);
|
||||
|
||||
$this->assertSame($expected_headers, $actual_headers);
|
||||
|
||||
// revert the super-global to its previous state
|
||||
$_SERVER = $tmp_server;
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
parent::setUp();
|
||||
Kohana::$config->load('url')->set('trusted_hosts', array('localhost'));
|
||||
$this->_initial_request = Request::$initial;
|
||||
Request::$initial = new Request('/');
|
||||
}
|
||||
@@ -125,16 +126,15 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
{
|
||||
$route = new Route('(<controller>(/<action>(/<id>)))');
|
||||
|
||||
$uri = 'foo/bar/id';
|
||||
$uri = 'kohana_requesttest_dummy/foobar/some_id';
|
||||
$request = Request::factory($uri, NULL, TRUE, array($route));
|
||||
|
||||
// We need to execute the request before it has matched a route
|
||||
try
|
||||
{
|
||||
$request->execute();
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
$response = $request->execute();
|
||||
$controller = new Controller_Kohana_RequestTest_Dummy($request, $response);
|
||||
|
||||
$this->assertSame(200, $response->status());
|
||||
$this->assertSame($controller->get_expected_response(), $response->body());
|
||||
$this->assertArrayHasKey('id', $request->param());
|
||||
$this->assertArrayNotHasKey('foo', $request->param());
|
||||
$this->assertEquals($request->uri(), $uri);
|
||||
@@ -150,17 +150,16 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
$this->assertArrayNotHasKey('route', $params);
|
||||
|
||||
$route = new Route('(<uri>)', array('uri' => '.+'));
|
||||
$route->defaults(array('controller' => 'foobar', 'action' => 'index'));
|
||||
$request = Request::factory('foobar', NULL, TRUE, array($route));
|
||||
$route->defaults(array('controller' => 'kohana_requesttest_dummy', 'action' => 'foobar'));
|
||||
$request = Request::factory('kohana_requesttest_dummy', NULL, TRUE, array($route));
|
||||
|
||||
// We need to execute the request before it has matched a route
|
||||
try
|
||||
{
|
||||
$request->execute();
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
$response = $request->execute();
|
||||
$controller = new Controller_Kohana_RequestTest_Dummy($request, $response);
|
||||
|
||||
$this->assertSame('foobar', $request->param('uri'));
|
||||
$this->assertSame(200, $response->status());
|
||||
$this->assertSame($controller->get_expected_response(), $response->body());
|
||||
$this->assertSame('kohana_requesttest_dummy', $request->param('uri'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,6 +269,16 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
'http',
|
||||
'http://localhost/kohana/foo'
|
||||
),
|
||||
array(
|
||||
'http://www.google.com',
|
||||
'http',
|
||||
'http://www.google.com'
|
||||
),
|
||||
array(
|
||||
'0',
|
||||
'http',
|
||||
'http://localhost/kohana/0'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -296,7 +305,14 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
'Kohana::$index_file' => FALSE,
|
||||
));
|
||||
|
||||
$this->assertEquals(Request::factory($uri)->url($protocol), $expected);
|
||||
// issue #3967: inject the route so that we don't conflict with the application's default route
|
||||
$route = new Route('(<controller>(/<action>))');
|
||||
$route->defaults(array(
|
||||
'controller' => 'welcome',
|
||||
'action' => 'index',
|
||||
));
|
||||
|
||||
$this->assertEquals(Request::factory($uri, array(), TRUE, array($route))->url($protocol), $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -397,8 +413,15 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
*/
|
||||
public function provider_uri_only_trimed_on_internal()
|
||||
{
|
||||
// issue #3967: inject the route so that we don't conflict with the application's default route
|
||||
$route = new Route('(<controller>(/<action>))');
|
||||
$route->defaults(array(
|
||||
'controller' => 'welcome',
|
||||
'action' => 'index',
|
||||
));
|
||||
|
||||
$old_request = Request::$initial;
|
||||
Request::$initial = new Request(TRUE);
|
||||
Request::$initial = new Request(TRUE, array(), TRUE, array($route));
|
||||
|
||||
$result = array(
|
||||
array(
|
||||
@@ -417,6 +440,14 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
new Request('foo/bar'),
|
||||
'foo/bar'
|
||||
),
|
||||
array(
|
||||
new Request('/0'),
|
||||
'0'
|
||||
),
|
||||
array(
|
||||
new Request('0'),
|
||||
'0'
|
||||
),
|
||||
array(
|
||||
new Request('/'),
|
||||
'/'
|
||||
@@ -505,18 +536,18 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
{
|
||||
$x_powered_by = 'Kohana Unit Test';
|
||||
$content_type = 'application/x-www-form-urlencoded';
|
||||
$request = new Request('foo/bar', array(), TRUE, array());
|
||||
|
||||
return array(
|
||||
array(
|
||||
$request = Request::factory('foo/bar')
|
||||
->headers(array(
|
||||
$request->headers(array(
|
||||
'x-powered-by' => $x_powered_by,
|
||||
'content-type' => $content_type
|
||||
)
|
||||
),
|
||||
array(
|
||||
'x-powered-by' => $x_powered_by,
|
||||
'content-type' => $content_type
|
||||
array(
|
||||
'x-powered-by' => $x_powered_by,
|
||||
'content-type' => $content_type
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -548,7 +579,6 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
Request::factory(),
|
||||
array(
|
||||
'content-type' => 'application/x-www-form-urlencoded',
|
||||
'x-test-header' => 'foo'
|
||||
@@ -556,7 +586,6 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
"Content-Type: application/x-www-form-urlencoded\r\nX-Test-Header: foo\r\n\r\n"
|
||||
),
|
||||
array(
|
||||
Request::factory(),
|
||||
array(
|
||||
'content-type' => 'application/json',
|
||||
'x-powered-by' => 'kohana'
|
||||
@@ -571,13 +600,13 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
*
|
||||
* @dataProvider provider_headers_set
|
||||
*
|
||||
* @param Request request object
|
||||
* @param array header(s) to set to the request object
|
||||
* @param string expected http header
|
||||
* @return void
|
||||
*/
|
||||
public function test_headers_set(Request $request, $headers, $expected)
|
||||
public function test_headers_set($headers, $expected)
|
||||
{
|
||||
$request = new Request(TRUE, array(), TRUE, array());
|
||||
$request->headers($headers);
|
||||
$this->assertSame($expected, (string) $request->headers());
|
||||
}
|
||||
@@ -707,14 +736,83 @@ class Kohana_RequestTest extends Unittest_TestCase
|
||||
$this->assertEquals($client->strict_redirect(), FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests correctness request content-length header after calling render
|
||||
*/
|
||||
public function test_content_length_after_render()
|
||||
{
|
||||
$request = Request::factory('https://example.org/post')
|
||||
->client(new Kohana_RequestTest_Header_Spying_Request_Client_External)
|
||||
->method(Request::POST)
|
||||
->post(array('aaa' => 'bbb'));
|
||||
|
||||
$request->render();
|
||||
|
||||
$request->execute();
|
||||
|
||||
$headers = $request->client()->get_received_request_headers();
|
||||
|
||||
$this->assertEquals(strlen($request->body()), $headers['content-length']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests correctness request content-length header after calling render
|
||||
* and changing post
|
||||
*/
|
||||
public function test_content_length_after_changing_post()
|
||||
{
|
||||
$request = Request::factory('https://example.org/post')
|
||||
->client(new Kohana_RequestTest_Header_Spying_Request_Client_External)
|
||||
->method(Request::POST)
|
||||
->post(array('aaa' => 'bbb'));
|
||||
|
||||
$request->render();
|
||||
|
||||
$request->post(array('one' => 'one', 'two' => 'two', 'three' => 'three'));
|
||||
|
||||
$request->execute();
|
||||
|
||||
$headers = $request->client()->get_received_request_headers();
|
||||
|
||||
$this->assertEquals(strlen($request->body()), $headers['content-length']);
|
||||
}
|
||||
|
||||
} // End Kohana_RequestTest
|
||||
|
||||
/**
|
||||
* A dummy Request_Client_External implementation, that spies on the headers
|
||||
* of the request
|
||||
*/
|
||||
class Kohana_RequestTest_Header_Spying_Request_Client_External extends Request_Client_External
|
||||
{
|
||||
private $headers;
|
||||
|
||||
protected function _send_message(\Request $request, \Response $response)
|
||||
{
|
||||
$this->headers = $request->headers();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function get_received_request_headers()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
}
|
||||
|
||||
class Controller_Kohana_RequestTest_Dummy extends Controller
|
||||
{
|
||||
public function action_index()
|
||||
// hard coded dummy response
|
||||
protected $dummy_response = "this is a dummy response";
|
||||
|
||||
public function action_foobar()
|
||||
{
|
||||
|
||||
$this->response->body($this->dummy_response);
|
||||
}
|
||||
|
||||
public function get_expected_response()
|
||||
{
|
||||
return $this->dummy_response;
|
||||
}
|
||||
|
||||
} // End Kohana_RequestTest
|
||||
|
@@ -171,27 +171,6 @@ class Kohana_ResponseTest extends Unittest_TestCase
|
||||
$this->assertSame(Cookie::$expiration, $cookie['expiration']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the headers are not sent by PHP in CLI mode
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_send_headers_cli()
|
||||
{
|
||||
if (headers_sent())
|
||||
{
|
||||
$this->markTestSkipped('Cannot test this feature as headers have already been sent!');
|
||||
}
|
||||
|
||||
$content_type = 'application/json';
|
||||
$response = new Response;
|
||||
$response->headers('content-type', $content_type)
|
||||
->send_headers();
|
||||
|
||||
$this->assertFalse(headers_sent());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the content type is sent when set
|
||||
*
|
||||
@@ -205,4 +184,4 @@ class Kohana_ResponseTest extends Unittest_TestCase
|
||||
$headers = $response->send_headers()->headers();
|
||||
$this->assertSame($content_type, (string) $headers['content-type']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,8 @@ class Kohana_RouteTest extends Unittest_TestCase
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Kohana::$config->load('url')->set('trusted_hosts', array('kohanaframework\.org'));
|
||||
|
||||
$this->cleanCacheDir();
|
||||
}
|
||||
|
||||
@@ -268,11 +270,7 @@ class Kohana_RouteTest extends Unittest_TestCase
|
||||
$route = new Route($uri);
|
||||
|
||||
// Mock a request class with the $match uri
|
||||
$stub = $this->getMock('Request', array('uri'), array($match));
|
||||
$stub->expects($this->any())
|
||||
->method('uri')
|
||||
// Request::uri() called by Route::matches() will return $match
|
||||
->will($this->returnValue($match));
|
||||
$stub = $this->get_request_mock($match);
|
||||
|
||||
$this->assertSame(FALSE, $route->matches($stub));
|
||||
}
|
||||
@@ -308,11 +306,7 @@ class Kohana_RouteTest extends Unittest_TestCase
|
||||
$route = new Route($uri);
|
||||
|
||||
// Mock a request class with the $m uri
|
||||
$request = $this->getMock('Request', array('uri'), array($m));
|
||||
$request->expects($this->any())
|
||||
->method('uri')
|
||||
// Request::uri() called by Route::matches() will return $m
|
||||
->will($this->returnValue($m));
|
||||
$request = $this->get_request_mock($m);
|
||||
|
||||
$matches = $route->matches($request);
|
||||
|
||||
@@ -381,10 +375,7 @@ class Kohana_RouteTest extends Unittest_TestCase
|
||||
$this->assertSame($defaults, $route->defaults());
|
||||
|
||||
// Mock a request class
|
||||
$request = $this->getMock('Request', array('uri'), array($default_uri));
|
||||
$request->expects($this->any())
|
||||
->method('uri')
|
||||
->will($this->returnValue($default_uri));
|
||||
$request = $this->get_request_mock($default_uri);
|
||||
|
||||
$matches = $route->matches($request);
|
||||
|
||||
@@ -550,28 +541,19 @@ class Kohana_RouteTest extends Unittest_TestCase
|
||||
$route = new Route($uri);
|
||||
|
||||
// Mock a request class that will return empty uri
|
||||
$request = $this->getMock('Request', array('uri'), array(''));
|
||||
$request->expects($this->any())
|
||||
->method('uri')
|
||||
->will($this->returnValue(''));
|
||||
$request = $this->get_request_mock('');
|
||||
|
||||
$this->assertFalse($route->matches($request));
|
||||
|
||||
// Mock a request class that will return route1
|
||||
$request = $this->getMock('Request', array('uri'), array($matches_route1));
|
||||
$request->expects($this->any())
|
||||
->method('uri')
|
||||
->will($this->returnValue($matches_route1));
|
||||
$request = $this->get_request_mock($matches_route1);
|
||||
|
||||
$matches = $route->matches($request);
|
||||
|
||||
$this->assertInternalType('array', $matches);
|
||||
|
||||
// Mock a request class that will return route2 uri
|
||||
$request = $this->getMock('Request', array('uri'), array($matches_route2));
|
||||
$request->expects($this->any())
|
||||
->method('uri')
|
||||
->will($this->returnValue($matches_route2));
|
||||
$request = $this->get_request_mock($matches_route2);
|
||||
|
||||
$matches = $route->matches($request);
|
||||
|
||||
@@ -899,14 +881,78 @@ class Kohana_RouteTest extends Unittest_TestCase
|
||||
$route = new Route($route);
|
||||
|
||||
// Mock a request class
|
||||
$request = $this->getMock('Request', array('uri'), array($uri));
|
||||
$request->expects($this->any())
|
||||
->method('uri')
|
||||
->will($this->returnValue($uri));
|
||||
$request = $this->get_request_mock($uri);
|
||||
|
||||
$params = $route->defaults($defaults)->filter($filter)->matches($request);
|
||||
|
||||
$this->assertSame($expected_params, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_route_uri_encode_parameters
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_route_uri_encode_parameters()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'article',
|
||||
'blog/article/<article_name>',
|
||||
array(
|
||||
'controller' => 'home',
|
||||
'action' => 'index'
|
||||
),
|
||||
'article_name',
|
||||
'Article name with special chars \\ ##',
|
||||
'blog/article/Article%20name%20with%20special%20chars%20\\%20%23%23'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* http://dev.kohanaframework.org/issues/4079
|
||||
*
|
||||
* @test
|
||||
* @covers Route::get
|
||||
* @ticket 4079
|
||||
* @dataProvider provider_route_uri_encode_parameters
|
||||
*/
|
||||
public function test_route_uri_encode_parameters($name, $uri_callback, $defaults, $uri_key, $uri_value, $expected)
|
||||
{
|
||||
Route::set($name, $uri_callback)->defaults($defaults);
|
||||
|
||||
$get_route_uri = Route::get($name)->uri(array($uri_key => $uri_value));
|
||||
|
||||
$this->assertSame($expected, $get_route_uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a mock of the Request class with a mocked `uri` method
|
||||
*
|
||||
* We are also mocking `method` method as it conflicts with newer PHPUnit,
|
||||
* in order to avoid the fatal errors
|
||||
*
|
||||
* @param string $uri
|
||||
* @return type
|
||||
*/
|
||||
public function get_request_mock($uri)
|
||||
{
|
||||
// Mock a request class with the $uri uri
|
||||
$request = $this->getMock('Request', array('uri', 'method'), array($uri));
|
||||
|
||||
// mock `uri` method
|
||||
$request->expects($this->any())
|
||||
->method('uri')
|
||||
// Request::uri() called by Route::matches() in the tests will return $uri
|
||||
->will($this->returnValue($uri));
|
||||
|
||||
// also mock `method` method
|
||||
$request->expects($this->any())
|
||||
->method('method')
|
||||
->withAnyParameters();
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -67,17 +67,6 @@ class Kohana_SecurityTest extends Unittest_TestCase
|
||||
*/
|
||||
public function provider_csrf_token()
|
||||
{
|
||||
// Unfortunately this data provider has to use the session in order to
|
||||
// generate its data. If headers have already been sent then this method
|
||||
// throws an error, even if the test is does not run. If we return an
|
||||
// empty array then this also causes an error, so the only way to get
|
||||
// around it is to return an array of misc data and have the test skip
|
||||
// if headers have been sent. It's annoying this hack has to be
|
||||
// implemented, but the security code isn't exactly brilliantly
|
||||
// implemented. Ideally we'd be able to inject a session instance
|
||||
if (headers_sent())
|
||||
return array(array('', '', 0));
|
||||
|
||||
$array = array();
|
||||
for ($i = 0; $i <= 4; $i++)
|
||||
{
|
||||
@@ -96,10 +85,7 @@ class Kohana_SecurityTest extends Unittest_TestCase
|
||||
*/
|
||||
public function test_csrf_token($expected, $input, $iteration)
|
||||
{
|
||||
if (headers_sent()) {
|
||||
$this->markTestSkipped('Headers have already been sent, session not available');
|
||||
}
|
||||
|
||||
//@todo: the Security::token tests need to be reviewed to check how much of the logic they're actually covering
|
||||
Security::$token_name = 'token_'.$iteration;
|
||||
$this->assertSame(TRUE, $input);
|
||||
$this->assertSame($expected, Security::token(FALSE));
|
||||
|
@@ -95,20 +95,14 @@ class Kohana_SessionTest extends Unittest_TestCase
|
||||
*/
|
||||
public function test_constructor_loads_session_with_session_id()
|
||||
{
|
||||
$this->markTestIncomplete(
|
||||
'Need to work out why constructor is not being called'
|
||||
);
|
||||
|
||||
$config = array();
|
||||
$session_id = 'lolums';
|
||||
|
||||
// Don't auto-call constructor, we need to setup the mock first
|
||||
$session = $this->getMockForAbstractClass(
|
||||
'Session',
|
||||
array(),
|
||||
'',
|
||||
FALSE
|
||||
);
|
||||
$session = $this->getMockBuilder('Session')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('read'))
|
||||
->getMockForAbstractClass();
|
||||
|
||||
$session
|
||||
->expects($this->once())
|
||||
|
@@ -196,6 +196,30 @@ class Kohana_TextTest extends Unittest_TestCase
|
||||
$this->assertSame('yes', Text::alternate($val_a, $val_b, $val_c));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_ucfirst
|
||||
*
|
||||
* @return array Test data
|
||||
*/
|
||||
public function provider_ucfirst()
|
||||
{
|
||||
return array(
|
||||
array('Content-Type', 'content-type', '-'),
|
||||
array('Բարեւ|Ձեզ', 'բարեւ|ձեզ', '|'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Covers Text::ucfirst()
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_ucfirst
|
||||
*/
|
||||
public function test_ucfirst($expected, $string, $delimiter)
|
||||
{
|
||||
$this->assertSame($expected, Text::ucfirst($string, $delimiter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_reducde_slashes()
|
||||
*
|
||||
@@ -386,9 +410,90 @@ class Kohana_TextTest extends Unittest_TestCase
|
||||
{
|
||||
return array
|
||||
(
|
||||
array('No gain, no pain', 'No gain, no pain'),
|
||||
array("spaces?what'rethey?", "spaces?what'rethey?"),
|
||||
array('', ''),
|
||||
// A very simple widont test
|
||||
array(
|
||||
'A very simple test',
|
||||
'A very simple test',
|
||||
),
|
||||
// Single word items shouldn't be changed
|
||||
array(
|
||||
'Test',
|
||||
'Test',
|
||||
),
|
||||
// Single word after single space shouldn't be changed either
|
||||
array(
|
||||
' Test',
|
||||
' Test',
|
||||
),
|
||||
// Single word with HTML all around
|
||||
array(
|
||||
'<ul><li><p>Test</p></li><ul>',
|
||||
'<ul><li><p>Test</p></li><ul>',
|
||||
),
|
||||
// Single word after single space with HTML all around
|
||||
array(
|
||||
'<ul><li><p> Test</p></li><ul>',
|
||||
'<ul><li><p> Test</p></li><ul>',
|
||||
),
|
||||
// Widont with more than one paragraph
|
||||
array(
|
||||
'<p>In a couple of paragraphs</p><p>paragraph two</p>',
|
||||
'<p>In a couple of paragraphs</p><p>paragraph two</p>',
|
||||
),
|
||||
// a link inside a heading
|
||||
array(
|
||||
'<h1><a href="#">In a link inside a heading </a></h1>',
|
||||
'<h1><a href="#">In a link inside a heading </a></h1>',
|
||||
),
|
||||
// a link followed by text
|
||||
array(
|
||||
'<h1><a href="#">In a link</a> followed by other text</h1>',
|
||||
'<h1><a href="#">In a link</a> followed by other text</h1>',
|
||||
),
|
||||
// empty html, with no text inside
|
||||
array(
|
||||
'<h1><a href="#"></a></h1>',
|
||||
'<h1><a href="#"></a></h1>',
|
||||
),
|
||||
// apparently, we don't love DIVs
|
||||
array(
|
||||
'<div>Divs get no love!</div>',
|
||||
'<div>Divs get no love!</div>',
|
||||
),
|
||||
// we don't love PREs, either
|
||||
array(
|
||||
'<pre>Neither do PREs</pre>',
|
||||
'<pre>Neither do PREs</pre>',
|
||||
),
|
||||
// but we love DIVs with paragraphs
|
||||
array(
|
||||
'<div><p>But divs with paragraphs do!</p></div>',
|
||||
'<div><p>But divs with paragraphs do!</p></div>',
|
||||
),
|
||||
array(
|
||||
'No gain, no pain',
|
||||
'No gain, no pain',
|
||||
),
|
||||
array(
|
||||
"spaces?what'rethey?",
|
||||
"spaces?what'rethey?",
|
||||
),
|
||||
/*
|
||||
* // @issue 3499, with HTML at the end
|
||||
* array(
|
||||
* 'with HTML at the end <strong>Kohana</strong>',
|
||||
* 'with HTML at the end <strong>Kohana</strong>',
|
||||
* ),
|
||||
* // @issue 3499, with HTML with attributes at the end
|
||||
* array(
|
||||
* 'with HTML at the end: <a href="#" title="Kohana">Kohana</a>',
|
||||
* 'with HTML at the end: <a href="#" title="Kohana">Kohana</a>',
|
||||
* ),
|
||||
*/
|
||||
array(
|
||||
'',
|
||||
'',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -639,4 +744,111 @@ class Kohana_TextTest extends Unittest_TestCase
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function provider_user_agents()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
|
||||
array(
|
||||
'browser' => 'Chrome',
|
||||
'version' => '37.0.2049.0',
|
||||
'platform' => "Windows 8.1"
|
||||
)
|
||||
),
|
||||
array(
|
||||
"Mozilla/5.0 (Macintosh; U; Mac OS X 10_6_1; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/ Safari/530.5",
|
||||
array(
|
||||
'browser' => 'Chrome',
|
||||
'version' => '530.5',
|
||||
'platform' => "Mac OS X"
|
||||
)
|
||||
),
|
||||
array(
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2",
|
||||
array(
|
||||
'browser' => 'Safari',
|
||||
'version' => '534.57.2',
|
||||
'platform' => 'Mac OS X'
|
||||
)
|
||||
),
|
||||
array(
|
||||
"Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1",
|
||||
array(
|
||||
'browser' => 'Lynx',
|
||||
'version' => '2.8.8dev.3',
|
||||
'platform' => false
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Text::user_agent
|
||||
*
|
||||
* @dataProvider provider_user_agents
|
||||
* @group current
|
||||
*/
|
||||
public function test_user_agent_returns_correct_browser($userAgent, $expectedData)
|
||||
{
|
||||
$browser = Text::user_agent($userAgent, 'browser');
|
||||
|
||||
$this->assertEquals($expectedData['browser'], $browser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Text::user_agent
|
||||
*
|
||||
* @dataProvider provider_user_agents
|
||||
* @test
|
||||
*/
|
||||
public function test_user_agent_returns_correct_version($userAgent, $expectedData)
|
||||
{
|
||||
$version = Text::user_agent($userAgent, 'version');
|
||||
|
||||
$this->assertEquals($expectedData['version'], $version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Text::user_agent
|
||||
* @test
|
||||
*/
|
||||
public function test_user_agent_recognizes_robots()
|
||||
{
|
||||
$bot = Text::user_agent('Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)', 'robot');
|
||||
|
||||
$this->assertEquals('Googlebot', $bot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Text::user_agent
|
||||
*
|
||||
* @dataProvider provider_user_agents
|
||||
* @test
|
||||
*/
|
||||
public function test_user_agent_returns_correct_platform($userAgent, $expectedData)
|
||||
{
|
||||
$platform = Text::user_agent($userAgent, 'platform');
|
||||
|
||||
$this->assertEquals($expectedData['platform'], $platform);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests Text::user_agent
|
||||
* @test
|
||||
*/
|
||||
public function test_user_agent_accepts_array()
|
||||
{
|
||||
$agent_info = Text::user_agent(
|
||||
'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 '.
|
||||
'(KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36',
|
||||
array('browser', 'version', 'platform'));
|
||||
|
||||
$this->assertArrayHasKey('browser', $agent_info);
|
||||
$this->assertArrayHasKey('version', $agent_info);
|
||||
$this->assertArrayHasKey('platform', $agent_info);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,6 +16,18 @@
|
||||
*/
|
||||
class Kohana_URLTest extends Unittest_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the environment
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function setUp()
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
parent::setUp();
|
||||
Kohana::$config->load('url')->set('trusted_hosts', array('example\.com', 'example\.org'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default values for the environment, see setEnvironment
|
||||
* @var array
|
||||
@@ -276,4 +288,95 @@ class Kohana_URLTest extends Unittest_TestCase
|
||||
URL::query($params, $use_get)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for URL::is_trusted_host()
|
||||
* @return array
|
||||
*/
|
||||
public function provider_is_trusted_host()
|
||||
{
|
||||
return array(
|
||||
// data set #0
|
||||
array(
|
||||
'givenhost',
|
||||
array(
|
||||
'list-of-trusted-hosts',
|
||||
),
|
||||
FALSE
|
||||
),
|
||||
// data set #1
|
||||
array(
|
||||
'givenhost',
|
||||
array(
|
||||
'givenhost',
|
||||
'example\.com',
|
||||
),
|
||||
TRUE
|
||||
),
|
||||
// data set #2
|
||||
array(
|
||||
'www.kohanaframework.org',
|
||||
array(
|
||||
'.*\.kohanaframework\.org',
|
||||
),
|
||||
TRUE
|
||||
),
|
||||
// data set #3
|
||||
array(
|
||||
'kohanaframework.org',
|
||||
array(
|
||||
'.*\.kohanaframework\.org',
|
||||
),
|
||||
FALSE // because we are requesting a subdomain
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests URL::is_trusted_hosts()
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_is_trusted_host
|
||||
* @param string $host the given host
|
||||
* @param array $trusted_hosts list of trusted hosts
|
||||
* @param boolean $expected TRUE if host is trusted, FALSE otherwise
|
||||
*/
|
||||
public function test_is_trusted_host($host, $trusted_hosts, $expected)
|
||||
{
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
URL::is_trusted_host($host, $trusted_hosts)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if invalid host throws "Invalid host" exception
|
||||
*
|
||||
* @test
|
||||
* @expectedException Kohana_Exception
|
||||
* @expectedExceptionMessage Invalid host <invalid>
|
||||
*/
|
||||
public function test_if_invalid_host_throws_exception()
|
||||
{
|
||||
// set the global HTTP_HOST to <invalid>
|
||||
$_SERVER['HTTP_HOST'] = '<invalid>';
|
||||
// trigger exception
|
||||
URL::base('https');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if untrusted host throws "Untrusted host" exception
|
||||
*
|
||||
* @test
|
||||
* @expectedException Kohana_Exception
|
||||
* @expectedExceptionMessage Untrusted host untrusted.com
|
||||
*/
|
||||
public function test_if_untrusted_host_throws_exception()
|
||||
{
|
||||
// set the global HTTP_HOST to a valid but untrusted host
|
||||
$_SERVER['HTTP_HOST'] = 'untrusted.com';
|
||||
// trigger exception
|
||||
URL::base('https');
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -673,4 +673,48 @@ class Kohana_ValidationTest extends Unittest_TestCase
|
||||
$this->assertSame($errors, $validation->errors('validation'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for test_rule_label_regex
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_rule_label_regex()
|
||||
{
|
||||
// $data, $field, $rules, $expected
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'email1' => '',
|
||||
),
|
||||
'email1',
|
||||
array(
|
||||
array(
|
||||
'not_empty'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'email1' => 'email1 must not be empty'
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* http://dev.kohanaframework.org/issues/4201
|
||||
*
|
||||
* @test
|
||||
* @ticket 4201
|
||||
* @covers Validation::rule
|
||||
* @dataProvider provider_rule_label_regex
|
||||
*/
|
||||
public function test_rule_label_regex($data, $field, $rules, $expected)
|
||||
{
|
||||
$validation = Validation::factory($data)->rules($field, $rules);
|
||||
|
||||
$validation->check();
|
||||
|
||||
$errors = $validation->errors('');
|
||||
|
||||
$this->assertSame($errors, $expected);
|
||||
}
|
||||
}
|
||||
|
@@ -60,9 +60,23 @@ class Kohana_ViewTest extends Unittest_TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider to test_set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_set()
|
||||
{
|
||||
return array(
|
||||
array('foo', 'bar', 'foo', 'bar'),
|
||||
array(array('foo' => 'bar'), NULL, 'foo', 'bar'),
|
||||
array(new ArrayIterator(array('foo' => 'bar')), NULL, 'foo', 'bar'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we can instantiate a view file
|
||||
*
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_instantiate
|
||||
*
|
||||
@@ -80,4 +94,33 @@ class Kohana_ViewTest extends Unittest_TestCase
|
||||
$this->assertSame(TRUE, $expects_exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we can set using string, array or Traversable object
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_set
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function test_set($data_key, $value, $test_key, $expected)
|
||||
{
|
||||
$view = View::factory()->set($data_key, $value);
|
||||
$this->assertSame($expected, $view->$test_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we can set global using string, array or Traversable object
|
||||
*
|
||||
* @test
|
||||
* @dataProvider provider_set
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function test_set_global($data_key, $value, $test_key, $expected)
|
||||
{
|
||||
$view = View::factory();
|
||||
$view::set_global($data_key, $value);
|
||||
$this->assertSame($expected, $view->$test_key);
|
||||
}
|
||||
}
|
||||
|
@@ -17,6 +17,30 @@
|
||||
*/
|
||||
class Kohana_Request_Client_InternalTest extends Unittest_TestCase
|
||||
{
|
||||
|
||||
protected $_log_object;
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
public function setUp()
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// temporarily save $log object
|
||||
$this->_log_object = Kohana::$log;
|
||||
Kohana::$log = NULL;
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
public function tearDown()
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
// re-assign log object
|
||||
Kohana::$log = $this->_log_object;
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function provider_response_failure_status()
|
||||
{
|
||||
return array(
|
||||
@@ -37,7 +61,7 @@ class Kohana_Request_Client_InternalTest extends Unittest_TestCase
|
||||
public function test_response_failure_status($directory, $controller, $action, $uri, $expected)
|
||||
{
|
||||
// Mock for request object
|
||||
$request = $this->getMock('Request', array('directory', 'controller', 'action', 'uri', 'response'), array($uri));
|
||||
$request = $this->getMock('Request', array('directory', 'controller', 'action', 'uri', 'response', 'method'), array($uri));
|
||||
|
||||
$request->expects($this->any())
|
||||
->method('directory')
|
||||
@@ -59,10 +83,15 @@ class Kohana_Request_Client_InternalTest extends Unittest_TestCase
|
||||
->method('response')
|
||||
->will($this->returnValue($this->getMock('Response')));
|
||||
|
||||
// mock `method` method to avoid fatals in newer versions of PHPUnit
|
||||
$request->expects($this->any())
|
||||
->method('method')
|
||||
->withAnyParameters();
|
||||
|
||||
$internal_client = new Request_Client_Internal;
|
||||
|
||||
$response = $internal_client->execute($request);
|
||||
|
||||
$this->assertSame($expected, $response->status());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
58
system/tests/test_data/feeds/activity.atom
Normal file
58
system/tests/test_data/feeds/activity.atom
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>Kohana v3.x: Activity</title>
|
||||
<link href="http://dev.kohanaframework.org/projects/kohana3/activity.atom" rel="self"/>
|
||||
<link href="http://dev.kohanaframework.org/projects/kohana3/activity" rel="alternate"/>
|
||||
<id>http://dev.kohanaframework.org/</id>
|
||||
<icon>http://dev.kohanaframework.org/favicon.ico?1392677580</icon>
|
||||
<updated>2014-08-28T01:52:12Z</updated>
|
||||
<author>
|
||||
<name>Kohana Development</name>
|
||||
</author>
|
||||
<generator uri="http://www.redmine.org/">
|
||||
Redmine </generator>
|
||||
<entry>
|
||||
<title>Proposals (Political/Workflow) #4839 (New)</title>
|
||||
<link href="http://dev.kohanaframework.org/issues/4839" rel="alternate"/>
|
||||
<id>http://dev.kohanaframework.org/issues/4839</id>
|
||||
<updated>2014-08-28T01:52:12Z</updated>
|
||||
<author>
|
||||
<name>Guillaume Poirier-Morency</name>
|
||||
<email>guillaumepoiriermorency@gmail.com</email>
|
||||
</author>
|
||||
<content type="html">
|
||||
<p>I have a prototype here <a class="external" href="https://github.com/arteymix/kohana-makefile">https://github.com/arteymix/kohana-makefile</a></p>
|
||||
|
||||
|
||||
<p>The tool is very useful for settings permissions and running tests.</p>
|
||||
|
||||
|
||||
<p>I think we should consider having a good make tool in the sample application for the 3.4.*.</p> </content>
|
||||
</entry>
|
||||
<entry>
|
||||
<title>Proposals (Political/Workflow) #4782</title>
|
||||
<link href="http://dev.kohanaframework.org/issues/4782#change-17279" rel="alternate"/>
|
||||
<id>http://dev.kohanaframework.org/issues/4782#change-17279</id>
|
||||
<updated>2014-08-28T01:44:26Z</updated>
|
||||
<author>
|
||||
<name>Guillaume Poirier-Morency</name>
|
||||
<email>guillaumepoiriermorency@gmail.com</email>
|
||||
</author>
|
||||
<content type="html">
|
||||
<p>Moving to composer is a nice idea. This will allow Kohana modules to define a wide range of dependencies.</p>
|
||||
|
||||
|
||||
<p>Although, I think that modules designed specifically for Kohana should end in modules and external libraries in application/vendor. This makes a clear dinsinction between what gets autoloaded by the CFS and what gets loaded by composer. Technically, we add "vendor-dir": "application/vendor" in "config" in composer.json.</p>
|
||||
|
||||
|
||||
<p>Then, only add a line after the modules loading in bootstrap.php</p>
|
||||
|
||||
|
||||
<pre>
|
||||
// Autoloading composer packages
|
||||
require Kohana::find_file('vendor', 'autoload');
|
||||
</pre>
|
||||
|
||||
<p>This is pretty much what I do right now. This doesn't break anything and allow a full access to composer.</p> </content>
|
||||
</entry>
|
||||
</feed>
|
20
system/tests/test_data/feeds/example.rss20
Normal file
20
system/tests/test_data/feeds/example.rss20
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<rss version="2.0">
|
||||
<channel>
|
||||
<title>RSS Title</title>
|
||||
<description>This is an example of an RSS feed</description>
|
||||
<link>http://www.example.com/main.html</link>
|
||||
<lastBuildDate>Mon, 06 Sep 2010 00:01:00 +0000 </lastBuildDate>
|
||||
<pubDate>Sun, 06 Sep 2009 16:20:00 +0000</pubDate>
|
||||
<ttl>1800</ttl>
|
||||
|
||||
<item>
|
||||
<title>Example entry</title>
|
||||
<description>Here is some text containing an interesting description.</description>
|
||||
<link>http://www.example.com/blog/post/1</link>
|
||||
<guid>7bd204c6-1655-4c27-aeee-53f933c5395f</guid>
|
||||
<pubDate>Sun, 06 Sep 2009 16:20:00 +0000</pubDate>
|
||||
</item>
|
||||
|
||||
</channel>
|
||||
</rss>
|
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
// See the Kohana_CoreTest tests for Kohana::message
|
||||
return array(
|
||||
'bottom_only' => 'inherited bottom message',
|
||||
'cfs_replaced' => 'inherited cfs_replaced message',
|
||||
);
|
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
// See the Kohana_CoreTest tests for Kohana::message
|
||||
return array(
|
||||
'top_only' => 'top only message',
|
||||
'cfs_replaced' => 'overriding cfs_replaced message',
|
||||
);
|
@@ -15,9 +15,10 @@ function _ucwords($str)
|
||||
|
||||
// [\x0c\x09\x0b\x0a\x0d\x20] matches form feeds, horizontal tabs, vertical tabs, linefeeds and carriage returns.
|
||||
// This corresponds to the definition of a 'word' defined at http://php.net/ucwords
|
||||
return preg_replace(
|
||||
'/(?<=^|[\x0c\x09\x0b\x0a\x0d\x20])[^\x0c\x09\x0b\x0a\x0d\x20]/ue',
|
||||
'UTF8::strtoupper(\'$0\')',
|
||||
$str
|
||||
);
|
||||
return preg_replace_callback(
|
||||
'/(?<=^|[\x0c\x09\x0b\x0a\x0d\x20])[^\x0c\x09\x0b\x0a\x0d\x20]/u',
|
||||
function($matches){
|
||||
return UTF8::strtoupper($matches[0]);
|
||||
},
|
||||
$str);
|
||||
}
|
||||
|
@@ -49,7 +49,7 @@ function koggle(elem)
|
||||
}
|
||||
</script>
|
||||
<div id="kohana_error">
|
||||
<h1><span class="type"><?php echo $class ?> [ <?php echo $code ?> ]:</span> <span class="message"><?php echo htmlspecialchars( (string) $message, ENT_QUOTES, Kohana::$charset, TRUE); ?></span></h1>
|
||||
<h1><span class="type"><?php echo $class ?> [ <?php echo $code ?> ]:</span> <span class="message"><?php echo htmlspecialchars( (string) $message, ENT_QUOTES | ENT_IGNORE, Kohana::$charset, TRUE); ?></span></h1>
|
||||
<div id="<?php echo $error_id ?>" class="content">
|
||||
<p><span class="file"><?php echo Debug::path($file) ?> [ <?php echo $line ?> ]</span></p>
|
||||
<?php echo Debug::source($file, $line) ?>
|
||||
|
@@ -35,7 +35,7 @@ $application_cols = array('min', 'max', 'average', 'current');
|
||||
<div>
|
||||
<div class="value"><?php echo number_format($stats[$key]['time'], 6) ?> <abbr title="seconds">s</abbr></div>
|
||||
<?php if ($key === 'total'): ?>
|
||||
<div class="graph" style="left: <?php echo max(0, 100 - $stats[$key]['time'] / $group_stats[$group]['max']['time'] * 100) ?>%"></div>
|
||||
<div class="graph" style="left: <?php echo $group_stats[$group]['max']['time'] ? max(0, 100 - $stats[$key]['time'] / $group_stats[$group]['max']['time'] * 100) : '0' ?>%"></div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
</td>
|
||||
@@ -47,7 +47,7 @@ $application_cols = array('min', 'max', 'average', 'current');
|
||||
<div>
|
||||
<div class="value"><?php echo number_format($stats[$key]['memory'] / 1024, 4) ?> <abbr title="kilobyte">kB</abbr></div>
|
||||
<?php if ($key === 'total'): ?>
|
||||
<div class="graph" style="left: <?php echo max(0, 100 - $stats[$key]['memory'] / $group_stats[$group]['max']['memory'] * 100) ?>%"></div>
|
||||
<div class="graph" style="left: <?php echo $group_stats[$group]['max']['memory'] ? max(0, 100 - $stats[$key]['memory'] / $group_stats[$group]['max']['memory'] * 100) : '0' ?>%"></div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
</td>
|
||||
@@ -71,4 +71,4 @@ $application_cols = array('min', 'max', 'average', 'current');
|
||||
<?php endforeach ?>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user