From 60056deb9390bc53c0daebb5f8a58feb3d2949b3 Mon Sep 17 00:00:00 2001 From: Nick Liu Date: Wed, 31 Oct 2018 07:27:38 -0500 Subject: [PATCH 1/5] Support for namespaced classes; added e_shims e_shims is an e107 v2-compatible class for the first namespaced core class, e107\Shims\All. e107\Shims\All is built from the e107\Shims\InternalShims trait. e107\Shims\InternalShims currently implements a resilient replacement for the PHP internal readfile(), which is needed by issue #3528. As for how the new namespaced classes are handled, the e107 class (e107_handlers/e107_class.php) has an updated e107::autoload() which detects namespaced classes and goes to e107::autoload_namespaced(). Namespaced classes handled by e107 are in the \e107 top-level namespace, and all sub-levels match directory paths under e_HANDLER. --- e107_handlers/Shims/InternalShims.php | 63 ++++++++++++++++++++++++ e107_handlers/Shims/e_shims.php | 31 ++++++++++++ e107_handlers/e107_class.php | 70 +++++++++++++++++++-------- 3 files changed, 144 insertions(+), 20 deletions(-) create mode 100644 e107_handlers/Shims/InternalShims.php create mode 100644 e107_handlers/Shims/e_shims.php diff --git a/e107_handlers/Shims/InternalShims.php b/e107_handlers/Shims/InternalShims.php new file mode 100644 index 000000000..eb9cae7be --- /dev/null +++ b/e107_handlers/Shims/InternalShims.php @@ -0,0 +1,63 @@ + '{e_HANDLER}shortcode_handler.php', 'e_plugin' => '{e_HANDLER}plugin_class.php', 'e_ranks' => '{e_HANDLER}e_ranks_class.php', + 'e_shims' => '{e_HANDLER}Shims/e_shims.php', 'e_shortcode' => '{e_HANDLER}shortcode_handler.php', 'e_system_user' => '{e_HANDLER}user_model.php', 'e_theme' => '{e_HANDLER}theme_handler.php', @@ -4613,31 +4614,31 @@ class e107 { $_data = self::getSession()->get('__sessionBrowserCache'); if(!is_array($_data)) $_data = array(); - + if(null === $set) { return in_array(e_REQUEST_URI, $_data); } - + // remove e_REQUEST_URI from the set if(false === $set) { $check = array_search(e_REQUEST_URI, $_data); - if(false !== $check) + if(false !== $check) { unset($_data[$check]); self::getSession()->set('__sessionBrowserCache', $_data); return; } } - + if(true === $set) { $set = e_REQUEST_URI; } - + if(empty($set) || !is_string($set) || in_array($set, $_data)) return; - + $_data[] = $set; self::getSession()->set('__sessionBrowserCache', array_unique($_data)); } @@ -4669,7 +4670,7 @@ class e107 * If $do_return, will always return with ban status - TRUE for OK, FALSE for banned. * If return permitted, will never display a message for a banned user; otherwise will display any message then exit * FIXME - moved to ban helper, replace all calls - * + * * * @param string $query * @param boolean $show_error @@ -4720,11 +4721,11 @@ class e107 * @param string $div divider * @return string encoded IP */ - + public function ipEncode($ip, $div = ':') { return self::getIPHandler()->ipEncode($ip); - } + } /** * Takes an encoded IP address - returns a displayable one @@ -4833,14 +4834,14 @@ class e107 { return spl_autoload_register($function); } - - foreach ($registered as $r) + + foreach ($registered as $r) { spl_autoload_unregister($r); } - + $result = spl_autoload_register($function); - foreach ($registered as $r) + foreach ($registered as $r) { if(!spl_autoload_register($r)) $result = false; } @@ -4849,7 +4850,7 @@ class e107 /** * Former __autoload, generic core autoload logic - * + * * Magic class autoload. * We are raising plugin structure standard here - plugin auto-loading works ONLY if * classes live inside 'includes' folder. @@ -4886,6 +4887,14 @@ class e107 { return; } + + // Detect namespaced class + if (strpos($className, '\\') !== false) + { + self::autoload_namespaced($className); + return; + } + $tmp = explode('_', $className); //echo 'autoloding...'.$className.'
'; @@ -4894,7 +4903,7 @@ class e107 case 'plugin': // plugin handlers/shortcode batches array_shift($tmp); // remove 'plugin' $end = array_pop($tmp); // check for 'shortcodes' end phrase - + if (!isset($tmp[0]) || !$tmp[0]) { if($end) @@ -4905,7 +4914,7 @@ class e107 } return; // In case we get an empty class part } - + // Currently only batches inside shortcodes/ folder are auto-detected, // read the todo for e_shortcode.php related problems if('shortcodes' == $end) @@ -4919,13 +4928,13 @@ class e107 { $tmp[] = $end; // not a shortcode batch - append the end phrase again } - + // Handler check $tmp[0] .= '/includes'; //folder 'includes' is not part of the class name $filename = e_PLUGIN.implode('/', $tmp).'.php'; //TODO add debug screen Auto-loaded classes - ['plugin: '.$filename.' - '.$className]; break; - + default: //core libraries, core shortcode batches // core SC batch check $end = array_pop($tmp); @@ -4934,12 +4943,12 @@ class e107 $filename = e_CORE.'shortcodes/batch/'.$className.'.php'; // core shortcode batch break; } - + $filename = self::getHandlerPath($className, true); //TODO add debug screen Auto-loaded classes - ['core: '.$filename.' - '.$className]; break; } - + if(!empty($filename) && is_file($filename)) // Test with chatbox_menu { // autoload doesn't REQUIRE files, because this will break things like call_user_func() @@ -4947,6 +4956,27 @@ class e107 } } + /** + * Autoloading logic for namespaced classes + * + * @param $className + * @return void + */ + private static function autoload_namespaced($className) + { + $levels = explode('\\', $className); + + // Guard against classes that are not ours + if ($levels[0] != 'e107') return; + + $levels[0] = e_HANDLER; + $classPath = implode('/', $levels).'.php'; + if (is_file($classPath) && is_readable($classPath)) + { + include($classPath); + } + } + public function __get($name) { switch ($name) From ee1a5b1278a4c6e47f93800d29b0b58504fd232c Mon Sep 17 00:00:00 2001 From: Nick Liu Date: Wed, 31 Oct 2018 07:38:32 -0500 Subject: [PATCH 2/5] Replaced all direct readfile()s with shim Fixes: #3528 --- e107_handlers/resize_handler.php | 2 +- thumb.php | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/e107_handlers/resize_handler.php b/e107_handlers/resize_handler.php index 0448d4d48..d550939ec 100644 --- a/e107_handlers/resize_handler.php +++ b/e107_handlers/resize_handler.php @@ -111,7 +111,7 @@ function resize_image($source_file, $destination_file, $type = "upload", $model { if (($result = mimeFromFilename($source_file)) === FALSE) { return FALSE; } header($result); - if (@readfile($source_file) === FALSE) { return FALSE; } + if (e_shims::readfile($source_file) === FALSE) { return FALSE; } } else { diff --git a/thumb.php b/thumb.php index b863bce59..07201ad98 100755 --- a/thumb.php +++ b/thumb.php @@ -156,6 +156,7 @@ class e_thumbpage @require($tmp.DIRECTORY_SEPARATOR.'core_functions.php'); //e107 class @require($tmp.DIRECTORY_SEPARATOR.'e107_class.php'); + e107::autoload_register(array('e107', 'autoload')); $e107_paths = compact( 'ADMIN_DIRECTORY', @@ -324,11 +325,12 @@ class e_thumbpage $fname = e107::getParser()->thumbCacheFile($this->_src_path, $options); - if(($this->_cache === true) && is_file(e_CACHE_IMAGE.$fname) && is_readable(e_CACHE_IMAGE.$fname) && ($this->_debug !== true)) + $cache_filename = e_CACHE_IMAGE . $fname; + if(($this->_cache === true) && is_file($cache_filename) && is_readable($cache_filename) && ($this->_debug !== true)) { - $thumbnfo['lmodified'] = filemtime(e_CACHE_IMAGE.$fname); - $thumbnfo['md5s'] = md5_file(e_CACHE_IMAGE.$fname); - $thumbnfo['fsize'] = filesize(e_CACHE_IMAGE.$fname); + $thumbnfo['lmodified'] = filemtime($cache_filename); + $thumbnfo['md5s'] = md5_file($cache_filename); + $thumbnfo['fsize'] = filesize($cache_filename); // Send required headers if($this->_debug !== true) @@ -349,9 +351,7 @@ class e_thumbpage // Send required headers //$this->sendHeaders($thumbnfo); - - - @readfile(e_CACHE_IMAGE.$fname); + e_shims::readfile($cache_filename); //$bench->end()->logResult('thumb.php', $_GET['src'].' - retrieve cache'); exit; @@ -443,7 +443,7 @@ class e_thumbpage //exit; // set cache - $thumb->save(e_CACHE_IMAGE.$fname); + $thumb->save($cache_filename); From 4c6828be9301959b45d235ace7189fd9e0c5145a Mon Sep 17 00:00:00 2001 From: Nick Liu Date: Wed, 31 Oct 2018 08:22:14 -0500 Subject: [PATCH 3/5] Moved autoload responsibility to e107_class.php Instead of every independently operating client code figuring out its own autoload policies, the e107 class file e107_class.php now takes care of autoloading. Any client that uses the e107 class will automatically benefit from autoloading for e107. This cuts down on potential code duplication, and e107::getSingleton() is no longer tied to trying to figure out the class path. This commit REMOVES support for the unused constant flag E107_DISABLE_AUTOLOAD introduced in bdef2707b4cafe34e5485d8733138a0e87f43a39 and the unused autoload code introduced in f4cee9289087c0119bc6797f7dfb7792a62b0be3. --- class2.php | 67 ------------------------------------ e107_handlers/e107_class.php | 9 +++++ install.php | 12 ------- thumb.php | 1 - 4 files changed, 9 insertions(+), 80 deletions(-) diff --git a/class2.php b/class2.php index edfd97aaa..a38c3966b 100755 --- a/class2.php +++ b/class2.php @@ -261,73 +261,6 @@ $e107 = e107::getInstance()->initCore($e107_paths, e_ROOT, $sql_info, varset($E1 e107::getSingleton('eIPHandler'); // This auto-handles bans etc - -### NEW Register Autoload - do it asap -if(!function_exists('spl_autoload_register')) -{ - // PHP >= 5.1.2 required - die('Fatal exception - spl_autoload_* required.'); -} - - -// allow disable of autoloading - may be removed as e107::autoload_register() is flexible enough -if(!defset('E107_DISABLE_AUTOLOAD', false)) -{ - /** - * Generic autoloader. (didn't work while in e107_class.php) - * @example if your plugin calls 'use Xxxxx\Yyyyy\Zzzzz;' it will attempt to load: ./vendor/Xxxxx/Yyyyy/Zzzzz.php - */ - function autoloadPsr0($className) - { - $className = str_replace("_", "\\", $className); - $className = ltrim($className, '\\'); - $fileName = ''; - $namespace = ''; - - if ($lastNsPos = strripos($className, '\\')) - { - $namespace = substr($className, 0, $lastNsPos); - $className = substr($className, $lastNsPos + 1); - $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; - } - - $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; - - $fullPath = 'vendor'. DIRECTORY_SEPARATOR . $fileName; - - if(file_exists($fullPath)) - { - e107_require_once($fullPath); - } - else - { - return false; - } - - } - - e107::autoload_register(array('e107', 'autoload')); -// e107::autoload_register('autoloadPsr0'); // Generic 'use xxxx\yyyy\zzzz;' fix/solution for plugin developers. - -} - - function genericAutoload($className) - { - $className = str_replace("_", "\\", $className); - $className = ltrim($className, '\\'); - $fileName = ''; - $namespace = ''; - if ($lastNsPos = strripos($className, '\\')) - { - $namespace = substr($className, 0, $lastNsPos); - $className = substr($className, $lastNsPos + 1); - $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; - } - $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; - - e107_require_once($fileName); - } - /** * NEW - system security levels * Could be overridden by e107_config.php OR $CLASS2_INCLUDE script (if not set earlier) diff --git a/e107_handlers/e107_class.php b/e107_handlers/e107_class.php index 7119e5f30..74d60343f 100755 --- a/e107_handlers/e107_class.php +++ b/e107_handlers/e107_class.php @@ -4830,6 +4830,13 @@ class e107 */ public static function autoload_register($function, $prepend = false) { + ### NEW Register Autoload - do it asap + if(!function_exists('spl_autoload_register')) + { + // PHP >= 5.1.2 required + die_fatal_error('Fatal exception - spl_autoload_* required.'); + } + if(!$prepend || false === ($registered = spl_autoload_functions())) { return spl_autoload_register($function); @@ -5155,3 +5162,5 @@ class e107 } + +e107::autoload_register(array(e107::class, 'autoload')); \ No newline at end of file diff --git a/install.php b/install.php index 4f89a2c24..8074303af 100644 --- a/install.php +++ b/install.php @@ -163,18 +163,6 @@ if($e107->initInstall($e107_paths, $ebase, $override)===false) unset($e107_paths,$override,$ebase); - - -### NEW Register Autoload - do it asap -if(!function_exists('spl_autoload_register')) -{ - // PHP >= 5.1.2 required - die_fatal_error('Fatal exception - spl_autoload_* required.'); -} - -// register core autoload -e107::autoload_register(array('e107', 'autoload')); - // NEW - session handler require_once(e_HANDLER.'session_handler.php'); define('e_SECURITY_LEVEL', e_session::SECURITY_LEVEL_NONE); diff --git a/thumb.php b/thumb.php index 07201ad98..1fafa0d81 100755 --- a/thumb.php +++ b/thumb.php @@ -156,7 +156,6 @@ class e_thumbpage @require($tmp.DIRECTORY_SEPARATOR.'core_functions.php'); //e107 class @require($tmp.DIRECTORY_SEPARATOR.'e107_class.php'); - e107::autoload_register(array('e107', 'autoload')); $e107_paths = compact( 'ADMIN_DIRECTORY', From b2de51dd1b58b482169acaec87224b64efc4c2da Mon Sep 17 00:00:00 2001 From: Nick Liu Date: Wed, 31 Oct 2018 09:37:07 -0500 Subject: [PATCH 4/5] Split e_shims into correct files for autoloading --- e107_handlers/Shims/All.php | 17 +++++++++++++++++ e107_handlers/Shims/Internal.php | 17 +++++++++++++++++ e107_handlers/Shims/e_shims.php | 13 ------------- 3 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 e107_handlers/Shims/All.php create mode 100644 e107_handlers/Shims/Internal.php diff --git a/e107_handlers/Shims/All.php b/e107_handlers/Shims/All.php new file mode 100644 index 000000000..c49e68994 --- /dev/null +++ b/e107_handlers/Shims/All.php @@ -0,0 +1,17 @@ + Date: Wed, 31 Oct 2018 12:24:45 -0500 Subject: [PATCH 5/5] Renamed e_shims to eShims To follow @myovchev's convention like eHelper Per @CaMer0n --- e107_handlers/Shims/{e_shims.php => eShims.php} | 2 +- e107_handlers/e107_class.php | 2 +- e107_handlers/resize_handler.php | 2 +- thumb.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename e107_handlers/Shims/{e_shims.php => eShims.php} (88%) diff --git a/e107_handlers/Shims/e_shims.php b/e107_handlers/Shims/eShims.php similarity index 88% rename from e107_handlers/Shims/e_shims.php rename to e107_handlers/Shims/eShims.php index dcb2e9b8c..e840f9cca 100644 --- a/e107_handlers/Shims/e_shims.php +++ b/e107_handlers/Shims/eShims.php @@ -12,7 +12,7 @@ // e107 v2-style classes namespace { - class e_shims extends \e107\Shims\All + class eShims extends \e107\Shims\All { } } \ No newline at end of file diff --git a/e107_handlers/e107_class.php b/e107_handlers/e107_class.php index 74d60343f..28055aefb 100755 --- a/e107_handlers/e107_class.php +++ b/e107_handlers/e107_class.php @@ -203,7 +203,6 @@ class e107 'e_parse_shortcode' => '{e_HANDLER}shortcode_handler.php', 'e_plugin' => '{e_HANDLER}plugin_class.php', 'e_ranks' => '{e_HANDLER}e_ranks_class.php', - 'e_shims' => '{e_HANDLER}Shims/e_shims.php', 'e_shortcode' => '{e_HANDLER}shortcode_handler.php', 'e_system_user' => '{e_HANDLER}user_model.php', 'e_theme' => '{e_HANDLER}theme_handler.php', @@ -227,6 +226,7 @@ class e107 'eRequest' => '{e_HANDLER}application.php', 'eResponse' => '{e_HANDLER}application.php', 'eRouter' => '{e_HANDLER}application.php', + 'eShims' => '{e_HANDLER}Shims/eShims.php', 'eUrl' => '{e_HANDLER}e107Url.php', 'eUrlConfig' => '{e_HANDLER}application.php', 'eUrlRule' => '{e_HANDLER}application.php', diff --git a/e107_handlers/resize_handler.php b/e107_handlers/resize_handler.php index d550939ec..61685374c 100644 --- a/e107_handlers/resize_handler.php +++ b/e107_handlers/resize_handler.php @@ -111,7 +111,7 @@ function resize_image($source_file, $destination_file, $type = "upload", $model { if (($result = mimeFromFilename($source_file)) === FALSE) { return FALSE; } header($result); - if (e_shims::readfile($source_file) === FALSE) { return FALSE; } + if (eShims::readfile($source_file) === FALSE) { return FALSE; } } else { diff --git a/thumb.php b/thumb.php index 1fafa0d81..ea0bd3eba 100755 --- a/thumb.php +++ b/thumb.php @@ -350,7 +350,7 @@ class e_thumbpage // Send required headers //$this->sendHeaders($thumbnfo); - e_shims::readfile($cache_filename); + eShims::readfile($cache_filename); //$bench->end()->logResult('thumb.php', $_GET['src'].' - retrieve cache'); exit;