Commit 1a357f14 authored by mku's avatar mku

ZP-150 #comment Inline images can not be downloaded with Windows Phone 7.5 or...

ZP-150 #comment Inline images can not be downloaded with Windows Phone 7.5 or Samsung Galaxy S2, added multipart request handling, new multipart prop for streamer vars, stat function for streams  #time 12h

git-svn-id: https://z-push.org/svn/z-push/trunk@1384 b7dd7b3b-3a3c-0410-9da9-bee62a6cc5b5
parent a6381c1e
...@@ -123,6 +123,19 @@ class MAPIStreamWrapper { ...@@ -123,6 +123,19 @@ class MAPIStreamWrapper {
return ($this->position >= $this->streamlength); return ($this->position >= $this->streamlength);
} }
/**
* Retrieves information about a stream
*
* @access public
* @return array
*/
public function stream_stat() {
return array(
7 => $this->streamlength,
'size' => $this->streamlength,
);
}
/** /**
* Instantiates a MAPIStreamWrapper * Instantiates a MAPIStreamWrapper
* *
......
...@@ -112,6 +112,19 @@ class StringStreamWrapper { ...@@ -112,6 +112,19 @@ class StringStreamWrapper {
return ($this->position >= $this->stringlength); return ($this->position >= $this->stringlength);
} }
/**
* Retrieves information about a stream
*
* @access public
* @return array
*/
public function stream_stat() {
return array(
7 => $this->stringlength,
'size' => $this->stringlength,
);
}
/** /**
* Instantiates a StringStreamWrapper * Instantiates a StringStreamWrapper
* *
......
...@@ -61,6 +61,7 @@ class Streamer implements Serializable { ...@@ -61,6 +61,7 @@ class Streamer implements Serializable {
const STREAMER_TYPE_NO_CONTAINER = 7; const STREAMER_TYPE_NO_CONTAINER = 7;
const STREAMER_TYPE_COMMA_SEPARATED = 8; const STREAMER_TYPE_COMMA_SEPARATED = 8;
const STREAMER_TYPE_SEMICOLON_SEPARATED = 9; const STREAMER_TYPE_SEMICOLON_SEPARATED = 9;
const STREAMER_TYPE_MULTIPART = 10;
protected $mapping; protected $mapping;
public $flags; public $flags;
...@@ -280,6 +281,14 @@ class Streamer implements Serializable { ...@@ -280,6 +281,14 @@ class Streamer implements Serializable {
continue; continue;
} }
if ($encoder->getMultipart() && isset($map[self::STREAMER_PROP]) && $map[self::STREAMER_PROP] == self::STREAMER_TYPE_MULTIPART) {
$encoder->addBodypartStream($this->$map[self::STREAMER_VAR]);
$encoder->startTag(SYNC_ITEMOPERATIONS_PART);
$encoder->content(count($encoder->getBodypartsCount()));
$encoder->endTag();
continue;
}
// Simple type // Simple type
if(!isset($map[self::STREAMER_TYPE]) && strlen($this->$map[self::STREAMER_VAR]) == 0) { if(!isset($map[self::STREAMER_TYPE]) && strlen($this->$map[self::STREAMER_VAR]) == 0) {
// send empty tags // send empty tags
......
...@@ -94,6 +94,7 @@ class Request { ...@@ -94,6 +94,7 @@ class Request {
static private $longId; //TODO static private $longId; //TODO
static private $occurence; //TODO static private $occurence; //TODO
static private $saveInSent; static private $saveInSent;
static private $acceptMultipart;
/** /**
...@@ -163,8 +164,11 @@ class Request { ...@@ -163,8 +164,11 @@ class Request {
if (isset($query[self::COMMANDPARAM_ITEMID])) if (isset($query[self::COMMANDPARAM_ITEMID]))
self::$itemId = self::filterEvilInput($query[self::COMMANDPARAM_ITEMID], self::HEX_ONLY); self::$itemId = self::filterEvilInput($query[self::COMMANDPARAM_ITEMID], self::HEX_ONLY);
if (isset($query[self::COMMANDPARAM_OPTIONS]) && ($query[self::COMMANDPARAM_OPTIONS] & 1)) if (isset($query[self::COMMANDPARAM_OPTIONS]) && (ord($query[self::COMMANDPARAM_OPTIONS]) & self::COMMANDPARAM_OPTIONS_SAVEINSENT))
self::$saveInSent = true; self::$saveInSent = true;
if (isset($query[self::COMMANDPARAM_OPTIONS]) && (ord($query[self::COMMANDPARAM_OPTIONS]) & self::COMMANDPARAM_OPTIONS_ACCEPTMULTIPART))
self::$acceptMultipart = true;
} }
// in base64 encoded query string user is not necessarily set // in base64 encoded query string user is not necessarily set
...@@ -201,6 +205,11 @@ class Request { ...@@ -201,6 +205,11 @@ class Request {
if (isset(self::$asProtocolVersion)) if (isset(self::$asProtocolVersion))
self::$headers["ms-asprotocolversion"] = self::$asProtocolVersion; self::$headers["ms-asprotocolversion"] = self::$asProtocolVersion;
} }
if (!isset(self::$acceptMultipart) && isset(self::$headers["ms-asacceptmultipart"]) && strtoupper(self::$headers["ms-asacceptmultipart"]) == "T") {
self::$acceptMultipart = true;
}
ZLog::Write(LOGLEVEL_DEBUG, sprintf("Request::ProcessHeaders() ASVersion: %s", self::$asProtocolVersion)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("Request::ProcessHeaders() ASVersion: %s", self::$asProtocolVersion));
} }
...@@ -316,6 +325,19 @@ class Request { ...@@ -316,6 +325,19 @@ class Request {
return true; return true;
} }
/**
* Returns if the AcceptMultipart parameter of the querystring is set
*
* @access public
* @return boolean
*/
static public function GetGETAcceptMultipart() {
if (isset(self::$acceptMultipart))
return self::$acceptMultipart;
else
return false;
}
/** /**
* Returns the value of the AttachmentName parameter of the querystring * Returns the value of the AttachmentName parameter of the querystring
* *
......
...@@ -110,7 +110,7 @@ abstract class RequestProcessor { ...@@ -110,7 +110,7 @@ abstract class RequestProcessor {
if (!ZPush::CommandNeedsPlainInput(Request::GetCommandCode())) if (!ZPush::CommandNeedsPlainInput(Request::GetCommandCode()))
self::$decoder = new WBXMLDecoder(Request::GetInputStream()); self::$decoder = new WBXMLDecoder(Request::GetInputStream());
self::$encoder = new WBXMLEncoder(Request::GetOutputStream()); self::$encoder = new WBXMLEncoder(Request::GetOutputStream(), Request::GetGETAcceptMultipart());
} }
/** /**
......
...@@ -56,7 +56,8 @@ class SyncBaseBody extends SyncObject { ...@@ -56,7 +56,8 @@ class SyncBaseBody extends SyncObject {
SYNC_AIRSYNCBASE_TYPE => array (self::STREAMER_VAR => "type"), SYNC_AIRSYNCBASE_TYPE => array (self::STREAMER_VAR => "type"),
SYNC_AIRSYNCBASE_ESTIMATEDDATASIZE => array (self::STREAMER_VAR => "estimatedDataSize"), SYNC_AIRSYNCBASE_ESTIMATEDDATASIZE => array (self::STREAMER_VAR => "estimatedDataSize"),
SYNC_AIRSYNCBASE_TRUNCATED => array (self::STREAMER_VAR => "truncated"), SYNC_AIRSYNCBASE_TRUNCATED => array (self::STREAMER_VAR => "truncated"),
SYNC_AIRSYNCBASE_DATA => array (self::STREAMER_VAR => "data"), //TODO data should be of a type stream SYNC_AIRSYNCBASE_DATA => array (self::STREAMER_VAR => "data",
self::STREAMER_PROP => self::STREAMER_TYPE_MULTIPART), //TODO data should be of a type stream
); );
if(Request::GetProtocolVersion() >= 14.0) { if(Request::GetProtocolVersion() >= 14.0) {
$mapping[SYNC_AIRSYNCBASE_PREVIEW] = array (self::STREAMER_VAR => "preview"); $mapping[SYNC_AIRSYNCBASE_PREVIEW] = array (self::STREAMER_VAR => "preview");
......
...@@ -52,7 +52,8 @@ class SyncItemOperationsAttachment extends SyncObject { ...@@ -52,7 +52,8 @@ class SyncItemOperationsAttachment extends SyncObject {
$mapping = array( $mapping = array(
SYNC_AIRSYNCBASE_CONTENTTYPE => array ( self::STREAMER_VAR => "contenttype"), SYNC_AIRSYNCBASE_CONTENTTYPE => array ( self::STREAMER_VAR => "contenttype"),
SYNC_ITEMOPERATIONS_DATA => array ( self::STREAMER_VAR => "data", SYNC_ITEMOPERATIONS_DATA => array ( self::STREAMER_VAR => "data",
self::STREAMER_TYPE => self::STREAMER_TYPE_STREAM), self::STREAMER_TYPE => self::STREAMER_TYPE_STREAM,
self::STREAMER_PROP => self::STREAMER_TYPE_MULTIPART),
); );
parent::SyncObject($mapping); parent::SyncObject($mapping);
......
...@@ -59,7 +59,10 @@ class WBXMLEncoder extends WBXMLDefs { ...@@ -59,7 +59,10 @@ class WBXMLEncoder extends WBXMLDefs {
private $_stack; private $_stack;
public function WBXMLEncoder($output) { private $multipart; // the content is multipart
private $bodyparts;
public function WBXMLEncoder($output, $multipart = false) {
// make sure WBXML_DEBUG is defined. It should be at this point // make sure WBXML_DEBUG is defined. It should be at this point
if (!defined('WBXML_DEBUG')) define('WBXML_DEBUG', false); if (!defined('WBXML_DEBUG')) define('WBXML_DEBUG', false);
...@@ -80,6 +83,8 @@ class WBXMLEncoder extends WBXMLDefs { ...@@ -80,6 +83,8 @@ class WBXMLEncoder extends WBXMLDefs {
} }
} }
$this->_stack = array(); $this->_stack = array();
$this->multipart = $multipart;
$this->bodyparts = array();
} }
/** /**
...@@ -89,7 +94,12 @@ class WBXMLEncoder extends WBXMLDefs { ...@@ -89,7 +94,12 @@ class WBXMLEncoder extends WBXMLDefs {
* @return * @return
*/ */
public function startWBXML() { public function startWBXML() {
if ($this->multipart) {
header("Content-Type: application/vnd.ms-sync.multipart");
}
else {
header("Content-Type: application/vnd.ms-sync.wbxml"); header("Content-Type: application/vnd.ms-sync.wbxml");
}
$this->outByte(0x03); // WBXML 1.3 $this->outByte(0x03); // WBXML 1.3
$this->outMBUInt(0x01); // Public ID 1 $this->outMBUInt(0x01); // Public ID 1
...@@ -138,6 +148,10 @@ class WBXMLEncoder extends WBXMLDefs { ...@@ -138,6 +148,10 @@ class WBXMLEncoder extends WBXMLDefs {
// Only output end tags for items that have had a start tag sent // Only output end tags for items that have had a start tag sent
if($stackelem['sent']) { if($stackelem['sent']) {
$this->_endTag(); $this->_endTag();
if(count($this->_stack) == 0 && $this->multipart == true) {
$this->processMultipart();
}
} }
} }
...@@ -160,6 +174,39 @@ class WBXMLEncoder extends WBXMLDefs { ...@@ -160,6 +174,39 @@ class WBXMLEncoder extends WBXMLDefs {
$this->_content($content); $this->_content($content);
} }
/**
* Gets the value of multipart
*
* @access public
* @return boolean
*/
public function getMultipart() {
return $this->multipart;
}
/**
* Adds a bodypart
*
* @param Stream $bp
*
* @access public
* @return void
*/
public function addBodypartStream($bp) {
if ($this->multipart)
$this->bodyparts[] = $bp;
}
/**
* Gets the number of bodyparts
*
* @access public
* @return int
*/
public function getBodypartsCount() {
return count($this->bodyparts);
}
/**---------------------------------------------------------------------------------------------------------- /**----------------------------------------------------------------------------------------------------------
* Private WBXMLEncoder stuff * Private WBXMLEncoder stuff
*/ */
...@@ -417,6 +464,38 @@ class WBXMLEncoder extends WBXMLDefs { ...@@ -417,6 +464,38 @@ class WBXMLEncoder extends WBXMLDefs {
$spaces = str_repeat(" ", count($this->logStack)); $spaces = str_repeat(" ", count($this->logStack));
ZLog::Write(LOGLEVEL_WBXML,"O " . $spaces . $content); ZLog::Write(LOGLEVEL_WBXML,"O " . $spaces . $content);
} }
/**
* Processes the multipart response
*
* @access private
* @return void
*/
private function processMultipart() {
$len = ob_get_length();
$buffer = ob_get_clean();
$nrBodyparts = $this->getBodypartsCount();
$blockstart = (($nrBodyparts + 1) * 2) * 4 + 4;
$data = pack("iii", ($nrBodyparts + 1), $blockstart, $len);
ob_start(null, 1048576);
foreach ($this->bodyparts as $bp) {
$blockstart = $blockstart + $len;
$len = fstat($bp);
$len = (isset($len['size'])) ? $len['size'] : 0;
$data .= pack("ii", $blockstart, $len);
}
fwrite($this->_out, $data);
fwrite($this->_out, $buffer);
foreach($this->bodyparts as $bp) {
while (!feof($bp)) {
fwrite($this->_out, fread($bp, 4096));
}
}
}
} }
?> ?>
\ No newline at end of file
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