[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/plugins/system/sef/ -> sef.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Plugin
   5   * @subpackage  System.sef
   6   *
   7   * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
   8   * @license     GNU General Public License version 2 or later; see LICENSE.txt
   9  
  10   * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
  11   */
  12  
  13  use Joomla\CMS\Plugin\CMSPlugin;
  14  use Joomla\CMS\Router\Route;
  15  use Joomla\CMS\Uri\Uri;
  16  
  17  // phpcs:disable PSR1.Files.SideEffects
  18  \defined('_JEXEC') or die;
  19  // phpcs:enable PSR1.Files.SideEffects
  20  
  21  /**
  22   * Joomla! SEF Plugin.
  23   *
  24   * @since  1.5
  25   */
  26  class PlgSystemSef extends CMSPlugin
  27  {
  28      /**
  29       * @var    \Joomla\CMS\Application\CMSApplication
  30       *
  31       * @since  3.5
  32       */
  33      protected $app;
  34  
  35      /**
  36       * Add the canonical uri to the head.
  37       *
  38       * @return  void
  39       *
  40       * @since   3.5
  41       */
  42      public function onAfterDispatch()
  43      {
  44          $doc = $this->app->getDocument();
  45  
  46          if (!$this->app->isClient('site') || $doc->getType() !== 'html') {
  47              return;
  48          }
  49  
  50          $sefDomain = $this->params->get('domain', false);
  51  
  52          // Don't add a canonical html tag if no alternative domain has added in SEF plugin domain field.
  53          if (empty($sefDomain)) {
  54              return;
  55          }
  56  
  57          // Check if a canonical html tag already exists (for instance, added by a component).
  58          $canonical = '';
  59  
  60          foreach ($doc->_links as $linkUrl => $link) {
  61              if (isset($link['relation']) && $link['relation'] === 'canonical') {
  62                  $canonical = $linkUrl;
  63                  break;
  64              }
  65          }
  66  
  67          // If a canonical html tag already exists get the canonical and change it to use the SEF plugin domain field.
  68          if (!empty($canonical)) {
  69              // Remove current canonical link.
  70              unset($doc->_links[$canonical]);
  71  
  72              // Set the current canonical link but use the SEF system plugin domain field.
  73              $canonical = $sefDomain . Uri::getInstance($canonical)->toString(array('path', 'query', 'fragment'));
  74          } else {
  75              // If a canonical html doesn't exists already add a canonical html tag using the SEF plugin domain field.
  76              $canonical = $sefDomain . Uri::getInstance()->toString(array('path', 'query', 'fragment'));
  77          }
  78  
  79          // Add the canonical link.
  80          $doc->addHeadLink(htmlspecialchars($canonical), 'canonical');
  81      }
  82  
  83      /**
  84       * Convert the site URL to fit to the HTTP request.
  85       *
  86       * @return  void
  87       */
  88      public function onAfterRender()
  89      {
  90          if (!$this->app->isClient('site')) {
  91              return;
  92          }
  93  
  94          // Replace src links.
  95          $base   = Uri::base(true) . '/';
  96          $buffer = $this->app->getBody();
  97  
  98          // For feeds we need to search for the URL with domain.
  99          $prefix = $this->app->getDocument()->getType() === 'feed' ? Uri::root() : '';
 100  
 101          // Replace index.php URI by SEF URI.
 102          if (strpos($buffer, 'href="' . $prefix . 'index.php?') !== false) {
 103              preg_match_all('#href="' . $prefix . 'index.php\?([^"]+)"#m', $buffer, $matches);
 104  
 105              foreach ($matches[1] as $urlQueryString) {
 106                  $buffer = str_replace(
 107                      'href="' . $prefix . 'index.php?' . $urlQueryString . '"',
 108                      'href="' . trim($prefix, '/') . Route::_('index.php?' . $urlQueryString) . '"',
 109                      $buffer
 110                  );
 111              }
 112  
 113              $this->checkBuffer($buffer);
 114          }
 115  
 116          // Check for all unknown protocols (a protocol must contain at least one alphanumeric character followed by a ":").
 117          $protocols  = '[a-zA-Z0-9\-]+:';
 118          $attributes = array('href=', 'src=', 'poster=');
 119  
 120          foreach ($attributes as $attribute) {
 121              if (strpos($buffer, $attribute) !== false) {
 122                  $regex  = '#\s' . $attribute . '"(?!/|' . $protocols . '|\#|\')([^"]*)"#m';
 123                  $buffer = preg_replace($regex, ' ' . $attribute . '"' . $base . '$1"', $buffer);
 124                  $this->checkBuffer($buffer);
 125              }
 126          }
 127  
 128          if (strpos($buffer, 'srcset=') !== false) {
 129              $regex = '#\s+srcset="([^"]+)"#m';
 130  
 131              $buffer = preg_replace_callback(
 132                  $regex,
 133                  function ($match) use ($base, $protocols) {
 134                      preg_match_all('#(?:[^\s]+)\s*(?:[\d\.]+[wx])?(?:\,\s*)?#i', $match[1], $matches);
 135  
 136                      foreach ($matches[0] as &$src) {
 137                          $src = preg_replace('#^(?!/|' . $protocols . '|\#|\')(.+)#', $base . '$1', $src);
 138                      }
 139  
 140                      return ' srcset="' . implode($matches[0]) . '"';
 141                  },
 142                  $buffer
 143              );
 144  
 145              $this->checkBuffer($buffer);
 146          }
 147  
 148          // Replace all unknown protocols in javascript window open events.
 149          if (strpos($buffer, 'window.open(') !== false) {
 150              $regex  = '#onclick="window.open\(\'(?!/|' . $protocols . '|\#)([^/]+[^\']*?\')#m';
 151              $buffer = preg_replace($regex, 'onclick="window.open(\'' . $base . '$1', $buffer);
 152              $this->checkBuffer($buffer);
 153          }
 154  
 155          // Replace all unknown protocols in onmouseover and onmouseout attributes.
 156          $attributes = array('onmouseover=', 'onmouseout=');
 157  
 158          foreach ($attributes as $attribute) {
 159              if (strpos($buffer, $attribute) !== false) {
 160                  $regex  = '#' . $attribute . '"this.src=([\']+)(?!/|' . $protocols . '|\#|\')([^"]+)"#m';
 161                  $buffer = preg_replace($regex, $attribute . '"this.src=$1' . $base . '$2"', $buffer);
 162                  $this->checkBuffer($buffer);
 163              }
 164          }
 165  
 166          // Replace all unknown protocols in CSS background image.
 167          if (strpos($buffer, 'style=') !== false) {
 168              $regex_url  = '\s*url\s*\(([\'\"]|\&\#0?3[49];)?(?!/|\&\#0?3[49];|' . $protocols . '|\#)([^\)\'\"]+)([\'\"]|\&\#0?3[49];)?\)';
 169              $regex  = '#style=\s*([\'\"])(.*):' . $regex_url . '#m';
 170              $buffer = preg_replace($regex, 'style=$1$2: url($3' . $base . '$4$5)', $buffer);
 171              $this->checkBuffer($buffer);
 172          }
 173  
 174          // Replace all unknown protocols in OBJECT param tag.
 175          if (strpos($buffer, '<param') !== false) {
 176              // OBJECT <param name="xx", value="yy"> -- fix it only inside the <param> tag.
 177              $regex  = '#(<param\s+)name\s*=\s*"(movie|src|url)"[^>]\s*value\s*=\s*"(?!/|' . $protocols . '|\#|\')([^"]*)"#m';
 178              $buffer = preg_replace($regex, '$1name="$2" value="' . $base . '$3"', $buffer);
 179              $this->checkBuffer($buffer);
 180  
 181              // OBJECT <param value="xx", name="yy"> -- fix it only inside the <param> tag.
 182              $regex  = '#(<param\s+[^>]*)value\s*=\s*"(?!/|' . $protocols . '|\#|\')([^"]*)"\s*name\s*=\s*"(movie|src|url)"#m';
 183              $buffer = preg_replace($regex, '<param value="' . $base . '$2" name="$3"', $buffer);
 184              $this->checkBuffer($buffer);
 185          }
 186  
 187          // Replace all unknown protocols in OBJECT tag.
 188          if (strpos($buffer, '<object') !== false) {
 189              $regex  = '#(<object\s+[^>]*)data\s*=\s*"(?!/|' . $protocols . '|\#|\')([^"]*)"#m';
 190              $buffer = preg_replace($regex, '$1data="' . $base . '$2"', $buffer);
 191              $this->checkBuffer($buffer);
 192          }
 193  
 194          // Use the replaced HTML body.
 195          $this->app->setBody($buffer);
 196      }
 197  
 198      /**
 199       * Check the buffer.
 200       *
 201       * @param   string  $buffer  Buffer to be checked.
 202       *
 203       * @return  void
 204       */
 205      private function checkBuffer($buffer)
 206      {
 207          if ($buffer === null) {
 208              switch (preg_last_error()) {
 209                  case PREG_BACKTRACK_LIMIT_ERROR:
 210                      $message = 'PHP regular expression limit reached (pcre.backtrack_limit)';
 211                      break;
 212                  case PREG_RECURSION_LIMIT_ERROR:
 213                      $message = 'PHP regular expression limit reached (pcre.recursion_limit)';
 214                      break;
 215                  case PREG_BAD_UTF8_ERROR:
 216                      $message = 'Bad UTF8 passed to PCRE function';
 217                      break;
 218                  default:
 219                      $message = 'Unknown PCRE error calling PCRE function';
 220              }
 221  
 222              throw new RuntimeException($message);
 223          }
 224      }
 225  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer