Spade
Mini Shell
| Directory:~$ /proc/self/root/home/lmsyaran/www/joomla5/plugins/system/redirect/src/Extension/ |
| [Home] [System Details] [Kill Me] |
<?php
/**
* @package Joomla.Plugin
* @subpackage System.redirect
*
* @copyright (C) 2009 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\Plugin\System\Redirect\Extension;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Event\ErrorEvent;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Database\ParameterType;
use Joomla\Event\SubscriberInterface;
use Joomla\String\StringHelper;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Plugin class for redirect handling.
*
* @since 1.6
*/
final class Redirect extends CMSPlugin implements SubscriberInterface
{
use DatabaseAwareTrait;
/**
* Returns an array of events this subscriber will listen to.
*
* @return array
*
* @since 4.0.0
*/
public static function getSubscribedEvents(): array
{
return ['onError' => 'handleError'];
}
/**
* Internal processor for all error handlers
*
* @param ErrorEvent $event The event object
*
* @return void
*
* @since 3.5
*/
public function handleError(ErrorEvent $event)
{
/** @var \Joomla\CMS\Application\CMSApplication $app */
$app = $event->getApplication();
if ($app->isClient('administrator') || ((int)
$event->getError()->getCode() !== 404)) {
return;
}
// Load translations
$this->loadLanguage();
$uri = Uri::getInstance();
// These are the original URLs
$orgurl =
rawurldecode($uri->toString(['scheme', 'host',
'port', 'path', 'query',
'fragment']));
$orgurlRel =
rawurldecode($uri->toString(['path', 'query',
'fragment']));
// The above doesn't work for sub directories, so do this
$orgurlRootRel = str_replace(Uri::root(), '',
$orgurl);
// For when users have added / to the url
$orgurlRootRelSlash = str_replace(Uri::root(), '/',
$orgurl);
$orgurlWithoutQuery =
rawurldecode($uri->toString(['scheme', 'host',
'port', 'path', 'fragment']));
$orgurlRelWithoutQuery =
rawurldecode($uri->toString(['path', 'fragment']));
// These are the URLs we save and use
$url =
StringHelper::strtolower(rawurldecode($uri->toString(['scheme',
'host', 'port', 'path', 'query',
'fragment'])));
$urlRel =
StringHelper::strtolower(rawurldecode($uri->toString(['path',
'query', 'fragment'])));
// The above doesn't work for sub directories, so do this
$urlRootRel = str_replace(Uri::root(), '', $url);
// For when users have added / to the url
$urlRootRelSlash = str_replace(Uri::root(), '/',
$url);
$urlWithoutQuery =
StringHelper::strtolower(rawurldecode($uri->toString(['scheme',
'host', 'port', 'path',
'fragment'])));
$urlRelWithoutQuery =
StringHelper::strtolower(rawurldecode($uri->toString(['path',
'fragment'])));
$excludes = (array)
$this->params->get('exclude_urls');
$skipUrl = false;
foreach ($excludes as $exclude) {
if (empty($exclude->term)) {
continue;
}
if (!empty($exclude->regexp)) {
// Only check $url, because it includes all other sub urls
if (preg_match('/' . $exclude->term .
'/i', $orgurlRel)) {
$skipUrl = true;
break;
}
} else {
if (StringHelper::strpos($orgurlRel, $exclude->term) !==
false) {
$skipUrl = true;
break;
}
}
}
/**
* Why is this (still) here?
* Because hackers still try urls with mosConfig_* and Url
Injection with =http[s]:// and we dont want to log/redirect these requests
*/
if ($skipUrl || (strpos($url, 'mosConfig_') !== false) ||
(strpos($url, '=http') !== false)) {
return;
}
$query = $this->getDatabase()->getQuery(true);
$query->select('*')
->from($this->getDatabase()->quoteName('#__redirect_links'))
->whereIn(
$this->getDatabase()->quoteName('old_url'),
[
$url,
$urlRel,
$urlRootRel,
$urlRootRelSlash,
$urlWithoutQuery,
$urlRelWithoutQuery,
$orgurl,
$orgurlRel,
$orgurlRootRel,
$orgurlRootRelSlash,
$orgurlWithoutQuery,
$orgurlRelWithoutQuery,
],
ParameterType::STRING
);
$this->getDatabase()->setQuery($query);
$redirect = null;
try {
$redirects = $this->getDatabase()->loadAssocList();
} catch (\Exception $e) {
$event->setError(new
\Exception($this->getApplication()->getLanguage()->_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'),
500, $e));
return;
}
$possibleMatches = array_unique(
[
$url,
$urlRel,
$urlRootRel,
$urlRootRelSlash,
$urlWithoutQuery,
$urlRelWithoutQuery,
$orgurl,
$orgurlRel,
$orgurlRootRel,
$orgurlRootRelSlash,
$orgurlWithoutQuery,
$orgurlRelWithoutQuery,
]
);
foreach ($possibleMatches as $match) {
if (($index = array_search($match, array_column($redirects,
'old_url'))) !== false) {
$redirect = (object) $redirects[$index];
if ((int) $redirect->published === 1) {
break;
}
}
}
// A redirect object was found and, if published, will be used
if ($redirect !== null && ((int) $redirect->published
=== 1)) {
if (!$redirect->header || (bool)
ComponentHelper::getParams('com_redirect')->get('mode',
false) === false) {
$redirect->header = 301;
}
if ($redirect->header < 400 &&
$redirect->header >= 300) {
$urlQuery = $uri->getQuery();
$oldUrlParts = parse_url($redirect->old_url);
$newUrl = $redirect->new_url;
if ($urlQuery !== '' &&
empty($oldUrlParts['query'])) {
$newUrl .= '?' . $urlQuery;
}
$dest = Uri::isInternal($newUrl) || strpos($newUrl,
'http') === false ?
Route::_($newUrl) : $newUrl;
// In case the url contains double // lets remove it
$destination = str_replace(Uri::root() . '/',
Uri::root(), $dest);
// Always count redirect hits
$redirect->hits++;
try {
$this->getDatabase()->updateObject('#__redirect_links',
$redirect, 'id');
} catch (\Exception $e) {
// We don't log issues for now
}
$app->redirect($destination, (int)
$redirect->header);
}
$event->setError(new
\RuntimeException($event->getError()->getMessage(),
$redirect->header, $event->getError()));
} elseif ($redirect === null) {
// No redirect object was found so we create an entry in the
redirect table
if ((bool) $this->params->get('collect_urls',
1)) {
if (!$this->params->get('includeUrl', 1)) {
$url = $urlRel;
}
$nowDate = Factory::getDate()->toSql();
$data = (object) [
'id' => 0,
'old_url' => $url,
'referer' =>
$app->getInput()->server->getString('HTTP_REFERER',
''),
'hits' => 1,
'published' => 0,
'created_date' => $nowDate,
'modified_date' => $nowDate,
];
try {
$this->getDatabase()->insertObject('#__redirect_links',
$data, 'id');
} catch (\Exception $e) {
$event->setError(new
\Exception($this->getApplication()->getLanguage()->_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'),
500, $e));
return;
}
}
} else {
// We have an unpublished redirect object, increment the hit
counter
$redirect->hits++;
try {
$this->getDatabase()->updateObject('#__redirect_links',
$redirect, ['id']);
} catch (\Exception $e) {
$event->setError(new
\Exception($this->getApplication()->getLanguage()->_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'),
500, $e));
return;
}
}
}
}