Commit f133d268 authored by Sebastian Kummer's avatar Sebastian Kummer

ZP-707 Use plain streams in mapi provider. Added writing functionality to

StringStreamWrapper and MapiStreamWrapper. Reading data is encapsulated
into a StringStreamWrapper by the Streamer.

Released under the Affero GNU General Public License (AGPL) version 3.
parent 8c8190cd
...@@ -798,8 +798,8 @@ class MAPIProvider { ...@@ -798,8 +798,8 @@ class MAPIProvider {
ZLog::Write(LOGLEVEL_DEBUG, "Attach the transport message headers to a signed message"); ZLog::Write(LOGLEVEL_DEBUG, "Attach the transport message headers to a signed message");
$transportHeaders = array(PR_TRANSPORT_MESSAGE_HEADERS_W); $transportHeaders = array(PR_TRANSPORT_MESSAGE_HEADERS_W);
$messageHeaders = $this->getProps($mapimessage, $transportHeaders); $messageHeaders = $this->getProps($mapimessage, $transportHeaders);
// TODO fix, this is ugly as f*ck! Use a prepend filter?
$message->asbody->data = StringStreamWrapper::Open($messageHeaders[PR_TRANSPORT_MESSAGE_HEADERS] ."\r\n\r\n" . stream_get_contents($message->asbody->data)); fwrite($message->asbody->data, $messageHeaders[PR_TRANSPORT_MESSAGE_HEADERS] ."\r\n\r\n");
} }
return $message; return $message;
...@@ -2355,8 +2355,7 @@ class MAPIProvider { ...@@ -2355,8 +2355,7 @@ class MAPIProvider {
$message->asbody->data = StringStreamWrapper::Open(Utils::ConvertCodepageStringToUtf8($message->internetcpid, $body)); $message->asbody->data = StringStreamWrapper::Open(Utils::ConvertCodepageStringToUtf8($message->internetcpid, $body));
else else
$message->asbody->data = StringStreamWrapper::Open($body); $message->asbody->data = StringStreamWrapper::Open($body);
// TODO fix $message->asbody->estimatedDataSize = strlen($body);
$message->asbody->estimatedDataSize = strlen($message->asbody->data);
} }
else { else {
$message->body = str_replace("\n","\r\n", w2u(str_replace("\r", "", $body))); $message->body = str_replace("\n","\r\n", w2u(str_replace("\r", "", $body)));
...@@ -2452,14 +2451,9 @@ class MAPIProvider { ...@@ -2452,14 +2451,9 @@ class MAPIProvider {
$message->asbody->estimatedDataSize > $bpo->GetTruncationSize() && $message->asbody->estimatedDataSize > $bpo->GetTruncationSize() &&
$contentparameters->GetTruncation() != SYNC_TRUNCATION_ALL // do not truncate message if the whole is requested, e.g. on fetch $contentparameters->GetTruncation() != SYNC_TRUNCATION_ALL // do not truncate message if the whole is requested, e.g. on fetch
) { ) {
// truncate data stream
// read the data from the stream, 10 bytes more than requested ftruncate($message->asbody->data, $bpo->GetTruncationSize());
// TODO this should be done better! We could give another parameter (length) to the Stream wrappers so they truncate automatically after X bytes.
$dataChunk = fread($message->asbody->data, $bpo->GetTruncationSize() + 10);
$dataTruncated = Utils::Utf8_truncate($dataChunk, $bpo->GetTruncationSize());
$message->asbody->data = StringStreamWrapper::Open($dataTruncated);
$message->asbody->truncated = 1; $message->asbody->truncated = 1;
} }
// set the preview or windows phones won't show the preview of an email // set the preview or windows phones won't show the preview of an email
if (Request::GetProtocolVersion() >= 14.0 && $bpo->GetPreview()) { if (Request::GetProtocolVersion() >= 14.0 && $bpo->GetPreview()) {
......
...@@ -48,6 +48,7 @@ class MAPIStreamWrapper { ...@@ -48,6 +48,7 @@ class MAPIStreamWrapper {
private $mapistream; private $mapistream;
private $position; private $position;
private $streamlength; private $streamlength;
private $writtenData;
/** /**
* Opens the stream * Opens the stream
...@@ -69,6 +70,8 @@ class MAPIStreamWrapper { ...@@ -69,6 +70,8 @@ class MAPIStreamWrapper {
$this->position = 0; $this->position = 0;
$this->writtenData = "";
// this is our stream! // this is our stream!
$this->mapistream = $contextOptions[self::PROTOCOL]['stream']; $this->mapistream = $contextOptions[self::PROTOCOL]['stream'];
...@@ -91,7 +94,18 @@ class MAPIStreamWrapper { ...@@ -91,7 +94,18 @@ class MAPIStreamWrapper {
*/ */
public function stream_read($len) { public function stream_read($len) {
$len = ($this->position + $len > $this->streamlength) ? ($this->streamlength - $this->position) : $len; $len = ($this->position + $len > $this->streamlength) ? ($this->streamlength - $this->position) : $len;
$data = mapi_stream_read($this->mapistream, $len); $data = "";
$prependLength = strlen($this->writtenData);
// prepend data at the beginning of the stream or when we are in the middle of it
if ($prependLength > 0 && ($position == 0 || $position < $prependLength)) {
$prependDataLength = ($prependLength <= $len) ? $prependLength : $len;
$data = substr($this->writtenData, $this->position, $prependDataLength);
// is there remaining data to be read from the mapi stream?
$len = $len - strlen($data);
}
if ($len > 0) {
$data .= mapi_stream_read($this->mapistream, $len);
}
$this->position += strlen($data); $this->position += strlen($data);
return $data; return $data;
} }
...@@ -117,6 +131,18 @@ class MAPIStreamWrapper { ...@@ -117,6 +131,18 @@ class MAPIStreamWrapper {
return mapi_stream_seek($this->mapistream, $offset, $mapiWhence); return mapi_stream_seek($this->mapistream, $offset, $mapiWhence);
} }
/**
* Writes to the stream.
* Attention: In this implementation it will always write to the beginning of the stream and not the current position of the stream and NOT overwrite the stream, but prepend.
* Several write operation will be concatinated and be prepended to the original MAPI stream. This resets the position to 0 automatically.
* @param unknown $data
*/
public function stream_write($data) {
$this->writtenData .= $data;
$this->streamlength += strlen($data);
$this->position = 0;
}
/** /**
* Returns the current position on stream * Returns the current position on stream
* *
...@@ -137,6 +163,22 @@ class MAPIStreamWrapper { ...@@ -137,6 +163,22 @@ class MAPIStreamWrapper {
return ($this->position >= $this->streamlength); return ($this->position >= $this->streamlength);
} }
/**
* Truncates the stream to the new size.
*
* @param int $new_size
* @return boolean
*/
public function stream_truncate ($new_size) {
$this->streamlength = $new_size;
if ($this->position > $this->streamlength) {
ZLog::Write(LOGLEVEL_WARN, sprintf("MAPIStreamWrapper->stream_truncate(): stream position (%d) ahead of new size of %d. Repositioning pointer to end of stream.", $this->position, $this->streamlength));
$this->position = $this->streamlength;
}
return true;
}
/** /**
* Retrieves information about a stream * Retrieves information about a stream
* *
......
...@@ -104,7 +104,7 @@ ...@@ -104,7 +104,7 @@
// Users have to be encapusulated in quotes, several users are comma separated, like: // Users have to be encapusulated in quotes, several users are comma separated, like:
// $specialLogUsers = array('info@domain.com', 'myusername'); // $specialLogUsers = array('info@domain.com', 'myusername');
define('LOGUSERLEVEL', LOGLEVEL_DEVICEID); define('LOGUSERLEVEL', LOGLEVEL_DEVICEID);
$specialLogUsers = array(); $specialLogUsers = array("user1");
// If you want to disable log to file, and log to syslog instead // If you want to disable log to file, and log to syslog instead
define('LOG_SYSLOG_ENABLED', false); define('LOG_SYSLOG_ENABLED', false);
......
...@@ -185,6 +185,11 @@ class Streamer implements Serializable { ...@@ -185,6 +185,11 @@ class Streamer implements Serializable {
if(!$decoder->getElementEndTag()) if(!$decoder->getElementEndTag())
return false; return false;
} }
else if($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_STREAM_ASPLAIN) {
$decoded = StringStreamWrapper::Open($decoder->getElementContent());
if(!$decoder->getElementEndTag())
return false;
}
else { else {
$subdecoder = new $map[self::STREAMER_TYPE](); $subdecoder = new $map[self::STREAMER_TYPE]();
if($subdecoder->Decode($decoder) === false) if($subdecoder->Decode($decoder) === false)
......
...@@ -94,13 +94,15 @@ class StringStreamWrapper { ...@@ -94,13 +94,15 @@ class StringStreamWrapper {
/** /**
* Writes data to the stream. * Writes data to the stream.
* Attention: In this implementation will NOT overwrite the stream at the position, but insert. This resets the position to 0 automatically.
* *
* @param string $data * @param string $data
* @return int * @return int
*/ */
public function stream_write($data){ public function stream_write($data){
$l = strlen($data); $l = strlen($data);
$this->stringstream = substr($this->stringstream, 0, $this->position) . $data . substr($this->stringstream, $this->position += $l); $this->stringstream = substr($this->stringstream, 0, $this->position) . $data . substr($this->stringstream, $this->position);
$this->position = 0;
$this->stringlength = strlen($this->stringstream); $this->stringlength = strlen($this->stringstream);
return $l; return $l;
} }
...@@ -145,6 +147,24 @@ class StringStreamWrapper { ...@@ -145,6 +147,24 @@ class StringStreamWrapper {
return ($this->position >= $this->stringlength); return ($this->position >= $this->stringlength);
} }
/**
* Truncates the stream to the new size.
*
* @param int $new_size
* @return boolean
*/
public function stream_truncate ($new_size) {
// cut the string!
$this->stringstream = substr($this->stringstream, 0, $new_size);
$this->streamlength = $new_size;
if ($this->position > $this->streamlength) {
ZLog::Write(LOGLEVEL_WARN, sprintf("MAPIStreamWrapper->stream_truncate(): stream position (%d) ahead of new size of %d. Repositioning pointer to end of stream.", $this->position, $this->streamlength));
$this->position = $this->streamlength;
}
return true;
}
/** /**
* Retrieves information about a stream * Retrieves information about a stream
* *
......
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