PageRenderTime 40ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/core/jaxl_xml_stream.php

https://github.com/onurdegerli/JAXL
PHP | 191 lines | 147 code | 2 blank | 42 comment | 0 complexity | b87efe30ebbe1d2378e39a4f0868c545 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Jaxl (Jabber XMPP Library)
  4. *
  5. * Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.com>.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * * Neither the name of Abhinav Singh nor the names of his
  21. * contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  27. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  28. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  29. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  30. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  31. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  32. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  34. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. */
  38. /**
  39. *
  40. * Enter description here ...
  41. * @author abhinavsingh
  42. *
  43. */
  44. class JAXLXmlStream {
  45. private $delimiter = '\\';
  46. private $ns;
  47. private $parser;
  48. private $stanza;
  49. private $depth = -1;
  50. private $start_cb;
  51. private $stanza_cb;
  52. private $end_cb;
  53. public function __construct() {
  54. $this->init_parser();
  55. }
  56. private function init_parser() {
  57. $this->depth = -1;
  58. $this->parser = xml_parser_create_ns("UTF-8", $this->delimiter);
  59. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
  60. xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
  61. xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
  62. xml_set_character_data_handler($this->parser, array(&$this, "handle_character"));
  63. xml_set_element_handler($this->parser, array(&$this, "handle_start_tag"), array(&$this, "handle_end_tag"));
  64. }
  65. public function __destruct() {
  66. //_debug("cleaning up xml parser...");
  67. @xml_parser_free($this->parser);
  68. }
  69. public function reset_parser() {
  70. $this->parse_final(null);
  71. @xml_parser_free($this->parser);
  72. $this->parser = null;
  73. $this->init_parser();
  74. }
  75. public function set_callback($start_cb, $end_cb, $stanza_cb) {
  76. $this->start_cb = $start_cb;
  77. $this->end_cb = $end_cb;
  78. $this->stanza_cb = $stanza_cb;
  79. }
  80. public function parse($str) {
  81. xml_parse($this->parser, $str, false);
  82. }
  83. public function parse_final($str) {
  84. xml_parse($this->parser, $str, true);
  85. }
  86. protected function handle_start_tag($parser, $name, $attrs) {
  87. $name = $this->explode($name);
  88. //echo "start of tag ".$name[1]." with ns ".$name[0].PHP_EOL;
  89. // replace ns with prefix
  90. foreach($attrs as $key=>$v) {
  91. $k = $this->explode($key);
  92. // no ns specified
  93. if($k[0] == null) {
  94. $attrs[$k[1]] = $v;
  95. }
  96. // xml ns
  97. else if($k[0] == NS_XML) {
  98. unset($attrs[$key]);
  99. $attrs['xml:'.$k[1]] = $v;
  100. }
  101. else {
  102. _error("==================> unhandled ns prefix on attribute");
  103. // remove attribute else will cause error with bad stanza format
  104. // report to developer if above error message is ever encountered
  105. unset($attrs[$key]);
  106. }
  107. }
  108. if($this->depth <= 0) {
  109. $this->depth = 0;
  110. $this->ns = $name[1];
  111. if($this->start_cb) {
  112. $stanza = new JAXLXml($name[1], $name[0], $attrs);
  113. call_user_func($this->start_cb, $stanza);
  114. }
  115. }
  116. else {
  117. if(!$this->stanza) {
  118. $stanza = new JAXLXml($name[1], $name[0], $attrs);
  119. $this->stanza = &$stanza;
  120. }
  121. else {
  122. $this->stanza->c($name[1], $name[0], $attrs);
  123. }
  124. }
  125. ++$this->depth;
  126. }
  127. protected function handle_end_tag($parser, $name) {
  128. $name = explode($this->delimiter, $name);
  129. $name = sizeof($name) == 1 ? array('', $name[0]) : $name;
  130. //echo "depth ".$this->depth.", $name[1] tag ended".PHP_EOL.PHP_EOL;
  131. if($this->depth == 1) {
  132. if($this->end_cb) {
  133. $stanza = new JAXLXml($name[1], $this->ns);
  134. call_user_func($this->end_cb, $stanza);
  135. }
  136. }
  137. else if($this->depth > 1) {
  138. if($this->stanza) $this->stanza->up();
  139. if($this->depth == 2) {
  140. if($this->stanza_cb) {
  141. call_user_func($this->stanza_cb, $this->stanza);
  142. $this->stanza = null;
  143. }
  144. }
  145. }
  146. --$this->depth;
  147. }
  148. protected function handle_character($parser, $data) {
  149. //echo "depth ".$this->depth.", character ".$data." for stanza ".$this->stanza->name.PHP_EOL;
  150. if($this->stanza) {
  151. $this->stanza->t(htmlentities($data, ENT_COMPAT, "UTF-8"), TRUE);
  152. }
  153. }
  154. private function implode($data) {
  155. return implode($this->delimiter, $data);
  156. }
  157. private function explode($data) {
  158. $data = explode($this->delimiter, $data);
  159. $data = sizeof($data) == 1 ? array(null, $data[0]) : $data;
  160. return $data;
  161. }
  162. }
  163. ?>