Initial commit of website to git. Has the "old" ob3 website as the main site, and...
[dana/openbox-web.git] / oldwiki / extensions / simplepie.inc
1 <?php
2 /****************************************************
3 SIMPLEPIE
4 A PHP-Based RSS and Atom Feed Framework
5 Takes the hard work out of managing a complete RSS/Atom solution.
6
7 Version: "Lemon Meringue"
8 Updated: 24 November 2006
9 Copyright: 2004-2006 Ryan Parman, Geoffrey Sneddon
10 http://simplepie.org
11
12 *****************************************************
13 LICENSE:
14
15 GNU Lesser General Public License 2.1 (LGPL)
16 http://creativecommons.org/licenses/LGPL/2.1/
17
18 *****************************************************
19 Please submit all bug reports and feature requests to the SimplePie forums.
20 http://simplepie.org/support/
21
22 ****************************************************/
23
24 class SimplePie
25 {
26         // SimplePie Info
27         var $name = 'SimplePie';
28         var $version = '1.0 b3.2';
29         var $build = '20061124';
30         var $url = 'http://simplepie.org/';
31         var $useragent;
32         var $linkback;
33         
34         // Other objects, instances created here so we can set options on them
35         var $sanitize;
36         
37         // Options
38         var $rss_url;
39         var $file;
40         var $timeout = 10;
41         var $xml_dump = false;
42         var $enable_cache = true;
43         var $max_minutes = 60;
44         var $cache_location = './cache';
45         var $order_by_date = true;
46         var $input_encoding = false;
47         var $cache_class = 'SimplePie_Cache';
48         var $locator_class = 'SimplePie_Locator';
49         var $parser_class = 'SimplePie_Parser';
50         var $file_class = 'SimplePie_File';
51         var $force_fsockopen = false;
52         var $cache_name_type = 'sha1';
53         
54         // Misc. variables
55         var $data;
56         var $error;
57         
58         function SimplePie($feed_url = null, $cache_location = null, $cache_max_minutes = null)
59         {
60                 // Couple of variables built up from other variables
61                 $this->useragent = $this->name . '/' . $this->version . ' (Feed Parser; ' . $this->url . '; Allow like Gecko) Build/' . $this->build;
62                 $this->linkback = '<a href="' . $this->url . '" title="' . $this->name . ' ' . $this->version . '">' . $this->name . '</a>';
63                 
64                 // Other objects, instances created here so we can set options on them
65                 $this->sanitize = new SimplePie_Sanitize;
66                 
67                 // Set options if they're passed to the constructor
68                 if (!is_null($feed_url))
69                 {
70                         $this->feed_url($feed_url);
71                 }
72
73                 if (!is_null($cache_location))
74                 {
75                         $this->cache_location($cache_location);
76                 }
77
78                 if (!is_null($cache_max_minutes))
79                 {
80                         $this->cache_max_minutes($cache_max_minutes);
81                 }
82
83                 // If we've passed an xmldump variable in the URL, snap into XMLdump mode
84                 if (isset($_GET['xmldump']))
85                 {
86                         $this->enable_xmldump(true);
87                 }
88                 
89                 // Only init the script if we're passed a feed URL
90                 if (!is_null($feed_url))
91                 {
92                         return $this->init();
93                 }
94         }
95         
96         function feed_url($url)
97         {
98                 $this->rss_url = SimplePie_Misc::fix_protocol($url, 1);
99         }
100         
101         function set_file(&$file)
102         {
103                 if (is_a($file, 'SimplePie_File'))
104                 {
105                         $this->rss_url = $file->url;
106                         $this->file =& $file;
107                 }
108         }
109         
110         function set_timeout($timeout = 10)
111         {
112                 $this->timeout = (int) $timeout;
113         }
114         
115         function set_raw_data($data)
116         {
117                 $this->raw_data = trim((string) $data);
118         }
119         
120         function enable_xmldump($enable = false)
121         {
122                 $this->xml_dump = (bool) $enable;
123         }
124         
125         function enable_caching($enable = true)
126         {
127                 $this->enable_cache = (bool) $enable;
128         }
129         
130         function cache_max_minutes($minutes = 60)
131         {
132                 $this->max_minutes = (float) $minutes;
133         }
134         
135         function cache_location($location = './cache')
136         {
137                 $this->cache_location = (string) $location;
138         }
139         
140         function order_by_date($enable = true)
141         {
142                 $this->order_by_date = (bool) $enable;
143         }
144         
145         function input_encoding($encoding = false)
146         {
147                 if ($encoding)
148                 {
149                         $this->input_encoding = (string) $encoding;
150                 }
151                 else
152                 {
153                         $this->input_encoding = false;
154                 }
155         }
156         
157         function set_cache_class($class = 'SimplePie_Cache')
158         {
159                 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Cache'))
160                 {
161                         $this->cache_class = $class;
162                         return true;
163                 }
164                 return false;
165         }
166         
167         function set_locator_class($class = 'SimplePie_Locator')
168         {
169                 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Locator'))
170                 {
171                         $this->locator_class = $class;
172                         return true;
173                 }
174                 return false;
175         }
176         
177         function set_parser_class($class = 'SimplePie_Parser')
178         {
179                 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Parser'))
180                 {
181                         $this->parser_class = $class;
182                         return true;
183                 }
184                 return false;
185         }
186         
187         function set_file_class($class = 'SimplePie_File')
188         {
189                 if (SimplePie_Misc::is_a_class($class, 'SimplePie_File'))
190                 {
191                         $this->file_class = $class;
192                         return true;
193                 }
194                 return false;
195         }
196         
197         function set_sanitize_class($object = 'SimplePie_Sanitize')
198         {
199                 if (class_exists($object))
200                 {
201                         $this->sanitize = new $object;
202                         return true;
203                 }
204                 return false;
205         }
206         
207         function set_useragent($ua)
208         {
209                 $this->useragent = (string) $ua;
210         }
211         
212         function force_fsockopen($enable = false)
213         {
214                 $this->force_fsockopen = (bool) $enable;
215         }
216         
217         function set_cache_name_type($type = 'sha1')
218         {
219                 $type = strtolower(trim($type));
220                 switch ($type)
221                 {
222                         case 'crc32':
223                                 $this->cache_name_type = 'crc32';
224                                 break;
225                         
226                         case 'md5':
227                                 $this->cache_name_type = 'md5';
228                                 break;
229                         
230                         case 'rawurlencode':
231                                 $this->cache_name_type = 'rawurlencode';
232                                 break;
233                         
234                         case 'urlencode':
235                                 $this->cache_name_type = 'urlencode';
236                                 break;
237                         
238                         default:
239                                 $this->cache_name_type = 'sha1';
240                                 break;
241                 }
242         }
243         
244         function bypass_image_hotlink($get = false)
245         {
246                 $this->sanitize->bypass_image_hotlink($get);
247         }
248         
249         function bypass_image_hotlink_page($page = false)
250         {
251                 $this->sanitize->bypass_image_hotlink_page($page);
252         }
253         
254         function replace_headers($enable = false)
255         {
256                 $this->sanitize->replace_headers($enable);
257         }
258         
259         function remove_div($enable = true)
260         {
261                 $this->sanitize->remove_div($enable);
262         }
263         
264         function strip_ads($enable = false)
265         {
266                 $this->sanitize->strip_ads($enable);
267         }
268         
269         function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'), $encode = null)
270         {
271                 $this->sanitize->strip_htmltags($tags);
272                 if (!is_null($encode))
273                 {
274                         $this->sanitize->encode_instead_of_strip($tags);
275                 }
276         }
277         
278         function encode_instead_of_strip($enable = true)
279         {
280                 $this->sanitize->encode_instead_of_strip($enable);
281         }
282         
283         function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur'))
284         {
285                 $this->sanitize->strip_attributes($attribs);
286         }
287         
288         function output_encoding($encoding = 'UTF-8')
289         {
290                 $this->sanitize->output_encoding($encoding);
291         }
292         
293         function set_item_class($class = 'SimplePie_Item')
294         {
295                 return $this->sanitize->set_item_class($class);
296         }
297         
298         function set_author_class($class = 'SimplePie_Author')
299         {
300                 return $this->sanitize->set_author_class($class);
301         }
302         
303         function set_enclosure_class($class = 'SimplePie_Enclosure')
304         {
305                 return $this->sanitize->set_enclosure_class($class);
306         }
307         
308         function init()
309         {
310                 if (!(function_exists('version_compare') && ((version_compare(phpversion(), '4.3.2', '>=') && version_compare(phpversion(), '5', '<')) || version_compare(phpversion(), '5.0.3', '>='))) || !extension_loaded('xml') || !extension_loaded('pcre'))
311                 {
312                         return false;
313                 }
314                 if ($this->sanitize->bypass_image_hotlink && !empty($_GET[$this->sanitize->bypass_image_hotlink]))
315                 {
316                         if (get_magic_quotes_gpc())
317                         {
318                                 $_GET[$this->sanitize->bypass_image_hotlink] = stripslashes($_GET[$this->sanitize->bypass_image_hotlink]);
319                         }
320                         SimplePie_Misc::display_file($_GET[$this->sanitize->bypass_image_hotlink], 10, $this->useragent);
321                 }
322                 
323                 if (isset($_GET['js']))
324                 {
325                         $embed = <<<EOT
326 function embed_odeo(link) {
327         document.writeln('<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url='+link+'"></embed>');
328 }
329
330 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
331         if (placeholder != '') {
332                 document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
333         }
334         else {
335                 document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
336         }
337 }
338
339 function embed_flash(bgcolor, width, height, link, loop, type) {
340         document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
341 }
342
343 function embed_wmedia(width, height, link) {
344         document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
345 }
346 EOT;
347
348                         if (function_exists('ob_gzhandler'))
349                         {
350                                 ob_start('ob_gzhandler');
351                         }
352                         header('Content-type: text/javascript; charset: UTF-8'); 
353                         header('Cache-Control: must-revalidate'); 
354                         header('Expires: ' .  gmdate('D, d M Y H:i:s', time() + 86400) . ' GMT');
355                         echo $embed;
356                         exit;
357                 }
358                 
359                 if (!empty($this->rss_url) || !empty($this->raw_data))
360                 {
361                         $this->data = array();
362                         $cache = false;
363                         
364                         if (!empty($this->rss_url))
365                         {
366                                 // Decide whether to enable caching
367                                 if ($this->enable_cache && preg_match('/^http(s)?:\/\//i', $this->rss_url))
368                                 {
369                                         $cache = new $this->cache_class($this->cache_location, call_user_func($this->cache_name_type, $this->rss_url), 'spc');
370                                 }
371                                 // If it's enabled and we don't want an XML dump, use the cache
372                                 if ($cache && !$this->xml_dump)
373                                 {
374                                         // Load the Cache
375                                         $this->data = $cache->load();
376                                         if (!empty($this->data))
377                                         {
378                                                 // If we've hit a collision just rerun it with caching disabled
379                                                 if (isset($this->data['url']) && $this->data['url'] != $this->rss_url)
380                                                 {
381                                                         $cache = false;
382                                                 }
383                                                 // If we've got a feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL
384                                                 else if (!empty($this->data['feed_url']))
385                                                 {
386                                                         if ($this->data['feed_url'] == $this->data['url'])
387                                                         {
388                                                                 $cache->unlink();
389                                                         }
390                                                         else
391                                                         {
392                                                                 $this->feed_url($this->data['feed_url']);
393                                                                 return $this->init();
394                                                         }
395                                                 }
396                                                 // If the cache is new enough
397                                                 else if ($cache->mtime() + $this->max_minutes * 60 < time())
398                                                 {
399                                                         // If we have last-modified and/or etag set
400                                                         if (!empty($this->data['last-modified']) || !empty($this->data['etag']))
401                                                         {
402                                                                 $headers = array();
403                                                                 if (!empty($this->data['last-modified']))
404                                                                 {
405                                                                         $headers['if-modified-since'] = $this->data['last-modified'];
406                                                                 }
407                                                                 if (!empty($this->data['etag']))
408                                                                 {
409                                                                         $headers['if-none-match'] = $this->data['etag'];
410                                                                 }
411                                                                 $file = new $this->file_class($this->rss_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
412                                                                 if ($file->success)
413                                                                 {
414                                                                         $headers = $file->headers();
415                                                                         if ($headers['status']['code'] == 304)
416                                                                         {
417                                                                                 $cache->touch();
418                                                                                 return true;
419                                                                         }
420                                                                 }
421                                                                 else
422                                                                 {
423                                                                         unset($file);
424                                                                 }
425                                                         }
426                                                         // If we don't have last-modified or etag set, just clear the cache
427                                                         else
428                                                         {
429                                                                 $cache->unlink();
430                                                         }
431                                                 }
432                                                 // If the cache is still valid, just return true
433                                                 else
434                                                 {
435                                                         return true;
436                                                 }
437                                         }
438                                         // If the cache is empty, delete it
439                                         else
440                                         {
441                                                 $cache->unlink();
442                                         }
443                                 }
444                                 $this->data = array();
445                                 // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
446                                 if (!isset($file))
447                                 {
448                                         if (is_a($this->file, 'SimplePie_File') && $this->file->url == $this->rss_url)
449                                         {
450                                                 $file =& $this->file;
451                                         }
452                                         else
453                                         {
454                                                 $file = new $this->file_class($this->rss_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
455                                         }
456                                 }
457                                 // If the file connection has an error, set SimplePie::error to that and quit
458                                 if (!$file->success)
459                                 {
460                                         $this->error = $file->error;
461                                         return false;
462                                 }
463                                 
464                                 // Check if the supplied URL is a feed, if it isn't, look for it.
465                                 $locate = new $this->locator_class($file, $this->timeout, $this->useragent);
466                                 if (!$locate->is_feed($file))
467                                 {
468                                         $feed = $locate->find();
469                                         if ($feed)
470                                         {
471                                                 if ($cache && !$cache->save(array('url' => $this->rss_url, 'feed_url' => $feed)))
472                                                 {
473                                                         $this->error = "$cache->name is not writeable";
474                                                         SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
475                                                 }
476                                                 $this->rss_url = $feed;
477                                                 return $this->init();
478                                         }
479                                         else
480                                         {
481                                                 $this->error = "A feed could not be found at $this->rss_url";
482                                                 SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
483                                                 return false;
484                                         }
485                                 }
486                                 
487                                 $headers = $file->headers();
488                                 $data = trim($file->body());
489                                 $file->close();
490                                 unset($file);
491                         }
492                         else
493                         {
494                                 $data = $this->raw_data;
495                         }
496                         
497                         // First check to see if input has been overridden.
498                         if (!empty($this->input_encoding))
499                         {
500                                 $encoding = $this->input_encoding;
501                         }
502                         // Second try HTTP headers
503                         else if (!empty($headers['content-type']) && preg_match('/charset\s*=\s*([^;]*)/i', $headers['content-type'], $charset))
504                         {
505                                 $encoding = $charset[1];
506                         }
507                         // Then prolog, if at the very start of the document
508                         else if (preg_match('/^<\?xml(.*)?>/msiU', $data, $prolog) && preg_match('/encoding\s*=\s*("([^"]*)"|\'([^\']*)\')/Ui', $prolog[1], $encoding))
509                         {
510                                 $encoding = substr($encoding[1], 1, -1);
511                         }
512                         // UTF-32 Big Endian BOM
513                         else if (strpos($data, sprintf('%c%c%c%c', 0x00, 0x00, 0xFE, 0xFF)) === 0)
514                         {
515                                 $encoding = 'UTF-32be';
516                         }
517                         // UTF-32 Little Endian BOM
518                         else if (strpos($data, sprintf('%c%c%c%c', 0xFF, 0xFE, 0x00, 0x00)) === 0)
519                         {
520                                 $encoding = 'UTF-32';
521                         }
522                         // UTF-16 Big Endian BOM
523                         else if (strpos($data, sprintf('%c%c', 0xFE, 0xFF)) === 0)
524                         {
525                                 $encoding = 'UTF-16be';
526                         }
527                         // UTF-16 Little Endian BOM
528                         else if (strpos($data, sprintf('%c%c', 0xFF, 0xFE)) === 0)
529                         {
530                                 $encoding = 'UTF-16le';
531                         }
532                         // UTF-8 BOM
533                         else if (strpos($data, sprintf('%c%c%c', 0xEF, 0xBB, 0xBF)) === 0)
534                         {
535                                 $encoding = 'UTF-8';
536                         }
537                         // Fallback to the default
538                         else
539                         {
540                                 $encoding = null;
541                         }
542                         
543                         // Change the encoding to UTF-8 (as we always use UTF-8 internally)
544                         $data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8');
545                         
546                         // Strip illegal characters (if on less  than PHP5, as on PHP5 expat can manage fine)
547                         if (version_compare(phpversion(), '5', '<'))
548                         {
549                                 if (function_exists('iconv'))
550                                 {
551                                         $data = iconv('UTF-8', 'UTF-8//IGNORE', $data);
552                                 }
553                                 else if (function_exists('mb_convert_encoding'))
554                                 {
555                                         $data = mb_convert_encoding($data, 'UTF-8', 'UTF-8');
556                                 }
557                                 else
558                                 {
559                                         $data = SimplePie_Misc::utf8_bad_replace($data);
560                                 }
561                         }
562
563                         // Start parsing
564                         $data = new $this->parser_class($data, 'UTF-8', $this->xml_dump);
565                         // If we want the XML, just output that and quit
566                         if ($this->xml_dump)
567                         {
568                                 header('Content-type: text/xml; charset=UTF-8');
569                                 echo $data->data;
570                                 exit;
571                         }
572                         // If it's parsed fine
573                         else if (!$data->error_code)
574                         {
575                                 // Parse the data, and make it sane
576                                 $this->sanitize->parse_data_array($data->data, $this->rss_url);
577                                 unset($data);
578                                 // Get the sane data
579                                 $this->data['feedinfo'] = $this->sanitize->feedinfo;
580                                 unset($this->sanitize->feedinfo);
581                                 $this->data['info'] = $this->sanitize->info;
582                                 unset($this->sanitize->info);
583                                 $this->data['items'] = $this->sanitize->items;
584                                 unset($this->sanitize->items);
585                                 $this->data['feedinfo']['encoding'] = $this->sanitize->output_encoding;
586                                 $this->data['url'] = $this->rss_url;
587                                 
588                                 // Store the headers that we need
589                                 if (!empty($headers['last-modified']))
590                                 {
591                                         $this->data['last-modified'] = $headers['last-modified'];
592                                 }
593                                 if (!empty($headers['etag']))
594                                 {
595                                         $this->data['etag'] = $headers['etag'];
596                                 }
597                                 
598                                 // If we want to order it by date, check if all items have a date, and then sort it
599                                 if ($this->order_by_date && !empty($this->data['items']))
600                                 {
601                                         $do_sort = true;
602                                         foreach ($this->data['items'] as $item)
603                                         {
604                                                 if (!$item->get_date('U'))
605                                                 {
606                                                         $do_sort = false;
607                                                         break;
608                                                 }
609                                         }
610                                         if ($do_sort)
611                                         {
612                                                 usort($this->data['items'], create_function('$a, $b', 'if ($a->get_date(\'U\') == $b->get_date(\'U\')) return 1; return ($a->get_date(\'U\') < $b->get_date(\'U\')) ? 1 : -1;'));
613                                         }
614                                 }
615                                 
616                                 // Cache the file if caching is enabled
617                                 if ($cache && !$cache->save($this->data))
618                                 {
619                                         $this->error = "$cache->name is not writeable";
620                                         SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
621                                 }
622                                 return true;
623                         }
624                         // If we have an error, just set SimplePie::error to it and quit
625                         else
626                         {
627                                 $this->error = "XML error: $data->error_string at line $data->current_line, column $data->current_column";
628                                 SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
629                                 return false;
630                         }
631                 }
632         }
633         
634         function get_encoding()
635         {
636                 if (!empty($this->data['feedinfo']['encoding']))
637                 {
638                         return $this->data['feedinfo']['encoding'];
639                 }
640                 else
641                 {
642                         return false;
643                 }
644         }
645         
646         function handle_content_type($mime = 'text/html')
647         {
648                 if (!headers_sent())
649                 {
650                         $header = "Content-type: $mime;";
651                         if ($this->get_encoding())
652                         {
653                                 $header .= ' charset=' . $this->get_encoding();
654                         }
655                         else
656                         {
657                                 $header .= ' charset=UTF-8';
658                         }
659                         header($header);
660                 }
661         }
662         
663         function get_type()
664         {
665                 if (!empty($this->data['feedinfo']['type']))
666                 {
667                         return $this->data['feedinfo']['type'];
668                 }
669                 else
670                 {
671                         return false;
672                 }
673         }
674         
675         function get_version()
676         {
677                 if (!empty($this->data['feedinfo']['version']))
678                 {
679                         return $this->data['feedinfo']['version'];
680                 }
681                 else
682                 {
683                         return false;
684                 }
685         }
686         
687         function get_favicon($check = false, $alternate = null)
688         {
689                 if (!empty($this->data['info']['link']['alternate'][0]))
690                 {
691                         $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $this->get_feed_link());
692
693                         if ($check)
694                         {
695                                 $file = new $this->file_class($favicon, $this->timeout/10, 5, null, $this->useragent, $this->force_fsockopen);
696                                 $headers = $file->headers();
697                                 $file->close();
698
699                                 if ($headers['status']['code'] == 200)
700                                 {
701                                         return $favicon;
702                                 }
703                         }
704                         else
705                         {
706                                 return $favicon;
707                         }
708                 }
709                 if (!is_null($alternate))
710                 {
711                         return $alternate;
712                 }
713                 else
714                 {
715                         return false;
716                 }
717         }
718         
719         function subscribe_url()
720         {
721                 if (!empty($this->rss_url))
722                 {
723                         return $this->rss_url;
724                 }
725                 else
726                 {
727                         return false;
728                 }
729         }
730         
731         function subscribe_feed()
732         {
733                 if (!empty($this->rss_url))
734                 {
735                         return SimplePie_Misc::fix_protocol($this->rss_url, 2);
736                 }
737                 else
738                 {
739                         return false;
740                 }
741         }
742         
743         function subscribe_outlook()
744         {
745                 if (!empty($this->rss_url))
746                 {
747                         return 'outlook' . SimplePie_Misc::fix_protocol($this->rss_url, 2);
748                 }
749                 else
750                 {
751                         return false;
752                 }
753         }
754         
755         function subscribe_podcast()
756         {
757                 if (!empty($this->rss_url))
758                 {
759                         return SimplePie_Misc::fix_protocol($this->rss_url, 3);
760                 }
761                 else
762                 {
763                         return false;
764                 }
765         }
766         
767         function subscribe_aol()
768         {
769                 if ($this->subscribe_url())
770                 {
771                         return 'http://feeds.my.aol.com/add.jsp?url=' . rawurlencode($this->subscribe_url());
772                 }
773                 else
774                 {
775                         return false;
776                 }
777         }
778         
779         function subscribe_bloglines()
780         {
781                 if ($this->subscribe_url())
782                 {
783                         return 'http://www.bloglines.com/sub/' . rawurlencode($this->subscribe_url());
784                 }
785                 else
786                 {
787                         return false;
788                 }
789         }
790         
791         function subscribe_eskobo()
792         {
793                 if ($this->subscribe_url())
794                 {
795                         return 'http://www.eskobo.com/?AddToMyPage=' . rawurlencode($this->subscribe_url());
796                 }
797                 else
798                 {
799                         return false;
800                 }
801         }
802         
803         function subscribe_feedfeeds()
804         {
805                 if ($this->subscribe_url())
806                 {
807                         return 'http://www.feedfeeds.com/add?feed=' . rawurlencode($this->subscribe_url());
808                 }
809                 else
810                 {
811                         return false;
812                 }
813         }
814         
815         function subscribe_feedlounge()
816         {
817                 if ($this->subscribe_url())
818                 {
819                         return 'http://my.feedlounge.com/external/subscribe?url=' . rawurlencode($this->subscribe_url());
820                 }
821                 else
822                 {
823                         return false;
824                 }
825         }
826         
827         function subscribe_feedster()
828         {
829                 if ($this->subscribe_url())
830                 {
831                         return 'http://www.feedster.com/myfeedster.php?action=addrss&amp;confirm=no&amp;rssurl=' . rawurlencode($this->subscribe_url());
832                 }
833                 else
834                 {
835                         return false;
836                 }
837         }
838         
839         function subscribe_google()
840         {
841                 if ($this->subscribe_url())
842                 {
843                         return 'http://fusion.google.com/add?feedurl=' . rawurlencode($this->subscribe_url());
844                 }
845                 else
846                 {
847                         return false;
848                 }
849         }
850         
851         function subscribe_gritwire()
852         {
853                 if ($this->subscribe_url())
854                 {
855                         return 'http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=' . rawurlencode($this->subscribe_url());
856                 }
857                 else
858                 {
859                         return false;
860                 }
861         }
862         
863         function subscribe_msn()
864         {
865                 if ($this->subscribe_url())
866                 {
867                         $url = 'http://my.msn.com/addtomymsn.armx?id=rss&amp;ut=' . rawurlencode($this->subscribe_url());
868                         if ($this->get_feed_link())
869                         {
870                                 $url .= '&amp;ru=' . rawurlencode($this->get_feed_link());
871                         }
872                         return $url;
873                 }
874                 else
875                 {
876                         return false;
877                 }
878         }
879         
880         function subscribe_netvibes()
881         {
882                 if ($this->subscribe_url())
883                 {
884                         return 'http://www.netvibes.com/subscribe.php?url=' . rawurlencode($this->subscribe_url());
885                 }
886                 else
887                 {
888                         return false;
889                 }
890         }
891         
892         function subscribe_newsburst()
893         {
894                 if ($this->subscribe_url())
895                 {
896                         return 'http://www.newsburst.com/Source/?add=' . rawurlencode($this->subscribe_url());
897                 }
898                 else
899                 {
900                         return false;
901                 }
902         }
903         
904         function subscribe_newsgator()
905         {
906                 if ($this->subscribe_url())
907                 {
908                         return 'http://www.newsgator.com/ngs/subscriber/subext.aspx?url=' . rawurlencode($this->subscribe_url());
909                 }
910                 else
911                 {
912                         return false;
913                 }
914         }
915         
916         function subscribe_odeo()
917         {
918                 if ($this->subscribe_url())
919                 {
920                         return 'http://www.odeo.com/listen/subscribe?feed=' . rawurlencode($this->subscribe_url());
921                 }
922                 else
923                 {
924                         return false;
925                 }
926         }
927         
928         function subscribe_pluck()
929         {
930                 if ($this->subscribe_url())
931                 {
932                         return 'http://client.pluck.com/pluckit/prompt.aspx?GCID=C12286x053&amp;a=' . rawurlencode($this->subscribe_url());
933                 }
934                 else
935                 {
936                         return false;
937                 }
938         }
939         
940         function subscribe_podnova()
941         {
942                 if ($this->subscribe_url())
943                 {
944                         return 'http://www.podnova.com/index_your_podcasts.srf?action=add&amp;url=' . rawurlencode($this->subscribe_url());
945                 }
946                 else
947                 {
948                         return false;
949                 }
950         }
951         
952         function subscribe_rojo()
953         {
954                 if ($this->subscribe_url())
955                 {
956                         return 'http://www.rojo.com/add-subscription?resource=' . rawurlencode($this->subscribe_url());
957                 }
958                 else
959                 {
960                         return false;
961                 }
962         }
963         
964         function subscribe_yahoo()
965         {
966                 if ($this->subscribe_url())
967                 {
968                         return 'http://add.my.yahoo.com/rss?url=' . rawurlencode($this->subscribe_url());
969                 }
970                 else
971                 {
972                         return false;
973                 }
974         }
975         
976         function get_feed_title()
977         {
978                 if (!empty($this->data['info']['title']))
979                 {
980                         return $this->data['info']['title'];
981                 }
982                 else
983                 {
984                         return false;
985                 }
986         }
987         
988         function get_feed_link()
989         {
990                 if (!empty($this->data['info']['link']['alternate'][0]))
991                 {
992                         return $this->data['info']['link']['alternate'][0];
993                 }
994                 else
995                 {
996                         return false;
997                 }
998         }
999         
1000         function get_feed_links()
1001         {
1002                 if (!empty($this->data['info']['link']))
1003                 {
1004                         return $this->data['info']['link'];
1005                 }
1006                 else
1007                 {
1008                         return false;
1009                 }
1010         }
1011         
1012         function get_feed_description()
1013         {
1014                 if (!empty($this->data['info']['description']))
1015                 {
1016                         return $this->data['info']['description'];
1017                 }
1018                 else if (!empty($this->data['info']['dc:description']))
1019                 {
1020                         return $this->data['info']['dc:description'];
1021                 }
1022                 else if (!empty($this->data['info']['tagline']))
1023                 {
1024                         return $this->data['info']['tagline'];
1025                 }
1026                 else if (!empty($this->data['info']['subtitle']))
1027                 {
1028                         return $this->data['info']['subtitle'];
1029                 }
1030                 else
1031                 {
1032                         return false;
1033                 }
1034         }
1035         
1036         function get_feed_copyright()
1037         {
1038                 if (!empty($this->data['info']['copyright']))
1039                 {
1040                         return $this->data['info']['copyright'];
1041                 }
1042                 else
1043                 {
1044                         return false;
1045                 }
1046         }
1047         
1048         function get_feed_language()
1049         {
1050                 if (!empty($this->data['info']['language']))
1051                 {
1052                         return $this->data['info']['language'];
1053                 }
1054                 else if (!empty($this->data['info']['xml:lang']))
1055                 {
1056                         return $this->data['info']['xml:lang'];
1057                 }
1058                 else
1059                 {
1060                         return false;
1061                 }
1062         }
1063         
1064         function get_image_exist()
1065         {
1066                 if (!empty($this->data['info']['image']['url']) || !empty($this->data['info']['image']['logo']))
1067                 {
1068                         return true;
1069                 }
1070                 else
1071                 {
1072                         return false;
1073                 }
1074         }
1075         
1076         function get_image_title()
1077         {
1078                 if (!empty($this->data['info']['image']['title']))
1079                 {
1080                         return $this->data['info']['image']['title'];
1081                 }
1082                 else
1083                 {
1084                         return false;
1085                 }
1086         }
1087         
1088         function get_image_url()
1089         {
1090                 if (!empty($this->data['info']['image']['url']))
1091                 {
1092                         return $this->data['info']['image']['url'];
1093                 }
1094                 else if (!empty($this->data['info']['image']['logo']))
1095                 {
1096                         return $this->data['info']['image']['logo'];
1097                 }
1098                 else
1099                 {
1100                         return false;
1101                 }
1102         }
1103         
1104         function get_image_link()
1105         {
1106                 if (!empty($this->data['info']['image']['link']))
1107                 {
1108                         return $this->data['info']['image']['link'];
1109                 }
1110                 else
1111                 {
1112                         return false;
1113                 }
1114         }
1115         
1116         function get_image_width()
1117         {
1118                 if (!empty($this->data['info']['image']['width']))
1119                 {
1120                         return $this->data['info']['image']['width'];
1121                 }
1122                 else
1123                 {
1124                         return false;
1125                 }
1126         }
1127         
1128         function get_image_height()
1129         {
1130                 if (!empty($this->data['info']['image']['height']))
1131                 {
1132                         return $this->data['info']['image']['height'];
1133                 }
1134                 else
1135                 {
1136                         return false;
1137                 }
1138         }
1139         
1140         function get_item_quantity($max = 0)
1141         {
1142                 if (!empty($this->data['items']))
1143                 {
1144                         $qty = sizeof($this->data['items']);
1145                 }
1146                 else
1147                 {
1148                         $qty = 0;
1149                 }
1150                 if ($max == 0)
1151                 {
1152                         return $qty;
1153                 }
1154                 else
1155                 {
1156                         return ($qty > $max) ? $max : $qty;
1157                 }
1158         }
1159         
1160         function get_item($key = 0)
1161         {
1162                 if (!empty($this->data['items'][$key]))
1163                 {
1164                         return $this->data['items'][$key];
1165                 }
1166                 else
1167                 {
1168                         return false;
1169                 }
1170         }
1171         
1172         function get_items($start = 0, $end = 0)
1173         {
1174                 if ($this->get_item_quantity() > 0)
1175                 {
1176                         if ($end == 0)
1177                         {
1178                                 return array_slice($this->data['items'], $start);
1179                         }
1180                         else
1181                         {
1182                                 return array_slice($this->data['items'], $start, $end);
1183                         }
1184                 }
1185                 else
1186                 {
1187                         return false;
1188                 }
1189         }
1190 }
1191
1192 class SimplePie_Item
1193 {
1194         var $data;
1195         
1196         function SimplePie_Item($data)
1197         {
1198                 $this->data =& $data;
1199         }
1200         
1201         function get_id()
1202         {
1203                 if (!empty($this->data['guid']['data']))
1204                 {
1205                         return $this->data['guid']['data'];
1206                 }
1207                 else if (!empty($this->data['id']))
1208                 {
1209                         return $this->data['id'];
1210                 }
1211                 else
1212                 {
1213                         return false;
1214                 }
1215         }
1216         
1217         function get_title()
1218         {
1219                 if (!empty($this->data['title']))
1220                 {
1221                         return $this->data['title'];
1222                 }
1223                 else if (!empty($this->data['dc:title']))
1224                 {
1225                         return $this->data['dc:title'];
1226                 }
1227                 else
1228                 {
1229                         return false;
1230                 }
1231         }
1232         
1233         function get_description()
1234         {
1235                 if (!empty($this->data['content']))
1236                 {
1237                         return $this->data['content'];
1238                 }
1239                 else if (!empty($this->data['encoded']))
1240                 {
1241                         return $this->data['encoded'];
1242                 }
1243                 else if (!empty($this->data['summary']))
1244                 {
1245                         return $this->data['summary'];
1246                 }
1247                 else if (!empty($this->data['description']))
1248                 {
1249                         return $this->data['description'];
1250                 }
1251                 else if (!empty($this->data['dc:description']))
1252                 {
1253                         return $this->data['dc:description'];
1254                 }
1255                 else if (!empty($this->data['longdesc']))
1256                 {
1257                         return $this->data['longdesc'];
1258                 }
1259                 else
1260                 {
1261                         return false;
1262                 }
1263         }
1264         
1265         function get_category($key = 0)
1266         {
1267                 $categories = $this->get_categories();
1268                 if (!empty($categories[$key]))
1269                 {
1270                         return $categories[$key];
1271                 }
1272                 else
1273                 {
1274                         return false;
1275                 }
1276         }
1277         
1278         function get_categories()
1279         {
1280                 $categories = array();
1281                 if (!empty($this->data['category']))
1282                 {
1283                         $categories = array_merge($categories, $this->data['category']);
1284                 }
1285                 if (!empty($this->data['subject']))
1286                 {
1287                         $categories = array_merge($categories, $this->data['subject']);
1288                 }
1289                 if (!empty($this->data['term']))
1290                 {
1291                         $categories = array_merge($categories, $this->data['term']);
1292                 }
1293                 if (!empty($categories))
1294                 {
1295                         return array_unique($categories);
1296                 }
1297                 else
1298                 {
1299                         return false;
1300                 }
1301         }
1302         
1303         function get_author($key = 0)
1304         {
1305                 $authors = $this->get_authors();
1306                 if (!empty($authors[$key]))
1307                 {
1308                         return $authors[$key];
1309                 }
1310                 else
1311                 {
1312                         return false;
1313                 }
1314         }
1315         
1316         function get_authors()
1317         {
1318                 $authors = array();
1319                 if (!empty($this->data['author']))
1320                 {
1321                         $authors = array_merge($authors, $this->data['author']);
1322                 }
1323                 if (!empty($this->data['creator']))
1324                 {
1325                         $authors = array_merge($authors, $this->data['creator']);
1326                 }
1327                 if (!empty($authors))
1328                 {
1329                         return array_unique($authors);
1330                 }
1331                 else
1332                 {
1333                         return false;
1334                 }
1335         }
1336         
1337         function get_date($date_format = 'j F Y, g:i a')
1338         {
1339                 if (!empty($this->data['pubdate']))
1340                 {
1341                         return date($date_format, $this->data['pubdate']);
1342                 }
1343                 else if (!empty($this->data['dc:date']))
1344                 {
1345                         return date($date_format, $this->data['dc:date']);
1346                 }
1347                 else if (!empty($this->data['issued']))
1348                 {
1349                         return date($date_format, $this->data['issued']);
1350                 }
1351                 else if (!empty($this->data['published']))
1352                 {
1353                         return date($date_format, $this->data['published']);
1354                 }
1355                 else if (!empty($this->data['modified']))
1356                 {
1357                         return date($date_format, $this->data['modified']);
1358                 }
1359                 else if (!empty($this->data['updated']))
1360                 {
1361                         return date($date_format, $this->data['updated']);
1362                 }
1363                 else
1364                 {
1365                         return false;
1366                 }
1367         }
1368         
1369         function get_permalink()
1370         {
1371                 $link = $this->get_link(0);
1372                 $enclosure = $this->get_enclosure(0);
1373                 if (!empty($link))
1374                 {
1375                         return $link;
1376                 }
1377                 else if (!empty($enclosure))
1378                 {
1379                         return $enclosure->get_link();
1380                 }
1381                 else
1382                 {
1383                         return false;
1384                 }
1385         }
1386         
1387         function get_link($key = 0, $rel = 'alternate')
1388         {
1389                 $links = $this->get_links($rel);
1390                 if (!empty($links[$key]))
1391                 {
1392                         return $links[$key];
1393                 }
1394                 else
1395                 {
1396                         return false;
1397                 }
1398         }
1399         
1400         function get_links($rel = 'alternate')
1401         {
1402                 if ($rel == 'alternate')
1403                 {
1404                         $links = array();
1405                         if (!empty($this->data['link'][$rel]))
1406                         {
1407                                 $links = $this->data['link'][$rel];
1408                         }
1409                         if (!empty($this->data['guid']['data']) && $this->data['guid']['permalink'] == true)
1410                         {
1411                                 $links[] = $this->data['guid']['data'];
1412                         }
1413                         return $links;
1414                 }
1415                 else if (!empty($this->data['link'][$rel]))
1416                 {
1417                         return $this->data['link'][$rel];
1418                 }
1419                 else
1420                 {
1421                         return false;
1422                 }
1423         }
1424         
1425         function get_enclosure($key = 0)
1426         {
1427                 $enclosures = $this->get_enclosures();
1428                 if (!empty($enclosures[$key]))
1429                 {
1430                         return $enclosures[$key];
1431                 }
1432                 else
1433                 {
1434                         return false;
1435                 }
1436         }
1437         
1438         function get_enclosures()
1439         {
1440                 $enclosures = array();
1441                 $links = $this->get_links('enclosure');
1442                 if (!empty($this->data['enclosures']))
1443                 {
1444                         $enclosures = array_merge($enclosures, $this->data['enclosures']);
1445                 }
1446                 if (!empty($links))
1447                 {
1448                         $enclosures = array_merge($enclosures, $links);
1449                 }
1450                 if (!empty($enclosures))
1451                 {
1452                         return array_unique($enclosures);
1453                 }
1454                 else
1455                 {
1456                         return false;
1457                 }
1458         }
1459         
1460         function add_to_blinklist()
1461         {
1462                 if ($this->get_permalink())
1463                 {
1464                         $url = 'http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;Description=&amp;Url=' . rawurlencode($this->get_permalink());
1465                         if ($this->get_title())
1466                         {
1467                                 $url .= '&amp;Title=' . rawurlencode($this->get_title());
1468                         }
1469                         return $url;
1470                 }
1471                 else
1472                 {
1473                         return false;
1474                 }
1475         }
1476         
1477         function add_to_blogmarks()
1478         {
1479                 if ($this->get_permalink())
1480                 {
1481                         $url = 'http://blogmarks.net/my/new.php?mini=1&amp;simple=1&amp;url=' . rawurlencode($this->get_permalink());
1482                         if ($this->get_title())
1483                         {
1484                                 $url .= '&amp;title=' . rawurlencode($this->get_title());
1485                         }
1486                         return $url;
1487                 }
1488                 else
1489                 {
1490                         return false;
1491                 }
1492         }
1493         
1494         function add_to_delicious()
1495         {
1496                 if ($this->get_permalink())
1497                 {
1498                         $url = 'http://del.icio.us/post/?v=3&amp;url=' . rawurlencode($this->get_permalink());
1499                         if ($this->get_title())
1500                         {
1501                                 $url .= '&amp;title=' . rawurlencode($this->get_title());
1502                         }
1503                         return $url;
1504                 }
1505                 else
1506                 {
1507                         return false;
1508                 }
1509         }
1510         
1511         function add_to_digg()
1512         {
1513                 if ($this->get_permalink())
1514                 {
1515                         return 'http://digg.com/submit?phase=2&amp;URL=' . rawurlencode($this->get_permalink());
1516                 }
1517                 else
1518                 {
1519                         return false;
1520                 }
1521         }
1522         
1523         function add_to_furl()
1524         {
1525                 if ($this->get_permalink())
1526                 {
1527                         $url = 'http://www.furl.net/storeIt.jsp?u=' . rawurlencode($this->get_permalink());
1528                         if ($this->get_title())
1529                         {
1530                                 $url .= '&amp;t=' . rawurlencode($this->get_title());
1531                         }
1532                         return $url;
1533                 }
1534                 else
1535                 {
1536                         return false;
1537                 }
1538         }
1539         
1540         function add_to_magnolia()
1541         {
1542                 if ($this->get_permalink())
1543                 {
1544                         $url = 'http://ma.gnolia.com/bookmarklet/add?url=' . rawurlencode($this->get_permalink());
1545                         if ($this->get_title())
1546                         {
1547                                 $url .= '&amp;title=' . rawurlencode($this->get_title());
1548                         }
1549                         return $url;
1550                 }
1551                 else
1552                 {
1553                         return false;
1554                 }
1555         }
1556         
1557         function add_to_myweb20()
1558         {
1559                 if ($this->get_permalink())
1560                 {
1561                         $url = 'http://myweb2.search.yahoo.com/myresults/bookmarklet?u=' . rawurlencode($this->get_permalink());
1562                         if ($this->get_title())
1563                         {
1564                                 $url .= '&amp;t=' . rawurlencode($this->get_title());
1565                         }
1566                         return $url;
1567                 }
1568                 else
1569                 {
1570                         return false;
1571                 }
1572         }
1573         
1574         function add_to_newsvine()
1575         {
1576                 if ($this->get_permalink())
1577                 {
1578                         $url = 'http://www.newsvine.com/_wine/save?u=' . rawurlencode($this->get_permalink());
1579                         if ($this->get_title())
1580                         {
1581                                 $url .= '&amp;h=' . rawurlencode($this->get_title());
1582                         }
1583                         return $url;
1584                 }
1585                 else
1586                 {
1587                         return false;
1588                 }
1589         }
1590         
1591         function add_to_reddit()
1592         {
1593                 if ($this->get_permalink())
1594                 {
1595                         $url = 'http://reddit.com/submit?url=' . rawurlencode($this->get_permalink());
1596                         if ($this->get_title())
1597                         {
1598                                 $url .= '&amp;title=' . rawurlencode($this->get_title());
1599                         }
1600                         return $url;
1601                 }
1602                 else
1603                 {
1604                         return false;
1605                 }
1606         }
1607         
1608         function add_to_segnalo()
1609         {
1610                 if ($this->get_permalink())
1611                 {
1612                         $url = 'http://segnalo.com/post.html.php?url=' . rawurlencode($this->get_permalink());
1613                         if ($this->get_title())
1614                         {
1615                                 $url .= '&amp;title=' . rawurlencode($this->get_title());
1616                         }
1617                         return $url;
1618                 }
1619                 else
1620                 {
1621                         return false;
1622                 }
1623         }
1624         
1625         function add_to_simpy()
1626         {
1627                 if ($this->get_permalink())
1628                 {
1629                         $url = 'http://www.simpy.com/simpy/LinkAdd.do?href=' . rawurlencode($this->get_permalink());
1630                         if ($this->get_title())
1631                         {
1632                                 $url .= '&amp;title=' . rawurlencode($this->get_title());
1633                         }
1634                         return $url;
1635                 }
1636                 else
1637                 {
1638                         return false;
1639                 }
1640         }
1641         
1642         function add_to_smarking()
1643         {
1644                 if ($this->get_permalink())
1645                 {
1646                         return 'http://smarking.com/editbookmark/?url=' . rawurlencode($this->get_permalink());
1647                 }
1648                 else
1649                 {
1650                         return false;
1651                 }
1652         }
1653         
1654         function add_to_spurl()
1655         {
1656                 if ($this->get_permalink())
1657                 {
1658                         $url = 'http://www.spurl.net/spurl.php?v=3&amp;url=' . rawurlencode($this->get_permalink());
1659                         if ($this->get_title())
1660                         {
1661                                 $url .= '&amp;title=' . rawurlencode($this->get_title());
1662                         }
1663                         return $url;
1664                 }
1665                 else
1666                 {
1667                         return false;
1668                 }
1669         }
1670         
1671         function add_to_wists()
1672         {
1673                 if ($this->get_permalink())
1674                 {
1675                         $url = 'http://wists.com/r.php?c=&amp;r=' . rawurlencode($this->get_permalink());
1676                         if ($this->get_title())
1677                         {
1678                                 $url .= '&amp;title=' . rawurlencode($this->get_title());
1679                         }
1680                         return $url;
1681                 }
1682                 else
1683                 {
1684                         return false;
1685                 }
1686         }
1687         
1688         function search_technorati()
1689         {
1690                 if ($this->get_permalink())
1691                 {
1692                         return 'http://www.technorati.com/search/' . rawurlencode($this->get_permalink());
1693                 }
1694                 else
1695                 {
1696                         return false;
1697                 }
1698         }
1699 }
1700
1701 class SimplePie_Author
1702 {
1703         var $name;
1704         var $link;
1705         var $email;
1706         
1707         // Constructor, used to input the data
1708         function SimplePie_Author($name, $link, $email)
1709         {
1710                 $this->name = $name;
1711                 $this->link = $link;
1712                 $this->email = $email;
1713         }
1714         
1715         function get_name()
1716         {
1717                 if (!empty($this->name))
1718                 {
1719                         return $this->name;
1720                 }
1721                 else
1722                 {
1723                         return false;
1724                 }
1725         }
1726         
1727         function get_link()
1728         {
1729                 if (!empty($this->link))
1730                 {
1731                         return $this->link;
1732                 }
1733                 else
1734                 {
1735                         return false;
1736                 }
1737         }
1738         
1739         function get_email()
1740         {
1741                 if (!empty($this->email))
1742                 {
1743                         return $this->email;
1744                 }
1745                 else
1746                 {
1747                         return false;
1748                 }
1749         }
1750 }
1751
1752 class SimplePie_Enclosure
1753 {
1754         var $link;
1755         var $type;
1756         var $length;
1757
1758         // Constructor, used to input the data
1759         function SimplePie_Enclosure($link, $type, $length)
1760         {
1761                 $this->link = $link;
1762                 $this->type = $type;
1763                 $this->length = $length;
1764         }
1765
1766         function get_link()
1767         {
1768                 if (!empty($this->link))
1769                 {
1770                         if (class_exists('idna_convert'))
1771                         {
1772                                 $idn = new idna_convert;
1773                                 $this->link = $idn->encode($this->link);
1774                         }
1775                         return $this->link;
1776                 }
1777                 else
1778                 {
1779                         return false;
1780                 }
1781         }
1782
1783         function get_extension()
1784         {
1785                 if (!empty($this->link))
1786                 {
1787                         return pathinfo($this->link, PATHINFO_EXTENSION);
1788                 }
1789                 else
1790                 {
1791                         return false;
1792                 }
1793         }
1794
1795         function get_type()
1796         {
1797                 if (!empty($this->type))
1798                 {
1799                         return $this->type;
1800                 }
1801                 else
1802                 {
1803                         return false;
1804                 }
1805         }
1806
1807         function get_length()
1808         {
1809                 if (!empty($this->length))
1810                 {
1811                         return $this->length;
1812                 }
1813                 else
1814                 {
1815                         return false;
1816                 }
1817         }
1818
1819         function get_size()
1820         {
1821                 $length = $this->get_length();
1822                 if (!empty($length))
1823                 {
1824                         return round($length/1048576, 2);
1825                 }
1826                 else
1827                 {
1828                         return false;
1829                 }
1830         }
1831
1832         function native_embed($options='')
1833         {
1834                 return $this->embed($options, true);            
1835         }
1836
1837         function embed($options = '', $native = false)
1838         {
1839                 // Set up defaults
1840                 $audio = '';
1841                 $video = '';
1842                 $alt = '';
1843                 $altclass = '';
1844                 $loop = 'false';
1845                 $width = 'auto';
1846                 $height = 'auto';
1847                 $bgcolor = '#ffffff';
1848
1849                 // Process options and reassign values as necessary
1850                 if (is_array($options))
1851                 {
1852                         extract($options);
1853                 }
1854                 else
1855                 {
1856                         $options = explode(',', $options);
1857                         foreach($options as $option)
1858                         {
1859                                 $opt = explode(':', $option, 2);
1860                                 if (isset($opt[0], $opt[1]))
1861                                 {
1862                                         $opt[0] = trim($opt[0]);
1863                                         $opt[1] = trim($opt[1]);
1864                                         switch ($opt[0])
1865                                         {
1866                                                 case 'audio':
1867                                                         $audio = $opt[1];
1868                                                         break;
1869                                                 
1870                                                 case 'video':
1871                                                         $video = $opt[1];
1872                                                         break;
1873                                                 
1874                                                 case 'alt':
1875                                                         $alt = $opt[1];
1876                                                         break;
1877                                                 
1878                                                 case 'altclass':
1879                                                         $altclass = $opt[1];
1880                                                         break;
1881                                                 
1882                                                 case 'loop':
1883                                                         $loop = $opt[1];
1884                                                         break;
1885                                                 
1886                                                 case 'width':
1887                                                         $width = $opt[1];
1888                                                         break;
1889                                                 
1890                                                 case 'height':
1891                                                         $height = $opt[1];
1892                                                         break;
1893                                                 
1894                                                 case 'bgcolor':
1895                                                         $bgcolor = $opt[1];
1896                                                         break;
1897                                         }
1898                                 }
1899                         }
1900                 }
1901         
1902                 $type = strtolower($this->get_type());
1903
1904                 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
1905                 if (!in_array($type, array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mpeg', 'audio/x-mpeg', 'audio/mp3', 'x-audio/mp3', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video', 'application/x-shockwave-flash', 'application/futuresplash', 'application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx')))
1906                 {                       
1907                         switch (strtolower($this->get_extension()))
1908                         {
1909                                 // Audio mime-types
1910                                 case 'aac':
1911                                 case 'adts':
1912                                         $type = 'audio/acc';
1913                                         break;
1914                                 
1915                                 case 'aif':
1916                                 case 'aifc':
1917                                 case 'aiff':
1918                                 case 'cdda':
1919                                         $type = 'audio/aiff';
1920                                         break;
1921                                 
1922                                 case 'bwf':
1923                                         $type = 'audio/wav';
1924                                         break;
1925                                 
1926                                 case 'kar':
1927                                 case 'mid':
1928                                 case 'midi':
1929                                 case 'smf':
1930                                         $type = 'audio/midi';
1931                                         break;
1932                                 
1933                                 case 'm4a':
1934                                         $type = 'audio/x-m4a';
1935                                         break;
1936                                 
1937                                 case 'mp3':
1938                                 case 'swa':
1939                                         $type = 'audio/mp3';
1940                                         break;
1941                                 
1942                                 case 'wav':
1943                                         $type = 'audio/wav';
1944                                         break;
1945                                 
1946                                 case 'wax':
1947                                         $type = 'audio/x-ms-wax';
1948                                         break;
1949                                 
1950                                 case 'wma':
1951                                         $type = 'audio/x-ms-wma';
1952                                         break;
1953                                 
1954                                 // Video mime-types
1955                                 case '3gp':
1956                                 case '3gpp':
1957                                         $type = 'video/3gpp';
1958                                         break;
1959
1960                                 case '3g2':
1961                                 case '3gp2':
1962                                         $type = 'video/3gpp2';
1963                                         break;
1964
1965                                 case 'asf':
1966                                         $type = 'video/x-ms-asf';
1967                                         break;
1968
1969                                 case 'm1a':
1970                                 case 'm1s':
1971                                 case 'm1v':
1972                                 case 'm15':
1973                                 case 'm75':
1974                                 case 'mp2':
1975                                 case 'mpa':
1976                                 case 'mpeg':
1977                                 case 'mpg':
1978                                 case 'mpm':
1979                                 case 'mpv':
1980                                         $type = 'video/mpeg';
1981                                         break;
1982
1983                                 case 'm4v':
1984                                         $type = 'video/x-m4v';
1985                                         break;
1986
1987                                 case 'mov':
1988                                 case 'qt':
1989                                         $type = 'video/quicktime';
1990                                         break;
1991
1992                                 case 'mp4':
1993                                 case 'mpg4':
1994                                         $type = 'video/mp4';
1995                                         break;
1996
1997                                 case 'sdv':
1998                                         $type = 'video/sd-video';
1999                                         break;
2000
2001                                 case 'wm':
2002                                         $type = 'video/x-ms-wm';
2003                                         break;
2004
2005                                 case 'wmv':
2006                                         $type = 'video/x-ms-wmv';
2007                                         break;
2008
2009                                 case 'wvx':
2010                                         $type = 'video/x-ms-wvx';
2011                                         break;
2012                                         
2013                                 // Flash mime-types
2014                                 case 'spl':
2015                                         $type = 'application/futuresplash';
2016                                         break;
2017
2018                                 case 'swf':
2019                                         $type = 'application/x-shockwave-flash';
2020                                         break;
2021                         }
2022                 }
2023
2024                 $mime = explode('/', $type, 2);
2025                 $mime = $mime[0];
2026                 
2027                 // Process values for 'auto'
2028                 if ($width == 'auto')
2029                 {
2030                         if ($mime == 'video')
2031                         {
2032                                 $width = '320';
2033                         }
2034                         else
2035                         {
2036                                 $width = '100%';
2037                         }
2038                 }
2039                 if ($height == 'auto')
2040                 {
2041                         if ($mime == 'audio')
2042                         {
2043                                 $height = 0;
2044                         }
2045                         else if ($mime == 'video')
2046                         {
2047                                 $height = 240;
2048                         }
2049                         else
2050                         {
2051                                 $height = 256;
2052                         }
2053                 }
2054
2055                 // Set proper placeholder value
2056                 if ($mime == 'audio')
2057                 {
2058                         $placeholder = $audio;
2059                 }
2060                 else if ($mime == 'video')
2061                 {
2062                         $placeholder = $video;
2063                 }
2064
2065                 $embed = '';
2066
2067                 // Make sure the JS library is included
2068                 // (I know it'll be included multiple times, but I can't think of a better way to do this automatically)
2069                 if (!$native)
2070                 {
2071                         $embed .= '<script type="text/javascript" src="?js"></script>';                 
2072                 }
2073
2074                 // Odeo Feed MP3's
2075                 if (substr(strtolower($this->get_link()), 0, 15) == 'http://odeo.com') {
2076                         if ($native)
2077                         {
2078                                 $embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url=' . $this->get_link() . '"></embed>';
2079                         }
2080                         else
2081                         {
2082                                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';                           
2083                         }
2084                 }
2085
2086                 // QuickTime 7 file types.  Need to test with QuickTime 6.
2087                 else if (in_array($type, array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mpeg', 'audio/x-mpeg', 'audio/mp3', 'x-audio/mp3', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video')))
2088                 {
2089                         $height += 16;
2090                         if ($native)
2091                         {
2092                                 if ($placeholder != "") {
2093                                         $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://www.apple.com/quicktime/download/\"></embed>";
2094                                 }
2095                                 else {
2096                                         $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width+\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://www.apple.com/quicktime/download/\"></embed>";
2097                                 }
2098                         }
2099                         else
2100                         {
2101                                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
2102                         }
2103                 }
2104
2105                 // Flash
2106                 else if (in_array($type, array('application/x-shockwave-flash', 'application/futuresplash')))
2107                 {
2108                         if ($native)
2109                         {
2110                                 $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
2111                         }
2112                         else
2113                         {
2114                                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
2115                         }
2116                 }
2117
2118                 // Windows Media
2119                 else if (in_array($type, array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx')))
2120                 {
2121                         $height += 45;
2122                         if ($native)
2123                         {
2124                                 $embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
2125                         }
2126                         else
2127                         {
2128                                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
2129                         }
2130                 }
2131
2132                 // Everything else
2133                 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
2134
2135                 return $embed;
2136         }
2137 }
2138
2139 class SimplePie_File
2140 {
2141         var $url;
2142         var $useragent;
2143         var $success = true;
2144         var $headers = array();
2145         var $body;
2146         var $fp;
2147         var $redirects = 0;
2148         var $error;
2149         var $method;
2150         
2151         function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
2152         {
2153                 if (class_exists('idna_convert'))
2154                 {
2155                         $idn = new idna_convert;
2156                         $url = $idn->encode($url);
2157                 }
2158                 $this->url = $url;
2159                 $this->useragent = $useragent;
2160                 if (preg_match('/^http(s)?:\/\//i', $url))
2161                 {
2162                         if (empty($useragent))
2163                         {
2164                                 $useragent = ini_get('user_agent');
2165                                 $this->useragent = $useragent;
2166                         }
2167                         if (!is_array($headers))
2168                         {
2169                                 $headers = array();
2170                         }
2171                         if (extension_loaded('curl') && version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>=') && !$force_fsockopen)
2172                         {
2173                                 $this->method = 'curl';
2174                                 $fp = curl_init();
2175                                 $headers2 = array();
2176                                 foreach ($headers as $key => $value)
2177                                 {
2178                                         $headers2[] = "$key: $value";
2179                                 }
2180                                 curl_setopt($fp, CURLOPT_ENCODING, '');
2181                                 curl_setopt($fp, CURLOPT_URL, $url);
2182                                 curl_setopt($fp, CURLOPT_HEADER, 1);
2183                                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
2184                                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
2185                                 curl_setopt($fp, CURLOPT_REFERER, $url);
2186                                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
2187                                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
2188                                 if (!ini_get('open_basedir') && !ini_get('safe_mode'))
2189                                 {
2190                                         curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
2191                                         curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
2192                                 }
2193
2194                                 $this->headers = trim(curl_exec($fp));
2195                                 if (curl_errno($fp) == 23 || curl_errno($fp) == 61)
2196                                 {
2197                                         curl_setopt($fp, CURLOPT_ENCODING, 'none');
2198                                         $this->headers = trim(curl_exec($fp));
2199                                 }
2200                                 if (curl_errno($fp))
2201                                 {
2202                                         $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
2203                                         $this->success = false;
2204                                         return false;
2205                                 }
2206                                 $info = curl_getinfo($fp);
2207                                 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 2);
2208                                 if (count($this->headers) == $info['redirect_count'] + 1)
2209                                 {
2210                                         $this->headers = array_pop($this->headers);
2211                                         $this->body = '';
2212                                 }
2213                                 else
2214                                 {
2215                                         $this->body = array_pop($this->headers);
2216                                         $this->headers = array_pop($this->headers);
2217                                 }
2218                                 $this->headers = $this->parse_headers($this->headers);
2219                                 if (($this->headers['status']['code'] == 301 || $this->headers['status']['code'] == 302 || $this->headers['status']['code'] == 303 || $this->headers['status']['code'] == 307) && !empty($this->headers['location']) && $this->redirects < $redirects)
2220                                 {
2221                                         $this->redirects++;
2222                                         return $this->SimplePie_File($this->headers['location'], $timeout, $redirects, $headers, $useragent, $force_fsockopen);
2223                                 }
2224                         }
2225                         else
2226                         {
2227                                 $this->method = 'fsockopen';
2228                                 $url_parts = parse_url($url);
2229                                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) == 'https')
2230                                 {
2231                                         $url_parts['host'] = "ssl://$url_parts[host]";
2232                                         $url_parts['port'] = 443;
2233                                 }
2234                                 if (!isset($url_parts['port']))
2235                                 {
2236                                         $url_parts['port'] = 80;
2237                                 }
2238                                 $this->fp = fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
2239                                 if (!$this->fp)
2240                                 {
2241                                         $this->error = 'fsockopen error: ' . $errstr;
2242                                         $this->success = false;
2243                                         return false;
2244                                 }
2245                                 else
2246                                 {
2247                                         stream_set_timeout($this->fp, $timeout);
2248                                         $get = (isset($url_parts['query'])) ? "$url_parts[path]?$url_parts[query]" : $url_parts['path'];
2249                                         $out = "GET $get HTTP/1.0\r\n";
2250                                         $out .= "Host: $url_parts[host]\r\n";
2251                                         $out .= "User-Agent: $useragent\r\n";
2252                                         if (function_exists('gzinflate'))
2253                                         {
2254                                                 $out .= "Accept-Encoding: gzip,deflate\r\n";
2255                                         }
2256
2257                                         if (!empty($url_parts['user']) && !empty($url_parts['pass']))
2258                                         {
2259                                                 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
2260                                         }
2261                                         foreach ($headers as $key => $value)
2262                                         {
2263                                                 $out .= "$key: $value\r\n";
2264                                         }
2265                                         $out .= "Connection: Close\r\n\r\n";
2266                                         fwrite($this->fp, $out);
2267                                         
2268                                         $info = stream_get_meta_data($this->fp);
2269                                         $data = '';
2270                                         while (strpos($data, "\r\n\r\n") === false && !$info['timed_out'])
2271                                         {
2272                                                 $data .= fgets($this->fp, 128);
2273                                                 $info = stream_get_meta_data($this->fp);
2274                                         }
2275                                         if (!$info['timed_out'])
2276                                         {
2277                                                 $this->headers = $this->parse_headers($data);
2278                                                 if (($this->headers['status']['code'] == 301 || $this->headers['status']['code'] == 302 || $this->headers['status']['code'] == 303 || $this->headers['status']['code'] == 307) && !empty($this->headers['location']) && $this->redirects < $redirects)
2279                                                 {
2280                                                         $this->redirects++;
2281                                                         return $this->SimplePie_File($this->headers['location'], $timeout, $redirects, $headers, $useragent, $force_fsockopen);
2282                                                 }
2283                                         }
2284                                         else
2285                                         {
2286                                                 $this->close();
2287                                                 $this->error = 'fsocket timed out';
2288                                                 $this->success = false;
2289                                                 return false;
2290                                         }
2291                                 }
2292                         }
2293                         return $this->headers['status']['code'];
2294                 }
2295                 else
2296                 {
2297                         $this->method = 'fopen';
2298                         if ($this->fp = fopen($url, 'r'))
2299                         {
2300                                 return true;
2301                         }
2302                         else
2303                         {
2304                                 $this->error = 'fopen could not open the file';
2305                                 $this->success = false;
2306                                 return false;
2307                         }
2308                 }
2309         }
2310         
2311         function headers()
2312         {
2313                 return $this->headers;
2314         }
2315         
2316         function body()
2317         {
2318                 if (is_null($this->body))
2319                 {
2320                         if ($this->fp)
2321                         {
2322                                 $info = stream_get_meta_data($this->fp);
2323                                 $this->body = '';
2324                                 while (!$info['eof'] && !$info['timed_out'])
2325                                 {
2326                                         $this->body .= fread($this->fp, 1024);
2327                                         $info = stream_get_meta_data($this->fp);
2328                                 }
2329                                 if (!$info['timed_out'])
2330                                 {
2331                                         $this->body = trim($this->body);
2332                                         if ($this->method == 'fsockopen' && !empty($this->headers['content-encoding']) && ($this->headers['content-encoding'] == 'gzip' || $this->headers['content-encoding'] == 'deflate'))
2333                                         {
2334                                                 if (substr($this->body, 0, 8) == "\x1f\x8b\x08\x00\x00\x00\x00\x00")
2335                                                 {
2336                                                         $this->body = substr($this->body, 10);
2337                                                 }
2338                                                 $this->body = gzinflate($this->body);
2339                                         }
2340                                         $this->close();
2341                                 }
2342                                 else
2343                                 {
2344                                         return false;
2345                                 }
2346                         }
2347                         else
2348                         {
2349                                 return false;
2350                         }
2351                 }
2352                 return $this->body;
2353         }
2354         
2355         function close()
2356         {
2357                 if (!is_null($this->fp))
2358                 {
2359                         if (fclose($this->fp))
2360                         {
2361                                 $this->fp = null;
2362                                 return true;
2363                         }
2364                         else
2365                         {
2366                                 return false;
2367                         }
2368                 }
2369                 else
2370                 {
2371                         return false;
2372                 }
2373         }
2374         
2375         function parse_headers($headers)
2376         {
2377                 $headers = explode("\r\n", trim($headers));
2378                 $status = array_shift($headers);
2379                 foreach ($headers as $header)
2380                 {
2381                         $data = explode(':', $header, 2);
2382                         $head[strtolower(trim($data[0]))] = trim($data[1]);
2383                 }
2384                 if (preg_match('/HTTP\/[0-9\.]+ ([0-9]+)(.*)$/i', $status, $matches))
2385                 {
2386                         if (isset($head['status']))
2387                         {
2388                                 unset($head['status']);
2389                         }
2390                         $head['status']['code'] = $matches[1];
2391                         $head['status']['name'] = trim($matches[2]);
2392                 }
2393                 return $head;
2394         }
2395 }
2396
2397 class SimplePie_Cache
2398 {
2399         var $location;
2400         var $filename;
2401         var $extension;
2402         var $name;
2403         
2404         function SimplePie_Cache($location, $filename, $extension)
2405         {
2406                 $this->location = $location;
2407                 $this->filename = rawurlencode($filename);
2408                 $this->extension = rawurlencode($extension);
2409                 $this->name = "$location/$this->filename.$this->extension";
2410         }
2411         
2412         function save($data)
2413         {
2414                 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
2415                 {
2416                         $fp = fopen($this->name, 'w');
2417                         if ($fp)
2418                         {
2419                                 fwrite($fp, serialize($data));
2420                                 fclose($fp);
2421                                 return true;
2422                         }
2423                 }
2424                 return false;
2425         }
2426         
2427         function load()
2428         {
2429                 if (file_exists($this->name) && is_readable($this->name))
2430                 {
2431                         return unserialize(file_get_contents($this->name));
2432                 }
2433                 return false;
2434         }
2435         
2436         function mtime()
2437         {
2438                 if (file_exists($this->name))
2439                 {
2440                         return filemtime($this->name);
2441                 }
2442                 return false;
2443         }
2444         
2445         function touch()
2446         {
2447                 if (file_exists($this->name))
2448                 {
2449                         return touch($this->name);
2450                 }
2451                 return false;
2452         }
2453         
2454         function unlink()
2455         {
2456                 if (file_exists($this->name))
2457                 {
2458                         return unlink($this->name);
2459                 }
2460                 return false;
2461         }
2462 }
2463
2464 class SimplePie_Misc
2465 {
2466         function absolutize_url($relative, $base)
2467         {
2468                 $relative = trim($relative);
2469                 $base = trim($base);
2470                 if (!empty($relative))
2471                 {
2472                         $relative = SimplePie_Misc::parse_url($relative, false);
2473                         $relative = array('scheme' => $relative[2], 'authority' => $relative[3], 'path' => $relative[5], 'query' => $relative[7], 'fragment' => $relative[9]);
2474                         if (!empty($relative['scheme']))
2475                         {
2476                                 $target = $relative;
2477                         }
2478                         else if (!empty($base))
2479                         {
2480                                 $base = SimplePie_Misc::parse_url($base, false);
2481                                 $base = array('scheme' => $base[2], 'authority' => $base[3], 'path' => $base[5], 'query' => $base[7], 'fragment' => $base[9]);
2482                                 $target['scheme'] = $base['scheme'];
2483                                 if (!empty($relative['authority']))
2484                                 {
2485                                         $target = array_merge($relative, $target);
2486                                 }
2487                                 else
2488                                 {
2489                                         $target['authority'] = $base['authority'];
2490                                         if (!empty($relative['path']))
2491                                         {
2492                                                 if (strpos($relative['path'], '/') === 0)
2493                                                 {
2494                                                         $target['path'] = $relative['path'];
2495                                                 }
2496                                                 else
2497                                                 {
2498                                                         if (!empty($base['path']))
2499                                                         {
2500                                                                 $target['path'] = dirname("$base[path].") . '/' . $relative['path'];
2501                                                         }
2502                                                         else
2503                                                         {
2504                                                                 $target['path'] = '/' . $relative['path'];
2505                                                         }
2506                                                 }
2507                                                 if (!empty($relative['query']))
2508                                                 {
2509                                                         $target['query'] = $relative['query'];
2510                                                 }
2511                                                 $input = $target['path'];
2512                                                 $target['path'] = '';
2513                                                 while (!empty($input))
2514                                                 {
2515                                                         if (strpos($input, '../') === 0)
2516                                                         {
2517                                                                 $input = substr($input, 3);
2518                                                         }
2519                                                         else if (strpos($input, './') === 0)
2520                                                         {
2521                                                                 $input = substr($input, 2);
2522                                                         }
2523                                                         else if (strpos($input, '/./') === 0)
2524                                                         {
2525                                                                 $input = substr_replace($input, '/', 0, 3);
2526                                                         }
2527                                                         else if (strpos($input, '/.') === 0 && SimplePie_Misc::strendpos($input, '/.') === 0)
2528                                                         {
2529                                                                 $input = substr_replace($input, '/', -2);
2530                                                         }
2531                                                         else if (strpos($input, '/../') === 0)
2532                                                         {
2533                                                                 $input = substr_replace($input, '/', 0, 4);
2534                                                                 $target['path'] = preg_replace('/(\/)?([^\/]+)$/msiU', '', $target['path']);
2535                                                         }
2536                                                         else if (strpos($input, '/..') === 0 && SimplePie_Misc::strendpos($input, '/..') === 0)
2537                                                         {
2538                                                                 $input = substr_replace($input, '/', 0, 3);
2539                                                                 $target['path'] = preg_replace('/(\/)?([^\/]+)$/msiU', '', $target['path']);
2540                                                         }
2541                                                         else if ($input == '.' || $input == '..')
2542                                                         {
2543                                                                 $input = '';
2544                                                         }
2545                                                         else
2546                                                         {
2547                                                                 if (preg_match('/^(.+)(\/|$)/msiU', $input, $match))
2548                                                                 {
2549                                                                         $target['path'] .= $match[1];
2550                                                                         $input = substr_replace($input, '', 0, strlen($match[1]));
2551                                                                 }
2552                                                         }
2553                                                 }
2554                                         }
2555                                         else
2556                                         {
2557                                                 if (!empty($base['path']))
2558                                                 {
2559                                                         $target['path'] = $base['path'];
2560                                                 }
2561                                                 else
2562                                                 {
2563                                                         $target['path'] = '/';
2564                                                 }
2565                                                 if (!empty($relative['query']))
2566                                                 {
2567                                                         $target['query'] = $relative['query'];
2568                                                 }
2569                                                 else if (!empty($base['query']))
2570                                                 {
2571                                                         $target['query'] = $base['query'];
2572                                                 }
2573                                         }
2574                                 }
2575                                 if (!empty($relative['fragment']))
2576                                 {
2577                                         $target['fragment'] = $relative['fragment'];
2578                                 }
2579                         }
2580                         else
2581                         {
2582                                 return false;
2583                         }
2584                         $return = '';
2585                         if (!empty($target['scheme']))
2586                         {
2587                                 $return .= "$target[scheme]:";
2588                         }
2589                         if (!empty($target['authority']))
2590                         {
2591                                 $return .= $target['authority'];
2592                         }
2593                         if (!empty($target['path']))
2594                         {
2595                                 $return .= $target['path'];
2596                         }
2597                         if (!empty($target['query']))
2598                         {
2599                                 $return .= "?$target[query]";
2600                         }
2601                         if (!empty($target['fragment']))
2602                         {
2603                                 $return .= "#$target[fragment]";
2604                         }
2605                 }
2606                 else
2607                 {
2608                         $return = $base;
2609                 }
2610                 return $return;
2611         }
2612         
2613         function strendpos($haystack, $needle)
2614         {
2615                 return strlen($haystack) - strpos($haystack, $needle) - strlen($needle);
2616         }
2617         
2618         function get_element($realname, $string)
2619         {
2620                 $return = array();
2621                 $name = preg_quote($realname, '/');
2622                 preg_match_all("/<($name)((\s*((\w+:)?\w+)\s*=\s*(\"([^\"]*)\"|'([^']*)'|(.*)))*)\s*((\/)?>|>(.*)<\/$name>)/msiU", $string, $matches, PREG_SET_ORDER);
2623                 for ($i = 0; $i < count($matches); $i++)
2624                 {
2625                         $return[$i]['tag'] = $realname;
2626                         $return[$i]['full'] = $matches[$i][0];
2627                         if (strlen($matches[$i][10]) <= 2)
2628                         {
2629                                 $return[$i]['self_closing'] = true;
2630                         }
2631                         else
2632                         {
2633                                 $return[$i]['self_closing'] = false;
2634                                 $return[$i]['content'] = $matches[$i][12];
2635                         }
2636                         $return[$i]['attribs'] = array();
2637                         if (!empty($matches[$i][2]))
2638                         {
2639                                 preg_match_all('/((\w+:)?\w+)\s*=\s*("([^"]*)"|\'([^\']*)\'|(\S+))\s/msiU', ' ' . $matches[$i][2] . ' ', $attribs, PREG_SET_ORDER);
2640                                 for ($j = 0; $j < count($attribs);  $j++)
2641                                 {
2642                                         $return[$i]['attribs'][strtoupper($attribs[$j][1])]['data'] = $attribs[$j][count($attribs[$j])-1];
2643                                         $first = substr($attribs[$j][2], 0, 1);
2644                                         $return[$i]['attribs'][strtoupper($attribs[$j][1])]['split'] = ($first == '"' || $first == "'") ? $first : '"';
2645                                 }
2646                         }
2647                 }
2648                 return $return;
2649         }
2650         
2651         function element_implode($element)
2652         {
2653                 $full = "<$element[tag]";
2654                 foreach ($element['attribs'] as $key => $value)
2655                 {
2656                         $key = strtolower($key);
2657                         $full .= " $key=$value[split]$value[data]$value[split]";
2658                 }
2659                 if ($element['self_closing'])
2660                 {
2661                         $full .= ' />';
2662                 }
2663                 else
2664                 {
2665                         $full .= ">$element[content]</$element[tag]>";
2666                 }
2667                 return $full;
2668         }
2669         
2670         function error($message, $level, $file, $line)
2671         {
2672                 switch ($level)
2673                 {
2674                         case E_USER_ERROR:
2675                                 $note = 'PHP Error';
2676                                 break;
2677                         case E_USER_WARNING:
2678                                 $note = 'PHP Warning';
2679                                 break;
2680                         case E_USER_NOTICE:
2681                                 $note = 'PHP Notice';
2682                                 break;
2683                         default:
2684                                 $note = 'Unknown Error';
2685                                 break;
2686                 }
2687                 error_log("$note: $message in $file on line $line", 0);
2688                 return $message;
2689         }
2690         
2691         function display_file($url, $timeout = 10, $useragent = null)
2692         {
2693                 $file = new SimplePie_File($url, $timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $useragent);
2694                 $headers = $file->headers();
2695                 if ($file->body() !== false)
2696                 {
2697                         header('Content-type: ' . $headers['content-type']);
2698                         echo $file->body();
2699                         exit;
2700                 }
2701         }
2702         
2703         function fix_protocol($url, $http = 1)
2704         {
2705                 $parsed = SimplePie_Misc::parse_url($url);
2706                 if (!empty($parsed['scheme']) && strtolower($parsed['scheme']) != 'http' && strtolower($parsed['scheme']) != 'https')
2707                 {
2708                         return SimplePie_Misc::fix_protocol("$parsed[authority]$parsed[path]$parsed[query]$parsed[fragment]", $http);
2709                 }
2710                 if (!file_exists($url) && empty($parsed['scheme']))
2711                 {
2712                         return SimplePie_Misc::fix_protocol("http://$url", $http);
2713                 }
2714
2715                 if ($http == 2 && !empty($parsed['scheme']))
2716                 {
2717                         return "feed:$url";
2718                 }
2719                 else if ($http == 3 && strtolower($parsed['scheme']) == 'http')
2720                 {
2721                         return substr_replace($url, 'podcast', 0, 4);
2722                 }
2723                 else
2724                 {
2725                         return $url;
2726                 }
2727         }
2728         
2729         function parse_url($url, $parse_match = true)
2730         {
2731                 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/i', $url, $match);
2732                 if (empty($match[0]))
2733                 {
2734                         return false;
2735                 }
2736                 else
2737                 {
2738                         for ($i = 6; $i < 10; $i++)
2739                         {
2740                                 if (!isset($match[$i]))
2741                                 {
2742                                         $match[$i] = '';
2743                                 }
2744                         }
2745                         if ($parse_match)
2746                         {
2747                                 $match = array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[6], 'fragment' => $match[8]);
2748                         }
2749                         return $match;
2750                 }
2751         }
2752         
2753         /**
2754          * Replace bad bytes
2755          *
2756          * PCRE Pattern to locate bad bytes in a UTF-8 string
2757          * Comes from W3 FAQ: Multilingual Forms
2758          * Note: modified to include full ASCII range including control chars
2759          *
2760          * Modified by Geoffrey Sneddon 2006-11-19 to remove functionality
2761          * to choose what the replace string is, and to use a variable for
2762          * the output instead of PHP's output buffer
2763          */
2764         function utf8_bad_replace($str)
2765         {
2766                 $UTF8_BAD =
2767                  '([\x00-\x7F]' .                                                       # ASCII (including control chars)
2768                  '|[\xC2-\xDF][\x80-\xBF]' .                            # non-overlong 2-byte
2769                  '|\xE0[\xA0-\xBF][\x80-\xBF]' .                        # excluding overlongs
2770                  '|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}' .         # straight 3-byte
2771                  '|\xED[\x80-\x9F][\x80-\xBF]' .                        # excluding surrogates
2772                  '|\xF0[\x90-\xBF][\x80-\xBF]{2}' .                     # planes 1-3
2773                  '|[\xF1-\xF3][\x80-\xBF]{3}' .                         # planes 4-15
2774                  '|\xF4[\x80-\x8F][\x80-\xBF]{2}' .                     # plane 16
2775                  '|(.{1}))';                                                            # invalid byte
2776                 $output = '';
2777                 while (preg_match('/' . $UTF8_BAD . '/S', $str, $matches))
2778                 {
2779                         if (!isset($matches[2]))
2780                         {
2781                                 $output .= $matches[0];
2782                         }
2783                         $str = substr($str, strlen($matches[0]));
2784                 }
2785                 return $output;
2786         }
2787         
2788         function change_encoding($data, $input, $output)
2789         {
2790                 $input = SimplePie_Misc::encoding($input);
2791                 $output = SimplePie_Misc::encoding($output);
2792                 
2793                 if ($input != $output)
2794                 {
2795                         if (function_exists('iconv') && $input['use_iconv'] && $output['use_iconv'] && iconv($input['encoding'], "$output[encoding]//TRANSLIT", $data))
2796                         {
2797                                 return iconv($input['encoding'], "$output[encoding]//TRANSLIT", $data);
2798                         }
2799                         else if (function_exists('iconv') && $input['use_iconv'] && $output['use_iconv'] && iconv($input['encoding'], $output['encoding'], $data))
2800                         {
2801                                 return iconv($input['encoding'], $output['encoding'], $data);   
2802                         }
2803                         else if (function_exists('mb_convert_encoding') && $input['use_mbstring'] && $output['use_mbstring'])
2804                         {
2805                                 return mb_convert_encoding($data, $output['encoding'], $input['encoding']);
2806                         }
2807                         else if ($input['encoding'] == 'ISO-8859-1' && $output['encoding'] == 'UTF-8')
2808                         {
2809                                 return utf8_encode($data);
2810                         }
2811                         else if ($input['encoding'] == 'UTF-8' && $output['encoding'] == 'ISO-8859-1')
2812                         {
2813                                 return utf8_decode($data);
2814                         }
2815                 }
2816                 return $data;
2817         }
2818         
2819         function encoding($encoding)
2820         {
2821                 $return['use_mbstring'] = false;
2822                 $return['use_iconv'] = false;
2823                 switch (strtolower($encoding))
2824                 {
2825
2826                         // 7bit
2827                         case '7bit':
2828                         case '7-bit':
2829                                 $return['encoding'] = '7bit';
2830                                 $return['use_mbstring'] = true;
2831                                 break;
2832
2833                         // 8bit
2834                         case '8bit':
2835                         case '8-bit':
2836                                 $return['encoding'] = '8bit';
2837                                 $return['use_mbstring'] = true;
2838                                 break;
2839
2840                         // ARMSCII-8
2841                         case 'armscii-8':
2842                         case 'armscii':
2843                                 $return['encoding'] = 'ARMSCII-8';
2844                                 $return['use_iconv'] = true;
2845                                 break;
2846
2847                         // ASCII
2848                         case 'us-ascii':
2849                         case 'ascii':
2850                                 $return['encoding'] = 'US-ASCII';
2851                                 $return['use_iconv'] = true;
2852                                 $return['use_mbstring'] = true;
2853                                 break;
2854
2855                         // BASE64
2856                         case 'base64':
2857                         case 'base-64':
2858                                 $return['encoding'] = 'BASE64';
2859                                 $return['use_mbstring'] = true;
2860                                 break;
2861
2862                         // Big5 - Traditional Chinese, mainly used in Taiwan
2863                         case 'big5':
2864                         case '950':
2865                                 $return['encoding'] = 'BIG5';
2866                                 $return['use_iconv'] = true;
2867                                 $return['use_mbstring'] = true;
2868                                 break;
2869
2870                         // Big5 with Hong Kong extensions, Traditional Chinese
2871                         case 'big5-hkscs':
2872                                 $return['encoding'] = 'BIG5-HKSCS';
2873                                 $return['use_iconv'] = true;
2874                                 $return['use_mbstring'] = true;
2875                                 break;
2876
2877                         // byte2be
2878                         case 'byte2be':
2879                                 $return['encoding'] = 'byte2be';
2880                                 $return['use_mbstring'] = true;
2881                                 break;
2882
2883                         // byte2le
2884                         case 'byte2le':
2885                                 $return['encoding'] = 'byte2le';
2886                                 $return['use_mbstring'] = true;
2887                                 break;
2888
2889                         // byte4be
2890                         case 'byte4be':
2891                                 $return['encoding'] = 'byte4be';
2892                                 $return['use_mbstring'] = true;
2893                                 break;
2894
2895                         // byte4le
2896                         case 'byte4le':
2897                                 $return['encoding'] = 'byte4le';
2898                                 $return['use_mbstring'] = true;
2899                                 break;
2900
2901                         // EUC-CN
2902                         case 'euc-cn':
2903                         case 'euccn':
2904                                 $return['encoding'] = 'EUC-CN';
2905                                 $return['use_iconv'] = true;
2906                                 $return['use_mbstring'] = true;
2907                                 break;
2908
2909                         // EUC-JISX0213
2910                         case 'euc-jisx0213':
2911                         case 'eucjisx0213':
2912                                 $return['encoding'] = 'EUC-JISX0213';
2913                                 $return['use_iconv'] = true;
2914                                 break;
2915
2916                         // EUC-JP
2917                         case 'euc-jp':
2918                         case 'eucjp':
2919                                 $return['encoding'] = 'EUC-JP';
2920                                 $return['use_iconv'] = true;
2921                                 $return['use_mbstring'] = true;
2922                                 break;
2923
2924                         // EUCJP-win
2925                         case 'euc-jp-win':
2926                         case 'eucjp-win':
2927                         case 'eucjpwin':
2928                                 $return['encoding'] = 'EUCJP-win';
2929                                 $return['use_iconv'] = true;
2930                                 $return['use_mbstring'] = true;
2931                                 break;
2932
2933                         // EUC-KR
2934                         case 'euc-kr':
2935                         case 'euckr':
2936                                 $return['encoding'] = 'EUC-KR';
2937                                 $return['use_iconv'] = true;
2938                                 $return['use_mbstring'] = true;
2939                                 break;
2940
2941                         // EUC-TW
2942                         case 'euc-tw':
2943                         case 'euctw':
2944                                 $return['encoding'] = 'EUC-TW';
2945                                 $return['use_iconv'] = true;
2946                                 $return['use_mbstring'] = true;
2947                                 break;
2948
2949                         // GB18030 - Simplified Chinese, national standard character set
2950                         case 'gb18030-2000':
2951                         case 'gb18030':
2952                                 $return['encoding'] = 'GB18030';
2953                                 $return['use_iconv'] = true;
2954                                 break;
2955
2956                         // GB2312 - Simplified Chinese, national standard character set
2957                         case 'gb2312':
2958                         case '936':
2959                                 $return['encoding'] = 'GB2312';
2960                                 $return['use_mbstring'] = true;
2961                                 break;
2962
2963                         // GBK
2964                         case 'gbk':
2965                                 $return['encoding'] = 'GBK';
2966                                 $return['use_iconv'] = true;
2967                                 break;
2968
2969                         // Georgian-Academy
2970                         case 'georgian-academy':
2971                                 $return['encoding'] = 'Georgian-Academy';
2972                                 $return['use_iconv'] = true;
2973                                 break;
2974
2975                         // Georgian-PS
2976                         case 'georgian-ps':
2977                                 $return['encoding'] = 'Georgian-PS';
2978                                 $return['use_iconv'] = true;
2979                                 break;
2980
2981                         // HTML-ENTITIES
2982                         case 'html-entities':
2983                         case 'htmlentities':
2984                                 $return['encoding'] = 'HTML-ENTITIES';
2985                                 $return['use_mbstring'] = true;
2986                                 break;
2987
2988                         // HZ
2989                         case 'hz':
2990                                 $return['encoding'] = 'HZ';
2991                                 $return['use_iconv'] = true;
2992                                 $return['use_mbstring'] = true;
2993                                 break;
2994
2995                         // ISO-2022-CN
2996                         case 'iso-2022-cn':
2997                         case 'iso2022-cn':
2998                         case 'iso2022cn':
2999                                 $return['encoding'] = 'ISO-2022-CN';
3000                                 $return['use_iconv'] = true;
3001                                 break;
3002
3003                         // ISO-2022-CN-EXT
3004                         case 'iso-2022-cn-ext':
3005                         case 'iso2022-cn-ext':
3006                         case 'iso2022cn-ext':
3007                         case 'iso2022cnext':
3008                                 $return['encoding'] = 'ISO-2022-CN';
3009                                 $return['use_iconv'] = true;
3010                                 break;
3011
3012                         // ISO-2022-JP
3013                         case 'iso-2022-jp':
3014                         case 'iso2022-jp':
3015                         case 'iso2022jp':
3016                                 $return['encoding'] = 'ISO-2022-JP';
3017                                 $return['use_iconv'] = true;
3018                                 $return['use_mbstring'] = true;
3019                                 break;
3020
3021                         // ISO-2022-JP-1
3022                         case 'iso-2022-jp-1':
3023                         case 'iso2022-jp-1':
3024                         case 'iso2022jp-1':
3025                         case 'iso2022jp1':
3026                                 $return['encoding'] = 'ISO-2022-JP-1';
3027                                 $return['use_iconv'] = true;
3028                                 break;
3029
3030                         // ISO-2022-JP-2
3031                         case 'iso-2022-jp-2':
3032                         case 'iso2022-jp-2':
3033                         case 'iso2022jp-2':
3034                         case 'iso2022jp2':
3035                                 $return['encoding'] = 'ISO-2022-JP-2';
3036                                 $return['use_iconv'] = true;
3037                                 break;
3038
3039                         // ISO-2022-JP-3
3040                         case 'iso-2022-jp-3':
3041                         case 'iso2022-jp-3':
3042                         case 'iso2022jp-3':
3043                         case 'iso2022jp3':
3044                                 $return['encoding'] = 'ISO-2022-JP-3';
3045                                 $return['use_iconv'] = true;
3046                                 break;
3047
3048                         // ISO-2022-KR
3049                         case 'iso-2022-kr':
3050                         case 'iso2022-kr':
3051                         case 'iso2022kr':
3052                                 $return['encoding'] = 'ISO-2022-KR';
3053                                 $return['use_iconv'] = true;
3054                                 $return['use_mbstring'] = true;
3055                                 break;
3056
3057                         // ISO-8859-1
3058                         case 'iso-8859-1':
3059                         case 'iso8859-1':
3060                                 $return['encoding'] = 'ISO-8859-1';
3061                                 $return['use_iconv'] = true;
3062                                 $return['use_mbstring'] = true;
3063                                 break;
3064
3065                         // ISO-8859-2
3066                         case 'iso-8859-2':
3067                         case 'iso8859-2':
3068                                 $return['encoding'] = 'ISO-8859-2';
3069                                 $return['use_iconv'] = true;
3070                                 $return['use_mbstring'] = true;
3071                                 break;
3072
3073                         // ISO-8859-3
3074                         case 'iso-8859-3':
3075                         case 'iso8859-3':
3076                                 $return['encoding'] = 'ISO-8859-3';
3077                                 $return['use_iconv'] = true;
3078                                 $return['use_mbstring'] = true;
3079                                 break;
3080
3081                         // ISO-8859-4
3082                         case 'iso-8859-4':
3083                         case 'iso8859-4':
3084                                 $return['encoding'] = 'ISO-8859-4';
3085                                 $return['use_iconv'] = true;
3086                                 $return['use_mbstring'] = true;
3087                                 break;
3088
3089                         // ISO-8859-5
3090                         case 'iso-8859-5':
3091                         case 'iso8859-5':
3092                                 $return['encoding'] = 'ISO-8859-5';
3093                                 $return['use_iconv'] = true;
3094                                 $return['use_mbstring'] = true;
3095                                 break;
3096
3097                         // ISO-8859-6
3098                         case 'iso-8859-6':
3099                         case 'iso8859-6':
3100                                 $return['encoding'] = 'ISO-8859-6';
3101                                 $return['use_iconv'] = true;
3102                                 $return['use_mbstring'] = true;
3103                                 break;
3104
3105                         // ISO-8859-7
3106                         case 'iso-8859-7':
3107                         case 'iso8859-7':
3108                                 $return['encoding'] = 'ISO-8859-7';
3109                                 $return['use_iconv'] = true;
3110                                 $return['use_mbstring'] = true;
3111                                 break;
3112
3113                         // ISO-8859-8
3114                         case 'iso-8859-8':
3115                         case 'iso8859-8':
3116                                 $return['encoding'] = 'ISO-8859-8';
3117                                 $return['use_iconv'] = true;
3118                                 $return['use_mbstring'] = true;
3119                                 break;
3120
3121                         // ISO-8859-9
3122                         case 'iso-8859-9':
3123                         case 'iso8859-9':
3124                                 $return['encoding'] = 'ISO-8859-9';
3125                                 $return['use_iconv'] = true;
3126                                 $return['use_mbstring'] = true;
3127                                 break;
3128
3129                         // ISO-8859-10
3130                         case 'iso-8859-10':
3131                         case 'iso8859-10':
3132                                 $return['encoding'] = 'ISO-8859-10';
3133                                 $return['use_iconv'] = true;
3134                                 $return['use_mbstring'] = true;
3135                                 break;
3136
3137                         // mbstring/iconv functions don't appear to support 11 & 12
3138
3139                         // ISO-8859-13
3140                         case 'iso-8859-13':
3141                         case 'iso8859-13':
3142                                 $return['encoding'] = 'ISO-8859-13';
3143                                 $return['use_iconv'] = true;
3144                                 $return['use_mbstring'] = true;
3145                                 break;
3146
3147                         // ISO-8859-14
3148                         case 'iso-8859-14':
3149                         case 'iso8859-14':
3150                                 $return['encoding'] = 'ISO-8859-14';
3151                                 $return['use_iconv'] = true;
3152                                 $return['use_mbstring'] = true;
3153                                 break;
3154
3155                         // ISO-8859-15
3156                         case 'iso-8859-15':
3157                         case 'iso8859-15':
3158                                 $return['encoding'] = 'ISO-8859-15';
3159                                 $return['use_iconv'] = true;
3160                                 $return['use_mbstring'] = true;
3161                                 break;
3162
3163                         // ISO-8859-16
3164                         case 'iso-8859-16':
3165                         case 'iso8859-16':
3166                                 $return['encoding'] = 'ISO-8859-16';
3167                                 $return['use_iconv'] = true;
3168                                 break;
3169
3170                         // JIS
3171                         case 'jis':
3172                                 $return['encoding'] = 'JIS';
3173                                 $return['use_mbstring'] = true;
3174                                 break;
3175
3176                         // JOHAB - Korean
3177                         case 'johab':
3178                                 $return['encoding'] = 'JOHAB';
3179                                 $return['use_iconv'] = true;
3180                                 break;
3181
3182                         // Russian
3183                         case 'koi8-r':
3184                         case 'koi8r':
3185                                 $return['encoding'] = 'KOI8-R';
3186                                 $return['use_iconv'] = true;
3187                                 $return['use_mbstring'] = true;
3188                                 break;
3189
3190                         // Turkish
3191                         case 'koi8-t':
3192                         case 'koi8t':
3193                                 $return['encoding'] = 'KOI8-T';
3194                                 $return['use_iconv'] = true;
3195                                 break;
3196
3197                         // Ukrainian
3198                         case 'koi8-u':
3199                         case 'koi8u':
3200                                 $return['encoding'] = 'KOI8-U';
3201                                 $return['use_iconv'] = true;
3202                                 break;
3203
3204                         // Russian+Ukrainian
3205                         case 'koi8-ru':
3206                         case 'koi8ru':
3207                                 $return['encoding'] = 'KOI8-RU';
3208                                 $return['use_iconv'] = true;
3209                                 break;
3210
3211                         // Macintosh (Mac OS Classic)
3212                         case 'macintosh':
3213                                 $return['encoding'] = 'Macintosh';
3214                                 $return['use_iconv'] = true;
3215                                 break;
3216
3217                         // MacArabic (Mac OS Classic)
3218                         case 'macarabic':
3219                                 $return['encoding'] = 'MacArabic';
3220                                 $return['use_iconv'] = true;
3221                                 break;
3222
3223                         // MacCentralEurope (Mac OS Classic)
3224                         case 'maccentraleurope':
3225                                 $return['encoding'] = 'MacCentralEurope';
3226                                 $return['use_iconv'] = true;
3227                                 break;
3228
3229                         // MacCroatian (Mac OS Classic)
3230                         case 'maccroatian':
3231                                 $return['encoding'] = 'MacCroatian';
3232                                 $return['use_iconv'] = true;
3233                                 break;
3234
3235                         // MacCyrillic (Mac OS Classic)
3236                         case 'maccyrillic':
3237                                 $return['encoding'] = 'MacCyrillic';
3238                                 $return['use_iconv'] = true;
3239                                 break;
3240
3241                         // MacGreek (Mac OS Classic)
3242                         case 'macgreek':
3243                                 $return['encoding'] = 'MacGreek';
3244                                 $return['use_iconv'] = true;
3245                                 break;
3246
3247                         // MacHebrew (Mac OS Classic)
3248                         case 'machebrew':
3249                                 $return['encoding'] = 'MacHebrew';
3250                                 $return['use_iconv'] = true;
3251                                 break;
3252
3253                         // MacIceland (Mac OS Classic)
3254                         case 'maciceland':
3255                                 $return['encoding'] = 'MacIceland';
3256                                 $return['use_iconv'] = true;
3257                                 break;
3258
3259                         // MacRoman (Mac OS Classic)
3260                         case 'macroman':
3261                                 $return['encoding'] = 'MacRoman';
3262                                 $return['use_iconv'] = true;
3263                                 break;
3264
3265                         // MacRomania (Mac OS Classic)
3266                         case 'macromania':
3267                                 $return['encoding'] = 'MacRomania';
3268                                 $return['use_iconv'] = true;
3269                                 break;
3270
3271                         // MacThai (Mac OS Classic)
3272                         case 'macthai':
3273                                 $return['encoding'] = 'MacThai';
3274                                 $return['use_iconv'] = true;
3275                                 break;
3276
3277                         // MacTurkish (Mac OS Classic)
3278                         case 'macturkish':
3279                                 $return['encoding'] = 'MacTurkish';
3280                                 $return['use_iconv'] = true;
3281                                 break;
3282
3283                         // MacUkraine (Mac OS Classic)
3284                         case 'macukraine':
3285                                 $return['encoding'] = 'MacUkraine';
3286                                 $return['use_iconv'] = true;
3287                                 break;
3288
3289                         // MuleLao-1
3290                         case 'mulelao-1':
3291                         case 'mulelao1':
3292                                 $return['encoding'] = 'MuleLao-1';
3293                                 $return['use_iconv'] = true;
3294                                 break;
3295
3296                         // Shift_JIS
3297                         case 'shift_jis':
3298                         case 'sjis':
3299                         case '932':
3300                                 $return['encoding'] = 'Shift_JIS';
3301                                 $return['use_iconv'] = true;
3302                                 $return['use_mbstring'] = true;
3303                                 break;
3304
3305                         // Shift_JISX0213
3306                         case 'shift-jisx0213':
3307                         case 'shiftjisx0213':
3308                                 $return['encoding'] = 'Shift_JISX0213';
3309                                 $return['use_iconv'] = true;
3310                                 break;
3311
3312                         // SJIS-win
3313                         case 'sjis-win':
3314                         case 'sjiswin':
3315                         case 'shift_jis-win':
3316                                 $return['encoding'] = 'SJIS-win';
3317                                 $return['use_iconv'] = true;
3318                                 $return['use_mbstring'] = true;
3319                                 break;
3320
3321                         // TCVN - Vietnamese
3322                         case 'tcvn':
3323                                 $return['encoding'] = 'TCVN';
3324                                 $return['use_iconv'] = true;
3325                                 break;
3326
3327                         // TDS565 - Turkish
3328                         case 'tds565':
3329                                 $return['encoding'] = 'TDS565';
3330                                 $return['use_iconv'] = true;
3331                                 break;
3332
3333                         // TIS-620 Thai
3334                         case 'tis-620':
3335                         case 'tis620':
3336                                 $return['encoding'] = 'TIS-620';
3337                                 $return['use_iconv'] = true;
3338                                 $return['use_mbstring'] = true;
3339                                 break;
3340
3341                         // UCS-2
3342                         case 'ucs-2':
3343                         case 'ucs2':
3344                         case 'utf-16':
3345                         case 'utf16':
3346                                 $return['encoding'] = 'UCS-2';
3347                                 $return['use_iconv'] = true;
3348                                 $return['use_mbstring'] = true;
3349                                 break;
3350
3351                         // UCS-2BE
3352                         case 'ucs-2be':
3353                         case 'ucs2be':
3354                         case 'utf-16be':
3355                         case 'utf16be':
3356                                 $return['encoding'] = 'UCS-2BE';
3357                                 $return['use_iconv'] = true;
3358                                 $return['use_mbstring'] = true;
3359                                 break;
3360
3361                         // UCS-2LE
3362                         case 'ucs-2le':
3363                         case 'ucs2le':
3364                         case 'utf-16le':
3365                         case 'utf16le':
3366                                 $return['encoding'] = 'UCS-2LE';
3367                                 $return['use_iconv'] = true;
3368                                 $return['use_mbstring'] = true;
3369                                 break;
3370
3371                         // UCS-2-INTERNAL
3372                         case 'ucs-2-internal':
3373                         case 'ucs2internal':
3374                                 $return['encoding'] = 'UCS-2-INTERNAL';
3375                                 $return['use_iconv'] = true;
3376                                 break;
3377
3378                         // UCS-4
3379                         case 'ucs-4':
3380                         case 'ucs4':
3381                         case 'utf-32':
3382                         case 'utf32':
3383                                 $return['encoding'] = 'UCS-4';
3384                                 $return['use_iconv'] = true;
3385                                 $return['use_mbstring'] = true;
3386                                 break;
3387
3388                         // UCS-4BE
3389                         case 'ucs-4be':
3390                         case 'ucs4be':
3391                         case 'utf-32be':
3392                         case 'utf32be':
3393                                 $return['encoding'] = 'UCS-4BE';
3394                                 $return['use_iconv'] = true;
3395                                 $return['use_mbstring'] = true;
3396                                 break;
3397
3398                         // UCS-4LE
3399                         case 'ucs-4le':
3400                         case 'ucs4le':
3401                         case 'utf-32le':
3402                         case 'utf32le':
3403                                 $return['encoding'] = 'UCS-4LE';
3404                                 $return['use_iconv'] = true;
3405                                 $return['use_mbstring'] = true;
3406                                 break;
3407
3408                         // UCS-4-INTERNAL
3409                         case 'ucs-4-internal':
3410                         case 'ucs4internal':
3411                                 $return['encoding'] = 'UCS-4-INTERNAL';
3412                                 $return['use_iconv'] = true;
3413                                 break;
3414
3415                         // UCS-16
3416                         case 'ucs-16':
3417                         case 'ucs16':
3418                                 $return['encoding'] = 'UCS-16';
3419                                 $return['use_iconv'] = true;
3420                                 $return['use_mbstring'] = true;
3421                                 break;
3422
3423                         // UCS-16BE
3424                         case 'ucs-16be':
3425                         case 'ucs16be':
3426                                 $return['encoding'] = 'UCS-16BE';
3427                                 $return['use_iconv'] = true;
3428                                 $return['use_mbstring'] = true;
3429                                 break;
3430
3431                         // UCS-16LE
3432                         case 'ucs-16le':
3433                         case 'ucs16le':
3434                                 $return['encoding'] = 'UCS-16LE';
3435                                 $return['use_iconv'] = true;
3436                                 $return['use_mbstring'] = true;
3437                                 break;
3438
3439                         // UCS-32
3440                         case 'ucs-32':
3441                         case 'ucs32':
3442                                 $return['encoding'] = 'UCS-32';
3443                                 $return['use_iconv'] = true;
3444                                 $return['use_mbstring'] = true;
3445                                 break;
3446
3447                         // UCS-32BE
3448                         case 'ucs-32be':
3449                         case 'ucs32be':
3450                                 $return['encoding'] = 'UCS-32BE';
3451                                 $return['use_iconv'] = true;
3452                                 $return['use_mbstring'] = true;
3453                                 break;
3454
3455                         // UCS-32LE
3456                         case 'ucs-32le':
3457                         case 'ucs32le':
3458                                 $return['encoding'] = 'UCS-32LE';
3459                                 $return['use_iconv'] = true;
3460                                 $return['use_mbstring'] = true;
3461                                 break;
3462
3463                         // UTF-7
3464                         case 'utf-7':
3465                         case 'utf7':
3466                                 $return['encoding'] = 'UTF-7';
3467                                 $return['use_iconv'] = true;
3468                                 $return['use_mbstring'] = true;
3469                                 break;
3470
3471                         // UTF7-IMAP
3472                         case 'utf-7-imap':
3473                         case 'utf7-imap':
3474                         case 'utf7imap':
3475                                 $return['encoding'] = 'UTF7-IMAP';
3476                                 $return['use_mbstring'] = true;
3477                                 break;
3478
3479                         // VISCII - Vietnamese ASCII
3480                         case 'viscii':
3481                                 $return['encoding'] = 'VISCII';
3482                                 $return['use_iconv'] = true;
3483                                 break;
3484
3485                         // Windows-specific Central & Eastern Europe
3486                         case 'cp1250':
3487                         case 'windows-1250':
3488                         case 'win-1250':
3489                         case '1250':
3490                                 $return['encoding'] = 'Windows-1250';
3491                                 $return['use_iconv'] = true;
3492                                 break;
3493
3494                         // Windows-specific Cyrillic
3495                         case 'cp1251':
3496                         case 'windows-1251':
3497                         case 'win-1251':
3498                         case '1251':
3499                                 $return['encoding'] = 'Windows-1251';
3500                                 $return['use_iconv'] = true;
3501                                 $return['use_mbstring'] = true;
3502                                 break;
3503
3504                         // Windows-specific Western Europe
3505                         case 'cp1252':
3506                         case 'windows-1252':
3507                         case '1252':
3508                                 $return['encoding'] = 'Windows-1252';
3509                                 $return['use_iconv'] = true;
3510                                 $return['use_mbstring'] = true;
3511                                 break;
3512
3513                         // Windows-specific Greek
3514                         case 'cp1253':
3515                         case 'windows-1253':
3516                         case '1253':
3517                                 $return['encoding'] = 'Windows-1253';
3518                                 $return['use_iconv'] = true;
3519                                 break;
3520
3521                         // Windows-specific Turkish
3522                         case 'cp1254':
3523                         case 'windows-1254':
3524                         case '1254':
3525                                 $return['encoding'] = 'Windows-1254';
3526                                 $return['use_iconv'] = true;
3527                                 break;
3528
3529                         // Windows-specific Hebrew
3530                         case 'cp1255':
3531                         case 'windows-1255':
3532                         case '1255':
3533                                 $return['encoding'] = 'Windows-1255';
3534                                 $return['use_iconv'] = true;
3535                                 break;
3536
3537                         // Windows-specific Arabic
3538                         case 'cp1256':
3539                         case 'windows-1256':
3540                         case '1256':
3541                                 $return['encoding'] = 'Windows-1256';
3542                                 $return['use_iconv'] = true;
3543                                 break;
3544
3545                         // Windows-specific Baltic
3546                         case 'cp1257':
3547                         case 'windows-1257':
3548                         case '1257':
3549                                 $return['encoding'] = 'Windows-1257';
3550                                 $return['use_iconv'] = true;
3551                                 break;
3552
3553                         // Windows-specific Vietnamese
3554                         case 'cp1258':
3555                         case 'windows-1258':
3556                         case '1258':
3557                                 $return['encoding'] = 'Windows-1258';
3558                                 $return['use_iconv'] = true;
3559                                 break;
3560
3561                         // Default to UTF-8
3562                         default:
3563                                 $return['encoding'] = 'UTF-8';
3564                                 $return['use_iconv'] = true;
3565                                 $return['use_mbstring'] = true;
3566                                 break;
3567                 }
3568                 
3569                 // Then, return it.
3570                 return $return;
3571         }
3572         
3573         function get_curl_version()
3574         {
3575                 $curl = 0;
3576                 if (is_array(curl_version()))
3577                 {
3578                         $curl = curl_version();
3579                         $curl = $curl['version'];
3580                 }
3581                 else
3582                 {
3583                         $curl = curl_version();
3584                         $curl = explode(' ', $curl);
3585                         $curl = explode('/', $curl[0]);
3586                         $curl = $curl[1];
3587                 }
3588                 return $curl;
3589         }
3590         
3591         function is_a_class($class1, $class2)
3592         {
3593                 if (class_exists($class1))
3594                 {
3595                         $classes = array(strtolower($class1));
3596                         while ($class1 = get_parent_class($class1))
3597                         {
3598                                 $classes[] = strtolower($class1);
3599                         }
3600                         return in_array(strtolower($class2), $classes);
3601                 }
3602                 else
3603                 {
3604                         return false;
3605                 }
3606         }
3607 }
3608
3609 class SimplePie_Locator
3610 {
3611         var $useragent;
3612         var $timeout;
3613         var $file;
3614         var $local;
3615         var $elsewhere;
3616         var $file_class = 'SimplePie_File';
3617         
3618         function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File')
3619         {
3620                 if (!is_a($file, 'SimplePie_File'))
3621                 {
3622                         $this->file = new $this->file_class($file, $timeout, $useragent);
3623                 }
3624                 else
3625                 {
3626                         $this->file =& $file;
3627                 }
3628                 $this->file_class = $file_class;
3629                 $this->useragent = $useragent;
3630                 $this->timeout = $timeout;
3631         }
3632                 
3633         
3634         function find()
3635         {               
3636                 if ($this->is_feed($this->file))
3637                 {
3638                         return $this->file->url;
3639                 }
3640                 
3641                 $autodiscovery = $this->autodiscovery($this->file);
3642                 if ($autodiscovery)
3643                 {
3644                         return $autodiscovery;
3645                 }
3646                 
3647                 if ($this->get_links($this->file))
3648                 {
3649                         if (!empty($this->local))
3650                         {
3651                                 $extension_local = $this->extension($this->local);
3652                                 if ($extension_local)
3653                                 {
3654                                         return $extension_local;
3655                                 }
3656                         
3657                                 $body_local = $this->body($this->local);
3658                                 if ($body_local)
3659                                 {
3660                                         return $body_local;
3661                                 }
3662                         }
3663                         
3664                         if (!empty($this->elsewhere))
3665                         {
3666                                 $extension_elsewhere = $this->extension($this->elsewhere);
3667                                 if ($extension_elsewhere)
3668                                 {
3669                                         return $extension_elsewhere;
3670                                 }
3671                                 
3672                                 $body_elsewhere = $this->body($this->elsewhere);
3673                                 if ($body_elsewhere)
3674                                 {
3675                                         return $body_elsewhere;
3676                                 }
3677                         }
3678                 }
3679                 return false;
3680         }
3681         
3682         function is_feed(&$file)
3683         {
3684                 if (!is_a($file, 'SimplePie_File'))
3685                 {
3686                         if (isset($this))
3687                         {
3688                                 $file2 = new $this->file_class($file, $this->timeout, 5, null, $this->useragent);
3689                         }
3690                         else
3691                         {
3692                                 $file2 = new $this->file_class($file);
3693                         }
3694                         $file2->body();
3695                         $file2->close();
3696                 }
3697                 else
3698                 {
3699                         $file2 =& $file;
3700                 }
3701                 $body = preg_replace('/<\!-(.*)-\>/msiU', '', $file2->body());
3702                 if (preg_match('/<(\w+\:)?rss/msiU', $body) || preg_match('/<(\w+\:)?RDF/mi', $body) || preg_match('/<(\w+\:)?feed/mi', $body))
3703                 {
3704                         return true;
3705                 }
3706                 return false;
3707         }
3708         
3709         function autodiscovery(&$file)
3710         {
3711                 $links = SimplePie_Misc::get_element('link', $file->body());
3712                 $done = array();
3713                 foreach ($links as $link)
3714                 {
3715                         if (!empty($link['attribs']['TYPE']['data']) && !empty($link['attribs']['HREF']['data']) && !empty($link['attribs']['REL']['data']))
3716                         {
3717                                 $rel = preg_split('/\s+/', strtolower(trim($link['attribs']['REL']['data'])));
3718                                 $type = preg_match('/^(application\/rss\+xml|application\/atom\+xml|application\/rdf\+xml|application\/xml\+rss|application\/xml\+atom|application\/xml\+rdf|application\/xml|application\/x\.atom\+xml|text\/xml)(;|$)/msiU', trim($link['attribs']['TYPE']['data']));
3719                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['HREF']['data']), $this->file->url);
3720                                 if (!in_array($href, $done) && in_array('alternate', $rel) && $type)
3721                                 {
3722                                         $feed = $this->is_feed($href);
3723                                         if ($feed)
3724                                         {
3725                                                 return $href;
3726                                         }
3727                                 }
3728                                 $done[] = $href;
3729                         }
3730                 }
3731                 return false;
3732         }
3733         
3734         function get_links(&$file)
3735         {
3736                 $links = SimplePie_Misc::get_element('a', $file->body());
3737                 foreach ($links as $link)
3738                 {
3739                         if (!empty($link['attribs']['HREF']['data']))
3740                         {
3741                                 $href = trim($link['attribs']['HREF']['data']);
3742                                 $parsed = SimplePie_Misc::parse_url($href);
3743                                 if (empty($parsed['scheme']) || $parsed['scheme'] != 'javascript')
3744                                 {
3745                                         $current = SimplePie_Misc::parse_url($this->file->url);
3746                                         if (empty($parsed['authority']) || $parsed['authority'] == $current['authority'])
3747                                         {
3748                                                 $this->local[] = SimplePie_Misc::absolutize_url($href, $this->file->url);
3749                                         }
3750                                         else
3751                                         {
3752                                                 $this->elsewhere[] = SimplePie_Misc::absolutize_url($href, $this->file->url);
3753                                         }
3754                                 }
3755                         }
3756                 }
3757                 if (!empty($this->local))
3758                 {
3759                         $this->local = array_unique($this->local);
3760                 }
3761                 if (!empty($this->elsewhere))
3762                 {
3763                         $this->elsewhere = array_unique($this->elsewhere);
3764                 }
3765                 if (!empty($this->local) || !empty($this->elsewhere))
3766                 {
3767                         return true;
3768                 }
3769                 return false;
3770         }
3771         
3772         function extension(&$array)
3773         {
3774                 foreach ($array as $key => $value)
3775                 {
3776                         $value = SimplePie_Misc::absolutize_url($value, $this->file->url);
3777                         if (in_array(strrchr($value, '.'), array('.rss', '.rdf', '.atom', '.xml')))
3778                         {
3779                                 if ($this->is_feed($value))
3780                                 {
3781                                         return $value;
3782                                 }
3783                                 else
3784                                 {
3785                                         unset($array[$key]);
3786                                 }
3787                         }
3788                 }
3789                 return false;
3790         }
3791         
3792         function body(&$array)
3793         {
3794                 foreach ($array as $key => $value)
3795                 {
3796                         $value = SimplePie_Misc::absolutize_url($value, $this->file->url);
3797                         if (preg_match('/(rss|rdf|atom|xml)/i', $value))
3798                         {
3799                                 if ($this->is_feed($value))
3800                                 {
3801                                         return $value;
3802                                 }
3803                                 else
3804                                 {
3805                                         unset($array[$key]);
3806                                 }
3807                         }
3808                 }
3809                 return false;
3810         }
3811 }
3812
3813 class SimplePie_Parser
3814 {       
3815         var $encoding;
3816         var $data;
3817         var $namespaces = array('xml' => 'HTTP://WWW.W3.ORG/XML/1998/NAMESPACE', 'atom' => 'ATOM', 'rss2' => 'RSS', 'rdf' => 'RDF', 'rss1' => 'RSS', 'dc' => 'DC', 'xhtml' => 'XHTML', 'content' => 'CONTENT');
3818         var $xml;
3819         var $error_code;
3820         var $error_string;
3821         var $current_line;
3822         var $current_column;
3823         var $current_byte;
3824         var $tag_name;
3825         var $inside_item;
3826         var $item_number = 0;
3827         var $inside_channel;
3828         var $author_number= 0;
3829         var $category_number = 0;
3830         var $enclosure_number = 0;
3831         var $link_number = 0;
3832         var $item_link_number = 0;
3833         var $inside_image;
3834         var $attribs;
3835         var $is_first;
3836         var $inside_author;
3837         var $depth_inside_item = 0;
3838                 
3839         function SimplePie_Parser($data, $encoding, $return_xml = false)
3840         {
3841                 $this->encoding = $encoding;
3842                 
3843                 // Strip BOM:
3844                 // UTF-32 Big Endian BOM
3845                 if (strpos($data, sprintf('%c%c%c%c', 0x00, 0x00, 0xFE, 0xFF)) === 0)
3846                 {
3847                         $data = substr($data, 4);
3848                 }
3849                 // UTF-32 Little Endian BOM
3850                 else if (strpos($data, sprintf('%c%c%c%c', 0xFF, 0xFE, 0x00, 0x00)) === 0)
3851                 {
3852                         $data = substr($data, 4);
3853                 }
3854                 // UTF-16 Big Endian BOM
3855                 else if (strpos($data, sprintf('%c%c', 0xFE, 0xFF)) === 0)
3856                 {
3857                         $data = substr($data, 2);
3858                 }
3859                 // UTF-16 Little Endian BOM
3860                 else if (strpos($data, sprintf('%c%c', 0xFF, 0xFE)) === 0)
3861                 {
3862                         $data = substr($data, 2);
3863                 }
3864                 // UTF-8 BOM
3865                 else if (strpos($data, sprintf('%c%c%c', 0xEF, 0xBB, 0xBF)) === 0)
3866                 {
3867                         $data = substr($data, 3);
3868                 }
3869                 
3870                 // Make sure the XML prolog is sane and has the correct encoding
3871                 if (preg_match('/^<\?xml(.*)?>/msiU', $data, $prolog))
3872                 {
3873                         $data = substr_replace($data, '', 0, strlen($prolog[0]));
3874                 }
3875                 $data = "<?xml version='1.0' encoding='$encoding'?>\n" . $data;
3876                 
3877                 // Put some data into CDATA blocks
3878                 // If we're RSS
3879                 if ((stristr($data, '<rss') || preg_match('/<([a-z0-9]+\:)?RDF/mi', $data)) && (preg_match('/<([a-z0-9]+\:)?channel/mi', $data) || preg_match('/<([a-z0-9]+\:)?item/mi', $data)))
3880                 {
3881                         $sp_elements = array(
3882                                 'author',
3883                                 'category',
3884                                 'copyright', 
3885                                 'description',
3886                                 'docs', 
3887                                 'generator', 
3888                                 'guid', 
3889                                 'language',
3890                                 'lastBuildDate', 
3891                                 'link',
3892                                 'managingEditor', 
3893                                 'pubDate', 
3894                                 'title',
3895                                 'url', 
3896                                 'webMaster', 
3897                         );
3898                 }
3899                 // Or if we're Atom
3900                 else
3901                 {
3902                         $sp_elements = array(
3903                                 'content',
3904                                 'copyright',
3905                                 'name',
3906                                 'subtitle',
3907                                 'summary',
3908                                 'tagline',
3909                                 'title',
3910                         );
3911                 }
3912                 foreach ($sp_elements as $full)
3913                 {
3914                         $data = preg_replace_callback("/<($full)((\s*((\w+:)?\w+)\s*=\s*(\"([^\"]*)\"|'([^']*)'))*)\s*(\/>|>(.*)<\/$full>)/msiU", array(&$this, 'add_cdata'), $data);
3915                 }
3916                 foreach ($sp_elements as $full)
3917                 {
3918                         // Deal with CDATA within CDATA (this can be caused by us inserting CDATA above)
3919                         $data = preg_replace_callback("/<($full)((\s*((\w+:)?\w+)\s*=\s*(\"([^\"]*)\"|'([^']*)'))*)\s*(\/>|><!\[CDATA\[(.*)\]\]><\/$full>)/msiU", array(&$this, 'cdata_in_cdata'), $data);
3920                 }
3921                 
3922                 // Return the XML, if so desired
3923                 if ($return_xml)
3924                 {
3925                         $this->data =& $data;
3926                         return;
3927                 }
3928                 
3929                 // Create the parser
3930                 $this->xml = xml_parser_create_ns($encoding);
3931                 xml_parser_set_option($this->xml, XML_OPTION_SKIP_WHITE, 1);
3932                 xml_set_object($this->xml, $this);
3933                 xml_set_character_data_handler($this->xml, 'data_handler');
3934                 xml_set_element_handler($this->xml, 'start_handler', 'end_handler');
3935                 xml_set_start_namespace_decl_handler($this->xml, 'start_name_space');
3936                 xml_set_end_namespace_decl_handler($this->xml, 'end_name_space');
3937                 
3938                 // Parse!
3939                 if (!xml_parse($this->xml, $data))
3940                 {
3941                         $this->data = null;
3942                         $this->error_code = xml_get_error_code($this->xml);
3943                         $this->error_string = xml_error_string($this->error_code);
3944                 }
3945                 $this->current_line = xml_get_current_line_number($this->xml);
3946                 $this->current_column = xml_get_current_column_number($this->xml);
3947                 $this->current_byte = xml_get_current_byte_index($this->xml);
3948                 xml_parser_free($this->xml);
3949                 return;
3950         }
3951         
3952         function add_cdata($match)
3953         {
3954                 if (isset($match[10]))
3955                 {
3956                         return "<$match[1]$match[2]><![CDATA[$match[10]]]></$match[1]>";
3957                 }
3958                 return $match[0];
3959         }
3960
3961         function cdata_in_cdata($match)
3962         {
3963                 if (isset($match[10]))
3964                 {
3965                         $match[10] = preg_replace_callback('/<!\[CDATA\[(.*)\]\]>/msiU', array(&$this, 'real_cdata_in_cdata'), $match[10]);
3966                         return "<$match[1]$match[2]><![CDATA[$match[10]]]></$match[1]>";
3967                 }
3968                 return $match[0];
3969         }
3970         
3971         function real_cdata_in_cdata($match)
3972         {
3973                 return htmlspecialchars($match[1], ENT_NOQUOTES);
3974         }
3975         
3976         function do_add_content(&$array, $data)
3977         {
3978                 if ($this->is_first)
3979                 {
3980                         $array['data'] = $data;
3981                         $array['attribs'] = $this->attribs;
3982                 }
3983                 else
3984                 {
3985                         $array['data'] .= $data;
3986                 }
3987         }
3988         
3989         function start_handler($parser, $name, $attribs)
3990         {
3991                 $this->tag_name = $name;
3992                 $this->attribs = $attribs;
3993                 $this->is_first = true;
3994
3995                 if ($this->inside_item)
3996                 {
3997                         $this->depth_inside_item++;
3998                 }
3999
4000                 switch ($this->tag_name)
4001                 {
4002                         case 'ITEM':
4003                         case $this->namespaces['rss2'] . ':ITEM':
4004                         case $this->namespaces['rss1'] . ':ITEM':
4005                         case 'ENTRY':
4006                         case $this->namespaces['atom'] . ':ENTRY':
4007                                 $this->inside_item = true;
4008                                 $this->do_add_content($this->data['items'][$this->item_number], '');
4009                                 break;
4010
4011                         case 'CHANNEL':
4012                         case $this->namespaces['rss2'] . ':CHANNEL':
4013                         case $this->namespaces['rss1'] . ':CHANNEL':
4014                                 $this->inside_channel = true;
4015                                 break;
4016
4017                         case 'RSS':
4018                         case $this->namespaces['rss2'] . ':RSS':
4019                                 $this->data['feedinfo']['type'] = 'RSS';
4020                                 $this->do_add_content($this->data['feeddata'], '');
4021                                 if (!empty($attribs['VERSION']))
4022                                 {
4023                                         $this->data['feedinfo']['version'] = trim($attribs['VERSION']);
4024                                 }
4025                                 break;
4026
4027                         case $this->namespaces['rdf'] . ':RDF':
4028                                 $this->data['feedinfo']['type'] = 'RSS';
4029                                 $this->do_add_content($this->data['feeddata'], '');
4030                                 $this->data['feedinfo']['version'] = 1;
4031                                 break;
4032
4033                         case 'FEED':
4034                         case $this->namespaces['atom'] . ':FEED':
4035                                 $this->data['feedinfo']['type'] = 'Atom';
4036                                 $this->do_add_content($this->data['feeddata'], '');
4037                                 if (!empty($attribs['VERSION']))
4038                                 {
4039                                         $this->data['feedinfo']['version'] = trim($attribs['VERSION']);
4040                                 }
4041                                 break;
4042
4043                         case 'IMAGE':
4044                         case $this->namespaces['rss2'] . ':IMAGE':
4045                         case $this->namespaces['rss1'] . ':IMAGE':
4046                                 if ($this->inside_channel)
4047                                 {
4048                                         $this->inside_image = true;
4049                                 }
4050                                 break;
4051                 }
4052
4053                 if (!empty($this->data['feedinfo']['type']) && $this->data['feedinfo']['type'] == 'Atom' && ($this->tag_name == 'AUTHOR' || $this->tag_name == $this->namespaces['atom'] . ':AUTHOR'))
4054                 {
4055                         $this->inside_author = true;
4056                 }
4057                 $this->data_handler($this->xml, '');
4058         }
4059
4060         function data_handler($parser, $data)
4061         {
4062                 if ($this->inside_item && $this->depth_inside_item == 1)
4063                 {
4064                         switch ($this->tag_name)
4065                         {
4066                                 case 'TITLE':
4067                                 case $this->namespaces['rss1'] . ':TITLE':
4068                                 case $this->namespaces['rss2'] . ':TITLE':
4069                                 case $this->namespaces['atom'] . ':TITLE':
4070                                         $this->do_add_content($this->data['items'][$this->item_number]['title'], $data);
4071                                         break;
4072                                         
4073                                 case $this->namespaces['dc'] . ':TITLE':
4074                                         $this->do_add_content($this->data['items'][$this->item_number]['dc:title'], $data);
4075                                         break;
4076
4077                                 case 'CONTENT':
4078                                 case $this->namespaces['atom'] . ':CONTENT':
4079                                         $this->do_add_content($this->data['items'][$this->item_number]['content'], $data);
4080                                         break;
4081
4082                                 case $this->namespaces['content'] . ':ENCODED':
4083                                         $this->do_add_content($this->data['items'][$this->item_number]['encoded'], $data);
4084                                         break;
4085
4086                                 case 'SUMMARY':
4087                                 case $this->namespaces['atom'] . ':SUMMARY':
4088                                         $this->do_add_content($this->data['items'][$this->item_number]['summary'], $data);
4089                                         break;
4090
4091                                 case 'LONGDESC':
4092                                         $this->do_add_content($this->data['items'][$this->item_number]['longdesc'], $data);
4093                                         break;
4094
4095                                 case 'DESCRIPTION':
4096                                 case $this->namespaces['rss1'] . ':DESCRIPTION':
4097                                 case $this->namespaces['rss2'] . ':DESCRIPTION':
4098                                         $this->do_add_content($this->data['items'][$this->item_number]['description'], $data);
4099                                         break;
4100
4101                                 case $this->namespaces['dc'] . ':DESCRIPTION':
4102                                         $this->do_add_content($this->data['items'][$this->item_number]['dc:description'], $data);
4103                                         break;
4104
4105                                 case 'LINK':
4106                                 case $this->namespaces['rss1'] . ':LINK':
4107                                 case $this->namespaces['rss2'] . ':LINK':
4108                                 case $this->namespaces['atom'] . ':LINK':
4109                                         $this->do_add_content($this->data['items'][$this->item_number]['link'][$this->item_link_number], $data);
4110                                         break;
4111                                         
4112                                 case 'ENCLOSURE':
4113                                 case $this->namespaces['rss1'] . ':ENCLOSURE':
4114                                 case $this->namespaces['rss2'] . ':ENCLOSURE':
4115                                 case $this->namespaces['atom'] . ':ENCLOSURE':
4116                                         $this->do_add_content($this->data['items'][$this->item_number]['enclosure'][$this->enclosure_number], $data);
4117                                         break;
4118
4119                                 case 'GUID':
4120                                 case $this->namespaces['rss1'] . ':GUID':
4121                                 case $this->namespaces['rss2'] . ':GUID':
4122                                         $this->do_add_content($this->data['items'][$this->item_number]['guid'], $data);
4123                                         break;
4124
4125                                 case 'ID':
4126                                 case $this->namespaces['atom'] . ':ID':
4127                                         $this->do_add_content($this->data['items'][$this->item_number]['id'], $data);
4128                                         break;
4129
4130                                 case 'PUBDATE':
4131                                 case $this->namespaces['rss1'] . ':PUBDATE':
4132                                 case $this->namespaces['rss2'] . ':PUBDATE':
4133                                         $this->do_add_content($this->data['items'][$this->item_number]['pubdate'], $data);
4134                                         break;
4135
4136                                 case $this->namespaces['dc'] . ':DATE':
4137                                         $this->do_add_content($this->data['items'][$this->item_number]['dc:date'], $data);
4138                                         break;
4139
4140                                 case 'ISSUED':
4141                                 case $this->namespaces['atom'] . ':ISSUED':
4142                                         $this->do_add_content($this->data['items'][$this->item_number]['issued'], $data);
4143                                         break;
4144
4145                                 case 'PUBLISHED':
4146                                 case $this->namespaces['atom'] . ':PUBLISHED':
4147                                         $this->do_add_content($this->data['items'][$this->item_number]['published'], $data);
4148                                         break;
4149
4150                                 case 'MODIFIED':
4151                                 case $this->namespaces['atom'] . ':MODIFIED':
4152                                         $this->do_add_content($this->data['items'][$this->item_number]['modified'], $data);
4153                                         break;
4154
4155                                 case 'UPDATED':
4156                                 case $this->namespaces['atom'] . ':UPDATED':
4157                                         $this->do_add_content($this->data['items'][$this->item_number]['updated'], $data);
4158                                         break;
4159         
4160                                 case 'CATEGORY':
4161                                 case $this->namespaces['rss1'] . ':CATEGORY':
4162                                 case $this->namespaces['rss2'] . ':CATEGORY':
4163                                 case $this->namespaces['atom'] . ':CATEGORY':
4164                                         $this->do_add_content($this->data['items'][$this->item_number]['category'][$this->category_number], $data);
4165                                         break;
4166
4167                                 case $this->namespaces['dc'] . ':SUBJECT':
4168                                         $this->do_add_content($this->data['items'][$this->item_number]['subject'][$this->category_number], $data);
4169                                         break;
4170
4171                                 case $this->namespaces['dc'] . ':CREATOR':
4172                                         $this->do_add_content($this->data['items'][$this->item_number]['creator'][$this->author_number], $data);
4173                                         break;
4174
4175                                 case 'AUTHOR':
4176                                 case $this->namespaces['rss1'] . ':AUTHOR':
4177                                 case $this->namespaces['rss2'] . ':AUTHOR':
4178                                         $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['rss'], $data);
4179                                         break;
4180                         }
4181
4182                         if ($this->inside_author)
4183                         {
4184                                 switch ($this->tag_name)
4185                                 {
4186                                         case 'NAME':
4187                                         case $this->namespaces['atom'] . ':NAME':
4188                                                 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['name'], $data);
4189                                                 break;
4190
4191                                         case 'URL':
4192                                         case $this->namespaces['atom'] . ':URL':
4193                                                 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['url'], $data);
4194                                                 break;
4195
4196                                         case 'URI':
4197                                         case $this->namespaces['atom'] . ':URI':
4198                                                 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['uri'], $data);
4199                                                 break;
4200
4201                                         case 'HOMEPAGE':
4202                                         case $this->namespaces['atom'] . ':HOMEPAGE':
4203                                                 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['homepage'], $data);
4204                                                 break;
4205
4206                                         case 'EMAIL':
4207                                         case $this->namespaces['atom'] . ':EMAIL':
4208                                                 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['email'], $data);
4209                                                 break;
4210                                 }
4211                         }
4212                 }
4213
4214                 else if (($this->inside_channel && !$this->inside_image) || (isset($this->data['feedinfo']['type']) && $this->data['feedinfo']['type'] == 'Atom'))
4215                 {
4216                         switch ($this->tag_name)
4217                         {
4218                                 case 'TITLE':
4219                                 case $this->namespaces['rss1'] . ':TITLE':
4220                                 case $this->namespaces['rss2'] . ':TITLE':
4221                                 case $this->namespaces['atom'] . ':TITLE':
4222                                         $this->do_add_content($this->data['info']['title'], $data);
4223                                         break;
4224
4225                                 case 'LINK':
4226                                 case $this->namespaces['rss1'] . ':LINK':
4227                                 case $this->namespaces['rss2'] . ':LINK':
4228                                 case $this->namespaces['atom'] . ':LINK':
4229                                         $this->do_add_content($this->data['info']['link'][$this->link_number], $data);
4230                                         break;
4231
4232                                 case 'DESCRIPTION':
4233                                 case $this->namespaces['rss1'] . ':DESCRIPTION':
4234                                 case $this->namespaces['rss2'] . ':DESCRIPTION':
4235                                         $this->do_add_content($this->data['info']['description'], $data);
4236                                         break;
4237
4238                                 case $this->namespaces['dc'] . ':DESCRIPTION':
4239                                         $this->do_add_content($this->data['info']['dc:description'], $data);
4240                                         break;
4241
4242                                 case 'TAGLINE':
4243                                 case $this->namespaces['atom'] . ':TAGLINE':
4244                                         $this->do_add_content($this->data['info']['tagline'], $data);
4245                                         break;
4246
4247                                 case 'SUBTITLE':
4248                                 case $this->namespaces['atom'] . ':SUBTITLE':
4249                                         $this->do_add_content($this->data['info']['subtitle'], $data);
4250                                         break;
4251
4252                                 case 'COPYRIGHT':
4253                                 case $this->namespaces['rss1'] . ':COPYRIGHT':
4254                                 case $this->namespaces['rss2'] . ':COPYRIGHT':
4255                                 case $this->namespaces['atom'] . ':COPYRIGHT':
4256                                         $this->do_add_content($this->data['info']['copyright'], $data);
4257                                         break;
4258
4259                                 case 'LANGUAGE':
4260                                 case $this->namespaces['rss1'] . ':LANGUAGE':
4261                                 case $this->namespaces['rss2'] . ':LANGUAGE':
4262                                         $this->do_add_content($this->data['info']['language'], $data);
4263                                         break;
4264                                 
4265                                 case 'LOGO':
4266                                 case $this->namespaces['atom'] . ':LOGO':
4267                                         $this->do_add_content($this->data['info']['logo'], $data);
4268                                         break;
4269                                 
4270                         }
4271                 }
4272
4273                 else if ($this->inside_channel && $this->inside_image)
4274                 {
4275                         switch ($this->tag_name)
4276                         {
4277                                 case 'TITLE':
4278                                 case $this->namespaces['rss1'] . ':TITLE':
4279                                 case $this->namespaces['rss2'] . ':TITLE':
4280                                         $this->do_add_content($this->data['info']['image']['title'], $data);
4281                                         break;
4282
4283                                 case 'URL':
4284                                 case $this->namespaces['rss1'] . ':URL':
4285                                 case $this->namespaces['rss2'] . ':URL':
4286                                         $this->do_add_content($this->data['info']['image']['url'], $data);
4287                                         break;
4288
4289                                 case 'LINK':
4290                                 case $this->namespaces['rss1'] . ':LINK':
4291                                 case $this->namespaces['rss2'] . ':LINK':
4292                                         $this->do_add_content($this->data['info']['image']['link'], $data);
4293                                         break;
4294
4295                                 case 'WIDTH':
4296                                 case $this->namespaces['rss1'] . ':WIDTH':
4297                                 case $this->namespaces['rss2'] . ':WIDTH':
4298                                         $this->do_add_content($this->data['info']['image']['width'], $data);
4299                                         break;
4300
4301                                 case 'HEIGHT':
4302                                 case $this->namespaces['rss1'] . ':HEIGHT':
4303                                 case $this->namespaces['rss2'] . ':HEIGHT':
4304                                         $this->do_add_content($this->data['info']['image']['height'], $data);
4305                                         break;
4306                         }
4307                 }
4308                 $this->is_first = false;
4309         }
4310
4311         function end_handler($parser, $name)
4312         {
4313                 $this->tag_name = '';
4314                 switch ($name)
4315                 {
4316                         case 'ITEM':
4317                         case $this->namespaces['rss1'] . ':ITEM':
4318                         case $this->namespaces['rss2'] . ':ITEM':
4319                         case 'ENTRY':
4320                         case $this->namespaces['atom'] . ':ENTRY':
4321                                 $this->inside_item = false;
4322                                 $this->item_number++;
4323                                 $this->author_number = 0;
4324                                 $this->category_number = 0;
4325                                 $this->enclosure_number = 0;
4326                                 $this->item_link_number = 0;
4327                                 break;
4328
4329                         case 'CHANNEL':
4330                         case $this->namespaces['rss1'] . ':CHANNEL':
4331                         case $this->namespaces['rss2'] . ':CHANNEL':
4332                                 $this->inside_channel = false;
4333                                 break;
4334
4335                         case 'IMAGE':
4336                         case $this->namespaces['rss1'] . ':IMAGE':
4337                         case $this->namespaces['rss2'] . ':IMAGE':
4338                                 $this->inside_image = false;
4339                                 break;
4340
4341                         case 'AUTHOR':
4342                         case $this->namespaces['rss1'] . ':AUTHOR':
4343                         case $this->namespaces['rss2'] . ':AUTHOR':
4344                         case $this->namespaces['atom'] . ':AUTHOR':
4345                                 $this->author_number++;
4346                                 $this->inside_author = false;
4347                                 break;
4348
4349                         case 'CATEGORY':
4350                         case $this->namespaces['rss1'] . ':CATEGORY':
4351                         case $this->namespaces['rss2'] . ':CATEGORY':
4352                         case $this->namespaces['atom'] . ':CATEGORY':
4353                         case $this->namespaces['dc'] . ':SUBJECT':
4354                                 $this->category_number++;
4355                                 break;
4356                         
4357                         case 'ENCLOSURE':
4358                         case $this->namespaces['rss1'] . ':ENCLOSURE':
4359                         case $this->namespaces['rss2'] . ':ENCLOSURE':
4360                                 $this->enclosure_number++;
4361                                 break;
4362                                 
4363                         case 'LINK':
4364                         case $this->namespaces['rss1'] . ':LINK':
4365                         case $this->namespaces['rss2'] . ':LINK':
4366                         case $this->namespaces['atom'] . ':LINK':
4367                                 if ($this->inside_item)
4368                                 {
4369                                         $this->item_link_number++;
4370                                 }
4371                                 else
4372                                 {
4373                                         $this->link_number++;
4374                                 }
4375                                 break;
4376                 }
4377                 if ($this->inside_item)
4378                 {
4379                         $this->depth_inside_item--;
4380                 }
4381         }
4382         
4383         function start_name_space($parser, $prefix, $uri = null)
4384         {
4385                 $prefix = strtoupper($prefix);
4386                 $uri = strtoupper($uri);
4387                 if ($prefix == 'ATOM' || $uri == 'HTTP://WWW.W3.ORG/2005/ATOM' || $uri == 'HTTP://PURL.ORG/ATOM/NS#')
4388                 {
4389                         $this->namespaces['atom'] = $uri;
4390                 }
4391                 else if ($prefix == 'RSS2' || $uri == 'HTTP://BACKEND.USERLAND.COM/RSS2')
4392                 {
4393                         $this->namespaces['rss2'] = $uri;
4394                 }
4395                 else if ($prefix == 'RDF' || $uri == 'HTTP://WWW.W3.ORG/1999/02/22-RDF-SYNTAX-NS#')
4396                 {
4397                         $this->namespaces['rdf'] = $uri;
4398                 }
4399                 else if ($prefix == 'RSS' || $uri == 'HTTP://PURL.ORG/RSS/1.0/' || $uri == 'HTTP://MY.NETSCAPE.COM/RDF/SIMPLE/0.9/')
4400                 {
4401                         $this->namespaces['rss1'] = $uri;
4402                 }
4403                 else if ($prefix == 'DC' || $uri == 'HTTP://PURL.ORG/DC/ELEMENTS/1.1/')
4404                 {
4405                         $this->namespaces['dc'] = $uri;
4406                 }
4407                 else if ($prefix == 'XHTML' || $uri == 'HTTP://WWW.W3.ORG/1999/XHTML')
4408                 {
4409                         $this->namespaces['xhtml'] = $uri;
4410                         $this->xhtml_prefix = $prefix;
4411                 }
4412                 else if ($prefix == 'CONTENT' || $uri == 'HTTP://PURL.ORG/RSS/1.0/MODULES/CONTENT/')
4413                 {
4414                         $this->namespaces['content'] = $uri;
4415                 }
4416         }
4417         
4418         function end_name_space($parser, $prefix)
4419         {
4420                 if ($key = array_search(strtoupper($prefix), $this->namespaces))
4421                 {
4422                         if ($key == 'atom')
4423                         {
4424                                 $this->namespaces['atom'] = 'ATOM';
4425                         }
4426                         else if ($key == 'rss2')
4427                         {
4428                                 $this->namespaces['rss2'] = 'RSS';
4429                         }
4430                         else if ($key == 'rdf')
4431                         {
4432                                 $this->namespaces['rdf'] = 'RDF';
4433                         }
4434                         else if ($key == 'rss1')
4435                         {
4436                                 $this->namespaces['rss1'] = 'RSS';
4437                         }
4438                         else if ($key == 'dc')
4439                         {
4440                                 $this->namespaces['dc'] = 'DC';
4441                         }
4442                         else if ($key == 'xhtml')
4443                         {
4444                                 $this->namespaces['xhtml'] = 'XHTML';
4445                                 $this->xhtml_prefix = 'XHTML';
4446                         }
4447                         else if ($key == 'content')
4448                         {
4449                                 $this->namespaces['content'] = 'CONTENT';
4450                         }
4451                 }
4452         }
4453 }
4454
4455 class SimplePie_Sanitize
4456 {
4457         // Private vars
4458         var $feedinfo;
4459         var $info;
4460         var $items;
4461         var $feed_xmlbase;
4462         var $item_xmlbase;
4463         var $attribs;
4464         var $cached_entities;
4465         var $cache_convert_entities;
4466         
4467         // Options
4468         var $remove_div = true;
4469         var $strip_ads = false;
4470         var $replace_headers = false;
4471         var $bypass_image_hotlink = false;
4472         var $bypass_image_hotlink_page = false;
4473         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
4474         var $encode_instead_of_strip = false;
4475         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur');
4476         var $input_encoding = 'UTF-8';
4477         var $output_encoding = 'UTF-8';
4478         var $item_class = 'SimplePie_Item';
4479         var $author_class = 'SimplePie_Author';
4480         var $enclosure_class = 'SimplePie_Enclosure';
4481         
4482         function remove_div($enable = true)
4483         {
4484                 $this->remove_div = (bool) $enable;
4485         }
4486         
4487         function strip_ads($enable = false)
4488         {
4489                 $this->strip_ads = (bool) $enable;
4490         }
4491         
4492         function replace_headers($enable = false)
4493         {
4494                 $this->enable_headers = (bool) $enable;
4495         }
4496         
4497         function bypass_image_hotlink($get = false)
4498         {
4499                 if ($get)
4500                 {
4501                         $this->bypass_image_hotlink = (string) $get;
4502                 }
4503                 else
4504                 {
4505                         $this->bypass_image_hotlink = false;
4506                 }
4507         }
4508         
4509         function bypass_image_hotlink_page($page = false)
4510         {
4511                 if ($page)
4512                 {
4513                         $this->bypass_image_hotlink_page = (string) $page;
4514                 }
4515                 else
4516                 {
4517                         $this->bypass_image_hotlink_page = false;
4518                 }
4519         }
4520         
4521         function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
4522         {
4523                 if ($tags)
4524                 {
4525                         if (is_array($tags))
4526                         {
4527                                 $this->strip_htmltags = $tags;
4528                         }
4529                         else
4530                         {
4531                                 $this->strip_htmltags = explode(',', $tags);
4532                         }
4533                 }
4534                 else
4535                 {
4536                         $this->strip_htmltags = false;
4537                 }
4538         }
4539         
4540         function encode_instead_of_strip($enable = false)
4541         {
4542                 $this->encode_instead_of_strip = (bool) $enable;
4543         }
4544         
4545         function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur'))
4546         {
4547                 if ($attribs)
4548                 {
4549                         if (is_array($attribs))
4550                         {
4551                                 $this->strip_attributes = $attribs;
4552                         }
4553                         else
4554                         {
4555                                 $this->strip_attributes = explode(',', $attribs);
4556                         }
4557                 }
4558                 else
4559                 {
4560                         $this->strip_attributes = false;
4561                 }
4562         }
4563         
4564         function input_encoding($encoding = 'UTF-8')
4565         {
4566                 $this->input_encoding = (string) $encoding;
4567         }
4568         
4569         function output_encoding($encoding = 'UTF-8')
4570         {
4571                 $this->output_encoding = (string) $encoding;
4572         }
4573         
4574         function set_item_class($class = 'SimplePie_Item')
4575         {
4576                 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Item'))
4577                 {
4578                         $this->item_class = $class;
4579                         return true;
4580                 }
4581                 return false;
4582         }
4583         
4584         function set_author_class($class = 'SimplePie_Author')
4585         {
4586                 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Author'))
4587                 {
4588                         $this->author_class = $class;
4589                         return true;
4590                 }
4591                 return false;
4592         }
4593         
4594         function set_enclosure_class($class = 'SimplePie_Enclosure')
4595         {
4596                 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Enclosure'))
4597                 {
4598                         $this->enclosure_class = $class;
4599                         return true;
4600                 }
4601                 return false;
4602         }
4603         
4604         function parse_data_array(&$data, $url)
4605         {               
4606                 // Feed Info (Type and Version)
4607                 if (!empty($data['feedinfo']['type']))
4608                 {
4609                         $this->feedinfo = $data['feedinfo'];
4610                 }
4611                 
4612                 // Feed level xml:base
4613                 if (!empty($data['feeddata']['attribs']['XML:BASE']))
4614                 {
4615                         $this->feed_xmlbase = $data['feeddata']['attribs']['XML:BASE'];
4616                 }
4617                 else if (!empty($data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE']))
4618                 {
4619                         $this->feed_xmlbase = $data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE'];
4620                 }
4621                 // FeedBurner feeds use alternate link
4622                 else if (strpos($url, 'http://feeds.feedburner.com/') !== 0)
4623                 {
4624                         $this->feed_xmlbase = SimplePie_Misc::parse_url($url);
4625                         if (empty($this->feed_xmlbase['authority']))
4626                         {
4627                                 $this->feed_xmlbase = preg_replace('/^' . preg_quote(realpath($_SERVER['DOCUMENT_ROOT']), '/') . '/', '', realpath($url));
4628                         }
4629                         else
4630                         {
4631                                 $this->feed_xmlbase = $url;
4632                         }
4633                 }
4634                 
4635                 
4636                 // Feed link(s)
4637                 if (!empty($data['info']['link']))
4638                 {
4639                         foreach ($data['info']['link'] as $link)
4640                         {
4641                                 if (empty($link['attribs']['REL']))
4642                                 {
4643                                         $rel = 'alternate';
4644                                 }
4645                                 else
4646                                 {
4647                                         $rel = strtolower($link['attribs']['REL']);
4648                                 }
4649                                 if ($rel == 'enclosure')
4650                                 {
4651                                         $href = null;
4652                                         $type = null;
4653                                         $length = null;
4654                                         if (!empty($link['data']))
4655                                         {
4656                                                 $href = $this->sanitize($link['data'], $link['attribs'], true);
4657                                         }
4658                                         else if (!empty($link['attribs']['HREF']))
4659                                         {
4660                                                 $href = $this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
4661                                         }
4662                                         if (!empty($link['attribs']['TYPE'])) {
4663                                                 $type = $this->sanitize($link['attribs']['TYPE'], $link['attribs']);
4664                                         }
4665                                         if (!empty($link['attribs']['LENGTH'])) {
4666                                                 $length = $this->sanitize($link['attribs']['LENGTH'], $link['attribs']);
4667                                         }
4668                                         $this->info['link']['enclosure'][] = new $this->enclosure_class($href, $type, $length);
4669                                 }
4670                                 else
4671                                 {
4672                                         if (!empty($link['data']))
4673                                         {
4674                                                 $this->info['link'][$rel][] = $this->sanitize($link['data'], $link['attribs'], true);
4675                                         }
4676                                         else if (!empty($link['attribs']['HREF']))
4677                                         {
4678                                                 $this->info['link'][$rel][] = $this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
4679                                         }
4680                                 }
4681                         }
4682                 }
4683                 
4684                 // Use the first alternate link if we don't have any feed xml:base
4685                 if (empty($this->feed_xmlbase) && !empty($this->info['link']['alternate'][0]))
4686                 {
4687                         $this->feed_xmlbase = $this->info['link']['alternate'][0];
4688                 }
4689                 
4690                 // Feed Title
4691                 if (!empty($data['info']['title']['data']))
4692                 {
4693                         $this->info['title'] = $this->sanitize($data['info']['title']['data'], $data['info']['title']['attribs']);
4694                 }
4695                 
4696                 // Feed Descriptions
4697                 if (!empty($data['info']['description']['data']))
4698                 {
4699                         $this->info['description'] = $this->sanitize($data['info']['description']['data'], $data['info']['description']['attribs'], false, true);
4700                 }
4701                 if (!empty($data['info']['dc:description']['data']))
4702                 {
4703                         $this->info['dc:description'] = $this->sanitize($data['info']['dc:description']['data'], $data['info']['dc:description']['attribs']);
4704                 }
4705                 if (!empty($data['info']['tagline']['data']))
4706                 {
4707                         $this->info['tagline'] = $this->sanitize($data['info']['tagline']['data'], $data['info']['tagline']['attribs']);
4708                 }
4709                 if (!empty($data['info']['subtitle']['data']))
4710                 {
4711                         $this->info['subtitle'] = $this->sanitize($data['info']['subtitle']['data'], $data['info']['subtitle']['attribs']);
4712                 }
4713                 
4714                 // Feed Language
4715                 if (!empty($data['info']['language']['data']))
4716                 {
4717                         $this->info['language'] = $this->sanitize($data['info']['language']['data'], $data['info']['language']['attribs']);
4718                 }
4719                 if (!empty($data['feeddata']['attribs']['XML:LANG']))
4720                 {
4721                         $this->info['xml:lang'] = $this->sanitize($data['feeddata']['attribs']['XML:LANG'], null);
4722                 }
4723                 else if (!empty($data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:LANG']))
4724                 {
4725                         $this->info['xml:lang'] = $this->sanitize($data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:LANG'], null);
4726                 }
4727                 
4728                 // Feed Copyright
4729                 if (!empty($data['info']['copyright']['data']))
4730                 {
4731                         $this->info['copyright'] = $this->sanitize($data['info']['copyright']['data'], $data['info']['copyright']['attribs']);
4732                 }
4733                 
4734                 // Feed Image
4735                 if (!empty($data['info']['image']['title']['data']))
4736                 {
4737                         $this->info['image']['title'] = $this->sanitize($data['info']['image']['title']['data'], $data['info']['image']['title']['attribs']);
4738                 }
4739                 if (!empty($data['info']['image']['url']['data']))
4740                 {
4741                         $this->info['image']['url'] = $this->sanitize($data['info']['image']['url']['data'], $data['info']['image']['url']['attribs'], true);
4742                 }
4743                 if (!empty($data['info']['logo']['data']))
4744                 {
4745                         $this->info['image']['logo'] = $this->sanitize($data['info']['logo']['data'], $data['info']['logo']['attribs'], true);
4746                 }
4747                 if (!empty($data['info']['image']['link']['data']))
4748                 {
4749                         $this->info['image']['link'] = $this->sanitize($data['info']['image']['link']['data'], $data['info']['image']['link']['attribs'], true);
4750                 }
4751                 if (!empty($data['info']['image']['width']['data']))
4752                 {
4753                         $this->info['image']['width'] = $this->sanitize($data['info']['image']['width']['data'], $data['info']['image']['width']['attribs']);
4754                 }
4755                 if (!empty($data['info']['image']['height']['data']))
4756                 {
4757                         $this->info['image']['height'] = $this->sanitize($data['info']['image']['height']['data'], $data['info']['image']['height']['attribs']);
4758                 }
4759                 
4760                 // Items
4761                 if (!empty($data['items']))
4762                 {
4763                         foreach ($data['items'] as $key => $item)
4764                         {
4765                                 $newitem = null;
4766                                 
4767                                 // Item level xml:base
4768                                 if (!empty($item['attribs']['XML:BASE']))
4769                                 {
4770                                         $this->item_xmlbase = SimplePie_Misc::absolutize_url($item['attribs']['XML:BASE'], $this->feed_xmlbase);
4771                                 }
4772                                 else if (!empty($item['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE']))
4773                                 {
4774                                         $this->item_xmlbase = SimplePie_Misc::absolutize_url($item['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE'], $this->feed_xmlbase);
4775                                 }
4776                                 else
4777                                 {
4778                                         $this->item_xmlbase = null;
4779                                 }
4780         
4781                                 // Title
4782                                 if (!empty($item['title']['data'])) {
4783                                         $newitem['title'] = $this->sanitize($item['title']['data'], $item['title']['attribs']);
4784                                 }
4785                                 if (!empty($item['dc:title']['data']))
4786                                 {
4787                                         $newitem['dc:title'] = $this->sanitize($item['dc:title']['data'], $item['dc:title']['attribs']);
4788                                 }
4789                                 
4790                                 // Description
4791                                 if (!empty($item['content']['data']))
4792                                 {
4793                                         $newitem['content'] = $this->sanitize($item['content']['data'], $item['content']['attribs']);
4794                                 }
4795                                 if (!empty($item['encoded']['data']))
4796                                 {
4797                                         $newitem['encoded'] = $this->sanitize($item['encoded']['data'], $item['encoded']['attribs']);
4798                                 }
4799                                 if (!empty($item['summary']['data']))
4800                                 {
4801                                         $newitem['summary'] = $this->sanitize($item['summary']['data'], $item['summary']['attribs']);
4802                                 }
4803                                 if (!empty($item['description']['data']))
4804                                 {
4805                                         $newitem['description'] = $this->sanitize($item['description']['data'], $item['description']['attribs'], false, true);
4806                                 }
4807                                 if (!empty($item['dc:description']['data']))
4808                                 {
4809                                         $newitem['dc:description'] = $this->sanitize($item['dc:description']['data'], $item['dc:description']['attribs']);
4810                                 }
4811                                 if (!empty($item['longdesc']['data']))
4812                                 {
4813                                         $newitem['longdesc'] = $this->sanitize($item['longdesc']['data'], $item['longdesc']['attribs']);
4814                                 }
4815                 
4816                                 // Link(s)
4817                                 if (!empty($item['link']))
4818                                 {
4819                                         foreach ($item['link'] as $link)
4820                                         {
4821                                                 if (empty($link['attribs']['REL']))
4822                                                 {
4823                                                         $rel = 'alternate';
4824                                                 }
4825                                                 else
4826                                                 {
4827                                                         $rel = strtolower($link['attribs']['REL']);
4828                                                 }
4829                                                 if ($rel == 'enclosure')
4830                                                 {
4831                                                         $href = null;
4832                                                         $type = null;
4833                                                         $length = null;
4834                                                         if (!empty($link['data']))
4835                                                         {
4836                                                                 $href = $this->sanitize($link['data'], $link['attribs'], true);
4837                                                         }
4838                                                         else if (!empty($link['attribs']['HREF']))
4839                                                         {
4840                                                                 $href = $this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
4841                                                         }
4842                                                         if (!empty($link['attribs']['TYPE'])) {
4843                                                                 $type = $this->sanitize($link['attribs']['TYPE'], $link['attribs']);
4844                                                         }
4845                                                         if (!empty($link['attribs']['LENGTH'])) {
4846                                                                 $length = $this->sanitize($link['attribs']['LENGTH'], $link['attribs']);
4847                                                         }
4848                                                         if (!empty($href))
4849                                                         {
4850                                                                 $newitem['link'][$rel][] = new $this->enclosure_class($href, $type, $length);
4851                                                         }
4852                                                 }
4853                                                 else
4854                                                 {
4855                                                         if (!empty($link['data']))
4856                                                         {
4857                                                                 $newitem['link'][$rel][] = $this->sanitize($link['data'], $link['attribs'], true);
4858                                                         }
4859                                                         else if (!empty($link['attribs']['HREF']))
4860                                                         {
4861                                                                 $newitem['link'][$rel][] = $this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
4862                                                         }
4863                                                 }
4864                                         }
4865                                 }
4866                                 
4867                                 // Enclosure(s)
4868                                 if (!empty($item['enclosure']))
4869                                 {
4870                                         foreach ($item['enclosure'] as $enclosure)
4871                                         {
4872                                                 if (!empty($enclosure['attribs']['URL']))
4873                                                 {
4874                                                         $type = null;
4875                                                         $length = null;
4876                                                         $href = $this->sanitize($enclosure['attribs']['URL'], $enclosure['attribs'], true);
4877                                                         if (!empty($enclosure['attribs']['TYPE']))
4878                                                         {
4879                                                                 $type = $this->sanitize($enclosure['attribs']['TYPE'], $enclosure['attribs']);
4880                                                         }
4881                                                         if (!empty($enclosure['attribs']['LENGTH']))
4882                                                         {
4883                                                                 $length = $this->sanitize($enclosure['attribs']['LENGTH'], $enclosure['attribs']);
4884                                                         }
4885                                                         $newitem['enclosures'][] = new $this->enclosure_class($href, $type, $length);
4886                                                 }
4887                                         }
4888                                 }
4889                                 
4890                                 // ID
4891                                 if (!empty($item['guid']['data']))
4892                                 {
4893                                         if (!empty($item['guid']['attribs']['ISPERMALINK']) && strtolower($item['guid']['attribs']['ISPERMALINK']) == 'false')
4894                                         {
4895                                                 $newitem['guid']['permalink'] = false;
4896                                         }
4897                                         else
4898                                         {
4899                                                 $newitem['guid']['permalink'] = true;
4900                                         }
4901                                         $newitem['guid']['data'] = $this->sanitize($item['guid']['data'], $item['guid']['attribs']);
4902                                 }
4903                                 if (!empty($item['id']['data']))
4904                                 {
4905                                         $newitem['id'] = $this->sanitize($item['id']['data'], $item['id']['attribs']);
4906                                 }
4907                                 
4908                                 // Date
4909                                 if (!empty($item['pubdate']['data']))
4910                                 {
4911                                         $newitem['pubdate'] = $this->parse_date($this->sanitize($item['pubdate']['data'], $item['pubdate']['attribs']));
4912                                 }
4913                                 if (!empty($item['dc:date']['data']))
4914                                 {
4915                                         $newitem['dc:date'] = $this->parse_date($this->sanitize($item['dc:date']['data'], $item['dc:date']['attribs']));
4916                                 }
4917                                 if (!empty($item['issued']['data']))
4918                                 {
4919                                         $newitem['issued'] = $this->parse_date($this->sanitize($item['issued']['data'], $item['issued']['attribs']));
4920                                 }
4921                                 if (!empty($item['published']['data']))
4922                                 {
4923                                         $newitem['published'] = $this->parse_date($this->sanitize($item['published']['data'], $item['published']['attribs']));
4924                                 }
4925                                 if (!empty($item['modified']['data']))
4926                                 {
4927                                         $newitem['modified'] = $this->parse_date($this->sanitize($item['modified']['data'], $item['modified']['attribs']));
4928                                 }
4929                                 if (!empty($item['updated']['data']))
4930                                 {
4931                                         $newitem['updated'] = $this->parse_date($this->sanitize($item['updated']['data'], $item['updated']['attribs']));
4932                                 }
4933                                 
4934                                 // Categories
4935                                 if (!empty($item['category']))
4936                                 {
4937                                         foreach ($item['category'] as $category)
4938                                         {
4939                                                 if (!empty($category['data']))
4940                                                 {
4941                                                         $newitem['category'][] = $this->sanitize($category['data'], $category['attribs']);
4942                                                 }
4943                                                 else if (!empty($category['attribs']['TERM']))
4944                                                 {
4945                                                         $newitem['term'][] = $this->sanitize($category['attribs']['TERM'], $category['attribs']);
4946                                                 }
4947                                         }
4948                                 }
4949                                 if (!empty($item['subject']))
4950                                 {
4951                                         foreach ($item['subject'] as $category)
4952                                         {
4953                                                 if (!empty($category['data']))
4954                                                 {
4955                                                         $newitem['subject'][] = $this->sanitize($category['data'], $category['attribs']);
4956                                                 }
4957                                         }
4958                                 }
4959                                 
4960                                 // Author
4961                                 if (!empty($item['creator']))
4962                                 {
4963                                         foreach ($item['creator'] as $creator)
4964                                         {
4965                                                 if (!empty($creator['data']))
4966                                                 {
4967                                                         $newitem['creator'][] = new $this->author_class($this->sanitize($creator['data'], $creator['attribs']), null, null);
4968                                                 }
4969                                         }
4970                                 }
4971                                 if (!empty($item['author']))
4972                                 {
4973                                         foreach ($item['author'] as $author)
4974                                         {
4975                                                 $name = null;
4976                                                 $link = null;
4977                                                 $email = null;
4978                                                 if (!empty($author['rss']))
4979                                                 {
4980                                                         $sane = $this->sanitize($author['rss']['data'], $author['rss']['attribs']);
4981                                                         if (preg_match('/(.*)@(.*) \((.*)\)/msiU', $sane, $matches)) {
4982                                                                 $name = trim($matches[3]);
4983                                                                 $email = trim("$matches[1]@$matches[2]");
4984                                                         } else {
4985                                                                 $email = $sane;
4986                                                         }
4987                                                 }
4988                                                 else
4989                                                 {
4990                                                         if (!empty($author['name']))
4991                                                         {
4992                                                                 $name = $this->sanitize($author['name']['data'], $author['name']['attribs']);
4993                                                         }
4994                                                         if (!empty($author['url']))
4995                                                         {
4996                                                                 $link = $this->sanitize($author['url']['data'], $author['url']['attribs'], true);
4997                                                         }
4998                                                         else if (!empty($author['uri']))
4999                                                         {
5000                                                                 $link = $this->sanitize($author['uri']['data'], $author['uri']['attribs'], true);
5001                                                         }
5002                                                         else if (!empty($author['homepage']))
5003                                                         {
5004                                                                 $link = $this->sanitize($author['homepage']['data'], $author['homepage']['attribs'], true);
5005                                                         }
5006                                                         if (!empty($author['email'])) {
5007                                                                 $email = $this->sanitize($author['email']['data'], $author['email']['attribs']);
5008                                                         }
5009                                                 }
5010                                                 $newitem['author'][] = new $this->author_class($name, $link, $email);
5011                                         }
5012                                 }
5013                                 unset($data['items'][$key]);
5014                                 $this->items[] = new $this->item_class($newitem);
5015                         }
5016                 }
5017         }
5018         
5019         function sanitize($data, $attribs, $is_url = false, $force_decode = false)
5020         {
5021                 $this->attribs = $attribs;
5022                 if (isset($this->feedinfo['type']) && $this->feedinfo['type'] == 'Atom')
5023                 {
5024                         if ((!empty($attribs['MODE']) && $attribs['MODE'] == 'base64') || (!empty($attribs['TYPE']) && $attribs['TYPE'] == 'application/octet-stream'))
5025                         {
5026                                 $data = trim($data);
5027                                 $data = base64_decode($data);
5028                         }
5029                         else if ((!empty($attribs['MODE']) && $attribs['MODE'] == 'escaped' || !empty($attribs['TYPE']) && ($attribs['TYPE'] == 'html' || $attribs['TYPE'] == 'text/html')))
5030                         {
5031                                 $data = $this->entities_decode($data);
5032                         }
5033                         if (!empty($attribs['TYPE']) && ($attribs['TYPE'] == 'xhtml' || $attribs['TYPE'] == 'application/xhtml+xml'))
5034                         {
5035                                 if ($this->remove_div)
5036                                 {
5037                                         $data = preg_replace('/<div( .*)?>/msiU', '', strrev(preg_replace('/>vid\/</i', '', strrev($data), 1)), 1);
5038                                 }
5039                                 else
5040                                 {
5041                                         $data = preg_replace('/<div( .*)?>/msiU', '<div>', $data, 1);
5042                                 }
5043                                 $data = $this->convert_entities($data);
5044                         }
5045                 }
5046                 else
5047                 {
5048                         $data = $this->convert_entities($data);
5049                 }
5050                 if ($force_decode)
5051                 {
5052                         $data = $this->entities_decode($data);
5053                 }
5054                 $data = trim($data);
5055                 $data = preg_replace('/<\!--([^-]|-[^-])*-->/msiU', '', $data);
5056
5057                 // If Strip Ads is enabled, strip them.
5058                 if ($this->strip_ads)
5059                 {
5060                         $data = preg_replace('/<a (.*)href=(.*)click\.phdo\?s=(.*)<\/a>/msiU', '', $data); // Pheedo links (tested with Dooce.com)
5061                         $data = preg_replace('/<p(.*)>(.*)<a href="http:\/\/ad.doubleclick.net\/jump\/(.*)<\/p>/msiU', '', $data); // Doubleclick links (tested with InfoWorld.com)
5062                         $data = preg_replace('/<p><map (.*)name=(.*)google_ad_map(.*)<\/p>/msiU', '', $data); // Google AdSense for Feeds (tested with tuaw.com).
5063                         // Feedflare, from Feedburner
5064                 }
5065
5066                 // Replace H1, H2, and H3 tags with the less important H4 tags.
5067                 // This is because on a site, the more important headers might make sense,
5068                 // but it most likely doesn't fit in the context of RSS-in-a-webpage.
5069                 if ($this->replace_headers)
5070                 {
5071                         $data = preg_replace('/<h[1-3]((\s*((\w+:)?\w+)\s*=\s*("([^"]*)"|\'([^\']*)\'|(.*)))*)\s*>/msiU', '<h4\\1>', $data);
5072                         $data = preg_replace('/<\/h[1-3]>/i', '</h4>', $data);
5073                 }
5074
5075                 if ($is_url)
5076                 {
5077                         $data = $this->replace_urls($data, true);
5078                 }
5079                 else
5080                 {
5081                         $data = preg_replace_callback('/<(\S+)((\s*((\w+:)?\w+)\s*=\s*("([^"]*)"|\'([^\']*)\'|(.*)))*)\s*(\/>|>(.*)<\/\S+>)/msiU', array(&$this, 'replace_urls'), $data);
5082                 }
5083
5084                 // If Bypass Image Hotlink is enabled, rewrite all the image tags.
5085                 if ($this->bypass_image_hotlink)
5086                 {
5087                         $images = SimplePie_Misc::get_element('img', $data);
5088                         foreach ($images as $img)
5089                         {
5090                                 if (!empty($img['attribs']['SRC']['data']))
5091                                 {
5092                                         $pre = '';
5093                                         if ($this->bypass_image_hotlink_page)
5094                                         {
5095                                                 $pre = $this->bypass_image_hotlink_page;
5096                                         }
5097                                         $pre .= "?$this->bypass_image_hotlink=";
5098                                         $img['attribs']['SRC']['data'] = $pre . rawurlencode(strtr($img['attribs']['SRC']['data'], array_flip(get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES))));
5099                                         $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
5100                                 }
5101                         }
5102                 }
5103
5104                 // Strip out HTML tags and attributes that might cause various security problems.
5105                 // Based on recommendations by Mark Pilgrim at:
5106                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
5107                 if ($this->strip_htmltags)
5108                 {
5109                         foreach ($this->strip_htmltags as $tag)
5110                         {
5111                                 $data = preg_replace_callback("/<($tag)((\s*((\w+:)?\w+)(\s*=\s*(\"([^\"]*)\"|'([^']*)'|(.*)))?)*)\s*(\/>|>(.*)<\/($tag)((\s*((\w+:)?\w+)(\s*=\s*(\"([^\"]*)\"|'([^']*)'|(.*)))?)*)\s*>)/msiU", array(&$this, 'do_strip_htmltags'), $data);
5112                         }
5113                 }
5114
5115                 if ($this->strip_attributes)
5116                 {
5117                         foreach ($this->strip_attributes as $attrib)
5118                         {
5119                                 $data = preg_replace('/ '. trim($attrib) .'=("|&quot;)(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|\'|&apos;|<|>|\+|{|})*("|&quot;)/i', '', $data);
5120                                 $data = preg_replace('/ '. trim($attrib) .'=(\'|&apos;)(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|"|&quot;|<|>|\+|{|})*(\'|&apos;)/i', '', $data);
5121                                 $data = preg_replace('/ '. trim($attrib) .'=(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|\+|{|})*/i', '', $data);
5122                         }
5123                 }
5124                 
5125                 // Convert encoding
5126                 $data = SimplePie_Misc::change_encoding($data, $this->input_encoding, $this->output_encoding);
5127
5128                 return $data;
5129         }
5130         
5131         function do_strip_htmltags($match)
5132         {
5133                 if ($this->encode_instead_of_strip)
5134                 {
5135                         if (isset($match[12]) && !in_array(strtolower($match[1]), array('script', 'style')))
5136                         {
5137                                 return "&lt;$match[1]$match[2]&gt;$match[12]&lt;/$match[1]&gt;";
5138                         }
5139                         else if (isset($match[12]))
5140                         {
5141                                 return "&lt;$match[1]$match[2]&gt;&lt;/$match[1]&gt;";
5142                         }
5143                         else
5144                         {
5145                                 return "&lt;$match[1]$match[2]/&gt;";
5146                         }
5147                 }
5148                 else
5149                 {
5150                         if (isset($match[12]) && !in_array(strtolower($match[1]), array('script', 'style')))
5151                         {
5152                                 return $match[12];
5153                         }
5154                         else
5155                         {
5156                                 return '';
5157                         }
5158                 }
5159         }
5160         
5161         function replace_urls($data, $raw_url = false)
5162         {
5163                 if (!empty($this->attribs['XML:BASE']))
5164                 {
5165                         $xmlbase = $attribs['XML:BASE'];
5166                 }
5167                 else if (!empty($this->attribs['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE']))
5168                 {
5169                         $xmlbase = $this->attribs['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE'];
5170                 }
5171                 if (!empty($xmlbase))
5172                 {
5173                         if (!empty($this->item_xmlbase))
5174                         {
5175                                 $xmlbase = SimplePie_Misc::absolutize_url($xmlbase, $this->item_xmlbase);
5176                         }
5177                         else
5178                         {
5179                                 $xmlbase = SimplePie_Misc::absolutize_url($xmlbase, $this->feed_xmlbase);
5180                         }
5181                 }
5182                 else if (!empty($this->item_xmlbase))
5183                 {
5184                         $xmlbase = $this->item_xmlbase;
5185                 }
5186                 else
5187                 {
5188                         $xmlbase = $this->feed_xmlbase;
5189                 }
5190                 
5191                 if ($raw_url)
5192                 {
5193                         return SimplePie_Misc::absolutize_url($data, $xmlbase);
5194                 }
5195                 else
5196                 {
5197                         $attributes = array(
5198                                 'background',
5199                                 'href',
5200                                 'src',
5201                                 'longdesc',
5202                                 'usemap',
5203                                 'codebase',
5204                                 'data',
5205                                 'classid',
5206                                 'cite',
5207                                 'action',
5208                                 'profile',
5209                                 'for'
5210                         );
5211                         foreach ($attributes as $attribute)
5212                         {
5213                                 if (preg_match("/$attribute='(.*)'/siU", $data[0], $attrib) || preg_match("/$attribute=\"(.*)\"/siU", $data[0], $attrib) || preg_match("/$attribute=(.*)[ |\/|>]/siU", $data[0], $attrib))
5214                                 {
5215                                         $new_tag = str_replace($attrib[1], SimplePie_Misc::absolutize_url($attrib[1], $xmlbase), $attrib[0]);
5216                                         $data[0] = str_replace($attrib[0], $new_tag, $data[0]);
5217                                 }
5218                         }
5219                         return $data[0];
5220                 }
5221         }
5222         
5223         function entities_decode($data)
5224         {
5225                 return preg_replace_callback('/&(#)?(x)?([0-9a-z]+);/mi', array(&$this, 'do_entites_decode'), $data);
5226         }
5227         
5228         function do_entites_decode($data)
5229         {
5230                 if (isset($this->cached_entities[$data[0]]))
5231                 {
5232                         return $this->cached_entities[$data[0]];
5233                 }
5234                 else
5235                 {
5236                         $return = SimplePie_Misc::change_encoding(html_entity_decode($data[0], ENT_QUOTES), 'ISO-8859-1', $this->input_encoding);
5237                         if ($return == $data[0])
5238                         {
5239                                 $return = SimplePie_Misc::change_encoding(preg_replace_callback('/&#([x]?[0-9a-f]+);/mi', array(&$this, 'replace_num_entity'), $data[0]), 'UTF-8', $this->input_encoding);
5240                         }
5241                         $this->cached_entities[$data[0]] = $return;
5242                         return $return;
5243                 }
5244         }
5245         
5246         function convert_entities($data)
5247         {
5248                 return preg_replace_callback('/&#(x)?([0-9a-z]+);/mi', array(&$this, 'do_convert_entities'), $data);
5249         }
5250         
5251         function do_convert_entities($data)
5252         {
5253                 if (isset($this->cache_convert_entities[$data[0]]))
5254                 {
5255                         return $this->cache_convert_entities[$data[0]];
5256                 }
5257                 else if (isset($this->cached_entities[$data[0]]))
5258                 {
5259                         $return = htmlentities($this->cached_entities[$data[0]], ENT_QUOTES, 'UTF-8');
5260                 }
5261                 else
5262                 {
5263                         $return = htmlentities(preg_replace_callback('/&#([x]?[0-9a-f]+);/mi', array(&$this, 'replace_num_entity'), $data[0]), ENT_QUOTES, 'UTF-8');
5264                 }
5265                 $this->cache_convert_entities[$data[0]] = $return;
5266                 return $return;
5267         }
5268
5269         /*
5270          * Escape numeric entities
5271          * From a PHP Manual note (on html_entity_decode())
5272          * Copyright (c) 2005 by "php dot net at c dash ovidiu dot tk", 
5273          * "emilianomartinezluque at yahoo dot com" and "hurricane at cyberworldz dot org".
5274          *
5275          * This material may be distributed only subject to the terms and conditions set forth in 
5276          * the Open Publication License, v1.0 or later (the latest version is presently available at 
5277          * http://www.opencontent.org/openpub/).
5278          */
5279         function replace_num_entity($ord)
5280         {
5281                 $ord = $ord[1];
5282                 if (preg_match('/^x([0-9a-f]+)$/i', $ord, $match))
5283                 {
5284                         $ord = hexdec($match[1]);
5285                 }
5286                 else
5287                 {
5288                         $ord = intval($ord);
5289                 }
5290                 
5291                 $no_bytes = 0;
5292                 $byte = array();
5293                 if ($ord < 128)
5294                 {
5295                         return chr($ord);
5296                 }
5297                 if ($ord < 2048)
5298                 {
5299                         $no_bytes = 2;
5300                 }
5301                 else if ($ord < 65536)
5302                 {
5303                         $no_bytes = 3;
5304                 }
5305                 else if ($ord < 1114112)
5306                 {
5307                         $no_bytes = 4;
5308                 }
5309                 else
5310                 {
5311                         return;
5312                 }
5313                 switch ($no_bytes)
5314                 {
5315                         case 2:
5316                                 $prefix = array(31, 192);
5317                                 break;
5318                                 
5319                         case 3:
5320                                 $prefix = array(15, 224);
5321                                 break;
5322                                 
5323                         case 4:
5324                                 $prefix = array(7, 240);
5325                                 break;
5326                 }
5327                 
5328                 for ($i = 0; $i < $no_bytes; $i++)
5329                 {
5330                         $byte[$no_bytes-$i-1] = (($ord & (63 * pow(2,6*$i))) / pow(2,6*$i)) & 63 | 128;
5331                 }
5332                 $byte[0] = ($byte[0] & $prefix[0]) | $prefix[1];
5333                 
5334                 $ret = '';
5335                 for ($i = 0; $i < $no_bytes; $i++)
5336                 {
5337                         $ret .= chr($byte[$i]);
5338                 }
5339                 return $ret;
5340         }
5341         
5342         function parse_date($date)
5343         {
5344                 $military_timezone = array('A' => '-0100', 'B' => '-0200', 'C' => '-0300', 'D' => '-0400', 'E' => '-0500', 'F' => '-0600', 'G' => '-0700', 'H' => '-0800', 'I' => '-0900', 'K' => '-1000', 'L' => '-1100', 'M' => '-1200', 'N' => '+0100', 'O' => '+0200', 'P' => '+0300', 'Q' => '+0400', 'R' => '+0500', 'S' => '+0600', 'T' => '+0700', 'U' => '+0800', 'V' => '+0900', 'W' => '+1000', 'X' => '+1100', 'Y' => '+1200', 'Z' => '-0000');
5345                 $north_american_timezone = array('GMT' => '-0000', 'EST' => '-0500', 'EDT' => '-0400', 'CST' => '-0600', 'CDT' => '-0500', 'MST' => '-0700', 'MDT' => '-0600', 'PST' => '-0800', 'PDT' => '-0700');
5346                 if (preg_match('/([0-9]{2,4})-?([0-9]{2})-?([0-9]{2})T([0-9]{2}):?([0-9]{2})(:?([0-9]{2}(\.[0-9]*)?))?(UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[a-z]|(\\+|-)[0-9]{4}|(\\+|-)[0-9]{2}:[0-9]{2})?/i', $date, $matches))
5347                 {
5348                         if (!isset($matches[7]))
5349                         {
5350                                 $matches[7] = '';
5351                         }
5352                         if (!isset($matches[9]))
5353                         {
5354                                 $matches[9] = '';
5355                         }
5356                         $matches[7] = str_pad(round($matches[7]), 2, '0', STR_PAD_LEFT);
5357                         switch (strlen($matches[9]))
5358                         {
5359                                 case 0:
5360                                         $timezone = '';
5361                                         break;
5362                                         
5363                                 case 1:
5364                                         $timezone = $military_timezone[strtoupper($matches[9])];
5365                                         break;
5366                                 
5367                                 case 2:
5368                                         $timezone = '-0000';
5369                                         break;
5370                                 
5371                                 case 3:
5372                                         $timezone = $north_american_timezone[strtoupper($matches[9])];
5373                                         break;
5374                                 
5375                                 case 5:
5376                                         $timezone = $matches[9];
5377                                         break;
5378                                 
5379                                 case 6:
5380                                         $timezone = substr_replace($matches[9], '', 3, 1);
5381                                         break;
5382                         }
5383                         $date = strtotime("$matches[1]-$matches[2]-$matches[3] $matches[4]:$matches[5]:$matches[7] $timezone");
5384                 }
5385                 else if (preg_match('/([0-9]{1,2})\s*(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s*([0-9]{2}|[0-9]{4})\s*([0-9]{2}):([0-9]{2})(:([0-9]{2}(\.[0-9]*)?))?\s*(UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[a-z]|(\\+|-)[0-9]{4}|(\\+|-)[0-9]{2}:[0-9]{2})?/i', $date, $matches))
5386                 {
5387                         $three_month = array('Jan' => 1, 'Feb' => 2, 'Mar' => 3, 'Apr' => 4, 'May' => 5, 'Jun' => 6, 'Jul' => 7, 'Aug' => 8, 'Sep' => 9, 'Oct' => 10, 'Nov' => 11, 'Dec' => 12);
5388                         $month = $three_month[$matches[2]];
5389                         if (strlen($matches[3]) == 2)
5390                         {
5391                                 $year = ($matches[3] < 70) ? "20$matches[3]" : "19$matches[3]";
5392                         }
5393                         else
5394                         {
5395                                 $year = $matches[3];
5396                         }
5397                         if (!isset($matches[7]))
5398                         {
5399                                 $matches[7] = '';
5400                         }
5401                         if (!isset($matches[9]))
5402                         {
5403                                 $matches[9] = '';
5404                         }
5405                         $second = str_pad(round($matches[7]), 2, '0', STR_PAD_LEFT);
5406                         switch (strlen($matches[9]))
5407                         {
5408                                 case 0:
5409                                         $timezone = '';
5410                                         break;
5411                                         
5412                                 case 1:
5413                                         $timezone = $military_timezone[strtoupper($matches[9])];
5414                                         break;
5415                                 
5416                                 case 2:
5417                                         $timezone = '-0000';
5418                                         break;
5419                                 
5420                                 case 3:
5421                                         $timezone = $north_american_timezone[strtoupper($matches[9])];
5422                                         break;
5423                                 
5424                                 case 5:
5425                                         $timezone = $matches[9];
5426                                         break;
5427                                 
5428                                 case 6:
5429                                         $timezone = substr_replace($matches[9], '', 3, 1);
5430                                         break;
5431                         }
5432                         $date = strtotime("$year-$month-$matches[1] $matches[4]:$matches[5]:$second $timezone");
5433                 }
5434                 else
5435                 {
5436                         $date = strtotime($date);
5437                 }
5438                 if ($date !== false && $date !== -1)
5439                 {
5440                         return $date;
5441                 }
5442                 else
5443                 {
5444                         return false;
5445                 }
5446         }
5447 }
5448
5449 ?>