PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/home/plugins/system/redirect/redirect.php

https://bitbucket.org/rubbystar/carimod
PHP | 250 lines | 146 code | 36 blank | 68 comment | 18 complexity | 7421e1a6d3081225a1327e1a7b1e3549 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, GPL-3.0
  1. <?php
  2. /**
  3. * @package Joomla.Plugin
  4. * @subpackage System.redirect
  5. *
  6. * @copyright Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE.txt
  8. */
  9. defined('_JEXEC') or die;
  10. use Joomla\Registry\Registry;
  11. /**
  12. * Plugin class for redirect handling.
  13. *
  14. * @since 1.6
  15. */
  16. class PlgSystemRedirect extends JPlugin
  17. {
  18. /**
  19. * Affects constructor behavior. If true, language files will be loaded automatically.
  20. *
  21. * @var boolean
  22. * @since 3.4
  23. */
  24. protected $autoloadLanguage = false;
  25. /**
  26. * The global exception handler registered before the plugin was instantiated
  27. *
  28. * @var callable
  29. * @since 3.6
  30. */
  31. private static $previousExceptionHandler;
  32. /**
  33. * Constructor.
  34. *
  35. * @param object &$subject The object to observe
  36. * @param array $config An optional associative array of configuration settings.
  37. *
  38. * @since 1.6
  39. */
  40. public function __construct(&$subject, $config)
  41. {
  42. parent::__construct($subject, $config);
  43. // Set the JError handler for E_ERROR to be the class' handleError method.
  44. JError::setErrorHandling(E_ERROR, 'callback', array('PlgSystemRedirect', 'handleError'));
  45. // Register the previously defined exception handler so we can forward errors to it
  46. self::$previousExceptionHandler = set_exception_handler(array('PlgSystemRedirect', 'handleException'));
  47. }
  48. /**
  49. * Method to handle an error condition from JError.
  50. *
  51. * @param JException $error The JException object to be handled.
  52. *
  53. * @return void
  54. *
  55. * @since 1.6
  56. */
  57. public static function handleError(JException $error)
  58. {
  59. self::doErrorHandling($error);
  60. }
  61. /**
  62. * Method to handle an uncaught exception.
  63. *
  64. * @param Exception|Throwable $exception The Exception or Throwable object to be handled.
  65. *
  66. * @return void
  67. *
  68. * @since 3.5
  69. * @throws InvalidArgumentException
  70. */
  71. public static function handleException($exception)
  72. {
  73. // If this isn't a Throwable then bail out
  74. if (!($exception instanceof Throwable) && !($exception instanceof Exception))
  75. {
  76. throw new InvalidArgumentException(
  77. sprintf('The error handler requires an Exception or Throwable object, a "%s" object was given instead.', get_class($exception))
  78. );
  79. }
  80. self::doErrorHandling($exception);
  81. }
  82. /**
  83. * Internal processor for all error handlers
  84. *
  85. * @param Exception|Throwable $error The Exception or Throwable object to be handled.
  86. *
  87. * @return void
  88. *
  89. * @since 3.5
  90. */
  91. private static function doErrorHandling($error)
  92. {
  93. $app = JFactory::getApplication();
  94. if ($app->isAdmin() || ((int) $error->getCode() !== 404))
  95. {
  96. // Proxy to the previous exception handler if available, otherwise just render the error page
  97. if (self::$previousExceptionHandler)
  98. {
  99. call_user_func_array(self::$previousExceptionHandler, array($error));
  100. }
  101. else
  102. {
  103. JErrorPage::render($error);
  104. }
  105. }
  106. $uri = JUri::getInstance();
  107. $url = rawurldecode($uri->toString(array('scheme', 'host', 'port', 'path', 'query', 'fragment')));
  108. $urlRel = rawurldecode($uri->toString(array('path', 'query', 'fragment')));
  109. $urlWithoutQuery = rawurldecode($uri->toString(array('scheme', 'host', 'port', 'path', 'fragment')));
  110. $urlRelWithoutQuery = rawurldecode($uri->toString(array('path', 'fragment')));
  111. // Why is this (still) here?
  112. if ((strpos($url, 'mosConfig_') !== false) || (strpos($url, '=http://') !== false))
  113. {
  114. JErrorPage::render($error);
  115. }
  116. $db = JFactory::getDbo();
  117. $query = $db->getQuery(true);
  118. $query->select('*')
  119. ->from($db->quoteName('#__redirect_links'))
  120. ->where(
  121. '('
  122. . $db->quoteName('old_url') . ' = ' . $db->quote($url)
  123. . ' OR '
  124. . $db->quoteName('old_url') . ' = ' . $db->quote($urlRel)
  125. . ' OR '
  126. . $db->quoteName('old_url') . ' = ' . $db->quote($urlWithoutQuery)
  127. . ' OR '
  128. . $db->quoteName('old_url') . ' = ' . $db->quote($urlRelWithoutQuery)
  129. . ')'
  130. );
  131. $db->setQuery($query);
  132. $redirect = null;
  133. try
  134. {
  135. $redirects = $db->loadAssocList();
  136. }
  137. catch (Exception $e)
  138. {
  139. JErrorPage::render(new Exception(JText::_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'), 500, $e));
  140. }
  141. $possibleMatches = array_unique(
  142. array($url, $urlRel, $urlWithoutQuery, $urlRelWithoutQuery)
  143. );
  144. foreach ($possibleMatches as $match)
  145. {
  146. if (($index = array_search($match, array_column($redirects, 'old_url'))) !== false)
  147. {
  148. $redirect = (object) $redirects[$index];
  149. if ((int) $redirect->published === 1)
  150. {
  151. break;
  152. }
  153. }
  154. }
  155. // A redirect object was found and, if published, will be used
  156. if (!is_null($redirect) && ((int) $redirect->published === 1))
  157. {
  158. if (!$redirect->header || (bool) JComponentHelper::getParams('com_redirect')->get('mode', false) === false)
  159. {
  160. $redirect->header = 301;
  161. }
  162. if ($redirect->header < 400 && $redirect->header >= 300)
  163. {
  164. $urlQuery = $uri->getQuery();
  165. $oldUrlParts = parse_url($redirect->old_url);
  166. if (empty($oldUrlParts['query']) && $urlQuery !== '')
  167. {
  168. $redirect->new_url .= '?' . $urlQuery;
  169. }
  170. $destination = JUri::isInternal($redirect->new_url) ? JRoute::_($redirect->new_url) : $redirect->new_url;
  171. $app->redirect($destination, (int) $redirect->header);
  172. }
  173. JErrorPage::render(new RuntimeException($error->getMessage(), $redirect->header, $error));
  174. }
  175. // No redirect object was found so we create an entry in the redirect table
  176. elseif (is_null($redirect))
  177. {
  178. $params = new Registry(JPluginHelper::getPlugin('system', 'redirect')->params);
  179. if ((bool) $params->get('collect_urls', true))
  180. {
  181. $data = (object) array(
  182. 'id' => 0,
  183. 'old_url' => $url,
  184. 'referer' => $app->input->server->getString('HTTP_REFERER', ''),
  185. 'hits' => 1,
  186. 'published' => 0,
  187. 'created_date' => JFactory::getDate()->toSql()
  188. );
  189. try
  190. {
  191. $db->insertObject('#__redirect_links', $data, 'id');
  192. }
  193. catch (Exception $e)
  194. {
  195. JErrorPage::render(new Exception(JText::_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'), 500, $e));
  196. }
  197. }
  198. }
  199. // We have an unpublished redirect object, increment the hit counter
  200. else
  201. {
  202. $redirect->hits += 1;
  203. try
  204. {
  205. $db->updateObject('#__redirect_links', $redirect, 'id');
  206. }
  207. catch (Exception $e)
  208. {
  209. JErrorPage::render(new Exception(JText::_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'), 500, $e));
  210. }
  211. }
  212. JErrorPage::render($error);
  213. }
  214. }