Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F223455
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/program/lib/Roundcube/rcube_string_replacer.php b/program/lib/Roundcube/rcube_string_replacer.php
index 0fc90a55a..d1f1f4dbc 100644
--- a/program/lib/Roundcube/rcube_string_replacer.php
+++ b/program/lib/Roundcube/rcube_string_replacer.php
@@ -1,215 +1,215 @@
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2009-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Handle string replacements based on preg_replace_callback |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
/**
* Helper class for string replacements based on preg_replace_callback
*
* @package Framework
* @subpackage Utils
*/
class rcube_string_replacer
{
public static $pattern = '/##str_replacement\[([0-9]+)\]##/';
public $mailto_pattern;
public $link_pattern;
private $values = array();
private $options = array();
function __construct($options = array())
{
// Simplified domain expression for UTF8 characters handling
// Support unicode/punycode in top-level domain part
$utf_domain = '[^?&@"\'\\/()<>\s\r\t\n]+\\.?([^\\x00-\\x2f\\x3b-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-zA-Z0-9]{2,})';
$url1 = '.:;,';
$url2 = 'a-zA-Z0-9%=#$@+?!&\\/_~\\[\\]\\(\\){}\*-';
- $this->link_pattern = "/([\w]+:\/\/|\W[Ww][Ww][Ww]\.|^[Ww][Ww][Ww]\.)($utf_domain([$url1]?[$url2]+)*)/";
+ $this->link_pattern = "/([\w]+:\/\/|\W[Ww][Ww][Ww]\.|^[Ww][Ww][Ww]\.)($utf_domain([$url1]*[$url2]+)*)/";
$this->mailto_pattern = "/("
."[-\w!\#\$%&\'*+~\/^`|{}=]+(?:\.[-\w!\#\$%&\'*+~\/^`|{}=]+)*" // local-part
."@$utf_domain" // domain-part
."(\?[$url1$url2]+)?" // e.g. ?subject=test...
.")/";
$this->options = $options;
}
/**
* Add a string to the internal list
*
* @param string String value
* @return int Index of value for retrieval
*/
public function add($str)
{
$i = count($this->values);
$this->values[$i] = $str;
return $i;
}
/**
* Build replacement string
*/
public function get_replacement($i)
{
return '##str_replacement['.$i.']##';
}
/**
* Callback function used to build HTML links around URL strings
*
* @param array Matches result from preg_replace_callback
* @return int Index of saved string value
*/
public function link_callback($matches)
{
$i = -1;
$scheme = strtolower($matches[1]);
if (preg_match('!^(http|ftp|file)s?://!i', $scheme)) {
$url = $matches[1] . $matches[2];
}
else if (preg_match('/^(\W*)(www\.)$/i', $matches[1], $m)) {
$url = $m[2] . $matches[2];
$url_prefix = 'http://';
$prefix = $m[1];
}
if ($url) {
$suffix = $this->parse_url_brackets($url);
$attrib = (array)$this->options['link_attribs'];
$attrib['href'] = $url_prefix . $url;
$i = $this->add(html::a($attrib, rcube::Q($url)) . $suffix);
}
// Return valid link for recognized schemes, otherwise
// return the unmodified string for unrecognized schemes.
return $i >= 0 ? $prefix . $this->get_replacement($i) : $matches[0];
}
/**
* Callback function used to build mailto: links around e-mail strings
*
* @param array Matches result from preg_replace_callback
* @return int Index of saved string value
*/
public function mailto_callback($matches)
{
$href = $matches[1];
$suffix = $this->parse_url_brackets($href);
$i = $this->add(html::a('mailto:' . $href, rcube::Q($href)) . $suffix);
return $i >= 0 ? $this->get_replacement($i) : '';
}
/**
* Look up the index from the preg_replace matches array
* and return the substitution value.
*
* @param array Matches result from preg_replace_callback
* @return string Value at index $matches[1]
*/
public function replace_callback($matches)
{
return $this->values[$matches[1]];
}
/**
* Replace all defined (link|mailto) patterns with replacement string
*
* @param string $str Text
*
* @return string Text
*/
public function replace($str)
{
// search for patterns like links and e-mail addresses
$str = preg_replace_callback($this->link_pattern, array($this, 'link_callback'), $str);
$str = preg_replace_callback($this->mailto_pattern, array($this, 'mailto_callback'), $str);
return $str;
}
/**
* Replace substituted strings with original values
*/
public function resolve($str)
{
return preg_replace_callback(self::$pattern, array($this, 'replace_callback'), $str);
}
/**
* Fixes bracket characters in URL handling
*/
public static function parse_url_brackets(&$url)
{
// #1487672: special handling of square brackets,
// URL regexp allows [] characters in URL, for example:
// "http://example.com/?a[b]=c". However we need to handle
// properly situation when a bracket is placed at the end
// of the link e.g. "[http://example.com]"
// Yes, this is not perfect handles correctly only paired characters
// but it should work for common cases
if (preg_match('/(\\[|\\])/', $url)) {
$in = false;
for ($i=0, $len=strlen($url); $i<$len; $i++) {
if ($url[$i] == '[') {
if ($in)
break;
$in = true;
}
else if ($url[$i] == ']') {
if (!$in)
break;
$in = false;
}
}
if ($i < $len) {
$suffix = substr($url, $i);
$url = substr($url, 0, $i);
}
}
// Do the same for parentheses
if (preg_match('/(\\(|\\))/', $url)) {
$in = false;
for ($i=0, $len=strlen($url); $i<$len; $i++) {
if ($url[$i] == '(') {
if ($in)
break;
$in = true;
}
else if ($url[$i] == ')') {
if (!$in)
break;
$in = false;
}
}
if ($i < $len) {
$suffix = substr($url, $i);
$url = substr($url, 0, $i);
}
}
return $suffix;
}
}
diff --git a/tests/Framework/StringReplacer.php b/tests/Framework/StringReplacer.php
index dc7638734..8f6eaf4b9 100644
--- a/tests/Framework/StringReplacer.php
+++ b/tests/Framework/StringReplacer.php
@@ -1,56 +1,58 @@
<?php
/**
* Test class to test rcube_string_replacer class
*
* @package Tests
*/
class Framework_StringReplacer extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$sr = new rcube_string_replacer;
$this->assertInstanceOf('rcube_string_replacer', $sr, "Class constructor");
}
/**
* Data for test_replace()
*/
function data_replace()
{
return array(
array('http://domain.tld/path*path2', '<a href="http://domain.tld/path*path2">http://domain.tld/path*path2</a>'),
array("Click this link:\nhttps://mail.xn--brderli-o2a.ch/rc/ EOF", "Click this link:\n<a href=\"https://mail.xn--brderli-o2a.ch/rc/\">https://mail.xn--brderli-o2a.ch/rc/</a> EOF"),
array('Start http://localhost/?foo End', 'Start <a href="http://localhost/?foo">http://localhost/?foo</a> End'),
+ array('http://localhost/?foo=bar. Period', '<a href="http://localhost/?foo=bar">http://localhost/?foo=bar</a>. Period'),
array('www.domain.tld', '<a href="http://www.domain.tld">www.domain.tld</a>'),
array('WWW.DOMAIN.TLD', '<a href="http://WWW.DOMAIN.TLD">WWW.DOMAIN.TLD</a>'),
array('[http://link.com]', '[<a href="http://link.com">http://link.com</a>]'),
array('http://link.com?a[]=1', '<a href="http://link.com?a[]=1">http://link.com?a[]=1</a>'),
array('http://link.com?a[]', '<a href="http://link.com?a[]">http://link.com?a[]</a>'),
array('(http://link.com)', '(<a href="http://link.com">http://link.com</a>)'),
array('http://link.com?a(b)c', '<a href="http://link.com?a(b)c">http://link.com?a(b)c</a>'),
array('http://link.com?(link)', '<a href="http://link.com?(link)">http://link.com?(link)</a>'),
+ array('https://github.com/a/b/compare/3a0f82...1f4b2a after', '<a href="https://github.com/a/b/compare/3a0f82...1f4b2a">https://github.com/a/b/compare/3a0f82...1f4b2a</a> after'),
array('http://<test>', 'http://<test>'),
array('http://', 'http://'),
array('1@1.com www.domain.tld', '<a href="mailto:1@1.com">1@1.com</a> <a href="http://www.domain.tld">www.domain.tld</a>'),
array(' www.domain.tld ', ' <a href="http://www.domain.tld">www.domain.tld</a> '),
);
}
/**
* @dataProvider data_replace
*/
function test_replace($input, $output)
{
$replacer = new rcube_string_replacer;
$result = $replacer->replace($input);
$result = $replacer->resolve($result);
$this->assertEquals($output, $result);
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Mar 1, 3:40 AM (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
165696
Default Alt Text
(10 KB)
Attached To
Mode
R3 roundcubemail
Attached
Detach File
Event Timeline
Log In to Comment