diff options
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | program/include/main.inc | 63 | ||||
-rw-r--r-- | program/include/rcube_shared.inc | 46 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 6 | ||||
-rw-r--r-- | tests/mailfunc.php | 4 | ||||
-rw-r--r-- | tests/src/htmlbase.txt | 2 |
6 files changed, 71 insertions, 51 deletions
@@ -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 @@ -164,52 +164,6 @@ function show_bytes($bytes) } /** - * 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 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 <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 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 @@ <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> |