?
avatar LTIOfficial
LTIOfficial
27 Feb 2015

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.

Votes

# of Users Experiencing Issue
1/1
Average Importance Score
5.00

avatar LTIOfficial LTIOfficial - open - 27 Feb 2015
avatar brianteeman brianteeman - change - 27 Feb 2015
Labels Added: ?
avatar orware
orware - comment - 27 Feb 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.
avatar LTIOfficial LTIOfficial - change - 27 Feb 2015
The description was changed
avatar LTIOfficial
LTIOfficial - comment - 27 Feb 2015

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.
avatar LTIOfficial
LTIOfficial - comment - 28 Feb 2015

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.

<?php
/**

  • @package Joomla.Libraries *
  • @copyright Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved.
  • @license GNU General Public License version 2 or later; see LICENSE */

namespace Composer\Autoload;

defined('_JEXEC') or die;

// We have to manually require the base ClassLoader as the autoloader isn't loaded yet, but only if it doesn't exist
if (!class_exists('Composer\Autoload\ClassLoader'))
{
require_once DIR . '/vendor/composer/ClassLoader.php';
}

/**

  • Extended Composer ClassLoader for Joomla! *
  • For backward compatibility due to class aliasing in the CMS, the loadClass() method was modified to call
  • the JLoader::applyAliasFor() method. *
  • @author Nicholas Dionysopoulos
  • @since 3.4
    /
    class ClassLoaderJoomla extends ClassLoader
    {
    /
    *

    • Loads the given class or interface. *
    • @param string $class The name of the class *
    • @return bool|null True if loaded, null otherwise *
    • @since 3.4
      */
      public function loadClass($class)
      {
      if ($file = $this->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.
avatar LTIOfficial
LTIOfficial - comment - 28 Feb 2015

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.
avatar orware
orware - comment - 28 Feb 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.
avatar LTIOfficial
LTIOfficial - comment - 28 Feb 2015

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.
avatar LTIOfficial
LTIOfficial - comment - 28 Feb 2015

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

<?php
/**

  • @package Joomla.Platform *
  • @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  • @license GNU General Public License version 2 or later; see LICENSE */

// Jaliro version, modified from Joomla 2.5

// CMS independent check to prevent direct execution
if (basename(@$SERVER['REQUEST_URI']) == basename(__FILE_)) die ('This software is for use within a larger system');

if (!function_exists('version_compare') OR version_compare(phpversion(), '5.2.3', '<')) {
die('Jaliro requires at least PHP 5.2.3');
}

if(!defined('DS')) define( 'DS', DIRECTORY_SEPARATOR );
if(!defined('_CMSAPI_CMS_BASE')) define ('_CMSAPI_CMS_BASE', 'Joomla');
if(!defined('_CMSAPI_ABSOLUTE_PATH')) define ('_CMSAPI_ABSOLUTE_PATH', JPATH_SITE);
if (!defined('_CMSAPI_CHARSET')) define ('_CMSAPI_CHARSET', 'utf-8');
if ('utf-8' == _CMSAPI_CHARSET) define ('_CMSAPI_LANGFILE', 'language-utf/');
else define ('_CMSAPI_LANGFILE', 'language/');

if (file_exists(_CMSAPI_ABSOLUTE_PATH.'/libraries/cms/version/version.php')) {
define('_CMSAPI_JOOMLA_VERSION', '2.5');
define ('_CMSAPI_PARAMETER_CLASS', 'JForm');
}
elseif (file_exists(_CMSAPI_ABSOLUTE_PATH.'/libraries/joomla/version.php')) {
define('_CMSAPI_JOOMLA_VERSION', '1.5');
define ('_CMSAPI_PARAMETER_CLASS', 'JParameter');
}
else {
define('_CMSAPI_JOOMLA_VERSION', '1.0');
define ('_CMSAPI_PARAMETER_CLASS', 'JParameter');
}

// Aliro definitions that are set dynamically
// Needs more work to be dynamic in Joomla
define ('_ALIRO_IS_ADMIN', 0);
define ('_ALIRO_SITE_BASE', _CMSAPI_ABSOLUTE_PATH);
define ('_ALIRO_ABSOLUTE_PATH', _CMSAPI_ABSOLUTE_PATH);

// Standard definitions for Aliro
// define ('_ALIRO_CLASS_BASE', '/var/www/OutsideDocRoot');

DEFINE('ALIRO_REGEXP_URL','/(https?|ftps?):\/\/[a-zA-Z0-9-.]+.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?\/?([a-zA-Z0-9-.\?\,\'\/\+&%\$#\=~])[^.\,)(\s]/');
DEFINE('ALIRO_REGEXP_IP','/(https?|ftps?):\/\/\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\/?([a-zA-Z0-9-.\?\,\'\/\+&%\$#\=~])
[^.\,)(\s]/');

// Define the class to handle storage of cached data, must inherit from aliroCacheStorage
define ('_ALIRO_CACHE_HANDLER', 'aliroCacheDiskStorage');

// Define values for login validation results
define ('_ALIRO_LOGIN_GOOD', 0);
define ('_ALIRO_LOGIN_FAILED', 1);
define ('_ALIRO_LOGIN_PROHIBITED', 2);

// Allows extensions written for Joomla 1.5+ to run
//define ('_JEXEC', 1);
//define ('JPATH_BASE', _ALIRO_ABSOLUTE_PATH);
//define ('DS', '/');

// Used with the getParam method of aliroAbstractRequest
if (!defined('_MOS_NOTRIM')) define( '_MOS_NOTRIM', 0x0001 ); // prevent getParam trimming input
if (!defined('_MOS_ALLOWHTML')) define( '_MOS_ALLOWHTML', 0x0002 ); // cause getParam to allow HTML - purified on user side
if (!defined('_MOS_ALLOWRAW')) define( '_MOS_ALLOWRAW', 0x0004 ); // suppresses forcing of integer if default is numeric
if (!defined('_MOS_NOSTRIP')) define( '_MOS_NOSTRIP', 0x0008 ); // suppress stripping of magic quotes

// Aliro error levels
if (!defined('_ALIRO_ERROR_INFORM')) define ('_ALIRO_ERROR_INFORM', 0);
if (!defined('_ALIRO_ERROR_WARN')) define ('_ALIRO_ERROR_WARN', 1);
if (!defined('_ALIRO_ERROR_SEVERE')) define ('_ALIRO_ERROR_SEVERE', 2);
if (!defined('_ALIRO_ERROR_FATAL')) define ('_ALIRO_ERROR_FATAL', 3);

// Aliro cache parameters
if (!defined('_ALIRO_HTML_CACHE_TIME_LIMIT')) define('_ALIRO_HTML_CACHE_TIME_LIMIT', 600);
if (!defined('_ALIRO_HTML_CACHE_SIZE_LIMIT')) define('_ALIRO_HTML_CACHE_SIZE_LIMIT', 100000);
if (!defined('_ALIRO_OBJECT_CACHE_TIME_LIMIT')) define('_ALIRO_OBJECT_CACHE_TIME_LIMIT', 600);
if (!defined('_ALIRO_OBJECT_CACHE_SIZE_LIMIT')) define('_ALIRO_OBJECT_CACHE_SIZE_LIMIT', 100000);

// Aliro parameter fetching parameters
if (!defined('_MOS_NOTRIM')) define( '_MOS_NOTRIM', 0x0001 ); // prevent getParam trimming input
if (!defined('_MOS_ALLOWHTML')) define( '_MOS_ALLOWHTML', 0x0002 ); // cause getParam to allow HTML - purified on user side
if (!defined('_MOS_ALLOWRAW')) define( '_MOS_ALLOWRAW', 0x0004 ); // suppresses forcing of integer if default is numeric

// Aliro form checking mechanism
if (!defined('_ALIRO_FORM_CHECK_OK')) define ('_ALIRO_FORM_CHECK_OK', 0);
if (!defined('_ALIRO_FORM_CHECK_REPEAT')) define ('_ALIRO_FORM_CHECK_REPEAT', 1);
if (!defined('_ALIRO_FORM_CHECK_FAIL')) define ('_ALIRO_FORM_CHECK_FAIL', 2);
if (!defined('_ALIRO_FORM_CHECK_NULL')) define ('_ALIRO_FORM_CHECK_NULL', 3);
if (!defined('_ALIRO_FORM_CHECK_EXPIRED')) define ('_ALIRO_FORM_CHECK_EXPIRED', 4);

// Database error conditions
define ('_ALIRO_DB_NO_INTERFACE', 1);
define ('_ALIRO_DB_CONNECT_FAILED', 2);

define ('_ALIRO_USER_SIDE', 1);
define ('_ALIRO_ADMIN_SIDE', 2);

// Menu options
define ('_ALIRO_SHOW_NO_SUBMENUS', 0);
define ('_ALIRO_SHOW_ACTIVE_SUBMENUS', 1);
define ('_ALIRO_SHOW_ALL_SUBMENUS', 2);

// Default user side page size
DEFINE ('_ALIRO_PAGE_NAV_DISPLAY_PAGES', 10);

define ('_ALIRO_SEF_MAX_CACHE_SIZE', 500000);
define ('_ALIRO_SEF_MAX_CACHE_TIME', 3600);

define ('_ALIRO_AUTHORISER_SESSION_CACHE_TIME', 600);

define ('_ALIRO_DATABASE_CACHE_TIME', 3600);

// How long to keep records of material checked for spam
define ('_ALIRO_KEEP_DAYS_OF_SPAM', 7);

// Location for class location cache
define ('_JALOADER_CLASS_CACHE', _CMSAPI_ABSOLUTE_PATH.'/cache/jaliroclasses');

interface ifAliroModule {

public function activate ($module, &$content, $area, $params);

}

interface ifAliroTemplate {
public static function defaultModulePosition ();
public function positions ();
public function render ();
}

interface ifAliroMainTemplate {
public static function defaultModulePosition ();
public function positions ();
public function render ();
public function component_render ();
}

interface ifAliroLocalTemplate {
public static function defaultModulePosition ();
public function positions ();
public function render ();
}

interface ifTemplateRenderer {
public function display ($template='');
public function fetch ($template='');
public function getengine ();
public function addvar ($key, $value);
public function addbyref ($key, &$value);
public function getvars ($name);
public function setdir ($dir);
public function settemplate ($template);
}

class jaliro {
public static $version = '1.4.4';

// Doesn't presently do anything except contain the version number
// Version MUST be changed if new library contents are to overwrite existing

public static function trace ($error=true, $useHTML=true) {
    static $counter = 0;
    $html = '';
    $newline = $useHTML ? '<br />' : "\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.
avatar LTIOfficial
LTIOfficial - comment - 28 Feb 2015

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.
avatar LTIOfficial
LTIOfficial - comment - 28 Feb 2015

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.
avatar LTIOfficial
LTIOfficial - comment - 28 Feb 2015

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.

avatar brianteeman
brianteeman - comment - 28 Feb 2015

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.
avatar brianteeman brianteeman - close - 28 Feb 2015
avatar brianteeman brianteeman - change - 28 Feb 2015
Status New Closed
Closed_Date 0000-00-00 00:00:00 2015-02-28 10:37:06
Closed_By brianteeman
avatar brianteeman
brianteeman - comment - 28 Feb 2015

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.
avatar brianteeman brianteeman - change - 28 Feb 2015
Closed_Date 2015-02-28 10:37:06 2015-02-28 10:37:07
avatar brianteeman brianteeman - close - 28 Feb 2015
avatar LTIOfficial
LTIOfficial - comment - 28 Feb 2015

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.

Add a Comment

Login with GitHub to post a comment