PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/administrator/components/com_lyftenbloggie/framework/libraries/pear/Parser.php

https://github.com/linkatic/Cultunet
PHP | 696 lines | 248 code | 58 blank | 390 comment | 35 complexity | ab1e21711ba6f27d519645ac10af2685 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * XML_Parser
  5. *
  6. * XML Parser package
  7. *
  8. * PHP versions 4 and 5
  9. *
  10. * LICENSE:
  11. *
  12. * Copyright (c) 2002-2008 The PHP Group
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions
  17. * are met:
  18. *
  19. * * Redistributions of source code must retain the above copyright
  20. * notice, this list of conditions and the following disclaimer.
  21. * * Redistributions in binary form must reproduce the above copyright
  22. * notice, this list of conditions and the following disclaimer in the
  23. * documentation and/or other materials provided with the distribution.
  24. * * The name of the author may not be used to endorse or promote products
  25. * derived from this software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  28. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  29. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  30. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  31. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  32. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  33. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  34. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  35. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  36. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  37. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. * @category XML
  40. * @package XML_Parser
  41. * @author Stig Bakken <ssb@fast.no>
  42. * @author Tomas V.V.Cox <cox@idecnet.com>
  43. * @author Stephan Schmidt <schst@php.net>
  44. * @copyright 2002-2008 The PHP Group
  45. * @license http://opensource.org/licenses/bsd-license New BSD License
  46. * @version CVS: $Id: Parser.php,v 1.30 2008/09/16 16:06:22 ashnazg Exp $
  47. * @link http://pear.php.net/package/XML_Parser
  48. */
  49. /**
  50. * uses PEAR's error handling
  51. */
  52. require_once 'PEAR.php';
  53. define('XML_PARSER_ERROR_NO_RESOURCE', 200);
  54. define('XML_PARSER_ERROR_UNSUPPORTED_MODE', 201);
  55. define('XML_PARSER_ERROR_INVALID_ENCODING', 202);
  56. define('XML_PARSER_ERROR_FILE_NOT_READABLE', 203);
  57. define('XML_PARSER_ERROR_INVALID_INPUT', 204);
  58. define('XML_PARSER_ERROR_REMOTE', 205);
  59. /**
  60. * XML Parser class.
  61. *
  62. * This is an XML parser based on PHP's "xml" extension,
  63. * based on the bundled expat library.
  64. *
  65. * @category XML
  66. * @package XML_Parser
  67. * @author Stig Bakken <ssb@fast.no>
  68. * @author Tomas V.V.Cox <cox@idecnet.com>
  69. * @author Stephan Schmidt <schst@php.net>
  70. * @copyright 2002-2008 The PHP Group
  71. * @license http://opensource.org/licenses/bsd-license New BSD License
  72. * @version Release: @package_version@
  73. * @link http://pear.php.net/package/XML_Parser
  74. */
  75. class XML_Parser extends PEAR
  76. {
  77. // {{{ properties
  78. /**
  79. * XML parser handle
  80. *
  81. * @var resource
  82. * @see xml_parser_create()
  83. */
  84. var $parser;
  85. /**
  86. * File handle if parsing from a file
  87. *
  88. * @var resource
  89. */
  90. var $fp;
  91. /**
  92. * Whether to do case folding
  93. *
  94. * If set to true, all tag and attribute names will
  95. * be converted to UPPER CASE.
  96. *
  97. * @var boolean
  98. */
  99. var $folding = true;
  100. /**
  101. * Mode of operation, one of "event" or "func"
  102. *
  103. * @var string
  104. */
  105. var $mode;
  106. /**
  107. * Mapping from expat handler function to class method.
  108. *
  109. * @var array
  110. */
  111. var $handler = array(
  112. 'character_data_handler' => 'cdataHandler',
  113. 'default_handler' => 'defaultHandler',
  114. 'processing_instruction_handler' => 'piHandler',
  115. 'unparsed_entity_decl_handler' => 'unparsedHandler',
  116. 'notation_decl_handler' => 'notationHandler',
  117. 'external_entity_ref_handler' => 'entityrefHandler'
  118. );
  119. /**
  120. * source encoding
  121. *
  122. * @var string
  123. */
  124. var $srcenc;
  125. /**
  126. * target encoding
  127. *
  128. * @var string
  129. */
  130. var $tgtenc;
  131. /**
  132. * handler object
  133. *
  134. * @var object
  135. */
  136. var $_handlerObj;
  137. /**
  138. * valid encodings
  139. *
  140. * @var array
  141. */
  142. var $_validEncodings = array('ISO-8859-1', 'UTF-8', 'US-ASCII');
  143. // }}}
  144. // {{{ php4 constructor
  145. /**
  146. * Creates an XML parser.
  147. *
  148. * This is needed for PHP4 compatibility, it will
  149. * call the constructor, when a new instance is created.
  150. *
  151. * @param string $srcenc source charset encoding, use NULL (default) to use
  152. * whatever the document specifies
  153. * @param string $mode how this parser object should work, "event" for
  154. * startelement/endelement-type events, "func"
  155. * to have it call functions named after elements
  156. * @param string $tgtenc a valid target encoding
  157. */
  158. function XML_Parser($srcenc = null, $mode = 'event', $tgtenc = null)
  159. {
  160. XML_Parser::__construct($srcenc, $mode, $tgtenc);
  161. }
  162. // }}}
  163. // {{{ php5 constructor
  164. /**
  165. * PHP5 constructor
  166. *
  167. * @param string $srcenc source charset encoding, use NULL (default) to use
  168. * whatever the document specifies
  169. * @param string $mode how this parser object should work, "event" for
  170. * startelement/endelement-type events, "func"
  171. * to have it call functions named after elements
  172. * @param string $tgtenc a valid target encoding
  173. */
  174. function __construct($srcenc = null, $mode = 'event', $tgtenc = null)
  175. {
  176. $this->PEAR('XML_Parser_Error');
  177. $this->mode = $mode;
  178. $this->srcenc = $srcenc;
  179. $this->tgtenc = $tgtenc;
  180. }
  181. // }}}
  182. /**
  183. * Sets the mode of the parser.
  184. *
  185. * Possible modes are:
  186. * - func
  187. * - event
  188. *
  189. * You can set the mode using the second parameter
  190. * in the constructor.
  191. *
  192. * This method is only needed, when switching to a new
  193. * mode at a later point.
  194. *
  195. * @param string $mode mode, either 'func' or 'event'
  196. *
  197. * @return boolean|object true on success, PEAR_Error otherwise
  198. * @access public
  199. */
  200. function setMode($mode)
  201. {
  202. if ($mode != 'func' && $mode != 'event') {
  203. $this->raiseError('Unsupported mode given',
  204. XML_PARSER_ERROR_UNSUPPORTED_MODE);
  205. }
  206. $this->mode = $mode;
  207. return true;
  208. }
  209. /**
  210. * Sets the object, that will handle the XML events
  211. *
  212. * This allows you to create a handler object independent of the
  213. * parser object that you are using and easily switch the underlying
  214. * parser.
  215. *
  216. * If no object will be set, XML_Parser assumes that you
  217. * extend this class and handle the events in $this.
  218. *
  219. * @param object &$obj object to handle the events
  220. *
  221. * @return boolean will always return true
  222. * @access public
  223. * @since v1.2.0beta3
  224. */
  225. function setHandlerObj(&$obj)
  226. {
  227. $this->_handlerObj = &$obj;
  228. return true;
  229. }
  230. /**
  231. * Init the element handlers
  232. *
  233. * @return mixed
  234. * @access private
  235. */
  236. function _initHandlers()
  237. {
  238. if (!is_resource($this->parser)) {
  239. return false;
  240. }
  241. if (!is_object($this->_handlerObj)) {
  242. $this->_handlerObj = &$this;
  243. }
  244. switch ($this->mode) {
  245. case 'func':
  246. xml_set_object($this->parser, $this->_handlerObj);
  247. xml_set_element_handler($this->parser,
  248. array(&$this, 'funcStartHandler'), array(&$this, 'funcEndHandler'));
  249. break;
  250. case 'event':
  251. xml_set_object($this->parser, $this->_handlerObj);
  252. xml_set_element_handler($this->parser, 'startHandler', 'endHandler');
  253. break;
  254. default:
  255. return $this->raiseError('Unsupported mode given',
  256. XML_PARSER_ERROR_UNSUPPORTED_MODE);
  257. break;
  258. }
  259. /**
  260. * set additional handlers for character data, entities, etc.
  261. */
  262. foreach ($this->handler as $xml_func => $method) {
  263. if (method_exists($this->_handlerObj, $method)) {
  264. $xml_func = 'xml_set_' . $xml_func;
  265. $xml_func($this->parser, $method);
  266. }
  267. }
  268. }
  269. // {{{ _create()
  270. /**
  271. * create the XML parser resource
  272. *
  273. * Has been moved from the constructor to avoid
  274. * problems with object references.
  275. *
  276. * Furthermore it allows us returning an error
  277. * if something fails.
  278. *
  279. * NOTE: uses '@' error suppresion in this method
  280. *
  281. * @return bool|PEAR_Error true on success, PEAR_Error otherwise
  282. * @access private
  283. * @see xml_parser_create
  284. */
  285. function _create()
  286. {
  287. if ($this->srcenc === null) {
  288. $xp = @xml_parser_create();
  289. } else {
  290. $xp = @xml_parser_create($this->srcenc);
  291. }
  292. if (is_resource($xp)) {
  293. if ($this->tgtenc !== null) {
  294. if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING,
  295. $this->tgtenc)
  296. ) {
  297. return $this->raiseError('invalid target encoding',
  298. XML_PARSER_ERROR_INVALID_ENCODING);
  299. }
  300. }
  301. $this->parser = $xp;
  302. $result = $this->_initHandlers($this->mode);
  303. if ($this->isError($result)) {
  304. return $result;
  305. }
  306. xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding);
  307. return true;
  308. }
  309. if (!in_array(strtoupper($this->srcenc), $this->_validEncodings)) {
  310. return $this->raiseError('invalid source encoding',
  311. XML_PARSER_ERROR_INVALID_ENCODING);
  312. }
  313. return $this->raiseError('Unable to create XML parser resource.',
  314. XML_PARSER_ERROR_NO_RESOURCE);
  315. }
  316. // }}}
  317. // {{{ reset()
  318. /**
  319. * Reset the parser.
  320. *
  321. * This allows you to use one parser instance
  322. * to parse multiple XML documents.
  323. *
  324. * @access public
  325. * @return boolean|object true on success, PEAR_Error otherwise
  326. */
  327. function reset()
  328. {
  329. $result = $this->_create();
  330. if ($this->isError($result)) {
  331. return $result;
  332. }
  333. return true;
  334. }
  335. // }}}
  336. // {{{ setInputString()
  337. /**
  338. * XML_Parser::setInputString()
  339. *
  340. * Sets the xml input from a string
  341. *
  342. * @param string $data a string containing the XML document
  343. *
  344. * @return null
  345. */
  346. function setInputString($data)
  347. {
  348. $this->fp = $data;
  349. return null;
  350. }
  351. // }}}
  352. // {{{ setInput()
  353. /**
  354. * Sets the file handle to use with parse().
  355. *
  356. * You should use setInputFile() or setInputString() if you
  357. * pass a string
  358. *
  359. * @param mixed $fp Can be either a resource returned from fopen(),
  360. * a URL, a local filename or a string.
  361. *
  362. * @return mixed
  363. * @access public
  364. * @see parse()
  365. * @uses setInputString(), setInputFile()
  366. */
  367. function setInput($fp)
  368. {
  369. if (is_resource($fp)) {
  370. $this->fp = $fp;
  371. return true;
  372. } elseif (eregi('^[a-z]+://', substr($fp, 0, 10))) {
  373. // see if it's an absolute URL (has a scheme at the beginning)
  374. return $this->setInputFile($fp);
  375. } elseif (file_exists($fp)) {
  376. // see if it's a local file
  377. return $this->setInputFile($fp);
  378. } else {
  379. // it must be a string
  380. $this->fp = $fp;
  381. return true;
  382. }
  383. return $this->raiseError('Illegal input format',
  384. XML_PARSER_ERROR_INVALID_INPUT);
  385. }
  386. // }}}
  387. // {{{ parse()
  388. /**
  389. * Central parsing function.
  390. *
  391. * @return bool|PEAR_Error returns true on success, or a PEAR_Error otherwise
  392. * @access public
  393. */
  394. function parse()
  395. {
  396. /**
  397. * reset the parser
  398. */
  399. $result = $this->reset();
  400. if ($this->isError($result)) {
  401. return $result;
  402. }
  403. // if $this->fp was fopened previously
  404. if (is_resource($this->fp)) {
  405. while ($data = fread($this->fp, 4096)) {
  406. if (!$this->_parseString($data, feof($this->fp))) {
  407. $error = &$this->raiseError();
  408. $this->free();
  409. return $error;
  410. }
  411. }
  412. } else {
  413. // otherwise, $this->fp must be a string
  414. if (!$this->_parseString($this->fp, true)) {
  415. $error = &$this->raiseError();
  416. $this->free();
  417. return $error;
  418. }
  419. }
  420. $this->free();
  421. return true;
  422. }
  423. /**
  424. * XML_Parser::_parseString()
  425. *
  426. * @param string $data data
  427. * @param bool $eof end-of-file flag
  428. *
  429. * @return bool
  430. * @access private
  431. * @see parseString()
  432. **/
  433. function _parseString($data, $eof = false)
  434. {
  435. return xml_parse($this->parser, $data, $eof);
  436. }
  437. // }}}
  438. // {{{ parseString()
  439. /**
  440. * XML_Parser::parseString()
  441. *
  442. * Parses a string.
  443. *
  444. * @param string $data XML data
  445. * @param boolean $eof If set and TRUE, data is the last piece
  446. * of data sent in this parser
  447. *
  448. * @return bool|PEAR_Error true on success or a PEAR Error
  449. * @throws XML_Parser_Error
  450. * @see _parseString()
  451. */
  452. function parseString($data, $eof = false)
  453. {
  454. if (!isset($this->parser) || !is_resource($this->parser)) {
  455. $this->reset();
  456. }
  457. if (!$this->_parseString($data, $eof)) {
  458. $error = &$this->raiseError();
  459. $this->free();
  460. return $error;
  461. }
  462. if ($eof === true) {
  463. $this->free();
  464. }
  465. return true;
  466. }
  467. /**
  468. * XML_Parser::free()
  469. *
  470. * Free the internal resources associated with the parser
  471. *
  472. * @return null
  473. **/
  474. function free()
  475. {
  476. if (isset($this->parser) && is_resource($this->parser)) {
  477. xml_parser_free($this->parser);
  478. unset( $this->parser );
  479. }
  480. if (isset($this->fp) && is_resource($this->fp)) {
  481. fclose($this->fp);
  482. }
  483. unset($this->fp);
  484. return null;
  485. }
  486. /**
  487. * XML_Parser::raiseError()
  488. *
  489. * Throws a XML_Parser_Error
  490. *
  491. * @param string $msg the error message
  492. * @param integer $ecode the error message code
  493. *
  494. * @return XML_Parser_Error reference to the error object
  495. **/
  496. function &raiseError($msg = null, $ecode = 0)
  497. {
  498. $msg = !is_null($msg) ? $msg : $this->parser;
  499. $err = new XML_Parser_Error($msg, $ecode);
  500. return parent::raiseError($err);
  501. }
  502. // }}}
  503. // {{{ funcStartHandler()
  504. /**
  505. * derives and calls the Start Handler function
  506. *
  507. * @param mixed $xp ??
  508. * @param mixed $elem ??
  509. * @param mixed $attribs ??
  510. *
  511. * @return void
  512. */
  513. function funcStartHandler($xp, $elem, $attribs)
  514. {
  515. $func = 'xmltag_' . $elem;
  516. $func = str_replace(array('.', '-', ':'), '_', $func);
  517. if (method_exists($this->_handlerObj, $func)) {
  518. call_user_func(array(&$this->_handlerObj, $func), $xp, $elem, $attribs);
  519. } elseif (method_exists($this->_handlerObj, 'xmltag')) {
  520. call_user_func(array(&$this->_handlerObj, 'xmltag'),
  521. $xp, $elem, $attribs);
  522. }
  523. }
  524. // }}}
  525. // {{{ funcEndHandler()
  526. /**
  527. * derives and calls the End Handler function
  528. *
  529. * @param mixed $xp ??
  530. * @param mixed $elem ??
  531. *
  532. * @return void
  533. */
  534. function funcEndHandler($xp, $elem)
  535. {
  536. $func = 'xmltag_' . $elem . '_';
  537. $func = str_replace(array('.', '-', ':'), '_', $func);
  538. if (method_exists($this->_handlerObj, $func)) {
  539. call_user_func(array(&$this->_handlerObj, $func), $xp, $elem);
  540. } elseif (method_exists($this->_handlerObj, 'xmltag_')) {
  541. call_user_func(array(&$this->_handlerObj, 'xmltag_'), $xp, $elem);
  542. }
  543. }
  544. // }}}
  545. // {{{ startHandler()
  546. /**
  547. * abstract method signature for Start Handler
  548. *
  549. * @param mixed $xp ??
  550. * @param mixed $elem ??
  551. * @param mixed &$attribs ??
  552. *
  553. * @return null
  554. * @abstract
  555. */
  556. function startHandler($xp, $elem, &$attribs)
  557. {
  558. return null;
  559. }
  560. // }}}
  561. // {{{ endHandler()
  562. /**
  563. * abstract method signature for End Handler
  564. *
  565. * @param mixed $xp ??
  566. * @param mixed $elem ??
  567. *
  568. * @return null
  569. * @abstract
  570. */
  571. function endHandler($xp, $elem)
  572. {
  573. return null;
  574. }
  575. // }}}me
  576. }
  577. /**
  578. * error class, replaces PEAR_Error
  579. *
  580. * An instance of this class will be returned
  581. * if an error occurs inside XML_Parser.
  582. *
  583. * There are three advantages over using the standard PEAR_Error:
  584. * - All messages will be prefixed
  585. * - check for XML_Parser error, using is_a( $error, 'XML_Parser_Error' )
  586. * - messages can be generated from the xml_parser resource
  587. *
  588. * @category XML
  589. * @package XML_Parser
  590. * @author Stig Bakken <ssb@fast.no>
  591. * @author Tomas V.V.Cox <cox@idecnet.com>
  592. * @author Stephan Schmidt <schst@php.net>
  593. * @copyright 2002-2008 The PHP Group
  594. * @license http://opensource.org/licenses/bsd-license New BSD License
  595. * @version Release: @package_version@
  596. * @link http://pear.php.net/package/XML_Parser
  597. * @see PEAR_Error
  598. */
  599. class XML_Parser_Error extends PEAR_Error
  600. {
  601. // {{{ properties
  602. /**
  603. * prefix for all messages
  604. *
  605. * @var string
  606. */
  607. var $error_message_prefix = '';
  608. // }}}
  609. // {{{ constructor()
  610. /**
  611. * construct a new error instance
  612. *
  613. * You may either pass a message or an xml_parser resource as first
  614. * parameter. If a resource has been passed, the last error that
  615. * happened will be retrieved and returned.
  616. *
  617. * @param string|resource $msgorparser message or parser resource
  618. * @param integer $code error code
  619. * @param integer $mode error handling
  620. * @param integer $level error level
  621. *
  622. * @access public
  623. * @todo PEAR CS - can't meet 85char line limit without arg refactoring
  624. */
  625. function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE)
  626. {
  627. if (is_resource($msgorparser)) {
  628. $code = xml_get_error_code($msgorparser);
  629. $msgorparser = sprintf('%s at XML input line %d:%d',
  630. xml_error_string($code),
  631. xml_get_current_line_number($msgorparser),
  632. xml_get_current_column_number($msgorparser));
  633. }
  634. $this->PEAR_Error($msgorparser, $code, $mode, $level);
  635. }
  636. // }}}
  637. }
  638. ?>