Fix incorrect handling of leading spaces in text wrapping

pull/88/head
Aleksander Machniak 11 years ago
parent f55bfe096d
commit 102b08c6a2

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Fix incorrect handling of leading spaces in text wrapping
- Fix unintentional messages list jumps on click in Internet Explorer (#1489056)
- Fix list of required configuration options (#1489055)
- Fix DB error when creating a new contact and a group is selected (#1489051)

@ -564,82 +564,122 @@ class rcube_mime
/**
* Improved wordwrap function.
* Improved wordwrap function with multibyte support.
* The code is based on Zend_Text_MultiByte::wordWrap().
*
* @param string $string Text to wrap
* @param int $width Line width
* @param string $break Line separator
* @param bool $cut Enable to cut word
* @param string $charset Charset of $string
* @param string $string Text to wrap
* @param int $width Line width
* @param string $break Line separator
* @param bool $cut Enable to cut word
* @param string $charset Charset of $string
* @param bool $wrap_quoted When enabled quoted lines will not be wrapped
*
* @return string Text
*/
public static function wordwrap($string, $width=75, $break="\n", $cut=false, $charset=null)
public static function wordwrap($string, $width=75, $break="\n", $cut=false, $charset=null, $wrap_quoted=true)
{
if ($charset && function_exists('mb_internal_encoding')) {
mb_internal_encoding($charset);
if (!$charset) {
$charset = RCUBE_CHARSET;
}
$para = preg_split('/\r?\n/', $string);
$string = '';
while (count($para)) {
$line = array_shift($para);
if ($line[0] == '>') {
$string .= $line . (count($para) ? $break : '');
continue;
// detect available functions
$strlen_func = function_exists('iconv_strlen') ? 'iconv_strlen' : 'mb_strlen';
$strpos_func = function_exists('iconv_strpos') ? 'iconv_strpos' : 'mb_strpos';
$strrpos_func = function_exists('iconv_strrpos') ? 'iconv_strrpos' : 'mb_strrpos';
$substr_func = function_exists('iconv_substr') ? 'iconv_substr' : 'mb_substr';
// Convert \r\n to \n, this is our line-separator
$string = str_replace("\r\n", "\n", $string);
$separator = "\n"; // must be 1 character length
$result = array();
while (($stringLength = $strlen_func($string, $charset)) > 0) {
$breakPos = $strpos_func($string, $separator, 0, $charset);
// quoted line (do not wrap)
if ($wrap_quoted && $string[0] == '>') {
if ($breakPos === $stringLength - 1 || $breakPos === false) {
$subString = $string;
$cutLength = null;
}
else {
$subString = $substr_func($string, 0, $breakPos, $charset);
$cutLength = $breakPos + 1;
}
}
// next line found and current line is shorter than the limit
else if ($breakPos !== false && $breakPos < $width) {
if ($breakPos === $stringLength - 1) {
$subString = $string;
$cutLength = null;
}
else {
$subString = $substr_func($string, 0, $breakPos, $charset);
$cutLength = $breakPos + 1;
}
}
else {
$subString = $substr_func($string, 0, $width, $charset);
$list = explode(' ', $line);
$len = 0;
while (count($list)) {
$line = array_shift($list);
$l = mb_strlen($line);
$space = $len ? 1 : 0;
$newlen = $len + $l + $space;
if ($newlen <= $width) {
$string .= ($space ? ' ' : '').$line;
$len += ($space + $l);
// last line
if ($subString === $string) {
$cutLength = null;
}
else {
if ($l > $width) {
if ($cut) {
$start = 0;
while ($l) {
$str = mb_substr($line, $start, $width);
$strlen = mb_strlen($str);
$string .= ($len ? $break : '').$str;
$start += $strlen;
$l -= $strlen;
$len = $strlen;
}
$nextChar = $substr_func($string, $width, 1, $charset);
if ($nextChar === ' ' || $nextChar === $separator) {
$afterNextChar = $substr_func($string, $width + 1, 1, $charset);
if ($afterNextChar === false) {
$subString .= $nextChar;
}
$cutLength = $strlen_func($subString, $charset) + 1;
}
else {
if ($strrpos_func[0] == 'm') {
$spacePos = $strrpos_func($subString, ' ', 0, $charset);
}
else {
$string .= ($len ? $break : '').$line;
if (count($list)) {
$string .= $break;
$spacePos = $strrpos_func($subString, ' ', $charset);
}
if ($spacePos !== false) {
$subString = $substr_func($subString, 0, $spacePos, $charset);
$cutLength = $spacePos + 1;
}
else if ($cut === false) {
$spacePos = $strpos_func($string, ' ', 0, $charset);
if ($spacePos !== false) {
$subString = $substr_func($string, 0, $spacePos, $charset);
$cutLength = $spacePos + 1;
}
else {
$subString = $string;
$cutLength = null;
}
$len = 0;
}
}
else {
$string .= $break.$line;
$len = $l;
else {
$subString = $substr_func($subString, 0, $width, $charset);
$cutLength = $width;
}
}
}
}
if (count($para)) {
$string .= $break;
}
}
$result[] = $subString;
if ($charset && function_exists('mb_internal_encoding')) {
mb_internal_encoding(RCUBE_CHARSET);
if ($cutLength !== null) {
$string = $substr_func($string, $cutLength, ($stringLength - $cutLength), $charset);
}
else {
break;
}
}
return $string;
return implode($break, $result);
}

@ -142,4 +142,50 @@ class Framework_Mime extends PHPUnit_Framework_TestCase
$this->assertEquals($unfolded, rcube_mime::unfold_flowed($flowed), "Test correct unfolding of quoted lines");
}
/**
* Test wordwrap()
*/
function test_wordwrap()
{
$samples = array(
array(
array("aaaa aaaa\n aaaa"),
"aaaa aaaa\n aaaa",
),
array(
array("123456789 123456789 123456789 123", 29),
"123456789 123456789 123456789\n123",
),
array(
array("123456789 3456789 123456789", 29),
"123456789 3456789 123456789",
),
array(
array("123456789 123456789 123456789 123", 29),
"123456789 123456789 123456789\n 123",
),
array(
array("abc", 1, "\n", true),
"a\nb\nc",
),
array(
array("ąść", 1, "\n", true, 'UTF-8'),
"ą\nś\nć",
),
array(
array(">abc\n>def", 2, "\n", true),
">abc\n>def",
),
array(
array("abc def", 3, "-"),
"abc-def",
),
);
foreach ($samples as $sample) {
$this->assertEquals($sample[1], call_user_func_array(array('rcube_mime', 'wordwrap'), $sample[0]), "Test text wrapping");
}
}
}

Loading…
Cancel
Save