PHP\'s XML Extension is not loaded or available.'); define('ONYX_ERR_NOT_WRITEABLE', 'The specified cache directory is not writeable.'); define('ONYX_ERR_INVALID_URI', 'The specified file could not be opened.'); define('ONYX_ERR_INVALID_ITEM', 'Invalid item index specified.'); define('ONYX_ERR_NO_STREAM', 'Could not open the specified file. Check the path, and make sure that you have write permissions to this file.'); define('ONYX_ERR_INV_ENC', 'Invalid encoding type.'); define('ONYX_META', 'meta'); define('ONYX_ITEMS', 'items'); define('ONYX_IMAGE', 'image'); define('ONYX_TEXTINPUT', 'textinput'); define('ONYX_NAMESPACES', 'namespaces'); define('ONYX_CACHE_AGE', 'cache_age'); define('ONYX_FETCH_ASSOC', 1); define('ONYX_FETCH_OBJECT', 2); class ONYX_RSS { var $parser; var $sourceEncoding; var $targetEncoding; var $RSSData; var $RSSVars; var $cachePath; var $cacheTime; var $cacheAge; var $fetchMode; var $debugMode; var $error; var $outputFile; var $inBetween; function ONYX_RSS($source=false, $target=false) { $this->__construct($source, $target); } function __construct($source=false, $target=false) { $this->sourceEncoding = $source; $this->targetEncoding = $target; $this->RSSData = array(); $this->RSSVars = array(); $this->cachePath = dirname(__FILE__); $this->cacheTime = 180; $this->cacheAge = 0; $this->fetchMode = ONYX_FETCH_ASSOC; $this->debugMode = true; $this->outputFile = ''; $this->error = '
Error on line %s of '.__FILE__.': %s
'; $this->inBetween = true; } //private function initParser($source=false, $target=false) function initParser($source=false, $target=false) { if (is_resource($this->parser)) xml_parser_free($this->parser); $this->parser = ($source) ? @xml_parser_create($source) : @xml_parser_create() ; if (!is_resource($this->parser)) { $this->raiseError((__LINE__-2), ONYX_ERR_NO_PARSER); return false; } xml_set_object($this->parser, $this); if ($target) if (!@xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $target)) { $this->raiseError((__LINE-2), ONYX_ERR_INV_ENC); return false; } xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); xml_set_element_handler($this->parser, 'tag_open', 'tag_close'); xml_set_character_data_handler($this->parser, 'cdata'); } //private function setVars() function setVars() { $this->RSSData = array(); $this->RSSVars = array( 'cache_age' => 0 , 'current_tag' => '', 'item_index' => 0 , 'output_index' => -1, 'active_level' => '' ); } function parse($uri, $cache=false, $time=false) { $this->initParser($this->sourceEncoding, $this->targetEncoding); $this->setVars(); $recache = false; if ($cache) $cache = $this->cachePath.'/'.basename($cache); if (!$cache || ($cache && !file_exists($cache)) || ($cache && $this->cacheNeedsUpdating($uri, $cache, $time))) { $fp = @fopen($uri, 'rb'); if (!is_resource($fp)) { $this->raiseError((__LINE__-3), ONYX_ERR_INVALID_URI); return false; } while ($chunk = fread($fp, 4096)) if (!xml_parse($this->parser, $chunk, feof($fp))) { $this->raiseError((__LINE__-2), sprintf('File has an XML error (%s at line %s).', xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser))); return false; } fclose($fp); $recache = true; } else $this->getDataFromCache($cache); if ($cache && $recache) $this->cache($cache); return true; } //private function getDataFromCache($cache) function getDataFromCache($cache) { if (!($fp = @fopen($cache, 'rb'))) { $this->raiseError((__LINE__-2), ONYX_ERR_INVALID_URI); return; } $this->cacheAge = ceil((time() - filemtime($cache)) / 60); $this->RSSData = unserialize(fread($fp, filesize($cache))); fclose($fp); } //private function cacheNeedsUpdating($uri, $cache, $time) function cacheNeedsUpdating($uri, $cache, $time) { $cache_mod = file_exists($cache) ? filemtime($cache) : 0; if ($this->isLocalFilename($uri)) $uri_mod = file_exists($uri) ? filemtime($uri) : 0; else $uri_mod = $this->remoteModTime($uri); $t = $time ? $time : $this->cacheTime; return (ceil((time() - $cache_mod) / 60) >= $t || $uri_mod >= $cache_mod); } function remoteModTime($uri) { if (function_exists('version_compare') && version_compare(phpversion(), '4.3.0') >= 0) { if (!($fp = @fopen($uri, 'rb'))) return 0; $meta = stream_get_meta_data($fp); for ($i = 0; isset($meta['wrapper_data'][$i]); $i++) if (strpos(strtolower($meta['wrapper_data'][$i]), 'last-modified') !== false) { $modtime = substr($meta['wrapper_data'][$i], 15); break; } fclose($fp); } else { $parts = parse_url($uri); $port = isset($parts['port']) ? $parts['port'] : 80; if (!($fp = @fsockopen($host, $port))) return 0; $req = "HEAD {$parts['path']} HTTP/1.1\r\nUser-Agent: PHP/".phpversion(); $req.= "\r\nHost: {$parts['host']}\r\nAccept: */*\r\n\r\n"; fputs($fp, $req); while (!feof($fp)) { $str = fgets($fp, 4096); if (strpos(strtolower($str), 'last-modified') !== false) { $modtime = substr($str, 15); break; } } fclose($fp); } return (isset($modtime)) ? strtotime($modtime) : 0; } function isLocalFileName($file) { $p = parse_url($file); return !isset($p['host']); } //private function cache($filename) function cache($filename) { if (!($fp = @fopen($filename, 'wb'))) { $this->raiseError((__LINE__-2), ONYX_ERR_NO_STREAM); return; } fwrite($fp, serialize($this->RSSData)); fclose($fp); $this->cacheAge = 0; } //private function tag_open($parser, $tag, $attrs) function tag_open($parser, $tag, $attrs) { $this->inBetween = false; $this->RSSVars['current_tag'] = $tag; switch ($tag) { case 'channel': case 'image': case 'textinput': $this->RSSVars['active_level'] = $tag; break; case 'item': $this->RSSVars['active_level'] = $tag; $this->RSSVars['item_index']++; break; default: break; } if (sizeof($attrs)) foreach ($attrs as $k => $v) if (strpos($k, 'xmlns') !== false) $this->RSSData['namespaces'][$k] = $v; } //private function tag_close($parser, $tag) function tag_close($parser, $tag) { $this->inBetween = true; } //private function cdata($parser, $data) function cdata($parser, $data) { if ($this->inBetween) return; switch ($this->RSSVars['active_level']) { case 'channel': case 'image': case 'textinput': if (!isset($this->RSSData[$this->RSSVars['active_level']][$this->RSSVars['current_tag']])) $this->RSSData[$this->RSSVars['active_level']][$this->RSSVars['current_tag']] = $data; else $this->RSSData[$this->RSSVars['active_level']][$this->RSSVars['current_tag']].= $data; break; case 'item': if (!isset($this->RSSData['items'][$this->RSSVars['item_index']-1][$this->RSSVars['current_tag']])) $this->RSSData['items'][$this->RSSVars['item_index']-1][$this->RSSVars['current_tag']] = $data; else $this->RSSData['items'][$this->RSSVars['item_index']-1][$this->RSSVars['current_tag']].= $data; break; } } function &getData($type) { if ($type == ONYX_META) return !isset($this->RSSData['channel']) ? false : ($this->fetchMode == 1 ? $this->RSSData['channel'] : (object)$this->RSSData['channel']); if ($type == ONYX_IMAGE) return !isset($this->RSSData['image']) ? false : ($this->fetchMode == 1 ? $this->RSSData['image'] : (object)$this->RSSData['image']); if ($type == ONYX_TEXTINPUT) return !isset($this->RSSData['textinput']) ? false : ($this->fetchMode == 1 ? $this->RSSData['textinput'] : (object)$this->RSSData['textinput']); if ($type == ONYX_ITEMS) { if ($this->fetchMode == 1) return $this->RSSData['items']; $temp = array(); for ($i=0; $i < sizeof($this->RSSData['items']); $i++) $temp[] = (object)$this->RSSData['items'][$i]; return $temp; } if ($type == ONYX_NAMESPACES) return !isset($this->RSSData['namespaces']) ? false : ($this->fetchMode == 1 ? $this->RSSData['namespaces'] : (object)$this->RSSData['namespaces']); if ($type == ONYX_CACHE_AGE) return $this->cacheAge; return false; } function numItems() { return sizeof($this->RSSData['items']); } function getNextItem($max=false) { $type = $this->fetchMode; $this->RSSVars['output_index']++; if (($max && $this->RSSVars['output_index'] > $max) || !isset($this->RSSData['items'][$this->RSSVars['output_index']])) return false; return ($type == ONYX_FETCH_ASSOC) ? $this->RSSData['items'][$this->RSSVars['output_index']] : (($type == ONYX_FETCH_OBJECT) ? (object)$this->RSSData['items'][$this->RSSVars['output_index']] : false); } function itemAt($num) { if (!isset($this->RSSData['items'][$num])) { $this->raiseError((__LINE__-3), ONYX_ERR_INVALID_ITEM); return false; } $type = $this->fetchMode; return ($type == ONYX_FETCH_ASSOC) ? $this->RSSData['items'][$num] : (($type == ONYX_FETCH_OBJECT) ? (object)$this->RSSData['items'][$num] : false); } function startBuffer($file=false) { $this->outputFile = $file; ob_start(); } function endBuffer() { if (!$this->outputFile) ob_end_flush(); else { if (!($fp = @fopen($this->outputFile, 'wb'))) { $this->raiseError((__LINE__-2), ONYX_ERR_NO_STREAM); ob_end_flush(); return; } fwrite($fp, ob_get_contents()); fclose($fp); ob_end_clean(); } } //private function raiseError($line, $err) function raiseError($line, $err) { if ($this->debugMode) printf($this->error, $line, $err); } function setCachePath($path) { $this->cachePath = $path; } function setExpiryTime($time) { $this->cacheTime = $time; } function setDebugMode($state) { $this->debugMode = (bool)$state; } function setFetchMode($mode) { $this->fetchMode = $mode; } function parseLocal($uri, $file=false, $time=false) { $this->raiseError((__LINE__-2), 'The parseLocal() function is deprecated, use parse() instead.'); return $this->parse($uri, $file, $time); } } ?