5 * +----------------------------------------------------------------------+
7 * | Copyright (c) 2001 Stefan Saasen |
8 * +----------------------------------------------------------------------+
9 * | The contents of this file are subject to the Mozilla Public License |
10 * | Version 1.1 (the "License"); you may not use this file except in |
11 * | compliance with the License. You may obtain a copy of the License at |
12 * | http: *www.mozilla.org/MPL/ |
14 * | Software distributed under the License is distributed on an "AS IS" |
15 * | basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See |
16 * | the License for the specific language governing rights and |
17 * | limitations under the License. |
18 * +----------------------------------------------------------------------+
20 * | Maintainer and initial developer: |
21 * | Stefan Saasen <s@fase4.com> |
23 * | Proxy and authentication methods added by: |
24 * | Marco Kraus <marco.kraus@siemens.com> |
26 * | Decoding of data by htmlentities or utf8_decode added by: |
27 * | Roland Haeder <webmaster@mxchange.org> |
29 * +----------------------------------------------------------------------+
31 * | @link http://www.fase4.com/rdf/ Latest release |
32 * +----------------------------------------------------------------------+
38 * This class offers methods to parse RSS Files
40 * @link http://www.fase4.com/rdf/ Latest release of this class
42 * @copyright Copyright (c) 2001 fase4.com. All rights reserved.
43 * @author Stefan Saasen <s@fase4.com>
44 * @author Roland Haeder <webmaster@mxchange.org>
52 * Word-wrapping mode for description, set it to 0 do disable this feature! Ommits _use_nl2br!
57 var $_word_wrap = '0';
60 * Wether to recode \n -> <br /> or not in description
65 var $_use_nl2br = TRUE;
68 * Sets the decoding mode of the read data (UTF8 scrambles some german umlauts here!)
70 * "htmlentities" - Use the function htmlentities()
71 * "utf8_decode" - Use the function ut8_decode() when you have UTF8 encoded text
72 * <empty> - Use none of both
77 var $_decoding_mode = '';
80 * If $_link_target is set a target='xxx' attribute in each <a /> and <form accept-charset="utf-8" /> html tag will be added
82 * Possible values are "_blank", "_content", "_parent", "_self", "_top"
87 var $_link_target = '_blank';
90 * vars for proxy settings - Prox Host
98 * vars for proxy settings - Prox Port
106 * vars for proxy settings - Prox Username
114 * vars for proxy settings - Prox Password
122 * just a flag for checking if proxy-support should be enabled
123 * set default to false (will be enabled if set_proxy is called)
129 var $_use_proxy = FALSE;
132 * just a flag for checking if proxy-support with authentication
134 * set default to false (will be enabled if set_proxy is called)
140 var $_use_proxy_auth = FALSE;
143 * The time the Files will be cached (in seconds).
148 var $_refresh = 60; // int
151 * The Name of the cached File.
156 var $_cached_file = ''; // String
159 * Indicates whether the cached or the remote file was used.
164 var $_use_cached_file = TRUE;
167 * (fast|normal) depends on _use_dynamic_display(). _use_dynamic_display(TRUE) -> 'normal', otherwise 'fast'
172 var $_cache_type = 'fast';
175 * The Name of the Remote File.
180 var $_remote_file = '';
183 * Path to the Cache Directory.
188 var $_cache_dir = 'cache/'; // String
191 * Indicates whether the Creating of the Cache Directory needs to be done or not.
196 var $_cache_dir_ok = FALSE;
199 * Type of the file to be parsed (RSS or RDF).
201 * The Type depends on the root node
206 var $_type = 'rss'; // string (rss or rdf)
209 * Array of Display Settings.
211 * Specific Parameters can be set to hidden. These are:
212 * image, channel and textinput. If set to "hidden" those elements won't be displayed.
217 var $_display_opt = array(
222 'cache_update' => '',
229 * Defines the width attribute in the table that holds the rdf/rss representation
233 * @see see_table_width()
235 var $_table_width = '100%';
238 * Indicates whether or not to use dynamic Display Settings
243 var $_use_dynamic_display = FALSE;
251 var $_item_count = '0';
259 var $_max_count = FALSE;
262 * Array containing the content of <channel />
267 var $_array_channel = array();
270 * Array containing the content of each <item />
275 var $_array_item = array();
278 * Array containing the content of <textinput />
283 var $_array_textinput = array();
286 * Array containing the content of <image />
291 var $_array_image = array();
294 * Array containing the Channel content. Just For internal XML Parser Purposes.
299 var $_citem = array();
302 * Array containing the Channel Parser Depth. Just For internal XML Parser Purposes.
307 var $_cdepth = array();
310 * Array containing the Channel tags. Just For internal XML Parser Purposes.
315 var $_ctags = array('x');
318 * Array containing the Channel content. Just For internal XML Parser Purposes.
323 var $_item = array(); // Array
326 * Array containing the Channel Parser Depth. Just For internal XML Parser Purposes.
331 var $_depth = array(); // Array
334 * Array containing the tags. Just For internal XML Parser Purposes.
339 var $_tags = array('x'); // Array
342 * Garbage collection: probability in percent
344 * @var integer 0 => never
347 var $gc_probability = 1;
360 var $_parse_mode = '';
373 * Callback function for processing content in finish() method.
375 var $_finishCallback = NULL;
378 * Constructor of our Class
380 * This Method checks if the Cache Directory can be found. Otherwise it tries to creat the Cache Directory at the specified Path.
381 * Additionally the Refresh Time is set to a default Value of 1200s (20 min).
384 * @author Stefan Saasen <s@fase4.com>
387 function fase4_rdf () {
388 // default Value, to be overwritten in set_refresh()
389 $this->_refresh = (time() - 1200);
390 $this->_clear_cItems();
391 $this->_clear_Items();
395 * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
398 * @author Stefan Saasen <s@fase4.com>
399 * @param string $rdf RDF File (Location)
400 * @return string Displays RDF Content (using _display())
401 * @see _remote_file, cache()
403 function parse_RDF ($rdf) {
404 unset($this->_array_item);
405 $this->_remote_file = $rdf;
406 $this->out .= "<!-- http://www.fase4.com/rdf/ -->";
407 $this->out .= "<table width=\"".$this->_table_width."\">";
408 $this->out .= $this->cache();
409 $this->out .= "</table>";
411 $this->_item_count = '0';
416 * This Method is called when all parsing is finished to use the garbage collection
419 * @author Stefan Saasen <s@fase4.com>
420 * @param string $rdf RDF File (Location)
421 * @return string Displays RDF Content (using _display())
422 * @see _remote_file, cache()
424 function finish ($return = FALSE) {
425 // Replace dollar chars as they may cause problems
426 $this->out = str_replace('$', '$', $this->out);
428 // Is the call-back enabled?
429 if ((!empty($this->out)) && (!is_null($this->_finishCallback)) && (is_callable($this->_finishCallback))) {
431 $this->out = call_user_func($this->_finishCallback, $this->out);
434 // Do garbage collection
435 $this->_garbage_collection();
438 if ($return === FALSE) {
446 * With this method you can decide whether to use the normal cache and dynamic display Options or to use a static cache.
448 * 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.
449 * In this case you can not modify the display settings.
450 * processing time: (1.4792) --> remote file
451 * processing time: (0.0313) --> using 'normal cache' with display Modification turned on.
452 * processing time: (0.0019) --> using 'fast cache'
455 * @author Stefan Saasen <s@fase4.com>
456 * @param string $rdf RDF File (Location)
457 * @return string Displays RDF Content (using _display())
458 * @see _remote_file, cache()
460 function use_dynamic_display ($bool) {
461 $this->_use_dynamic_display = $bool;
466 * This Method avtually parses the XML data.
469 * @author Stefan Saasen <s@fase4.com>
470 * @param string $data RDF File XML Data
471 * @see _clear_Items()
473 function _parse_xRDF($data) {
474 $this->_clear_Items();
475 $xml_parser = xml_parser_create();
476 xml_set_object($xml_parser,$this);
477 xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
478 xml_set_element_handler($xml_parser, '_startElement', '_endElement');
479 xml_set_character_data_handler($xml_parser, '_parseData');
480 if (!xml_parse($xml_parser, trim($data))) {
481 $this->_throw_exception(sprintf("XML error: %s at line %d",
482 xml_error_string(xml_get_error_code($xml_parser)),
483 xml_get_current_line_number($xml_parser)).'<br /><br />Exception in function parse_RDF().');
485 xml_parser_free($xml_parser);
490 * This Methods allows you to set the Refresh Time
493 * @author Stefan Saasen <s@fase4.com>
494 * @param int $seconds time files will be cached (in seconds).
498 function set_refresh($seconds) {
499 $this->_refresh = (time() - $seconds);
503 function set_salt ($saltPara) {
504 $this->salt = $saltPara;
509 * This Methods allows you to set the No. of <item>s to display
512 * @param int $int No of max <item>s
513 * @author Stefan Saasen <s@fase4.com>
515 * @see _max_count, _endElement()
517 function set_max_item ($int) {
518 $this->_max_count = $int;
523 * This Methods allows you to set the Cache Directory
526 * @author Stefan Saasen <s@fase4.com>
527 * @param string $dir Path to Directory.
531 function set_CacheDir ($dir) {
532 if (substr($dir, -1) != '/') {
535 $this->_cache_dir = $dir;
539 * This Method displays Error Messages and terminates the Execution of the Script
542 * @param string $msg Message to display on failure
543 * @author Stefan Saasen <s@fase4.com>
545 function _throw_exception ($msg) {
546 $this->out .= "<div style=\"font-family: verdana, helvetica, arial, sans-serif;font-size:11px; color: #6699cc;margin-top:10px;margin-bottom:10px;\" align=\"center\">fase4 RDF Error: ".$msg."</div>";
551 * This Method clears the Array containig the Items.
554 * @author Stefan Saasen <s@fase4.com>
557 function _clear_Items() {
558 $this->_item = array(
565 'lastBuildDate' => '',
571 * This Method clears the Array containig the Channel Items.
574 * @author Stefan Saasen <s@fase4.com>
577 function _clear_cItems() {
578 $this->_citem = array(
585 'managingEditor' => '',
588 'lastBuildDate' => '',
605 * XML Parser Start Element Handler
608 * @author Stefan Saasen <s@fase4.com>
609 * @param mixed $parser a reference to the XML parser calling the handler.
610 * @param string $name contains the name of the element for which this handler is called.
611 * @param string $attrs contains an associative array with the element's attributes (if any).
612 * @see _get_ChannelData(), _clear_Items(), _type, _parse_mode, _depth, _tags, _cdepth, _ctags
614 function _startElement ($parser, $name, $attrs) {
615 // We have to determine, which type of xml data we have to parse
616 if ($name == 'rss') {
617 $this->_type = 'rss';
618 } elseif ($name == 'rdf:RDF' || $name == 'rdf') {
619 $this->_type = 'rdf';
623 if ($name == 'channel' && $this->_type != 'rdf') {
624 $this->_parse_mode = 'channel';
625 } elseif (($name == 'item')
626 || ($name == 'image')
627 || ($name == 'textinput')
628 || (($name == 'channel') && ($this->_type != 'rss'))) {
629 if ($this->_parse_mode == 'channel') {
630 $this->_get_ChannelData($parser);
632 $this->_parse_mode = 'all';
635 if (!isset($this->_depth[$this->get_parser_id($parser)])) {
636 $this->_depth[$this->get_parser_id($parser)] = '0';
638 $this->_depth[$this->get_parser_id($parser)]++;
639 array_push($this->_tags, $name);
641 if (!isset($this->_cdepth[$this->get_parser_id($parser)])) {
642 $this->_cdepth[$this->get_parser_id($parser)] = '0';
644 $this->_cdepth[$this->get_parser_id($parser)]++;
645 array_push($this->_ctags, $name);
646 } // END _startElement()
649 * Retrives the Channel Data in <rss> File
652 * @author Stefan Saasen <s@fase4.com>
653 * @param mixed $parser a reference to the XML parser calling the handler.
654 * @see _output, _display_opt, _citem
656 function _get_ChannelData ($parser) {
657 $this->_citem['link'] = trim($this->_citem['link']);
658 if (($this->_display_opt['sitelink'] == $this->_citem['link']) && (!empty($this->_display_opt['reflink'])) && (!empty($this->_display_opt['refid'])))
660 $this->_citem['link'] .= $this->_display_opt['reflink'].$this->_display_opt['refid'];
663 if (empty($this->_display_opt['channel']) ||
664 $this->_display_opt['channel'] != 'hidden') {
665 $this->_output .= "<tr><td>\n";
666 $this->_output .= "<table border=\"0\" width=\"100%\" class=\"fase4_rdf_meta\" cellspacing=\"5\" cellpadding=\"2\">\n";
667 $this->_output .= "<tr><td class=\"fase4_rdf_main_title\"><div class=\"fase4_rdf_main_title\">".htmlspecialchars($this->_citem['title'])."</div></td></tr>\n";
668 $this->_output .= "<tr><td class=\"fase4_rdf\">".strip_tags($this->_citem['description'], '<a>, <img>')."</td></tr>\n";
669 $this->_output .= "<tr><td> </td></tr>\n";
670 $this->_output .= "<tr><td class=\"fase4_rdf\">\n";
671 if (isset($this->_display_opt['build']) && $this->_display_opt['build'] != 'hidden') {
672 if ($this->_citem['lastBuildDate']) { $this->_output .= 'build: '. $this->_citem['lastBuildDate'].'<br />';}
674 if (isset($this->_display_opt['cache_update']) && $this->_display_opt['cache_update'] != 'hidden' && ($_update = $this->get_cache_update_time())) {
675 $this->_output .= 'cache update: '.$_update."<br />\n";
677 $this->_output .= "<a href=\"".$this->_citem['link']."\" ";
678 if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
679 $this->_output .= ">".$this->_cut_string($this->_citem['link']) . '</a>';
680 $this->_output .= "</td></tr>\n";
681 $this->_output .= "<tr><td><hr noshade width=\"100%\" size=\"1\"></td></tr>\n";
682 $this->_output .= "</table></td></tr>";
684 $this->_array_channel = array(
685 'title' => $this->_citem['title'],
686 'link' => $this->_citem['link'],
687 'description' => $this->_citem['description'],
688 'lastBuildDate' => $this->_citem['lastBuildDate']);
692 * XML Parser End Element Handler
695 * @author Stefan Saasen <s@fase4.com>
696 * @param mixed $parser a reference to the XML parser calling the handler.
697 * @param string $name contains the name of the element for which this handler is called.
698 * @see _clear_Items(), _type, _parse_mode, _depth, _tags, _cdepth, _ctags, _item, _output, _display_opt
700 function _endElement ($parser, $name) {
701 array_pop($this->_tags);
702 $this->_depth[$this->get_parser_id($parser)]--;
703 array_pop($this->_ctags);
704 $this->_cdepth[$this->get_parser_id($parser)]--;
705 $this->_item['link'] = trim($this->_item['link']);
706 if ((!empty($this->_display_opt['refid'])) && (!empty($this->_item['link'])))
708 if (!isInString('refid=', $this->_item['link'])) $this->_item['link'] .= '?refid=' . $this->_display_opt['refid'];
712 if (empty($this->_max_count) || $this->_item_count < $this->_max_count) {
713 if ($this->_item['title'] != $this->_item['description']
714 && $this->_item['description']) {
716 // word-wrapping added by Roland Haeder <webmaster@mxchange.org>
717 if (($this->_word_wrap > 0) && (strlen($this->_item['description']) > $this->_word_wrap))
719 // Switch off _use_nl2br
720 $this->_use_nl2br = FALSE;
721 // First remove all \n
722 $this->_item['description'] = str_replace('\n', ' ', $this->_item['description']);
723 // Wrap with <br />\n
724 $this->_item['description'] = wordwrap($this->_item['description'], $this->_word_wrap, "*<br />\n");
726 elseif (($this->_word_wrap == '0') && (!$this->_use_nl2br))
728 // Strip tags out instead when word-wrap is disabled
729 $this->_item['description'] = strip_tags($this->_item['description'], '<a>, <img>');
732 // nl2br added by Roland Haeder <webmaster@mxchange.org>
733 if ($this->_use_nl2br) $this->_item['description'] = nl2br($this->_item['description']);
735 $this->_output .= "<tr><td class=\"fase4_rdf_title\"><div class=\"fase4_rdf_title\"><a class=\"fase4_rdf_title\" href=\"".$this->_item['link']."\" ";
736 if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
737 $this->_output .= ">".strip_tags($this->_item['title'], '<a>, <img>').'</a> ('.$this->_item['pubDate'].")</div></td></tr>\n";
738 $this->_output .= "<tr><td class=\"fase4_rdf\">".$this->_item['description']."</td></tr>\n";
739 // we just display the <hr> if there is a description
740 $this->_output .= "<tr><td><hr noshade=\"noshade\" size=\"1\" /></td></tr>\n";
742 $this->_output .= "<tr><td class=\"fase4_rdf\">\n";
743 $this->_output .= "<a href=\"".$this->_item["link"]."\" ";
744 if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
745 $this->_output .= ">".$this->_item["title"]."</a></td></tr>\n";
748 $this->_array_item[] = array(
749 'title' => $this->_item['title'],
750 'link' => $this->_item['link'],
751 'description' => $this->_item['description']
754 ++$this->_item_count;
756 $this->_clear_Items();
760 if (isset($this->_display_opt['image']) && ($this->_display_opt['image'] != 'hidden') && $this->_item['url']) {
761 $this->_output .= "<tr><td class=\"fase4_rdf\">\n";
762 $this->_output .= "<a href=\"".$this->_item['link']."\" ";
763 if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
764 $this->_output .= "><img src=\"".$this->_item['url']."\"";
765 if (isset($this->_item['width']) && isset($this->_item['height'])) {
766 $this->_output .= " width=\"".$this->_item['width']."\" height=\"".$this->_item['height']."\"";
768 $this->_output .= " alt=\"".$this->_item['title']."\" border=\"0\" /></a></td></tr>\n";
770 $this->_array_image[] = array(
771 'url' => $this->_item['url'],
772 'link' => $this->_item['link'],
773 'width' => $this->_item['width'],
774 'height' => $this->_item['height']
776 $this->_clear_Items();
777 } elseif (isset($this->_display_opt['image']) && ($this->_display_opt['image'] == 'hidden')) {
778 $this->_clear_Items();
784 if (isset($this->_display_opt['channel']) && $this->_display_opt['channel'] != 'hidden' && $this->_item['title'] != '') {
785 $this->_output .= "<tr><td>\n";
786 $this->_output .= "<table border=\"0\" width=\"100%\" class=\"fase4_rdf_meta\" cellspacing=\"5\" cellpadding=\"2\">\n";
787 $this->_output .= "<tr><td class=\"fase4_rdf\"><div class=\"fase4_rdf_title\">".htmlspecialchars($this->_item['title'])."</div></td></tr>\n";
788 $this->_output .= "<tr><td class=\"fase4_rdf\">".strip_tags($this->_item['description'], '<a>, <img>')."</td></tr>\n";
789 $this->_output .= "<tr><td> </td></tr>\n";
790 $this->_output .= "<tr><td class=\"fase4_rdf\">\n";
791 if ($this->_display_opt['build'] != 'hidden') {
792 if ($this->_item['lastBuildDate']) { $this->_output .= 'build: '. $this->_item['lastBuildDate'].'<br />';}
794 if ($this->_display_opt['cache_update'] != 'hidden' && ($_update = $this->get_cache_update_time())) {
795 $this->_output .= 'cache update: '.$_update."<br />\n";
797 $this->_output .= "<a href=\"".$this->_item['link']."\" ";
798 if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
799 $this->_output .= ">".$this->_cut_string($this->_item['link'])."</a>\n";
800 $this->_output .= "</td></tr>\n";
801 $this->_output .= "</table></td></tr>\n";
803 $this->_array_channel = array(
804 'title' => $this->_item['title'],
805 'link' => $this->_item['link'],
806 'description' => $this->_item['description'],
807 'lastBuildDate' => $this->_item['lastBuildDate']
809 $this->_clear_Items();
810 $this->_clear_cItems();
814 if (isset($this->_display_opt['textinput']) && ($this->_display_opt['textinput'] != 'hidden') && $this->_item['name'] && $this->_item['link']) {
815 $this->_output .= "<tr><td class=\"fase4_rdf\">\n";
816 $this->_output .= "<form accept-charset=\"UTF-8\" action=\"".$this->_item['link']."\" ";
817 if (isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
818 $this->_output .= "method=\"get\">\n";
819 $this->_output .= "<div class=\"fase4_rdf_title\">".$this->_item['title']."</div>";
820 $this->_output .= strip_tags($this->_item['description'], '<a>, <img>')."<br /><br />\n";
821 $this->_output .= "<input class=\"fase4_rdf_input\" type=\"text\" name=\"".$this->_item['name']."\"> \n";
822 $this->_output .= "<input class=\"fase4_rdf_input\" type=\"submit\" value=\"go\">";
823 $this->_output .= "</form>\n";
824 $this->_output .= "</td></tr>\n";
825 $this->_array_textinput = array(
826 'title' => $this->_item['title'],
827 'name' => $this->_item['name'],
828 'link' => $this->_item['link'],
829 'description' => $this->_item['description']
831 $this->_clear_Items();
832 } elseif (isset($this->_display_opt['textinput']) && ($this->_display_opt['textinput'] == 'hidden')) {
833 $this->_clear_Items();
841 * This Method returns the data from the <channel /> paragraph.
844 * @author Stefan Saasen <s@fase4.com>
846 * @see _array_channel
848 function get_array_channel () {
849 return $this->_array_channel;
853 * This Method returns the data from each <item /> paragraph.
856 * @author Stefan Saasen <s@fase4.com>
860 function get_array_item () {
861 return $this->_array_item;
865 * This Method returns the data from <textinput />.
868 * @author Stefan Saasen <s@fase4.com>
870 * @see _array_textinput
872 function get_array_textinput () {
873 return $this->_array_textinput;
877 * Getter for parser id from resource
880 * @author Roland Haeder <webmaster@mxchange.org>
883 function get_parser_id ($parser) {
888 if (is_resource($parser)) {
889 // Cast the resource into id
898 * This Method returns the data from <image />.
901 * @author Stefan Saasen <s@fase4.com>
905 function get_array_image() {
906 return $this->_array_image;
910 * XML Parser Data Handler
913 * @author Stefan Saasen <s@fase4.com>
914 * @param mixed $parser a reference to the XML parser calling the handler.
915 * @param string $text contains the character data as a string.
916 * @see _parse_mode, _item, _tags, _depth, _citem, _ctags, _cdepth
918 function _parseData($parser, $text) {
919 // Deocing mode added by Roland Haeder <webmaster@mxchange.org>
920 switch ($this->_decoding_mode) {
922 $text = utf8_decode($text);
926 $text = htmlentities($text);
930 $clean = preg_replace("/\s/", '', $text);
932 $text = preg_replace("/^\s+/", '', $text)."\n";
933 if ($this->_parse_mode == 'all') {
934 if (isset($this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]]) &&
935 $this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]]) {
936 $this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]] .= $text;
938 $this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]] = $text;
940 } elseif (isset($this->_parse_mode) && $this->_parse_mode == 'channel') {
941 if (isset($this->_citem[$this->_ctags[$this->_cdepth[$this->get_parser_id($parser)]]])) {
942 $this->_citem[$this->_ctags[$this->_cdepth[$this->get_parser_id($parser)]]] .= $text;
944 $this->_citem[$this->_ctags[$this->_cdepth[$this->get_parser_id($parser)]]] = $text;
951 * This Method allows you to choose if specific Parameters are displayed or not. These are:
952 * image, channel, textinput, build and cache_update. If set to "hidden" those elements won't be displayed.
955 * @author Stefan Saasen <s@fase4.com>
956 * @param array $options
959 function set_Options ($options = NULL) {
960 if (is_array($options)) {
961 $this->_display_opt = $options;
964 unset($this->_display_opt);
970 * This Method allows you to define the width of the table that holds the representation of the rdf/rss file.
973 * @author Stefan Saasen <s@fase4.com>
974 * @param int $width attribute width in tag <table>
977 function set_table_width ($width = 400) {
978 $this->_table_width = $width;
983 * This Method returns an assocative Array with available Options.
985 * The Keys are the Name of the Options to be set.
986 * The Values are short Description of available Options.
989 * @author Stefan Saasen <s@fase4.com>
990 * @return array $options
993 function get_Options () {
995 'image' => "If 'image' is set to "hidden" no image provided by the RDF Publisher will be displayed.",
996 '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",
997 'textinput' => "If set to "hidden" no Input Form will be displayed",
998 'build' => "If set to "hidden" the Build Date (if provided) of the RDF File will not be displayed",
999 'cache_update' => "If set to "hidden" the Update Date/Time of the cached Rdf File will not be displayed"
1005 * This Method returns the Content of the RDF File in one string. The String actually holds the whole XML Document.
1008 * @author Stefan Saasen <s@fase4.com>
1009 * @param string $rdf RDF File (Location)
1010 * @return string XML Presentation of parsed RDF File
1011 * @see _cached_file, _remote_file, _cache_dir, _refresh, _update_cache()
1014 // checks if the cache directory already exists
1015 // if not, the cache directory will be created
1016 if (!$this->_cache_dir_ok) {
1017 $this->_create_cache_dir();
1020 if ($this->_use_dynamic_display == TRUE) {
1021 $this->_cached_file = md5('dynamic' . $this->salt.$this->_remote_file) . '.rss';
1022 $this->_cache_type = 'normal';
1024 $this->_cached_file = md5($this->salt . $this->_remote_file) . '.rss';
1025 $this->_cache_type = 'fast';
1028 $_cache_f = $this->_cache_dir.$this->_cached_file;
1030 if ((!file_exists($_cache_f)) || (filemtime($_cache_f) < $this->_refresh) || (filesize($_cache_f) == 0)) {
1031 // We have to parse the remote file
1032 $this->_use_cached_file = FALSE;
1033 // --> we want to provide proper Information for Use in
1034 // get_cache_update_time()
1036 if ($this->_use_dynamic_display == TRUE) {
1037 $_rdf = implode(' ', $this->_rdf_data()); // -> proxy
1039 $this->_throw_exception($this->_remote_file.' is not available');
1041 $this->_parse_xRDF($_rdf);
1042 $this->_update_cache($_rdf);
1043 $data = $this->_output;
1045 $_rdf = implode(' ', $this->_rdf_data()); // -> proxy
1047 $this->_throw_exception($this->_remote_file.' is not available');
1049 $this->_parse_xRDF($_rdf);
1050 $this->_update_cache($this->_output);
1051 $data = $this->_output;
1053 } elseif (defined('__SECURITY') && function_exists('readFromFile')) {
1054 // Use readFromFile() from mailer project
1055 $this->_use_cached_file = TRUE;
1056 if ($this->_use_dynamic_display == TRUE) {
1057 $this->_parse_xRDF(readFromFile($_cache_f));
1058 $data = $this->_output;
1060 $data = readFromFile($_cache_f);
1063 // we can use the cached file
1064 $this->_use_cached_file = TRUE;
1065 if ($this->_use_dynamic_display == TRUE) {
1066 $this->_parse_xRDF(implode(' ', file($_cache_f)));
1067 $data = $this->_output;
1069 $data = implode(' ', file($_cache_f));
1073 // Return trimmed data
1078 * This Methods creates the Cache Directory if the specified Directory does not exist.
1081 * @author Stefan Saasen <s@fase4.com>
1082 * @param string $dir Path to Directory.
1084 * @see _cache_dir, _cache_dir_ok
1086 function _create_cache_dir()
1089 if (!is_dir($this->_cache_dir)) {
1090 $arr = explode('/', $this->_cache_dir);
1092 if ($arr[0] == '') {
1095 for($i = '0';$i<$c;$i++) {
1097 $path .= $arr[$i].'/';
1098 if (!is_dir($path)) {
1099 if (!mkdir($path, 0777)) {
1100 $this->_throw_exception("failed to create directory:<b>".$this->_cache_dir."</b>.<br /><br />Exception on Line: ".__LINE__);
1106 $this->_cache_dir_ok = TRUE;
1109 $this->_cache_dir_ok = TRUE;
1112 } // END _create_cache_dir()
1115 * This Method updates the cached RDF Files and synchronises them with their remote Counterparts.
1118 * @author Stefan Saasen <s@fase4.com>
1119 * @param string $rdf RDF File (Location)
1120 * @see _cache_dir, _cached_file, _throw_exception()
1122 function _update_cache ($content = '') {
1123 if (defined('__SECURITY') && function_exists('writeToFile')) {
1124 // Use mailer-project function
1125 return writeToFile($this->_cache_dir.$this->_cached_file, $content);
1128 $_local = @fopen($this->_cache_dir.$this->_cached_file, 'w');
1130 $this->_throw_exception('Cannot open '.$this->_cached_file.'<br /><br />Exception at Line: '.__LINE__);
1134 if (fwrite($_local, $content) === FALSE) {
1135 $this->_throw_exception('Cannot write to '.$this->_cached_file.'<br /<br />Exeception at Line: '.__LINE__);
1140 @chmod($this->_cache_dir.$this->_cached_file, 0666);
1142 } // END _update_cache()
1145 * This Method returns the Date/Time of last Cache Update of the actually parsed RDF File.
1148 * @author Stefan Saasen <s@fase4.com>
1149 * @return string Date/Time of last Update
1150 * @see _cache_dir, _cached_file
1152 function get_cache_update_time () {
1153 return (file_exists($this->_cache_dir.$this->_cached_file))?date('d.m.Y H:i:s', filemtime($this->_cache_dir.$this->_cached_file)):'Cachemiss';
1154 } // END get_cache_update_time()
1157 * This Method returns the Type of Cache that was used ('normal' or 'fast')
1160 * @author Stefan Saasen <s@fase4.com>
1161 * @param string $rdf RDF File (Location)
1162 * @return string Displays RDF Content (using _display())
1163 * @see _remote_file, cache()
1165 function get_CacheType() {
1166 return $this->_cache_type;
1170 * Returns true if cached file was used, otherwise false
1173 * @author Stefan Saasen <s@fase4.com>
1174 * @return array $options
1175 * @see _use_cached_file
1177 function is_cachedFile () {
1178 return $this->_use_cached_file;
1182 * This Method deletes all the cached Files.
1184 * Please keep in mind to use this method just as a 'manual garbage collection'
1185 * You should cache the rss/rdf files locally to avoid unnecessary traffic.
1186 * (Both for your visitors and the Publisher)
1189 * @author Stefan Saasen <s@fase4.com>
1192 function clear_cache () {
1193 $dir = dir($this->_cache_dir);
1194 while($file = $dir->read()) {
1195 // Exclude directories
1196 if (is_file($dir->path . $file) && substr($file, -4, 4) == '.rss') {
1197 if ((defined('__SECURITY') && function_exists('removeFile')) && (!removeFile($dir->path . $file))) {
1198 $this->_throw_exception("removeFile() was unable to unlink ".$dir->path . $file."<br />\n<br />\nException at Line: ".__LINE__);
1200 } elseif (!unlink($dir->path . $file)) {
1201 $this->_throw_exception("Unable to unlink ".$dir->path . $file."<br />\n<br />\nException at Line: ".__LINE__);
1208 } // END clear_cache()
1211 * Cuts the String $string after $str_len and adds '... '
1214 * @param string $string String to be shortened
1215 * @param int $str_len length of the returned String (overall length including '... ')
1216 * @return string Cut String
1218 function _cut_string($string, $str_len = '30')
1220 if (strlen(trim($string))>$str_len) {
1221 $string = substr(trim($string) , 0, $str_len - 4);
1225 } // END _cut_string()
1228 * this Method implements simple Garbage Collection
1231 * @author Stefan Saasen <s@fase4.com>
1232 * @see _cache_dir, gc_probability, gc_maxlifetime
1234 function _garbage_collection()
1236 srand((double) microtime() * 1000000);
1237 if (mt_rand(1, 100) <= $this->gc_probability) {
1238 $dir = dir($this->_cache_dir);
1239 while($file = $dir->read()) {
1240 if ((is_file($dir->path . $file)) && (substr($file, -4, 4) == '.rss') && (filemtime($dir->path . $file) <= time() - $this->_refresh)) {
1241 if (defined('__SECURITY') && function_exists('removeFile')) {
1242 // Use mailer-project's function
1243 removeFile($dir->path . $file);
1245 // Use PHP's function
1246 unlink($dir->path . $file);
1254 /* ==== Proxy/Auth methods ==== */
1257 * this method sets a proxy server
1260 * @param string $phost Proxy Host
1261 * @param string $pport Prox Port
1262 * @author Marco Kraus <marco.kraus@siemens.com>
1264 function set_proxy($phost, $pport)
1266 $this->_use_proxy = TRUE;
1269 $this->_phost = $phost;
1272 $this->_pport = $pport;
1276 * this method sets a proxy server authentification
1279 * @param string $pname Username
1280 * @param string $ppaswd Password
1281 * @author Marco Kraus <marco.kraus@siemens.com>
1283 function set_proxy_auth($pname, $ppasswd)
1285 $this->_use_proxy_auth = TRUE;
1288 $this->_pname = $pname;
1291 $this->_ppasswd = $ppasswd;
1296 * gets _remote_file into an array
1298 * needed, cause if you use a proxy, you have to open
1299 * a raw-tcp-socket to get the data
1302 * @author Marco Kraus <Marco.Kraus@siemens.com>
1304 * @see _use_proxy, cache()
1306 function _rdf_data () {
1310 // Use mailer-project's function or own code?
1311 if (defined('__SECURITY') && function_exists('sendHttpGetRequest')) {
1312 // Use mailer-project instead (see http://mxchange.org)
1313 $output = sendHttpGetRequest($this->_remote_file, array(), TRUE);
1314 } elseif ($this->_use_proxy == TRUE) {
1315 // we need a raw socket here to connect to proxy
1316 $fp = fsockopen($this->_phost,$this->_pport);
1319 $this->_throw_exception($this->_remote_file.' is not available with proxy');
1321 if ($this->_use_proxy_auth == TRUE) {
1322 fputs($fp, "GET ".$this->_remote_file." HTTP/1.0\r\nUser-Agent: Fase4 RDF-Reader/1.40 modified by Quix0r\r\n\r\n");
1324 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");
1329 for ($i = '0'; !feof ($fp) ; $i++)
1331 $usable_data[$i] = '';
1332 $usable_data[$i] = fgets($fp,4096);
1334 // PARSE HEADER ---- first line has to be <?xml, second rdf or rss, and third is blank
1336 // strstr did not fit (ask Rasmus why), so we compare each character
1337 if (($usable_data[$i][0] == '<') &&
1338 ($usable_data[$i][1] == '?') &&
1339 ($usable_data[$i][2] == 'x') &&
1340 ($usable_data[$i][3] == 'm') &&
1341 ($usable_data[$i][4] == 'l')) {
1342 $usable_data[0] = $usable_data[$i]; // save current field
1343 $i = 1; // just reset array to start
1346 // there seems to be proxystuff after the <?xml....we delete this
1348 ($usable_data[$i][0] == '<') &&
1349 ($usable_data[$i][1] == 'r') &&
1350 ($usable_data[$i][2] == 'd') &&
1351 ($usable_data[$i][3] == 'f') &&
1352 ($usable_data[$i][4] == ':')
1356 ($usable_data[$i][0] == '<') &&
1357 ($usable_data[$i][1] == 'r') &&
1358 ($usable_data[$i][2] == 's') &&
1359 ($usable_data[$i][3] == 's')
1363 $usable_data[1] = $usable_data[$i]; // save current field
1364 $usable_data[2] = "\n";
1365 $i = 2; // just reset array to start
1370 $output = $usable_data;
1372 if (substr($this->_remote_file, 0, 7) != 'http://') {
1373 $this->_throw_exception('Cannot find http:// in '.$this->_remote_file.'!');
1376 // Extract host information
1377 $host = substr($this->_remote_file, 7);
1379 // Extract the GET part
1381 if (strpos($host, '/') > 0) {
1382 $get = substr($host, strpos($host, '/'));
1383 $host = substr($host, 0, strpos($host, '/'));
1388 if (strpos($host, ':') > 0) {
1389 $port = substr($host, (strpos($host, ':') + 1));
1390 $host = substr($host, 0, (strpos($host, ':') - 1));
1393 // Start connection to server
1394 $fp = fsockopen($host, $port);
1396 $this->_throw_exception($this->_remote_file.' is maybe not available.');
1400 // Repare request line
1401 $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);
1404 fputs($fp, $request);
1405 $reply = ''; $isContent = FALSE; $dummy = '';
1409 while (!feof($fp)) {
1410 $read = trim(fgets($fp, 4096));
1411 if (substr($read, 0, 5) == '<?xml' || $isContent) {
1423 if ((count($dummy) > 0) && (count($reply) == 0) && (!$isContent)) {
1424 // Transfer content from dummy
1429 //die(htmlentities($reply));
1436 } // END _rdf_data()