[ Index ]
 

Code source de Horde 3.1.3

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/XML/WBXML/ -> Encoder.php (source)

   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.25.10.13 2006/05/31 17:06:37 selsky 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          if (!$this->_dtd) {
 101              // TODO: proper error handling
 102              die('Unable to find dtd for ' . $uri);
 103          }
 104          $dpiString = $this->_dtd->getDPI();
 105  
 106          // Set Version Number from Section 5.4
 107          // version = u_int8
 108          // currently 1, 2 or 3
 109          $this->writeVersionNumber($this->_wbxmlVersion);
 110  
 111          // Set Document Public Idetifier from Section 5.5
 112          // publicid = mb_u_int32 | ( zero index )
 113          // zero = u_int8
 114          // containing the value zero (0)
 115          // The actual DPI is determined after the String Table is read.
 116          $this->writeDocumentPublicIdentifier($dpiString, $this->_strings);
 117  
 118          // Set Charset from 5.6
 119          // charset = mb_u_int32
 120          $this->writeCharset($this->_charset);
 121  
 122          // Set String Table from 5.7
 123          // strb1 = length *byte
 124          $this->writeStringTable($this->_strings, $this->_charset, $this->_stringTable);
 125  
 126          $this->_currentURI = $uri;
 127  
 128          $this->_hasWrittenHeader = true;
 129      }
 130  
 131      function writeVersionNumber($version)
 132      {
 133          $this->_output .= chr($version);
 134      }
 135  
 136      function writeDocumentPublicIdentifier($dpiString, &$strings)
 137      {
 138          $i = XML_WBXML::getDPIInt($dpiString);
 139  
 140          if ($i == 0) {
 141              $strings[0] = $dpiString;
 142              $this->_output .= chr(0);
 143              $this->_output .= chr(0);
 144          } else {
 145              XML_WBXML::intToMBUInt32($this->_output, $i);
 146          }
 147      }
 148  
 149      function writeCharset($charset)
 150      {
 151          $cs = XML_WBXML::getCharsetInt($charset);
 152  
 153          if ($cs == 0) {
 154              return $this->raiseError('Unsupported Charset: ' . $charset);
 155          } else {
 156              XML_WBXML::intToMBUInt32($this->_output, $cs);
 157          }
 158      }
 159  
 160      function writeStringTable($strings, $charset, $stringTable)
 161      {
 162          $stringBytes = array();
 163          $count = 0;
 164          foreach ($strings as $str) {
 165              $bytes = $this->_getBytes($str, $charset);
 166              $stringBytes = array_merge($stringBytes, $bytes);
 167              $nullLength = $this->_addNullByte($bytes);
 168              $this->_stringTable->set($str, $count);
 169              $count += count($bytes) + $nullLength;
 170          }
 171  
 172          XML_WBXML::intToMBUInt32($this->_output, count($stringBytes));
 173          $this->_output .= implode('', $stringBytes);
 174      }
 175  
 176      function writeString($str, $cs)
 177      {
 178          $bytes = $this->_getBytes($str, $cs);
 179          $this->_output .= implode('', $bytes);
 180          $this->writeNull($cs);
 181      }
 182  
 183      function writeNull($charset)
 184      {
 185          $this->_output .= chr(0);
 186          return 1;
 187      }
 188  
 189      function _addNullByte(&$bytes)
 190      {
 191          $bytes[] = chr(0);
 192          return 1;
 193      }
 194  
 195      function _getBytes($string, $cs)
 196      {
 197          $string = String::convertCharset($string, $cs, 'utf-8');
 198          $nbytes = strlen($string);
 199  
 200          $bytes = array();
 201          for ($i = 0; $i < $nbytes; $i++) {
 202              $bytes[] = $string{$i};
 203          }
 204  
 205          return $bytes;
 206      }
 207  
 208      function _splitURI($tag)
 209      {
 210          $parts = explode(':', $tag);
 211          $name = array_pop($parts);
 212          $uri = implode(':', $parts);
 213          return array($uri, $name);
 214      }
 215  
 216      function startElement($uri, $name, $attributes)
 217      {
 218          if ($this->_subParser == null) {
 219              if (!$this->_hasWrittenHeader) {
 220                  $this->writeHeader($uri);
 221              }
 222              if ($this->_currentURI != $uri) {
 223                  $this->changecodepage($uri);
 224              }
 225              if ($this->_subParser == null) {
 226                  $this->writeTag($name, $attributes, true, $this->_charset);
 227              } else {
 228                  $this->_subParser->startElement($uri,$name, $attributes);
 229              }
 230          } else {
 231              $this->_subParserStack++;
 232              $this->_subParser->startElement($uri,$name,$attributes);
 233          }
 234      }
 235  
 236      function _startElement($parser, $tag, $attributes)
 237      {
 238          list($uri, $name) = $this->_splitURI($tag);
 239  
 240          $this->startElement($uri, $name, $attributes);
 241      }
 242  
 243      function opaque($o)
 244      {
 245          $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_OPAQUE);
 246          XML_WBXML::intToMBUInt32($this->_output, strlen($o));
 247          $this->_output .= $o;
 248      }
 249  
 250      function characters($chars)
 251      {
 252          $chars = trim($chars);
 253  
 254          if (strlen($chars)) {
 255              /* We definitely don't want any whitespace. */
 256              if ($this->_subParser == null) {
 257                  $i = $this->_stringTable->get($chars);
 258                  if ($i != null) {
 259                      $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_T);
 260                      XML_WBXML::intToMBUInt32($this->_output, $i);
 261                  } else {
 262                      $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_I);
 263                      $this->writeString($chars, $this->_charset);
 264                  }
 265              } else {
 266                  $this->_subParser->characters($chars);
 267              }
 268          }
 269      }
 270  
 271      function _characters($parser, $chars)
 272      {
 273          $this->characters($chars);
 274      }
 275  
 276      function writeTag($name, $attrs, $hasContent, $cs)
 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          if ($this->_dtd->getVersion() == 1 && !preg_match('/1\.1$/', $uri)) {
 381              $uri .= '1.1';
 382          }
 383          if ($this->_dtd->getVersion() == 0 && !preg_match('/1\.0$/', $uri)) {
 384              $uri .= '1.0';
 385          }
 386          
 387          $cp = $this->_dtd->toCodePageURI($uri);
 388          if (strlen($cp)) {
 389              $this->_dtd = &$this->_dtdManager->getInstanceURI($uri);
 390  
 391              $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_SWITCH_PAGE);
 392              $this->_output .= chr($cp);
 393              $this->_currentURI = $uri;
 394  
 395          } else {
 396              $this->_subParser = &new XML_WBXML_Encoder(true);
 397              $this->_subParserStack = 1;
 398          }
 399      }
 400  
 401      /**
 402       * Getter for property output.
 403       */
 404      function getOutput()
 405      {
 406          return $this->_output;
 407      }
 408  
 409      function getOutputSize()
 410      {
 411          return strlen($this->_output);
 412      }
 413  
 414  }


Généré le : Sun Feb 25 18:01:28 2007 par Balluche grâce à PHPXref 0.7