| * | | * | Proxy and authentication methods added by: | * | Marco Kraus | * | | * | Decoding of data by htmlentities or utf8_decode added by: | * | Roland Haeder | * | | * +----------------------------------------------------------------------+ * | Ref: | * | @link http://www.fase4.com/rdf/ Latest release | * +----------------------------------------------------------------------+ */ /** * Class RSS Parser * * This class offers methods to parse RSS Files * * @link http://www.fase4.com/rdf/ Latest release of this class * @package rss * @copyright Copyright (c) 2001 fase4.com. All rights reserved. * @author Stefan Saasen * @author Roland Haeder * @version 1.7 ($Date$Revision: 856 $ * @access public */ class fase4_rdf { /** * Word-wrapping mode for description, set it to 0 do disable this feature! Ommits _use_nl2br! * * @access private * @var integer */ var $_word_wrap = '0'; /** * Wether to recode \n ->
or not in description * * @access private * @var boolean */ var $_use_nl2br = TRUE; /** * Sets the decoding mode of the read data (UTF8 scrambles some german umlauts here!) * * "htmlentities" - Use the function htmlentities() * "utf8_decode" - Use the function ut8_decode() when you have UTF8 encoded text * - Use none of both * * @access private * @var string */ var $_decoding_mode = ''; /** * If $_link_target is set a target='xxx' attribute in each and
html tag will be added * * Possible values are "_blank", "_content", "_parent", "_self", "_top" * * @access private * @var string */ var $_link_target = '_blank'; /** * vars for proxy settings - Prox Host * * @access private * @var string */ var $_phost = ''; /** * vars for proxy settings - Prox Port * * @access private * @var string */ var $_pport = ''; /** * vars for proxy settings - Prox Username * * @access private * @var string */ var $_pname = ''; /** * vars for proxy settings - Prox Password * * @access private * @var string */ var $_ppasswd = ''; /** * just a flag for checking if proxy-support should be enabled * set default to false (will be enabled if set_proxy is called) * * @access private * @see set_proxy() * @var bool */ var $_use_proxy = FALSE; /** * just a flag for checking if proxy-support with authentication * should be enabled * set default to false (will be enabled if set_proxy is called) * * @access private * @see set_proxy() * @var boolean */ var $_use_proxy_auth = FALSE; /** * The time the Files will be cached (in seconds). * * @access private * @var int */ var $_refresh = 60; // int /** * The Name of the cached File. * * @access private * @var string */ var $_cached_file = ''; // String /** * Indicates whether the cached or the remote file was used. * * @access private * @var boolean */ var $_use_cached_file = TRUE; /** * (fast|normal) depends on _use_dynamic_display(). _use_dynamic_display(TRUE) -> 'normal', otherwise 'fast' * * @access private * @var string */ var $_cache_type = 'fast'; /** * The Name of the Remote File. * * @access private * @var string */ var $_remote_file = ''; /** * Path to the Cache Directory. * * @access private * @var string */ var $_cache_dir = 'cache/'; // String /** * Indicates whether the Creating of the Cache Directory needs to be done or not. * * @access private * @var boolean */ var $_cache_dir_ok = FALSE; /** * Type of the file to be parsed (RSS or RDF). * * The Type depends on the root node * * @access private * @var string */ var $_type = 'rss'; // string (rss or rdf) /** * Array of Display Settings. * * Specific Parameters can be set to hidden. These are: * image, channel and textinput. If set to "hidden" those elements won't be displayed. * * @access private * @var array */ var $_display_opt = array( 'build' => '', 'image' => '', 'channel' => '', 'textinput' => '', 'cache_update' => '', 'sitelink' => '', 'refid' => '', 'reflink' => '', ); /** * Defines the width attribute in the table that holds the rdf/rss representation * * @access private * @var int * @see see_table_width() */ var $_table_width = '100%'; /** * Indicates whether or not to use dynamic Display Settings * * @access private * @var array */ var $_use_dynamic_display = FALSE; /** * count * * @access private * @var int */ var $_item_count = '0'; /** * No of max s * * @access private * @var boolean */ var $_max_count = FALSE; /** * Array containing the content of * * @access private * @var array */ var $_array_channel = array(); /** * Array containing the content of each * * @access private * @var array */ var $_array_item = array(); /** * Array containing the content of * * @access private * @var array */ var $_array_textinput = array(); /** * Array containing the content of * * @access private * @var array */ var $_array_image = array(); /** * Array containing the Channel content. Just For internal XML Parser Purposes. * * @access private * @var array */ var $_citem = array(); /** * Array containing the Channel Parser Depth. Just For internal XML Parser Purposes. * * @access private * @var array */ var $_cdepth = array(); /** * Array containing the Channel tags. Just For internal XML Parser Purposes. * * @access private * @var array */ var $_ctags = array('x'); /** * Array containing the Channel content. Just For internal XML Parser Purposes. * * @access private * @var array */ var $_item = array(); // Array /** * Array containing the Channel Parser Depth. Just For internal XML Parser Purposes. * * @access private * @var array */ var $_depth = array(); // Array /** * Array containing the tags. Just For internal XML Parser Purposes. * * @access private * @var array */ var $_tags = array('x'); // Array /** * Garbage collection: probability in percent * * @var integer 0 => never * @access public */ var $gc_probability = 1; /** * HTML Output * * @var string * @access private */ var $_output = ''; /** * @var string */ var $_parse_mode = ''; /** * Output variable */ var $out = ''; /** * Salt for hashing */ var $salt = ''; /** * Callback function for processing content in finish() method. */ var $_finishCallback = NULL; /** * Constructor of our Class * * This Method checks if the Cache Directory can be found. Otherwise it tries to creat the Cache Directory at the specified Path. * Additionally the Refresh Time is set to a default Value of 1200s (20 min). * * @access public * @author Stefan Saasen * @see _refresh */ function fase4_rdf () { // default Value, to be overwritten in set_refresh() $this->_refresh = (time() - 1200); $this->_clear_cItems(); $this->_clear_Items(); } /** * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File. * * @access public * @author Stefan Saasen * @param string $rdf RDF File (Location) * @return string Displays RDF Content (using _display()) * @see _remote_file, cache() */ function parse_RDF ($rdf) { unset($this->_array_item); $this->_remote_file = $rdf; $this->out .= ""; $this->out .= "_table_width."\">"; $this->out .= $this->cache(); $this->out .= "
"; $this->_output = ''; $this->_item_count = '0'; return TRUE; } /** * This Method is called when all parsing is finished to use the garbage collection * * @access public * @author Stefan Saasen * @param string $rdf RDF File (Location) * @return string Displays RDF Content (using _display()) * @see _remote_file, cache() */ function finish ($return = FALSE) { // Replace dollar chars as they may cause problems $this->out = str_replace('$', '$', $this->out); // Is the call-back enabled? if ((!empty($this->out)) && (!is_null($this->_finishCallback)) && (is_callable($this->_finishCallback))) { // Then call it $this->out = call_user_func($this->_finishCallback, $this->out); } // END - if // Do garbage collection $this->_garbage_collection(); // Return or output? if ($return === FALSE) { print($this->out); } else { return $this->out; } } /** * With this method you can decide whether to use the normal cache and dynamic display Options or to use a static cache. * * In the first case the rdf/rss File will be stored locally, in the second case the html output of the specified source will be stored. * In this case you can not modify the display settings. * processing time: (1.4792) --> remote file * processing time: (0.0313) --> using 'normal cache' with display Modification turned on. * processing time: (0.0019) --> using 'fast cache' * * @access public * @author Stefan Saasen * @param string $rdf RDF File (Location) * @return string Displays RDF Content (using _display()) * @see _remote_file, cache() */ function use_dynamic_display ($bool) { $this->_use_dynamic_display = $bool; return TRUE; } /** * This Method avtually parses the XML data. * * @access private * @author Stefan Saasen * @param string $data RDF File XML Data * @see _clear_Items() */ function _parse_xRDF($data) { $this->_clear_Items(); $xml_parser = xml_parser_create(); xml_set_object($xml_parser,$this); xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0); xml_set_element_handler($xml_parser, '_startElement', '_endElement'); xml_set_character_data_handler($xml_parser, '_parseData'); if (!xml_parse($xml_parser, trim($data))) { $this->_throw_exception(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser)).'

Exception in function parse_RDF().'); } // END - if xml_parser_free($xml_parser); } /** * This Methods allows you to set the Refresh Time * * @access public * @author Stefan Saasen * @param int $seconds time files will be cached (in seconds). * @return boolean * @see _refresh */ function set_refresh($seconds) { $this->_refresh = (time() - $seconds); return TRUE; } function set_salt ($saltPara) { $this->salt = $saltPara; return TRUE; } /** * This Methods allows you to set the No. of s to display * * @access public * @param int $int No of max s * @author Stefan Saasen * @return boolean * @see _max_count, _endElement() */ function set_max_item ($int) { $this->_max_count = $int; return TRUE; } /** * This Methods allows you to set the Cache Directory * * @access public * @author Stefan Saasen * @param string $dir Path to Directory. * @return boolean * @see _cache_dir */ function set_CacheDir ($dir) { if (substr($dir, -1) != '/') { $dir = $dir.'/'; } $this->_cache_dir = $dir; } /** * This Method displays Error Messages and terminates the Execution of the Script * * @access private * @param string $msg Message to display on failure * @author Stefan Saasen */ function _throw_exception ($msg) { $this->out .= "
fase4 RDF Error: ".$msg."
"; return TRUE; } /** * This Method clears the Array containig the Items. * * @access private * @author Stefan Saasen * @see _item */ function _clear_Items() { $this->_item = array( 'title' => '', 'link' => '', 'description' => '', 'url' => '', 'language' => '', 'pubDate' => '', 'lastBuildDate' => '', 'width' => '', 'height' => '' ); } /** * This Method clears the Array containig the Channel Items. * * @access private * @author Stefan Saasen * @see _item */ function _clear_cItems() { $this->_citem = array( 'title' => '', 'link' => '', 'description' => '', 'url' => '', 'language' => '', 'copyright' => '', 'managingEditor' => '', 'webMaster' => '', 'pubDate' => '', 'lastBuildDate' => '', 'category' => '', 'generator' => '', 'docs' => '', 'cloud' => '', 'ttl' => '', 'image' => '', 'textinput' => '', 'skipHours' => '', 'skipDays' => '', 'sitelink' => '', 'refid' => '', 'reflink' => '', ); } /** * XML Parser Start Element Handler * * @access private * @author Stefan Saasen * @param mixed $parser a reference to the XML parser calling the handler. * @param string $name contains the name of the element for which this handler is called. * @param string $attrs contains an associative array with the element's attributes (if any). * @see _get_ChannelData(), _clear_Items(), _type, _parse_mode, _depth, _tags, _cdepth, _ctags */ function _startElement ($parser, $name, $attrs) { // We have to determine, which type of xml data we have to parse if ($name == 'rss') { $this->_type = 'rss'; } elseif ($name == 'rdf:RDF' || $name == 'rdf') { $this->_type = 'rdf'; } if ($name == 'channel' && $this->_type != 'rdf') { $this->_parse_mode = 'channel'; } elseif (($name == 'item') || ($name == 'image') || ($name == 'textinput') || (($name == 'channel') && ($this->_type != 'rss'))) { if ($this->_parse_mode == 'channel') { $this->_get_ChannelData($parser); } $this->_parse_mode = 'all'; } if (!isset($this->_depth[$this->get_parser_id($parser)])) { $this->_depth[$this->get_parser_id($parser)] = '0'; } $this->_depth[$this->get_parser_id($parser)]++; array_push($this->_tags, $name); if (!isset($this->_cdepth[$this->get_parser_id($parser)])) { $this->_cdepth[$this->get_parser_id($parser)] = '0'; } $this->_cdepth[$this->get_parser_id($parser)]++; array_push($this->_ctags, $name); } // END _startElement() /** * Retrives the Channel Data in File * * @access private * @author Stefan Saasen * @param mixed $parser a reference to the XML parser calling the handler. * @see _output, _display_opt, _citem */ function _get_ChannelData ($parser) { $this->_citem['link'] = trim($this->_citem['link']); if (($this->_display_opt['sitelink'] == $this->_citem['link']) && (!empty($this->_display_opt['reflink'])) && (!empty($this->_display_opt['refid']))) { $this->_citem['link'] .= $this->_display_opt['reflink'].$this->_display_opt['refid']; } if (empty($this->_display_opt['channel']) || $this->_display_opt['channel'] != 'hidden') { $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "
".htmlspecialchars($this->_citem['title'])."
".strip_tags($this->_citem['description'], ', ')."
 
\n"; if (isset($this->_display_opt['build']) && $this->_display_opt['build'] != 'hidden') { if ($this->_citem['lastBuildDate']) { $this->_output .= 'build: '. $this->_citem['lastBuildDate'].'
';} } if (isset($this->_display_opt['cache_update']) && $this->_display_opt['cache_update'] != 'hidden' && ($_update = $this->get_cache_update_time())) { $this->_output .= 'cache update: '.$_update."
\n"; } $this->_output .= "_citem['link']."\" "; if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; } $this->_output .= ">".$this->_cut_string($this->_citem['link']) . ''; $this->_output .= "

"; } $this->_array_channel = array( 'title' => $this->_citem['title'], 'link' => $this->_citem['link'], 'description' => $this->_citem['description'], 'lastBuildDate' => $this->_citem['lastBuildDate']); } /** * XML Parser End Element Handler * * @access private * @author Stefan Saasen * @param mixed $parser a reference to the XML parser calling the handler. * @param string $name contains the name of the element for which this handler is called. * @see _clear_Items(), _type, _parse_mode, _depth, _tags, _cdepth, _ctags, _item, _output, _display_opt */ function _endElement ($parser, $name) { array_pop($this->_tags); $this->_depth[$this->get_parser_id($parser)]--; array_pop($this->_ctags); $this->_cdepth[$this->get_parser_id($parser)]--; $this->_item['link'] = trim($this->_item['link']); if ((!empty($this->_display_opt['refid'])) && (!empty($this->_item['link']))) { if (!isInString('refid=', $this->_item['link'])) $this->_item['link'] .= '?refid=' . $this->_display_opt['refid']; } switch ($name) { case 'item': if (empty($this->_max_count) || $this->_item_count < $this->_max_count) { if ($this->_item['title'] != $this->_item['description'] && $this->_item['description']) { // word-wrapping added by Roland Haeder if (($this->_word_wrap > 0) && (strlen($this->_item['description']) > $this->_word_wrap)) { // Switch off _use_nl2br $this->_use_nl2br = FALSE; // First remove all \n $this->_item['description'] = str_replace('\n', ' ', $this->_item['description']); // Wrap with
\n $this->_item['description'] = wordwrap($this->_item['description'], $this->_word_wrap, "*
\n"); } elseif (($this->_word_wrap == '0') && (!$this->_use_nl2br)) { // Strip tags out instead when word-wrap is disabled $this->_item['description'] = strip_tags($this->_item['description'], '
, '); } // nl2br added by Roland Haeder if ($this->_use_nl2br) $this->_item['description'] = nl2br($this->_item['description']); $this->_output .= "\n"; $this->_output .= "".$this->_item['description']."\n"; // we just display the
if there is a description $this->_output .= "
\n"; } else { $this->_output .= "\n"; $this->_output .= "_item["link"]."\" "; if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; } $this->_output .= ">".$this->_item["title"]."\n"; } $this->_array_item[] = array( 'title' => $this->_item['title'], 'link' => $this->_item['link'], 'description' => $this->_item['description'] ); ++$this->_item_count; } $this->_clear_Items(); break; case 'image': if (isset($this->_display_opt['image']) && ($this->_display_opt['image'] != 'hidden') && $this->_item['url']) { $this->_output .= "\n"; $this->_output .= "_item['link']."\" "; if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; } $this->_output .= ">_item['url']."\""; if (isset($this->_item['width']) && isset($this->_item['height'])) { $this->_output .= " width=\"".$this->_item['width']."\" height=\"".$this->_item['height']."\""; } $this->_output .= " alt=\"".$this->_item['title']."\" border=\"0\" />\n"; $this->_array_image[] = array( 'url' => $this->_item['url'], 'link' => $this->_item['link'], 'width' => $this->_item['width'], 'height' => $this->_item['height'] ); $this->_clear_Items(); } elseif (isset($this->_display_opt['image']) && ($this->_display_opt['image'] == 'hidden')) { $this->_clear_Items(); } break; case 'channel': if (isset($this->_display_opt['channel']) && $this->_display_opt['channel'] != 'hidden' && $this->_item['title'] != '') { $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "\n"; $this->_output .= "
".htmlspecialchars($this->_item['title'])."
".strip_tags($this->_item['description'], ', ')."
 
\n"; if ($this->_display_opt['build'] != 'hidden') { if ($this->_item['lastBuildDate']) { $this->_output .= 'build: '. $this->_item['lastBuildDate'].'
';} } if ($this->_display_opt['cache_update'] != 'hidden' && ($_update = $this->get_cache_update_time())) { $this->_output .= 'cache update: '.$_update."
\n"; } $this->_output .= "_item['link']."\" "; if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; } $this->_output .= ">".$this->_cut_string($this->_item['link'])."\n"; $this->_output .= "
\n"; } $this->_array_channel = array( 'title' => $this->_item['title'], 'link' => $this->_item['link'], 'description' => $this->_item['description'], 'lastBuildDate' => $this->_item['lastBuildDate'] ); $this->_clear_Items(); $this->_clear_cItems(); break; case 'textinput': if (isset($this->_display_opt['textinput']) && ($this->_display_opt['textinput'] != 'hidden') && $this->_item['name'] && $this->_item['link']) { $this->_output .= "\n"; $this->_output .= "_item['link']."\" "; if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; } $this->_output .= "method=\"get\">\n"; $this->_output .= "
".$this->_item['title']."
"; $this->_output .= strip_tags($this->_item['description'], ', ')."

\n"; $this->_output .= "_item['name']."\"> \n"; $this->_output .= ""; $this->_output .= "\n"; $this->_output .= "\n"; $this->_array_textinput = array( 'title' => $this->_item['title'], 'name' => $this->_item['name'], 'link' => $this->_item['link'], 'description' => $this->_item['description'] ); $this->_clear_Items(); } elseif (isset($this->_display_opt['textinput']) && ($this->_display_opt['textinput'] == 'hidden')) { $this->_clear_Items(); } break; } } /** * This Method returns the data from the paragraph. * * @access public * @author Stefan Saasen * @return array * @see _array_channel */ function get_array_channel () { return $this->_array_channel; } /** * This Method returns the data from each paragraph. * * @access public * @author Stefan Saasen * @return array * @see _array_item */ function get_array_item () { return $this->_array_item; } /** * This Method returns the data from . * * @access public * @author Stefan Saasen * @return array * @see _array_textinput */ function get_array_textinput () { return $this->_array_textinput; } /** * Getter for parser id from resource * * @access private * @author Roland Haeder * @return int */ function get_parser_id ($parser) { // Default is zero $id = '0'; // Is it a resource? if (is_resource($parser)) { // Cast the resource into id $id = (int) $parser; } // END - if // Return the id return $id; } /** * This Method returns the data from . * * @access public * @author Stefan Saasen * @return array * @see _array_image */ function get_array_image() { return $this->_array_image; } /** * XML Parser Data Handler * * @access private * @author Stefan Saasen * @param mixed $parser a reference to the XML parser calling the handler. * @param string $text contains the character data as a string. * @see _parse_mode, _item, _tags, _depth, _citem, _ctags, _cdepth */ function _parseData($parser, $text) { // Deocing mode added by Roland Haeder switch ($this->_decoding_mode) { case 'utf8_decode': $text = utf8_decode($text); break; case 'htmlentities': $text = htmlentities($text); break; } $clean = preg_replace("/\s/", '', $text); if ($clean) { $text = preg_replace("/^\s+/", '', $text)."\n"; if ($this->_parse_mode == 'all') { if (isset($this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]]) && $this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]]) { $this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]] .= $text; } else { $this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]] = $text; } } elseif (isset($this->_parse_mode) && $this->_parse_mode == 'channel') { if (isset($this->_citem[$this->_ctags[$this->_cdepth[$this->get_parser_id($parser)]]])) { $this->_citem[$this->_ctags[$this->_cdepth[$this->get_parser_id($parser)]]] .= $text; } else { $this->_citem[$this->_ctags[$this->_cdepth[$this->get_parser_id($parser)]]] = $text; } } } } /** * This Method allows you to choose if specific Parameters are displayed or not. These are: * image, channel, textinput, build and cache_update. If set to "hidden" those elements won't be displayed. * * @access public * @author Stefan Saasen * @param array $options * @see _display_opt */ function set_Options ($options = NULL) { if (is_array($options)) { $this->_display_opt = $options; return TRUE; } else { unset($this->_display_opt); return FALSE; } } /** * This Method allows you to define the width of the table that holds the representation of the rdf/rss file. * * @access public * @author Stefan Saasen * @param int $width attribute width in tag * @see _table_width */ function set_table_width ($width = 400) { $this->_table_width = $width; return TRUE; } /** * This Method returns an assocative Array with available Options. * * The Keys are the Name of the Options to be set. * The Values are short Description of available Options. * * @access public * @author Stefan Saasen * @return array $options * @see _display_opt */ function get_Options () { $options = array( 'image' => "If 'image' is set to "hidden" no image provided by the RDF Publisher will be displayed.", 'channel' => "If 'channel' is set to "hidden" the Channel Meta Data (i.e the Title and the short description regarding the RDF Publisher will not be displayed", 'textinput' => "If set to "hidden" no Input Form will be displayed", 'build' => "If set to "hidden" the Build Date (if provided) of the RDF File will not be displayed", 'cache_update' => "If set to "hidden" the Update Date/Time of the cached Rdf File will not be displayed" ); return $options; } /** * This Method returns the Content of the RDF File in one string. The String actually holds the whole XML Document. * * @access public * @author Stefan Saasen * @param string $rdf RDF File (Location) * @return string XML Presentation of parsed RDF File * @see _cached_file, _remote_file, _cache_dir, _refresh, _update_cache() */ function cache () { // checks if the cache directory already exists // if not, the cache directory will be created if (!$this->_cache_dir_ok) { $this->_create_cache_dir(); } if ($this->_use_dynamic_display == TRUE) { $this->_cached_file = md5('dynamic' . $this->salt.$this->_remote_file) . '.rss'; $this->_cache_type = 'normal'; } else { $this->_cached_file = md5($this->salt . $this->_remote_file) . '.rss'; $this->_cache_type = 'fast'; } $_cache_f = $this->_cache_dir.$this->_cached_file; if ((!file_exists($_cache_f)) || (filemtime($_cache_f) < $this->_refresh) || (filesize($_cache_f) == 0)) { // We have to parse the remote file $this->_use_cached_file = FALSE; // --> we want to provide proper Information for Use in // get_cache_update_time() clearstatcache(); if ($this->_use_dynamic_display == TRUE) { $_rdf = implode(' ', $this->_rdf_data()); // -> proxy if (!$_rdf) { $this->_throw_exception($this->_remote_file.' is not available'); } $this->_parse_xRDF($_rdf); $this->_update_cache($_rdf); $data = $this->_output; } else { $_rdf = implode(' ', $this->_rdf_data()); // -> proxy if (!$_rdf) { $this->_throw_exception($this->_remote_file.' is not available'); } $this->_parse_xRDF($_rdf); $this->_update_cache($this->_output); $data = $this->_output; } } elseif (defined('__SECURITY') && function_exists('readFromFile')) { // Use readFromFile() from mailer project $this->_use_cached_file = TRUE; if ($this->_use_dynamic_display == TRUE) { $this->_parse_xRDF(readFromFile($_cache_f)); $data = $this->_output; } else { $data = readFromFile($_cache_f); } } else { // we can use the cached file $this->_use_cached_file = TRUE; if ($this->_use_dynamic_display == TRUE) { $this->_parse_xRDF(implode(' ', file($_cache_f))); $data = $this->_output; } else { $data = implode(' ', file($_cache_f)); } } // Return trimmed data return trim($data); } // END cache() /** * This Methods creates the Cache Directory if the specified Directory does not exist. * * @access private * @author Stefan Saasen * @param string $dir Path to Directory. * @return boolean * @see _cache_dir, _cache_dir_ok */ function _create_cache_dir() { $path = ''; if (!is_dir($this->_cache_dir)) { $arr = explode('/', $this->_cache_dir); $c = count($arr); if ($arr[0] == '') { $path = '/'; } for($i = '0';$i<$c;$i++) { if ($arr[$i]!='') { $path .= $arr[$i].'/'; if (!is_dir($path)) { if (!mkdir($path, 0777)) { $this->_throw_exception("failed to create directory:".$this->_cache_dir.".

Exception on Line: ".__LINE__); return FALSE; } } } } $this->_cache_dir_ok = TRUE; return TRUE; } else { $this->_cache_dir_ok = TRUE; return TRUE; } } // END _create_cache_dir() /** * This Method updates the cached RDF Files and synchronises them with their remote Counterparts. * * @access private * @author Stefan Saasen * @param string $rdf RDF File (Location) * @see _cache_dir, _cached_file, _throw_exception() */ function _update_cache ($content = '') { if (defined('__SECURITY') && function_exists('writeToFile')) { // Use mailer-project function return writeToFile($this->_cache_dir.$this->_cached_file, $content); } $_local = @fopen($this->_cache_dir.$this->_cached_file, 'w'); if (!$_local) { $this->_throw_exception('Cannot open '.$this->_cached_file.'

Exception at Line: '.__LINE__); return FALSE; } if (fwrite($_local, $content) === FALSE) { $this->_throw_exception('Cannot write to '.$this->_cached_file.'
Exeception at Line: '.__LINE__); return FALSE; } fclose($_local); @chmod($this->_cache_dir.$this->_cached_file, 0666); return TRUE; } // END _update_cache() /** * This Method returns the Date/Time of last Cache Update of the actually parsed RDF File. * * @access public * @author Stefan Saasen * @return string Date/Time of last Update * @see _cache_dir, _cached_file */ function get_cache_update_time () { return (file_exists($this->_cache_dir.$this->_cached_file))?date('d.m.Y H:i:s', filemtime($this->_cache_dir.$this->_cached_file)):'Cachemiss'; } // END get_cache_update_time() /** * This Method returns the Type of Cache that was used ('normal' or 'fast') * * @access public * @author Stefan Saasen * @param string $rdf RDF File (Location) * @return string Displays RDF Content (using _display()) * @see _remote_file, cache() */ function get_CacheType() { return $this->_cache_type; } /** * Returns true if cached file was used, otherwise false * * @access public * @author Stefan Saasen * @return array $options * @see _use_cached_file */ function is_cachedFile () { return $this->_use_cached_file; } /** * This Method deletes all the cached Files. * * Please keep in mind to use this method just as a 'manual garbage collection' * You should cache the rss/rdf files locally to avoid unnecessary traffic. * (Both for your visitors and the Publisher) * * @access public * @author Stefan Saasen * @see _cache_dir */ function clear_cache () { $dir = dir($this->_cache_dir); while($file = $dir->read()) { // Exclude directories if (is_file($dir->path . $file) && substr($file, -4, 4) == '.rss') { if ((defined('__SECURITY') && function_exists('removeFile')) && (!removeFile($dir->path . $file))) { $this->_throw_exception("removeFile() was unable to unlink ".$dir->path . $file."
\n
\nException at Line: ".__LINE__); return FALSE; } elseif (!unlink($dir->path . $file)) { $this->_throw_exception("Unable to unlink ".$dir->path . $file."
\n
\nException at Line: ".__LINE__); return FALSE; } // END - if } // END - if } // END - while $dir->close(); return TRUE; } // END clear_cache() /** * Cuts the String $string after $str_len and adds '... ' * * @access private * @param string $string String to be shortened * @param int $str_len length of the returned String (overall length including '... ') * @return string Cut String */ function _cut_string($string, $str_len = '30') { if (strlen(trim($string))>$str_len) { $string = substr(trim($string) , 0, $str_len - 4); $string .= ' ...'; } return $string; } // END _cut_string() /** * this Method implements simple Garbage Collection * * @access private * @author Stefan Saasen * @see _cache_dir, gc_probability, gc_maxlifetime */ function _garbage_collection() { srand((double) microtime() * 1000000); if (mt_rand(1, 100) <= $this->gc_probability) { $dir = dir($this->_cache_dir); while($file = $dir->read()) { if ((is_file($dir->path . $file)) && (substr($file, -4, 4) == '.rss') && (filemtime($dir->path . $file) <= time() - $this->_refresh)) { if (defined('__SECURITY') && function_exists('removeFile')) { // Use mailer-project's function removeFile($dir->path . $file); } else { // Use PHP's function unlink($dir->path . $file); } } // END - if } $dir->close(); } // END if } /* ==== Proxy/Auth methods ==== */ /** * this method sets a proxy server * * @access public * @param string $phost Proxy Host * @param string $pport Prox Port * @author Marco Kraus */ function set_proxy($phost, $pport) { $this->_use_proxy = TRUE; if ($phost != '') $this->_phost = $phost; if ($pport != '') $this->_pport = $pport; } /** * this method sets a proxy server authentification * * @access public * @param string $pname Username * @param string $ppaswd Password * @author Marco Kraus */ function set_proxy_auth($pname, $ppasswd) { $this->_use_proxy_auth = TRUE; if ($pname != '') $this->_pname = $pname; if ($ppasswd != '') $this->_ppasswd = $ppasswd; } /** * gets _remote_file into an array * * needed, cause if you use a proxy, you have to open * a raw-tcp-socket to get the data * * @access private * @author Marco Kraus * @return array * @see _use_proxy, cache() */ function _rdf_data () { // Init output $output = array(); // Use mailer-project's function or own code? if (defined('__SECURITY') && function_exists('sendHttpGetRequest')) { // Use mailer-project instead (see http://mxchange.org) $output = sendHttpGetRequest($this->_remote_file, array(), TRUE); } elseif ($this->_use_proxy == TRUE) { // we need a raw socket here to connect to proxy $fp = fsockopen($this->_phost,$this->_pport); if (!$fp) { $this->_throw_exception($this->_remote_file.' is not available with proxy'); } else { if ($this->_use_proxy_auth == TRUE) { fputs($fp, "GET ".$this->_remote_file." HTTP/1.0\r\nUser-Agent: Fase4 RDF-Reader/1.40 modified by Quix0r\r\n\r\n"); } else { fputs($fp, "GET ".$this->_remote_file." HTTP/1.0\r\nUser-Agent: Fase4 RDF-Reader/1.40 modified by Quix0r\r\nProxy-Authorization: Basic ".base64_encode("$this->_pname:$this->_ppasswd") ."\r\n\r\n"); } } for ($i = '0'; !feof ($fp) ; $i++) { $usable_data[$i] = ''; $usable_data[$i] = fgets($fp,4096); // PARSE HEADER ---- first line has to be _remote_file, 0, 7) != 'http://') { $this->_throw_exception('Cannot find http:// in '.$this->_remote_file.'!'); return array(); } else { // Extract host information $host = substr($this->_remote_file, 7); // Extract the GET part $get = '/'; if (strpos($host, '/') > 0) { $get = substr($host, strpos($host, '/')); $host = substr($host, 0, strpos($host, '/')); } // END - if // Extract port $port = '80'; if (strpos($host, ':') > 0) { $port = substr($host, (strpos($host, ':') + 1)); $host = substr($host, 0, (strpos($host, ':') - 1)); } // END - if // Start connection to server $fp = fsockopen($host, $port); if (!$fp) { $this->_throw_exception($this->_remote_file.' is maybe not available.'); return array(); } // END - if // Repare request line $request = sprintf("GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Fase4 RDF-Reader/1.40 modified by Quix0r\r\n\r\n", $get, $host); // Send request out fputs($fp, $request); $reply = ''; $isContent = FALSE; $dummy = ''; // Read reply $i=0; while (!feof($fp)) { $read = trim(fgets($fp, 4096)); if (substr($read, 0, 5) == ' 0) && (count($reply) == 0) && (!$isContent)) { // Transfer content from dummy $reply = $content; } // END - if fclose($fp); //die(htmlentities($reply)); $output = $reply; } } // Exit here return $output; } // END _rdf_data() } // END class // [EOF] ?>