CodeIgniter 3.1.11 -> 3.4.5 (pocketarc fork) en PHP 8.3-fixes

- system/ vervangen door CodeIgniter 3.4.5 (pocketarc/codeigniter, PHP 8.2-8.5 compatibel)
- config.php, mimes.php, user_agents.php en error-views bijgewerkt naar 3.4.5
- composer.json: php-constraint "^7.4 || ^8.0" zodat composer install op 8.3 werkt
- PHP 8-fatals opgelost: count()/array-functies op FALSE/null, rekenen met lege
  strings, delen door nul, property zetten op FALSE, curly-brace string offsets,
  ongedefinieerde constanten, foute curl_setopt in Phantom_model::create_img
- dynamic properties gedeclareerd in libraries, optionele parameters voor verplichte opgelost
- vergelijkingen waar '' == 0 in PHP 8 anders uitvalt gecast naar (int)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-22 09:34:46 +02:00
co-authored by Claude Opus 5.5
parent c6afbb01f2
commit 172fcf566c
284 changed files with 3497 additions and 3718 deletions
+74 -249
View File
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014 - 2019, British Columbia Institute of Technology
* Copyright (c) 2019 - 2022, CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,6 +30,7 @@
* @author EllisLab Dev Team
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
* @copyright Copyright (c) 2014 - 2019, British Columbia Institute of Technology (https://bcit.ca/)
* @copyright Copyright (c) 2019 - 2022, CodeIgniter Foundation (https://codeigniter.com/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 1.0.0
@@ -46,7 +47,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Input
* @author EllisLab Dev Team
* @link https://codeigniter.com/user_guide/libraries/input.html
* @link https://codeigniter.com/userguide3/libraries/input.html
*/
class CI_Input {
@@ -57,45 +58,6 @@ class CI_Input {
*/
protected $ip_address = FALSE;
/**
* Allow GET array flag
*
* If set to FALSE, then $_GET will be set to an empty array.
*
* @var bool
*/
protected $_allow_get_array = TRUE;
/**
* Standardize new lines flag
*
* If set to TRUE, then newlines are standardized.
*
* @var bool
*/
protected $_standardize_newlines;
/**
* Enable XSS flag
*
* Determines whether the XSS filter is always active when
* GET, POST or COOKIE data is encountered.
* Set automatically based on config setting.
*
* @var bool
*/
protected $_enable_xss = FALSE;
/**
* Enable CSRF flag
*
* Enables a CSRF cookie token to be set.
* Set automatically based on config setting.
*
* @var bool
*/
protected $_enable_csrf = FALSE;
/**
* List of all HTTP request headers
*
@@ -122,8 +84,15 @@ class CI_Input {
*/
protected $_input_stream;
/**
* CI_Security instance
*
* Used for the optional $xss_filter parameter that most
* getter methods have here.
*
* @var CI_Security
*/
protected $security;
protected $uni;
// --------------------------------------------------------------------
@@ -135,30 +104,9 @@ class CI_Input {
*
* @return void
*/
public function __construct()
public function __construct(CI_Security &$security)
{
$this->_allow_get_array = (config_item('allow_get_array') !== FALSE);
$this->_enable_xss = (config_item('global_xss_filtering') === TRUE);
$this->_enable_csrf = (config_item('csrf_protection') === TRUE);
$this->_standardize_newlines = (bool) config_item('standardize_newlines');
$this->security =& load_class('Security', 'core');
// Do we need the UTF-8 class?
if (UTF8_ENABLED === TRUE)
{
$this->uni =& load_class('Utf8', 'core');
}
// Sanitize global arrays
$this->_sanitize_globals();
// CSRF Protection check
if ($this->_enable_csrf === TRUE && ! is_cli())
{
$this->security->csrf_verify();
}
$this->security = $security;
log_message('info', 'Input Class Initialized');
}
@@ -174,10 +122,8 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = NULL)
protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = FALSE)
{
is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
// If $index is NULL, it means that the whole $array is requested
isset($index) OR $index = array_keys($array);
@@ -237,7 +183,7 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
public function get($index = NULL, $xss_clean = NULL)
public function get($index = NULL, $xss_clean = FALSE)
{
return $this->_fetch_from_array($_GET, $index, $xss_clean);
}
@@ -251,7 +197,7 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
public function post($index = NULL, $xss_clean = NULL)
public function post($index = NULL, $xss_clean = FALSE)
{
return $this->_fetch_from_array($_POST, $index, $xss_clean);
}
@@ -265,11 +211,10 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
public function post_get($index, $xss_clean = NULL)
public function post_get($index, $xss_clean = FALSE)
{
return isset($_POST[$index])
? $this->post($index, $xss_clean)
: $this->get($index, $xss_clean);
$output = $this->post($index, $xss_clean);
return isset($output) ? $output : $this->get($index, $xss_clean);
}
// --------------------------------------------------------------------
@@ -281,11 +226,10 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
public function get_post($index, $xss_clean = NULL)
public function get_post($index, $xss_clean = FALSE)
{
return isset($_GET[$index])
? $this->get($index, $xss_clean)
: $this->post($index, $xss_clean);
$output = $this->get($index, $xss_clean);
return isset($output) ? $output : $this->post($index, $xss_clean);
}
// --------------------------------------------------------------------
@@ -297,7 +241,7 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
public function cookie($index = NULL, $xss_clean = NULL)
public function cookie($index = NULL, $xss_clean = FALSE)
{
return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
}
@@ -311,7 +255,7 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
public function server($index, $xss_clean = NULL)
public function server($index, $xss_clean = FALSE)
{
return $this->_fetch_from_array($_SERVER, $index, $xss_clean);
}
@@ -327,7 +271,7 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
public function input_stream($index = NULL, $xss_clean = NULL)
public function input_stream($index = NULL, $xss_clean = FALSE)
{
// Prior to PHP 5.6, the input stream can only be read once,
// so we'll need to check if we have already done that first.
@@ -357,14 +301,15 @@ class CI_Input {
* @param string $prefix Cookie name prefix
* @param bool $secure Whether to only transfer cookies via SSL
* @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript)
* @param string $samesite SameSite attribute
* @return void
*/
public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL)
public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL, $samesite = NULL)
{
if (is_array($name))
{
// always leave 'name' in last place, as the loop will break otherwise, due to $$item
foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name') as $item)
foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'samesite', 'name') as $item)
{
if (isset($name[$item]))
{
@@ -396,16 +341,56 @@ class CI_Input {
? (bool) config_item('cookie_httponly')
: (bool) $httponly;
if ( ! is_numeric($expire))
if ( ! is_numeric($expire) OR $expire < 0)
{
$expire = time() - 86500;
$expire = 1;
}
else
{
$expire = ($expire > 0) ? time() + $expire : 0;
}
setcookie($prefix.$name, $value, $expire, $path, $domain, $secure, $httponly);
isset($samesite) OR $samesite = config_item('cookie_samesite');
if (isset($samesite))
{
$samesite = ucfirst(strtolower($samesite));
in_array($samesite, array('Lax', 'Strict', 'None'), TRUE) OR $samesite = 'Lax';
}
else
{
$samesite = 'Lax';
}
if ($samesite === 'None' && ! $secure)
{
log_message('error', $name.' cookie sent with SameSite=None, but without Secure attribute.');
}
if ( ! is_php('7.3'))
{
$maxage = $expire - time();
if ($maxage < 1)
{
$maxage = 0;
}
$cookie_header = 'Set-Cookie: '.$prefix.$name.'='.rawurlencode($value);
$cookie_header .= ($expire === 0 ? '' : '; Expires='.gmdate('D, d-M-Y H:i:s T', $expire)).'; Max-Age='.$maxage;
$cookie_header .= '; Path='.$path.($domain !== '' ? '; Domain='.$domain : '');
$cookie_header .= ($secure ? '; Secure' : '').($httponly ? '; HttpOnly' : '').'; SameSite='.$samesite;
header($cookie_header);
return;
}
$setcookie_options = array(
'expires' => $expire,
'path' => $path,
'domain' => $domain,
'secure' => $secure,
'httponly' => $httponly,
'samesite' => $samesite,
);
setcookie($prefix.$name, $value, $setcookie_options);
}
// --------------------------------------------------------------------
@@ -565,7 +550,7 @@ class CI_Input {
$which = FILTER_FLAG_IPV6;
break;
default:
$which = NULL;
$which = 0;
break;
}
@@ -579,174 +564,13 @@ class CI_Input {
*
* @return string|null User Agent string or NULL if it doesn't exist
*/
public function user_agent($xss_clean = NULL)
public function user_agent($xss_clean = FALSE)
{
return $this->_fetch_from_array($_SERVER, 'HTTP_USER_AGENT', $xss_clean);
}
// --------------------------------------------------------------------
/**
* Sanitize Globals
*
* Internal method serving for the following purposes:
*
* - Unsets $_GET data, if query strings are not enabled
* - Cleans POST, COOKIE and SERVER data
* - Standardizes newline characters to PHP_EOL
*
* @return void
*/
protected function _sanitize_globals()
{
// Is $_GET data allowed? If not we'll set the $_GET to an empty array
if ($this->_allow_get_array === FALSE)
{
$_GET = array();
}
elseif (is_array($_GET))
{
foreach ($_GET as $key => $val)
{
$_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
}
}
// Clean $_POST Data
if (is_array($_POST))
{
foreach ($_POST as $key => $val)
{
$_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
}
}
// Clean $_COOKIE Data
if (is_array($_COOKIE))
{
// Also get rid of specially treated cookies that might be set by a server
// or silly application, that are of no use to a CI application anyway
// but that when present will trip our 'Disallowed Key Characters' alarm
// http://www.ietf.org/rfc/rfc2109.txt
// note that the key names below are single quoted strings, and are not PHP variables
unset(
$_COOKIE['$Version'],
$_COOKIE['$Path'],
$_COOKIE['$Domain']
);
foreach ($_COOKIE as $key => $val)
{
if (($cookie_key = $this->_clean_input_keys($key)) !== FALSE)
{
$_COOKIE[$cookie_key] = $this->_clean_input_data($val);
}
else
{
unset($_COOKIE[$key]);
}
}
}
// Sanitize PHP_SELF
$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
log_message('debug', 'Global POST, GET and COOKIE data sanitized');
}
// --------------------------------------------------------------------
/**
* Clean Input Data
*
* Internal method that aids in escaping data and
* standardizing newline characters to PHP_EOL.
*
* @param string|string[] $str Input string(s)
* @return string
*/
protected function _clean_input_data($str)
{
if (is_array($str))
{
$new_array = array();
foreach (array_keys($str) as $key)
{
$new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($str[$key]);
}
return $new_array;
}
/* We strip slashes if magic quotes is on to keep things consistent
NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and
it will probably not exist in future versions at all.
*/
if ( ! is_php('5.4') && get_magic_quotes_gpc())
{
$str = stripslashes($str);
}
// Clean UTF-8 if supported
if (UTF8_ENABLED === TRUE)
{
$str = $this->uni->clean_string($str);
}
// Remove control characters
$str = remove_invisible_characters($str, FALSE);
// Standardize newlines if needed
if ($this->_standardize_newlines === TRUE)
{
return preg_replace('/(?:\r\n|[\r\n])/', PHP_EOL, $str);
}
return $str;
}
// --------------------------------------------------------------------
/**
* Clean Keys
*
* Internal method that helps to prevent malicious users
* from trying to exploit keys we make sure that keys are
* only named with alpha-numeric text and a few other items.
*
* @param string $str Input string
* @param bool $fatal Whether to terminate script exection
* or to return FALSE if an invalid
* key is encountered
* @return string|bool
*/
protected function _clean_input_keys($str, $fatal = TRUE)
{
if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str))
{
if ($fatal === TRUE)
{
return FALSE;
}
else
{
set_status_header(503);
echo 'Disallowed Key Characters.';
exit(7); // EXIT_USER_INPUT
}
}
// Clean UTF-8 if supported
if (UTF8_ENABLED === TRUE)
{
return $this->uni->clean_string($str);
}
return $str;
}
// --------------------------------------------------------------------
/**
* Request Headers
*
@@ -844,6 +668,7 @@ class CI_Input {
* Test to see if a request was made from the command line.
*
* @deprecated 3.0.0 Use is_cli() instead
* @see is_cli()
* @return bool
*/
public function is_cli_request()