Commit a883560a authored by Sebastian Kummer's avatar Sebastian Kummer

Merge pull request #562 in ZP/z-push from...

Merge pull request #562 in ZP/z-push from bugfix/ZP-1240-html-bodies-should-not-be-truncated to develop

* commit '4b293f5e':
  ZP-1240 Also HTML-trucate bodies from IMAP.
  ZP-1240 HTML safe truncate streams containing HTML data.
  ZP-1240 Add HTML safe truncation options to stream wrappers.
  ZP-1240 Add parameter $htmlsafe (default false) to Utils::Utf8_truncate().
parents 53ca2776 4b293f5e
......@@ -1124,7 +1124,8 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
}
}
$output->asbody->data = StringStreamWrapper::Open($data);
// indicate in open that the data is HTML so it can be truncated correctly if required
$output->asbody->data = StringStreamWrapper::Open($data, ($bpReturnType == SYNC_BODYPREFERENCE_HTML));
$output->asbody->estimatedDataSize = strlen($data);
unset($data);
$output->asbody->type = $bpReturnType;
......
......@@ -2437,11 +2437,13 @@ class MAPIProvider {
* @return boolean
*/
private function setMessageBodyForType($mapimessage, $bpReturnType, &$message) {
$truncateHtmlSafe = false;
//default value is PR_BODY
$property = PR_BODY;
switch ($bpReturnType) {
case SYNC_BODYPREFERENCE_HTML:
$property = PR_HTML;
$truncateHtmlSafe = true;
break;
case SYNC_BODYPREFERENCE_RTF:
$property = PR_RTF_COMPRESSED;
......@@ -2473,11 +2475,11 @@ class MAPIProvider {
elseif (isset($message->internetcpid) && $bpReturnType == SYNC_BODYPREFERENCE_HTML) {
// if PR_HTML is UTF-8 we can stream it directly, else we have to convert to UTF-8 & wrap it
if (Utils::GetCodepageCharset($message->internetcpid) == "utf-8") {
$message->asbody->data = MAPIStreamWrapper::Open($stream);
$message->asbody->data = MAPIStreamWrapper::Open($stream, $truncateHtmlSafe);
}
else {
$body = $this->mapiReadStream($stream, $streamsize);
$message->asbody->data = StringStreamWrapper::Open(Utils::ConvertCodepageStringToUtf8($message->internetcpid, $body));
$message->asbody->data = StringStreamWrapper::Open(Utils::ConvertCodepageStringToUtf8($message->internetcpid, $body), $truncateHtmlSafe);
$message->internetcpid = INTERNET_CPID_UTF8;
}
}
......
......@@ -31,6 +31,7 @@ class MAPIStreamWrapper {
private $position;
private $streamlength;
private $toTruncate;
private $truncateHtmlSafe;
/**
* Opens the stream
......@@ -52,6 +53,7 @@ class MAPIStreamWrapper {
$this->position = 0;
$this->toTruncate = false;
$this->truncateHtmlSafe = (isset($contextOptions[self::PROTOCOL]['truncatehtmlsafe'])) ? $contextOptions[self::PROTOCOL]['truncatehtmlsafe'] : false;
// this is our stream!
$this->mapistream = $contextOptions[self::PROTOCOL]['stream'];
......@@ -65,7 +67,7 @@ class MAPIStreamWrapper {
$this->streamlength = 0;
}
ZLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIStreamWrapper::stream_open(): initialized mapistream: %s streamlength: %d", $this->mapistream, $this->streamlength));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIStreamWrapper::stream_open(): initialized mapistream: %s - streamlength: %d - HTML-safe-truncate: %s", $this->mapistream, $this->streamlength, Utils::PrintAsString($this->truncateHtmlSafe)));
return true;
}
......@@ -95,7 +97,7 @@ class MAPIStreamWrapper {
// we need to truncate UTF8 compatible if ftruncate() was called
if ($this->toTruncate && $this->position >= $this->streamlength) {
$data = Utils::Utf8_truncate($data, $this->streamlength);
$data = Utils::Utf8_truncate($data, $this->streamlength, $this->truncateHtmlSafe);
}
return $data;
......@@ -175,13 +177,14 @@ class MAPIStreamWrapper {
/**
* Instantiates a MAPIStreamWrapper
*
* @param mapistream $mapistream The stream to be wrapped
* @param mapistream $mapistream The stream to be wrapped
* @param boolean $truncatehtmlsafe Indicates if a truncation should be done html-safe - default: false
*
* @access public
* @return MAPIStreamWrapper
*/
static public function Open($mapistream) {
$context = stream_context_create(array(self::PROTOCOL => array('stream' => &$mapistream)));
static public function Open($mapistream, $truncatehtmlsafe = false) {
$context = stream_context_create(array(self::PROTOCOL => array('stream' => &$mapistream, 'truncatehtmlsafe' => $truncatehtmlsafe)));
return fopen(self::PROTOCOL . "://",'r', false, $context);
}
}
......
......@@ -30,6 +30,7 @@ class StringStreamWrapper {
private $stringstream;
private $position;
private $stringlength;
private $truncateHtmlSafe;
/**
* Opens the stream
......@@ -53,9 +54,10 @@ class StringStreamWrapper {
// this is our stream!
$this->stringstream = $contextOptions[self::PROTOCOL]['string'];
$this->truncateHtmlSafe = (isset($contextOptions[self::PROTOCOL]['truncatehtmlsafe'])) ? $contextOptions[self::PROTOCOL]['truncatehtmlsafe'] : false;
$this->stringlength = strlen($this->stringstream);
ZLog::Write(LOGLEVEL_DEBUG, sprintf("StringStreamWrapper::stream_open(): initialized stream length: %d", $this->stringlength));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("StringStreamWrapper::stream_open(): initialized stream length: %d - HTML-safe-truncate: %s", $this->stringlength, Utils::PrintAsString($this->truncateHtmlSafe)));
return true;
}
......@@ -135,7 +137,7 @@ class StringStreamWrapper {
*/
public function stream_truncate ($new_size) {
// cut the string!
$this->stringstream = Utils::Utf8_truncate($this->stringstream, $new_size);
$this->stringstream = Utils::Utf8_truncate($this->stringstream, $new_size, $this->truncateHtmlSafe);
$this->stringlength = strlen($this->stringstream);
if ($this->position > $this->stringlength) {
......@@ -161,13 +163,14 @@ class StringStreamWrapper {
/**
* Instantiates a StringStreamWrapper
*
* @param string $string The string to be wrapped
* @param string $string The string to be wrapped
* @param boolean $truncatehtmlsafe Indicates if a truncation should be done html-safe - default: false
*
* @access public
* @return StringStreamWrapper
*/
static public function Open($string) {
$context = stream_context_create(array(self::PROTOCOL => array('string' => &$string)));
static public function Open($string, $truncatehtmlsafe = false) {
$context = stream_context_create(array(self::PROTOCOL => array('string' => &$string, 'truncatehtmlsafe' => $truncatehtmlsafe)));
return fopen(self::PROTOCOL . "://",'r', false, $context);
}
}
......
......@@ -380,11 +380,13 @@ class Utils {
*
* If it's not possible to truncate properly, an empty string is returned
*
* @param string $string - the string
* @param string $length - position where string should be cut
* @param string $string the string
* @param string $length position where string should be cut
* @param boolean $htmlsafe doesn't cut html tags in half, doesn't ensure correct html - default: false
*
* @return string truncated string
*/
static public function Utf8_truncate($string, $length) {
static public function Utf8_truncate($string, $length, $htmlsafe = false) {
// make sure length is always an interger
$length = (int)$length;
......@@ -393,6 +395,16 @@ class Utils {
$length = strlen($string) - 1;
}
// The intent is not to cut HTML tags in half which causes displaying issues (see ZP-1240).
// The used method just tries to cut outside of tags, without checking tag validity and closing tags.
if ($htmlsafe) {
$offset = 0 - strlen($string) + $length;
$validPos = strrpos($string, "<", $offset);
if ($validPos > strrpos($string, ">", $offset)) {
$length = $validPos;
}
}
while($length >= 0) {
if ((ord($string[$length]) < 0x80) || (ord($string[$length]) >= 0xC0)) {
return substr($string, 0, $length);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment