Page MenuHomePhorge

No OneTemporary

Size
16 KB
Referenced Files
None
Subscribers
None
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

Mime Type
text/x-diff
Expires
Thu, Mar 19, 8:57 AM (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
456327
Default Alt Text
(16 KB)

Event Timeline