Your IP : 216.73.217.68


Current Path : /home/w/u/e/wuectly/www/03cbe/
Upload File :
Current File : /home/w/u/e/wuectly/www/03cbe/actionlog.zip

PKka!]�>[>�s�sjoomla/joomla.phpnu&1i�<?php
/**
 * @package     Joomla.Plugins
 * @subpackage  System.actionlogs
 *
 * @copyright   (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\User\User;
use Joomla\CMS\Version;
use Joomla\Utilities\ArrayHelper;

JLoader::register('ActionLogPlugin', JPATH_ADMINISTRATOR . '/components/com_actionlogs/libraries/actionlogplugin.php');
JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php');

/**
 * Joomla! Users Actions Logging Plugin.
 *
 * @since  3.9.0
 */
class PlgActionlogJoomla extends ActionLogPlugin
{
	/**
	 * Array of loggable extensions.
	 *
	 * @var    array
	 * @since  3.9.0
	 */
	protected $loggableExtensions = array();

	/**
	 * Context aliases
	 *
	 * @var    array
	 * @since  3.9.0
	 */
	protected $contextAliases = array('com_content.form' => 'com_content.article');

	/**
	 * Constructor.
	 *
	 * @param   object  &$subject  The object to observe.
	 * @param   array   $config    An optional associative array of configuration settings.
	 *
	 * @since   3.9.0
	 */
	public function __construct(&$subject, $config)
	{
		parent::__construct($subject, $config);

		$params = ComponentHelper::getComponent('com_actionlogs')->getParams();

		$this->loggableExtensions = $params->get('loggable_extensions', array());
	}

	/**
	 * After save content logging method
	 * This method adds a record to #__action_logs contains (message, date, context, user)
	 * Method is called right after the content is saved
	 *
	 * @param   string   $context  The context of the content passed to the plugin
	 * @param   object   $article  A JTableContent object
	 * @param   boolean  $isNew    If the content is just about to be created
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onContentAfterSave($context, $article, $isNew)
	{
		if (isset($this->contextAliases[$context]))
		{
			$context = $this->contextAliases[$context];
		}

		$option = $this->app->input->getCmd('option');

		if (!$this->checkLoggable($option))
		{
			return;
		}

		$params = ActionlogsHelper::getLogContentTypeParams($context);

		// Not found a valid content type, don't process further
		if ($params === null)
		{
			return;
		}

		list(, $contentType) = explode('.', $params->type_alias);

		if ($isNew)
		{
			$messageLanguageKey = $params->text_prefix . '_' . $params->type_title . '_ADDED';
			$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
		}
		else
		{
			$messageLanguageKey = $params->text_prefix . '_' . $params->type_title . '_UPDATED';
			$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
		}

		// If the content type doesn't has it own language key, use default language key
		if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
		{
			$messageLanguageKey = $defaultLanguageKey;
		}

		$id = empty($params->id_holder) ? 0 : $article->get($params->id_holder);

		$message = array(
			'action'   => $isNew ? 'add' : 'update',
			'type'     => $params->text_prefix . '_TYPE_' . $params->type_title,
			'id'       => $id,
			'title'    => $article->get($params->title_holder),
			'itemlink' => ActionlogsHelper::getContentTypeLink($option, $contentType, $id, $params->id_holder, $article),
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * After delete content logging method
	 * This method adds a record to #__action_logs contains (message, date, context, user)
	 * Method is called right after the content is deleted
	 *
	 * @param   string  $context  The context of the content passed to the plugin
	 * @param   object  $article  A JTableContent object
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onContentAfterDelete($context, $article)
	{
		$option = $this->app->input->get('option');

		if (!$this->checkLoggable($option))
		{
			return;
		}

		$params = ActionlogsHelper::getLogContentTypeParams($context);

		// Not found a valid content type, don't process further
		if ($params === null)
		{
			return;
		}

		// If the content type has it own language key, use it, otherwise, use default language key
		if ($this->app->getLanguage()->hasKey(strtoupper($params->text_prefix . '_' . $params->type_title . '_DELETED')))
		{
			$messageLanguageKey = $params->text_prefix . '_' . $params->type_title . '_DELETED';
		}
		else
		{
			$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';
		}

		$id = empty($params->id_holder) ? 0 : $article->get($params->id_holder);

		$message = array(
			'action' => 'delete',
			'type'   => $params->text_prefix . '_TYPE_' . $params->type_title,
			'id'     => $id,
			'title'  => $article->get($params->title_holder)
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On content change status logging method
	 * This method adds a record to #__action_logs contains (message, date, context, user)
	 * Method is called when the status of the article is changed
	 *
	 * @param   string   $context  The context of the content passed to the plugin
	 * @param   array    $pks      An array of primary key ids of the content that has changed state.
	 * @param   integer  $value    The value of the state that the content has been changed to.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onContentChangeState($context, $pks, $value)
	{
		$option = $this->app->input->getCmd('option');

		if (!$this->checkLoggable($option))
		{
			return;
		}

		$params = ActionlogsHelper::getLogContentTypeParams($context);

		// Not found a valid content type, don't process further
		if ($params === null)
		{
			return;
		}

		list(, $contentType) = explode('.', $params->type_alias);

		switch ($value)
		{
			case 0:
				$messageLanguageKey = $params->text_prefix . '_' . $params->type_title . '_UNPUBLISHED';
				$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UNPUBLISHED';
				$action             = 'unpublish';
				break;
			case 1:
				$messageLanguageKey = $params->text_prefix . '_' . $params->type_title . '_PUBLISHED';
				$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_PUBLISHED';
				$action             = 'publish';
				break;
			case 2:
				$messageLanguageKey = $params->text_prefix . '_' . $params->type_title . '_ARCHIVED';
				$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ARCHIVED';
				$action             = 'archive';
				break;
			case -2:
				$messageLanguageKey = $params->text_prefix . '_' . $params->type_title . '_TRASHED';
				$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_TRASHED';
				$action             = 'trash';
				break;
			default:
				$messageLanguageKey = '';
				$defaultLanguageKey = '';
				$action             = '';
				break;
		}

		// If the content type doesn't has it own language key, use default language key
		if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
		{
			$messageLanguageKey = $defaultLanguageKey;
		}

		$db    = $this->db;
		$query = $db->getQuery(true)
			->select($db->quoteName(array($params->title_holder, $params->id_holder)))
			->from($db->quoteName($params->table_name))
			->where($db->quoteName($params->id_holder) . ' IN (' . implode(',', ArrayHelper::toInteger($pks)) . ')');
		$db->setQuery($query);

		try
		{
			$items = $db->loadObjectList($params->id_holder);
		}
		catch (RuntimeException $e)
		{
			$items = array();
		}

		$messages = array();

		foreach ($pks as $pk)
		{
			$message = array(
				'action'      => $action,
				'type'        => $params->text_prefix . '_TYPE_' . $params->type_title,
				'id'          => $pk,
				'title'       => $items[$pk]->{$params->title_holder},
				'itemlink'    => ActionlogsHelper::getContentTypeLink($option, $contentType, $pk, $params->id_holder, null)
			);

			$messages[] = $message;
		}

		$this->addLog($messages, $messageLanguageKey, $context);
	}

	/**
	 * On Saving application configuration logging method
	 * Method is called when the application config is being saved
	 *
	 * @param   JRegistry  $config  JRegistry object with the new config
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onApplicationAfterSave($config)
	{
		$option = $this->app->input->getCmd('option');

		if (!$this->checkLoggable($option))
		{
			return;
		}

		$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_APPLICATION_CONFIG_UPDATED';
		$action             = 'update';

		$message = array(
			'action'         => $action,
			'type'           => 'PLG_ACTIONLOG_JOOMLA_TYPE_APPLICATION_CONFIG',
			'extension_name' => 'com_config.application',
			'itemlink'       => 'index.php?option=com_config'
		);

		$this->addLog(array($message), $messageLanguageKey, 'com_config.application');
	}

	/**
	 * On installing extensions logging method
	 * This method adds a record to #__action_logs contains (message, date, context, user)
	 * Method is called when an extension is installed
	 *
	 * @param   JInstaller  $installer  Installer object
	 * @param   integer     $eid        Extension Identifier
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onExtensionAfterInstall($installer, $eid)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$manifest      = $installer->get('manifest');

		if ($manifest === null)
		{
			return;
		}

		$extensionType = $manifest->attributes()->type;

		// If the extension type has it own language key, use it, otherwise, use default language key
		if ($this->app->getLanguage()->hasKey(strtoupper('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_INSTALLED')))
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_INSTALLED';
		}
		else
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_EXTENSION_INSTALLED';
		}

		$message = array(
			'action'         => 'install',
			'type'           => 'PLG_ACTIONLOG_JOOMLA_TYPE_' . $extensionType,
			'id'             => $eid,
			'name'           => (string) $manifest->name,
			'extension_name' => (string) $manifest->name
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On uninstalling extensions logging method
	 * This method adds a record to #__action_logs contains (message, date, context, user)
	 * Method is called when an extension is uninstalled
	 *
	 * @param   JInstaller  $installer  Installer instance
	 * @param   integer     $eid        Extension id
	 * @param   integer     $result     Installation result
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onExtensionAfterUninstall($installer, $eid, $result)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		// If the process failed, we don't have manifest data, stop process to avoid fatal error
		if ($result === false)
		{
			return;
		}

		$manifest      = $installer->get('manifest');

		if ($manifest === null)
		{
			return;
		}

		$extensionType = $manifest->attributes()->type;

		// If the extension type has it own language key, use it, otherwise, use default language key
		if ($this->app->getLanguage()->hasKey(strtoupper('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_UNINSTALLED')))
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_UNINSTALLED';
		}
		else
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_EXTENSION_UNINSTALLED';
		}

		$message = array(
			'action'         => 'install',
			'type'           => 'PLG_ACTIONLOG_JOOMLA_TYPE_' . $extensionType,
			'id'             => $eid,
			'name'           => (string) $manifest->name,
			'extension_name' => (string) $manifest->name
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On updating extensions logging method
	 * This method adds a record to #__action_logs contains (message, date, context, user)
	 * Method is called when an extension is updated
	 *
	 * @param   JInstaller  $installer  Installer instance
	 * @param   integer     $eid        Extension id
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onExtensionAfterUpdate($installer, $eid)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$manifest      = $installer->get('manifest');

		if ($manifest === null)
		{
			return;
		}

		$extensionType = $manifest->attributes()->type;

		// If the extension type has it own language key, use it, otherwise, use default language key
		if ($this->app->getLanguage()->hasKey('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_UPDATED'))
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_UPDATED';
		}
		else
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_EXTENSION_UPDATED';
		}

		$message = array(
			'action'         => 'update',
			'type'           => 'PLG_ACTIONLOG_JOOMLA_TYPE_' . $extensionType,
			'id'             => $eid,
			'name'           => (string) $manifest->name,
			'extension_name' => (string) $manifest->name
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On Saving extensions logging method
	 * Method is called when an extension is being saved
	 *
	 * @param   string   $context  The extension
	 * @param   JTable   $table    DataBase Table object
	 * @param   boolean  $isNew    If the extension is new or not
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onExtensionAfterSave($context, $table, $isNew)
	{
		$option = $this->app->input->getCmd('option');

		if ($table->get('module') != null)
		{
			$option = 'com_modules';
		}

		if (!$this->checkLoggable($option))
		{
			return;
		}

		$params = ActionlogsHelper::getLogContentTypeParams($context);

		// Not found a valid content type, don't process further
		if ($params === null)
		{
			return;
		}

		list(, $contentType) = explode('.', $params->type_alias);

		if ($isNew)
		{
			$messageLanguageKey = $params->text_prefix . '_' . $params->type_title . '_ADDED';
			$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
		}
		else
		{
			$messageLanguageKey = $params->text_prefix . '_' . $params->type_title . '_UPDATED';
			$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
		}

		// If the extension type doesn't have it own language key, use default language key
		if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
		{
			$messageLanguageKey = $defaultLanguageKey;
		}

		$message = array(
			'action'         => $isNew ? 'add' : 'update',
			'type'           => 'PLG_ACTIONLOG_JOOMLA_TYPE_' . $params->type_title,
			'id'             => $table->get($params->id_holder),
			'title'          => $table->get($params->title_holder),
			'extension_name' => $table->get($params->title_holder),
			'itemlink'       => ActionlogsHelper::getContentTypeLink($option, $contentType, $table->get($params->id_holder), $params->id_holder, null)
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On Deleting extensions logging method
	 * Method is called when an extension is being deleted
	 *
	 * @param   string  $context  The extension
	 * @param   JTable  $table    DataBase Table object
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onExtensionAfterDelete($context, $table)
	{
		if (!$this->checkLoggable($this->app->input->get('option')))
		{
			return;
		}

		$params = ActionlogsHelper::getLogContentTypeParams($context);

		// Not found a valid content type, don't process further
		if ($params === null)
		{
			return;
		}

		$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';

		$message = array(
			'action' => 'delete',
			'type'   => 'PLG_ACTIONLOG_JOOMLA_TYPE_' . $params->type_title,
			'title'  => $table->get($params->title_holder)
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On saving user data logging method
	 *
	 * Method is called after user data is stored in the database.
	 * This method logs who created/edited any user's data
	 *
	 * @param   array    $user     Holds the new user data.
	 * @param   boolean  $isnew    True if a new user is stored.
	 * @param   boolean  $success  True if user was successfully stored in the database.
	 * @param   string   $msg      Message.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterSave($user, $isnew, $success, $msg)
	{
		$context = $this->app->input->get('option');
		$task    = $this->app->input->get->getCmd('task');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$jUser = Factory::getUser();

		if (!$jUser->id)
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_REGISTERED';
			$action             = 'register';

			// Reset request
			if ($task === 'reset.request')
			{
				$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_RESET_REQUEST';
				$action             = 'resetrequest';
			}

			// Reset complete
			if ($task === 'reset.complete')
			{
				$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_RESET_COMPLETE';
				$action             = 'resetcomplete';
			}

			// Registration Activation
			if ($task === 'registration.activate')
			{
				$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_REGISTRATION_ACTIVATE';
				$action             = 'activaterequest';
			}
		}
		elseif ($isnew)
		{
			$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
			$action             = 'add';
		}
		else
		{
			$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
			$action             = 'update';
		}

		$userId   = $jUser->id ?: $user['id'];
		$username = $jUser->username ?: $user['username'];

		$message = array(
			'action'      => $action,
			'type'        => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user['id'],
			'title'       => $user['name'],
			'itemlink'    => 'index.php?option=com_users&task=user.edit&id=' . $user['id'],
			'userid'      => $userId,
			'username'    => $username,
			'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $userId,
		);

		$this->addLog(array($message), $messageLanguageKey, $context, $userId);
	}

	/**
	 * On deleting user data logging method
	 *
	 * Method is called after user data is deleted from the database
	 *
	 * @param   array    $user     Holds the user data
	 * @param   boolean  $success  True if user was successfully stored in the database
	 * @param   string   $msg      Message
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterDelete($user, $success, $msg)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';

		$message = array(
			'action'      => 'delete',
			'type'        => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user['id'],
			'title'       => $user['name']
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On after save user group data logging method
	 *
	 * Method is called after user group is stored into the database
	 *
	 * @param   string   $context  The context
	 * @param   JTable   $table    DataBase Table object
	 * @param   boolean  $isNew    Is new or not
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterSaveGroup($context, $table, $isNew)
	{
		// Override context (com_users.group) with the component context (com_users) to pass the checkLoggable
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		if ($isNew)
		{
			$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
			$action             = 'add';
		}
		else
		{
			$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
			$action             = 'update';
		}

		$message = array(
			'action'      => $action,
			'type'        => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP',
			'id'          => $table->id,
			'title'       => $table->title,
			'itemlink'    => 'index.php?option=com_users&task=group.edit&id=' . $table->id
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On deleting user group data logging method
	 *
	 * Method is called after user group is deleted from the database
	 *
	 * @param   array    $group    Holds the group data
	 * @param   boolean  $success  True if user was successfully stored in the database
	 * @param   string   $msg      Message
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterDeleteGroup($group, $success, $msg)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';

		$message = array(
			'action'      => 'delete',
			'type'        => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP',
			'id'          => $group['id'],
			'title'       => $group['title']
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * Method to log user login success action
	 *
	 * @param   array  $options  Array holding options (user, responseType)
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterLogin($options)
	{
		$context = 'com_users';

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$loggedInUser       = $options['user'];
		$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGGED_IN';

		$message = array(
			'action'      => 'login',
			'userid'      => $loggedInUser->id,
			'username'    => $loggedInUser->username,
			'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $loggedInUser->id,
			'app'         => 'PLG_ACTIONLOG_JOOMLA_APPLICATION_' . $this->app->getName(),
		);

		$this->addLog(array($message), $messageLanguageKey, $context, $loggedInUser->id);
	}

	/**
	 * Method to log user login failed action
	 *
	 * @param   array  $response  Array of response data.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserLoginFailure($response)
	{
		$context = 'com_users';

		if (!$this->checkLoggable($context))
		{
			return;
		}

		// Get the user id for the given username
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName(array('id', 'username')))
			->from($this->db->quoteName('#__users'))
			->where($this->db->quoteName('username') . ' = ' . $this->db->quote($response['username']));
		$this->db->setQuery($query);

		try
		{
			$loggedInUser = $this->db->loadObject();
		}
		catch (JDatabaseExceptionExecuting $e)
		{
			return;
		}

		// Not a valid user, return
		if (!isset($loggedInUser->id))
		{
			return;
		}

		$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGIN_FAILED';

		$message = array(
			'action'      => 'login',
			'id'          => $loggedInUser->id,
			'userid'      => $loggedInUser->id,
			'username'    => $loggedInUser->username,
			'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $loggedInUser->id,
			'app'         => 'PLG_ACTIONLOG_JOOMLA_APPLICATION_' . $this->app->getName(),
		);

		$this->addLog(array($message), $messageLanguageKey, $context, $loggedInUser->id);
	}

	/**
	 * Method to log user's logout action
	 *
	 * @param   array  $user     Holds the user data
	 * @param   array  $options  Array holding options (remember, autoregister, group)
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserLogout($user, $options = array())
	{
		$context = 'com_users';

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$loggedOutUser = User::getInstance($user['id']);

		if ($loggedOutUser->block)
		{
			return;
		}

		$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGGED_OUT';

		$message = array(
			'action'      => 'logout',
			'id'          => $loggedOutUser->id,
			'userid'      => $loggedOutUser->id,
			'username'    => $loggedOutUser->username,
			'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $loggedOutUser->id,
			'app'         => 'PLG_ACTIONLOG_JOOMLA_APPLICATION_' . $this->app->getName(),
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * Function to check if a component is loggable or not
	 *
	 * @param   string  $extension  The extension that triggered the event
	 *
	 * @return  boolean
	 *
	 * @since   3.9.0
	 */
	protected function checkLoggable($extension)
	{
		return in_array($extension, $this->loggableExtensions);
	}

	/**
	 * On after Remind username request
	 *
	 * Method is called after user request to remind their username.
	 *
	 * @param   array  $user  Holds the user data.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterRemind($user)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$message = array(
			'action'      => 'remind',
			'type'        => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->name,
			'itemlink'    => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
			'userid'      => $user->id,
			'username'    => $user->name,
			'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
		);

		$this->addLog(array($message), 'PLG_ACTIONLOG_JOOMLA_USER_REMIND', $context, $user->id);
	}

	/**
	 * On after Check-in request
	 *
	 * Method is called after user request to check-in items.
	 *
	 * @param   array  $table  Holds the table name.
	 *
	 * @return  void
	 *
	 * @since   3.9.3
	 */
	public function onAfterCheckin($table)
	{
		$context = 'com_checkin';
		$user    = Factory::getUser();

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$message = array(
			'action'      => 'checkin',
			'type'        => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->username,
			'itemlink'    => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
			'userid'      => $user->id,
			'username'    => $user->username,
			'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
			'table'       => $table,
		);

		$this->addLog(array($message), 'PLG_ACTIONLOG_JOOMLA_USER_CHECKIN', $context, $user->id);
	}

	/**
	 * On after log action purge
	 *
	 * Method is called after user request to clean action log items.
	 *
	 * @param   array  $group  Holds the group name.
	 *
	 * @return  void
	 *
	 * @since   3.9.4
	 */
	public function onAfterLogPurge($group = '')
	{
		$context = $this->app->input->get('option');
		$user    = Factory::getUser();
		$message = array(
			'action'      => 'actionlogs',
			'type'        => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->username,
			'itemlink'    => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
			'userid'      => $user->id,
			'username'    => $user->username,
			'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
		);
		$this->addLog(array($message), 'PLG_ACTIONLOG_JOOMLA_USER_LOG', $context, $user->id);
	}

	/**
	 * On after log export
	 *
	 * Method is called after user request to export action log items.
	 *
	 * @param   array  $group  Holds the group name.
	 *
	 * @return  void
	 *
	 * @since   3.9.4
	 */
	public function onAfterLogExport($group = '')
	{
		$context = $this->app->input->get('option');
		$user    = Factory::getUser();
		$message = array(
			'action'      => 'actionlogs',
			'type'        => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->username,
			'itemlink'    => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
			'userid'      => $user->id,
			'username'    => $user->username,
			'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
		);
		$this->addLog(array($message), 'PLG_ACTIONLOG_JOOMLA_USER_LOGEXPORT', $context, $user->id);
	}

	/**
	 * On after Cache purge
	 *
	 * Method is called after user request to clean cached items.
	 *
	 * @param   string  $group  Holds the group name.
	 *
	 * @return  void
	 *
	 * @since   3.9.4
	 */
	public function onAfterPurge($group = 'all')
	{
		$context = $this->app->input->get('option');
		$user    = JFactory::getUser();

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$message = array(
			'action'      => 'cache',
			'type'        => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->username,
			'itemlink'    => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
			'userid'      => $user->id,
			'username'    => $user->username,
			'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
			'group'       => $group,
		);
		$this->addLog(array($message), 'PLG_ACTIONLOG_JOOMLA_USER_CACHE', $context, $user->id);
	}

	/**
	 * On after CMS Update
	 *
	 * Method is called after user update the CMS.
	 *
	 * @param   string  $oldVersion  The Joomla version before the update
	 *
	 * @return  void
	 *
	 * @since   3.9.21
	 */
	public function onJoomlaAfterUpdate($oldVersion = null)
	{
		$context = $this->app->input->get('option');
		$user    = JFactory::getUser();

		if (empty($oldVersion))
		{
			$oldVersion = JText::_('JLIB_UNKNOWN');
		}

		$message = array(
			'action'      => 'joomlaupdate',
			'type'        => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->username,
			'itemlink'    => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
			'userid'      => $user->id,
			'username'    => $user->username,
			'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
			'version'     => JVERSION,
			'oldversion'  => $oldVersion,
		);
		$this->addLog(array($message), 'PLG_ACTIONLOG_JOOMLA_USER_UPDATE', $context, $user->id);
	}
}
PKka!]7K�Xjoomla/joomla.xmlnu&1i�<?xml version="1.0" encoding="UTF-8"?>
<extension version="3.9" type="plugin" group="actionlog" method="upgrade">
	<name>PLG_ACTIONLOG_JOOMLA</name>
	<author>Joomla! Project</author>
	<creationDate>May 2018</creationDate>
	<copyright>(C) 2018 Open Source Matters, Inc.</copyright>
	<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.9.0</version>
	<description>PLG_ACTIONLOG_JOOMLA_XML_DESCRIPTION</description>
	<files>
		<filename plugin="joomla">joomla.php</filename>
	</files>
	<languages>
		<language tag="en-GB">en-GB.plg_actionlog_joomla.ini</language>
		<language tag="en-GB">en-GB.plg_actionlog_joomla.sys.ini</language>
	</languages>
</extension>
PKka!]��ѡ��akeebabackup/.htaccessnu&1i�<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
PKka!]NH���akeebabackup/script.phpnu&1i�<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

use FOF40\InstallScript\Plugin;

defined('_JEXEC') || die;

// Load FOF if not already loaded
if (!defined('FOF40_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof40/include.php'))
{
	throw new RuntimeException('This extension requires FOF 4.');
}

class plgActionlogAkeebabackupInstallerScript extends Plugin
{
}
PKka!]��M��akeebabackup/akeebabackup.xmlnu&1i�<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->

<extension version="3.9.0" type="plugin" group="actionlog" method="upgrade">
	<name>PLG_ACTIONLOG_AKEEBABACKUP</name>
	<author>Nicholas K. Dionysopoulos</author>
	<authorEmail>nicholas@dionysopoulos.me</authorEmail>
	<authorUrl>https://www.akeeba.com</authorUrl>
	<copyright>Copyright (c)2006-2023 Nicholas K. Dionysopoulos</copyright>
	<license>GNU General Public License version 3, or later</license>
	<creationDate>2025-05-09</creationDate>
	<version>8.4.1</version>
	<description>PLG_ACTIONLOG_AKEEBABACKUP_XML_DESCRIPTION</description>
	<files>
		<filename plugin="akeebabackup">akeebabackup.php</filename>
		<filename>.htaccess</filename>
		<filename>web.config</filename>
	</files>
	<languages folder="language">
		<language tag="en-GB">en-GB/en-GB.plg_actionlog_akeebabackup.ini</language>
		<language tag="en-GB">en-GB/en-GB.plg_actionlog_akeebabackup.sys.ini</language>
	</languages>

	<scriptfile>script.php</scriptfile>
</extension>PKka!]�/���*�*akeebabackup/akeebabackup.phpnu&1i�<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Plugin\CMSPlugin;

defined('_JEXEC') || die();

class plgActionlogAkeebabackup extends CMSPlugin
{
	/** @var Container */
	private $container;

	/**
	 * Constructor
	 *
	 * @param   object  $subject  The object to observe
	 * @param   array   $config   An array that holds the plugin configuration
	 *
	 * @since       6.4.0
	 */
	public function __construct(&$subject, $config)
	{
		// Make sure Akeeba Backup is installed
		if (!file_exists(JPATH_ADMINISTRATOR . '/components/com_akeeba'))
		{
			return;
		}

		// Make sure Akeeba Backup is enabled
		if (!ComponentHelper::isEnabled('com_akeeba'))
		{
			return;
		}

		// Load FOF
		if (!defined('FOF40_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof40/include.php'))
		{
			return;
		}

		$this->container = Container::getInstance('com_akeeba');

		// No point in logging guest actions
		if ($this->container->platform->getUser()->guest)
		{
			return;
		}

		// If any of the above statement returned, our plugin is not attached to the subject, so it's basically disabled
		parent::__construct($subject, $config);
	}

	/**
	 * Logs the creation of a new backup profile
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Profiles  $controller
	 * @param   array                                     $data
	 * @param   int                                       $id
	 */
	public function onComAkeebaControllerProfilesAfterApplySave($controller, $data, $id)
	{
		// If I have an ID in the request and it's the same of the model, I'm just editing a record
		if (isset($data['id']) && $data['id'] == $id)
		{
			return;
		}

		$profile_title = $data['description'];

		$this->container->platform->logUserAction($profile_title, 'COM_AKEEBA_LOGS_PROFILE_ADD', 'com_akeeba');
	}

	/**
	 * Logs deletion of a backup profile
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Profiles  $controller
	 */
	public function onComAkeebaControllerProfilesAfterRemove($controller)
	{
		$ids           = $controller->input->get('cid', [], 'array', 2);
		$profile_title = '# ' . implode(', ', $ids);

		$this->container->platform->logUserAction($profile_title, 'COM_AKEEBA_LOGS_PROFILE_DELETE', 'com_akeeba');
	}

	/**
	 * Log configuration edit (apply)
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Configuration  $controller
	 */
	public function onComAkeebaControllerConfigurationAfterApply($controller)
	{
		$this->logConfigurationChange();
	}

	/**
	 * Log configuration edit (save and close)
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Configuration  $controller
	 */
	public function onComAkeebaControllerConfigurationAfterSave($controller)
	{
		$this->logConfigurationChange();
	}

	/**
	 * Log configuration edit (save and new)
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Configuration  $controller
	 */
	public function onComAkeebaControllerConfigurationAfterSavenew($controller)
	{
		$this->logConfigurationChange();
	}

	/**
	 * Log starting a new backup
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Backup  $controller
	 */
	public function onComAkeebaControllerBackupBeforeAjax($controller)
	{
		$ajaxTask = $this->container->input->get('ajax', '', 'cmd');

		// Log only starting the backup
		if ($ajaxTask != 'start')
		{
			return;
		}

		$profile_id = $this->container->platform->getSessionVar('profile', -10, 'akeeba');

		if ($profile_id < 1)
		{
			return;
		}

		$profile_id = '#' . $profile_id;

		$this->container->platform->logUserAction($profile_id, 'COM_AKEEBA_LOGS_BACKUP_RUN', 'com_akeeba');
	}

	/**
	 * Log downloading a backup using Joomla interface
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Manage  $controller
	 */
	public function onComAkeebaControllerManageBeforeDownload($controller)
	{
		$id   = $this->container->input->getInt('id');
		$part = $this->container->input->getInt('part', -1);

		// This should never happens, but better be safe
		if (!$id)
		{
			return;
		}

		$stat         = Platform::getInstance()->get_statistics($id);
		$profile_name = Platform::getInstance()->get_profile_name($stat['profile_id']);

		$title = 'Profile: "' . $profile_name . '" ID: ' . $id;

		if ($part > -1)
		{
			$title .= ' part: ' . $part;
		}

		$this->container->platform->logUserAction($title, 'COM_AKEEBA_LOGS_MANAGE_DOWNLOAD', 'com_akeeba');
	}

	/**
	 * Logs deleting backup files
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Manage  $controller
	 */
	public function onComAkeebaControllerManageBeforeDeletefiles($controller)
	{
		$ids = $this->getIDsFromRequest();

		foreach ($ids as $id)
		{
			$this->container->platform->logUserAction('ID: ' . $id, 'COM_AKEEBA_LOGS_MANAGE_DELETEFILES', 'com_akeeba');
		}
	}

	/**
	 * Logs deleting backup stat entry
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Manage  $controller
	 */
	public function onComAkeebaControllerManageBeforeRemove($controller)
	{
		$ids = $this->getIDsFromRequest();

		foreach ($ids as $id)
		{
			$this->container->platform->logUserAction($id, 'COM_AKEEBA_LOGS_MANAGE_DELETE', 'com_akeeba');
		}
	}

	/**
	 * Logs downloading remote archives to browser
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\RemoteFiles  $controller
	 */
	public function onComAkeebaControllerRemoteFilesBeforeDlfromremote($controller)
	{
		$id   = $this->container->input->getInt('id');
		$part = $this->container->input->getInt('part', -1);

		// This should never happens, but better be safe
		if (!$id)
		{
			return;
		}

		$stat         = Platform::getInstance()->get_statistics($id);
		$profile_name = Platform::getInstance()->get_profile_name($stat['profile_id']);

		$title = 'Profile: "' . $profile_name . '" ID: ' . $id;

		if ($part > -1)
		{
			$title .= ' part: ' . $part;
		}

		$this->container->platform->logUserAction($title, 'COM_AKEEBA_LOGS_REMOTEFILE_DOWNLOAD', 'com_akeeba');
	}

	/**
	 * Logs downloading remote archives back to the server
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\RemoteFiles  $controller
	 */
	public function onComAkeebaControllerRemoteFilesBeforeDltoserver($controller)
	{
		$id   = $this->container->input->getInt('id');
		$part = $this->container->input->getInt('part', -1);
		$frag = $this->container->input->getInt('frag', -1);

		// Log only the first step
		if ($frag > -1 || $part > -1)
		{
			return;
		}

		// This should never happens, but better be safe
		if (!$id)
		{
			return;
		}

		$stat         = Platform::getInstance()->get_statistics($id);
		$profile_name = Platform::getInstance()->get_profile_name($stat['profile_id']);

		$title = 'Profile: "' . $profile_name . '" ID: ' . $id;

		$this->container->platform->logUserAction($title, 'COM_AKEEBA_LOGS_REMOTEFILE_FETCH', 'com_akeeba');
	}

	/**
	 * Logs downloading remote archives to browser
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\RemoteFiles  $controller
	 */
	public function onComAkeebaControllerRemoteFilesBeforeDelete($controller)
	{
		$id   = $this->container->input->getInt('id');
		$part = $this->container->input->getInt('part', -1);

		// This should never happens, but better be safe
		if (!$id)
		{
			return;
		}

		$stat         = Platform::getInstance()->get_statistics($id);
		$profile_name = Platform::getInstance()->get_profile_name($stat['profile_id']);

		$title = 'Profile: "' . $profile_name . '" ID: ' . $id;

		if ($part > -1)
		{
			$title .= ' part: ' . $part;
		}

		$this->container->platform->logUserAction($title, 'COM_AKEEBA_LOGS_REMOTEFILE_DELETE', 'com_akeeba');
	}

	/**
	 * Logs downloading remote archives to browser
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Upload  $controller
	 */
	public function onComAkeebaControllerUploadBeforeStart($controller)
	{
		$id = $this->container->input->getInt('id');

		// This should never happens, but better be safe
		if (!$id)
		{
			return;
		}

		$stat         = Platform::getInstance()->get_statistics($id);
		$profile_name = Platform::getInstance()->get_profile_name($stat['profile_id']);

		$title = 'Profile: "' . $profile_name . '" ID: ' . $id;

		$this->container->platform->logUserAction($title, 'COM_AKEEBA_LOGS_UPLOADS_ADD', 'com_akeeba');
	}

	/**
	 * Log starting a site transfer wizard (connections valid, just before starting to actually transfer files)
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Transfer  $controller
	 */
	public function onComAkeebaControllerTransferBeforeUpload($controller)
	{
		$start = $this->container->input->getBool('start', false);

		if (!$start)
		{
			return;
		}

		$title = $this->container->platform->getSessionVar('transfer.url', '', 'akeeba');

		if (!$title)
		{
			return;
		}

		$this->container->platform->logUserAction($title, 'COM_AKEEBA_LOGS_TRANSFER_RUN', 'com_akeeba');
	}

	/**
	 * Logs downloading a backup log
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Log  $controller
	 */
	public function onComAkeebaControllerLogBeforeDownload($controller)
	{
		$tag = $this->container->input->get('tag', null, 'cmd');;

		$this->container->platform->logUserAction($tag, 'COM_AKEEBA_LOGS_LOG_DOWNLOAD', 'com_akeeba');
	}

	/**
	 * Log importing a backup archive
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Discover  $controller
	 */
	public function onComAkeebaControllerDiscoverBeforeImport($controller)
	{
		$files = $this->container->input->get('files', [], 'array');

		foreach ($files as $file)
		{
			$this->container->platform->logUserAction($file, 'COM_AKEEBA_LOGS_DISCOVER_IMPORT', 'com_akeeba');
		}
	}

	/**
	 * Log importing a backup archive from S3
	 *
	 * @param   \Akeeba\Backup\Admin\Controller\Discover  $controller
	 */
	public function onComAkeebaControllerS3ImportBeforeDltoserver($controller)
	{
		$file = $this->container->input->get('file', '', 'string');

		// Log only the initial download step
		$part = $this->container->input->getInt('part', -1);
		$frag = $this->container->input->getInt('frag', -1);
		$step = $this->container->input->getInt('step', -1);

		if ($part > -1 || $frag > -1 || $step > -1)
		{
			return;
		}

		$this->container->platform->logUserAction($file, 'COM_AKEEBA_LOGS_S3IMPORT_IMPORT', 'com_akeeba');
	}

	private function logConfigurationChange()
	{
		$profileName = $this->container->input->getString('profilename', null);

		$this->container->platform->logUserAction('"' . $profileName . '"', 'COM_AKEEBA_LOGS_CONFIGURATION_EDIT', 'com_akeeba');
	}

	/**
	 * Gets the list of IDs from the request data
	 *
	 * @return array
	 */
	private function getIDsFromRequest()
	{
		// Get the ID or list of IDs from the request or the configuration
		$cid = $this->container->input->get('cid', [], 'array');
		$id  = $this->container->input->getInt('id', 0);

		$ids = [];

		if (is_array($cid) && !empty($cid))
		{
			$ids = $cid;
		}
		elseif (!empty($id))
		{
			$ids = [$id];
		}

		return $ids;
	}
}
PKka!]|��Nakeebabackup/web.confignu&1i�<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>PKka!]�>[>�s�sjoomla/joomla.phpnu&1i�PKka!]7K�X;tjoomla/joomla.xmlnu&1i�PKka!]��ѡ���wakeebabackup/.htaccessnu&1i�PKka!]NH���xxakeebabackup/script.phpnu&1i�PKka!]��M���zakeebabackup/akeebabackup.xmlnu&1i�PKka!]�/���*�*�akeebabackup/akeebabackup.phpnu&1i�PKka!]|��N��akeebabackup/web.confignu&1i�PK`�