From f5d62f7157a629d8d1611d848be6e4167dd17075 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Thu, 05 Jan 2012 04:51:41 -0500
Subject: [PATCH] - Fix bug in handling of base href and inline content (#1488290)

---
 CHANGELOG                        |    1 
 program/include/rcube_shared.inc |   46 ---------------
 tests/src/htmlbase.txt           |    2 
 program/include/main.inc         |   63 ++++++++++++++++++++
 program/steps/mail/func.inc      |    6 -
 tests/mailfunc.php               |    4 +
 6 files changed, 71 insertions(+), 51 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 8be44a4..4ecd740 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
+- Fix bug in handling of base href and inline content (#1488290)
 - Fix SQL Error when saving a contact with many email addresses (#1488286)
 - Fix strict email address searching if contact has more than one address
 - Use proper timezones from PHP's internal timezonedb (#1485592)
diff --git a/program/include/main.inc b/program/include/main.inc
index ad41a13..b16f020 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -2093,7 +2093,68 @@
 
   public function callback($matches)
   {
-    return $matches[1] . '="' . make_absolute_url($matches[3], $this->base_url) . '"';
+    return $matches[1] . '="' . self::absolute_url($matches[3], $this->base_url) . '"';
+  }
+
+  public function replace($body)
+  {
+    return preg_replace_callback(array(
+      '/(src|background|href)=(["\']?)([^"\'\s]+)(\2|\s|>)/Ui',
+      '/(url\s*\()(["\']?)([^"\'\)\s]+)(\2)\)/Ui',
+      ),
+      array($this, 'callback'), $body);
+  }
+
+  /**
+   * Convert paths like ../xxx to an absolute path using a base url
+   *
+   * @param string $path     Relative path
+   * @param string $base_url Base URL
+   *
+   * @return string Absolute URL
+   */
+  public static function absolute_url($path, $base_url)
+  {
+    $host_url = $base_url;
+    $abs_path = $path;
+
+    // check if path is an absolute URL
+    if (preg_match('/^[fhtps]+:\/\//', $path)) {
+      return $path;
+    }
+
+    // check if path is a content-id scheme
+    if (strpos($path, 'cid:') === 0) {
+      return $path;
+    }
+
+    // cut base_url to the last directory
+    if (strrpos($base_url, '/') > 7) {
+      $host_url = substr($base_url, 0, strpos($base_url, '/', 7));
+      $base_url = substr($base_url, 0, strrpos($base_url, '/'));
+    }
+
+    // $path is absolute
+    if ($path[0] == '/') {
+      $abs_path = $host_url.$path;
+    }
+    else {
+      // strip './' because its the same as ''
+      $path = preg_replace('/^\.\//', '', $path);
+
+      if (preg_match_all('/\.\.\//', $path, $matches, PREG_SET_ORDER)) {
+        foreach ($matches as $a_match) {
+          if (strrpos($base_url, '/')) {
+            $base_url = substr($base_url, 0, strrpos($base_url, '/'));
+          }
+          $path = substr($path, 3);
+        }
+      }
+
+      $abs_path = $base_url.'/'.$path;
+    }
+
+    return $abs_path;
   }
 }
 
diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc
index abaa8aa..aef0834 100644
--- a/program/include/rcube_shared.inc
+++ b/program/include/rcube_shared.inc
@@ -164,52 +164,6 @@
 }
 
 /**
- * Convert paths like ../xxx to an absolute path using a base url
- *
- * @param string Relative path
- * @param string Base URL
- * @return string Absolute URL
- */
-function make_absolute_url($path, $base_url)
-{
-  $host_url = $base_url;
-  $abs_path = $path;
-
-  // check if path is an absolute URL
-  if (preg_match('/^[fhtps]+:\/\//', $path))
-    return $path;
-
-  // cut base_url to the last directory
-  if (strrpos($base_url, '/')>7)
-  {
-    $host_url = substr($base_url, 0, strpos($base_url, '/', 7));
-    $base_url = substr($base_url, 0, strrpos($base_url, '/'));
-  }
-
-  // $path is absolute
-  if ($path[0] == '/')
-    $abs_path = $host_url.$path;
-  else
-  {
-    // strip './' because its the same as ''
-    $path = preg_replace('/^\.\//', '', $path);
-
-    if (preg_match_all('/\.\.\//', $path, $matches, PREG_SET_ORDER))
-      foreach ($matches as $a_match)
-      {
-        if (strrpos($base_url, '/'))
-          $base_url = substr($base_url, 0, strrpos($base_url, '/'));
-
-        $path = substr($path, 3);
-      }
-
-    $abs_path = $base_url.'/'.$path;
-  }
-
-  return $abs_path;
-}
-
-/**
  * Wrapper function for wordwrap
  */
 function rc_wordwrap($string, $width=75, $break="\n", $cut=false)
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 3784456..f791f70 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -1110,15 +1110,13 @@
   // check for <base href=...>
   if (preg_match('!(<base.*href=["\']?)([hftps]{3,5}://[a-z0-9/.%-]+)!i', $body, $regs)) {
     $replacer = new rcube_base_replacer($regs[2]);
-
-    // replace all relative paths
-    $body = preg_replace_callback('/(src|background|href)=(["\']?)([^"\'\s]+)(\2|\s|>)/Ui', array($replacer, 'callback'), $body);
-    $body = preg_replace_callback('/(url\s*\()(["\']?)([^"\'\)\s]+)(\2)\)/Ui', array($replacer, 'callback'), $body);
+    $body     = $replacer->replace($body);
   }
 
   return $body;
 }
 
+
 /**
  * modify a HTML message that it can be displayed inside a HTML page
  */
diff --git a/tests/mailfunc.php b/tests/mailfunc.php
index 1b1bbdf..2e55d33 100644
--- a/tests/mailfunc.php
+++ b/tests/mailfunc.php
@@ -166,5 +166,9 @@
     $this->assertPattern('|src="http://alec\.pl/dir/img1\.gif"|', $html, "URI base resolving [1]");
     $this->assertPattern('|src="http://alec\.pl/dir/img2\.gif"|', $html, "URI base resolving [2]");
     $this->assertPattern('|src="http://alec\.pl/img3\.gif"|', $html, "URI base resolving [3]");
+
+    // base resolving exceptions
+    $this->assertPattern('|src="cid:theCID"|', $html, "URI base resolving exception [1]");
+    $this->assertPattern('|src="http://other\.domain\.tld/img3\.gif"|', $html, "URI base resolving exception [2]");
   }
 }
diff --git a/tests/src/htmlbase.txt b/tests/src/htmlbase.txt
index d1ddd54..eb59074 100644
--- a/tests/src/htmlbase.txt
+++ b/tests/src/htmlbase.txt
@@ -6,5 +6,7 @@
 <img src="img1.gif" />
 <img src="./img2.gif" />
 <img src="../img3.gif" />
+<img src="cid:theCID" />
+<img src="http://other.domain.tld/img3.gif" />
 </body>
 </html>

--
Gitblit v1.9.1