summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--application/config/config.php22
-rw-r--r--system/core/CodeIgniter.php19
-rw-r--r--system/core/compat/password.php9
-rw-r--r--system/core/compat/standard.php (renamed from system/core/compat/array.php)143
-rw-r--r--system/libraries/Encryption.php78
-rw-r--r--tests/Bootstrap.php2
-rw-r--r--tests/codeigniter/core/compat/array_test.php429
-rw-r--r--tests/codeigniter/core/compat/standard_test.php576
-rw-r--r--user_guide_src/source/changelog.rst3
-rw-r--r--user_guide_src/source/general/autoloader.rst6
-rw-r--r--user_guide_src/source/general/compatibility_functions.rst47
-rw-r--r--user_guide_src/source/general/creating_drivers.rst6
-rw-r--r--user_guide_src/source/libraries/encryption.rst4
13 files changed, 870 insertions, 474 deletions
diff --git a/application/config/config.php b/application/config/config.php
index d269b6e5d..b6b3c9fdf 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -121,7 +121,6 @@ $config['charset'] = 'UTF-8';
*/
$config['enable_hooks'] = FALSE;
-
/*
|--------------------------------------------------------------------------
| Class Extension Prefix
@@ -136,6 +135,27 @@ $config['enable_hooks'] = FALSE;
*/
$config['subclass_prefix'] = 'MY_';
+/*
+|--------------------------------------------------------------------------
+| Composer auto-loading
+|--------------------------------------------------------------------------
+|
+| Enabling this setting will tell CodeIgniter to look for a Composer
+| package auto-loader script in application/vendor/autoload.php.
+|
+| $config['composer_autoload'] = TRUE;
+|
+| Or if you have your vendor/ directory located somewhere else, you
+| can opt to set a specific path as well:
+|
+| $config['composer_autoload'] = '/path/to/vendor/autoload.php';
+|
+| For more information about Composer, please visit http://getcomposer.org/
+|
+| Note: This will NOT disable or override the CodeIgniter-specific
+| autoloading (application/config/autoload.php)
+*/
+$config['composer_autoload'] = FALSE;
/*
|--------------------------------------------------------------------------
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 1c6e76b4f..5ff788ae3 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -249,7 +249,7 @@ if ( ! is_php('5.4'))
require_once(BASEPATH.'core/compat/mbstring.php');
require_once(BASEPATH.'core/compat/hash.php');
require_once(BASEPATH.'core/compat/password.php');
- require_once(BASEPATH.'core/compat/array.php');
+ require_once(BASEPATH.'core/compat/standard.php');
/*
* ------------------------------------------------------
@@ -449,6 +449,23 @@ if ( ! is_php('5.4'))
/*
* ------------------------------------------------------
+ * Should we use a Composer autoloader?
+ * ------------------------------------------------------
+ */
+ if (($composer_autoload = config_item('composer_autoload')) !== FALSE)
+ {
+ if ($composer_autoload === TRUE && file_exists(APPPATH.'vendor/autoload.php'))
+ {
+ require_once(APPPATH.'vendor/autoload.php');
+ }
+ elseif (file_exists($composer_autoload))
+ {
+ require_once($composer_autoload);
+ }
+ }
+
+/*
+ * ------------------------------------------------------
* Is there a "pre_controller" hook?
* ------------------------------------------------------
*/
diff --git a/system/core/compat/password.php b/system/core/compat/password.php
index d5a017d9a..a8bc756f0 100644
--- a/system/core/compat/password.php
+++ b/system/core/compat/password.php
@@ -83,6 +83,9 @@ if ( ! function_exists('password_hash'))
*/
function password_hash($password, $algo, array $options = array())
{
+ static $func_override;
+ isset($func_override) OR $func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));
+
if ($algo !== 1)
{
trigger_error('password_hash(): Unknown hashing algorithm: '.(int) $algo, E_USER_WARNING);
@@ -95,9 +98,9 @@ if ( ! function_exists('password_hash'))
return NULL;
}
- if (isset($options['salt']) && strlen($options['salt']) < 22)
+ if (isset($options['salt']) && ($saltlen = ($func_override ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))) < 22)
{
- trigger_error('password_hash(): Provided salt is too short: '.strlen($options['salt']).' expecting 22', E_USER_WARNING);
+ trigger_error('password_hash(): Provided salt is too short: '.$saltlen.' expecting 22', E_USER_WARNING);
return NULL;
}
elseif ( ! isset($options['salt']))
@@ -119,7 +122,7 @@ if ( ! function_exists('password_hash'))
}
$options['salt'] = '';
- for ($read = 0; $read < 16; $read = strlen($options['salt']))
+ for ($read = 0; $read < 16; $read = ($func_override) ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))
{
if (($read = fread($fp, 16 - $read)) === FALSE)
{
diff --git a/system/core/compat/array.php b/system/core/compat/standard.php
index 07dae21c2..afe9e9852 100644
--- a/system/core/compat/array.php
+++ b/system/core/compat/standard.php
@@ -27,14 +27,13 @@
defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * PHP ext/standard/array compatibility package
+ * PHP ext/standard compatibility package
*
* @package CodeIgniter
* @subpackage CodeIgniter
* @category Compatibility
* @author Andrey Andreev
* @link http://codeigniter.com/user_guide/
- * @link http://php.net/book.array
*/
// ------------------------------------------------------------------------
@@ -125,6 +124,54 @@ if ( ! function_exists('array_column'))
// ------------------------------------------------------------------------
+if (is_php('5.4'))
+{
+ return;
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('hex2bin'))
+{
+ /**
+ * hex2bin()
+ *
+ * @link http://php.net/hex2bin
+ * @param string $data
+ * @return string
+ */
+ function hex2bin($data)
+ {
+ if (in_array($type = gettype($data), array('array', 'double', 'object'), TRUE))
+ {
+ if ($type === 'object' && method_exists($data, '__toString'))
+ {
+ $data = (string) $data;
+ }
+ else
+ {
+ trigger_error('hex2bin() expects parameter 1 to be string, '.$type.' given', E_USER_WARNING);
+ return NULL;
+ }
+ }
+
+ if (strlen($data) % 2 !== 0)
+ {
+ trigger_error('Hexadecimal input string must have an even length', E_USER_WARNING);
+ return FALSE;
+ }
+ elseif ( ! preg_match('/^[0-9a-f]*$/i', $data))
+ {
+ trigger_error('Input string must be hexadecimal string', E_USER_WARNING);
+ return FALSE;
+ }
+
+ return pack('H*', $data);
+ }
+}
+
+// ------------------------------------------------------------------------
+
if (is_php('5.3'))
{
return;
@@ -242,5 +289,93 @@ if ( ! function_exists('array_replace_recursive'))
}
}
-/* End of file array.php */
-/* Location: ./system/core/compat/array.php */ \ No newline at end of file
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('quoted_printable_encode'))
+{
+ /**
+ * quoted_printable_encode()
+ *
+ * @link http://php.net/quoted_printable_encode
+ * @param string $str
+ * @return string
+ */
+ function quoted_printable_encode($str)
+ {
+ if (strlen($str) === 0)
+ {
+ return '';
+ }
+ elseif (in_array($type = gettype($str), array('array', 'object'), TRUE))
+ {
+ if ($type === 'object' && method_exists($str, '__toString'))
+ {
+ $str = (string) $str;
+ }
+ else
+ {
+ trigger_error('quoted_printable_encode() expects parameter 1 to be string, '.$type.' given', E_USER_WARNING);
+ return NULL;
+ }
+ }
+
+ if (function_exists('imap_8bit'))
+ {
+ return imap_8bit($str);
+ }
+
+ $i = $lp = 0;
+ $output = '';
+ $hex = '0123456789ABCDEF';
+ $length = (extension_loaded('mbstring') && ini_get('mbstring.func_overload'))
+ ? mb_strlen($str, '8bit')
+ : strlen($str);
+
+ while ($length--)
+ {
+ if ((($c = $str[$i++]) === "\015") && isset($str[$i]) && ($str[$i] === "\012") && $length > 0)
+ {
+ $output .= "\015".$str[$i++];
+ $length--;
+ $lp = 0;
+ continue;
+ }
+
+ if (
+ ctype_cntrl($c)
+ OR (ord($c) === 0x7f)
+ OR (ord($c) & 0x80)
+ OR ($c === '=')
+ OR ($c === ' ' && isset($str[$i]) && $str[$i] === "\015")
+ )
+ {
+ if (
+ (($lp += 3) > 75 && ord($c) <= 0x7f)
+ OR (ord($c) > 0x7f && ord($c) <= 0xdf && ($lp + 3) > 75)
+ OR (ord($c) > 0xdf && ord($c) <= 0xef && ($lp + 6) > 75)
+ OR (ord($c) > 0xef && ord($c) <= 0xf4 && ($lp + 9) > 75)
+ )
+ {
+ $output .= "=\015\012";
+ $lp = 3;
+ }
+
+ $output .= '='.$hex[ord($c) >> 4].$hex[ord($c) & 0xf];
+ continue;
+ }
+
+ if ((++$lp) > 75)
+ {
+ $output .= "=\015\012";
+ $lp = 1;
+ }
+
+ $output .= $c;
+ }
+
+ return $output;
+ }
+}
+
+/* End of file standard.php */
+/* Location: ./system/core/compat/standard.php */ \ No newline at end of file
diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php
index b85d7da36..1a61967a7 100644
--- a/system/libraries/Encryption.php
+++ b/system/libraries/Encryption.php
@@ -123,6 +123,13 @@ class CI_Encryption {
'sha512' => 64
);
+ /**
+ * mbstring.func_override flag
+ *
+ * @var bool
+ */
+ protected static $func_override;
+
// --------------------------------------------------------------------
/**
@@ -145,8 +152,10 @@ class CI_Encryption {
return show_error('Encryption: Unable to find an available encryption driver.');
}
+ isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));
$this->initialize($params);
- if ( ! isset($this->_key) && strlen($key = config_item('encryption_key')) > 0)
+
+ if ( ! isset($this->_key) && self::strlen($key = config_item('encryption_key')) > 0)
{
$this->_key = $key;
}
@@ -337,7 +346,7 @@ class CI_Encryption {
return FALSE;
}
- isset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, strlen($this->_key), 'encryption');
+ isset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');
if (($data = $this->{'_'.$this->_driver.'_encrypt'}($data, $params)) === FALSE)
{
@@ -392,7 +401,7 @@ class CI_Encryption {
if (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE))
{
$block_size = mcrypt_enc_get_block_size($params['handle']);
- $pad = $block_size - (strlen($data) % $block_size);
+ $pad = $block_size - (self::strlen($data) % $block_size);
$data .= str_repeat(chr($pad), $pad);
}
@@ -480,13 +489,13 @@ class CI_Encryption {
? $this->_digests[$params['hmac_digest']] * 2
: $this->_digests[$params['hmac_digest']];
- if (strlen($data) <= $digest_size)
+ if (self::strlen($data) <= $digest_size)
{
return FALSE;
}
- $hmac_input = substr($data, 0, $digest_size);
- $data = substr($data, $digest_size);
+ $hmac_input = self::substr($data, 0, $digest_size);
+ $data = self::substr($data, $digest_size);
isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');
$hmac_check = hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']);
@@ -509,7 +518,7 @@ class CI_Encryption {
$data = base64_decode($data);
}
- isset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, strlen($this->_key), 'encryption');
+ isset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');
return $this->{'_'.$this->_driver.'_decrypt'}($data, $params);
}
@@ -536,8 +545,8 @@ class CI_Encryption {
{
if (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB')
{
- $iv = substr($data, 0, $iv_size);
- $data = substr($data, $iv_size);
+ $iv = self::substr($data, 0, $iv_size);
+ $data = self::substr($data, $iv_size);
}
else
{
@@ -564,7 +573,7 @@ class CI_Encryption {
// Remove PKCS#7 padding, if necessary
if (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE))
{
- $data = substr($data, 0, -ord($data[strlen($data)-1]));
+ $data = self::substr($data, 0, -ord($data[self::strlen($data)-1]));
}
mcrypt_generic_deinit($params['handle']);
@@ -589,8 +598,8 @@ class CI_Encryption {
{
if ($iv_size = openssl_cipher_iv_length($params['handle']))
{
- $iv = substr($data, 0, $iv_size);
- $data = substr($data, $iv_size);
+ $iv = self::substr($data, 0, $iv_size);
+ $data = self::substr($data, $iv_size);
}
else
{
@@ -827,17 +836,17 @@ class CI_Encryption {
return FALSE;
}
- strlen($salt) OR $salt = str_repeat("\0", $this->_digests[$digest]);
+ self::strlen($salt) OR $salt = str_repeat("\0", $this->_digests[$digest]);
$prk = hash_hmac($digest, $key, $salt, TRUE);
$key = '';
- for ($key_block = '', $block_index = 1; strlen($key) < $length; $block_index++)
+ for ($key_block = '', $block_index = 1; self::strlen($key) < $length; $block_index++)
{
$key_block = hash_hmac($digest, $key_block.$info.chr($block_index), $prk, TRUE);
$key .= $key_block;
}
- return substr($key, 0, $length);
+ return self::substr($key, 0, $length);
}
// --------------------------------------------------------------------
@@ -863,6 +872,45 @@ class CI_Encryption {
return NULL;
}
+ // --------------------------------------------------------------------
+
+ /**
+ * Byte-safe strlen()
+ *
+ * @param string $str
+ * @return integer
+ */
+ protected static function strlen($str)
+ {
+ return (self::$func_override)
+ ? mb_strlen($str, '8bit')
+ : strlen($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Byte-safe substr()
+ *
+ * @param string $str
+ * @param int $start
+ * @param int $length
+ * @return string
+ */
+ protected static function substr($str, $start, $length = NULL)
+ {
+ if (self::$func_override)
+ {
+ // mb_substr($str, $start, null, '8bit') returns an empty
+ // string on PHP 5.3
+ isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start);
+ return mb_substr($str, $start, $length, '8bit');
+ }
+
+ return isset($length)
+ ? substr($str, $start, $length)
+ : substr($str, $start);
+ }
}
/* End of file Encryption.php */
diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php
index cc84abf28..713c0fdb3 100644
--- a/tests/Bootstrap.php
+++ b/tests/Bootstrap.php
@@ -69,7 +69,7 @@ is_php('5.6') && ini_set('php.internal_encoding', 'UTF-8');
include_once SYSTEM_PATH.'core/compat/mbstring.php';
include_once SYSTEM_PATH.'core/compat/hash.php';
include_once SYSTEM_PATH.'core/compat/password.php';
-include_once SYSTEM_PATH.'core/compat/array.php';
+include_once SYSTEM_PATH.'core/compat/standard.php';
include_once $dir.'/mocks/autoloader.php';
spl_autoload_register('autoload');
diff --git a/tests/codeigniter/core/compat/array_test.php b/tests/codeigniter/core/compat/array_test.php
deleted file mode 100644
index 9d2deaba6..000000000
--- a/tests/codeigniter/core/compat/array_test.php
+++ /dev/null
@@ -1,429 +0,0 @@
-<?php
-
-class array_test extends CI_TestCase {
-
- public function test_bootstrap()
- {
- if (is_php('5.5'))
- {
- return $this->markTestSkipped('All array functions are already available on PHP 5.5');
- }
- elseif ( ! is_php('5.3'))
- {
- $this->assertTrue(function_exists('array_replace'));
- $this->assertTrue(function_exists('array_replace_recursive'));
- }
-
- $this->assertTrue(function_exists('array_column'));
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * array_column() test
- *
- * Borrowed from PHP's own tests
- *
- * @depends test_bootstrap
- */
- public function test_array_column()
- {
- // Basic tests
-
- $input = array(
- array(
- 'id' => 1,
- 'first_name' => 'John',
- 'last_name' => 'Doe'
- ),
- array(
- 'id' => 2,
- 'first_name' => 'Sally',
- 'last_name' => 'Smith'
- ),
- array(
- 'id' => 3,
- 'first_name' => 'Jane',
- 'last_name' => 'Jones'
- )
- );
-
- // Ensure internal array position doesn't break it
- next($input);
-
- $this->assertEquals(
- array('John', 'Sally', 'Jane'),
- array_column($input, 'first_name')
- );
-
- $this->assertEquals(
- array(1, 2, 3),
- array_column($input, 'id')
- );
-
- $this->assertEquals(
- array(
- 1 => 'Doe',
- 2 => 'Smith',
- 3 => 'Jones'
- ),
- array_column($input, 'last_name', 'id')
- );
-
- $this->assertEquals(
- array(
- 'John' => 'Doe',
- 'Sally' => 'Smith',
- 'Jane' => 'Jones'
- ),
- array_column($input, 'last_name', 'first_name')
- );
-
- // Object key search
-
- $f = new Foo();
- $b = new Bar();
-
- $this->assertEquals(
- array('Doe', 'Smith', 'Jones'),
- array_column($input, $f)
- );
-
- $this->assertEquals(
- array(
- 'John' => 'Doe',
- 'Sally' => 'Smith',
- 'Jane' => 'Jones'
- ),
- array_column($input, $f, $b)
- );
-
- // NULL parameters
-
- $input = array(
- 456 => array(
- 'id' => '3',
- 'title' => 'Foo',
- 'date' => '2013-03-25'
- ),
- 457 => array(
- 'id' => '5',
- 'title' => 'Bar',
- 'date' => '2012-05-20'
- )
- );
-
- $this->assertEquals(
- array(
- 3 => array(
- 'id' => '3',
- 'title' => 'Foo',
- 'date' => '2013-03-25'
- ),
- 5 => array(
- 'id' => '5',
- 'title' => 'Bar',
- 'date' => '2012-05-20'
- )
- ),
- array_column($input, NULL, 'id')
- );
-
- $this->assertEquals(
- array(
- array(
- 'id' => '3',
- 'title' => 'Foo',
- 'date' => '2013-03-25'
- ),
- array(
- 'id' => '5',
- 'title' => 'Bar',
- 'date' => '2012-05-20'
- )
- ),
- array_column($input, NULL, 'foo')
- );
-
- $this->assertEquals(
- array(
- array(
- 'id' => '3',
- 'title' => 'Foo',
- 'date' => '2013-03-25'
- ),
- array(
- 'id' => '5',
- 'title' => 'Bar',
- 'date' => '2012-05-20'
- )
- ),
- array_column($input, NULL)
- );
-
- // Data types
-
- $fh = fopen(__FILE__, 'r', TRUE);
- $stdClass = new stdClass();
- $input = array(
- array(
- 'id' => 1,
- 'value' => $stdClass
- ),
- array(
- 'id' => 2,
- 'value' => 34.2345
- ),
- array(
- 'id' => 3,
- 'value' => TRUE
- ),
- array(
- 'id' => 4,
- 'value' => FALSE
- ),
- array(
- 'id' => 5,
- 'value' => NULL
- ),
- array(
- 'id' => 6,
- 'value' => 1234
- ),
- array(
- 'id' => 7,
- 'value' => 'Foo'
- ),
- array(
- 'id' => 8,
- 'value' => $fh
- )
- );
-
- $this->assertEquals(
- array(
- $stdClass,
- 34.2345,
- TRUE,
- FALSE,
- NULL,
- 1234,
- 'Foo',
- $fh
- ),
- array_column($input, 'value')
- );
-
- $this->assertEquals(
- array(
- 1 => $stdClass,
- 2 => 34.2345,
- 3 => TRUE,
- 4 => FALSE,
- 5 => NULL,
- 6 => 1234,
- 7 => 'Foo',
- 8 => $fh
- ),
- array_column($input, 'value', 'id')
- );
-
- // Numeric column keys
-
- $input = array(
- array('aaa', '111'),
- array('bbb', '222'),
- array('ccc', '333', -1 => 'ddd')
- );
-
- $this->assertEquals(
- array('111', '222', '333'),
- array_column($input, 1)
- );
-
- $this->assertEquals(
- array(
- 'aaa' => '111',
- 'bbb' => '222',
- 'ccc' => '333'
- ),
- array_column($input, 1, 0)
- );
-
- $this->assertEquals(
- array(
- 'aaa' => '111',
- 'bbb' => '222',
- 'ccc' => '333'
- ),
- array_column($input, 1, 0.123)
- );
-
- $this->assertEquals(
- array(
- 0 => '111',
- 1 => '222',
- 'ddd' => '333'
- ),
- array_column($input, 1, -1)
- );
-
- // Non-existing columns
-
- $this->assertEquals(array(), array_column($input, 2));
- $this->assertEquals(array(), array_column($input, 'foo'));
- $this->assertEquals(
- array('aaa', 'bbb', 'ccc'),
- array_column($input, 0, 'foo')
- );
- $this->assertEquals(array(), array_column($input, 3.14));
-
- // One-dimensional array
- $this->assertEquals(array(), array_column(array('foo', 'bar', 'baz'), 1));
-
- // Columns not present in all rows
-
- $input = array(
- array('a' => 'foo', 'b' => 'bar', 'e' => 'bbb'),
- array('a' => 'baz', 'c' => 'qux', 'd' => 'aaa'),
- array('a' => 'eee', 'b' => 'fff', 'e' => 'ggg')
- );
-
- $this->assertEquals(
- array('qux'),
- array_column($input, 'c')
- );
-
- $this->assertEquals(
- array('baz' => 'qux'),
- array_column($input, 'c', 'a')
- );
-
- $this->assertEquals(
- array(
- 0 => 'foo',
- 'aaa' => 'baz',
- 1 => 'eee'
- ),
- array_column($input, 'a', 'd')
- );
-
- $this->assertEquals(
- array(
- 'bbb' => 'foo',
- 0 => 'baz',
- 'ggg' => 'eee'
- ),
- array_column($input, 'a', 'e')
- );
-
- $this->assertEquals(
- array('bar', 'fff'),
- array_column($input, 'b')
- );
-
- $this->assertEquals(
- array(
- 'foo' => 'bar',
- 'eee' => 'fff'
- ),
- array_column($input, 'b', 'a')
- );
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * array_replace(), array_replace_recursive() tests
- *
- * Borrowed from PHP's own tests
- *
- * @depends test_bootstrap
- */
- public function test_array_replace_recursive()
- {
- if (is_php('5.3'))
- {
- return $this->markTestSkipped('array_replace() and array_replace_recursive() are already available on PHP 5.3');
- }
-
- $array1 = array(
- 0 => 'dontclobber',
- '1' => 'unclobbered',
- 'test2' => 0.0,
- 'test3' => array(
- 'testarray2' => TRUE,
- 1 => array(
- 'testsubarray1' => 'dontclobber2',
- 'testsubarray2' => 'dontclobber3'
- )
- )
- );
-
- $array2 = array(
- 1 => 'clobbered',
- 'test3' => array(
- 'testarray2' => FALSE
- ),
- 'test4' => array(
- 'clobbered3' => array(0, 1, 2)
- )
- );
-
- // array_replace()
- $this->assertEquals(
- array(
- 0 => 'dontclobber',
- 1 => 'clobbered',
- 'test2' => 0.0,
- 'test3' => array(
- 'testarray2' => FALSE
- ),
- 'test4' => array(
- 'clobbered3' => array(0, 1, 2)
- )
- ),
- array_replace($array1, $array2)
- );
-
- // array_replace_recursive()
- $this->assertEquals(
- array(
- 0 => 'dontclobber',
- 1 => 'clobbered',
- 'test2' => 0.0,
- 'test3' => array(
- 'testarray2' => FALSE,
- 1 => array(
- 'testsubarray1' => 'dontclobber2',
- 'testsubarray2' => 'dontclobber3'
- )
- ),
- 'test4' => array(
- 'clobbered3' => array(0, 1, 2)
- )
- ),
- array_replace_recursive($array1, $array2)
- );
- }
-}
-
-// ------------------------------------------------------------------------
-
-// These are necessary for the array_column() tests
-
-class Foo {
-
- public function __toString()
- {
- return 'last_name';
- }
-}
-
-class Bar {
-
- public function __toString()
- {
- return 'first_name';
- }
-} \ No newline at end of file
diff --git a/tests/codeigniter/core/compat/standard_test.php b/tests/codeigniter/core/compat/standard_test.php
new file mode 100644
index 000000000..a3a6d9552
--- /dev/null
+++ b/tests/codeigniter/core/compat/standard_test.php
@@ -0,0 +1,576 @@
+<?php
+
+class standard_test extends CI_TestCase {
+
+ public function test_bootstrap()
+ {
+ if (is_php('5.5'))
+ {
+ return $this->markTestSkipped('All array functions are already available on PHP 5.5');
+ }
+
+ $this->assertTrue(function_exists('array_column'));
+
+ if ( ! is_php('5.4'))
+ {
+ $this->assertTrue(function_exists('hex2bin'));
+ }
+
+ if ( ! is_php('5.3'))
+ {
+ $this->assertTrue(function_exists('array_replace'));
+ $this->assertTrue(function_exists('array_replace_recursive'));
+ $this->assertTrue(function_exists('quoted_printable_encode'));
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * array_column() test
+ *
+ * Borrowed from PHP's own tests
+ *
+ * @depends test_bootstrap
+ */
+ public function test_array_column()
+ {
+ // Basic tests
+
+ $input = array(
+ array(
+ 'id' => 1,
+ 'first_name' => 'John',
+ 'last_name' => 'Doe'
+ ),
+ array(
+ 'id' => 2,
+ 'first_name' => 'Sally',
+ 'last_name' => 'Smith'
+ ),
+ array(
+ 'id' => 3,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Jones'
+ )
+ );
+
+ // Ensure internal array position doesn't break it
+ next($input);
+
+ $this->assertEquals(
+ array('John', 'Sally', 'Jane'),
+ array_column($input, 'first_name')
+ );
+
+ $this->assertEquals(
+ array(1, 2, 3),
+ array_column($input, 'id')
+ );
+
+ $this->assertEquals(
+ array(
+ 1 => 'Doe',
+ 2 => 'Smith',
+ 3 => 'Jones'
+ ),
+ array_column($input, 'last_name', 'id')
+ );
+
+ $this->assertEquals(
+ array(
+ 'John' => 'Doe',
+ 'Sally' => 'Smith',
+ 'Jane' => 'Jones'
+ ),
+ array_column($input, 'last_name', 'first_name')
+ );
+
+ // Object key search
+
+ $f = new Foo();
+ $b = new Bar();
+
+ $this->assertEquals(
+ array('Doe', 'Smith', 'Jones'),
+ array_column($input, $f)
+ );
+
+ $this->assertEquals(
+ array(
+ 'John' => 'Doe',
+ 'Sally' => 'Smith',
+ 'Jane' => 'Jones'
+ ),
+ array_column($input, $f, $b)
+ );
+
+ // NULL parameters
+
+ $input = array(
+ 456 => array(
+ 'id' => '3',
+ 'title' => 'Foo',
+ 'date' => '2013-03-25'
+ ),
+ 457 => array(
+ 'id' => '5',
+ 'title' => 'Bar',
+ 'date' => '2012-05-20'
+ )
+ );
+
+ $this->assertEquals(
+ array(
+ 3 => array(
+ 'id' => '3',
+ 'title' => 'Foo',
+ 'date' => '2013-03-25'
+ ),
+ 5 => array(
+ 'id' => '5',
+ 'title' => 'Bar',
+ 'date' => '2012-05-20'
+ )
+ ),
+ array_column($input, NULL, 'id')
+ );
+
+ $this->assertEquals(
+ array(
+ array(
+ 'id' => '3',
+ 'title' => 'Foo',
+ 'date' => '2013-03-25'
+ ),
+ array(
+ 'id' => '5',
+ 'title' => 'Bar',
+ 'date' => '2012-05-20'
+ )
+ ),
+ array_column($input, NULL, 'foo')
+ );
+
+ $this->assertEquals(
+ array(
+ array(
+ 'id' => '3',
+ 'title' => 'Foo',
+ 'date' => '2013-03-25'
+ ),
+ array(
+ 'id' => '5',
+ 'title' => 'Bar',
+ 'date' => '2012-05-20'
+ )
+ ),
+ array_column($input, NULL)
+ );
+
+ // Data types
+
+ $fh = fopen(__FILE__, 'r', TRUE);
+ $stdClass = new stdClass();
+ $input = array(
+ array(
+ 'id' => 1,
+ 'value' => $stdClass
+ ),
+ array(
+ 'id' => 2,
+ 'value' => 34.2345
+ ),
+ array(
+ 'id' => 3,
+ 'value' => TRUE
+ ),
+ array(
+ 'id' => 4,
+ 'value' => FALSE
+ ),
+ array(
+ 'id' => 5,
+ 'value' => NULL
+ ),
+ array(
+ 'id' => 6,
+ 'value' => 1234
+ ),
+ array(
+ 'id' => 7,
+ 'value' => 'Foo'
+ ),
+ array(
+ 'id' => 8,
+ 'value' => $fh
+ )
+ );
+
+ $this->assertEquals(
+ array(
+ $stdClass,
+ 34.2345,
+ TRUE,
+ FALSE,
+ NULL,
+ 1234,
+ 'Foo',
+ $fh
+ ),
+ array_column($input, 'value')
+ );
+
+ $this->assertEquals(
+ array(
+ 1 => $stdClass,
+ 2 => 34.2345,
+ 3 => TRUE,
+ 4 => FALSE,
+ 5 => NULL,
+ 6 => 1234,
+ 7 => 'Foo',
+ 8 => $fh
+ ),
+ array_column($input, 'value', 'id')
+ );
+
+ // Numeric column keys
+
+ $input = array(
+ array('aaa', '111'),
+ array('bbb', '222'),
+ array('ccc', '333', -1 => 'ddd')
+ );
+
+ $this->assertEquals(
+ array('111', '222', '333'),
+ array_column($input, 1)
+ );
+
+ $this->assertEquals(
+ array(
+ 'aaa' => '111',
+ 'bbb' => '222',
+ 'ccc' => '333'
+ ),
+ array_column($input, 1, 0)
+ );
+
+ $this->assertEquals(
+ array(
+ 'aaa' => '111',
+ 'bbb' => '222',
+ 'ccc' => '333'
+ ),
+ array_column($input, 1, 0.123)
+ );
+
+ $this->assertEquals(
+ array(
+ 0 => '111',
+ 1 => '222',
+ 'ddd' => '333'
+ ),
+ array_column($input, 1, -1)
+ );
+
+ // Non-existing columns
+
+ $this->assertEquals(array(), array_column($input, 2));
+ $this->assertEquals(array(), array_column($input, 'foo'));
+ $this->assertEquals(
+ array('aaa', 'bbb', 'ccc'),
+ array_column($input, 0, 'foo')
+ );
+ $this->assertEquals(array(), array_column($input, 3.14));
+
+ // One-dimensional array
+ $this->assertEquals(array(), array_column(array('foo', 'bar', 'baz'), 1));
+
+ // Columns not present in all rows
+
+ $input = array(
+ array('a' => 'foo', 'b' => 'bar', 'e' => 'bbb'),
+ array('a' => 'baz', 'c' => 'qux', 'd' => 'aaa'),
+ array('a' => 'eee', 'b' => 'fff', 'e' => 'ggg')
+ );
+
+ $this->assertEquals(
+ array('qux'),
+ array_column($input, 'c')
+ );
+
+ $this->assertEquals(
+ array('baz' => 'qux'),
+ array_column($input, 'c', 'a')
+ );
+
+ $this->assertEquals(
+ array(
+ 0 => 'foo',
+ 'aaa' => 'baz',
+ 1 => 'eee'
+ ),
+ array_column($input, 'a', 'd')
+ );
+
+ $this->assertEquals(
+ array(
+ 'bbb' => 'foo',
+ 0 => 'baz',
+ 'ggg' => 'eee'
+ ),
+ array_column($input, 'a', 'e')
+ );
+
+ $this->assertEquals(
+ array('bar', 'fff'),
+ array_column($input, 'b')
+ );
+
+ $this->assertEquals(
+ array(
+ 'foo' => 'bar',
+ 'eee' => 'fff'
+ ),
+ array_column($input, 'b', 'a')
+ );
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * hex2bin() tests
+ *
+ * @depends test_bootstrap
+ */
+ public function test_hex2bin()
+ {
+ if (is_php('5.4'))
+ {
+ return $this->markTestSkipped('hex2bin() is already available on PHP 5.4');
+ }
+
+ $this->assertEquals("\x03\x04", hex2bin("0304"));
+ $this->assertEquals('', hex2bin(''));
+ $this->assertEquals("\x01\x02\x03", hex2bin(new FooHex()));
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * array_replace(), array_replace_recursive() tests
+ *
+ * Borrowed from PHP's own tests
+ *
+ * @depends test_bootstrap
+ */
+ public function test_array_replace_recursive()
+ {
+ if (is_php('5.3'))
+ {
+ return $this->markTestSkipped('array_replace() and array_replace_recursive() are already available on PHP 5.3');
+ }
+
+ $array1 = array(
+ 0 => 'dontclobber',
+ '1' => 'unclobbered',
+ 'test2' => 0.0,
+ 'test3' => array(
+ 'testarray2' => TRUE,
+ 1 => array(
+ 'testsubarray1' => 'dontclobber2',
+ 'testsubarray2' => 'dontclobber3'
+ )
+ )
+ );
+
+ $array2 = array(
+ 1 => 'clobbered',
+ 'test3' => array(
+ 'testarray2' => FALSE
+ ),
+ 'test4' => array(
+ 'clobbered3' => array(0, 1, 2)
+ )
+ );
+
+ // array_replace()
+ $this->assertEquals(
+ array(
+ 0 => 'dontclobber',
+ 1 => 'clobbered',
+ 'test2' => 0.0,
+ 'test3' => array(
+ 'testarray2' => FALSE
+ ),
+ 'test4' => array(
+ 'clobbered3' => array(0, 1, 2)
+ )
+ ),
+ array_replace($array1, $array2)
+ );
+
+ // array_replace_recursive()
+ $this->assertEquals(
+ array(
+ 0 => 'dontclobber',
+ 1 => 'clobbered',
+ 'test2' => 0.0,
+ 'test3' => array(
+ 'testarray2' => FALSE,
+ 1 => array(
+ 'testsubarray1' => 'dontclobber2',
+ 'testsubarray2' => 'dontclobber3'
+ )
+ ),
+ 'test4' => array(
+ 'clobbered3' => array(0, 1, 2)
+ )
+ ),
+ array_replace_recursive($array1, $array2)
+ );
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * quoted_printable_encode() tests
+ *
+ * Borrowed from PHP's own tests
+ *
+ * @depends test_bootstrap
+ */
+ public function test_quoted_printable_encode()
+ {
+ if (is_php('5.3'))
+ {
+ return $this->markTestSkipped('quoted_printable_encode() is already available on PHP 5.3');
+ }
+
+
+ // These are actually imap_8bit() tests:
+ $this->assertEquals("String with CRLF at end=20\r\n", quoted_printable_encode("String with CRLF at end \r\n"));
+ // ext/imap/tests/imap_8bit_basic.phpt says for this line:
+ // NB this appears to be a bug in cclient; a space at end of string should be encoded as =20
+ $this->assertEquals("String with space at end ", quoted_printable_encode("String with space at end "));
+ $this->assertEquals("String with tabs =09=09 in middle", quoted_printable_encode("String with tabs \t\t in middle"));
+ $this->assertEquals("String with tab at end =09", quoted_printable_encode("String with tab at end \t"));
+ $this->assertEquals("=00=01=02=03=04=FE=FF=0A=0D", quoted_printable_encode("\x00\x01\x02\x03\x04\xfe\xff\x0a\x0d"));
+
+ // And these are from ext/standard/tests/strings/quoted_printable_encode_002.phpt:
+ $this->assertEquals(
+ "=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=\r\n"
+ ."=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=\r\n"
+ ."=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=\r\n"
+ ."=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=\r\n"
+ ."=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=\r\n"
+ ."=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=\r\n"
+ ."=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=\r\n"
+ ."=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00",
+ $d = quoted_printable_encode(str_repeat("\0", 200))
+ );
+ $this->assertEquals(str_repeat("\x0", 200), quoted_printable_decode($d));
+ $this->assertEquals(
+ "=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=\r\n"
+ ."=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=\r\n"
+ ."=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=\r\n"
+ ."=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=\r\n"
+ ."=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=\r\n"
+ ."=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=\r\n"
+ ."=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=\r\n"
+ ."=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=\r\n"
+ ."=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =\r\n"
+ ."=D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=\r\n"
+ ."=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=\r\n"
+ ."=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=\r\n"
+ ."=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=\r\n"
+ ."=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=\r\n"
+ ."=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=\r\n"
+ ."=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=\r\n"
+ ."=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=\r\n"
+ ."=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=\r\n"
+ ."=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=\r\n"
+ ."=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =\r\n"
+ ."=D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=\r\n"
+ ."=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=\r\n"
+ ."=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=\r\n"
+ ."=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=\r\n"
+ ."=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=\r\n"
+ ."=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=\r\n"
+ ."=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=\r\n"
+ ."=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=\r\n"
+ ."=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=\r\n"
+ ."=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=\r\n"
+ ."=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=\r\n"
+ ."=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =\r\n"
+ ."=D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=\r\n"
+ ."=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=\r\n"
+ ."=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=\r\n"
+ ."=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=\r\n"
+ ."=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=\r\n"
+ ."=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=\r\n"
+ ."=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=\r\n"
+ ."=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=\r\n"
+ ."=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=\r\n"
+ ."=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=\r\n"
+ ."=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =\r\n"
+ ."=D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=\r\n"
+ ."=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=\r\n"
+ ."=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=\r\n"
+ ."=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=\r\n"
+ ."=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=\r\n"
+ ."=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=\r\n"
+ ."=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=\r\n"
+ ."=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=\r\n"
+ ."=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=\r\n"
+ ."=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=\r\n"
+ ."=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=\r\n"
+ ."=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =\r\n"
+ ."=D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=\r\n"
+ ."=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=\r\n"
+ ."=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=\r\n"
+ ."=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=8E=D0=BD=D0=B8=\r\n"
+ ."=D0=BA=D0=BE=D0=B4=D0=B5=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0 =D0=B2 =D1=\r\n"
+ ."=8E=D0=BD=D0=B8=D0=BA=D0=BE=D0=B4=D0=B5",
+ $d = quoted_printable_encode(str_repeat('строка в юникоде', 50))
+ );
+ $this->assertEquals(str_repeat('строка в юникоде', 50), quoted_printable_decode($d));
+ $this->assertEquals('this is a foo', quoted_printable_encode(new FooObject()));
+ }
+}
+
+// ------------------------------------------------------------------------
+
+class Foo {
+
+ public function __toString()
+ {
+ return 'last_name';
+ }
+}
+
+class Bar {
+
+ public function __toString()
+ {
+ return 'first_name';
+ }
+}
+
+class FooHex {
+
+ public function __toString()
+ {
+ return '010203';
+ }
+}
+
+class FooObject
+{
+ public function __toString()
+ {
+ return 'this is a foo';
+ }
+} \ No newline at end of file
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index ec38a3ea9..d2bb195b6 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -61,6 +61,7 @@ Release Date: Not Released
- Added availability checks where usage of dangerous functions like ``eval()`` and ``exec()`` is required.
- Added support for changing the file extension of log files using ``$config['log_file_extension']``.
- Added support for turning newline standardization on/off via ``$config['standardize_newlines']`` and set it to FALSE by default.
+ - Added configuration setting ``$config['composer_autoload']`` to enable loading of a `Composer <https://getcomposer.org/>`_ auto-loader.
- Helpers
@@ -531,7 +532,7 @@ Release Date: Not Released
- `Multibyte String <http://php.net/mbstring>`_ (limited support).
- `Hash <http://php.net/hash>`_ (``hash_equals()``, ``hash_pbkdf2()``).
- `Password Hashing <http://php.net/password>`_.
- - `Array Functions <http://php.net/book.array>`_ (``array_column()``, ``array_replace()``, ``array_replace_recursive()``).
+ - `Standard Functions ``array_column()``, ``array_replace()``, ``array_replace_recursive()``, ``hex2bin()``, ``quoted_printable_encode()``.
- Removed ``CI_CORE`` boolean constant from *CodeIgniter.php* (no longer Reactor and Core versions).
- Log Library will now try to create the **log_path** directory if it doesn't exist.
diff --git a/user_guide_src/source/general/autoloader.rst b/user_guide_src/source/general/autoloader.rst
index bf2e3935a..2f1223e28 100644
--- a/user_guide_src/source/general/autoloader.rst
+++ b/user_guide_src/source/general/autoloader.rst
@@ -20,4 +20,8 @@ file and add the item you want loaded to the autoload array. You'll
find instructions in that file corresponding to each type of item.
.. note:: Do not include the file extension (.php) when adding items to
- the autoload array. \ No newline at end of file
+ the autoload array.
+
+Additionally, if you want CodeIgniter to use a `Composer <https://getcomposer.org/>`_
+auto-loader, just set ``$config['composer_autoload']`` to ``TRUE`` or
+a custom path in **application/config/config.php**. \ No newline at end of file
diff --git a/user_guide_src/source/general/compatibility_functions.rst b/user_guide_src/source/general/compatibility_functions.rst
index e685073a1..aee9b1ef0 100644
--- a/user_guide_src/source/general/compatibility_functions.rst
+++ b/user_guide_src/source/general/compatibility_functions.rst
@@ -7,12 +7,12 @@ you to use functions what are otherwise natively available in PHP,
but only in higher versions or depending on a certain extension.
Being custom implementations, these functions will also have some
-set of dependancies on their own, but are still useful if your
+set of dependencies on their own, but are still useful if your
PHP setup doesn't offer them natively.
.. note:: Much like the `common functions <common_functions>`, the
compatibility functions are always available, as long as
- their dependancies are met.
+ their dependencies are met.
.. contents::
:local:
@@ -29,7 +29,7 @@ This set of compatibility functions offers a "backport" of PHP's
standard `Password Hashing extension <http://php.net/password>`_
that is otherwise available only since PHP 5.5.
-Dependancies
+Dependencies
============
- PHP 5.3.7
@@ -65,7 +65,7 @@ Function reference
password_hash() <http://php.net/password_hash>`_.
.. note:: Unless you provide your own (and valid) salt, this function
- has a further dependancy on an available CSPRNG source. Each
+ has a further dependency on an available CSPRNG source. Each
of the following would satisfy that:
- ``mcrypt_create_iv()`` with ``MCRYPT_DEV_URANDOM``
- ``openssl_random_pseudo_bytes()``
@@ -101,7 +101,7 @@ This compatibility layer contains backports for the ``hash_equals()``
and ``hash_pbkdf2()`` functions, which otherwise require PHP 5.6 and/or
PHP 5.5 respectively.
-Dependancies
+Dependencies
============
- None
@@ -144,19 +144,19 @@ the limited alternative solutions, only a few functions are available.
.. note:: When a character set parameter is ommited,
``$config['charset']`` will be used.
-Dependancies
+Dependencies
============
- `iconv <http://php.net/iconv>`_ extension
-.. important:: This dependancy is optional and these functions will
+.. important:: This dependency is optional and these functions will
always be declared. If iconv is not available, they WILL
fall-back to their non-mbstring versions.
.. important:: Where a character set is supplied, it must be
supported by iconv and in a format that it recognizes.
-.. note:: For you own dependancy check on the actual mbstring
+.. note:: For you own dependency check on the actual mbstring
extension, use the ``MB_ENABLED`` constant.
Function reference
@@ -196,15 +196,14 @@ Function reference
For more information, please refer to the `PHP manual for
mb_substr() <http://php.net/mb_substr>`_.
-***************
-Array Functions
-***************
+******************
+Standard Functions
+******************
This set of compatibility functions offers support for a few
-standard `Array Functions <http://php.net/book.array>`_ in PHP
-that otherwise require a newer PHP version.
+standard functions in PHP that otherwise require a newer PHP version.
-Dependancies
+Dependencies
============
- None
@@ -244,4 +243,22 @@ Function reference
array_replace_recursive() <http://php.net/array_replace_recursive>`_.
.. important:: Only PHP's native function can detect endless recursion.
- Unless you are running PHP 5.3+, be careful with references! \ No newline at end of file
+ Unless you are running PHP 5.3+, be careful with references!
+
+.. function:: hex2bin($data)
+
+ :param array $data: Hexadecimal representation of data
+ :returns: Binary representation of the given data
+ :rtype: string
+
+ For more information, please refer to the `PHP manual for hex2bin()
+ <http://php.net/hex2bin>`_.
+
+.. function:: quoted_printable_encode($str)
+
+ :param string $str: Input string
+ :returns: 8bit-encoded string
+ :rtype: string
+
+ For more information, please refer to the `PHP manual for
+ quoted_printable_encode() <http://php.net/quoted_printable_encode>`_. \ No newline at end of file
diff --git a/user_guide_src/source/general/creating_drivers.rst b/user_guide_src/source/general/creating_drivers.rst
index cf4ea5d7f..63ac83902 100644
--- a/user_guide_src/source/general/creating_drivers.rst
+++ b/user_guide_src/source/general/creating_drivers.rst
@@ -18,4 +18,8 @@ Sample driver directory and file structure layout:
.. note:: In order to maintain compatibility on case-sensitive
file systems, the Driver_name directory must be
- named in the format returned by ``ucfirst()``. \ No newline at end of file
+ named in the format returned by ``ucfirst()``.
+
+.. note:: The Driver library's architecture is such that
+ the subclasses don't extend and therefore don't inherit
+ properties or methods of the main driver. \ No newline at end of file
diff --git a/user_guide_src/source/libraries/encryption.rst b/user_guide_src/source/libraries/encryption.rst
index 5d92b109a..f29ebf4ed 100644
--- a/user_guide_src/source/libraries/encryption.rst
+++ b/user_guide_src/source/libraries/encryption.rst
@@ -5,13 +5,13 @@ Encryption Library
The Encryption Library provides two-way data encryption. To do so in
a cryptographically secure way, it utilizes PHP extensions that are
unfortunately not always available on all systems.
-You must meet one of the following dependancies in order to use this
+You must meet one of the following dependencies in order to use this
library:
- `OpenSSL <http://php.net/openssl>`_ (and PHP 5.3.3)
- `MCrypt <http://php.net/mcrypt>`_ (and `MCRYPT_DEV_URANDOM` availability)
-If neither of the above dependancies is met, we simply cannot offer
+If neither of the above dependencies is met, we simply cannot offer
you a good enough implementation to meet the high standards required
for proper cryptography.