fd0ff99b1b672f075f4adfc7ee64580270945e90
[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 /**
36  * Class RSS Parser
37  *
38  * This class offers methods to parse RSS Files
39  *
40  * @link      http://www.fase4.com/rdf/ Latest release of this class
41  * @package   rss
42  * @copyright Copyright (c) 2001 fase4.com. All rights reserved.
43  * @author    Stefan Saasen <s@fase4.com>
44  * @author    Roland Haeder <webmaster@mxchange.org>
45  * @version   1.7 ($Date$Revision: 856 $
46  * @access    public
47  */
48
49 class fase4_rdf {
50
51         /**
52          * Word-wrapping mode for description, set it to 0 do disable this feature! Ommits _use_nl2br!
53          *
54          * @access private
55          * @var    integer
56          */
57         var $_word_wrap = '0';
58
59         /**
60          * Wether to recode \n -> <br /> or not in description
61          *
62          * @access private
63          * @var    boolean
64          */
65         var $_use_nl2br = TRUE;
66
67         /**
68          * Sets the decoding mode of the read data (UTF8 scrambles some german umlauts here!)
69          *
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
73          *
74          * @access private
75          * @var    string
76          */
77         var $_decoding_mode = '';
78
79         /**
80          * If $_link_target is set a target='xxx' attribute in each <a /> and <form accept-charset="utf-8" /> html tag will be added
81          *
82          * Possible values are "_blank", "_content", "_parent", "_self", "_top"
83          *
84          * @access private
85          * @var    string
86          */
87         var $_link_target = '_blank';
88
89         /**
90          * vars for proxy settings - Prox Host
91          *
92          * @access private
93          * @var      string
94          */
95         var $_phost = '';
96
97         /**
98          * vars for proxy settings - Prox Port
99          *
100          * @access private
101          * @var      string
102          */
103         var $_pport = '';
104
105         /**
106          * vars for proxy settings - Prox Username
107          *
108          * @access private
109          * @var      string
110          */
111         var $_pname = '';
112
113         /**
114          * vars for proxy settings - Prox Password
115          *
116          * @access private
117          * @var      string
118          */
119         var $_ppasswd = '';
120
121         /**
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)
124          *
125          * @access   private
126          * @see      set_proxy()
127          * @var      bool
128          */
129         var $_use_proxy = FALSE;
130
131         /**
132          * just a flag for checking if proxy-support with authentication
133          * should be enabled
134          * set default to false (will be enabled if set_proxy is called)
135          *
136          * @access   private
137          * @see      set_proxy()
138          * @var      boolean
139          */
140         var $_use_proxy_auth = FALSE;
141
142         /**
143          * The time the Files will be cached (in seconds).
144          *
145          * @access private
146          * @var    int
147          */
148         var $_refresh = 60;   // int
149
150         /**
151          * The Name of the cached File.
152          *
153          * @access private
154          * @var    string
155          */
156         var $_cached_file = '';   // String
157
158         /**
159          * Indicates whether the cached or the remote file was used.
160          *
161          * @access private
162          * @var    boolean
163          */
164         var $_use_cached_file = TRUE;
165
166         /**
167          * (fast|normal) depends on _use_dynamic_display(). _use_dynamic_display(TRUE) -> 'normal', otherwise 'fast'
168          *
169          * @access private
170          * @var    string
171          */
172         var $_cache_type = 'fast';
173
174         /**
175          * The Name of the Remote File.
176          *
177          * @access private
178          * @var    string
179          */
180         var $_remote_file = '';
181
182         /**
183          * Path to the Cache Directory.
184          *
185          * @access private
186          * @var    string
187          */
188         var $_cache_dir = 'cache/';  // String
189
190         /**
191          * Indicates whether the Creating of the Cache Directory needs to be done or not.
192          *
193          * @access private
194          * @var    boolean
195          */
196         var $_cache_dir_ok = FALSE;
197
198         /**
199          * Type of the file to be parsed (RSS or RDF).
200          *
201          * The Type depends on the root node
202          *
203          * @access private
204          * @var    string
205          */
206         var $_type = 'rss'; // string (rss or rdf)
207
208         /**
209          * Array of Display Settings.
210          *
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.
213          *
214          * @access private
215          * @var    array
216          */
217         var $_display_opt = array(
218                 'build'        => '',
219                 'image'        => '',
220                 'channel'      => '',
221                 'textinput'    => '',
222                 'cache_update' => '',
223                 'sitelink'     => '',
224                 'refid'        => '',
225                 'reflink'      => '',
226         );
227
228         /**
229          * Defines the width attribute in the table that holds the rdf/rss representation
230          *
231          * @access private
232          * @var    int
233          * @see    see_table_width()
234          */
235         var $_table_width = '100%';
236
237         /**
238          * Indicates whether or not to use dynamic Display Settings
239          *
240          * @access private
241          * @var    array
242          */
243         var $_use_dynamic_display = FALSE;
244
245         /**
246          * <item> count
247          *
248          * @access private
249          * @var    int
250          */
251         var $_item_count = '0';
252
253         /**
254          * No of max <item>s
255          *
256          * @access private
257          * @var    boolean
258          */
259         var $_max_count = FALSE;
260
261         /**
262          * Array containing the content of <channel />
263          *
264          * @access private
265          * @var    array
266          */
267         var $_array_channel = array();
268
269         /**
270          * Array containing the content of each <item />
271          *
272          * @access private
273          * @var    array
274          */
275         var $_array_item = array();
276
277         /**
278          * Array containing the content of <textinput />
279          *
280          * @access private
281          * @var    array
282          */
283         var $_array_textinput = array();
284
285         /**
286          * Array containing the content of <image />
287          *
288          * @access private
289          * @var    array
290          */
291         var $_array_image = array();
292
293         /**
294          * Array containing the Channel content. Just For internal XML Parser Purposes.
295          *
296          * @access private
297          * @var    array
298          */
299         var $_citem = array();
300
301         /**
302          * Array containing the Channel Parser Depth. Just For internal XML Parser Purposes.
303          *
304          * @access private
305          * @var    array
306          */
307         var $_cdepth = array();
308
309         /**
310          * Array containing the Channel tags. Just For internal XML Parser Purposes.
311          *
312          * @access private
313          * @var    array
314          */
315         var $_ctags = array('x');
316
317         /**
318          * Array containing the Channel content. Just For internal XML Parser Purposes.
319          *
320          * @access private
321          * @var    array
322          */
323         var $_item = array();   // Array
324
325         /**
326          * Array containing the Channel Parser Depth. Just For internal XML Parser Purposes.
327          *
328          * @access private
329          * @var    array
330          */
331         var $_depth = array();  // Array
332
333         /**
334          * Array containing the tags. Just For internal XML Parser Purposes.
335          *
336          * @access private
337          * @var    array
338          */
339         var $_tags = array('x');  // Array
340
341         /**
342          * Garbage collection: probability in percent
343          *
344          * @var      integer     0 => never
345          * @access   public
346          */
347         var $gc_probability = 1;
348
349         /**
350          * HTML Output
351          *
352          * @var      string
353          * @access   private
354          */
355         var $_output = '';
356
357         /**
358          * @var      string
359          */
360         var $_parse_mode = '';
361
362         /**
363          * Output variable
364          */
365         var $out = '';
366
367         /**
368          * Salt for hashing
369          */
370         var $salt = '';
371
372         /**
373          * Callback function for processing content in finish() method.
374          */
375         var $_finishCallback = NULL;
376
377         /**
378          * Constructor of our Class
379          *
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).
382          *
383          * @access    public
384          * @author    Stefan Saasen <s@fase4.com>
385          * @see       _refresh
386          */
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();
392         }
393
394         /**
395          * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
396          *
397          * @access    public
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()
402          */
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>";
410                 $this->_output = '';
411                 $this->_item_count = '0';
412                 return TRUE;
413         }
414
415         /**
416          * This Method is called when all parsing is finished to use the garbage collection
417          *
418          * @access    public
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()
423          */
424         function finish ($return = FALSE) {
425                 // Replace dollar chars as they may cause problems
426                 $this->out = str_replace('$', '&#36;', $this->out);
427
428                 // Is the call-back enabled?
429                 if ((!empty($this->out)) && (!is_null($this->_finishCallback)) && (is_callable($this->_finishCallback))) {
430                         // Then call it
431                         $this->out = call_user_func($this->_finishCallback, $this->out);
432                 } // END - if
433
434                 // Do garbage collection
435                 $this->_garbage_collection();
436
437                 // Return or output?
438                 if ($return === FALSE) {
439                         print($this->out);
440                 } else {
441                         return $this->out;
442                 }
443         }
444
445         /**
446          * With this method you can decide whether to use the normal cache and dynamic display Options or to use a static cache.
447          *
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'
453          *
454          * @access    public
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()
459          */
460         function use_dynamic_display ($bool) {
461                 $this->_use_dynamic_display = $bool;
462                 return TRUE;
463         }
464
465         /**
466          * This Method avtually parses the XML data.
467          *
468          * @access    private
469          * @author    Stefan Saasen <s@fase4.com>
470          * @param     string $data    RDF File XML Data
471          * @see       _clear_Items()
472          */
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().');
484                 } // END - if
485                 xml_parser_free($xml_parser);
486         }
487
488
489         /**
490          * This Methods allows you to set the Refresh Time
491          *
492          * @access    public
493          * @author    Stefan Saasen <s@fase4.com>
494          * @param     int $seconds time files will be cached (in seconds).
495          * @return    boolean
496          * @see       _refresh
497          */
498         function set_refresh($seconds) {
499                 $this->_refresh = (time() - $seconds);
500                 return TRUE;
501         }
502
503         function set_salt ($saltPara) {
504                 $this->salt = $saltPara;
505                 return TRUE;
506         }
507
508         /**
509          * This Methods allows you to set the No. of <item>s to display
510          *
511          * @access    public
512          * @param     int $int No of max <item>s
513          * @author    Stefan Saasen <s@fase4.com>
514          * @return    boolean
515          * @see       _max_count, _endElement()
516          */
517         function set_max_item ($int) {
518                 $this->_max_count = $int;
519                 return TRUE;
520         }
521
522         /**
523          * This Methods allows you to set the Cache Directory
524          *
525          * @access    public
526          * @author    Stefan Saasen <s@fase4.com>
527          * @param     string $dir Path to Directory.
528          * @return    boolean
529          * @see       _cache_dir
530          */
531         function set_CacheDir ($dir) {
532                 if (substr($dir, -1) != '/') {
533                         $dir = $dir.'/';
534                 }
535                 $this->_cache_dir = $dir;
536         }
537
538         /**
539          * This Method displays Error Messages and terminates the Execution of the Script
540          *
541          * @access    private
542          * @param     string $msg Message to display on failure
543          * @author    Stefan Saasen <s@fase4.com>
544          */
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>";
547                 return TRUE;
548         }
549
550         /**
551          * This Method clears the Array containig the Items.
552          *
553          * @access    private
554          * @author    Stefan Saasen <s@fase4.com>
555          * @see       _item
556          */
557         function _clear_Items() {
558                 $this->_item = array(
559                         'title'         => '',
560                         'link'          => '',
561                         'description'   => '',
562                         'url'           => '',
563                         'language'      => '',
564                         'pubDate'       => '',
565                         'lastBuildDate' => '',
566                         'width'         => '',
567                         'height'        => ''
568                 );
569         }
570         /**
571          * This Method clears the Array containig the Channel Items.
572          *
573          * @access    private
574          * @author    Stefan Saasen <s@fase4.com>
575          * @see       _item
576          */
577         function _clear_cItems() {
578                 $this->_citem = array(
579                         'title'          => '',
580                         'link'           => '',
581                         'description'    => '',
582                         'url'            => '',
583                         'language'       => '',
584                         'copyright'      => '',
585                         'managingEditor' => '',
586                         'webMaster'      => '',
587                         'pubDate'        => '',
588                         'lastBuildDate'  => '',
589                         'category'       => '',
590                         'generator'      => '',
591                         'docs'           => '',
592                         'cloud'          => '',
593                         'ttl'            => '',
594                         'image'          => '',
595                         'textinput'      => '',
596                         'skipHours'      => '',
597                         'skipDays'       => '',
598                         'sitelink'       => '',
599                         'refid'          => '',
600                         'reflink'        => '',
601                 );
602         }
603
604         /**
605          * XML Parser Start Element Handler
606          *
607          * @access    private
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
613          */
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';
620                 }
621
622
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);
631                         }
632                         $this->_parse_mode = 'all';
633                 }
634
635                 if (!isset($this->_depth[$this->get_parser_id($parser)])) {
636                         $this->_depth[$this->get_parser_id($parser)] = '0';
637                 }
638                 $this->_depth[$this->get_parser_id($parser)]++;
639                 array_push($this->_tags, $name);
640
641                 if (!isset($this->_cdepth[$this->get_parser_id($parser)])) {
642                         $this->_cdepth[$this->get_parser_id($parser)] = '0';
643                 }
644                 $this->_cdepth[$this->get_parser_id($parser)]++;
645                 array_push($this->_ctags, $name);
646         }   // END _startElement()
647
648         /**
649          * Retrives the Channel Data in <rss> File
650          *
651          * @access    private
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
655          */
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'])))
659                 {
660                         $this->_citem['link'] .= $this->_display_opt['reflink'].$this->_display_opt['refid'];
661                 }
662
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>&nbsp;</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 />';}
673                         }
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";
676                         }
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>";
683                 }
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']);
689         }
690
691         /**
692          * XML Parser End Element Handler
693          *
694          * @access    private
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
699          */
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'])))
707                 {
708                         if (!isInString('refid=', $this->_item['link'])) $this->_item['link'] .= '?refid=' . $this->_display_opt['refid'];
709                 }
710                 switch ($name) {
711                         case 'item':
712                                 if (empty($this->_max_count) || $this->_item_count < $this->_max_count) {
713                                         if ($this->_item['title'] != $this->_item['description']
714                                         && $this->_item['description']) {
715
716                                                 // word-wrapping added by Roland Haeder <webmaster@mxchange.org>
717                                                 if (($this->_word_wrap > 0) && (strlen($this->_item['description']) > $this->_word_wrap))
718                                                 {
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");
725                                                 }
726                                                 elseif (($this->_word_wrap == '0') && (!$this->_use_nl2br))
727                                                 {
728                                                         // Strip tags out instead when word-wrap is disabled
729                                                         $this->_item['description'] = strip_tags($this->_item['description'], '<a>, <img>');
730                                                 }
731
732                                                 // nl2br added by Roland Haeder <webmaster@mxchange.org>
733                                                 if ($this->_use_nl2br) $this->_item['description'] = nl2br($this->_item['description']);
734
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";
741                                         } else {
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";
746                                         }
747
748                                         $this->_array_item[] = array(
749                                                 'title'       => $this->_item['title'],
750                                                 'link'        => $this->_item['link'],
751                                                 'description' => $this->_item['description']
752                                         );
753
754                                         ++$this->_item_count;
755                                 }
756                                 $this->_clear_Items();
757                                 break;
758
759                         case 'image':
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']."\"";
767                                         }
768                                         $this->_output .= " alt=\"".$this->_item['title']."\" border=\"0\" /></a></td></tr>\n";
769
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']
775                                         );
776                                         $this->_clear_Items();
777                                 } elseif (isset($this->_display_opt['image']) && ($this->_display_opt['image'] == 'hidden')) {
778                                         $this->_clear_Items();
779                                 }
780
781                                 break;
782
783                         case 'channel':
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>&nbsp;</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 />';}
793                                         }
794                                         if ($this->_display_opt['cache_update'] != 'hidden' && ($_update = $this->get_cache_update_time())) {
795                                                 $this->_output .= 'cache update: '.$_update."<br />\n";
796                                         }
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";
802                                 }
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']
808                                 );
809                                 $this->_clear_Items();
810                                 $this->_clear_cItems();
811                                 break;
812
813                         case 'textinput':
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']."\">&nbsp;\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']
830                                         );
831                                         $this->_clear_Items();
832                                 } elseif (isset($this->_display_opt['textinput']) && ($this->_display_opt['textinput'] == 'hidden')) {
833                                         $this->_clear_Items();
834                                 }
835
836                                 break;
837                 }
838         }
839
840         /**
841          * This Method returns the data from the <channel /> paragraph.
842          *
843          * @access    public
844          * @author    Stefan Saasen <s@fase4.com>
845          * @return    array
846          * @see       _array_channel
847          */
848         function get_array_channel () {
849                 return $this->_array_channel;
850         }
851
852         /**
853          * This Method returns the data from each <item /> paragraph.
854          *
855          * @access    public
856          * @author    Stefan Saasen <s@fase4.com>
857          * @return    array
858          * @see       _array_item
859          */
860         function get_array_item () {
861                 return $this->_array_item;
862         }
863
864         /**
865          * This Method returns the data from <textinput />.
866          *
867          * @access    public
868          * @author    Stefan Saasen <s@fase4.com>
869          * @return    array
870          * @see       _array_textinput
871          */
872         function get_array_textinput () {
873                 return $this->_array_textinput;
874         }
875
876         /**
877          * Getter for parser id from resource
878          *
879          * @access   private
880          * @author   Roland Haeder <webmaster@mxchange.org>
881          * @return   int
882          */
883         function get_parser_id ($parser) {
884                 // Default is zero
885                 $id = '0';
886
887                 // Is it a resource?
888                 if (is_resource($parser)) {
889                         // Cast the resource into id
890                         $id = (int) $parser;
891                 } // END - if
892
893                 // Return the id
894                 return $id;
895         }
896
897         /**
898          * This Method returns the data from <image />.
899          *
900          * @access    public
901          * @author    Stefan Saasen <s@fase4.com>
902          * @return    array
903          * @see       _array_image
904          */
905         function get_array_image() {
906                 return $this->_array_image;
907         }
908
909         /**
910          * XML Parser Data Handler
911          *
912          * @access    private
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
917          */
918         function _parseData($parser, $text) {
919                 // Deocing mode added by Roland Haeder <webmaster@mxchange.org>
920                 switch ($this->_decoding_mode) {
921                         case 'utf8_decode':
922                                 $text = utf8_decode($text);
923                                 break;
924
925                         case 'htmlentities':
926                                 $text = htmlentities($text);
927                                 break;
928                 }
929
930                 $clean = preg_replace("/\s/", '', $text);
931                 if ($clean) {
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;
937                                 } else {
938                                         $this->_item[$this->_tags[$this->_depth[$this->get_parser_id($parser)]]] = $text;
939                                 }
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;
943                                 } else {
944                                         $this->_citem[$this->_ctags[$this->_cdepth[$this->get_parser_id($parser)]]] = $text;
945                                 }
946                         }
947                 }
948         }
949
950         /**
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.
953          *
954          * @access    public
955          * @author    Stefan Saasen <s@fase4.com>
956          * @param     array  $options
957          * @see       _display_opt
958          */
959         function set_Options ($options = NULL) {
960                 if (is_array($options)) {
961                         $this->_display_opt = $options;
962                         return TRUE;
963                 } else {
964                         unset($this->_display_opt);
965                         return FALSE;
966                 }
967         }
968
969         /**
970          * This Method allows you to define the width of the table that holds the representation of the rdf/rss file.
971          *
972          * @access    public
973          * @author    Stefan Saasen <s@fase4.com>
974          * @param     int  $width  attribute width in tag <table>
975          * @see       _table_width
976          */
977         function set_table_width ($width = 400) {
978                 $this->_table_width = $width;
979                 return TRUE;
980         }
981
982         /**
983          * This Method returns an assocative Array with available Options.
984          *
985          * The Keys are the Name of the Options to be set.
986          * The Values are  short Description of available Options.
987          *
988          * @access    public
989          * @author    Stefan Saasen <s@fase4.com>
990          * @return    array  $options
991          * @see       _display_opt
992          */
993         function get_Options () {
994                 $options = array(
995                         'image'        => "If &#39;image&#39; is set to &quot;hidden&quot; no image provided by the RDF Publisher will be displayed.",
996                         'channel'      => "If &#39;channel&#39; is set to &quot;hidden&quot; 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 &quot;hidden&quot; no Input Form will be displayed",
998                         'build'        => "If set to &quot;hidden&quot; the Build Date (if provided) of the RDF File will not be displayed",
999                         'cache_update' => "If set to &quot;hidden&quot; the Update Date/Time of the cached Rdf File will not be displayed"
1000                 );
1001                 return $options;
1002         }
1003
1004         /**
1005          * This Method returns the Content of the RDF File in one string. The String actually holds the whole XML Document.
1006          *
1007          * @access    public
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()
1012          */
1013         function 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();
1018                 }
1019
1020                 if ($this->_use_dynamic_display == TRUE) {
1021                         $this->_cached_file = md5('dynamic' . $this->salt.$this->_remote_file) . '.rss';
1022                         $this->_cache_type = 'normal';
1023                 } else {
1024                         $this->_cached_file = md5($this->salt . $this->_remote_file) . '.rss';
1025                         $this->_cache_type = 'fast';
1026                 }
1027
1028                 $_cache_f = $this->_cache_dir.$this->_cached_file;
1029
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()
1035                         clearstatcache();
1036                         if ($this->_use_dynamic_display == TRUE) {
1037                                 $_rdf = implode(' ', $this->_rdf_data()); // -> proxy
1038                                 if (!$_rdf) {
1039                                         $this->_throw_exception($this->_remote_file.' is not available');
1040                                 }
1041                                 $this->_parse_xRDF($_rdf);
1042                                 $this->_update_cache($_rdf);
1043                                 $data = $this->_output;
1044                         } else {
1045                                 $_rdf = implode(' ', $this->_rdf_data()); // -> proxy
1046                                 if (!$_rdf) {
1047                                         $this->_throw_exception($this->_remote_file.' is not available');
1048                                 }
1049                                 $this->_parse_xRDF($_rdf);
1050                                 $this->_update_cache($this->_output);
1051                                 $data = $this->_output;
1052                         }
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;
1059                         } else {
1060                                 $data = readFromFile($_cache_f);
1061                         }
1062                 } else {
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;
1068                         } else {
1069                                 $data = implode(' ', file($_cache_f));
1070                         }
1071                 }
1072
1073                 // Return trimmed data
1074                 return trim($data);
1075         }   // END cache()
1076
1077         /**
1078          * This Methods creates the Cache Directory if the specified Directory does not exist.
1079          *
1080          * @access    private
1081          * @author    Stefan Saasen <s@fase4.com>
1082          * @param     string $dir Path to Directory.
1083          * @return    boolean
1084          * @see       _cache_dir, _cache_dir_ok
1085          */
1086         function _create_cache_dir()
1087         {
1088                 $path = '';
1089                 if (!is_dir($this->_cache_dir)) {
1090                         $arr = explode('/', $this->_cache_dir);
1091                         $c = count($arr);
1092                         if ($arr[0] == '') {
1093                                 $path = '/';
1094                         }
1095                         for($i = '0';$i<$c;$i++) {
1096                                 if ($arr[$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__);
1101                                                         return FALSE;
1102                                                 }
1103                                         }
1104                                 }
1105                         }
1106                         $this->_cache_dir_ok = TRUE;
1107                         return TRUE;
1108                 } else {
1109                         $this->_cache_dir_ok = TRUE;
1110                         return TRUE;
1111                 }
1112         }   // END _create_cache_dir()
1113
1114         /**
1115          * This Method updates the cached RDF Files and synchronises them with their remote Counterparts.
1116          *
1117          * @access    private
1118          * @author    Stefan Saasen <s@fase4.com>
1119          * @param     string $rdf    RDF File (Location)
1120          * @see       _cache_dir, _cached_file, _throw_exception()
1121          */
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);
1126                 }
1127
1128                 $_local = @fopen($this->_cache_dir.$this->_cached_file, 'w');
1129                 if (!$_local) {
1130                         $this->_throw_exception('Cannot open '.$this->_cached_file.'<br /><br />Exception at Line: '.__LINE__);
1131                         return FALSE;
1132                 }
1133
1134                 if (fwrite($_local, $content) === FALSE) {
1135                         $this->_throw_exception('Cannot write to '.$this->_cached_file.'<br /<br />Exeception at Line: '.__LINE__);
1136                         return FALSE;
1137                 }
1138
1139                 fclose($_local);
1140                 @chmod($this->_cache_dir.$this->_cached_file, 0666);
1141                 return TRUE;
1142         }   // END _update_cache()
1143
1144         /**
1145          * This Method returns the Date/Time of last Cache Update of the actually parsed RDF File.
1146          *
1147          * @access    public
1148          * @author    Stefan Saasen <s@fase4.com>
1149          * @return    string Date/Time of last Update
1150          * @see       _cache_dir, _cached_file
1151          */
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()
1155
1156         /**
1157          * This Method returns the Type of Cache that was used ('normal' or 'fast')
1158          *
1159          * @access    public
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()
1164          */
1165         function get_CacheType() {
1166                 return $this->_cache_type;
1167         }
1168
1169         /**
1170          * Returns true if cached file was used, otherwise false
1171          *
1172          * @access    public
1173          * @author    Stefan Saasen <s@fase4.com>
1174          * @return    array  $options
1175          * @see       _use_cached_file
1176          */
1177         function is_cachedFile () {
1178                 return $this->_use_cached_file;
1179         }
1180
1181         /**
1182          * This Method deletes all the cached Files.
1183          *
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)
1187          *
1188          * @access    public
1189          * @author    Stefan Saasen <s@fase4.com>
1190          * @see       _cache_dir
1191          */
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__);
1199                                         return FALSE;
1200                                 } elseif (!unlink($dir->path . $file)) {
1201                                         $this->_throw_exception("Unable to unlink ".$dir->path . $file."<br />\n<br />\nException at Line: ".__LINE__);
1202                                         return FALSE;
1203                                 } // END - if
1204                         } // END - if
1205                 } // END - while
1206                 $dir->close();
1207                 return TRUE;
1208         }   // END clear_cache()
1209
1210         /**
1211          * Cuts the String $string after $str_len and adds '... '
1212          *
1213          * @access   private
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
1217          */
1218         function _cut_string($string, $str_len = '30')
1219         {
1220                 if (strlen(trim($string))>$str_len) {
1221                         $string = substr(trim($string) , 0, $str_len - 4);
1222                         $string .= ' ...';
1223                 }
1224                 return $string;
1225         }   // END _cut_string()
1226
1227         /**
1228          * this Method implements simple Garbage Collection
1229          *
1230          * @access    private
1231          * @author    Stefan Saasen <s@fase4.com>
1232          * @see       _cache_dir, gc_probability, gc_maxlifetime
1233          */
1234         function _garbage_collection()
1235         {
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);
1244                                         } else {
1245                                                 // Use PHP's function
1246                                                 unlink($dir->path . $file);
1247                                         }
1248                                 } // END - if
1249                         }
1250                         $dir->close();
1251                 }   // END if
1252         }
1253
1254         /* ==== Proxy/Auth methods ==== */
1255
1256         /**
1257          * this method sets a proxy server
1258          *
1259          * @access    public
1260          * @param     string $phost Proxy Host
1261          * @param     string $pport Prox Port
1262          * @author    Marco Kraus <marco.kraus@siemens.com>
1263          */
1264         function set_proxy($phost, $pport)
1265         {
1266                 $this->_use_proxy = TRUE;
1267
1268                 if ($phost != '')
1269                 $this->_phost = $phost;
1270
1271                 if ($pport != '')
1272                 $this->_pport = $pport;
1273         }
1274
1275         /**
1276          * this method sets a proxy server authentification
1277          *
1278          * @access    public
1279          * @param     string $pname Username
1280          * @param     string $ppaswd Password
1281          * @author    Marco Kraus <marco.kraus@siemens.com>
1282          */
1283         function set_proxy_auth($pname, $ppasswd)
1284         {
1285                 $this->_use_proxy_auth = TRUE;
1286
1287                 if ($pname != '')
1288                 $this->_pname = $pname;
1289
1290                 if ($ppasswd != '')
1291                 $this->_ppasswd = $ppasswd;
1292         }
1293
1294
1295         /**
1296          * gets _remote_file into an array
1297          *
1298          * needed, cause if you use a proxy, you have to open
1299          * a raw-tcp-socket to get the data
1300          *
1301          * @access    private
1302          * @author    Marco Kraus <Marco.Kraus@siemens.com>
1303          * @return     array
1304          * @see       _use_proxy, cache()
1305          */
1306         function _rdf_data () {
1307                 // Init output
1308                 $output = array();
1309
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);
1317
1318                         if (!$fp) {
1319                                 $this->_throw_exception($this->_remote_file.' is not available with proxy');
1320                         } else {
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");
1323                                 } else {
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");
1325                                 }
1326                         }
1327
1328
1329                         for ($i = '0'; !feof ($fp) ; $i++)
1330                         {
1331                                 $usable_data[$i] = '';
1332                                 $usable_data[$i] = fgets($fp,4096);
1333
1334                                 // PARSE HEADER ---- first line has to be <?xml, second rdf or rss, and third is blank
1335
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
1344                                 }
1345
1346                                 // there seems to be proxystuff after the <?xml....we delete this
1347                                 if ((
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] == ':')
1353                                 )
1354                                 ||
1355                                 (
1356                                 ($usable_data[$i][0] == '<') &&
1357                                 ($usable_data[$i][1] == 'r') &&
1358                                 ($usable_data[$i][2] == 's') &&
1359                                 ($usable_data[$i][3] == 's')
1360                                 )
1361                                 ) {
1362
1363                                         $usable_data[1] = $usable_data[$i]; // save current field
1364                                         $usable_data[2] = "\n";
1365                                         $i = 2; // just reset array to start
1366                                 }
1367                         }
1368
1369                         fclose($fp);
1370                         $output = $usable_data;
1371                 } else {
1372                         if (substr($this->_remote_file, 0, 7) != 'http://') {
1373                                 $this->_throw_exception('Cannot find http:// in '.$this->_remote_file.'!');
1374                                 return array();
1375                         } else {
1376                                 // Extract host information
1377                                 $host = substr($this->_remote_file, 7);
1378
1379                                 // Extract the GET part
1380                                 $get = '/';
1381                                 if (strpos($host, '/') > 0) {
1382                                         $get = substr($host, strpos($host, '/'));
1383                                         $host = substr($host, 0, strpos($host, '/'));
1384                                 } // END - if
1385
1386                                 // Extract port
1387                                 $port = '80';
1388                                 if (strpos($host, ':') > 0) {
1389                                         $port = substr($host, (strpos($host, ':') + 1));
1390                                         $host = substr($host, 0, (strpos($host, ':') - 1));
1391                                 } // END - if
1392
1393                                 // Start connection to server
1394                                 $fp = fsockopen($host, $port);
1395                                 if (!$fp) {
1396                                         $this->_throw_exception($this->_remote_file.' is maybe not available.');
1397                                         return array();
1398                                 } // END - if
1399
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);
1402
1403                                 // Send request out
1404                                 fputs($fp, $request);
1405                                 $reply = ''; $isContent = FALSE; $dummy = '';
1406
1407                                 // Read reply
1408                                 $i=0;
1409                                 while (!feof($fp)) {
1410                                         $read = trim(fgets($fp, 4096));
1411                                         if (substr($read, 0, 5) == '<?xml' || $isContent) {
1412                                                 // Add content
1413                                                 $reply[] = $read;
1414                                                 $isContent = TRUE;
1415                                         } else {
1416                                                 // Put in dummy
1417                                                 $dummy[] = $read;
1418                                         }
1419
1420                                         $i++;
1421                                 } // END - while
1422
1423                                 if ((count($dummy) > 0) && (count($reply) == 0) && (!$isContent)) {
1424                                         // Transfer content from dummy
1425                                         $reply = $content;
1426                                 } // END - if
1427
1428                                 fclose($fp);
1429                                 //die(htmlentities($reply));
1430                                 $output = $reply;
1431                         }
1432                 }
1433
1434                 // Exit here
1435                 return $output;
1436         } // END _rdf_data()
1437 } // END class
1438
1439 // [EOF]
1440 ?>