diff --git a/CHANGELOG b/CHANGELOG index 9b6808f10..d609edc47 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,10 @@ CHANGELOG RoundCube Webmail --------------------------- +2009/02/13 (alec) +---------- +- Fix multiple recipients input parsing (#1485733) + 2009/02/10 (alec) ---------- - Use default_charset for messages without specified charset (#1485661, #1484961) diff --git a/program/include/main.inc b/program/include/main.inc index 5cc0fb214..5c055740f 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -1233,5 +1233,29 @@ class rcube_base_replacer } } +/** + * Explode quoted string + * + * @param string Delimiter expression string for preg_match() + * @param string Input string + */ +function rcube_explode_quoted_string($delimiter, $string) +{ + $result = array(); + $strlen = strlen($string); + + for ($q=$p=$i=0; $i < $strlen; $i++) { + if ($string[$i] == "\"" && $string[$i-1] != "\\") { + $q = $q ? false : true; + } + else if (!$q && preg_match("/$delimiter/", $string[$i])) { + $result[] = substr($string, $p, $i - $p); + $p = $i + 1; + } + } + + $result[] = substr($string, $p); + return $result; +} ?> diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php index 0e2dd6a07..3dbd35d90 100644 --- a/program/include/rcube_imap.php +++ b/program/include/rcube_imap.php @@ -2958,13 +2958,13 @@ class rcube_imap function _parse_address_list($str, $decode=true) { // remove any newlines and carriage returns before - $a = $this->_explode_quoted_string('[,;]', preg_replace( "/[\r\n]/", " ", $str)); + $a = rcube_explode_quoted_string('[,;]', preg_replace( "/[\r\n]/", " ", $str)); $result = array(); foreach ($a as $key => $val) { $val = preg_replace("/([\"\w])_explode_quoted_string(' ', $decode ? $this->decode_header($val) : $val); + $sub_a = rcube_explode_quoted_string(' ', $decode ? $this->decode_header($val) : $val); $result[$key]['name'] = ''; foreach ($sub_a as $k => $v) @@ -2985,29 +2985,6 @@ class rcube_imap return $result; } - - /** - * @access private - */ - function _explode_quoted_string($delimiter, $string) - { - $result = array(); - $strlen = strlen($string); - for ($q=$p=$i=0; $i < $strlen; $i++) - { - if ($string{$i} == "\"" && $string{$i-1} != "\\") - $q = $q ? false : true; - else if (!$q && preg_match("/$delimiter/", $string{$i})) - { - $result[] = substr($string, $p, $i - $p); - $p = $i + 1; - } - } - - $result[] = substr($string, $p); - return $result; - } - } // end class rcube_imap diff --git a/program/include/rcube_mail_mime.php b/program/include/rcube_mail_mime.php index 55e0ec423..f59354fea 100644 --- a/program/include/rcube_mail_mime.php +++ b/program/include/rcube_mail_mime.php @@ -128,7 +128,7 @@ class rcube_mail_mime extends Mail_mime { // if header contains e-mail addresses if (preg_match('/\s<.+@[a-z0-9\-\.]+\.[a-z]+>/U', $hdr_value)) { - $chunks = $this->_explode_quoted_string(',', $hdr_value); + $chunks = rcube_explode_quoted_string(',', $hdr_value); } else { $chunks = array($hdr_value); @@ -187,24 +187,6 @@ class rcube_mail_mime extends Mail_mime } - function _explode_quoted_string($delimiter, $string) - { - $result = array(); - $strlen = strlen($string); - for ($q=$p=$i=0; $i < $strlen; $i++) { - if ($string{$i} == "\"" && $string{$i-1} != "\\") { - $q = $q ? false : true; - } - else if (!$q && $string{$i} == $delimiter) { - $result[] = substr($string, $p, $i - $p); - $p = $i + 1; - } - } - - $result[] = substr($string, $p); - return $result; - } - /** * Provides caching of body of constructed MIME Message to avoid * duplicate construction of message and damage of MIME headers diff --git a/program/include/rcube_smtp.inc b/program/include/rcube_smtp.inc index 92f808bd3..692106d9b 100644 --- a/program/include/rcube_smtp.inc +++ b/program/include/rcube_smtp.inc @@ -327,7 +327,7 @@ function smtp_parse_rfc822($recipients) $recipients = implode(', ', $recipients); $addresses = array(); - $recipients = smtp_explode_quoted_str(",", $recipients); + $recipients = rcube_explode_quoted_string(',', $recipients); reset($recipients); while (list($k, $recipient) = each($recipients)) @@ -346,24 +346,4 @@ function smtp_parse_rfc822($recipients) return $addresses; } - -/** - * @access private - */ -function smtp_explode_quoted_str($delimiter, $string) - { - $quotes=explode("\"", $string); - while ( list($key, $val) = each($quotes)) - if (($key % 2) == 1) - $quotes[$key] = str_replace($delimiter, "_!@!_", $quotes[$key]); - $string=implode("\"", $quotes); - - $result=explode($delimiter, $string); - while (list($key, $val) = each($result)) - $result[$key] = str_replace("_!@!_", $delimiter, $result[$key]); - - return $result; - } - - ?> diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index 0a9c3681e..f73c44bac 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -143,33 +143,39 @@ function rcmail_mailto_format($mailto) $regexp = array('/[,;]\s*[\r\n]+/', '/[\r\n]+/', '/[,;]\s*$/m', '/;/', '/(\S{1})(<\S+@\S+>)/U'); $replace = array(', ', ', ', '', ',', '\\1 \\2'); - // replace new lines and strip ending ', ', make address strings more valid also + // replace new lines and strip ending ', ', make address input more valid $mailto = trim(preg_replace($regexp, $replace, $mailto)); - $result = $name = ''; - - // handle simple email (without <>) - if (preg_match('/^\S+@\S+$/', $mailto)) - $result = '<' . $mailto . '>'; - else - // quote unquoted names (#1485654) - foreach (explode(' ', $mailto) as $item) { - if (preg_match('/<\S+@\S+>,*/', $item)) { - if ($name && ($name[0] != '"' || $name[strlen($name)-1] != '"') + $result = array(); + $items = rcube_explode_quoted_string(',', $mailto); + + foreach($items as $item) { + $item = trim($item); + // address in brackets without name (do nothing) + if (preg_match('/^<\S+@\S+>$/', $item)) { + $result[] = $item; + // address without brackets and without name (add brackets) + } else if (preg_match('/^\S+@\S+$/', $item)) { + $result[] = '<'.$item.'>'; + // address with name (handle name) + } else if (preg_match('/\S+@\S+>*$/', $item, $matches)) { + $address = $matches[0]; + $name = str_replace($address, '', $item); + $name = trim($name); + if ($name && ($name[0] != '"' || $name[strlen($name)-1] != '"') && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) { $name = '"'.addcslashes($name, '"').'"'; - } - if ($name) { - $result .= ' ' . $name; - $name = ''; - } - $result .= ' ' . $item; - } else { - $name .= ($name ? ' ' : '') . $item; } + if (!preg_match('/^<\S+@\S+>$/', $address)) + $address = '<'.$address.'>'; + + $result[] = $name.' '.$address; + } else if (trim($item)) { + // @TODO: handle errors } + } - return trim($result); + return implode(', ', $result); } /****** compose message ********/