From 050410f56097bfb29bb8e5d99e792cc3a9165a55 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Fri, 13 Feb 2009 05:44:49 -0500
Subject: [PATCH] - Fix multiple recipients input parsing (#1485733) - added shared rcube_explode_quoted_string() function

---
 CHANGELOG                           |    4 +
 program/include/main.inc            |   24 ++++++++
 program/include/rcube_imap.php      |   27 --------
 program/include/rcube_mail_mime.php |   20 ------
 program/include/rcube_smtp.inc      |   22 -------
 program/steps/mail/sendmail.inc     |   46 ++++++++------
 6 files changed, 58 insertions(+), 85 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 9b6808f..d609edc 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 5cc0fb2..5c05574 100644
--- a/program/include/main.inc
+++ b/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;
+}
 
 ?>
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 0e2dd6a..3dbd35d 100644
--- a/program/include/rcube_imap.php
+++ b/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;
     }
 
diff --git a/program/include/rcube_mail_mime.php b/program/include/rcube_mail_mime.php
index 55e0ec4..f59354f 100644
--- a/program/include/rcube_mail_mime.php
+++ b/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
diff --git a/program/include/rcube_smtp.inc b/program/include/rcube_smtp.inc
index 92f808b..692106d 100644
--- a/program/include/rcube_smtp.inc
+++ b/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;
-  } 
-
 
 ?>
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index 0a9c368..f73c44b 100644
--- a/program/steps/mail/sendmail.inc
+++ b/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 ********/

--
Gitblit v1.9.1