Fix incorrect handling of leading spaces in text wrapping

pull/68/merge
Aleksander Machniak 11 years ago
parent 8ad2c98e9d
commit 7439d3ee14

@ -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