[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |