Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fatal error: Call to undefined method JLoader::applyAliasFor() in .../public/libraries/ClassLoader.php on line 45 #6224

Closed
LTIOfficial opened this issue Feb 27, 2015 · 14 comments

Comments

@LTIOfficial
Copy link

While using the back-end installer to update from J3.3.6 to 3.4, both front and back-ends now show the following error:

Fatal error: Call to undefined method JLoader::applyAliasFor() in .../public/libraries/ClassLoader.php on line 45

All extensions were fully updated prior to the Joomla update attempt, and the update procedure went directly to the error message

It appears that I am not the only updater with this result:
http://forum.joomla.org/viewtopic.php?f=707&t=874775&p=3272296#p3271767

System information (as much as possible)

Our LAMP server is Centos 5.11, running php 5.4.36, mysql 5.5.40 & apache 2.2.3.

@orware
Copy link
Contributor

orware commented Feb 27, 2015

Hi LTI,

Quick question...do you have any of the Akeeba Products installed on your site?

That ClassLoader.php file doesn't seem to be a standard file that comes with Joomla, and in the forum article you linked to the user included the file contents and the Akeeba developer's name is mentioned in the comments "Nicholas Dionysopoulos" so my thought at the moment is that the file is being added by an extension like Akeeba Backup.

Overall though it looks like the code in that file would be correct if your site had been fully updated to 3.4 (since the "applyAliasFor" method was added then (I don't see it in the 3.3.6 version of Joomla's loader.php file).

It almost feels like the new loader.php file didn't make it in yet (there was an error when you tried to update) OR another possibility is that since you updated your extensions beforehand, when you tried to do the update to 3.4 the new Akeeba Backup code was expecting the 3.4 version of the loader file and was in fact calling a method that doesn't exist yet (because the update to 3.4 hadn't completed yet).

On a new 3.3.6 installation on my end, running the upgrade completed successfully and there aren't any issues, so I'm pretty sure this is due to Akeeba Backup (you can probably copy over the 3.4. Update files to fix things): https://github.com/joomla/joomla-cms/releases/download/3.4.0/Joomla_3.4.0-Stable-Update_Package.zip


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@mbabker
Copy link
Contributor

mbabker commented Feb 27, 2015

@LTIOfficial
Copy link
Author

If relevant, the site was originally developed under an early J2.5.x, and migrated to J3.3.0 I believe, about three months ago. It has since been updated two or three times to reach 3.3.6 without issues.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@LTIOfficial
Copy link
Author

I do have Akeeba extensions installed (one of which was updated just prior to my running the J update), but this error is pointing to a Joomla file, as mbabker mentioned. The contents of the file within the error are below, and I'm guessing that the other poster simply found the wrong ClassLoader file.

findFile($class)) { includeFile($file); ``` \JLoader::applyAliasFor($class); return true; ``` } } }
This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@LTIOfficial
Copy link
Author

I now see where you found Nicholas' name in the file, but it still appears to be a Joomla-produced file where, perhaps Nicholas contributed some of the code.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@orware
Copy link
Contributor

orware commented Feb 28, 2015

@mbabker Thanks, I overlooked the ClassLoader.php file when I opened up the 3.4 ZIP on my end (I had directories sorted in descending order and my eyes stopped when I saw loader.php file).

In that case though, since it doesn't seem like it would have anything to do with having an Akeeba product installed, I wonder what the issue would be in this case?

@LTIOfficial Can you confirm whether or not the loader.php file on your end contains the applyAliasFor() function? (It should be listed on line 534 of the file...if it's not there, then it would indicate you still have the 3.3.6 version of the file on your site...if it is there, then it might indicate that this is more of a coding issue).


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@LTIOfficial
Copy link
Author

Line 534 shows:

protected function __construct () {
    clearstatcache();
    if (is_readable(_JALOADER_CLASS_CACHE) AND filemtime(_JALOADER_CLASS_CACHE) > (time() - 3600*24)) $this->discovered = unserialize(file_get_contents (_JALOADER_CLASS_CACHE));
}

And the top of the file includes the following, implying that it is an older version of the file.

@copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.

On another note, the server shows it with today's date, at the time I performed the update attempt. All other updated files show Feb 24th as their date.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@LTIOfficial
Copy link
Author

Another note: This loader file is twice the size of the one in the J3.4 upgrade download tar. It's contents are below:

' : "\n"; foreach(debug_backtrace() as $back) { if (isset($back['file']) AND $back['file']) { $html .= $newline.$back['file'].':'.$back['line']; } } if ($error) $counter++; if (1000 < $counter) { echo $html; die ('Program killed - Probably looping'); } return $html; } ``` } class aliro { private static $instance = null; ``` public $installed = true; private $timer = 0; private function __construct () { $this->timer = new aliroProfiler(); } public function getElapsed () { return $this->timer->getElapsed(); } public static function convertClass ($object, $toclass) { if (is_object($object)) { $quotedfrom = '"'.get_class($object).'"'; $ser = serialize($object); $ser = substr_replace($ser, "\"$toclass\"", strpos($ser, $quotedfrom), strlen($quotedfrom)); return unserialize($ser); } return null; } public static function getInstance () { return self::$instance instanceof self ? self::$instance : self::$instance = new self(); } ``` } class aliroCore { ``` private static $instance = null; private $config = array(); protected function __construct () { // Set time zone to UTC in case we have not yet installed //if (function_exists('date_default_timezone_set')) date_default_timezone_set('UTC'); //$this->config = aliroCore::getConfigData('configuration.php'); //if (function_exists('date_default_timezone_set') AND !empty($this->config['timezone'])) { //date_default_timezone_set($this->config['timezone']); //} } public static function getInstance () { return is_object(self::$instance) ? self::$instance : (self::$instance = new self()); } public function getCfg ($name) { if ('cachetype' == $name) return 'Disk'; return JFactory::getApplication()->getCfg($name); } public static function getConfigData ($configname) { if ('corecredentials.php' == $configname OR 'credentials.php' == $configname) { $config = self::getInstance(); $credentials['dbhost'] = $config->getCfg('host'); $credentials['dbusername'] = $config->getCfg('user'); $credentials['dbpassword'] = $config->getCfg('password'); $credentials['dbname'] = $config->getCfg('db'); $credentials['dbprefix'] = $config->getCfg('dbprefix'); return $credentials; } } public static function set () { } public function fixlanguage () {} ``` } class aliroRequest { ``` public static function getInstance () { return cmsapiInterface::getParticular('bot_jaliro'); } ``` } /** - Static class to handle loading of libraries. * - @Package Joomla.Platform - @SInCE 11.1 _/ abstract class JLoader { /_* - Container for already imported library paths. * - @var array - @SInCE 11.1 */ protected static $classes = array(); /** - Container for already imported library paths. * - @var array - @SInCE 11.1 */ protected static $imported = array(); /** - Container for registered library class prefixes and path lookups. * - @var array - @SInCE 12.1 */ protected static $prefixes = array(); /** - Holds proxy classes and the class names the proxy. * - @var array - @SInCE 3.2 */ protected static $classAliases = array(); /** - Container for namespace => path map. * - @var array - @SInCE 12.3 */ protected static $namespaces = array(); /** - Method to discover classes of a given type in a given path. * - @param string $classPrefix The class name prefix to use for discovery. - @param string $parentPath Full path to the parent folder for the classes to discover. - @param boolean $force True to overwrite the autoload path value for the class if it already exists. - @param boolean $recurse Recurse through all child directories as well as the parent path. * - @return void * - @SInCE 11.1 */ public static function discover($classPrefix, $parentPath, $force = true, $recurse = false) { JALoader::getInstance()->fileIterator('jaDiscover', $parentPath, $recurse, $classPrefix, $force); } /** - Method to get the list of registered classes and their respective file paths for the autoloader. * - @return array The array of class => path values for the autoloader. * - @SInCE 11.1 */ public static function getClassList() { return JALoader::getInstance()->jaGetClassList(); } /** - Loads a class from specified directories. * - @param string $key The class name to look for (dot notation). - @param string $base Search this directory for the class. * - @return boolean True on success. * - @SInCE 11.1 */ public static function import($key, $base = null) { return JALoader::getInstance()->jaImport($key, $base); } /** - Load the file for a class. * - @param string $class The class to be loaded. * - @return boolean True on success * - @SInCE 11.1 */ public static function load($class) { return JALoader::getInstance()->jaLoad($class); } /** - Directly register a class to the autoload list. * - @param string $class The class name to register. - @param string $path Full path to the file that holds the class to register. - @param boolean $force True to overwrite the autoload path value for the class if it already exists. * - @return void * - @SInCE 11.1 */ public static function register($class, $path, $force = true) { JALoader::getInstance()->jaRegister($class, $path, $force); } /** - Register a class prefix with lookup path. This will allow developers to register library - packages with different class prefixes to the system autoloader. More than one lookup path - may be registered for the same class prefix, but if this method is called with the reset flag - set to true then any registered lookups for the given prefix will be overwritten with the current - lookup path. When loaded, prefix paths are searched in a "last in, first out" order. * - @param string $prefix The class prefix to register. - @param string $path Absolute file path to the library root where classes with the given prefix can be found. - @param boolean $reset True to reset the prefix with only the given lookup path. - @param boolean $prepend If true, push the path to the beginning of the prefix lookup paths array. * - @return void * - @throws RuntimeException * - @SInCE 12.1 */ public static function registerPrefix($prefix, $path, $reset = false, $prepend = false) { JALoader::getInstance()->jaRegisterPrefix($prefix, $path, $reset, $prepend); } /** - Offers the ability for "just in time" usage of `class_alias()`. - You cannot overwrite an existing alias. * - @param string $alias The alias name to register. - @param string $original The original class to alias. * - @return boolean True if registration was successful. False if the alias already exists. * - @SInCE 3.2 */ public static function registerAlias($alias, $original) { JALoader::getInstance()->jaRegisterAlias($alias, $original); } /** - Method to autoload classes that have been aliased using the registerAlias method. * - @param string $class The fully qualified class name to autoload. * - @return boolean True on success, false otherwise. * - @SInCE 3.2 */ public static function loadByAlias($class) { JALoader::getInstance()->jaLoadByAlias($class); } /** - Method to setup the autoloaders for the Joomla Platform. Since the SPL autoloaders are - called in a queue we will add our explicit, class-registration based loader first, then - fall back on the autoloader based on conventions. This will allow people to register a - class in a specific location and override platform libraries as was previously possible. * - @return void * - @SInCE 11.3 */ public static function setup ($enablePsr = true, $enablePrefixes = true, $enableClasses = true) { JALoader::getInstance()->jaSetup($enablePsr, $enablePrefixes, $enableClasses); } /** - Method to get the list of registered namespaces. * - @return array The array of namespace => path values for the autoloader. * - @SInCE 12.3 */ public static function getNamespaces() { return self::$namespaces; } /** - Register a namespace to the autoloader. When loaded, namespace paths are searched in a "last in, first out" order. * - @param string $namespace A case sensitive Namespace to register. - @param string $path A case sensitive absolute file path to the library root where classes of the given namespace can be found. - @param boolean $reset True to reset the namespace with only the given lookup path. - @param boolean $prepend If true, push the path to the beginning of the namespace lookup paths array. * - @return void * - @throws RuntimeException * - @SInCE 12.3 */ public static function registerNamespace($namespace, $path, $reset = false, $prepend = false) { JALoader::getInstance()->jaRegisterNamespace($namespace, $path, $reset, $prepend); } /** - Method to autoload classes that are namespaced to the PSR-0 standard. * - @param string $class The fully qualified class name to autoload. * - @return boolean True on success, false otherwise. * - @SInCE 13.1 */ public static function loadByPsr0 ($class) { JALoader::getInstance()->jaLoadByPsr0($class); } } /** - More civilised class to handle loading of libraries. * - @Package Joomla.Platform - @SInCE 11.1 */ final class JALoader extends JLoader { ``` /** * Container for singleton instance. * * @var object * @SInCE 11.1 */ protected static $instance = null; /** * Container for auto discovered classes. * * @var array * @SInCE Jaliro */ protected $discovered = array(); /** * List of Jaliro libraries * * @var array * @SInCE Jaliro * Must be kept the same as the declaration in the Jaliro plugin */ public static $jalirolibs = array( 'aliro', 'cmsapi', 'extclasses' ); /** * Constructor. * * @SInCE 11.1 */ protected function __construct () { clearstatcache(); if (is_readable(_JALOADER_CLASS_CACHE) AND filemtime(_JALOADER_CLASS_CACHE) > (time() - 3600*24)) $this->discovered = unserialize(file_get_contents (_JALOADER_CLASS_CACHE)); } /** * Method to cache class location information * * @return null * * @SInCE 11.1 */ protected function saveToCache () { file_put_contents(_JALOADER_CLASS_CACHE, serialize($this->discovered)); } /** * Method to get singleton instance. * * @return object * * @SInCE 11.1 */ public static function getInstance () { return (self::$instance instanceof self) ? self::$instance : self::$instance = new self(); } /** * Method to discover classes of a given type in a given path. * * @param string $classPrefix The class name prefix to use for discovery. * @param string $parentPath Full path to the parent folder for the classes to discover. * @param boolean $force True to overwrite the autoload path value for the class if it already exists. * @param boolean $recurse Recurse through all child directories as well as the parent path. * * @return void * * @SInCE 11.1 */ public function jaDiscover ($file, $fileName, $classPrefix, $force = true) { // Get the class name and full path for each file. $class = strtolower($classPrefix . preg_replace('#\.php$#', '', $fileName)); // Register the class with the autoloader if not already registered or the force flag is set. if (empty(parent::$classes[$class]) || $force) { $this->jaRegister($class, $file->getPath() . '/' . $fileName); } } /** * Method to discover classes of a given type in a given path. * * @param string $parentPath Full path to the parent folder for the classes to discover. * @param boolean $recurse Recurse through all child directories as well as the parent path. * * @return void * * @SInCE 11.1 */ public function jaAutoDiscover ($parentPath, $recurse=true) { if (!isset($this->discovered[$parentPath])) { $this->fileIterator('jaAutoDiscoverFile', $parentPath, $recurse); $this->saveToCache(); } } public function jaClearDiscovery ($parentPath) { if (isset($this->discovered[$parentPath])) unset($this->discovered[$parentPath]); } public function jaAutoDiscoverFile ($file, $fileName, $parentPath) { $filedir = $file->getPath(); $tokens = @token_get_all(file_get_contents($filedir.'/'.$fileName)); //http://php.filearena.net/manual/en/function.token-get-all.php#79502 if (!empty($tokens)) foreach ($tokens as $key=>$token) { if (T_CLASS == $token[0]) { $classname = isset($tokens[$key+2][1]) ? $tokens[$key+2][1] : ''; $extends = (isset($tokens[$key+4][0]) AND T_EXTENDS == $tokens[$key+4][0] AND isset($tokens[$key+6][1])) ? $tokens[$key+6][1] : ''; if (isset($classes[$classname])) { if ($extends != $classes[$classname]) $classes[$classname] = ''; } else $classes[$classname] = $extends; } } if (!empty($classes)) { $filemap = ('.' == $filedir ? '' : $filedir.'/').basename($fileName); foreach ($classes as $classname=>$extends) { $this->discovered[$parentPath][strtolower($classname)]=array('path' => $filemap, 'extends' => $extends); } } unset($tokens); } /** * Method to iterate through PHP files in a directory - with or without recursion. * * @param callback $callback Callback to operate on each file. * @param string $parentPath Full path to the parent folder for the classes to discover. * @param boolean $recurse Recurse through all child directories as well as the parent path. * * @return void * * @SInCE 11.1 */ protected function fileIterator () { $args = func_get_args(); $callbackmethod = array_shift($args); $parentPath = array_shift($args); $recurse = count($args) ? array_shift($args) : true; if ('jaAutoDiscoverFile' == $callbackmethod) array_unshift($args, $parentPath); try { if ($recurse) { $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($parentPath), RecursiveIteratorIterator::SELF_FIRST ); } else { $iterator = new DirectoryIterator($parentPath); } foreach ($iterator as $file) { $fileName = $file->getFilename(); // Only load for php files. // Note: DirectoryIterator::getExtension only available PHP >= 5.3.6 if ($file->isFile() && substr($fileName, strrpos($fileName, '.') + 1) == 'php') { $fargs = $args; array_unshift($fargs, $fileName); array_unshift($fargs, $file); call_user_func_array(array($this, $callbackmethod), $fargs); } } } catch (UnexpectedValueException $e) { // Exception will be thrown if the path is not a directory. Ignore it. } } /** * Method to get the list of registered classes and their respective file paths for the autoloader. * * @return array The array of class => path values for the autoloader. * * @SInCE 11.1 */ public function jaGetClassList () { return parent::$classes; } /** * Loads a class from specified directories. * * @param string $key The class name to look for (dot notation). * @param string $base Search this directory for the class. * * @return boolean True on success. * * @SInCE 11.1 */ public function jaImport ($key, $base = null) { // Only import the library if not already attempted. if (!isset(parent::$imported[$key])) { // Setup some variables. $success = false; $parts = explode('.', $key); $class = array_pop($parts); $base = (!empty($base)) ? $base : __DIR__; $path = str_replace('.', DIRECTORY_SEPARATOR, $key); // Handle special case for helper classes. if ($class == 'helper') { $class = ucfirst(array_pop($parts)) . ucfirst($class); } // Standard class. else { $class = ucfirst($class); } // If we are importing a library from the Joomla namespace set the class to autoload. if (strpos($path, 'joomla') === 0) { // Since we are in the Joomla namespace prepend the classname with J. $class = 'J' . $class; // Only register the class for autoloading if the file exists. if (is_file($base . '/' . $path . '.php')) { parent::$classes[strtolower($class)] = $base . '/' . $path . '.php'; $success = true; } } /* * If we are not importing a library from the Joomla namespace directly include the * file since we cannot assert the file/folder naming conventions. */ else { // If the file exists attempt to include it. if (is_file($base . '/' . $path . '.php')) { $success = (bool) include_once $base . '/' . $path . '.php'; } } // Add the import key to the memory cache container. parent::$imported[$key] = $success; } return parent::$imported[$key]; } /** * Load the file for a class. * * @param string $class The class to be loaded. * * @return boolean True on success * * @SInCE 11.1 */ public function jaLoad ($class) { // Sanitize class name. $class = strtolower($class); // If the class already exists do nothing. if (class_exists($class, false)) { return true; } // If the class is registered include the file. if (isset(parent::$classes[$class])) { include_once parent::$classes[$class]; return true; } return false; } /** * Directly register a class to the autoload list. * * @param string $class The class name to register. * @param string $path Full path to the file that holds the class to register. * @param boolean $force True to overwrite the autoload path value for the class if it already exists. * * @return void * * @SInCE 11.1 */ public function jaRegister ($class, $path, $force = true) { // Sanitize class name. $class = strtolower($class); // Only attempt to register the class if the name and file exist. if (!empty($class) && is_readable($path)) { // Register the class with the autoloader if not already registered or the force flag is set. if (empty(parent::$classes[$class]) || $force) { parent::$classes[$class] = $path; } } } /** * Register a class prefix with lookup path. This will allow developers to register library * packages with different class prefixes to the system autoloader. More than one lookup path * may be registered for the same class prefix, but if this method is called with the reset flag * set to true then any registered lookups for the given prefix will be overwritten with the current * lookup path. When loaded, prefix paths are searched in a "last in, first out" order. * * @param string $prefix The class prefix to register. * @param string $path Absolute file path to the library root where classes with the given prefix can be found. * @param boolean $reset True to reset the prefix with only the given lookup path. * @param boolean $prepend If true, push the path to the beginning of the prefix lookup paths array. * * @return void * * @throws RuntimeException * * @SInCE 12.1 */ public function jaRegisterPrefix($prefix, $path, $reset = false, $prepend = false) { // Verify the library path exists. if (!file_exists($path)) { throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500); } // If the prefix is not yet registered or we have an explicit reset flag then set set the path. if (!isset(parent::$prefixes[$prefix]) || $reset) { parent::$prefixes[$prefix] = array($path); } // Otherwise we want to simply add the path to the prefix. else { if ($prepend) { array_unshift(parent::$prefixes[$prefix], $path); } else { parent::$prefixes[$prefix][] = $path; } } } /** * Offers the ability for "just in time" usage of `class_alias()`. * You cannot overwrite an existing alias. * * @param string $alias The alias name to register. * @param string $original The original class to alias. * * @return boolean True if registration was successful. False if the alias already exists. * * @SInCE 3.2 */ public function jaRegisterAlias($alias, $original) { if (!isset(parent::$classAliases[$alias])) { parent::$classAliases[$alias] = $original; return true; } return false; } /** * Register a namespace to the autoloader. When loaded, namespace paths are searched in a "last in, first out" order. * * @param string $namespace A case sensitive Namespace to register. * @param string $path A case sensitive absolute file path to the library root where classes of the given namespace can be found. * @param boolean $reset True to reset the namespace with only the given lookup path. * @param boolean $prepend If true, push the path to the beginning of the namespace lookup paths array. * * @return void * * @throws RuntimeException * * @SInCE 12.3 */ public function jaRegisterNamespace($namespace, $path, $reset = false, $prepend = false) { // Verify the library path exists. if (!file_exists($path)) { throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500); } // If the namespace is not yet registered or we have an explicit reset flag then set the path. if (!isset(self::$namespaces[$namespace]) || $reset) { self::$namespaces[$namespace] = array($path); } // Otherwise we want to simply add the path to the namespace. else { if ($prepend) { array_unshift(self::$namespaces[$namespace], $path); } else { self::$namespaces[$namespace][] = $path; } } } /** * Method to setup the autoloaders for the Joomla Platform. Since the SPL autoloaders are * called in a queue we will add our explicit, class-registration based loader first, then * fall back on the autoloader based on conventions. This will allow people to register a * class in a specific location and override platform libraries as was previously possible. * * @return void * * @SInCE 11.3 */ public function jaSetup ($enablePsr = true, $enablePrefixes = true, $enableClasses = true) { // Register the base path for Joomla platform libraries. if (!defined('JPATH_PLATFORM')) define ('JPATH_PLATFORM', dirname(__FILE__)); if ($enableClasses) { // Register the class map based autoloader. spl_autoload_register(array($this, 'jaLoad')); } if ($enablePrefixes) { $this->registerPrefix('J', JPATH_PLATFORM . '/joomla'); spl_autoload_register(array($this, '_autoload')); } if ($enablePsr) { // Register the PSR-0 based autoloader. spl_autoload_register(array($this, 'jaLoadByPsr0')); spl_autoload_register(array($this, 'jaLoadByAlias')); } // Check to see if our plugin has been removed - if so, uninstall if (!is_dir(_CMSAPI_ABSOLUTE_PATH.'/plugins/system/jaliro')) { self::uninstall(); header('Location: index.php?option=com_installer'); } } /** * Autoload a class based on name. * * @param string $class The class to be loaded. * * @return void * * @SInCE 11.3 */ private function _autoload ($class) { $lclass = strtolower($class); foreach ($this->discovered as $pathdiscovered) if (isset($pathdiscovered[$lclass]['path'])) { return include_once($pathdiscovered[$lclass]['path']); } foreach (parent::$prefixes as $prefix => $lookup) { $chr = substr($class, strlen($prefix), 1); if (strpos($class, $prefix) === 0 AND (!$chr OR ctype_upper($chr))) { return $this->_load(substr($class, strlen($prefix)), $lookup); } } return false; } /** * Method to autoload classes that have been aliased using the registerAlias method. * * @param string $class The fully qualified class name to autoload. * * @return boolean True on success, false otherwise. * * @SInCE 3.2 */ public static function jaLoadByAlias($class) { // Remove the root backslash if present. if ($class[0] == '\\') { $class = substr($class, 1); } if (isset(self::$classAliases[$class])) { class_alias(self::$classAliases[$class], $class); } } /** * Method to autoload classes that are namespaced to the PSR-0 standard. * * @param string $class The fully qualified class name to autoload. * * @return boolean True on success, false otherwise. * * @SInCE 13.1 */ public function jaLoadByPsr0 ($class) { // Remove root backslash, jump out if class already exists $class = ltrim($class, '\\'); if (class_exists($class, false)) return false; // Turn namespace and class name into an array $nameparts = explode('\\', $class); // Pull out class name and make underscores into directory separators, put back, combine array_push($nameparts, str_replace('_', DIRECTORY_SEPARATOR, array_pop($nameparts))); $classpath = implode(DIRECTORY_SEPARATOR, $nameparts).'.php'; // Loop through registered namespaces to look for a match with requested class foreach (self::$namespaces as $nsname => $nspaths) { if (0 === strpos($class, $nsname)) foreach ($nspaths as $path) { $classfile = $path.DIRECTORY_SEPARATOR.$classpath; if (file_exists($classfile)) return (bool) include_once ($classfile); } } return false; } /** * Load a class based on name and lookup array. * * @param string $class The class to be loaded (wihtout prefix). * @param array $lookup The array of base paths to use for finding the class file. * * @return varies Appears to return either a path or false * * @SInCE 12.1 */ private function _load($class, $lookup) { // Split the class name into parts separated by camelCase. $parts = preg_split('/(?<=[a-z0-9])(?=[A-Z])/x', $class); // If there is only one part we want to duplicate that part for generating the path. $parts = (count($parts) === 1) ? array($parts[0], $parts[0]) : $parts; foreach ($lookup as $base) { // Generate the path based on the class name parts. $path = $base . '/' . implode('/', array_map('strtolower', $parts)) . '.php'; // Load the file if it exists. if (file_exists($path)) { return include $path; } } return false; } public static function uninstall ($internal=false) { if (file_exists(JPATH_ROOT.'/libraries/joomla.loader.php') AND (!is_writeable(JPATH_ROOT.'/libraries/loader.php') OR !is_writeable(JPATH_ROOT.'/libraries/joomla.loader.php'))) { die('Cannot write to loaders in '.JPATH_ROOT.'/libraries/ - unable to uninstall or deactivate Jaliro'); } if (self::deactivate()) { if ($internal) JFactory::getApplication()->redirect('index.php?option=com_installer', 'Jaliro inactive'); else { clearstatcache(); foreach (self::$jalirolibs as $jalib) { if (is_writeable(JPATH_ROOT.'/libraries/'.$jalib)) JFolder::delete(JPATH_ROOT.'/libraries/'.$jalib); } } } else JFactory::getApplication()->redirect('index.php?option=com_installer', 'Failed to deactivate Jaliro'); } public static function deactivate () { return (@Unlink(JPATH_ROOT.'/libraries/loader.php') AND @rename(JPATH_ROOT.'/libraries/joomla.loader.php', JPATH_ROOT.'/libraries/loader.php')); } ``` } /** - Global application exit. * - This function provides a single exit point for the platform. * - @param mixed $message Exit code or string. Defaults to zero. * - @return void * - @codeCoverageIgnore - @SInCE 11.1 */ function jexit($message = 0) { exit($message); } /** - Intelligent file importer. * - @param string $path A dot syntax path. * - @return boolean True on success. * - @SInCE 11.1 */ function jimport($path) { return JLoader::import($path); } if ('2.5' != _CMSAPI_JOOMLA_VERSION) JLoader::setup();
This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@LTIOfficial
Copy link
Author

Using WinMerge to compare the two, Jaliro stands out as responsible for the extra code.
Jaliro belongs to a component extension called Glossary:
http://remository.com/downloads/joomla-3.x-software/jaliro-for-joomla-3.x/


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@LTIOfficial
Copy link
Author

Very interesting!
My co-admin pulled down a copy of the site files from host, loaded it up locally and tried replacing the offending loader.php file with the one from J3.4. While bring up the site in his browser, the Joomla version file was immediately overwritten with the big Jaliro version above, early in Joomla's execution cycle. He's tracked the event down to the Jaliro system plugin, which again, is part of the Glossary extension, but perhaps also used by the same developer's "Remository" extension.

Upon deactivating the Jaliro system plugin and trying again, the original issue disappears, but he's now getting a new error, related to the other extension:
Fatal error: Class 'sef_glossary' not found in D:\xampp\htdocs\mp\public\components\com_glossary\router.php on line 35


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@LTIOfficial
Copy link
Author

It looks like something (Jaliro is suspected) renamed the original Joomla loader.php file as joomla.loader.php within the same directory, back on Oct 1, 2014.

@brianteeman
Copy link
Contributor

Based on everything you have said above this is not a core joomla issue and is an issue created by the Jaliro system plugin. A quick scan of the source code shows that this extension is deliberately changing the core joomla file and replacing it with its own. This is something that should obviously never be done (it is also against the rules of a listing on the JED. (It looks like it may also be changing other core files but I havent dug in any further)

As your issue is 100% coming from this extension there is nothing that the core of joomla can do. All I can suggest is that you Uninstall the extension (I hope it is at least nice enough to restore the modified files)


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@brianteeman
Copy link
Contributor

I am closing this as it is not a core Joomla issue. It is caused by an extension replacing core joomla files which clearly is not something that should be done.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

@LTIOfficial
Copy link
Author

Once we dug into the files, we quickly became aware that this was not a Joomla issue. I simply switched over to providing you folks with our 'discovery' as we learned more so that you could take whatever actions you feel are appropriate to the situation.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6224.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants