Skip to content
Snippets Groups Projects
Unverified Commit 88f605cf authored by Peter Rotich's avatar Peter Rotich Committed by GitHub
Browse files

Merge pull request #5131 from JediKev/issue/umlauts-sender-name

issue: Umlauts In Sender's Name
parents b58251df e3f42c33
No related branches found
No related tags found
No related merge requests found
...@@ -2,31 +2,33 @@ ...@@ -2,31 +2,33 @@
/** /**
* RFC 822 Email address list validation Utility * RFC 822 Email address list validation Utility
* *
* PHP versions 4 and 5 * PHP version 5
* *
* LICENSE: * LICENSE:
* *
* Copyright (c) 2001-2010, Richard Heyes * Copyright (c) 2001-2017, Chuck Hagenbuch & Richard Heyes
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* *
* o Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* o Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the * 2. Redistributions in binary form must reproduce the above copyright
* documentation and/or other materials provided with the distribution. * notice, this list of conditions and the following disclaimer in the
* o The names of the authors may not be used to endorse or promote * documentation and/or other materials provided with the distribution.
* products derived from this software without specific prior written *
* permission. * 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
...@@ -38,9 +40,9 @@ ...@@ -38,9 +40,9 @@
* @package Mail * @package Mail
* @author Richard Heyes <richard@phpguru.org> * @author Richard Heyes <richard@phpguru.org>
* @author Chuck Hagenbuch <chuck@horde.org * @author Chuck Hagenbuch <chuck@horde.org
* @copyright 2001-2010 Richard Heyes * @copyright 2001-2017 Richard Heyes
* @license http://opensource.org/licenses/bsd-license.php New BSD License * @license http://opensource.org/licenses/BSD-3-Clause New BSD License
* @version CVS: $Id: RFC822.php 294749 2010-02-08 08:22:25Z clockwerx $ * @version CVS: $Id$
* @link http://pear.php.net/package/Mail/ * @link http://pear.php.net/package/Mail/
*/ */
...@@ -63,7 +65,7 @@ ...@@ -63,7 +65,7 @@
* *
* @author Richard Heyes <richard@phpguru.org> * @author Richard Heyes <richard@phpguru.org>
* @author Chuck Hagenbuch <chuck@horde.org> * @author Chuck Hagenbuch <chuck@horde.org>
* @version $Revision: 294749 $ * @version $Revision$
* @license BSD * @license BSD
* @package Mail * @package Mail
*/ */
...@@ -141,7 +143,6 @@ class Mail_RFC822 { ...@@ -141,7 +143,6 @@ class Mail_RFC822 {
* Sets up the object. The address must either be set here or when * Sets up the object. The address must either be set here or when
* calling parseAddressList(). One or the other. * calling parseAddressList(). One or the other.
* *
* @access public
* @param string $address The address(es) to validate. * @param string $address The address(es) to validate.
* @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost. * @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost.
* @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
...@@ -149,7 +150,7 @@ class Mail_RFC822 { ...@@ -149,7 +150,7 @@ class Mail_RFC822 {
* *
* @return object Mail_RFC822 A new Mail_RFC822 object. * @return object Mail_RFC822 A new Mail_RFC822 object.
*/ */
function __construct($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) public function __construct($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
{ {
if (isset($address)) $this->address = $address; if (isset($address)) $this->address = $address;
if (isset($default_domain)) $this->default_domain = $default_domain; if (isset($default_domain)) $this->default_domain = $default_domain;
...@@ -162,7 +163,6 @@ class Mail_RFC822 { ...@@ -162,7 +163,6 @@ class Mail_RFC822 {
* Starts the whole process. The address must either be set here * Starts the whole process. The address must either be set here
* or when creating the object. One or the other. * or when creating the object. One or the other.
* *
* @access public
* @param string $address The address(es) to validate. * @param string $address The address(es) to validate.
* @param string $default_domain Default domain/host etc. * @param string $default_domain Default domain/host etc.
* @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
...@@ -170,7 +170,7 @@ class Mail_RFC822 { ...@@ -170,7 +170,7 @@ class Mail_RFC822 {
* *
* @return array A structured array of addresses. * @return array A structured array of addresses.
*/ */
function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) public function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
{ {
if (!isset($this) || !isset($this->mailRFC822)) { if (!isset($this) || !isset($this->mailRFC822)) {
$obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit); $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit);
...@@ -222,11 +222,10 @@ class Mail_RFC822 { ...@@ -222,11 +222,10 @@ class Mail_RFC822 {
/** /**
* Splits an address into separate addresses. * Splits an address into separate addresses.
* *
* @access private
* @param string $address The addresses to split. * @param string $address The addresses to split.
* @return boolean Success or failure. * @return boolean Success or failure.
*/ */
function _splitAddresses($address) protected function _splitAddresses($address)
{ {
if (!empty($this->limit) && count($this->addresses) == $this->limit) { if (!empty($this->limit) && count($this->addresses) == $this->limit) {
return ''; return '';
...@@ -298,11 +297,10 @@ class Mail_RFC822 { ...@@ -298,11 +297,10 @@ class Mail_RFC822 {
/** /**
* Checks for a group at the start of the string. * Checks for a group at the start of the string.
* *
* @access private
* @param string $address The address to check. * @param string $address The address to check.
* @return boolean Whether or not there is a group at the start of the string. * @return boolean Whether or not there is a group at the start of the string.
*/ */
function _isGroup($address) protected function _isGroup($address)
{ {
// First comma not in quotes, angles or escaped: // First comma not in quotes, angles or escaped:
$parts = explode(',', $address); $parts = explode(',', $address);
...@@ -322,12 +320,11 @@ class Mail_RFC822 { ...@@ -322,12 +320,11 @@ class Mail_RFC822 {
/** /**
* A common function that will check an exploded string. * A common function that will check an exploded string.
* *
* @access private
* @param array $parts The exloded string. * @param array $parts The exloded string.
* @param string $char The char that was exploded on. * @param string $char The char that was exploded on.
* @return mixed False if the string contains unclosed quotes/brackets, or the string on success. * @return mixed False if the string contains unclosed quotes/brackets, or the string on success.
*/ */
function _splitCheck($parts, $char) protected function _splitCheck($parts, $char)
{ {
$string = $parts[0]; $string = $parts[0];
...@@ -355,22 +352,19 @@ class Mail_RFC822 { ...@@ -355,22 +352,19 @@ class Mail_RFC822 {
/** /**
* Checks if a string has unclosed quotes or not. * Checks if a string has unclosed quotes or not.
* *
* @access private
* @param string $string The string to check. * @param string $string The string to check.
* @return boolean True if there are unclosed quotes inside the string, * @return boolean True if there are unclosed quotes inside the string,
* false otherwise. * false otherwise.
*/ */
function _hasUnclosedQuotes($string) protected function _hasUnclosedQuotes($string)
{ {
$matches = array(); $string = trim($string);
if (!preg_match_all('/[\\"]/', trim($string), $matches)) $iMax = strlen($string);
return false;
$in_quote = false; $in_quote = false;
$slashes = 0; $i = $slashes = 0;
foreach ($matches[0] as $m) { for (; $i < $iMax; ++$i) {
switch ($m) { switch ($string[$i]) {
case '\\': case '\\':
++$slashes; ++$slashes;
break; break;
...@@ -394,12 +388,11 @@ class Mail_RFC822 { ...@@ -394,12 +388,11 @@ class Mail_RFC822 {
* Checks if a string has an unclosed brackets or not. IMPORTANT: * Checks if a string has an unclosed brackets or not. IMPORTANT:
* This function handles both angle brackets and square brackets; * This function handles both angle brackets and square brackets;
* *
* @access private
* @param string $string The string to check. * @param string $string The string to check.
* @param string $chars The characters to check for. * @param string $chars The characters to check for.
* @return boolean True if there are unclosed brackets inside the string, false otherwise. * @return boolean True if there are unclosed brackets inside the string, false otherwise.
*/ */
function _hasUnclosedBrackets($string, $chars) protected function _hasUnclosedBrackets($string, $chars)
{ {
$num_angle_start = substr_count($string, $chars[0]); $num_angle_start = substr_count($string, $chars[0]);
$num_angle_end = substr_count($string, $chars[1]); $num_angle_end = substr_count($string, $chars[1]);
...@@ -418,16 +411,15 @@ class Mail_RFC822 { ...@@ -418,16 +411,15 @@ class Mail_RFC822 {
/** /**
* Sub function that is used only by hasUnclosedBrackets(). * Sub function that is used only by hasUnclosedBrackets().
* *
* @access private
* @param string $string The string to check. * @param string $string The string to check.
* @param integer &$num The number of occurences. * @param integer &$num The number of occurences.
* @param string $char The character to count. * @param string $char The character to count.
* @return integer The number of occurences of $char in $string, adjusted for backslashes. * @return integer The number of occurences of $char in $string, adjusted for backslashes.
*/ */
function _hasUnclosedBracketsSub($string, &$num, $char) protected function _hasUnclosedBracketsSub($string, &$num, $char)
{ {
$parts = explode($char, $string); $parts = explode($char, $string);
for ($i = 0, $k = count($parts); $i < $k; $i++){ for ($i = 0; $i < count($parts); $i++){
if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i])) if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i]))
$num--; $num--;
if (isset($parts[$i + 1])) if (isset($parts[$i + 1]))
...@@ -440,11 +432,10 @@ class Mail_RFC822 { ...@@ -440,11 +432,10 @@ class Mail_RFC822 {
/** /**
* Function to begin checking the address. * Function to begin checking the address.
* *
* @access private
* @param string $address The address to validate. * @param string $address The address to validate.
* @return mixed False on failure, or a structured array of address information on success. * @return mixed False on failure, or a structured array of address information on success.
*/ */
function _validateAddress($address) protected function _validateAddress($address)
{ {
$is_group = false; $is_group = false;
$addresses = array(); $addresses = array();
...@@ -485,14 +476,6 @@ class Mail_RFC822 { ...@@ -485,14 +476,6 @@ class Mail_RFC822 {
$addresses[] = $address['address']; $addresses[] = $address['address'];
} }
// Check that $addresses is set, if address like this:
// Groupname:;
// Then errors were appearing.
if (!count($addresses)){
$this->error = 'Empty group.';
return false;
}
// Trim the whitespace from all of the address strings. // Trim the whitespace from all of the address strings.
array_map('trim', $addresses); array_map('trim', $addresses);
...@@ -533,11 +516,10 @@ class Mail_RFC822 { ...@@ -533,11 +516,10 @@ class Mail_RFC822 {
/** /**
* Function to validate a phrase. * Function to validate a phrase.
* *
* @access private
* @param string $phrase The phrase to check. * @param string $phrase The phrase to check.
* @return boolean Success or failure. * @return boolean Success or failure.
*/ */
function _validatePhrase($phrase) protected function _validatePhrase($phrase)
{ {
// Splits on one or more Tab or space. // Splits on one or more Tab or space.
$parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY); $parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);
...@@ -574,11 +556,10 @@ class Mail_RFC822 { ...@@ -574,11 +556,10 @@ class Mail_RFC822 {
* can split a list of addresses up before encoding personal names * can split a list of addresses up before encoding personal names
* (umlauts, etc.), for example. * (umlauts, etc.), for example.
* *
* @access private
* @param string $atom The string to check. * @param string $atom The string to check.
* @return boolean Success or failure. * @return boolean Success or failure.
*/ */
function _validateAtom($atom) protected function _validateAtom($atom)
{ {
if (!$this->validate) { if (!$this->validate) {
// Validation has been turned off; assume the atom is okay. // Validation has been turned off; assume the atom is okay.
...@@ -607,11 +588,10 @@ class Mail_RFC822 { ...@@ -607,11 +588,10 @@ class Mail_RFC822 {
* Function to validate quoted string, which is: * Function to validate quoted string, which is:
* quoted-string = <"> *(qtext/quoted-pair) <"> * quoted-string = <"> *(qtext/quoted-pair) <">
* *
* @access private
* @param string $qstring The string to check * @param string $qstring The string to check
* @return boolean Success or failure. * @return boolean Success or failure.
*/ */
function _validateQuotedString($qstring) protected function _validateQuotedString($qstring)
{ {
// Leading and trailing " // Leading and trailing "
$qstring = substr($qstring, 1, -1); $qstring = substr($qstring, 1, -1);
...@@ -625,11 +605,10 @@ class Mail_RFC822 { ...@@ -625,11 +605,10 @@ class Mail_RFC822 {
* mailbox = addr-spec ; simple address * mailbox = addr-spec ; simple address
* / phrase route-addr ; name and route-addr * / phrase route-addr ; name and route-addr
* *
* @access public
* @param string &$mailbox The string to check. * @param string &$mailbox The string to check.
* @return boolean Success or failure. * @return boolean Success or failure.
*/ */
function validateMailbox(&$mailbox) public function validateMailbox(&$mailbox)
{ {
// A couple of defaults. // A couple of defaults.
$phrase = ''; $phrase = '';
...@@ -714,11 +693,10 @@ class Mail_RFC822 { ...@@ -714,11 +693,10 @@ class Mail_RFC822 {
* Angle brackets have already been removed at the point of * Angle brackets have already been removed at the point of
* getting to this function. * getting to this function.
* *
* @access private
* @param string $route_addr The string to check. * @param string $route_addr The string to check.
* @return mixed False on failure, or an array containing validated address/route information on success. * @return mixed False on failure, or an array containing validated address/route information on success.
*/ */
function _validateRouteAddr($route_addr) protected function _validateRouteAddr($route_addr)
{ {
// Check for colon. // Check for colon.
if (strpos($route_addr, ':') !== false) { if (strpos($route_addr, ':') !== false) {
...@@ -764,11 +742,10 @@ class Mail_RFC822 { ...@@ -764,11 +742,10 @@ class Mail_RFC822 {
* Function to validate a route, which is: * Function to validate a route, which is:
* route = 1#("@" domain) ":" * route = 1#("@" domain) ":"
* *
* @access private
* @param string $route The string to check. * @param string $route The string to check.
* @return mixed False on failure, or the validated $route on success. * @return mixed False on failure, or the validated $route on success.
*/ */
function _validateRoute($route) protected function _validateRoute($route)
{ {
// Split on comma. // Split on comma.
$domains = explode(',', trim($route)); $domains = explode(',', trim($route));
...@@ -787,11 +764,10 @@ class Mail_RFC822 { ...@@ -787,11 +764,10 @@ class Mail_RFC822 {
* *
* domain = sub-domain *("." sub-domain) * domain = sub-domain *("." sub-domain)
* *
* @access private
* @param string $domain The string to check. * @param string $domain The string to check.
* @return mixed False on failure, or the validated domain on success. * @return mixed False on failure, or the validated domain on success.
*/ */
function _validateDomain($domain) protected function _validateDomain($domain)
{ {
// Note the different use of $subdomains and $sub_domains // Note the different use of $subdomains and $sub_domains
$subdomains = explode('.', $domain); $subdomains = explode('.', $domain);
...@@ -815,11 +791,10 @@ class Mail_RFC822 { ...@@ -815,11 +791,10 @@ class Mail_RFC822 {
* Function to validate a subdomain: * Function to validate a subdomain:
* subdomain = domain-ref / domain-literal * subdomain = domain-ref / domain-literal
* *
* @access private
* @param string $subdomain The string to check. * @param string $subdomain The string to check.
* @return boolean Success or failure. * @return boolean Success or failure.
*/ */
function _validateSubdomain($subdomain) protected function _validateSubdomain($subdomain)
{ {
if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){ if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){
if (!$this->_validateDliteral($arr[1])) return false; if (!$this->_validateDliteral($arr[1])) return false;
...@@ -835,13 +810,12 @@ class Mail_RFC822 { ...@@ -835,13 +810,12 @@ class Mail_RFC822 {
* Function to validate a domain literal: * Function to validate a domain literal:
* domain-literal = "[" *(dtext / quoted-pair) "]" * domain-literal = "[" *(dtext / quoted-pair) "]"
* *
* @access private
* @param string $dliteral The string to check. * @param string $dliteral The string to check.
* @return boolean Success or failure. * @return boolean Success or failure.
*/ */
function _validateDliteral($dliteral) protected function _validateDliteral($dliteral)
{ {
return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && $matches[1] != '\\'; return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && ((! isset($matches[1])) || $matches[1] != '\\');
} }
/** /**
...@@ -849,11 +823,10 @@ class Mail_RFC822 { ...@@ -849,11 +823,10 @@ class Mail_RFC822 {
* *
* addr-spec = local-part "@" domain * addr-spec = local-part "@" domain
* *
* @access private
* @param string $addr_spec The string to check. * @param string $addr_spec The string to check.
* @return mixed False on failure, or the validated addr-spec on success. * @return mixed False on failure, or the validated addr-spec on success.
*/ */
function _validateAddrSpec($addr_spec) protected function _validateAddrSpec($addr_spec)
{ {
$addr_spec = trim($addr_spec); $addr_spec = trim($addr_spec);
...@@ -880,17 +853,16 @@ class Mail_RFC822 { ...@@ -880,17 +853,16 @@ class Mail_RFC822 {
* Function to validate the local part of an address: * Function to validate the local part of an address:
* local-part = word *("." word) * local-part = word *("." word)
* *
* @access private
* @param string $local_part * @param string $local_part
* @return mixed False on failure, or the validated local part on success. * @return mixed False on failure, or the validated local part on success.
*/ */
function _validateLocalPart($local_part) protected function _validateLocalPart($local_part)
{ {
$parts = explode('.', $local_part); $parts = explode('.', $local_part);
$words = array(); $words = array();
// Split the local_part into words. // Split the local_part into words.
while (count($parts) > 0){ while (count($parts) > 0) {
$words[] = $this->_splitCheck($parts, '.'); $words[] = $this->_splitCheck($parts, '.');
for ($i = 0; $i < $this->index + 1; $i++) { for ($i = 0; $i < $this->index + 1; $i++) {
array_shift($parts); array_shift($parts);
...@@ -899,6 +871,10 @@ class Mail_RFC822 { ...@@ -899,6 +871,10 @@ class Mail_RFC822 {
// Validate each word. // Validate each word.
foreach ($words as $word) { foreach ($words as $word) {
// word cannot be empty (#17317)
if ($word === '') {
return false;
}
// If this word contains an unquoted space, it is invalid. (6.2.4) // If this word contains an unquoted space, it is invalid. (6.2.4)
if (strpos($word, ' ') && $word[0] !== '"') if (strpos($word, ' ') && $word[0] !== '"')
{ {
...@@ -922,7 +898,7 @@ class Mail_RFC822 { ...@@ -922,7 +898,7 @@ class Mail_RFC822 {
* @param string $data Addresses to count * @param string $data Addresses to count
* @return int Approximate count * @return int Approximate count
*/ */
function approximateCount($data) public function approximateCount($data)
{ {
return count(preg_split('/(?<!\\\\),/', $data)); return count(preg_split('/(?<!\\\\),/', $data));
} }
...@@ -940,7 +916,7 @@ class Mail_RFC822 { ...@@ -940,7 +916,7 @@ class Mail_RFC822 {
* @return mixed False if it fails, an indexed array * @return mixed False if it fails, an indexed array
* username/domain if it matches * username/domain if it matches
*/ */
function isValidInetAddress($data, $strict = false) public function isValidInetAddress($data, $strict = false)
{ {
$regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i'; $regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i';
if (preg_match($regex, trim($data), $matches)) { if (preg_match($regex, trim($data), $matches)) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment