diff --git a/CHANGELOG b/CHANGELOG
index 8be44a41b..4ecd740c1 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 ad41a13e7..b16f0202a 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -2093,7 +2093,68 @@ class rcube_base_replacer
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 abaa8aa03..aef08341d 100644
--- a/program/include/rcube_shared.inc
+++ b/program/include/rcube_shared.inc
@@ -163,52 +163,6 @@ function show_bytes($bytes)
return $str;
}
-/**
- * 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
*/
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 3784456c7..f791f7033 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -1110,15 +1110,13 @@ function rcmail_resolve_base($body)
// check for
if (preg_match('!()/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 1b1bbdf38..2e55d331d 100644
--- a/tests/mailfunc.php
+++ b/tests/mailfunc.php
@@ -166,5 +166,9 @@ class rcube_test_mailfunc extends UnitTestCase
$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 d1ddd5406..eb590748b 100644
--- a/tests/src/htmlbase.txt
+++ b/tests/src/htmlbase.txt
@@ -6,5 +6,7 @@
+
+