Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2571743
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/ext/Syncroton/Wbxml/Abstract.php b/lib/ext/Syncroton/Wbxml/Abstract.php
index 7fdd653..bec61f1 100644
--- a/lib/ext/Syncroton/Wbxml/Abstract.php
+++ b/lib/ext/Syncroton/Wbxml/Abstract.php
@@ -1,241 +1,255 @@
<?php
/**
* Syncroton
*
* @package Wbxml
* @subpackage Wbxml
* @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
* @copyright Copyright (c) 2008-2009 Metaways Infosystems GmbH (http://www.metaways.de)
* @author Lars Kneschke <l.kneschke@metaways.de>
* @version $Id:Abstract.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $
*/
/**
* class documentation
*
* @package Wbxml
* @subpackage Wbxml
*/
abstract class Syncroton_Wbxml_Abstract
{
/**
* stream containing the wbxml encoded data
*
* @var resource
*/
protected $_stream;
/**
* the wbxml version
*
* @var string
*/
protected $_version;
/**
* the Document Public Identifier
*
* @var string
*/
protected $_dpi;
/**
* the current active dtd
*
* @var Syncroton_Wbxml_Dtd_Syncml_Abstract
*/
protected $_dtd;
/**
* the charSet used in the wbxml file
*
* @var string
*/
protected $_charSet;
/**
* currently active code page
*
* @var array
*/
protected $_codePage;
/**
* see section 5.5
*
*/
const DPI_WELLKNOWN = 'WELLKNOWN';
/**
* see section 5.5
*
*/
const DPI_STRINGTABLE = 'STRINGTABLE';
const SWITCH_PAGE = 0x00;
const END = 0x01;
const ENTITY = 0x02;
const STR_I = 0x03;
const LITERAL = 0x04;
const EXT_I_0 = 0x40;
const EXT_I_1 = 0x41;
const EXT_I_2 = 0x42;
const PI = 0x43;
const LITERAL_C = 0x44;
const EXT_T_0 = 0x80;
const EXT_T_1 = 0x81;
const EXT_T_2 = 0x82;
const STR_T = 0x83;
const LITERAL_A = 0x84;
const EXT_0 = 0xC0;
const EXT_1 = 0xC1;
const EXT_2 = 0xC2;
const OPAQUE = 0xC3;
const LITERAL_AC = 0xC4;
/**
* the real name for this DPI is "unknown"
* But Microsoft is using them for their ActiveSync stuff
* instead defining their own DPI like the sycnml creators did
*
*/
const DPI_1 = '-//AIRSYNC//DTD AirSync//EN';
/**
* return wellknown identifiers
*
* @param integer $_uInt
* @todo add well known identifiers from section 7.2
* @return string
*/
public function getDPI($_uInt = 0)
{
if(!defined('Syncroton_Wbxml_Abstract::DPI_' . $_uInt)) {
throw new Syncroton_Wbxml_Exception('unknown wellknown identifier: ' . $_uInt);
}
$dpi = constant('Syncroton_Wbxml_Abstract::DPI_' . $_uInt);
return $dpi;
}
/**
* return multibyte integer
*
* @return integer
*/
protected function _getMultibyteUInt()
{
$uInt = 0;
do {
$byte = $this->_getByte();
$uInt <<= 7;
$uInt += ($byte & 127);
} while (($byte & 128) != 0);
return $uInt;
}
protected function _getByte()
{
$byte = fread($this->_stream, 1);
if($byte === false) {
throw new Syncroton_Wbxml_Exception("failed reading one byte");
}
return ord($byte);
}
protected function _getOpaque($_length)
{
- $string = fread($this->_stream, $_length);
-
- if($string === false) {
- throw new Syncroton_Wbxml_Exception("failed reading opaque data");
+ $string = '';
+
+ // it might happen that not complete data is read from stream.
+ // loop until all data is read or EOF
+ while ($_length) {
+ $chunk = fread($this->_stream, $_length);
+
+ if ($chunk === false) {
+ throw new Syncroton_Wbxml_Exception("failed reading opaque data");
+ }
+
+ if ($len = strlen($chunk)) {
+ $string .= $chunk;
+ $_length -= $len;
+ }
+ else if (feof($this->_stream)) {
+ break;
+ }
}
-
+
return $string;
}
/**
* get a 0 terminated string
*
* @return string
*/
protected function _getTerminatedString()
{
$string = '';
while (($byte = $this->_getByte()) != 0) {
$string .= chr($byte);
}
return $string;
}
protected function _writeByte($_byte)
{
fwrite($this->_stream, chr($_byte));
}
protected function _writeMultibyteUInt($_integer)
{
$multibyte = NULL;
$remainder = $_integer;
do {
$byte = ($remainder & 127);
$remainder >>= 7;
if($multibyte === NULL) {
$multibyte = chr($byte);
} else {
$multibyte = chr($byte | 128) . $multibyte;
}
} while ($remainder != 0);
fwrite($this->_stream, $multibyte);
}
protected function _writeString($_string)
{
fwrite($this->_stream, $_string);
}
/**
* write opaque string to stream
*
* @param string|resource $_string
* @throws Syncroton_Wbxml_Exception
*/
protected function _writeOpaqueString($_string)
{
if (is_resource($_string)) {
$stream = $_string;
} else {
$stream = fopen("php://temp", 'r+');
fwrite($stream, $_string);
}
$length = ftell($stream);
rewind($stream);
$this->_writeByte(Syncroton_Wbxml_Abstract::OPAQUE);
$this->_writeMultibyteUInt($length);
$writenBytes = stream_copy_to_stream($stream, $this->_stream);
if($writenBytes !== $length) {
throw new Syncroton_Wbxml_Exception('blow');
}
fclose($stream);
}
protected function _writeTerminatedString($_string)
{
$this->_writeByte(Syncroton_Wbxml_Abstract::STR_I);
fwrite($this->_stream, $_string);
fwrite($this->_stream, chr(0));
}
}
\ No newline at end of file
diff --git a/lib/ext/Syncroton/Wbxml/Decoder.php b/lib/ext/Syncroton/Wbxml/Decoder.php
index f99b7f3..130d84f 100644
--- a/lib/ext/Syncroton/Wbxml/Decoder.php
+++ b/lib/ext/Syncroton/Wbxml/Decoder.php
@@ -1,301 +1,303 @@
<?php
/**
* Syncroton
*
* @package Wbxml
* @subpackage Wbxml
* @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
* @copyright Copyright (c) 2008-2009 Metaways Infosystems GmbH (http://www.metaways.de)
* @author Lars Kneschke <l.kneschke@metaways.de>
* @version $Id:Decoder.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $
*/
/**
* class to convert WBXML to XML
*
* @package Wbxml
* @subpackage Wbxml
*/
class Syncroton_Wbxml_Decoder extends Syncroton_Wbxml_Abstract
{
/**
* type of Document Public Identifier
*
* @var string the type can be Syncroton_Wbxml_Abstract::DPI_STRINGTABLE or Syncroton_Wbxml_Abstract::DPI_WELLKNOWN
*/
protected $_dpiType;
/**
* the string table
*
* @var array
*/
protected $_stringTable = array();
/**
* the xml document
*
* @var DOMDocument
*/
protected $_dom;
/**
* the main name space / aka the namespace of first tag
*
* @var string
*/
protected $_mainNameSpace;
/**
* the constructor will try to read all data until the first tag
*
* @param resource $_stream
*/
public function __construct($_stream, $_dpi = NULL)
{
if(!is_resource($_stream) || get_resource_type($_stream) != 'stream') {
throw new Syncroton_Wbxml_Exception('$_stream must be a stream');
}
if($_dpi !== NULL) {
$this->_dpi = $_dpi;
}
$this->_stream = $_stream;
$this->_version = $this->_getByte();
if(feof($this->_stream)) {
throw new Syncroton_Wbxml_Exception_UnexpectedEndOfFile();
}
$this->_getDPI();
$this->_getCharset();
$this->_getStringTable();
// resolve DPI as we have read the stringtable now
// this->_dpi contains the string table index
if($this->_dpiType === Syncroton_Wbxml_Abstract::DPI_STRINGTABLE) {
$this->_dpi = $this->_stringTable[$this->_dpi];
}
#$this->_dtd = Syncroton_Wbxml_Dtd_Factory::factory($this->_dpi);
$this->_dtd = Syncroton_Wbxml_Dtd_Factory::factory(Syncroton_Wbxml_Dtd_Factory::ACTIVESYNC);
}
/**
* return the Document Public Identifier
*
* @param integer $_uInt unused param, needed to satisfy abstract class method signature
* @return string
*/
public function getDPI($_uInt = 0)
{
return $this->_dpi;
}
/**
* return the wbxml version
*
* @return string
*/
public function getVersion()
{
return $this->_version;
}
/**
* decodes the tags
*
* @return DOMDocument the decoded xml
*/
public function decode()
{
$openTags = NULL;
$node = NULL;
$this->_codePage = $this->_dtd->getCurrentCodePage();
while (!feof($this->_stream)) {
$byte = $this->_getByte();
switch($byte) {
case Syncroton_Wbxml_Abstract::END:
$node = $node->parentNode;
$openTags--;
break;
case Syncroton_Wbxml_Abstract::OPAQUE:
$length = $this->_getMultibyteUInt();
if($length > 0) {
+ // @TODO: handle big data with streams
+ // E.g. in SendMail command "opaqued" <Mime> contains full email body
$opaque = $this->_getOpaque($length);
try {
// let see if we can decode it. maybe the opaque data is wbxml encoded content
$opaqueDataStream = fopen("php://temp", 'r+');
fputs($opaqueDataStream, $opaque);
rewind($opaqueDataStream);
$opaqueContentDecoder = new Syncroton_Wbxml_Decoder($opaqueDataStream);
$dom = $opaqueContentDecoder->decode();
fclose($opaqueDataStream);
foreach($dom->childNodes as $newNode) {
if($newNode instanceof DOMElement) {
$newNode = $this->_dom->importNode($newNode, true);
$node->appendChild($newNode);
}
}
} catch (Exception $e) {
// if not, just treat it as a string
$node->appendChild($this->_dom->createTextNode($opaque));
}
}
break;
case Syncroton_Wbxml_Abstract::STR_I:
$string = $this->_getTerminatedString();
$node->appendChild($this->_dom->createTextNode($string));
break;
case Syncroton_Wbxml_Abstract::SWITCH_PAGE:
$page = $this->_getByte();
$this->_codePage = $this->_dtd->switchCodePage($page);
#echo "switched to codepage $page\n";
break;
default:
$tagHasAttributes = (($byte & 0x80) != 0);
$tagHasContent = (($byte & 0x40) != 0);
// get rid of bit 7+8
$tagHexCode = $byte & 0x3F;
$tag = $this->_codePage->getTag($tagHexCode);
$nameSpace = $this->_codePage->getNameSpace();
$codePageName = $this->_codePage->getCodePageName();
#echo "Tag: $nameSpace:$tag\n";
if($node === NULL) {
// create the domdocument
$node = $this->_createDomDocument($nameSpace, $tag);
$newNode = $node->documentElement;
} else {
if(!$this->_dom->isDefaultNamespace($nameSpace)) {
$this->_dom->documentElement->setAttribute('xmlns:' . $codePageName, $nameSpace);
}
$newNode = $node->appendChild($this->_dom->createElementNS('uri:' . $codePageName, $tag));
}
if($tagHasAttributes) {
$attributes = $this->_getAttributes();
}
if($tagHasContent == true) {
$node = $newNode;
$openTags++;
}
break;
}
}
return $this->_dom;
}
/**
* creates the root of the xml document
*
* @return DOMDocument
*/
protected function _createDomDocument($_nameSpace, $_tag)
{
$this->_dom = $this->_dtd->getDomDocument($_nameSpace, $_tag);
return $this->_dom;
}
/**
* read the attributes of the current tag
*
* @todo implement logic
*/
protected function _getAttributes()
{
die("fetching attributes not yet implemented!\n");
}
/**
* get document public identifier
*
* the identifier can be all welknown identifier (see section 7.2) or a string from the stringtable
*/
protected function _getDPI()
{
$uInt = $this->_getMultibyteUInt();
if($uInt == 0) {
// get identifier from stringtable
$this->_dpiType = Syncroton_Wbxml_Abstract::DPI_STRINGTABLE;
// string table identifier, can be resolved only after reading string table
$this->_dpi = $this->_getByte();
} else {
// wellknown identifier
$this->_dpiType = Syncroton_Wbxml_Abstract::DPI_WELLKNOWN;
$this->_dpi = Syncroton_Wbxml_Abstract::getDPI($uInt);
}
}
/**
* see http://www.iana.org/assignments/character-sets (MIBenum)
* 106: UTF-8
*
*/
protected function _getCharset()
{
$uInt = $this->_getMultibyteUInt();
switch($uInt) {
case 106:
$this->_charSet = 'UTF-8';
break;
default:
throw new Syncroton_Wbxml_Exception('unsuported charSet: ' . $uInt);
break;
}
}
/**
* get string table and store strings indexed by start
*
* @todo validate spliting at 0 value
*/
protected function _getStringTable()
{
$length = $this->_getMultibyteUInt();
if($length > 0) {
$rawStringTable = $this->_getOpaque($length);
$index = NULL;
$string = NULL;
for($i = 0; $i < strlen($rawStringTable); $i++) {
if($index === NULL) {
$index = $i;
}
if(ord($rawStringTable[$i]) != 0) {
$string .= $rawStringTable[$i];
}
// either the string has ended or we reached a \0
if($i+1 == strlen($rawStringTable) || ord($rawStringTable[$i]) == 0){
$this->_stringTable[$index] = $string;
$index = NULL;
$string = NULL;
}
}
}
}
}
\ No newline at end of file
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Mar 19, 8:57 AM (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
456327
Default Alt Text
(16 KB)
Attached To
Mode
R4 syncroton
Attached
Detach File
Event Timeline
Log In to Comment