|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 00004 00055 require_once 'PEAR.php'; 00056 00060 define('XML_PARSER_ERROR_NO_RESOURCE', 200); 00061 00065 define('XML_PARSER_ERROR_UNSUPPORTED_MODE', 201); 00066 00070 define('XML_PARSER_ERROR_INVALID_ENCODING', 202); 00071 00075 define('XML_PARSER_ERROR_FILE_NOT_READABLE', 203); 00076 00080 define('XML_PARSER_ERROR_INVALID_INPUT', 204); 00081 00085 define('XML_PARSER_ERROR_REMOTE', 205); 00086 00116 class XML_Parser extends PEAR 00117 { 00118 // {{{ properties 00119 00126 var $parser; 00127 00133 var $fp; 00134 00143 var $folding = true; 00144 00150 var $mode; 00151 00157 var $handler = array( 00158 'character_data_handler' => 'cdataHandler', 00159 'default_handler' => 'defaultHandler', 00160 'processing_instruction_handler' => 'piHandler', 00161 'unparsed_entity_decl_handler' => 'unparsedHandler', 00162 'notation_decl_handler' => 'notationHandler', 00163 'external_entity_ref_handler' => 'entityrefHandler' 00164 ); 00165 00171 var $srcenc; 00172 00178 var $tgtenc; 00179 00185 var $_handlerObj; 00186 00192 var $_validEncodings = array('ISO-8859-1', 'UTF-8', 'US-ASCII'); 00193 00194 // }}} 00195 // {{{ php4 constructor 00196 00210 function XML_Parser($srcenc = null, $mode = 'event', $tgtenc = null) 00211 { 00212 XML_Parser::__construct($srcenc, $mode, $tgtenc); 00213 } 00214 // }}} 00215 // {{{ php5 constructor 00216 00227 function __construct($srcenc = null, $mode = 'event', $tgtenc = null) 00228 { 00229 $this->PEAR('XML_Parser_Error'); 00230 00231 $this->mode = $mode; 00232 $this->srcenc = $srcenc; 00233 $this->tgtenc = $tgtenc; 00234 } 00235 // }}} 00236 00255 function setMode($mode) 00256 { 00257 if ($mode != 'func' && $mode != 'event') { 00258 $this->raiseError('Unsupported mode given', 00259 XML_PARSER_ERROR_UNSUPPORTED_MODE); 00260 } 00261 00262 $this->mode = $mode; 00263 return true; 00264 } 00265 00282 function setHandlerObj(&$obj) 00283 { 00284 $this->_handlerObj = &$obj; 00285 return true; 00286 } 00287 00294 function _initHandlers() 00295 { 00296 if (!is_resource($this->parser)) { 00297 return false; 00298 } 00299 00300 if (!is_object($this->_handlerObj)) { 00301 $this->_handlerObj = &$this; 00302 } 00303 switch ($this->mode) { 00304 00305 case 'func': 00306 xml_set_object($this->parser, $this->_handlerObj); 00307 xml_set_element_handler($this->parser, 00308 array(&$this, 'funcStartHandler'), array(&$this, 'funcEndHandler')); 00309 break; 00310 00311 case 'event': 00312 xml_set_object($this->parser, $this->_handlerObj); 00313 xml_set_element_handler($this->parser, 'startHandler', 'endHandler'); 00314 break; 00315 default: 00316 return $this->raiseError('Unsupported mode given', 00317 XML_PARSER_ERROR_UNSUPPORTED_MODE); 00318 break; 00319 } 00320 00324 foreach ($this->handler as $xml_func => $method) { 00325 if (method_exists($this->_handlerObj, $method)) { 00326 $xml_func = 'xml_set_' . $xml_func; 00327 $xml_func($this->parser, $method); 00328 } 00329 } 00330 } 00331 00332 // {{{ _create() 00333 00349 function _create() 00350 { 00351 if ($this->srcenc === null) { 00352 $xp = @xml_parser_create(); 00353 } else { 00354 $xp = @xml_parser_create($this->srcenc); 00355 } 00356 if (is_resource($xp)) { 00357 if ($this->tgtenc !== null) { 00358 if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING, 00359 $this->tgtenc) 00360 ) { 00361 return $this->raiseError('invalid target encoding', 00362 XML_PARSER_ERROR_INVALID_ENCODING); 00363 } 00364 } 00365 $this->parser = $xp; 00366 $result = $this->_initHandlers($this->mode); 00367 if ($this->isError($result)) { 00368 return $result; 00369 } 00370 xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding); 00371 return true; 00372 } 00373 if (!in_array(strtoupper($this->srcenc), $this->_validEncodings)) { 00374 return $this->raiseError('invalid source encoding', 00375 XML_PARSER_ERROR_INVALID_ENCODING); 00376 } 00377 return $this->raiseError('Unable to create XML parser resource.', 00378 XML_PARSER_ERROR_NO_RESOURCE); 00379 } 00380 00381 // }}} 00382 // {{{ reset() 00383 00393 function reset() 00394 { 00395 $result = $this->_create(); 00396 if ($this->isError($result)) { 00397 return $result; 00398 } 00399 return true; 00400 } 00401 00402 // }}} 00403 // {{{ setInputFile() 00404 00415 function setInputFile($file) 00416 { 00420 if (preg_match('#^(http|ftp)://#i', substr($file, 0, 10))) { 00421 if (!ini_get('allow_url_fopen')) { 00422 return $this-> 00423 raiseError('Remote files cannot be parsed, as safe mode is enabled.', 00424 XML_PARSER_ERROR_REMOTE); 00425 } 00426 } 00427 00428 $fp = @fopen($file, 'rb'); 00429 if (is_resource($fp)) { 00430 $this->fp = $fp; 00431 return $fp; 00432 } 00433 return $this->raiseError('File could not be opened.', 00434 XML_PARSER_ERROR_FILE_NOT_READABLE); 00435 } 00436 00437 // }}} 00438 // {{{ setInputString() 00439 00449 function setInputString($data) 00450 { 00451 $this->fp = $data; 00452 return null; 00453 } 00454 00455 // }}} 00456 // {{{ setInput() 00457 00472 function setInput($fp) 00473 { 00474 if (is_resource($fp)) { 00475 $this->fp = $fp; 00476 return true; 00477 } elseif (preg_match('#^[a-z]+://#i', substr($fp, 0, 10))) { 00478 // see if it's an absolute URL (has a scheme at the beginning) 00479 return $this->setInputFile($fp); 00480 } elseif (file_exists($fp)) { 00481 // see if it's a local file 00482 return $this->setInputFile($fp); 00483 } else { 00484 // it must be a string 00485 $this->fp = $fp; 00486 return true; 00487 } 00488 00489 return $this->raiseError('Illegal input format', 00490 XML_PARSER_ERROR_INVALID_INPUT); 00491 } 00492 00493 // }}} 00494 // {{{ parse() 00495 00502 function parse() 00503 { 00507 $result = $this->reset(); 00508 if ($this->isError($result)) { 00509 return $result; 00510 } 00511 // if $this->fp was fopened previously 00512 if (is_resource($this->fp)) { 00513 00514 while ($data = fread($this->fp, 4096)) { 00515 if (!$this->_parseString($data, feof($this->fp))) { 00516 $error = &$this->raiseError(); 00517 $this->free(); 00518 return $error; 00519 } 00520 } 00521 } else { 00522 // otherwise, $this->fp must be a string 00523 if (!$this->_parseString($this->fp, true)) { 00524 $error = &$this->raiseError(); 00525 $this->free(); 00526 return $error; 00527 } 00528 } 00529 $this->free(); 00530 00531 return true; 00532 } 00533 00544 function _parseString($data, $eof = false) 00545 { 00546 return xml_parse($this->parser, $data, $eof); 00547 } 00548 00549 // }}} 00550 // {{{ parseString() 00551 00565 function parseString($data, $eof = false) 00566 { 00567 if (!isset($this->parser) || !is_resource($this->parser)) { 00568 $this->reset(); 00569 } 00570 00571 if (!$this->_parseString($data, $eof)) { 00572 $error = &$this->raiseError(); 00573 $this->free(); 00574 return $error; 00575 } 00576 00577 if ($eof === true) { 00578 $this->free(); 00579 } 00580 return true; 00581 } 00582 00590 function free() 00591 { 00592 if (isset($this->parser) && is_resource($this->parser)) { 00593 xml_parser_free($this->parser); 00594 unset( $this->parser ); 00595 } 00596 if (isset($this->fp) && is_resource($this->fp)) { 00597 fclose($this->fp); 00598 } 00599 unset($this->fp); 00600 return null; 00601 } 00602 00613 function &raiseError($msg = null, $ecode = 0) 00614 { 00615 $msg = !is_null($msg) ? $msg : $this->parser; 00616 $err = &new XML_Parser_Error($msg, $ecode); 00617 return parent::raiseError($err); 00618 } 00619 00620 // }}} 00621 // {{{ funcStartHandler() 00622 00632 function funcStartHandler($xp, $elem, $attribs) 00633 { 00634 $func = 'xmltag_' . $elem; 00635 $func = str_replace(array('.', '-', ':'), '_', $func); 00636 if (method_exists($this->_handlerObj, $func)) { 00637 call_user_func(array(&$this->_handlerObj, $func), $xp, $elem, $attribs); 00638 } elseif (method_exists($this->_handlerObj, 'xmltag')) { 00639 call_user_func(array(&$this->_handlerObj, 'xmltag'), 00640 $xp, $elem, $attribs); 00641 } 00642 } 00643 00644 // }}} 00645 // {{{ funcEndHandler() 00646 00655 function funcEndHandler($xp, $elem) 00656 { 00657 $func = 'xmltag_' . $elem . '_'; 00658 $func = str_replace(array('.', '-', ':'), '_', $func); 00659 if (method_exists($this->_handlerObj, $func)) { 00660 call_user_func(array(&$this->_handlerObj, $func), $xp, $elem); 00661 } elseif (method_exists($this->_handlerObj, 'xmltag_')) { 00662 call_user_func(array(&$this->_handlerObj, 'xmltag_'), $xp, $elem); 00663 } 00664 } 00665 00666 // }}} 00667 // {{{ startHandler() 00668 00679 function startHandler($xp, $elem, &$attribs) 00680 { 00681 return null; 00682 } 00683 00684 // }}} 00685 // {{{ endHandler() 00686 00696 function endHandler($xp, $elem) 00697 { 00698 return null; 00699 } 00700 00701 00702 // }}}me 00703 } 00704 00727 class XML_Parser_Error extends PEAR_Error 00728 { 00729 // {{{ properties 00730 00736 var $error_message_prefix = 'XML_Parser: '; 00737 00738 // }}} 00739 // {{{ constructor() 00755 function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE) 00756 { 00757 if (is_resource($msgorparser)) { 00758 $code = xml_get_error_code($msgorparser); 00759 $msgorparser = sprintf('%s at XML input line %d:%d', 00760 xml_error_string($code), 00761 xml_get_current_line_number($msgorparser), 00762 xml_get_current_column_number($msgorparser)); 00763 } 00764 $this->PEAR_Error($msgorparser, $code, $mode, $level); 00765 } 00766 // }}} 00767 } 00768 ?>