[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 <?php 2 3 include_once 'XML/WBXML.php'; 4 include_once 'XML/WBXML/ContentHandler.php'; 5 include_once 'XML/WBXML/DTDManager.php'; 6 include_once 'Horde/String.php'; 7 8 /** 9 * $Horde: framework/XML_WBXML/WBXML/Encoder.php,v 1.39 2006/01/01 21:10:25 jan Exp $ 10 * 11 * Copyright 2003-2006 Anthony Mills <amills@pyramid6.com> 12 * 13 * See the enclosed file COPYING for license information (LGPL). If you 14 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 15 * 16 * From Binary XML Content Format Specification Version 1.3, 25 July 17 * 2001 found at http://www.wapforum.org 18 * 19 * @package XML_WBXML 20 */ 21 class XML_WBXML_Encoder extends XML_WBXML_ContentHandler { 22 23 var $_strings = array(); 24 25 var $_stringTable; 26 27 var $_hasWrittenHeader = false; 28 29 var $_dtd; 30 31 var $_output = ''; 32 33 var $_uris = array(); 34 35 var $_uriNums = array(); 36 37 var $_currentURI; 38 39 var $_subParser = null; 40 var $_subParserStack = 0; 41 42 /** 43 * The XML parser. 44 * 45 * @var resource 46 */ 47 var $_parser; 48 49 /** 50 * The DTD Manager. 51 * 52 * @var XML_WBXML_DTDManager 53 */ 54 var $_dtdManager; 55 56 /** 57 * Constructor. 58 */ 59 function XML_WBXML_Encoder() 60 { 61 $this->_dtdManager = &new XML_WBXML_DTDManager(); 62 $this->_stringTable = &new XML_WBXML_HashTable(); 63 } 64 65 /** 66 * Take the input $xml and turn it into WBXML. This is _not_ the 67 * intended way of using this class. It is derived from 68 * Contenthandler and one should use it as a ContentHandler and 69 * produce the XML-structure with startElement(), endElement(), 70 * and characters(). 71 */ 72 function encode($xml) 73 { 74 // Create the XML parser and set method references. 75 $this->_parser = xml_parser_create_ns($this->_charset); 76 xml_set_object($this->_parser, $this); 77 xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); 78 xml_set_element_handler($this->_parser, '_startElement', '_endElement'); 79 xml_set_character_data_handler($this->_parser, '_characters'); 80 xml_set_processing_instruction_handler($this->_parser, ''); 81 xml_set_external_entity_ref_handler($this->_parser, ''); 82 83 if (!xml_parse($this->_parser, $xml)) { 84 return $this->raiseError(sprintf('XML error: %s at line %d', 85 xml_error_string(xml_get_error_code($this->_parser)), 86 xml_get_current_line_number($this->_parser))); 87 } 88 89 xml_parser_free($this->_parser); 90 91 return $this->_output; 92 } 93 94 /** 95 * This will write the correct headers. 96 */ 97 function writeHeader($uri) 98 { 99 $this->_dtd = &$this->_dtdManager->getInstanceURI($uri); 100 101 $dpiString = $this->_dtd->getDPI(); 102 103 // Set Version Number from Section 5.4 104 // version = u_int8 105 // currently 1, 2 or 3 106 $this->writeVersionNumber($this->_wbxmlVersion); 107 108 // Set Document Public Idetifier from Section 5.5 109 // publicid = mb_u_int32 | ( zero index ) 110 // zero = u_int8 111 // containing the value zero (0) 112 // The actual DPI is determined after the String Table is read. 113 $this->writeDocumentPublicIdentifier($dpiString, $this->_strings); 114 115 // Set Charset from 5.6 116 // charset = mb_u_int32 117 $this->writeCharset($this->_charset); 118 119 // Set String Table from 5.7 120 // strb1 = length *byte 121 $this->writeStringTable($this->_strings, $this->_charset, $this->_stringTable); 122 123 $this->_currentURI = $uri; 124 125 $this->_hasWrittenHeader = true; 126 } 127 128 function writeVersionNumber($version) 129 { 130 $this->_output .= chr($version); 131 } 132 133 function writeDocumentPublicIdentifier($dpiString, &$strings) 134 { 135 $i = XML_WBXML::getDPIInt($dpiString); 136 137 if ($i == 0) { 138 $strings[0] = $dpiString; 139 $this->_output .= chr(0); 140 $this->_output .= chr(0); 141 } else { 142 XML_WBXML::intToMBUInt32($this->_output, $i); 143 } 144 } 145 146 function writeCharset($charset) 147 { 148 $cs = XML_WBXML::getCharsetInt($charset); 149 150 if ($cs == 0) { 151 return $this->raiseError('Unsupported Charset: ' . $charset); 152 } else { 153 XML_WBXML::intToMBUInt32($this->_output, $cs); 154 } 155 } 156 157 function writeStringTable($strings, $charset, $stringTable) 158 { 159 $stringBytes = array(); 160 $count = 0; 161 foreach ($strings as $str) { 162 $bytes = $this->_getBytes($str, $charset); 163 $stringBytes = array_merge($stringBytes, $bytes); 164 $nullLength = $this->_addNullByte($bytes); 165 $this->_stringTable->set($str, $count); 166 $count += count($bytes) + $nullLength; 167 } 168 169 XML_WBXML::intToMBUInt32($this->_output, count($stringBytes)); 170 $this->_output .= implode('', $stringBytes); 171 } 172 173 function writeString($str, $cs) 174 { 175 $bytes = $this->_getBytes($str, $cs); 176 $this->_output .= implode('', $bytes); 177 $this->writeNull($cs); 178 } 179 180 function writeNull($charset) 181 { 182 $this->_output .= chr(0); 183 return 1; 184 } 185 186 function _addNullByte(&$bytes) 187 { 188 $bytes[] = chr(0); 189 return 1; 190 } 191 192 function _getBytes($string, $cs) 193 { 194 $string = String::convertCharset($string, $cs, 'utf-8'); 195 $nbytes = strlen($string); 196 197 $bytes = array(); 198 for ($i = 0; $i < $nbytes; $i++) { 199 $bytes[] = $string{$i}; 200 } 201 202 return $bytes; 203 } 204 205 function _splitURI($tag) 206 { 207 $parts = explode(':', $tag); 208 $name = array_pop($parts); 209 $uri = implode(':', $parts); 210 return array($uri, $name); 211 } 212 213 function startElement($uri, $name, $attributes) 214 { 215 if ($this->_subParser == null) { 216 if (!$this->_hasWrittenHeader) { 217 $this->writeHeader($uri); 218 } 219 if ($this->_currentURI != $uri) { 220 $this->changecodepage($uri); 221 } 222 if ($this->_subParser == null) { 223 $this->writeTag($name, $attributes, true, $this->_charset); 224 } else { 225 $this->_subParser->startElement($uri,$name, $attributes); 226 } 227 } else { 228 $this->_subParserStack++; 229 $this->_subParser->startElement($uri,$name,$attributes); 230 } 231 } 232 233 function _startElement($parser, $tag, $attributes) 234 { 235 list($uri, $name) = $this->_splitURI($tag); 236 237 $this->startElement($uri, $name, $attributes); 238 } 239 240 function opaque($bytes) 241 { 242 if ($this->_subParser == null) { 243 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_OPAQUE); 244 XML_WBXML::intToMBUInt32($this->_output, count($bytes)); 245 $this->_output .= $bytes; 246 } 247 } 248 249 function characters($chars) 250 { 251 $chars = trim($chars); 252 253 if (strlen($chars)) { 254 /* We definitely don't want any whitespace. */ 255 if ($this->_subParser == null) { 256 $i = $this->_stringTable->get($chars); 257 if ($i != null) { 258 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_T); 259 XML_WBXML::intToMBUInt32($this->_output, $i); 260 } else { 261 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_I); 262 $this->writeString($chars, $this->_charset); 263 } 264 } else { 265 $this->_subParser->characters($chars); 266 } 267 } 268 } 269 270 function _characters($parser, $chars) 271 { 272 $this->characters($chars); 273 } 274 275 function writeTag($name, $attrs, $hasContent, $cs) 276 { 277 278 if ($attrs != null && !count($attrs)) { 279 $attrs = null; 280 } 281 282 $t = $this->_dtd->toTagInt($name); 283 if ($t == -1) { 284 $i = $this->_stringTable->get($name); 285 if ($i == null) { 286 return $this->raiseError($name . ' is not found in String Table or DTD'); 287 } else { 288 if ($attrs == null && !$hasContent) { 289 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL); 290 } elseif ($attrs == null && $hasContent) { 291 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL_A); 292 } elseif ($attrs != null && $hasContent) { 293 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL_C); 294 } elseif ($attrs != null && !$hasContent) { 295 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL_AC); 296 } 297 298 XML_WBXML::intToMBUInt32($this->_output, $i); 299 } 300 } else { 301 if ($attrs == null && !$hasContent) { 302 $this->_output .= chr($t); 303 } elseif ($attrs == null && $hasContent) { 304 $this->_output .= chr($t | 64); 305 } elseif ($attrs != null && $hasContent) { 306 $this->_output .= chr($t | 128); 307 } elseif ($attrs != null && !$hasContent) { 308 $this->_output .= chr($t | 192); 309 } 310 } 311 312 if ($attrs != null && is_array($attrs) && count($attrs) > 0 ) { 313 $this->writeAttributes($attrs, $cs); 314 } 315 } 316 317 function writeAttributes($attrs, $cs) 318 { 319 foreach ($attrs as $name => $value) { 320 $this->writeAttribute($name, $value, $cs); 321 } 322 323 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_END); 324 } 325 326 function writeAttribute($name, $value, $cs) 327 { 328 $a = $this->_dtd->toAttribute($name); 329 if ($a == -1) { 330 $i = $this->_stringTable->get($name); 331 if ($i == null) { 332 return $this->raiseError($name . ' is not found in String Table or DTD'); 333 } else { 334 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL); 335 XML_WBXML::intToMBUInt32($this->_output, $i); 336 } 337 } else { 338 $this->_output .= $a; 339 } 340 341 $i = $this->_stringTable->get($name); 342 if ($i != null) { 343 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_T); 344 XML_WBXML::intToMBUInt32($this->_output, $i); 345 } else { 346 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_I); 347 $this->writeString($value, $cs); 348 } 349 } 350 351 function endElement($uri, $name) 352 { 353 if ($this->_subParser == null) { 354 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_END); 355 } else { 356 $this->_subParser->endElement($uri, $name); 357 $this->_subParserStack--; 358 359 if ($this->_subParserStack == 0) { 360 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_OPAQUE); 361 362 XML_WBXML::intToMBUInt32($this->_output, 363 strlen($this->_subParser->getOutput())); 364 $this->_output .= $this->_subParser->getOutput(); 365 366 $this->_subParser = null; 367 } 368 } 369 } 370 371 function _endElement($parser, $tag) 372 { 373 list($uri, $name) = $this->_splitURI($tag); 374 $this->endElement($uri, $name); 375 } 376 377 function changecodepage($uri) 378 { 379 // @todo: this is a hack! 380 // what's the reason for this hack???? Lars 381 if ($uri != 'syncml:devinf' && $uri != 'syncml:metinf' && $uri != 'syncml:syncml1.0' && !preg_match('/1\.1$/', $uri)) { 382 $uri .= '1.1'; 383 } 384 $cp = $this->_dtd->toCodePageURI($uri); 385 if (strlen($cp)) { 386 $this->_dtd = &$this->_dtdManager->getInstanceURI($uri); 387 388 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_SWITCH_PAGE); 389 $this->_output .= chr($cp); 390 $this->_currentURI = $uri; 391 392 } else { 393 $this->_subParser = &new XML_WBXML_Encoder(true); 394 $this->_subParserStack = 1; 395 } 396 } 397 398 /** 399 * Getter for property output. 400 */ 401 function getOutput() 402 { 403 return $this->_output; 404 } 405 406 function getOutputSize() 407 { 408 return strlen($this->_output); 409 } 410 411 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |