diff --git a/application/config/autoload.php b/application/config/autoload.php index bd12cb688bd6..ed2657ce709b 100644 --- a/application/config/autoload.php +++ b/application/config/autoload.php @@ -83,6 +83,7 @@ public function __construct() 'CodeIgniter\Log\Logger' => BASEPATH.'Log/Logger.php', 'CodeIgniter\View\RenderableInterface' => BASEPATH.'View/RenderableInterface.php', 'CodeIgniter\View\View' => BASEPATH.'View/View.php', + 'Zend\Escaper\Escaper' => BASEPATH.'View/Escaper.php', 'PSR\Log\LoggerInterface' => BASEPATH.'Log/LoggerInterface.php', 'PSR\Log\LogLevel' => BASEPATH.'Log/LogLevel.php', 'PSR\Log\LoggerAwareInterface' => BASEPATH.'Log/LoggerAwareInterface.php', diff --git a/system/Common.php b/system/Common.php index cf88d9a142a4..201e879d5210 100644 --- a/system/Common.php +++ b/system/Common.php @@ -8,7 +8,7 @@ * @category Common Functions */ -if (! function_exists('log_message')) +if ( ! function_exists('log_message')) { /** * A convenience/compatibility method for logging events through @@ -30,16 +30,17 @@ * * @return mixed */ - function log_message(string $level, $message, array $context=[]) + function log_message(string $level, $message, array $context = []) { // @todo Don't create a new class each time! - return \App\Config\Services::logger()->log($level, $message, $context); + return \App\Config\Services::logger() + ->log($level, $message, $context); } } //-------------------------------------------------------------------- -if (! function_exists('view')) +if ( ! function_exists('view')) { /** * Grabs the current RenderableInterface-compatible class @@ -56,7 +57,7 @@ function log_message(string $level, $message, array $context=[]) * * @return string */ - function view(string $name, array $data=[], array $options=[]) + function view(string $name, array $data = [], array $options = []) { /** * @var CodeIgniter\View\View $renderer @@ -64,7 +65,72 @@ function view(string $name, array $data=[], array $options=[]) $renderer = \App\Config\Services::renderer(); return $renderer->setData($data, 'raw') - ->render($name, $options); + ->render($name, $options); + } +} + +//-------------------------------------------------------------------- + +if ( ! function_exists('esc')) +{ + /** + * Performs simple auto-escaping of data for security reasons. + * Might consider making this more complex at a later date. + * + * If $data is a string, then it simply escapes and returns it. + * If $data is an array, then it loops over it, escaping each + * 'value' of the key/value pairs. + * + * Valid context values: html, js, css, url, attr, raw, null + * + * @param string|array $data + * @param string $context + * @param string $encoding + * + * @return $data + */ + function esc($data, $context = 'html', $encoding=null) + { + if (is_array($data)) + { + foreach ($data as $key => &$value) + { + $value = esc($value, $context); + } + } + + if (is_string($data)) + { + $context = strtolower($context); + + // Provide a way to NOT escape data since + // this could be called automatically by + // the View library. + if (empty($context) || $context == 'raw') + { + return $data; + } + + if ( ! in_array($context, ['html', 'js', 'css', 'url', 'attr'])) + { + throw new \InvalidArgumentException('Invalid escape context provided.'); + } + + if ($context == 'attr') + { + $method = 'escapeHtmlAttr'; + } + else + { + $method = 'escape'.ucfirst($context); + } + + $escaper = new \Zend\Escaper\Escaper($encoding); + + $data = $escaper->$method($data); + } + + return $data; } } @@ -78,7 +144,7 @@ function view(string $name, array $data=[], array $options=[]) * * Test to see if a request was made from the command line. * - * @return bool + * @return bool */ function is_cli() { diff --git a/system/View/View.php b/system/View/View.php index 937eb71552b2..b10b9ecfa367 100644 --- a/system/View/View.php +++ b/system/View/View.php @@ -1,7 +1,5 @@