Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117755083
Encoder.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
11 KB
Referenced Files
None
Subscribers
None
Encoder.php
View Options
<?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:Encoder.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $
*/
/**
* class to convert XML to WBXML
*
* @package Wbxml
* @subpackage Wbxml
*/
class
Syncroton_Wbxml_Encoder
extends
Syncroton_Wbxml_Abstract
{
/**
* stack of dtd objects
*
* @var array
*/
protected
$_dtdStack
=
array
();
/**
* stack of stream resources
*
* @var array
*/
protected
$_streamStack
=
array
();
/**
* stack of levels when to pop data from the other stacks
*
* @var array
*/
protected
$_popStack
=
array
();
/**
* count level of tags
*
* @var string
*/
protected
$_level
=
0
;
/**
* when to take data next time from the different stacks
*
* @var unknown_type
*/
protected
$_nextStackPop
=
NULL
;
/**
* collect data trough different calls to _handleCharacters
*
* @var string
*/
protected
$_currentTagData
=
NULL
;
/**
* the current tag as read by the parser
*
* @var string
*/
protected
$_currentTag
=
NULL
;
/**
* the constructor
*
* @param resource $_stream
* @param string $_charSet
* @param integer $_version
*/
public
function
__construct
(
$_stream
,
$_charSet
=
'UTF-8'
,
$_version
=
2
)
{
$this
->
_stream
=
$_stream
;
$this
->
_charSet
=
$_charSet
;
$this
->
_version
=
$_version
;
}
/**
* initialize internal variables and write wbxml header to stream
*
* @param string $_urn
* @todo check if dpi > 0, instead checking the urn
*/
protected
function
_initialize
(
$_dom
)
{
$this
->
_dtd
=
Syncroton_Wbxml_Dtd_Factory
::
factory
(
$_dom
->
doctype
->
name
);
$this
->
_codePage
=
$this
->
_dtd
->
getCurrentCodePage
();
// the WBXML version
$this
->
_writeByte
(
$this
->
_version
);
if
(
$this
->
_codePage
->
getDPI
()
===
NULL
)
{
// the document public identifier
$this
->
_writeMultibyteUInt
(
1
);
}
else
{
// the document public identifier
// defined in string table
$this
->
_writeMultibyteUInt
(
0
);
// the offset of the DPI in the string table
$this
->
_writeByte
(
0
);
}
// write the charSet
$this
->
_writeCharSet
(
$this
->
_charSet
);
if
(
$this
->
_codePage
->
getDPI
()
===
NULL
)
{
// the length of the string table
$this
->
_writeMultibyteUInt
(
0
);
}
else
{
// the length of the string table
$this
->
_writeMultibyteUInt
(
strlen
(
$this
->
_codePage
->
getDPI
()));
// the dpi
$this
->
_writeString
(
$this
->
_codePage
->
getDPI
());
}
}
/**
* write charset to stream
*
* @param string $_charSet
* @todo add charset lookup table. currently only utf-8 is supported
*/
protected
function
_writeCharSet
(
$_charSet
)
{
switch
(
strtoupper
(
$_charSet
))
{
case
'UTF-8'
:
$this
->
_writeMultibyteUInt
(
106
);
break
;
default
:
throw
new
Syncroton_Wbxml_Exception
(
'unsuported charSet '
.
strtoupper
(
$_charSet
));
break
;
}
}
/**
* start encoding of xml to wbxml
*
* @param string $_xml the xml string
* @return resource stream
*/
public
function
encode
(
DOMDocument
$_dom
)
{
$_dom
->
formatOutput
=
false
;
$tempStream
=
tmpfile
();
$meta_data
=
stream_get_meta_data
(
$tempStream
);
$filename
=
$meta_data
[
"uri"
];
$_dom
->
save
(
$filename
);
rewind
(
$tempStream
);
$this
->
_initialize
(
$_dom
);
$parser
=
xml_parser_create_ns
(
$this
->
_charSet
,
';'
);
xml_set_object
(
$parser
,
$this
);
xml_set_element_handler
(
$parser
,
'_handleStartTag'
,
'_handleEndTag'
);
xml_set_character_data_handler
(
$parser
,
'_handleCharacters'
);
xml_parser_set_option
(
$parser
,
XML_OPTION_CASE_FOLDING
,
0
);
while
(!
feof
(
$tempStream
))
{
if
(!
xml_parse
(
$parser
,
fread
(
$tempStream
,
1048576
),
feof
(
$tempStream
)))
{
// uncomment to write xml document to file
#rewind($tempStream);
#$xmlStream = fopen(tempnam(sys_get_temp_dir(), "xmlerrors"), 'r+');
#stream_copy_to_stream($tempStream, $xmlStream);
#fclose($xmlStream);
throw
new
Syncroton_Wbxml_Exception
(
sprintf
(
'XML error: %s at line %d'
,
xml_error_string
(
xml_get_error_code
(
$parser
)),
xml_get_current_line_number
(
$parser
)
));
}
}
fclose
(
$tempStream
);
xml_parser_free
(
$parser
);
}
/**
* get's called by xml parser when tag starts
*
* @param resource $_parser
* @param string $_tag current tag prefixed with namespace
* @param array $_attributes list of tag attributes
*/
protected
function
_handleStartTag
(
$_parser
,
$_tag
,
$_attributes
)
{
$this
->
_level
++;
$this
->
_currentTagData
=
null
;
// write data for previous tag happens whith <tag1><tag2>
if
(
$this
->
_currentTag
!==
NULL
)
{
$this
->
_writeTag
(
$this
->
_currentTag
,
$this
->
_attributes
,
true
);
}
list
(
$nameSpace
,
$this
->
_currentTag
)
=
explode
(
';'
,
$_tag
);
if
(
$this
->
_codePage
->
getNameSpace
()
!=
$nameSpace
)
{
$this
->
_switchCodePage
(
$nameSpace
);
}
$this
->
_attributes
=
$_attributes
;
}
/**
* strip uri: from nameSpace
*
* @param unknown_type $_nameSpace
* @return unknown
*/
protected
function
_stripNameSpace
(
$_nameSpace
)
{
return
substr
(
$_nameSpace
,
4
);
}
/**
* get's called by xml parser when tag ends
*
* @param resource $_parser
* @param string $_tag current tag prefixed with namespace
*/
protected
function
_handleEndTag
(
$_parser
,
$_tag
)
{
#echo "$_tag Level: $this->_level == $this->_nextStackPop \n";
if
(
$this
->
_nextStackPop
!==
NULL
&&
$this
->
_nextStackPop
==
$this
->
_level
)
{
#echo "TAG: $_tag\n";
$this
->
_writeByte
(
Syncroton_Wbxml_Abstract
::
END
);
$subStream
=
$this
->
_stream
;
$subStreamLength
=
ftell
(
$subStream
);
$this
->
_dtd
=
array_pop
(
$this
->
_dtdStack
);
$this
->
_stream
=
array_pop
(
$this
->
_streamStack
);
$this
->
_nextStackPop
=
array_pop
(
$this
->
_popStack
);
$this
->
_codePage
=
$this
->
_dtd
->
getCurrentCodePage
();
rewind
(
$subStream
);
#while (!feof($subStream)) {$buffer = fgets($subStream, 4096);echo $buffer;}
$this
->
_writeByte
(
Syncroton_Wbxml_Abstract
::
OPAQUE
);
$this
->
_writeMultibyteUInt
(
$subStreamLength
);
$writenBytes
=
stream_copy_to_stream
(
$subStream
,
$this
->
_stream
);
if
(
$writenBytes
!==
$subStreamLength
)
{
//echo "$writenBytes !== $subStreamLength\n";
throw
new
Syncroton_Wbxml_Exception
(
'blow'
);
}
fclose
(
$subStream
);
#echo "$this->_nextStackPop \n"; exit;
}
else
{
if
(
$this
->
_currentTag
!==
NULL
&&
$this
->
_currentTagData
!==
NULL
)
{
$this
->
_writeTag
(
$this
->
_currentTag
,
$this
->
_attributes
,
true
,
$this
->
_currentTagData
);
$this
->
_writeByte
(
Syncroton_Wbxml_Abstract
::
END
);
}
elseif
(
$this
->
_currentTag
!==
NULL
&&
$this
->
_currentTagData
===
NULL
)
{
// for example <UTC/> tag with no data, jumps directly from _handleStartTag to _handleEndTag
$this
->
_writeTag
(
$this
->
_currentTag
,
$this
->
_attributes
);
// no end tag required, tag has no content
}
else
{
$this
->
_writeByte
(
Syncroton_Wbxml_Abstract
::
END
);
}
}
#list($urn, $tag) = explode(';', $_tag); echo "</$tag> ($this->_level)\n";
// reset $this->_currentTag, as tag got writen to stream already
$this
->
_currentTag
=
NULL
;
$this
->
_level
--;
}
/**
* collects data(value) of tag
* can be called multiple lines if the value contains linebreaks
*
* @param resource $_parser the xml parser
* @param string $_data the data(value) of the tag
*/
protected
function
_handleCharacters
(
$_parser
,
$_data
)
{
$this
->
_currentTagData
.=
$_data
;
}
/**
* writes tag with data to stream
*
* @param string $_tag
* @param array $_attributes
* @param bool $_hasContent
* @param string $_data
*/
protected
function
_writeTag
(
$_tag
,
$_attributes
=
NULL
,
$_hasContent
=
false
,
$_data
=
NULL
)
{
if
(
$_hasContent
==
false
&&
$_data
!==
NULL
)
{
throw
new
Syncroton_Wbxml_Exception
(
'$_hasContent can not be false, when $_data !== NULL'
);
}
// handle the tag
$identity
=
$this
->
_codePage
->
getIdentity
(
$_tag
);
if
(
is_array
(
$_attributes
)
&&
isset
(
$_attributes
[
'uri:Syncroton;encoding'
]))
{
$encoding
=
'opaque'
;
unset
(
$_attributes
[
'uri:Syncroton;encoding'
]);
}
else
{
$encoding
=
'termstring'
;
}
if
(!
empty
(
$_attributes
))
{
$identity
|=
0x80
;
}
if
(
$_hasContent
==
true
)
{
$identity
|=
0x40
;
}
$this
->
_writeByte
(
$identity
);
// handle the data
if
(
$_data
!==
NULL
)
{
if
(
$encoding
==
'opaque'
)
{
$this
->
_writeOpaqueString
(
base64_decode
(
$_data
));
}
else
{
$this
->
_writeTerminatedString
(
$_data
);
}
}
$this
->
_currentTagData
=
NULL
;
}
/**
* switch code page
*
* @param string $_urn
*/
protected
function
_switchCodePage
(
$_nameSpace
)
{
try
{
$codePageName
=
$this
->
_stripNameSpace
(
$_nameSpace
);
if
(!
defined
(
'Syncroton_Wbxml_Dtd_ActiveSync::CODEPAGE_'
.
strtoupper
(
$codePageName
)))
{
throw
new
Syncroton_Wbxml_Exception
(
'codepage '
.
$codePageName
.
' not found'
.
$_nameSpace
);
}
// switch to another codepage
// no need to write the wbxml header again
$codePageId
=
constant
(
'Syncroton_Wbxml_Dtd_ActiveSync::CODEPAGE_'
.
strtoupper
(
$codePageName
));
$this
->
_codePage
=
$this
->
_dtd
->
switchCodePage
(
$codePageId
);
$this
->
_writeByte
(
Syncroton_Wbxml_Abstract
::
SWITCH_PAGE
);
$this
->
_writeByte
(
$codePageId
);
}
catch
(
Syncroton_Wbxml_Dtd_Exception_CodePageNotFound
$e
)
{
// switch to another dtd
// need to write the wbxml header again
// put old dtd and stream on stack
$this
->
_dtdStack
[]
=
$this
->
_dtd
;
$this
->
_streamStack
[]
=
$this
->
_stream
;
$this
->
_popStack
[]
=
$this
->
_nextStackPop
;
$this
->
_nextStackPop
=
$this
->
_level
;
$this
->
_stream
=
fopen
(
"php://temp"
,
'r+'
);
$this
->
_initialize
(
$_urn
);
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, Apr 4, 7:41 AM (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18823056
Default Alt Text
Encoder.php (11 KB)
Attached To
Mode
rK kolab
Attached
Detach File
Event Timeline