From 5a870688b082ec958c99a757139dd2e26b1f8233 Mon Sep 17 00:00:00 2001
From: cmcnulty <cmcnulty@kznf.com>
Date: Mon, 04 Nov 2013 08:47:42 -0500
Subject: [PATCH] Merge remote-tracking branch 'upstream/master' into row-focus

---
 CHANGELOG                                    |    2 
 tests/MailFunc.php                           |   48 ++++++++++++++++
 program/js/editor.js                         |    2 
 program/steps/mail/func.inc                  |   42 ++++++++-----
 program/lib/Roundcube/rcube_spellchecker.php |    3 +
 program/steps/mail/sendmail.inc              |   33 ++++++++--
 6 files changed, 104 insertions(+), 26 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 8cb4685..0ae6254 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,8 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
+- Improve identity selection based on From: header (#1489378)
+- Fix issue where mails with inline images of the same name contained only the first image multiple times (#1489406)
 - Use left/right arrow keys to collapse/expand thread and spacebar to select a row, change Ctrl key behavior (#1489392)
 - Fix an issue where using arrow keys to go up a list can result in selected message being under headers (#1489403)
 - Fix an issue where Home/End keys don't focus list row properly, don't scrollTo properly (#1489396)
diff --git a/program/js/editor.js b/program/js/editor.js
index b349c9c..020971d 100644
--- a/program/js/editor.js
+++ b/program/js/editor.js
@@ -162,7 +162,7 @@
   for (i in files) {
     att = files[i];
     if (att.complete && att.mimetype.startsWith('image/')) {
-      list.push([att.name, rcmail.env.comm_path+'&_action=display-attachment&_file='+i+'&_id='+rcmail.env.compose_id]);
+      list.push([att.name, rcmail.env.comm_path+'&_id='+rcmail.env.compose_id+'&_action=display-attachment&_file='+i]);
     }
   }
 
diff --git a/program/lib/Roundcube/rcube_spellchecker.php b/program/lib/Roundcube/rcube_spellchecker.php
index d087d25..3182ff3 100644
--- a/program/lib/Roundcube/rcube_spellchecker.php
+++ b/program/lib/Roundcube/rcube_spellchecker.php
@@ -104,6 +104,9 @@
             }
         }
 
+        // remove possible duplicates (#1489395)
+        $languages = array_unique($languages);
+
         asort($languages);
 
         return $languages;
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 43651ec..b5a8de4 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -1781,28 +1781,34 @@
         }
     }
 
-    $from_idx         = null;
-    $found_idx        = null;
-    $default_identity = 0; // default identity is always first on the list
+    // decode From: address
+    $from = rcube_mime::decode_address_list($MESSAGE->headers->from, null, true, $MESSAGE->headers->charset);
+    $from = array_shift($from);
+    $from['mailto'] = strtolower($from['mailto']);
+
+    $from_idx   = null;
+    $found_idx  = array('to' => null, 'from' => null);
+    $check_from = in_array($compose_mode, array('draft', 'edit', 'reply'));
 
     // Select identity
     foreach ($identities as $idx => $ident) {
-        // use From header
-        if (in_array($compose_mode, array('draft', 'edit'))) {
-            if ($MESSAGE->headers->from == $ident['ident']) {
+        // use From: header when in edit/draft or reply-to-self
+        if ($check_from && $from['mailto'] == strtolower($ident['email_ascii'])) {
+            // remember first matching identity address
+            if ($found_idx['from'] === null) {
+                $found_idx['from'] = $idx;
+            }
+            // match identity name
+            if ($from['name'] && $ident['name'] && $from['name'] == $ident['name']) {
                 $from_idx = $idx;
                 break;
             }
         }
-        // reply to yourself
-        else if ($compose_mode == 'reply' && $MESSAGE->headers->from == $ident['ident']) {
-            $from_idx = $idx;
-            break;
-        }
-        // use replied message recipients
+        // use replied/forwarded message recipients
         else if (($found = array_search(strtolower($ident['email_ascii']), $a_recipients)) !== false) {
-            if ($found_idx === null) {
-                $found_idx = $idx;
+            // remember first matching identity address
+            if ($found_idx['to'] === null) {
+                $found_idx['to'] = $idx;
             }
             // match identity name
             if ($a_names[$found] && $ident['name'] && $a_names[$found] == $ident['name']) {
@@ -1812,9 +1818,10 @@
         }
     }
 
-    // If matching by name+address doesn't found any matches, get first found address (identity)
+    // If matching by name+address didn't find any matches,
+    // get first found identity (address) if any
     if ($from_idx === null) {
-        $from_idx = $found_idx;
+        $from_idx = $found_idx['from'] !== null ? $found_idx['from'] : $found_idx['to'];
     }
 
     // Try Return-Path
@@ -1845,7 +1852,8 @@
 
     $selected = $plugin['selected'];
 
-    return $identities[$selected !== null ? $selected : $default_identity];
+    // default identity is always first on the list
+    return $identities[$selected !== null ? $selected : 0];
 }
 
 // Fixes some content-type names
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index ccb8978..52b02ec 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -615,22 +615,39 @@
 }
 
 // add stored attachments, if any
-if (is_array($COMPOSE['attachments']))
-{
+if (is_array($COMPOSE['attachments'])) {
   foreach ($COMPOSE['attachments'] as $id => $attachment) {
     // This hook retrieves the attachment contents from the file storage backend
     $attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment);
 
-    $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\s\'"]*/';
-    $message_body = $MAIL_MIME->getHTMLBody();
-    if ($isHtml && (preg_match($dispurl, $message_body) > 0)) {
-      $message_body = preg_replace($dispurl, ' src="'.$attachment['name'].'" ', $message_body);
+    if ($isHtml) {
+      $dispurl      = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\s\'"]*/';
+      $message_body = $MAIL_MIME->getHTMLBody();
+      $is_inline    = preg_match($dispurl, $message_body);
+    }
+    else {
+      $is_inline = false;
+    }
+
+    // inline image
+    if ($is_inline) {
+      // Mail_Mime does not support many inline attachments with the same name (#1489406)
+      // we'll generate cid: urls here to workaround this
+      $cid = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true));
+      if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $from, $matches)) {
+        $cid .= $matches[1];
+      } else {
+        $cid .= '@localhost';
+      }
+
+      $message_body = preg_replace($dispurl, ' src="cid:' . $cid . '" ', $message_body);
+
       $MAIL_MIME->setHTMLBody($message_body);
 
       if ($attachment['data'])
-        $MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false);
+        $MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false, $cid);
       else
-        $MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true);
+        $MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true, $cid);
     }
     else {
       $ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914
diff --git a/tests/MailFunc.php b/tests/MailFunc.php
index 08cbd4e..ab0074e 100644
--- a/tests/MailFunc.php
+++ b/tests/MailFunc.php
@@ -217,4 +217,52 @@
 
         $this->assertSame($identities[1], $res);
     }
+
+    /**
+     * Test identities selection (#1489378)
+     */
+    function test_rcmail_identity_select2()
+    {
+        $identities = array(
+            array(
+                'name' => 'Test 1',
+                'email_ascii' => 'addr1@domain.tld',
+                'ident' => 'Test 1 <addr1@domain.tld>',
+            ),
+            array(
+                'name' => 'Test 2',
+                'email_ascii' => 'addr2@domain.tld',
+                'ident' => 'Test 2 <addr2@domain.tld>',
+            ),
+            array(
+                'name' => 'Test 3',
+                'email_ascii' => 'addr3@domain.tld',
+                'ident' => 'Test 3 <addr3@domain.tld>',
+            ),
+            array(
+                'name' => 'Test 4',
+                'email_ascii' => 'addr2@domain.tld',
+                'ident' => 'Test 4 <addr2@domain.tld>',
+            ),
+        );
+
+        $message = new stdClass;
+        $message->headers = new rcube_message_header;
+
+        $message->headers->set('From', '<addr2@domain.tld>');
+        $res = rcmail_identity_select($message, $identities);
+        $this->assertSame($identities[1], $res);
+
+        $message->headers->set('From', 'Test 2 <addr2@domain.tld>');
+        $res = rcmail_identity_select($message, $identities);
+        $this->assertSame($identities[1], $res);
+
+        $message->headers->set('From', 'Other <addr2@domain.tld>');
+        $res = rcmail_identity_select($message, $identities);
+        $this->assertSame($identities[1], $res);
+
+        $message->headers->set('From', 'Test 4 <addr2@domain.tld>');
+        $res = rcmail_identity_select($message, $identities);
+        $this->assertSame($identities[3], $res);
+    }
 }

--
Gitblit v1.9.1