c74eada6fbed6715bc17f71af1c8dd9dc4aaa895
[mailer.git] / inc / classes / rdf.class.php
1 <?php
2 /* $Id$ */
3
4 //
5 // +----------------------------------------------------------------------+
6 // | rss Parser                                                           |
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/                                          |
13 // |                                                                      |
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 // +----------------------------------------------------------------------+
19 // |                                                                      |
20 // | Maintainer and initial developer:                                    |
21 // | Stefan Saasen <s@fase4.com>                                          |
22 // |                                                                      |
23 // | Proxy and authentication methods added by:                           |
24 // | Marco Kraus <marco.kraus@siemens.com>                                |
25 // |                                                                      |
26 // | Decoding of data by htmlentities or utf8_decode added by:            |
27 // | Roland Haeder <webmaster@mxchange.org>                               |
28 // |                                                                      |
29 // +----------------------------------------------------------------------+
30 // | Ref:                                                                 |
31 // |   @link http://www.fase4.com/rdf/                   Latest release   |
32 // +----------------------------------------------------------------------+
33
34 /**
35  * Class RSS Parser
36  *
37  * This class offers methods to parse RSS Files
38  *
39  * @link      http://www.fase4.com/rdf/ Latest release of this class
40  * @package   rss
41  * @copyright Copyright (c) 2001 fase4.com. All rights reserved.
42  * @author    Stefan Saasen <s@fase4.com>
43  * @author    Roland Haeder <webmaster@mxchange.org>
44  * @version   1.7 ($Date$Revision: 856 $
45  * @access    public
46  */
47
48 class fase4_rdf {
49
50         /**
51          * Word-wrapping mode for description, set it to 0 do disable this feature! Ommits _use_nl2br!
52          *
53          * @access private
54          * @var    integer
55          */
56         var $_word_wrap = '0';
57
58         /**
59          * Wether to recode \n -> <br /> or not in description
60          *
61          * @access private
62          * @var    boolean
63          */
64         var $_use_nl2br = true;
65
66         /**
67          * Sets the decoding mode of the read data (UTF8 scrambles some german umlauts here!)
68          *
69          * "htmlentities" - Use the function htmlentities()
70          * "utf8_decode"  - Use the function ut8_decode() when you have UTF8 encoded text
71          *
72          * @access private
73          * @var    string
74          */
75         var $_decoding_mode = 'utf8_decode';
76
77         /**
78          * If $_link_target is set a target='xxx' attribute in each <a /> and <form accept-charset="utf-8" /> html tag will be added
79          *
80          * Possible values are "_blank", "_content", "_parent", "_self", "_top"
81          *
82          * @access private
83          * @var    string
84          */
85         var $_link_target = '_blank';
86
87         /**
88          * vars for proxy settings - Prox Host
89          *
90          * @access private
91          * @var      string
92          */
93         var $_phost = '';
94
95         /**
96          * vars for proxy settings - Prox Port
97          *
98          * @access private
99          * @var      string
100          */
101         var $_pport = '';
102
103         /**
104          * vars for proxy settings - Prox Username
105          *
106          * @access private
107          * @var      string
108          */
109         var $_pname = '';
110
111         /**
112          * vars for proxy settings - Prox Password
113          *
114          * @access private
115          * @var      string
116          */
117         var $_ppasswd = '';
118
119         /**
120          * just a flag for checking if proxy-support should be enabled
121          * set default to false (will be enabled if set_proxy is called)
122          *
123          * @access   private
124          * @see      set_proxy()
125          * @var      bool
126          */
127         var $_use_proxy = false;
128
129         /**
130          * just a flag for checking if proxy-support with authentication
131          * should be enabled
132          * set default to false (will be enabled if set_proxy is called)
133          *
134          * @access   private
135          * @see      set_proxy()
136          * @var      boolean
137          */
138         var $_use_proxy_auth = false;
139
140         /**
141          * The time the Files will be cached (in seconds).
142          *
143          * @access private
144          * @var    int
145          */
146         var $_refresh = 60;   // int
147
148         /**
149          * The Name of the cached File.
150          *
151          * @access private
152          * @var    string
153          */
154         var $_cached_file = '';   // String
155
156         /**
157          * Indicates whether the cached or the remote file was used.
158          *
159          * @access private
160          * @var    boolean
161          */
162         var $_use_cached_file = true;
163
164         /**
165          * (fast|normal) depends on _use_dynamic_display(). _use_dynamic_display( TRUE ) -> 'normal', otherwise 'fast'
166          *
167          * @access private
168          * @var    string
169          */
170         var $_cache_type = 'fast';
171
172         /**
173          * The Name of the Remote File.
174          *
175          * @access private
176          * @var    string
177          */
178         var $_remote_file = '';
179
180         /**
181          * Path to the Cache Directory.
182          *
183          * @access private
184          * @var    string
185          */
186         var $_cache_dir = 'cache/';  // String
187
188         /**
189          * Indicates whether the Creating of the Cache Directory needs to be done or not.
190          *
191          * @access private
192          * @var    boolean
193          */
194         var $_cache_dir_ok = false;
195
196         /**
197          * Type of the file to be parsed (RSS or RDF).
198          *
199          * The Type depends on the root node
200          *
201          * @access private
202          * @var    string
203          */
204         var $_type = 'rss'; // string (rss or rdf)
205
206         /**
207          * Array of Display Settings.
208          *
209          * Specific Parameters can be set to hidden. These are:
210          * image, channel and textinput. If set to "hidden" those elements won't be displayed.
211          *
212          * @access private
213          * @var    array
214          */
215         var $_display_opt = array(
216                 'build'        => '',
217                 'image'        => '',
218                 'channel'      => '',
219                 'textinput'    => '',
220                 'cache_update' => '',
221                 'sitelink'     => '',
222                 'refid'        => '',
223                 'reflink'      => '',
224         );
225
226         /**
227          * Defines the width attribute in the table that holds the rdf/rss representation
228          *
229          * @access private
230          * @var    int
231          * @see    see_table_width()
232          */
233         var $_table_width = '100%';
234
235         /**
236          * Indicates whether or not to use dynamic Display Settings
237          *
238          * @access private
239          * @var    array
240          */
241         var $_use_dynamic_display = false;
242
243         /**
244          * <item> count
245          *
246          * @access private
247          * @var    int
248          */
249         var $_item_count = '0';
250
251         /**
252          * No of max <item>s
253          *
254          * @access private
255          * @var    boolean
256          */
257         var $_max_count = false;
258
259         /**
260          * Array containing the content of <channel />
261          *
262          * @access private
263          * @var    array
264          */
265         var $_array_channel = array();
266
267         /**
268          * Array containing the content of each <item />
269          *
270          * @access private
271          * @var    array
272          */
273         var $_array_item = array();
274
275         /**
276          * Array containing the content of <textinput />
277          *
278          * @access private
279          * @var    array
280          */
281         var $_array_textinput = array();
282
283         /**
284          * Array containing the content of <image />
285          *
286          * @access private
287          * @var    array
288          */
289         var $_array_image = array();
290
291         /**
292          * Array containing the Channel content. Just For internal XML Parser Purposes.
293          *
294          * @access private
295          * @var    array
296          */
297         var $_citem = array();
298
299         /**
300          * Array containing the Channel Parser Depth. Just For internal XML Parser Purposes.
301          *
302          * @access private
303          * @var    array
304          */
305         var $_cdepth = array();
306
307         /**
308          * Array containing the Channel tags. Just For internal XML Parser Purposes.
309          *
310          * @access private
311          * @var    array
312          */
313         var $_ctags = array( 'x' );
314
315         /**
316          * Array containing the Channel content. Just For internal XML Parser Purposes.
317          *
318          * @access private
319          * @var    array
320          */
321         var $_item = array();   // Array
322
323         /**
324          * Array containing the Channel Parser Depth. Just For internal XML Parser Purposes.
325          *
326          * @access private
327          * @var    array
328          */
329         var $_depth = array();  // Array
330
331         /**
332          * Array containing the tags. Just For internal XML Parser Purposes.
333          *
334          * @access private
335          * @var    array
336          */
337         var $_tags = array( 'x' );  // Array
338
339         /**
340          * Garbage collection: probability in percent
341          *
342          * @var      integer     0 => never
343          * @access   public
344          */
345         var $gc_probability = 1;
346
347         /**
348          * HTML Output
349          *
350          * @var      string
351          * @access   private
352          */
353         var $_output = '';
354
355         /**
356          * @var  string
357          */
358         var $_parse_mode = '';
359
360         // Output variable
361         var $out = '';
362
363         // Salt for hashing
364         var $salt = '';
365
366         /**
367          * Constructor of our Class
368          *
369          * This Method checks if the Cache Directory can be found. Otherwise it tries to creat the Cache Directory at the specified Path.
370          * Additionally the Refresh Time is set to a default Value of 1200s (20 min).
371          *
372          * @access    public
373          * @author    Stefan Saasen <s@fase4.com>
374          * @see          _refresh
375          */
376         function fase4_rdf()
377         {
378                 // default Value, to be overwritten in set_refresh()
379                 $this->_refresh = (time() - 1200);
380                 $this->_clear_cItems();
381                 $this->_clear_Items();
382         }
383
384         /**
385          * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
386          *
387          * @access    public
388          * @author    Stefan Saasen <s@fase4.com>
389          * @param     string $rdf    RDF File (Location)
390          * @return    string Displays RDF Content ( using _display() )
391          * @see          _remote_file, cache()
392          */
393         function parse_RDF( $rdf )
394         {
395                 unset($this->_array_item);
396                 $this->_remote_file = $rdf;
397                 $this->out .= "<!-- http://www.fase4.com/rdf/ -->";
398                 $this->out .= "<table width=\"".$this->_table_width."\">";
399                 $this->out .= $this->cache();
400                 $this->out .= "</table>";
401                 $this->_output = '';
402                 $this->_item_count = '0';
403                 return true;
404         }
405
406         /**
407          * This Method is called when all parsing is finished to use the garbage collection
408          *
409          * @access    public
410          * @author    Stefan Saasen <s@fase4.com>
411          * @param     string $rdf    RDF File (Location)
412          * @return    string Displays RDF Content ( using _display() )
413          * @see          _remote_file, cache()
414          */
415         function finish($return = false)
416         {
417                 $this->out = str_replace('$', '&#36;', $this->out);
418
419                 if (!$return) {
420                         echo $this->out;
421                 } else {
422                         return $this->out;
423                 }
424                 $this->_garbage_collection();
425         }
426
427         /**
428          * With this method you can decide whether to use the normal cache and dynamic display Options or to use a static cache.
429          *
430          * 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.
431          * In this case you can not modify the display settings.
432          * processing time: ( 1.4792) --> remote file
433          * processing time: ( 0.0313) --> using 'normal cache' with display Modification turned on.
434          * processing time: ( 0.0019) --> using 'fast cache'
435          *
436          * @access    public
437          * @author    Stefan Saasen <s@fase4.com>
438          * @param     string $rdf    RDF File (Location)
439          * @return    string Displays RDF Content ( using _display() )
440          * @see          _remote_file, cache()
441          */
442         function use_dynamic_display( $bool )
443         {
444                 $this->_use_dynamic_display = $bool;
445                 return true;
446         }
447
448         /**
449          * This Method avtually parses the XML data.
450          *
451          * @access    private
452          * @author    Stefan Saasen <s@fase4.com>
453          * @param     string $data    RDF File XML Data
454          * @see       _clear_Items()
455          */
456         function _parse_xRDF( $data )
457         {
458                 $this->_clear_Items();
459                 $xml_parser = xml_parser_create();
460                 xml_set_object($xml_parser,$this);
461                 xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
462                 xml_set_element_handler($xml_parser, '_startElement', '_endElement');
463                 xml_set_character_data_handler($xml_parser, '_parseData');
464                 if (!xml_parse($xml_parser, trim($data))) {
465                         $this->_throw_exception(sprintf("XML error: %s at line %d",
466                         xml_error_string(xml_get_error_code($xml_parser)),
467                         xml_get_current_line_number($xml_parser)).'<br /><br />Exception in function parse_RDF().');
468                 }
469                 xml_parser_free($xml_parser);
470         }
471
472
473         /**
474          * This Methods allows you to set the Refresh Time
475          *
476          * @access    public
477          * @author    Stefan Saasen <s@fase4.com>
478          * @param     int $seconds time files will be cached (in seconds).
479          * @return       boolean
480          * @see          _refresh
481          */
482         function set_refresh( $seconds )
483         {
484                 $this->_refresh = (time() - $seconds);
485                 return true;
486         }
487
488         function set_salt( $saltPara )
489         {
490                 $this->salt = $saltPara;
491                 return true;
492         }
493
494         /**
495          * This Methods allows you to set the No. of <item>s to display
496          *
497          * @access    public
498          * @param     int $int No of max <item>s
499          * @author    Stefan Saasen <s@fase4.com>
500          * @return       boolean
501          * @see          _max_count, _endElement()
502          */
503         function set_max_item( $int )
504         {
505                 $this->_max_count = $int;
506                 return true;
507         }
508
509         /**
510          * This Methods allows you to set the Cache Directory
511          *
512          * @access    public
513          * @author    Stefan Saasen <s@fase4.com>
514          * @param     string $dir Path to Directory.
515          * @return       boolean
516          * @see          _cache_dir
517          */
518         function set_CacheDir( $dir )
519         {
520                 if(substr($dir, -1) != '/') {
521                         $dir = $dir.'/';
522                 }
523                 $this->_cache_dir = $dir;
524         }
525
526         /**
527          * This Method displays Error Messages and terminates the Execution of the Script
528          *
529          * @access    private
530          * @param     string $msg Message to display on failure
531          * @author    Stefan Saasen <s@fase4.com>
532          */
533         function _throw_exception( $msg )
534         {
535                 $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>";
536                 return true;
537         }
538
539         /**
540          * This Method clears the Array containig the Items.
541          *
542          * @access    private
543          * @author    Stefan Saasen <s@fase4.com>
544          * @see       _item
545          */
546         function _clear_Items( ) {
547                 $this->_item = array(
548                         'title'         => '',
549                         'link'          => '',
550                         'description'   => '',
551                         'url'           => '',
552                         'language'      => '',
553                         'pubDate'       => '',
554                         'lastBuildDate' => '',
555                         'width'         => '',
556                         'height'        => ''
557                 );
558         }
559         /**
560          * This Method clears the Array containig the Channel Items.
561          *
562          * @access    private
563          * @author    Stefan Saasen <s@fase4.com>
564          * @see       _item
565          */
566         function _clear_cItems( ) {
567                 $this->_citem = array(
568                         'title'          => '',
569                         'link'           => '',
570                         'description'    => '',
571                         'url'            => '',
572                         'language'       => '',
573                         'copyright'      => '',
574                         'managingEditor' => '',
575                         'webMaster'      => '',
576                         'pubDate'        => '',
577                         'lastBuildDate'  => '',
578                         'category'       => '',
579                         'generator'      => '',
580                         'docs'           => '',
581                         'cloud'          => '',
582                         'ttl'            => '',
583                         'image'          => '',
584                         'textinput'      => '',
585                         'skipHours'      => '',
586                         'skipDays'       => '',
587                         'sitelink'       => '',
588                         'refid'          => '',
589                         'reflink'        => '',
590                 );
591         }
592
593         /**
594          * XML Parser Start Element Handler
595          *
596          * @access    private
597          * @author    Stefan Saasen <s@fase4.com>
598          * @param     mixed  $parser a reference to the XML parser calling the handler.
599          * @param     string $name contains the name of the element for which this handler is called.
600          * @param     string $attrs contains an associative array with the element's attributes (if any).
601          * @see          _get_ChannelData(), _clear_Items(), _type, _parse_mode, _depth, _tags, _cdepth, _ctags
602          */
603         function _startElement($parser, $name, $attrs) {
604                 // We have to determine, which type of xml data we have to parse
605                 if($name == 'rss') {
606                         $this->_type = 'rss';
607                 } elseif($name == 'rdf:RDF' OR $name == 'rdf') {
608                         $this->_type = 'rdf';
609                 }
610
611
612                 if ( $name == 'channel' AND $this->_type != 'rdf' ) {
613                         $this->_parse_mode = 'channel';
614                 } elseif ( ($name=='item')
615                 ||($name=='image')
616                 ||($name=='textinput')
617                 ||(($name=='channel') && ($this->_type != 'rss')) ) {
618                         if($this->_parse_mode=='channel') {
619                                 $this->_get_ChannelData( $parser );
620                         }
621                         $this->_parse_mode = 'all';
622                 }
623
624                 if( !isset( $this->_depth[$this->get_parser_id($parser)] ) ) {
625                         $this->_depth[$this->get_parser_id($parser)] = '0';
626                 }
627                 $this->_depth[$this->get_parser_id($parser)]++;
628                 array_push($this->_tags, $name);
629
630                 if( !isset( $this->_cdepth[$this->get_parser_id($parser)] ) ) {
631                         $this->_cdepth[$this->get_parser_id($parser)] = '0';
632                 }
633                 $this->_cdepth[$this->get_parser_id($parser)]++;
634                 array_push($this->_ctags, $name);
635         }   // END _startElement()
636
637         /**
638          * Retrives the Channel Data in <rss> File
639          *
640          * @access    private
641          * @author    Stefan Saasen <s@fase4.com>
642          * @param     mixed  $parser a reference to the XML parser calling the handler.
643          * @see          _output, _display_opt, _citem
644          */
645         function _get_ChannelData( $parser )
646         {
647                 $this->_citem['link'] = trim($this->_citem['link']);
648                 if (($this->_display_opt['sitelink'] == $this->_citem['link']) && (!empty($this->_display_opt['reflink'])) && (!empty($this->_display_opt['refid'])))
649                 {
650                         $this->_citem['link'] .= $this->_display_opt['reflink'].$this->_display_opt['refid'];
651                 }
652
653                 if( empty($this->_display_opt['channel']) OR
654                 $this->_display_opt['channel'] != 'hidden') {
655                         $this->_output .= "<tr><td>\n";
656                         $this->_output .= "<table border=\"0\" width=\"100%\" class=\"fase4_rdf_meta\" cellspacing=\"5\" cellpadding=\"2\">\n";
657                         $this->_output .= "<tr><td class=\"fase4_rdf_main_title\"><div class=\"fase4_rdf_main_title\">".htmlspecialchars($this->_citem['title'])."</div></td></tr>\n";
658                         $this->_output .= "<tr><td class=\"fase4_rdf\">".strip_tags($this->_citem['description'], '<a>, <img>')."</td></tr>\n";
659                         $this->_output .= "<tr><td>&nbsp;</td></tr>\n";
660                         $this->_output .= "<tr><td class=\"fase4_rdf\">\n";
661                         if(isset($this->_display_opt['build']) && $this->_display_opt['build'] != 'hidden') {
662                                 if($this->_citem['lastBuildDate']){$this->_output .= 'build: '. $this->_citem['lastBuildDate'].'<br />';}
663                         }
664                         if(isset($this->_display_opt['cache_update']) && $this->_display_opt['cache_update'] != 'hidden' && ( $_update = $this->get_cache_update_time()) ) {
665                                 $this->_output .= 'cache update: '.$_update."<br />\n";
666                         }
667                         $this->_output .= "<a href=\"".$this->_citem['link']."\" ";
668                         if(isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
669                         $this->_output .= ">".$this->_cut_string($this->_citem['link']) . '</a>';
670                         $this->_output .= "</td></tr>\n";
671                         $this->_output .= "<tr><td><hr noshade width=\"100%\" size=\"1\"></td></tr>\n";
672                         $this->_output .= "</table></td></tr>";
673                 }
674                 $this->_array_channel = array(
675                         'title'         => $this->_citem['title'],
676                         'link'          => $this->_citem['link'],
677                         'description'   => $this->_citem['description'],
678                         'lastBuildDate' => $this->_citem['lastBuildDate']);
679         }
680
681         /**
682          * XML Parser End Element Handler
683          *
684          * @access    private
685          * @author    Stefan Saasen <s@fase4.com>
686          * @param     mixed  $parser a reference to the XML parser calling the handler.
687          * @param     string $name contains the name of the element for which this handler is called.
688          * @see          _clear_Items(), _type, _parse_mode, _depth, _tags, _cdepth, _ctags, _item, _output, _display_opt
689          */
690         function _endElement($parser, $name) {
691                 array_pop($this->_tags);
692                 $this->_depth[$this->get_parser_id($parser)]--;
693                 array_pop($this->_ctags);
694                 $this->_cdepth[$this->get_parser_id($parser)]--;
695                 $this->_item['link'] = trim($this->_item['link']);
696                 if ((!empty($this->_display_opt['refid'])) && (!empty($this->_item['link'])))
697                 {
698                         if (!isInString('refid=', $this->_item['link'])) $this->_item['link'] .= '?refid=' . $this->_display_opt['refid'];
699                 }
700                 switch ($name) {
701                         case 'item':
702                                 if(empty($this->_max_count) OR $this->_item_count < $this->_max_count) {
703                                         if($this->_item['title'] != $this->_item['description']
704                                         AND $this->_item['description']) {
705
706                                                 // word-wrapping added by Roland Haeder <webmaster@mxchange.org>
707                                                 if (($this->_word_wrap > 0) && (strlen($this->_item['description']) > $this->_word_wrap))
708                                                 {
709                                                         // Switch off _use_nl2br
710                                                         $this->_use_nl2br = false;
711                                                         // First remove all \n
712                                                         $this->_item['description'] = str_replace('\n', ' ', $this->_item['description']);
713                                                         // Wrap with <br />\n
714                                                         $this->_item['description'] = wordwrap($this->_item['description'], $this->_word_wrap, "*<br />\n");
715                                                 }
716                                                 elseif (($this->_word_wrap == '0') && (!$this->_use_nl2br))
717                                                 {
718                                                         // Strip tags out instead when word-wrap is disabled
719                                                         $this->_item['description'] = strip_tags($this->_item['description'], '<a>, <img>');
720                                                 }
721
722                                                 // nl2br added by Roland Haeder <webmaster@mxchange.org>
723                                                 if ($this->_use_nl2br) $this->_item['description'] = nl2br($this->_item['description']);
724
725                                                 $this->_output .= "<tr><td class=\"fase4_rdf_title\"><div class=\"fase4_rdf_title\"><a class=\"fase4_rdf_title\" href=\"".$this->_item['link']."\" ";
726                                                 if(isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
727                                                 $this->_output .= ">".strip_tags($this->_item['title'], '<a>, <img>').'</a> ('.$this->_item['pubDate'].")</div></td></tr>\n";
728                                                 $this->_output .= "<tr><td class=\"fase4_rdf\">".$this->_item['description']."</td></tr>\n";
729                                                 // we just display the <hr> if there is a description
730                                                 $this->_output .= "<tr><td><hr noshade=\"noshade\" size=\"1\" /></td></tr>\n";
731                                         } else {
732                                                 $this->_output .= "<tr><td class=\"fase4_rdf\">\n";
733                                                 $this->_output .= "<a href=\"".$this->_item["link"]."\" ";
734                                                 if(isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
735                                                 $this->_output .= ">".$this->_item["title"]."</a></td></tr>\n";
736                                         }
737
738                                         $this->_array_item[] = array(
739                                                 'title'       => $this->_item['title'],
740                                                 'link'        => $this->_item['link'],
741                                                 'description' => $this->_item['description']
742                                         );
743
744                                         ++$this->_item_count;
745                                 }
746                                 $this->_clear_Items();
747                                 break;
748
749                         case 'image':
750                                 if(isset($this->_display_opt['image']) && ($this->_display_opt['image'] != 'hidden') && $this->_item['url']) {
751                                         $this->_output .= "<tr><td class=\"fase4_rdf\">\n";
752                                         $this->_output .= "<a href=\"".$this->_item['link']."\" ";
753                                         if(isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
754                                         $this->_output .= "><img src=\"".$this->_item['url']."\"";
755                                         if(isset($this->_item['width']) && isset($this->_item['height'])) {
756                                                 $this->_output .= " width=\"".$this->_item['width']."\" height=\"".$this->_item['height']."\"";
757                                         }
758                                         $this->_output .= " alt=\"".$this->_item['title']."\" border=\"0\" /></a></td></tr>\n";
759
760                                         $this->_array_image[] = array(
761                                                 'url'    => $this->_item['url'],
762                                                 'link'   => $this->_item['link'],
763                                                 'width'  => $this->_item['width'],
764                                                 'height' => $this->_item['height']
765                                         );
766                                         $this->_clear_Items();
767                                 } elseif( isset($this->_display_opt['image'] ) && ($this->_display_opt['image'] == 'hidden') ) {
768                                         $this->_clear_Items();
769                                 }
770
771                                 break;
772
773                         case 'channel':
774                                 if(isset($this->_display_opt['channel']) AND $this->_display_opt['channel'] != 'hidden' AND $this->_item['title'] != '') {
775                                         $this->_output .= "<tr><td>\n";
776                                         $this->_output .= "<table border=\"0\" width=\"100%\" class=\"fase4_rdf_meta\" cellspacing=\"5\" cellpadding=\"2\">\n";
777                                         $this->_output .= "<tr><td class=\"fase4_rdf\"><div class=\"fase4_rdf_title\">".htmlspecialchars($this->_item['title'])."</div></td></tr>\n";
778                                         $this->_output .= "<tr><td class=\"fase4_rdf\">".strip_tags($this->_item['description'], '<a>, <img>')."</td></tr>\n";
779                                         $this->_output .= "<tr><td>&nbsp;</td></tr>\n";
780                                         $this->_output .= "<tr><td class=\"fase4_rdf\">\n";
781                                         if($this->_display_opt['build'] != 'hidden') {
782                                                 if($this->_item['lastBuildDate']){$this->_output .= 'build: '. $this->_item['lastBuildDate'].'<br />';}
783                                         }
784                                         if($this->_display_opt['cache_update'] != 'hidden' && ( $_update = $this->get_cache_update_time()) ) {
785                                                 $this->_output .= 'cache update: '.$_update."<br />\n";
786                                         }
787                                         $this->_output .= "<a href=\"".$this->_item['link']."\" ";
788                                         if(isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
789                                         $this->_output .= ">".$this->_cut_string($this->_item['link'])."</a>\n";
790                                         $this->_output .= "</td></tr>\n";
791                                         $this->_output .= "</table></td></tr>\n";
792                                 }
793                                 $this->_array_channel = array(
794                                         'title'         => $this->_item['title'],
795                                         'link'          => $this->_item['link'],
796                                         'description'   => $this->_item['description'],
797                                         'lastBuildDate' => $this->_item['lastBuildDate']
798                                 );
799                                 $this->_clear_Items();
800                                 $this->_clear_cItems();
801                                 break;
802
803                         case 'textinput':
804                                 if(isset($this->_display_opt['textinput']) && ($this->_display_opt['textinput'] != 'hidden') && $this->_item['name'] && $this->_item['link']) {
805                                         $this->_output .= "<tr><td class=\"fase4_rdf\">\n";
806                                         $this->_output .= "<form accept-charset=\"utf-8\" action=\"".$this->_item['link']."\" ";
807                                         if(isset($this->_link_target)) { $this->_output .= "target=\"".$this->_link_target."\" "; }
808                                         $this->_output .= "method=\"get\">\n";
809                                         $this->_output .= "<div class=\"fase4_rdf_title\">".$this->_item['title']."</div>";
810                                         $this->_output .= strip_tags($this->_item['description'], '<a>, <img>')."<br /><br />\n";
811                                         $this->_output .= "<input class=\"fase4_rdf_input\" type=\"text\" name=\"".$this->_item['name']."\">&nbsp;\n";
812                                         $this->_output .= "<input class=\"fase4_rdf_input\" type=\"submit\" value=\"go\">";
813                                         $this->_output .= "</form>\n";
814                                         $this->_output .= "</td></tr>\n";
815                                         $this->_array_textinput = array(
816                                                 'title'       => $this->_item['title'],
817                                                 'name'        => $this->_item['name'],
818                                                 'link'        => $this->_item['link'],
819                                                 'description' => $this->_item['description']
820                                         );
821                                         $this->_clear_Items();
822                                 } elseif( isset($this->_display_opt['textinput']) && ($this->_display_opt['textinput'] == 'hidden') ) {
823                                         $this->_clear_Items();
824                                 }
825
826                                 break;
827                 }
828         }
829
830         /**
831          * This Method returns the data from the <channel /> paragraph.
832          *
833          * @access    public
834          * @author    Stefan Saasen <s@fase4.com>
835          * @return    array
836          * @see       _array_channel
837          */
838         function get_array_channel( )
839         {
840                 return $this->_array_channel;
841         }
842
843         /**
844          * This Method returns the data from each <item /> paragraph.
845          *
846          * @access    public
847          * @author    Stefan Saasen <s@fase4.com>
848          * @return    array
849          * @see       _array_item
850          */
851         function get_array_item( )
852         {
853                 return $this->_array_item;
854         }
855
856         /**
857          * This Method returns the data from <textinput />.
858          *
859          * @access    public
860          * @author    Stefan Saasen <s@fase4.com>
861          * @return    array
862          * @see       _array_textinput
863          */
864         function get_array_textinput( )
865         {
866                 return $this->_array_textinput;
867         }
868
869         /**
870          * Getter for parser id from resource
871          *
872          * @access   private
873          * @author   Roland Haeder <webmaster@mxchange.org>
874          * @return   int
875          */
876         function get_parser_id ($parser) {
877                 // Default is zero
878                 $id = '0';
879
880                 // Is it a resource?
881                 if (is_resource($parser)) {
882                         // Cast the resource into id
883                         $id = (int) $parser;
884                 } // END - if
885
886                 // Return the id
887                 return $id;
888         }
889
890         /**
891          * This Method returns the data from <image />.
892          *
893          * @access    public
894          * @author    Stefan Saasen <s@fase4.com>
895          * @return    array
896          * @see       _array_image
897          */
898         function get_array_image( )
899         {
900                 return $this->_array_image;
901         }
902
903         /**
904          * XML Parser Data Handler
905          *
906          * @access    private
907          * @author    Stefan Saasen <s@fase4.com>
908          * @param     mixed  $parser a reference to the XML parser calling the handler.
909          * @param     string $text contains the character data as a string.
910          * @see          _parse_mode, _item, _tags, _depth, _citem, _ctags, _cdepth
911          */
912         function _parseData($parser, $text)
913         {
914                 // Deocing mode added by Roland Haeder <webmaster@mxchange.org>
915                 switch ($this->_decoding_mode)
916                 {
917                         case 'utf8_decode':
918                                 $text = utf8_decode($text);
919                                 break;
920
921                         case 'htmlentities':
922                                 $text = htmlentities($text);
923                                 break;
924                 }
925
926                 $clean = preg_replace("/\s/", "", $text);
927                 if ($clean) {
928                         $text = preg_replace("/^\s+/", "", $text)."\n";
929                         if($this->_parse_mode == 'all') {
930                                 if ( isset($this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]]) &&
931                                 $this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]] ) {
932                                         $this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]] .= $text;
933                                 } else {
934                                         $this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]] = $text;
935                                 }
936                         } elseif (isset($this->_parse_mode) && $this->_parse_mode == 'channel') {
937                                 if ( isset($this->_citem[$this->_ctags[$this->_cdepth[$this->get_parser_id($parser)]]]) ) {
938                                         $this->_citem[$this->_ctags[$this->_cdepth[$this->get_parser_id($parser)]]] .= $text;
939                                 } else {
940                                         $this->_citem[$this->_ctags[$this->_cdepth[$this->get_parser_id($parser)]]] = $text;
941                                 }
942                         }
943                 }
944         }
945
946         /**
947          * This Method allows you to choose if specific Parameters are displayed or not. These are:
948          * image, channel, textinput, build and cache_update. If set to "hidden" those elements won't be displayed.
949          *
950          * @access    public
951          * @author    Stefan Saasen <s@fase4.com>
952          * @param     array  $options
953          * @see          _display_opt
954          */
955         function set_Options( $options = '' )
956         {
957                 if(is_array( $options )) {
958                         $this->_display_opt = $options;
959                         return true;
960                 } else {
961                         unset($this->_display_opt);
962                         return false;
963                 }
964         }
965
966         /**
967          * This Method allows you to define the width of the table that holds the representation of the rdf/rss file.
968          *
969          * @access    public
970          * @author    Stefan Saasen <s@fase4.com>
971          * @param     int  $width  attribute width in tag <table>
972          * @see          _table_width
973          */
974         function set_table_width( $width = 400 )
975         {
976                 $this->_table_width = $width;
977                 return true;
978         }
979
980         /**
981          * This Method returns an assocative Array with available Options.
982          *
983          * The Keys are the Name of the Options to be set.
984          * The Values are  short Description of available Options.
985          *
986          * @access    public
987          * @author    Stefan Saasen <s@fase4.com>
988          * @return    array  $options
989          * @see          _display_opt
990          */
991         function get_Options() {
992                 $options = array(
993                         'image'        => "If 'image' is set to \"hidden\" no image provided by the RDF Publisher will be displayed.",
994                         '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",
995                         'textinput'    => "If set to \"hidden\" no Input Form will be displayed",
996                         'build'        => "If set to \"hidden\" the Build Date (if provided) of the RDF File will not be displayed",
997                         'cache_update' => "If set to \"hidden\" the Update Date/Time of the cached Rdf File will not be displayed"
998                 );
999                 return $options;
1000         }
1001
1002         /**
1003          * This Method returns the Content of the RDF File in one string. The String actually holds the whole XML Document.
1004          *
1005          * @access    public
1006          * @author    Stefan Saasen <s@fase4.com>
1007          * @param     string $rdf    RDF File (Location)
1008          * @return    string XML Presentation of parsed RDF File
1009          * @see          _cached_file, _remote_file, _cache_dir, _refresh, _update_cache()
1010          */
1011         function cache()
1012         {
1013                 // checks if the cache directory already exists
1014                 // if not, the cache directory will be created
1015                 if(!$this->_cache_dir_ok) {
1016                         $this->_create_cache_dir();
1017                 }
1018                 if($this->_use_dynamic_display == true) {
1019                         $this->_cached_file = md5('dynamic'.$this->salt.$this->_remote_file) . '.cache';
1020                         $this->_cache_type = 'normal';
1021                 } else {
1022                         $this->_cached_file = md5($this->salt.$this->_remote_file) . '.cache';
1023                         $this->_cache_type = 'fast';
1024                 }
1025
1026                 $_cache_f = $this->_cache_dir.$this->_cached_file;
1027
1028                 if ( (!file_exists($_cache_f)) || (filemtime($_cache_f) < $this->_refresh) || (filesize($_cache_f) == '0')) {
1029                         // We have to parse the remote file
1030                         $this->_use_cached_file = false;
1031                         // --> we want to provide proper Information for Use in
1032                         // get_cache_update_time()
1033                         clearstatcache();
1034                         if($this->_use_dynamic_display == true) {
1035                                 $_rdf = @implode(' ', $this->_rdf_data()); // -> proxy
1036                                 if(!$_rdf) {
1037                                         $this->_throw_exception( $this->_remote_file.' is not available' );
1038                                 }
1039                                 $this->_parse_xRDF( $_rdf );
1040                                 $this->_update_cache( $_rdf );
1041                                 $data = $this->_output;
1042                         } else {
1043                                 $_rdf = @implode(' ', $this->_rdf_data()); // -> proxy
1044                                 if(!$_rdf) {
1045                                         $this->_throw_exception( $this->_remote_file.' is not available' );
1046                                 }
1047                                 $this->_parse_xRDF( $_rdf );
1048                                 $this->_update_cache( $this->_output );
1049                                 $data = $this->_output;
1050                         }
1051                 } else {
1052                         // we can use the cached file
1053                         $this->_use_cached_file = true;
1054                         if($this->_use_dynamic_display == true) {
1055                                 $this->_parse_xRDF( implode(' ', file($_cache_f)) );
1056                                 $data = $this->_output;
1057                         } else {
1058                                 $data = @implode(' ', file($_cache_f));
1059                         }
1060                 }
1061                 return trim($data);
1062         }   // END cache()
1063
1064         /**
1065          * This Methods creates the Cache Directory if the specified Directory does not exist.
1066          *
1067          * @access    private
1068          * @author    Stefan Saasen <s@fase4.com>
1069          * @param     string $dir Path to Directory.
1070          * @return       boolean
1071          * @see          _cache_dir, _cache_dir_ok
1072          */
1073         function _create_cache_dir()
1074         {
1075                 $path = '';
1076                 if(!@is_dir($this->_cache_dir)) {
1077                         $arr = explode('/', $this->_cache_dir);
1078                         $c = count($arr);
1079                         if($arr[0]=='') {
1080                                 $path = '/';
1081                         }
1082                         for($i = '0';$i<$c;$i++)
1083                         {
1084                                 if($arr[$i]!='') {
1085                                         $path .= $arr[$i].'/';
1086                                         if(!@is_dir($path)) {
1087                                                 if(!@mkdir($path, 0777)) {
1088                                                         $this->_throw_exception("failed to create directory:<b>".$this->_cache_dir."</b>.<br /><br />Exception on Line: ".__LINE__);
1089                                                         return false;
1090                                                 }
1091                                         }
1092                                 }
1093                         }
1094                         $this->_cache_dir_ok = true;
1095                         return true;
1096                 } else {
1097                         $this->_cache_dir_ok = true;
1098                         return true;
1099                 }
1100         }   // END _create_cache_dir()
1101
1102         /**
1103          * This Method updates the cached RDF Files and synchronises them with their remote Counterparts.
1104          *
1105          * @access    private
1106          * @author    Stefan Saasen <s@fase4.com>
1107          * @param     string $rdf    RDF File (Location)
1108          * @see          _cache_dir, _cached_file, _throw_exception()
1109          */
1110         function _update_cache( $content = '' )
1111         {
1112                 $_local = @fopen( $this->_cache_dir.$this->_cached_file, 'w' );
1113                 if(!$_local) {
1114                         $this->_throw_exception( 'Cannot open '.$this->_cached_file.'<br /><br />Exception at Line: '.__LINE__ );
1115                         return false;
1116                 }
1117                 if (fwrite( $_local, $content) === false) {
1118                         $this->_throw_exception( 'Cannot write to '.$this->_cached_file.'<br /<br />Exeception at Line: '.__LINE__);
1119                         return false;
1120                 }
1121                 fclose( $_local );
1122                 @chmod( $this->_cache_dir.$this->_cached_file, 0666);
1123                 return true;
1124         }   // END _update_cache()
1125
1126         /**
1127          * This Method returns the Date/Time of last Cache Update of the actually parsed RDF File.
1128          *
1129          * @access    public
1130          * @author    Stefan Saasen <s@fase4.com>
1131          * @return       string Date/Time of last Update
1132          * @see          _cache_dir, _cached_file
1133          */
1134         function get_cache_update_time()
1135         {
1136                 return (file_exists($this->_cache_dir.$this->_cached_file))?date('d.m.Y H:i:s', filemtime($this->_cache_dir.$this->_cached_file)):'Cachemiss';
1137         }   // END get_cache_update_time()
1138
1139         /**
1140          * This Method returns the Type of Cache that was used ('normal' or 'fast')
1141          *
1142          * @access    public
1143          * @author    Stefan Saasen <s@fase4.com>
1144          * @param     string $rdf    RDF File (Location)
1145          * @return    string Displays RDF Content ( using _display() )
1146          * @see          _remote_file, cache()
1147          */
1148         function get_CacheType()
1149         {
1150                 return $this->_cache_type;
1151         }
1152
1153         /**
1154          * Returns true if cached file was used, otherwise false
1155          *
1156          * @access    public
1157          * @author    Stefan Saasen <s@fase4.com>
1158          * @return    array  $options
1159          * @see          _use_cached_file
1160          */
1161         function is_cachedFile()
1162         {
1163                 return $this->_use_cached_file;
1164         }
1165
1166         /**
1167          * This Method deletes all the cached Files.
1168          *
1169          * Please keep in mind to use this method just as a 'manual garbage collection'
1170          * You should cache the rss/rdf files locally to avoid unnecessary traffic.
1171          * (Both for your visitors and the Publisher)
1172          *
1173          * @access    public
1174          * @author    Stefan Saasen <s@fase4.com>
1175          * @see          _cache_dir
1176          */
1177         function clear_cache()
1178         {
1179                 $dir = dir($this->_cache_dir);
1180                 while($file=$dir->read()) {
1181                         // Exclude directories
1182                         if (is_file($dir->path.$file) && substr($file, -6, 6) != '.cache' && substr($file, -4, 4) != '.log')  {
1183                                 if(!@unlink($dir->path.$file)) {
1184                                         $this->_throw_exception("Unable to unlink ".$dir->path.$file."<br />\n<br />\nException at Line: ".__LINE__ );
1185                                         return false;
1186                                 } // END - if
1187                         } // END - if
1188                 } // END - while
1189                 $dir->close();
1190                 return true;
1191         }   // END clear_cache()
1192
1193         /**
1194          * Cuts the String $string after $str_len and adds '... '
1195          *
1196          * @access   private
1197          * @param    string  $string String to be shortened
1198          * @param    int     $str_len length of the returned String (overall length including '... ')
1199          * @return   string  Cut String
1200          */
1201         function _cut_string( $string, $str_len = '30' )
1202         {
1203                 if(strlen(trim($string))>$str_len) {
1204                         $string = substr( trim($string) , 0, $str_len - 4);
1205                         $string .= ' ...';
1206                 }
1207                 return $string;
1208         }   // END _cut_string()
1209
1210         /**
1211          * this Method implements simple Garbage Collection
1212          *
1213          * @access    private
1214          * @author    Stefan Saasen <s@fase4.com>
1215          * @see          _cache_dir, gc_probability, gc_maxlifetime
1216          */
1217         function _garbage_collection()
1218         {
1219                 srand((double) microtime() * 1000000);
1220                 if (mt_rand(1, 100) <= $this->gc_probability) {
1221                         $dir = dir($this->_cache_dir);
1222                         while($file=$dir->read()) {
1223                                 if (is_file($dir->path.$file) && substr($file, -6, 6) != '.cache' && substr($file, -4, 4) != '.log' && filemtime($dir->path.$file) <= time() - $this->_refresh )  {
1224                                         @unlink($dir->path.$file);
1225                                 } // END - if
1226                         }
1227                         $dir->close();
1228                 }   // END if
1229         }
1230
1231         /* ==== Proxy/Auth methods ==== */
1232
1233         /**
1234          * this method sets a proxy server
1235          *
1236          * @access    public
1237          * @param     string $phost Proxy Host
1238          * @param     string $pport Prox Port
1239          * @author    Marco Kraus <marco.kraus@siemens.com>
1240          */
1241         function set_proxy($phost, $pport)
1242         {
1243                 $this->_use_proxy = true;
1244
1245                 if ($phost != '')
1246                 $this->_phost = $phost;
1247
1248                 if ($pport != '')
1249                 $this->_pport = $pport;
1250         }
1251
1252         /**
1253          * this method sets a proxy server authentification
1254          *
1255          * @access    public
1256          * @param     string $pname Username
1257          * @param     string $ppaswd Password
1258          * @author    Marco Kraus <marco.kraus@siemens.com>
1259          */
1260         function set_proxy_auth( $pname, $ppasswd )
1261         {
1262                 $this->_use_proxy_auth = true;
1263
1264                 if ($pname != '')
1265                 $this->_pname = $pname;
1266
1267                 if ($ppasswd != '')
1268                 $this->_ppasswd = $ppasswd;
1269         }
1270
1271
1272         /**
1273          * gets _remote_file into an array
1274          *
1275          * needed, cause if you use a proxy, you have to open
1276          * a raw-tcp-socket to get the data
1277          *
1278          * @access    private
1279          * @author    Marco Kraus <Marco.Kraus@siemens.com>
1280          * @return array
1281          * @see _use_proxy, cache()
1282          */
1283         function _rdf_data()
1284         {
1285                 if ( $this->_use_proxy == true )
1286                 {
1287                         // we need a raw socket here to connect to proxy
1288                         $fp = fsockopen($this->_phost,$this->_pport);
1289
1290                         if (!$fp) {
1291                                 $this->_throw_exception( $this->_remote_file.' is not available with proxy' );
1292                         } else {
1293                                 if ( $this->_use_proxy_auth == true ) {
1294                                         fputs($fp, "GET ".$this->_remote_file." HTTP/1.0\r\nUser-Agent: Fase4 RDF-Reader/1.40 modified by Quix0r\r\n\r\n");
1295                                 } else {
1296                                         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");
1297                                 }
1298                         }
1299
1300
1301                         for ( $i = '0'; !feof ($fp) ; $i++)
1302                         {
1303                                 $usable_data[$i] = "";
1304                                 $usable_data[$i] = fgets($fp,4096);
1305
1306                                 // PARSE HEADER ---- first line has to be <?xml, second rdf or rss, and third is blank
1307
1308                                 // strstr did not fit (ask Rasmus why), so we compare each character
1309                                 if ( ($usable_data[$i][0] == '<' ) &&
1310                                 ($usable_data[$i][1] == '?' ) &&
1311                                 ($usable_data[$i][2] == 'x' ) &&
1312                                 ($usable_data[$i][3] == 'm' ) &&
1313                                 ($usable_data[$i][4] == 'l' ) ) {
1314                                         $usable_data[0] = $usable_data[$i]; // save current field
1315                                         $i = 1; // just reset array to start
1316                                 }
1317
1318                                 // there seems to be proxystuff after the <?xml....we delete this
1319                                 if ( (
1320                                 ($usable_data[$i][0] == '<' ) &&
1321                                 ($usable_data[$i][1] == 'r' ) &&
1322                                 ($usable_data[$i][2] == 'd' ) &&
1323                                 ($usable_data[$i][3] == 'f' ) &&
1324                                 ($usable_data[$i][4] == ':' )
1325                                 )
1326                                 ||
1327                                 (
1328                                 ($usable_data[$i][0] == '<' ) &&
1329                                 ($usable_data[$i][1] == 'r' ) &&
1330                                 ($usable_data[$i][2] == 's' ) &&
1331                                 ($usable_data[$i][3] == 's' )
1332                                 )
1333                                 ) {
1334
1335                                         $usable_data[1] = $usable_data[$i]; // save current field
1336                                         $usable_data[2] = "\n";
1337                                         $i = 2; // just reset array to start
1338                                 }
1339                         }
1340
1341                         fclose($fp);
1342                         return $usable_data;
1343                 } else {
1344                         if (substr($this->_remote_file, 0, 7) != 'http://') {
1345                                 $this->_throw_exception( 'Cannot find http:// in '.$this->_remote_file.'!' );
1346                                 return '';
1347                         } else {
1348                                 // Extract host information
1349                                 $host = substr($this->_remote_file, 7);
1350                                 // Extract the GET part
1351                                 $get = '/';
1352                                 if (strpos($host, '/') > 0) {
1353                                         $get = substr($host, strpos($host, '/'));
1354                                         $host = substr($host, 0, strpos($host, '/'));
1355                                 }
1356                                 // Extract port
1357                                 $port = '80';
1358                                 if (strpos($host, ':') > 0) {
1359                                         $port = substr($host, (strpos($host, ':') + 1));
1360                                         $host = substr($host, 0, (strpos($host, ':') - 1));
1361                                 }
1362
1363                                 // Start connection to server
1364                                 $fp = fsockopen($host, $port);
1365                                 if (!$fp) {
1366                                         $this->_throw_exception( $this->_remote_file.' is maybe not available.' );
1367                           return '';
1368                                 }
1369                                 // Repare request line
1370                                 $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);
1371                                 // Send request out
1372                                 fputs($fp, $request);
1373                                 $reply = ''; $isContent = false; $dummy = '';
1374                                 // Read reply
1375                                 $i=0;
1376                                 while ( !feof($fp) ) {
1377                                         $read = trim(fgets($fp, 4096));
1378                                         if (substr($read, 0, 5) == '<?xml' || $isContent) {
1379                                                 // Add content
1380                                                 $reply[] = $read;
1381                                                 $isContent = true;
1382                                         } else {
1383                                                 // Put in dummy
1384                                                 $dummy[] = $read;
1385                                         }
1386                                         $i++;
1387                                 }
1388                                 if ((count($dummy) > 0) && (count($reply) == '0') && (!$isContent)) {
1389                                         // Transfer content from dummy
1390                                         $reply = $content;
1391                                 }
1392                                 fclose($fp);
1393                                 //die(htmlentities($reply));
1394                                 return $reply;
1395                         }
1396                 }
1397         }    // END _rdf_data()
1398 }   // END class
1399 ?>