[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\Mail; 11 12 use Joomla\CMS\Router\Route; 13 use Joomla\CMS\String\PunycodeHelper; 14 use Joomla\CMS\Uri\Uri; 15 16 // phpcs:disable PSR1.Files.SideEffects 17 \defined('JPATH_PLATFORM') or die; 18 // phpcs:enable PSR1.Files.SideEffects 19 20 /** 21 * Email helper class, provides static methods to perform various tasks relevant 22 * to the Joomla email routines. 23 * 24 * @todo: Test these methods as the regex work is first run and not tested thoroughly 25 * 26 * @since 1.7.0 27 */ 28 abstract class MailHelper 29 { 30 /** 31 * Cleans single line inputs. 32 * 33 * @param string $value String to be cleaned. 34 * 35 * @return string Cleaned string. 36 * 37 * @since 1.7.0 38 */ 39 public static function cleanLine($value) 40 { 41 $value = PunycodeHelper::emailToPunycode($value); 42 43 return trim(preg_replace('/(%0A|%0D|\n+|\r+)/i', '', $value)); 44 } 45 46 /** 47 * Cleans multi-line inputs. 48 * 49 * @param string $value Multi-line string to be cleaned. 50 * 51 * @return string Cleaned multi-line string. 52 * 53 * @since 1.7.0 54 */ 55 public static function cleanText($value) 56 { 57 return trim(preg_replace('/(%0A|%0D|\n+|\r+)(content-type:|to:|cc:|bcc:)/i', '', $value)); 58 } 59 60 /** 61 * Cleans any injected headers from the email body. 62 * 63 * @param string $body email body string. 64 * 65 * @return string Cleaned email body string. 66 * 67 * @since 1.7.0 68 */ 69 public static function cleanBody($body) 70 { 71 // Strip all email headers from a string 72 return preg_replace("/((From:|To:|Cc:|Bcc:|Subject:|Content-type:) ([\S]+))/", '', $body); 73 } 74 75 /** 76 * Cleans any injected headers from the subject string. 77 * 78 * @param string $subject email subject string. 79 * 80 * @return string Cleaned email subject string. 81 * 82 * @since 1.7.0 83 */ 84 public static function cleanSubject($subject) 85 { 86 return preg_replace("/((From:|To:|Cc:|Bcc:|Content-type:) ([\S]+))/", '', $subject); 87 } 88 89 /** 90 * Verifies that an email address does not have any extra headers injected into it. 91 * 92 * @param string $address email address. 93 * 94 * @return mixed email address string or boolean false if injected headers are present. 95 * 96 * @since 1.7.0 97 */ 98 public static function cleanAddress($address) 99 { 100 if (preg_match("[\s;,]", $address)) { 101 return false; 102 } 103 104 return $address; 105 } 106 107 /** 108 * Verifies that the string is in a proper email address format. 109 * 110 * @param string $email String to be verified. 111 * 112 * @return boolean True if string has the correct format; false otherwise. 113 * 114 * @since 1.7.0 115 */ 116 public static function isEmailAddress($email) 117 { 118 // Split the email into a local and domain 119 $atIndex = strrpos($email, '@'); 120 $domain = substr($email, $atIndex + 1); 121 $local = substr($email, 0, $atIndex); 122 123 // Check Length of domain 124 $domainLen = \strlen($domain); 125 126 if ($domainLen < 1 || $domainLen > 255) { 127 return false; 128 } 129 130 /* 131 * Check the local address 132 * We're a bit more conservative about what constitutes a "legal" address, that is, a-zA-Z0-9.!#$%&'*+/=?^_`{|}~- 133 * The first and last character in local cannot be a period ('.') 134 * Also, period should not appear 2 or more times consecutively 135 */ 136 $allowed = "a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-"; 137 $regex = "/^[$allowed][\.$allowed]{0,63}$/"; 138 139 if (!preg_match($regex, $local) || substr($local, -1) === '.' || $local[0] === '.' || preg_match('/\.\./', $local)) { 140 return false; 141 } 142 143 // No problem if the domain looks like an IP address, ish 144 $regex = '/^[0-9\.]+$/'; 145 146 if (preg_match($regex, $domain)) { 147 return true; 148 } 149 150 // Check Lengths 151 $localLen = \strlen($local); 152 153 if ($localLen < 1 || $localLen > 64) { 154 return false; 155 } 156 157 // Check the domain 158 $domain_array = explode('.', $domain); 159 $regex = '/^[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/'; 160 161 foreach ($domain_array as $domain) { 162 // Convert domain to punycode 163 $domain = PunycodeHelper::toPunycode($domain); 164 165 // Must be something 166 if (!$domain) { 167 return false; 168 } 169 170 // Check for invalid characters 171 if (!preg_match($regex, $domain)) { 172 return false; 173 } 174 175 // Check for a dash at the beginning of the domain 176 if (strpos($domain, '-') === 0) { 177 return false; 178 } 179 180 // Check for a dash at the end of the domain 181 $length = \strlen($domain) - 1; 182 183 if (strpos($domain, '-', $length) === $length) { 184 return false; 185 } 186 } 187 188 return true; 189 } 190 191 /** 192 * Convert relative (links, images sources) to absolute urls so that content is accessible in email 193 * 194 * @param string $content The content need to convert 195 * 196 * @return string The converted content which the relative urls are converted to absolute urls 197 * 198 * @since 4.1.0 199 */ 200 public static function convertRelativeToAbsoluteUrls($content) 201 { 202 $siteUrl = Uri::root(); 203 204 // Replace none SEF URLs by absolute SEF URLs 205 if (strpos($content, 'href="index.php?') !== false) { 206 preg_match_all('#href="index.php\?([^"]+)"#m', $content, $matches); 207 208 foreach ($matches[1] as $urlQueryString) { 209 $content = str_replace( 210 'href="index.php?' . $urlQueryString . '"', 211 'href="' . Route::link('site', 'index.php?' . $urlQueryString, Route::TLS_IGNORE, true) . '"', 212 $content 213 ); 214 } 215 216 self::checkContent($content); 217 } 218 219 // Replace relative links, image sources with absolute Urls 220 $protocols = '[a-zA-Z0-9\-]+:'; 221 $attributes = array('href=', 'src=', 'poster='); 222 223 foreach ($attributes as $attribute) { 224 if (strpos($content, $attribute) !== false) { 225 $regex = '#\s' . $attribute . '"(?!/|' . $protocols . '|\#|\')([^"]*)"#m'; 226 227 $content = preg_replace($regex, ' ' . $attribute . '"' . $siteUrl . '$1"', $content); 228 229 self::checkContent($content); 230 } 231 } 232 233 return $content; 234 } 235 236 /** 237 * Check the content after regular expression function call. 238 * 239 * @param string $content Content to be checked. 240 * 241 * @return void 242 * 243 * @throws \RuntimeException If there is an error in previous regular expression function call. 244 * @since 4.1.0 245 */ 246 private static function checkContent($content) 247 { 248 if ($content !== null) { 249 return; 250 } 251 252 switch (preg_last_error()) { 253 case PREG_BACKTRACK_LIMIT_ERROR: 254 $message = 'PHP regular expression limit reached (pcre.backtrack_limit)'; 255 break; 256 case PREG_RECURSION_LIMIT_ERROR: 257 $message = 'PHP regular expression limit reached (pcre.recursion_limit)'; 258 break; 259 case PREG_BAD_UTF8_ERROR: 260 $message = 'Bad UTF8 passed to PCRE function'; 261 break; 262 default: 263 $message = 'Unknown PCRE error calling PCRE function'; 264 } 265 266 throw new \RuntimeException($message); 267 } 268 }
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 |