3declare(strict_types=1);
157 ?
bool $nest_groups =
null,
167 if (isset($nest_groups)) {
168 $this->nestGroups = $nest_groups;
192 ?
bool $nest_groups =
null,
196 if (!isset($this, $this->mailRFC822)) {
198 return $obj->parseAddressList();
207 if (isset($nest_groups)) {
208 $this->nestGroups = $nest_groups;
217 $this->structure = [];
218 $this->addresses = [];
223 $this->address = preg_replace(
'/\r?\n/',
"\r\n", $this->address);
224 $this->address = preg_replace(
'/\r\n(\t| )+/',
' ', $this->address);
227 $this->address = $tmp_address;
230 if ($tmp_address ===
false || isset($this->
error)) {
238 foreach ($this->addresses as
$address) {
247 if (!$this->nestGroups) {
248 $this->structure = array_merge($this->structure,
$valid);
250 $this->structure[] =
$valid;
265 if (!empty($this->limit) && count($this->addresses) === $this->limit) {
269 if (!isset($this->
error) && $this->_isGroup($address)) {
272 } elseif (!isset($this->
error)) {
275 } elseif (isset($this->
error)) {
280 $parts = explode($split_char, $address);
281 $string = $this->_splitCheck(
$parts, $split_char);
289 if (strpos($string,
':') ===
false) {
290 $this->
error =
'Invalid address: ' . $string;
295 if (!$this->_splitCheck(explode(
':', $string),
':')) {
305 $this->addresses[] = [
306 'address' => trim($string),
307 'group' => $is_group,
312 $address = trim((
string) substr($address, strlen($string) + 1));
317 if ($is_group && $address !==
'' && str_starts_with($address,
',')) {
318 $address = trim(substr($address, 1));
333 $parts = explode(
',', $address);
334 $string = $this->_splitCheck(
$parts,
',');
339 if (count(
$parts = explode(
':', $string)) > 1) {
340 $string2 = $this->_splitCheck(
$parts,
':');
341 return ($string2 !== $string);
358 for ($i = 0, $iMax = count(
$parts); $i < $iMax; $i++) {
359 if ($this->_hasUnclosedQuotes($string)
360 || $this->_hasUnclosedBrackets($string,
'<>')
361 || $this->_hasUnclosedBrackets($string,
'[]')
362 || $this->_hasUnclosedBrackets($string,
'()')
363 || substr($string, -1) ===
'\\') {
364 if (isset(
$parts[$i + 1])) {
365 $string .= $char .
$parts[$i + 1];
367 $this->
error =
'Invalid address spec. Unclosed bracket or quotes';
387 $string = trim($string);
388 $iMax = strlen($string);
392 for (; $i < $iMax; ++$i) {
393 switch ($string[$i]) {
399 if ($slashes % 2 === 0) {
400 $in_quote = !$in_quote;
424 $num_angle_start = substr_count($string, $chars[0]);
425 $num_angle_end = substr_count($string, $chars[1]);
427 $this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]);
428 $this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);
430 if ($num_angle_start < $num_angle_end) {
431 $this->
error =
'Invalid address spec. Unmatched quote or bracket (' . $chars .
')';
435 return ($num_angle_start > $num_angle_end);
448 $parts = explode($char, $string);
449 for ($i = 0, $iMax = count(
$parts); $i < $iMax; $i++) {
450 if (substr(
$parts[$i], -1) ===
'\\' || $this->_hasUnclosedQuotes(
$parts[$i])) {
453 if (isset(
$parts[$i + 1])) {
472 if ($address[
'group']) {
476 $parts = explode(
':', $address[
'address']);
477 $groupname = $this->_splitCheck(
$parts,
':');
481 if (!$this->_validatePhrase($groupname)) {
482 $this->
error =
'Group name did not validate.';
486 if ($this->nestGroups) {
493 $address[
'address'] = ltrim(substr($address[
'address'], strlen($groupname .
':')));
499 while (strlen($address[
'address']) > 0) {
500 $parts = explode(
',', $address[
'address']);
501 $addresses[] = $this->_splitCheck(
$parts,
',');
502 $address[
'address'] = trim(substr($address[
'address'], strlen(end($addresses) .
',')));
505 $addresses[] = $address[
'address'];
509 array_map(
'trim', $addresses);
516 for ($i = 0, $iMax = count($addresses); $i < $iMax; $i++) {
517 if (!$this->validateMailbox($addresses[$i])) {
518 if (empty($this->
error)) {
519 $this->
error =
'Validation failed for: ' . $addresses[$i];
526 if ($this->nestGroups) {
534 } elseif ($is_group) {
552 $parts = preg_split(
'/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);
555 while (count(
$parts) > 0) {
556 $phrase_parts[] = $this->_splitCheck(
$parts,
' ');
557 for ($i = 0; $i < $this->index + 1; $i++) {
562 foreach ($phrase_parts as $part) {
564 if (strpos($part,
'"') === 0) {
565 if (!$this->_validateQuotedString($part)) {
572 if (!$this->_validateAtom($part)) {
594 if (!$this->validate) {
602 if (preg_match(
'/[][()<>@,;\\:". ]/', $atom)) {
607 if (preg_match(
'/[\\x00-\\x1F]+/', $atom)) {
612 if (!(
bool) preg_match(
'//u', $atom)) {
630 $qstring = substr($qstring, 1, -1);
633 return !preg_match(
'/[\x0D\\\\"]/', preg_replace(
'/\\\\./',
'', $qstring));
652 $_mailbox = $mailbox;
653 while (trim($_mailbox) !==
'') {
654 $parts = explode(
'(', $_mailbox);
655 $before_comment = $this->_splitCheck(
$parts,
'(');
656 if ($before_comment !== $_mailbox) {
658 $comment = substr(str_replace($before_comment,
'', $_mailbox), 1);
664 $_mailbox = substr($_mailbox, strpos($_mailbox,
'(' .
$comment) + strlen(
$comment) + 2);
671 $mailbox = str_replace(
"($comment)",
'', $mailbox);
674 $mailbox = trim($mailbox);
677 if (substr($mailbox, -1) ===
'>' && $mailbox[0] !==
'<') {
678 $parts = explode(
'<', $mailbox);
679 $name = $this->_splitCheck(
$parts,
'<');
681 $phrase = trim($name);
682 $route_addr = trim(substr($mailbox, strlen($name .
'<'), -1));
684 if ($this->_validatePhrase($phrase) ===
false ||
685 ($route_addr = $this->_validateRouteAddr($route_addr)) ===
false) {
692 if ($mailbox[0] ===
'<' && substr($mailbox, -1) ===
'>') {
693 $addr_spec = substr($mailbox, 1, -1);
695 $addr_spec = $mailbox;
698 if (($addr_spec = $this->_validateAddrSpec($addr_spec)) ===
false) {
704 $mbox =
new stdClass();
707 $mbox->personal = $phrase;
710 if (isset($route_addr)) {
711 $mbox->mailbox = $route_addr[
'local_part'];
712 $mbox->host = $route_addr[
'domain'];
713 if ($route_addr[
'adl'] !==
'') {
714 $mbox->adl = $route_addr[
'adl'];
717 $mbox->mailbox = $addr_spec[
'local_part'];
718 $mbox->host = $addr_spec[
'domain'];
738 if (strpos($route_addr,
':') !==
false) {
739 $parts = explode(
':', $route_addr);
740 $route = $this->_splitCheck(
$parts,
':');
742 $route = $route_addr;
747 if ($route === $route_addr) {
749 $addr_spec = $route_addr;
750 if (($addr_spec = $this->_validateAddrSpec($addr_spec)) ===
false) {
755 if (($route = $this->_validateRoute($route)) ===
false) {
759 $addr_spec = substr($route_addr, strlen($route .
':'));
762 if (($addr_spec = $this->_validateAddrSpec($addr_spec)) ===
false) {
768 $return[
'adl'] = $route;
773 $return = array_merge($return, $addr_spec);
787 $domains = explode(
',', trim($route));
789 foreach ($domains as $domain) {
790 $domain = str_replace(
'@',
'', trim($domain));
791 if (!$this->_validateDomain($domain)) {
811 $subdomains = explode(
'.', $domain);
814 while (count($subdomains) > 0) {
815 $sub_domains[] = $this->_splitCheck($subdomains,
'.');
816 for ($i = 0; $i < $this->index + 1; $i++) {
817 array_shift($subdomains);
821 foreach ($sub_domains as $sub_domain) {
822 if (!$this->_validateSubdomain(trim($sub_domain))) {
840 if (preg_match(
'|^\[(.*)]$|', $subdomain, $arr)) {
841 if (!$this->_validateDliteral($arr[1])) {
844 } elseif (!$this->_validateAtom($subdomain)) {
861 return !preg_match(
'/(.)[][\x0D\\\\]/', $dliteral, $matches) &&
862 ((!isset($matches[1])) || $matches[1] !=
'\\');
875 $addr_spec = trim($addr_spec);
878 $validateState = $this->validate;
881 if (strpos($addr_spec,
'@') !==
false) {
882 $parts = explode(
'@', $addr_spec);
883 $local_part = $this->_splitCheck(
$parts,
'@');
884 $domain = substr($addr_spec, strlen($local_part .
'@'));
886 if (substr_count($addr_spec,
'@') !== 1 && $local_part ===
'') {
887 $this->validate =
false;
888 $local_part = $addr_spec;
889 $domain = $this->default_domain;
894 $local_part = $addr_spec;
895 $domain = $this->default_domain;
898 if (($local_part = $this->_validateLocalPart($local_part)) ===
false) {
902 if ($validateState !== $this->validate) {
903 $this->validate = $validateState;
906 if (($domain = $this->_validateDomain($domain)) ===
false) {
911 return [
'local_part' => $local_part,
'domain' => $domain];
924 $parts = explode(
'.', $local_part);
928 while (count(
$parts) > 0) {
929 $words[] = $this->_splitCheck(
$parts,
'.');
930 for ($i = 0; $i < $this->index + 1; $i++) {
936 foreach ($words as $word) {
944 if (strpos($word,
' ') && $word[0] !==
'"') {
952 if ($this->_validatePhrase(trim($word)) ===
false) {
973 return count(preg_split(
'/(?<!\\\\),/',
$data));
993 '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' :
994 '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i';
995 if (preg_match($regex, trim(
$data), $matches)) {
996 return [$matches[1], $matches[2]];
$structure
TOTAL STRUCTURE.
_hasUnclosedBracketsSub(string $string, int &$num, string $char)
Sub function that is used only by hasUnclosedBrackets().
bool $validate
Whether or not to validate atoms for non-ascii characters.
string $error
The current error message, if any.
_validateRouteAddr(string $route_addr)
This function validates a route-addr which is: route-addr = "<" [route] addr-spec ">".
_splitCheck(array $parts, string $char)
A common function that will check an exploded string.
_splitAddresses(string $address)
Splits an address into separate addresses.
_validateAddress(array $address)
Function to begin checking the address.
approximateCount(string $data)
Returns an approximate count of how many addresses are in the given string.
_validateDliteral(string $dliteral)
Function to validate a domain literal: domain-literal = "[" *(dtext / quoted-pair) "]".
int $index
An internal counter/pointer.
_validateQuotedString(string $qstring)
Function to validate quoted string, which is: quoted-string = <"> *(qtext/quoted-pair) <">
array $structure
The final array of parsed address information that we build up.
string $default_domain
The default domain to use for unqualified addresses.
_validatePhrase(string $phrase)
Function to validate a phrase.
isValidInetAddress(string $data, bool $strict=false)
This is a email validating function separate to the rest of the class.
_validateRoute(string $route)
Function to validate a route, which is: route = 1#("@" domain) ":".
_validateDomain(string $domain)
Function to validate a domain, though this is not quite what you expect of a strict internet domain.
__construct(?string $address=null, ?string $default_domain=null, ?bool $nest_groups=null, ?bool $validate=null, ?int $limit=null)
Sets up the object.
_isGroup(string $address)
Checks for a group at the start of the string.
int $num_groups
The number of groups that have been found in the address list.
validateMailbox(string &$mailbox)
Function to validate a mailbox, which is: mailbox = addr-spec ; simple address / phrase route-addr ; ...
_hasUnclosedBrackets(string $string, string $chars)
Checks if a string has an unclosed brackets or not.
bool $mailRFC822
A variable so that we can tell whether or not we're inside a Mail_RFC822 object.
parseAddressList(?string $address=null, ?string $default_domain=null, ?bool $nest_groups=null, ?bool $validate=null, ?int $limit=null)
Starts the whole process.
array $addresses
The array of raw addresses built up as we parse.
_validateAtom(string $atom)
Function to validate an atom which from rfc822 is: atom = 1*<any CHAR except specials,...
_hasUnclosedQuotes(string $string)
Checks if a string has unclosed quotes or not.
bool $nestGroups
Should we return a nested array showing groups, or flatten everything?
string $address
The address being parsed by the RFC822 object.
int $limit
A limit after which processing stops.
_validateLocalPart(string $local_part)
Function to validate the local part of an address: local-part = word *("." word)
_validateAddrSpec(string $addr_spec)
Function to validate an addr-spec.
_validateSubdomain(string $subdomain)
Function to validate a subdomain: subdomain = domain-ref / domain-literal.
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
if(!file_exists('../ilias.ini.php'))