alecpl
2009-02-13 050410f56097bfb29bb8e5d99e792cc3a9165a55
- Fix multiple recipients input parsing (#1485733)
- added shared rcube_explode_quoted_string() function


6 files modified
143 ■■■■■ changed files
CHANGELOG 4 ●●●● patch | view | raw | blame | history
program/include/main.inc 24 ●●●●● patch | view | raw | blame | history
program/include/rcube_imap.php 27 ●●●●● patch | view | raw | blame | history
program/include/rcube_mail_mime.php 20 ●●●●● patch | view | raw | blame | history
program/include/rcube_smtp.inc 22 ●●●●● patch | view | raw | blame | history
program/steps/mail/sendmail.inc 46 ●●●●● patch | view | raw | blame | history
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)
program/include/main.inc
@@ -1233,5 +1233,29 @@
  }
}
/**
 * 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;
}
?>
program/include/rcube_imap.php
@@ -2958,13 +2958,13 @@
  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])</", "$1 <", $val);
      $sub_a = $this->_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)
@@ -2982,29 +2982,6 @@
        $result[$key]['address'] = $result[$key]['name'];
      }
    
    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;
    }
program/include/rcube_mail_mime.php
@@ -128,7 +128,7 @@
    {
      // 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 @@
  }
  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
program/include/rcube_smtp.inc
@@ -327,7 +327,7 @@
    $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))
@@ -345,25 +345,5 @@
    }
  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;
  }
?>
program/steps/mail/sendmail.inc
@@ -143,33 +143,39 @@
  $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 = '';
  $result = array();
  $items = rcube_explode_quoted_string(',', $mailto);
  // 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] != '"')
  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.'>';
  return trim($result);
      $result[] = $name.' '.$address;
    } else if (trim($item)) {
      // @TODO: handle errors
    }
  }
  return implode(', ', $result);
}
/****** compose message ********/