From 54dc648b185a0ee13e1159b472f819f6c3cae390 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Fri, 18 Apr 2014 12:51:17 +0000 Subject: [PATCH] an implementation of imap_rfc822_parse_adrlist and imap_rfc822_write_address, to obsolete imap extension --- phpgwapi/inc/common_functions.inc.php | 74 ++++++++++++++++++++++----- phpgwapi/tests/rfc822.php | 41 +++++++++++++++ 2 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 phpgwapi/tests/rfc822.php diff --git a/phpgwapi/inc/common_functions.inc.php b/phpgwapi/inc/common_functions.inc.php index 46f3921a59..59f4171708 100755 --- a/phpgwapi/inc/common_functions.inc.php +++ b/phpgwapi/inc/common_functions.inc.php @@ -73,11 +73,20 @@ function cut_bytes(&$data,$offset,$len=null) if (!function_exists('imap_rfc822_parse_adrlist')) { /** - * parses an address string - * Examples: Joe Doe , "Doe, Joe" , "\'Joe Doe\'" , - * postmaster@example.com, root, "Joe on its way Down Under :-\)" , - * "Giant; \"Big\" Box" , sysservices@example.net , + * parses a (comma-separated) address string + * + * Examples: + * - Joe Doe + * - "Doe, Joe" + * - "\'Joe Doe\'" // actually not necessary to quote + * - postmaster@example.com + * - root + * - "Joe on its way Down Under :-\)" + * - "Giant; \"Big\" Box" + * - sysservices@example.net // this is wrong, because @ need to be quoted + * * Invalid addresses, if detected, set host to '.SYNTAX-ERROR.' + * * @param string $address - A string containing addresses * @param string $default_host - The default host name * @return array of objects. The objects properties are: @@ -86,10 +95,48 @@ if (!function_exists('imap_rfc822_parse_adrlist')) * personal - the personal name * adl - at domain source route */ - //function imap_rfc822_parse_adrlist(string $address, string $default_host) - //{ - // return array(); - //} + function imap_rfc822_parse_adrlist($address, $default_host) + { + $addresses = array(); + $pending = ''; + foreach(explode(',', $address) as $part) + { + $trimmed = trim(($pending ? $pending.',' : '').$part); + if ($trimmed[0] == '"' && substr($trimmed, -1) != '>') + { + $pending .= ($pending ? $pending.',' : '').$part; + continue; + } + $pending = ''; + $matches = $personal = $mailbox = $host = null; + if (preg_match('/^(.*)<([^>@]+)(@([^>]+))?>$/', $trimmed, $matches)) + { + $personal = trim($matches[1]); + $mailbox = $matches[2]; + $host = $matches[4]; + } + elseif (strpos($trimmed, '@') !== false) + { + list($mailbox, $host) = explode('@', $trimmed); + } + else + { + $mailbox = $trimmed; + } + if ($personal[0] == '"' && substr($personal, -1) == '"') + { + $personal = str_replace('\\', '', substr($personal, 1, -1)); + } + if (empty($host)) $host = $default_host; + + $addresses[] = (object)array_diff(array( + 'mailbox' => $mailbox, + 'host' => $host, + 'personal' => $personal, + ), array(null, '')); + } + return $addresses; + } } if (!function_exists('imap_rfc822_write_address')) @@ -101,11 +148,14 @@ if (!function_exists('imap_rfc822_write_address')) * @param string $personal - The name of the account owner * @return string properly formatted email address as defined in ยป RFC2822. */ - function imap_rfc822_write_address(string $mailbox , string $host , string $personal) + function imap_rfc822_write_address($mailbox, $host, $personal) { - // ToDo: correctly handle personal strings like "Giant; \"Big\" Box" or Fuzzy, Brain - if (stripos($personal,',')) $personal = '"'.$personal.'"'; // probably too simplistic - return (!empty($personal)?$personal.' ':'').'<'.$mailbox.'@'.$host.'>'; + //if (!preg_match('/^[!#$%&\'*+/0-9=?A-Z^_`a-z{|}~-]+$/u', $personal)) // that's how I read the rfc(2)822 + if ($personal && !preg_match('/^[0-9A-Z -]*$/iu', $personal)) // but quoting is never wrong, so quote more then necessary + { + $personal = '"'.str_replace(array('\\', '"'),array('\\\\', '\\"'), $personal).'"'; + } + return ($personal ? $personal.' <' : '').$mailbox.($host ? '@'.$host : '').($personal ? '>' : ''); } } diff --git a/phpgwapi/tests/rfc822.php b/phpgwapi/tests/rfc822.php new file mode 100644 index 0000000000..9921bbf566 --- /dev/null +++ b/phpgwapi/tests/rfc822.php @@ -0,0 +1,41 @@ + + */ + +if (php_sapi_name() != 'cli') +{ + echo "
\n";
+}
+else
+{
+	chdir(__DIR__);
+}
+
+include '../inc/common_functions.inc.php';
+
+$addresses = array(
+	'Joe Doe ',
+	'"Doe, Joe" ',
+	'"\\\'Joe Doe\\\'" ',	// "\'Joe Doe\'" 
+	'postmaster@example.com',
+	'root',
+	'"Joe on its way Down Under :-\)" ',
+	'"Giant; \\"Big\\" Box" ',		// "Giant; \"Big\" Box" 
+	'"sysservices@example.net" ',
+);
+$addresses[] = implode(', ', $addresses);
+
+$default_host = 'default.host';
+
+foreach($addresses as $address)
+{
+	echo "\n\n$address:\n";
+	$parsed = my_imap_rfc822_parse_adrlist($address, $default_host);
+	print_r($parsed);
+	echo my_imap_rfc822_write_address($parsed[0]->mailbox,
+		$parsed[0]->host !== $default_host ? $parsed[0]->host : '',
+		!empty($parsed[0]->personal) ? $parsed[0]->personal : '')."\n";
+}
\ No newline at end of file