]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/class-simplepie.php
WordPress 3.4-scripts
[autoinstalls/wordpress.git] / wp-includes / class-simplepie.php
1 <?php
2 if ( ! class_exists( 'SimplePie' ) ) :
3 /**
4  * SimplePie
5  *
6  * A PHP-Based RSS and Atom Feed Framework.
7  * Takes the hard work out of managing a complete RSS/Atom solution.
8  *
9  * Copyright (c) 2004-2011, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without modification, are
13  * permitted provided that the following conditions are met:
14  *
15  *      * Redistributions of source code must retain the above copyright notice, this list of
16  *        conditions and the following disclaimer.
17  *
18  *      * Redistributions in binary form must reproduce the above copyright notice, this list
19  *        of conditions and the following disclaimer in the documentation and/or other materials
20  *        provided with the distribution.
21  *
22  *      * Neither the name of the SimplePie Team nor the names of its contributors may be used
23  *        to endorse or promote products derived from this software without specific prior
24  *        written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
27  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
29  * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * @package SimplePie
37  * @version 1.2.1
38  * @copyright 2004-2011 Ryan Parman, Geoffrey Sneddon, Ryan McCue
39  * @author Ryan Parman
40  * @author Geoffrey Sneddon
41  * @author Ryan McCue
42  * @link http://simplepie.org/ SimplePie
43  * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
44  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
45  * @todo phpDoc comments
46  */
47
48 /**
49  * SimplePie Name
50  */
51 define('SIMPLEPIE_NAME', 'SimplePie');
52
53 /**
54  * SimplePie Version
55  */
56 define('SIMPLEPIE_VERSION', '1.2.1');
57
58 /**
59  * SimplePie Build
60  */
61 define('SIMPLEPIE_BUILD', '20111015034325');
62
63 /**
64  * SimplePie Website URL
65  */
66 define('SIMPLEPIE_URL', 'http://simplepie.org');
67
68 /**
69  * SimplePie Useragent
70  * @see SimplePie::set_useragent()
71  */
72 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
73
74 /**
75  * SimplePie Linkback
76  */
77 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
78
79 /**
80  * No Autodiscovery
81  * @see SimplePie::set_autodiscovery_level()
82  */
83 define('SIMPLEPIE_LOCATOR_NONE', 0);
84
85 /**
86  * Feed Link Element Autodiscovery
87  * @see SimplePie::set_autodiscovery_level()
88  */
89 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
90
91 /**
92  * Local Feed Extension Autodiscovery
93  * @see SimplePie::set_autodiscovery_level()
94  */
95 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
96
97 /**
98  * Local Feed Body Autodiscovery
99  * @see SimplePie::set_autodiscovery_level()
100  */
101 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
102
103 /**
104  * Remote Feed Extension Autodiscovery
105  * @see SimplePie::set_autodiscovery_level()
106  */
107 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
108
109 /**
110  * Remote Feed Body Autodiscovery
111  * @see SimplePie::set_autodiscovery_level()
112  */
113 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
114
115 /**
116  * All Feed Autodiscovery
117  * @see SimplePie::set_autodiscovery_level()
118  */
119 define('SIMPLEPIE_LOCATOR_ALL', 31);
120
121 /**
122  * No known feed type
123  */
124 define('SIMPLEPIE_TYPE_NONE', 0);
125
126 /**
127  * RSS 0.90
128  */
129 define('SIMPLEPIE_TYPE_RSS_090', 1);
130
131 /**
132  * RSS 0.91 (Netscape)
133  */
134 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
135
136 /**
137  * RSS 0.91 (Userland)
138  */
139 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
140
141 /**
142  * RSS 0.91 (both Netscape and Userland)
143  */
144 define('SIMPLEPIE_TYPE_RSS_091', 6);
145
146 /**
147  * RSS 0.92
148  */
149 define('SIMPLEPIE_TYPE_RSS_092', 8);
150
151 /**
152  * RSS 0.93
153  */
154 define('SIMPLEPIE_TYPE_RSS_093', 16);
155
156 /**
157  * RSS 0.94
158  */
159 define('SIMPLEPIE_TYPE_RSS_094', 32);
160
161 /**
162  * RSS 1.0
163  */
164 define('SIMPLEPIE_TYPE_RSS_10', 64);
165
166 /**
167  * RSS 2.0
168  */
169 define('SIMPLEPIE_TYPE_RSS_20', 128);
170
171 /**
172  * RDF-based RSS
173  */
174 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
175
176 /**
177  * Non-RDF-based RSS (truly intended as syndication format)
178  */
179 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
180
181 /**
182  * All RSS
183  */
184 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
185
186 /**
187  * Atom 0.3
188  */
189 define('SIMPLEPIE_TYPE_ATOM_03', 256);
190
191 /**
192  * Atom 1.0
193  */
194 define('SIMPLEPIE_TYPE_ATOM_10', 512);
195
196 /**
197  * All Atom
198  */
199 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
200
201 /**
202  * All feed types
203  */
204 define('SIMPLEPIE_TYPE_ALL', 1023);
205
206 /**
207  * No construct
208  */
209 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
210
211 /**
212  * Text construct
213  */
214 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
215
216 /**
217  * HTML construct
218  */
219 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
220
221 /**
222  * XHTML construct
223  */
224 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
225
226 /**
227  * base64-encoded construct
228  */
229 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
230
231 /**
232  * IRI construct
233  */
234 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
235
236 /**
237  * A construct that might be HTML
238  */
239 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
240
241 /**
242  * All constructs
243  */
244 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
245
246 /**
247  * Don't change case
248  */
249 define('SIMPLEPIE_SAME_CASE', 1);
250
251 /**
252  * Change to lowercase
253  */
254 define('SIMPLEPIE_LOWERCASE', 2);
255
256 /**
257  * Change to uppercase
258  */
259 define('SIMPLEPIE_UPPERCASE', 4);
260
261 /**
262  * PCRE for HTML attributes
263  */
264 define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
265
266 /**
267  * PCRE for XML attributes
268  */
269 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
270
271 /**
272  * XML Namespace
273  */
274 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
275
276 /**
277  * Atom 1.0 Namespace
278  */
279 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
280
281 /**
282  * Atom 0.3 Namespace
283  */
284 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
285
286 /**
287  * RDF Namespace
288  */
289 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
290
291 /**
292  * RSS 0.90 Namespace
293  */
294 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
295
296 /**
297  * RSS 1.0 Namespace
298  */
299 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
300
301 /**
302  * RSS 1.0 Content Module Namespace
303  */
304 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
305
306 /**
307  * RSS 2.0 Namespace
308  * (Stupid, I know, but I'm certain it will confuse people less with support.)
309  */
310 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
311
312 /**
313  * DC 1.0 Namespace
314  */
315 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
316
317 /**
318  * DC 1.1 Namespace
319  */
320 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
321
322 /**
323  * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
324  */
325 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
326
327 /**
328  * GeoRSS Namespace
329  */
330 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
331
332 /**
333  * Media RSS Namespace
334  */
335 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
336
337 /**
338  * Wrong Media RSS Namespace
339  */
340 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
341
342 /**
343  * iTunes RSS Namespace
344  */
345 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
346
347 /**
348  * XHTML Namespace
349  */
350 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
351
352 /**
353  * IANA Link Relations Registry
354  */
355 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
356
357 /**
358  * Whether we're running on PHP5
359  */
360 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
361
362 /**
363  * No file source
364  */
365 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
366
367 /**
368  * Remote file source
369  */
370 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
371
372 /**
373  * Local file source
374  */
375 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
376
377 /**
378  * fsockopen() file source
379  */
380 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
381
382 /**
383  * cURL file source
384  */
385 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
386
387 /**
388  * file_get_contents() file source
389  */
390 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
391
392 /**
393  * SimplePie
394  *
395  * @package SimplePie
396  */
397 class SimplePie
398 {
399         /**
400          * @var array Raw data
401          * @access private
402          */
403         var $data = array();
404
405         /**
406          * @var mixed Error string
407          * @access private
408          */
409         var $error;
410
411         /**
412          * @var object Instance of SimplePie_Sanitize (or other class)
413          * @see SimplePie::set_sanitize_class()
414          * @access private
415          */
416         var $sanitize;
417
418         /**
419          * @var string SimplePie Useragent
420          * @see SimplePie::set_useragent()
421          * @access private
422          */
423         var $useragent = SIMPLEPIE_USERAGENT;
424
425         /**
426          * @var string Feed URL
427          * @see SimplePie::set_feed_url()
428          * @access private
429          */
430         var $feed_url;
431
432         /**
433          * @var object Instance of SimplePie_File to use as a feed
434          * @see SimplePie::set_file()
435          * @access private
436          */
437         var $file;
438
439         /**
440          * @var string Raw feed data
441          * @see SimplePie::set_raw_data()
442          * @access private
443          */
444         var $raw_data;
445
446         /**
447          * @var int Timeout for fetching remote files
448          * @see SimplePie::set_timeout()
449          * @access private
450          */
451         var $timeout = 10;
452
453         /**
454          * @var bool Forces fsockopen() to be used for remote files instead
455          * of cURL, even if a new enough version is installed
456          * @see SimplePie::force_fsockopen()
457          * @access private
458          */
459         var $force_fsockopen = false;
460
461         /**
462          * @var bool Force the given data/URL to be treated as a feed no matter what
463          * it appears like
464          * @see SimplePie::force_feed()
465          * @access private
466          */
467         var $force_feed = false;
468
469         /**
470          * @var bool Enable/Disable XML dump
471          * @see SimplePie::enable_xml_dump()
472          * @access private
473          */
474         var $xml_dump = false;
475
476         /**
477          * @var bool Enable/Disable Caching
478          * @see SimplePie::enable_cache()
479          * @access private
480          */
481         var $cache = true;
482
483         /**
484          * @var int Cache duration (in seconds)
485          * @see SimplePie::set_cache_duration()
486          * @access private
487          */
488         var $cache_duration = 3600;
489
490         /**
491          * @var int Auto-discovery cache duration (in seconds)
492          * @see SimplePie::set_autodiscovery_cache_duration()
493          * @access private
494          */
495         var $autodiscovery_cache_duration = 604800; // 7 Days.
496
497         /**
498          * @var string Cache location (relative to executing script)
499          * @see SimplePie::set_cache_location()
500          * @access private
501          */
502         var $cache_location = './cache';
503
504         /**
505          * @var string Function that creates the cache filename
506          * @see SimplePie::set_cache_name_function()
507          * @access private
508          */
509         var $cache_name_function = 'md5';
510
511         /**
512          * @var bool Reorder feed by date descending
513          * @see SimplePie::enable_order_by_date()
514          * @access private
515          */
516         var $order_by_date = true;
517
518         /**
519          * @var mixed Force input encoding to be set to the follow value
520          * (false, or anything type-cast to false, disables this feature)
521          * @see SimplePie::set_input_encoding()
522          * @access private
523          */
524         var $input_encoding = false;
525
526         /**
527          * @var int Feed Autodiscovery Level
528          * @see SimplePie::set_autodiscovery_level()
529          * @access private
530          */
531         var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
532
533         /**
534          * @var string Class used for caching feeds
535          * @see SimplePie::set_cache_class()
536          * @access private
537          */
538         var $cache_class = 'SimplePie_Cache';
539
540         /**
541          * @var string Class used for locating feeds
542          * @see SimplePie::set_locator_class()
543          * @access private
544          */
545         var $locator_class = 'SimplePie_Locator';
546
547         /**
548          * @var string Class used for parsing feeds
549          * @see SimplePie::set_parser_class()
550          * @access private
551          */
552         var $parser_class = 'SimplePie_Parser';
553
554         /**
555          * @var string Class used for fetching feeds
556          * @see SimplePie::set_file_class()
557          * @access private
558          */
559         var $file_class = 'SimplePie_File';
560
561         /**
562          * @var string Class used for items
563          * @see SimplePie::set_item_class()
564          * @access private
565          */
566         var $item_class = 'SimplePie_Item';
567
568         /**
569          * @var string Class used for authors
570          * @see SimplePie::set_author_class()
571          * @access private
572          */
573         var $author_class = 'SimplePie_Author';
574
575         /**
576          * @var string Class used for categories
577          * @see SimplePie::set_category_class()
578          * @access private
579          */
580         var $category_class = 'SimplePie_Category';
581
582         /**
583          * @var string Class used for enclosures
584          * @see SimplePie::set_enclosures_class()
585          * @access private
586          */
587         var $enclosure_class = 'SimplePie_Enclosure';
588
589         /**
590          * @var string Class used for Media RSS <media:text> captions
591          * @see SimplePie::set_caption_class()
592          * @access private
593          */
594         var $caption_class = 'SimplePie_Caption';
595
596         /**
597          * @var string Class used for Media RSS <media:copyright>
598          * @see SimplePie::set_copyright_class()
599          * @access private
600          */
601         var $copyright_class = 'SimplePie_Copyright';
602
603         /**
604          * @var string Class used for Media RSS <media:credit>
605          * @see SimplePie::set_credit_class()
606          * @access private
607          */
608         var $credit_class = 'SimplePie_Credit';
609
610         /**
611          * @var string Class used for Media RSS <media:rating>
612          * @see SimplePie::set_rating_class()
613          * @access private
614          */
615         var $rating_class = 'SimplePie_Rating';
616
617         /**
618          * @var string Class used for Media RSS <media:restriction>
619          * @see SimplePie::set_restriction_class()
620          * @access private
621          */
622         var $restriction_class = 'SimplePie_Restriction';
623
624         /**
625          * @var string Class used for content-type sniffing
626          * @see SimplePie::set_content_type_sniffer_class()
627          * @access private
628          */
629         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
630
631         /**
632          * @var string Class used for item sources.
633          * @see SimplePie::set_source_class()
634          * @access private
635          */
636         var $source_class = 'SimplePie_Source';
637
638         /**
639          * @var mixed Set javascript query string parameter (false, or
640          * anything type-cast to false, disables this feature)
641          * @see SimplePie::set_javascript()
642          * @access private
643          */
644         var $javascript = 'js';
645
646         /**
647          * @var int Maximum number of feeds to check with autodiscovery
648          * @see SimplePie::set_max_checked_feeds()
649          * @access private
650          */
651         var $max_checked_feeds = 10;
652
653         /**
654          * @var array All the feeds found during the autodiscovery process
655          * @see SimplePie::get_all_discovered_feeds()
656          * @access private
657          */
658         var $all_discovered_feeds = array();
659
660         /**
661          * @var string Web-accessible path to the handler_favicon.php file.
662          * @see SimplePie::set_favicon_handler()
663          * @access private
664          */
665         var $favicon_handler = '';
666
667         /**
668          * @var string Web-accessible path to the handler_image.php file.
669          * @see SimplePie::set_image_handler()
670          * @access private
671          */
672         var $image_handler = '';
673
674         /**
675          * @var array Stores the URLs when multiple feeds are being initialized.
676          * @see SimplePie::set_feed_url()
677          * @access private
678          */
679         var $multifeed_url = array();
680
681         /**
682          * @var array Stores SimplePie objects when multiple feeds initialized.
683          * @access private
684          */
685         var $multifeed_objects = array();
686
687         /**
688          * @var array Stores the get_object_vars() array for use with multifeeds.
689          * @see SimplePie::set_feed_url()
690          * @access private
691          */
692         var $config_settings = null;
693
694         /**
695          * @var integer Stores the number of items to return per-feed with multifeeds.
696          * @see SimplePie::set_item_limit()
697          * @access private
698          */
699         var $item_limit = 0;
700
701         /**
702          * @var array Stores the default attributes to be stripped by strip_attributes().
703          * @see SimplePie::strip_attributes()
704          * @access private
705          */
706         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
707
708         /**
709          * @var array Stores the default tags to be stripped by strip_htmltags().
710          * @see SimplePie::strip_htmltags()
711          * @access private
712          */
713         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
714
715         /**
716          * The SimplePie class contains feed level data and options
717          *
718          * There are two ways that you can create a new SimplePie object. The first
719          * is by passing a feed URL as a parameter to the SimplePie constructor
720          * (as well as optionally setting the cache location and cache expiry). This
721          * will initialise the whole feed with all of the default settings, and you
722          * can begin accessing methods and properties immediately.
723          *
724          * The second way is to create the SimplePie object with no parameters
725          * at all. This will enable you to set configuration options. After setting
726          * them, you must initialise the feed using $feed->init(). At that point the
727          * object's methods and properties will be available to you. This format is
728          * what is used throughout this documentation.
729          *
730          * @access public
731          * @since 1.0 Preview Release
732          * @param string $feed_url This is the URL you want to parse.
733          * @param string $cache_location This is where you want the cache to be stored.
734          * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
735          */
736         function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
737         {
738                 // Other objects, instances created here so we can set options on them
739                 $this->sanitize =& new SimplePie_Sanitize;
740
741                 // Set options if they're passed to the constructor
742                 if ($cache_location !== null)
743                 {
744                         $this->set_cache_location($cache_location);
745                 }
746
747                 if ($cache_duration !== null)
748                 {
749                         $this->set_cache_duration($cache_duration);
750                 }
751
752                 // Only init the script if we're passed a feed URL
753                 if ($feed_url !== null)
754                 {
755                         $this->set_feed_url($feed_url);
756                         $this->init();
757                 }
758         }
759
760         /**
761          * Used for converting object to a string
762          */
763         function __toString()
764         {
765                 return md5(serialize($this->data));
766         }
767
768         /**
769          * Remove items that link back to this before destroying this object
770          */
771         function __destruct()
772         {
773                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
774                 {
775                         if (!empty($this->data['items']))
776                         {
777                                 foreach ($this->data['items'] as $item)
778                                 {
779                                         $item->__destruct();
780                                 }
781                                 unset($item, $this->data['items']);
782                         }
783                         if (!empty($this->data['ordered_items']))
784                         {
785                                 foreach ($this->data['ordered_items'] as $item)
786                                 {
787                                         $item->__destruct();
788                                 }
789                                 unset($item, $this->data['ordered_items']);
790                         }
791                 }
792         }
793
794         /**
795          * Force the given data/URL to be treated as a feed no matter what it
796          * appears like
797          *
798          * @access public
799          * @since 1.1
800          * @param bool $enable Force the given data/URL to be treated as a feed
801          */
802         function force_feed($enable = false)
803         {
804                 $this->force_feed = (bool) $enable;
805         }
806
807         /**
808          * This is the URL of the feed you want to parse.
809          *
810          * This allows you to enter the URL of the feed you want to parse, or the
811          * website you want to try to use auto-discovery on. This takes priority
812          * over any set raw data.
813          *
814          * You can set multiple feeds to mash together by passing an array instead
815          * of a string for the $url. Remember that with each additional feed comes
816          * additional processing and resources.
817          *
818          * @access public
819          * @since 1.0 Preview Release
820          * @param mixed $url This is the URL (or array of URLs) that you want to parse.
821          * @see SimplePie::set_raw_data()
822          */
823         function set_feed_url($url)
824         {
825                 if (is_array($url))
826                 {
827                         $this->multifeed_url = array();
828                         foreach ($url as $value)
829                         {
830                                 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
831                         }
832                 }
833                 else
834                 {
835                         $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
836                 }
837         }
838
839         /**
840          * Provides an instance of SimplePie_File to use as a feed
841          *
842          * @access public
843          * @param object &$file Instance of SimplePie_File (or subclass)
844          * @return bool True on success, false on failure
845          */
846         function set_file(&$file)
847         {
848                 if (is_a($file, 'SimplePie_File'))
849                 {
850                         $this->feed_url = $file->url;
851                         $this->file =& $file;
852                         return true;
853                 }
854                 return false;
855         }
856
857         /**
858          * Allows you to use a string of RSS/Atom data instead of a remote feed.
859          *
860          * If you have a feed available as a string in PHP, you can tell SimplePie
861          * to parse that data string instead of a remote feed. Any set feed URL
862          * takes precedence.
863          *
864          * @access public
865          * @since 1.0 Beta 3
866          * @param string $data RSS or Atom data as a string.
867          * @see SimplePie::set_feed_url()
868          */
869         function set_raw_data($data)
870         {
871                 $this->raw_data = $data;
872         }
873
874         /**
875          * Allows you to override the default timeout for fetching remote feeds.
876          *
877          * This allows you to change the maximum time the feed's server to respond
878          * and send the feed back.
879          *
880          * @access public
881          * @since 1.0 Beta 3
882          * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
883          */
884         function set_timeout($timeout = 10)
885         {
886                 $this->timeout = (int) $timeout;
887         }
888
889         /**
890          * Forces SimplePie to use fsockopen() instead of the preferred cURL
891          * functions.
892          *
893          * @access public
894          * @since 1.0 Beta 3
895          * @param bool $enable Force fsockopen() to be used
896          */
897         function force_fsockopen($enable = false)
898         {
899                 $this->force_fsockopen = (bool) $enable;
900         }
901
902         /**
903          * Outputs the raw XML content of the feed, after it has gone through
904          * SimplePie's filters.
905          *
906          * Used only for debugging, this function will output the XML content as
907          * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
908          * before trying to parse it. Many parts of the feed are re-written in
909          * memory, and in the end, you have a parsable feed. XML dump shows you the
910          * actual XML that SimplePie tries to parse, which may or may not be very
911          * different from the original feed.
912          *
913          * @access public
914          * @since 1.0 Preview Release
915          * @param bool $enable Enable XML dump
916          */
917         function enable_xml_dump($enable = false)
918         {
919                 $this->xml_dump = (bool) $enable;
920         }
921
922         /**
923          * Enables/disables caching in SimplePie.
924          *
925          * This option allows you to disable caching all-together in SimplePie.
926          * However, disabling the cache can lead to longer load times.
927          *
928          * @access public
929          * @since 1.0 Preview Release
930          * @param bool $enable Enable caching
931          */
932         function enable_cache($enable = true)
933         {
934                 $this->cache = (bool) $enable;
935         }
936
937         /**
938          * Set the length of time (in seconds) that the contents of a feed
939          * will be cached.
940          *
941          * @access public
942          * @param int $seconds The feed content cache duration.
943          */
944         function set_cache_duration($seconds = 3600)
945         {
946                 $this->cache_duration = (int) $seconds;
947         }
948
949         /**
950          * Set the length of time (in seconds) that the autodiscovered feed
951          * URL will be cached.
952          *
953          * @access public
954          * @param int $seconds The autodiscovered feed URL cache duration.
955          */
956         function set_autodiscovery_cache_duration($seconds = 604800)
957         {
958                 $this->autodiscovery_cache_duration = (int) $seconds;
959         }
960
961         /**
962          * Set the file system location where the cached files should be stored.
963          *
964          * @access public
965          * @param string $location The file system location.
966          */
967         function set_cache_location($location = './cache')
968         {
969                 $this->cache_location = (string) $location;
970         }
971
972         /**
973          * Determines whether feed items should be sorted into reverse chronological order.
974          *
975          * @access public
976          * @param bool $enable Sort as reverse chronological order.
977          */
978         function enable_order_by_date($enable = true)
979         {
980                 $this->order_by_date = (bool) $enable;
981         }
982
983         /**
984          * Allows you to override the character encoding reported by the feed.
985          *
986          * @access public
987          * @param string $encoding Character encoding.
988          */
989         function set_input_encoding($encoding = false)
990         {
991                 if ($encoding)
992                 {
993                         $this->input_encoding = (string) $encoding;
994                 }
995                 else
996                 {
997                         $this->input_encoding = false;
998                 }
999         }
1000
1001         /**
1002          * Set how much feed autodiscovery to do
1003          *
1004          * @access public
1005          * @see SIMPLEPIE_LOCATOR_NONE
1006          * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1007          * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1008          * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1009          * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1010          * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1011          * @see SIMPLEPIE_LOCATOR_ALL
1012          * @param int $level Feed Autodiscovery Level (level can be a
1013          * combination of the above constants, see bitwise OR operator)
1014          */
1015         function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1016         {
1017                 $this->autodiscovery = (int) $level;
1018         }
1019
1020         /**
1021          * Allows you to change which class SimplePie uses for caching.
1022          * Useful when you are overloading or extending SimplePie's default classes.
1023          *
1024          * @access public
1025          * @param string $class Name of custom class.
1026          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1027          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1028          */
1029         function set_cache_class($class = 'SimplePie_Cache')
1030         {
1031                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1032                 {
1033                         $this->cache_class = $class;
1034                         return true;
1035                 }
1036                 return false;
1037         }
1038
1039         /**
1040          * Allows you to change which class SimplePie uses for auto-discovery.
1041          * Useful when you are overloading or extending SimplePie's default classes.
1042          *
1043          * @access public
1044          * @param string $class Name of custom class.
1045          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1046          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1047          */
1048         function set_locator_class($class = 'SimplePie_Locator')
1049         {
1050                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1051                 {
1052                         $this->locator_class = $class;
1053                         return true;
1054                 }
1055                 return false;
1056         }
1057
1058         /**
1059          * Allows you to change which class SimplePie uses for XML parsing.
1060          * Useful when you are overloading or extending SimplePie's default classes.
1061          *
1062          * @access public
1063          * @param string $class Name of custom class.
1064          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1065          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1066          */
1067         function set_parser_class($class = 'SimplePie_Parser')
1068         {
1069                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1070                 {
1071                         $this->parser_class = $class;
1072                         return true;
1073                 }
1074                 return false;
1075         }
1076
1077         /**
1078          * Allows you to change which class SimplePie uses for remote file fetching.
1079          * Useful when you are overloading or extending SimplePie's default classes.
1080          *
1081          * @access public
1082          * @param string $class Name of custom class.
1083          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1084          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1085          */
1086         function set_file_class($class = 'SimplePie_File')
1087         {
1088                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1089                 {
1090                         $this->file_class = $class;
1091                         return true;
1092                 }
1093                 return false;
1094         }
1095
1096         /**
1097          * Allows you to change which class SimplePie uses for data sanitization.
1098          * Useful when you are overloading or extending SimplePie's default classes.
1099          *
1100          * @access public
1101          * @param string $class Name of custom class.
1102          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1103          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1104          */
1105         function set_sanitize_class($class = 'SimplePie_Sanitize')
1106         {
1107                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1108                 {
1109                         $this->sanitize =& new $class;
1110                         return true;
1111                 }
1112                 return false;
1113         }
1114
1115         /**
1116          * Allows you to change which class SimplePie uses for handling feed items.
1117          * Useful when you are overloading or extending SimplePie's default classes.
1118          *
1119          * @access public
1120          * @param string $class Name of custom class.
1121          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1122          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1123          */
1124         function set_item_class($class = 'SimplePie_Item')
1125         {
1126                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1127                 {
1128                         $this->item_class = $class;
1129                         return true;
1130                 }
1131                 return false;
1132         }
1133
1134         /**
1135          * Allows you to change which class SimplePie uses for handling author data.
1136          * Useful when you are overloading or extending SimplePie's default classes.
1137          *
1138          * @access public
1139          * @param string $class Name of custom class.
1140          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1141          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1142          */
1143         function set_author_class($class = 'SimplePie_Author')
1144         {
1145                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1146                 {
1147                         $this->author_class = $class;
1148                         return true;
1149                 }
1150                 return false;
1151         }
1152
1153         /**
1154          * Allows you to change which class SimplePie uses for handling category data.
1155          * Useful when you are overloading or extending SimplePie's default classes.
1156          *
1157          * @access public
1158          * @param string $class Name of custom class.
1159          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1160          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1161          */
1162         function set_category_class($class = 'SimplePie_Category')
1163         {
1164                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1165                 {
1166                         $this->category_class = $class;
1167                         return true;
1168                 }
1169                 return false;
1170         }
1171
1172         /**
1173          * Allows you to change which class SimplePie uses for feed enclosures.
1174          * Useful when you are overloading or extending SimplePie's default classes.
1175          *
1176          * @access public
1177          * @param string $class Name of custom class.
1178          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1179          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1180          */
1181         function set_enclosure_class($class = 'SimplePie_Enclosure')
1182         {
1183                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1184                 {
1185                         $this->enclosure_class = $class;
1186                         return true;
1187                 }
1188                 return false;
1189         }
1190
1191         /**
1192          * Allows you to change which class SimplePie uses for <media:text> captions
1193          * Useful when you are overloading or extending SimplePie's default classes.
1194          *
1195          * @access public
1196          * @param string $class Name of custom class.
1197          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1198          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1199          */
1200         function set_caption_class($class = 'SimplePie_Caption')
1201         {
1202                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1203                 {
1204                         $this->caption_class = $class;
1205                         return true;
1206                 }
1207                 return false;
1208         }
1209
1210         /**
1211          * Allows you to change which class SimplePie uses for <media:copyright>
1212          * Useful when you are overloading or extending SimplePie's default classes.
1213          *
1214          * @access public
1215          * @param string $class Name of custom class.
1216          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1217          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1218          */
1219         function set_copyright_class($class = 'SimplePie_Copyright')
1220         {
1221                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1222                 {
1223                         $this->copyright_class = $class;
1224                         return true;
1225                 }
1226                 return false;
1227         }
1228
1229         /**
1230          * Allows you to change which class SimplePie uses for <media:credit>
1231          * Useful when you are overloading or extending SimplePie's default classes.
1232          *
1233          * @access public
1234          * @param string $class Name of custom class.
1235          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1236          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1237          */
1238         function set_credit_class($class = 'SimplePie_Credit')
1239         {
1240                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1241                 {
1242                         $this->credit_class = $class;
1243                         return true;
1244                 }
1245                 return false;
1246         }
1247
1248         /**
1249          * Allows you to change which class SimplePie uses for <media:rating>
1250          * Useful when you are overloading or extending SimplePie's default classes.
1251          *
1252          * @access public
1253          * @param string $class Name of custom class.
1254          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1255          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1256          */
1257         function set_rating_class($class = 'SimplePie_Rating')
1258         {
1259                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1260                 {
1261                         $this->rating_class = $class;
1262                         return true;
1263                 }
1264                 return false;
1265         }
1266
1267         /**
1268          * Allows you to change which class SimplePie uses for <media:restriction>
1269          * Useful when you are overloading or extending SimplePie's default classes.
1270          *
1271          * @access public
1272          * @param string $class Name of custom class.
1273          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1274          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1275          */
1276         function set_restriction_class($class = 'SimplePie_Restriction')
1277         {
1278                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1279                 {
1280                         $this->restriction_class = $class;
1281                         return true;
1282                 }
1283                 return false;
1284         }
1285
1286         /**
1287          * Allows you to change which class SimplePie uses for content-type sniffing.
1288          * Useful when you are overloading or extending SimplePie's default classes.
1289          *
1290          * @access public
1291          * @param string $class Name of custom class.
1292          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1293          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1294          */
1295         function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1296         {
1297                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1298                 {
1299                         $this->content_type_sniffer_class = $class;
1300                         return true;
1301                 }
1302                 return false;
1303         }
1304
1305         /**
1306          * Allows you to change which class SimplePie uses item sources.
1307          * Useful when you are overloading or extending SimplePie's default classes.
1308          *
1309          * @access public
1310          * @param string $class Name of custom class.
1311          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1312          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1313          */
1314         function set_source_class($class = 'SimplePie_Source')
1315         {
1316                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1317                 {
1318                         $this->source_class = $class;
1319                         return true;
1320                 }
1321                 return false;
1322         }
1323
1324         /**
1325          * Allows you to override the default user agent string.
1326          *
1327          * @access public
1328          * @param string $ua New user agent string.
1329          */
1330         function set_useragent($ua = SIMPLEPIE_USERAGENT)
1331         {
1332                 $this->useragent = (string) $ua;
1333         }
1334
1335         /**
1336          * Set callback function to create cache filename with
1337          *
1338          * @access public
1339          * @param mixed $function Callback function
1340          */
1341         function set_cache_name_function($function = 'md5')
1342         {
1343                 if (is_callable($function))
1344                 {
1345                         $this->cache_name_function = $function;
1346                 }
1347         }
1348
1349         /**
1350          * Set javascript query string parameter
1351          *
1352          * @access public
1353          * @param mixed $get Javascript query string parameter
1354          */
1355         function set_javascript($get = 'js')
1356         {
1357                 if ($get)
1358                 {
1359                         $this->javascript = (string) $get;
1360                 }
1361                 else
1362                 {
1363                         $this->javascript = false;
1364                 }
1365         }
1366
1367         /**
1368          * Set options to make SP as fast as possible.  Forgoes a
1369          * substantial amount of data sanitization in favor of speed.
1370          *
1371          * @access public
1372          * @param bool $set Whether to set them or not
1373          */
1374         function set_stupidly_fast($set = false)
1375         {
1376                 if ($set)
1377                 {
1378                         $this->enable_order_by_date(false);
1379                         $this->remove_div(false);
1380                         $this->strip_comments(false);
1381                         $this->strip_htmltags(false);
1382                         $this->strip_attributes(false);
1383                         $this->set_image_handler(false);
1384                 }
1385         }
1386
1387         /**
1388          * Set maximum number of feeds to check with autodiscovery
1389          *
1390          * @access public
1391          * @param int $max Maximum number of feeds to check
1392          */
1393         function set_max_checked_feeds($max = 10)
1394         {
1395                 $this->max_checked_feeds = (int) $max;
1396         }
1397
1398         function remove_div($enable = true)
1399         {
1400                 $this->sanitize->remove_div($enable);
1401         }
1402
1403         function strip_htmltags($tags = '', $encode = null)
1404         {
1405                 if ($tags === '')
1406                 {
1407                         $tags = $this->strip_htmltags;
1408                 }
1409                 $this->sanitize->strip_htmltags($tags);
1410                 if ($encode !== null)
1411                 {
1412                         $this->sanitize->encode_instead_of_strip($tags);
1413                 }
1414         }
1415
1416         function encode_instead_of_strip($enable = true)
1417         {
1418                 $this->sanitize->encode_instead_of_strip($enable);
1419         }
1420
1421         function strip_attributes($attribs = '')
1422         {
1423                 if ($attribs === '')
1424                 {
1425                         $attribs = $this->strip_attributes;
1426                 }
1427                 $this->sanitize->strip_attributes($attribs);
1428         }
1429
1430         function set_output_encoding($encoding = 'UTF-8')
1431         {
1432                 $this->sanitize->set_output_encoding($encoding);
1433         }
1434
1435         function strip_comments($strip = false)
1436         {
1437                 $this->sanitize->strip_comments($strip);
1438         }
1439
1440         /**
1441          * Set element/attribute key/value pairs of HTML attributes
1442          * containing URLs that need to be resolved relative to the feed
1443          *
1444          * @access public
1445          * @since 1.0
1446          * @param array $element_attribute Element/attribute key/value pairs
1447          */
1448         function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
1449         {
1450                 $this->sanitize->set_url_replacements($element_attribute);
1451         }
1452
1453         /**
1454          * Set the handler to enable the display of cached favicons.
1455          *
1456          * @access public
1457          * @param str $page Web-accessible path to the handler_favicon.php file.
1458          * @param str $qs The query string that the value should be passed to.
1459          */
1460         function set_favicon_handler($page = false, $qs = 'i')
1461         {
1462                 if ($page !== false)
1463                 {
1464                         $this->favicon_handler = $page . '?' . $qs . '=';
1465                 }
1466                 else
1467                 {
1468                         $this->favicon_handler = '';
1469                 }
1470         }
1471
1472         /**
1473          * Set the handler to enable the display of cached images.
1474          *
1475          * @access public
1476          * @param str $page Web-accessible path to the handler_image.php file.
1477          * @param str $qs The query string that the value should be passed to.
1478          */
1479         function set_image_handler($page = false, $qs = 'i')
1480         {
1481                 if ($page !== false)
1482                 {
1483                         $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1484                 }
1485                 else
1486                 {
1487                         $this->image_handler = '';
1488                 }
1489         }
1490
1491         /**
1492          * Set the limit for items returned per-feed with multifeeds.
1493          *
1494          * @access public
1495          * @param integer $limit The maximum number of items to return.
1496          */
1497         function set_item_limit($limit = 0)
1498         {
1499                 $this->item_limit = (int) $limit;
1500         }
1501
1502         function init()
1503         {
1504                 // Check absolute bare minimum requirements.
1505                 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1506                 {
1507                         return false;
1508                 }
1509                 // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
1510                 elseif (!extension_loaded('xmlreader'))
1511                 {
1512                         static $xml_is_sane = null;
1513                         if ($xml_is_sane === null)
1514                         {
1515                                 $parser_check = xml_parser_create();
1516                                 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1517                                 xml_parser_free($parser_check);
1518                                 $xml_is_sane = isset($values[0]['value']);
1519                         }
1520                         if (!$xml_is_sane)
1521                         {
1522                                 return false;
1523                         }
1524                 }
1525
1526                 if (isset($_GET[$this->javascript]))
1527                 {
1528                         SimplePie_Misc::output_javascript();
1529                         exit;
1530                 }
1531
1532                 // Pass whatever was set with config options over to the sanitizer.
1533                 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1534                 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1535
1536                 if ($this->feed_url !== null || $this->raw_data !== null)
1537                 {
1538                         $this->data = array();
1539                         $this->multifeed_objects = array();
1540                         $cache = false;
1541
1542                         if ($this->feed_url !== null)
1543                         {
1544                                 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1545                                 // Decide whether to enable caching
1546                                 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1547                                 {
1548                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1549                                 }
1550                                 // If it's enabled and we don't want an XML dump, use the cache
1551                                 if ($cache && !$this->xml_dump)
1552                                 {
1553                                         // Load the Cache
1554                                         $this->data = $cache->load();
1555                                         if (!empty($this->data))
1556                                         {
1557                                                 // If the cache is for an outdated build of SimplePie
1558                                                 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1559                                                 {
1560                                                         $cache->unlink();
1561                                                         $this->data = array();
1562                                                 }
1563                                                 // If we've hit a collision just rerun it with caching disabled
1564                                                 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1565                                                 {
1566                                                         $cache = false;
1567                                                         $this->data = array();
1568                                                 }
1569                                                 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1570                                                 elseif (isset($this->data['feed_url']))
1571                                                 {
1572                                                         // If the autodiscovery cache is still valid use it.
1573                                                         if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1574                                                         {
1575                                                                 // Do not need to do feed autodiscovery yet.
1576                                                                 if ($this->data['feed_url'] === $this->data['url'])
1577                                                                 {
1578                                                                         $cache->unlink();
1579                                                                         $this->data = array();
1580                                                                 }
1581                                                                 else
1582                                                                 {
1583                                                                         $this->set_feed_url($this->data['feed_url']);
1584                                                                         return $this->init();
1585                                                                 }
1586                                                         }
1587                                                 }
1588                                                 // Check if the cache has been updated
1589                                                 elseif ($cache->mtime() + $this->cache_duration < time())
1590                                                 {
1591                                                         // If we have last-modified and/or etag set
1592                                                         if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1593                                                         {
1594                                                                 $headers = array();
1595                                                                 if (isset($this->data['headers']['last-modified']))
1596                                                                 {
1597                                                                         $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1598                                                                 }
1599                                                                 if (isset($this->data['headers']['etag']))
1600                                                                 {
1601                                                                         $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1602                                                                 }
1603                                                                 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1604                                                                 if ($file->success)
1605                                                                 {
1606                                                                         if ($file->status_code === 304)
1607                                                                         {
1608                                                                                 $cache->touch();
1609                                                                                 return true;
1610                                                                         }
1611                                                                         else
1612                                                                         {
1613                                                                                 $headers = $file->headers;
1614                                                                         }
1615                                                                 }
1616                                                                 else
1617                                                                 {
1618                                                                         unset($file);
1619                                                                 }
1620                                                         }
1621                                                 }
1622                                                 // If the cache is still valid, just return true
1623                                                 else
1624                                                 {
1625                                                         return true;
1626                                                 }
1627                                         }
1628                                         // If the cache is empty, delete it
1629                                         else
1630                                         {
1631                                                 $cache->unlink();
1632                                                 $this->data = array();
1633                                         }
1634                                 }
1635                                 // 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.
1636                                 if (!isset($file))
1637                                 {
1638                                         if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1639                                         {
1640                                                 $file =& $this->file;
1641                                         }
1642                                         else
1643                                         {
1644                                                 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1645                                         }
1646                                 }
1647                                 // If the file connection has an error, set SimplePie::error to that and quit
1648                                 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1649                                 {
1650                                         $this->error = $file->error;
1651                                         if (!empty($this->data))
1652                                         {
1653                                                 return true;
1654                                         }
1655                                         else
1656                                         {
1657                                                 return false;
1658                                         }
1659                                 }
1660
1661                                 if (!$this->force_feed)
1662                                 {
1663                                         // Check if the supplied URL is a feed, if it isn't, look for it.
1664                                         $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1665                                         if (!$locate->is_feed($file))
1666                                         {
1667                                                 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1668                                                 unset($file);
1669                                                 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1670                                                 {
1671                                                         if ($cache)
1672                                                         {
1673                                                                 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1674                                                                 if (!$cache->save($this))
1675                                                                 {
1676                                                                         trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1677                                                                 }
1678                                                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1679                                                         }
1680                                                         $this->feed_url = $file->url;
1681                                                 }
1682                                                 else
1683                                                 {
1684                                                         $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
1685                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1686                                                         return false;
1687                                                 }
1688                                         }
1689                                         $locate = null;
1690                                 }
1691
1692                                 $headers = $file->headers;
1693                                 $data = $file->body;
1694                                 $sniffer =& new $this->content_type_sniffer_class($file);
1695                                 $sniffed = $sniffer->get_type();
1696                         }
1697                         else
1698                         {
1699                                 $data = $this->raw_data;
1700                         }
1701
1702                         // Set up array of possible encodings
1703                         $encodings = array();
1704
1705                         // First check to see if input has been overridden.
1706                         if ($this->input_encoding !== false)
1707                         {
1708                                 $encodings[] = $this->input_encoding;
1709                         }
1710
1711                         $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1712                         $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1713
1714                         // RFC 3023 (only applies to sniffed content)
1715                         if (isset($sniffed))
1716                         {
1717                                 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1718                                 {
1719                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1720                                         {
1721                                                 $encodings[] = strtoupper($charset[1]);
1722                                         }
1723                                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1724                                         $encodings[] = 'UTF-8';
1725                                 }
1726                                 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1727                                 {
1728                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1729                                         {
1730                                                 $encodings[] = $charset[1];
1731                                         }
1732                                         $encodings[] = 'US-ASCII';
1733                                 }
1734                                 // Text MIME-type default
1735                                 elseif (substr($sniffed, 0, 5) === 'text/')
1736                                 {
1737                                         $encodings[] = 'US-ASCII';
1738                                 }
1739                         }
1740
1741                         // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1742                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1743                         $encodings[] = 'UTF-8';
1744                         $encodings[] = 'ISO-8859-1';
1745
1746                         // There's no point in trying an encoding twice
1747                         $encodings = array_unique($encodings);
1748
1749                         // If we want the XML, just output that with the most likely encoding and quit
1750                         if ($this->xml_dump)
1751                         {
1752                                 header('Content-type: text/xml; charset=' . $encodings[0]);
1753                                 echo $data;
1754                                 exit;
1755                         }
1756
1757                         // Loop through each possible encoding, till we return something, or run out of possibilities
1758                         foreach ($encodings as $encoding)
1759                         {
1760                                 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1761                                 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1762                                 {
1763                                         // Create new parser
1764                                         $parser =& new $this->parser_class();
1765
1766                                         // If it's parsed fine
1767                                         if ($parser->parse($utf8_data, 'UTF-8'))
1768                                         {
1769                                                 $this->data = $parser->get_data();
1770                                                 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1771                                                 {
1772                                                         if (isset($headers))
1773                                                         {
1774                                                                 $this->data['headers'] = $headers;
1775                                                         }
1776                                                         $this->data['build'] = SIMPLEPIE_BUILD;
1777
1778                                                         // Cache the file if caching is enabled
1779                                                         if ($cache && !$cache->save($this))
1780                                                         {
1781                                                                 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1782                                                         }
1783                                                         return true;
1784                                                 }
1785                                                 else
1786                                                 {
1787                                                         $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1788                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1789                                                         return false;
1790                                                 }
1791                                         }
1792                                 }
1793                         }
1794                         if (isset($parser))
1795                         {
1796                                 // We have an error, just set SimplePie_Misc::error to it and quit
1797                                 $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1798                         }
1799                         else
1800                         {
1801                                 $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
1802                         }
1803                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1804                         return false;
1805                 }
1806                 elseif (!empty($this->multifeed_url))
1807                 {
1808                         $i = 0;
1809                         $success = 0;
1810                         $this->multifeed_objects = array();
1811                         foreach ($this->multifeed_url as $url)
1812                         {
1813                                 if (SIMPLEPIE_PHP5)
1814                                 {
1815                                         // This keyword needs to defy coding standards for PHP4 compatibility
1816                                         $this->multifeed_objects[$i] = clone($this);
1817                                 }
1818                                 else
1819                                 {
1820                                         $this->multifeed_objects[$i] = $this;
1821                                 }
1822                                 $this->multifeed_objects[$i]->set_feed_url($url);
1823                                 $success |= $this->multifeed_objects[$i]->init();
1824                                 $i++;
1825                         }
1826                         return (bool) $success;
1827                 }
1828                 else
1829                 {
1830                         return false;
1831                 }
1832         }
1833
1834         /**
1835          * Return the error message for the occured error
1836          *
1837          * @access public
1838          * @return string Error message
1839          */
1840         function error()
1841         {
1842                 return $this->error;
1843         }
1844
1845         function get_encoding()
1846         {
1847                 return $this->sanitize->output_encoding;
1848         }
1849
1850         function handle_content_type($mime = 'text/html')
1851         {
1852                 if (!headers_sent())
1853                 {
1854                         $header = "Content-type: $mime;";
1855                         if ($this->get_encoding())
1856                         {
1857                                 $header .= ' charset=' . $this->get_encoding();
1858                         }
1859                         else
1860                         {
1861                                 $header .= ' charset=UTF-8';
1862                         }
1863                         header($header);
1864                 }
1865         }
1866
1867         function get_type()
1868         {
1869                 if (!isset($this->data['type']))
1870                 {
1871                         $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1872                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1873                         {
1874                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1875                         }
1876                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1877                         {
1878                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1879                         }
1880                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1881                         {
1882                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1883                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1884                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1885                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1886                                 {
1887                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1888                                 }
1889                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1890                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1891                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1892                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1893                                 {
1894                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1895                                 }
1896                         }
1897                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1898                         {
1899                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1900                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1901                                 {
1902                                         switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1903                                         {
1904                                                 case '0.91':
1905                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1906                                                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1907                                                         {
1908                                                                 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1909                                                                 {
1910                                                                         case '0':
1911                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1912                                                                                 break;
1913
1914                                                                         case '24':
1915                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1916                                                                                 break;
1917                                                                 }
1918                                                         }
1919                                                         break;
1920
1921                                                 case '0.92':
1922                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1923                                                         break;
1924
1925                                                 case '0.93':
1926                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1927                                                         break;
1928
1929                                                 case '0.94':
1930                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1931                                                         break;
1932
1933                                                 case '2.0':
1934                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1935                                                         break;
1936                                         }
1937                                 }
1938                         }
1939                         else
1940                         {
1941                                 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1942                         }
1943                 }
1944                 return $this->data['type'];
1945         }
1946
1947         /**
1948          * Returns the URL for the favicon of the feed's website.
1949          *
1950          * @todo Cache atom:icon
1951          * @access public
1952          * @since 1.0
1953          */
1954         function get_favicon()
1955         {
1956                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1957                 {
1958                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1959                 }
1960                 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1961                 {
1962                         $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1963
1964                         if ($this->cache && $this->favicon_handler)
1965                         {
1966                                 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1967                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1968
1969                                 if ($cache->load())
1970                                 {
1971                                         return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1972                                 }
1973                                 else
1974                                 {
1975                                         $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1976
1977                                         if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
1978                                         {
1979                                                 $sniffer =& new $this->content_type_sniffer_class($file);
1980                                                 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1981                                                 {
1982                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1983                                                         {
1984                                                                 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1985                                                         }
1986                                                         else
1987                                                         {
1988                                                                 trigger_error("$cache->name is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1989                                                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1990                                                         }
1991                                                 }
1992                                                 // not an image
1993                                                 else
1994                                                 {
1995                                                         return false;
1996                                                 }
1997                                         }
1998                                 }
1999                         }
2000                         else
2001                         {
2002                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2003                         }
2004                 }
2005                 return false;
2006         }
2007
2008         /**
2009          * @todo If we have a perm redirect we should return the new URL
2010          * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2011          * @todo Also, |atom:link|@rel=self
2012          */
2013         function subscribe_url()
2014         {
2015                 if ($this->feed_url !== null)
2016                 {
2017                         return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2018                 }
2019                 else
2020                 {
2021                         return null;
2022                 }
2023         }
2024
2025         function subscribe_feed()
2026         {
2027                 if ($this->feed_url !== null)
2028                 {
2029                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2030                 }
2031                 else
2032                 {
2033                         return null;
2034                 }
2035         }
2036
2037         function subscribe_outlook()
2038         {
2039                 if ($this->feed_url !== null)
2040                 {
2041                         return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2042                 }
2043                 else
2044                 {
2045                         return null;
2046                 }
2047         }
2048
2049         function subscribe_podcast()
2050         {
2051                 if ($this->feed_url !== null)
2052                 {
2053                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2054                 }
2055                 else
2056                 {
2057                         return null;
2058                 }
2059         }
2060
2061         function subscribe_itunes()
2062         {
2063                 if ($this->feed_url !== null)
2064                 {
2065                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2066                 }
2067                 else
2068                 {
2069                         return null;
2070                 }
2071         }
2072
2073         /**
2074          * Creates the subscribe_* methods' return data
2075          *
2076          * @access private
2077          * @param string $feed_url String to prefix to the feed URL
2078          * @param string $site_url String to prefix to the site URL (and
2079          * suffix to the feed URL)
2080          * @return mixed URL if feed exists, false otherwise
2081          */
2082         function subscribe_service($feed_url, $site_url = null)
2083         {
2084                 if ($this->subscribe_url())
2085                 {
2086                         $return = $feed_url . rawurlencode($this->feed_url);
2087                         if ($site_url !== null && $this->get_link() !== null)
2088                         {
2089                                 $return .= $site_url . rawurlencode($this->get_link());
2090                         }
2091                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2092                 }
2093                 else
2094                 {
2095                         return null;
2096                 }
2097         }
2098
2099         function subscribe_aol()
2100         {
2101                 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2102         }
2103
2104         function subscribe_bloglines()
2105         {
2106                 return $this->subscribe_service('http://www.bloglines.com/sub/');
2107         }
2108
2109         function subscribe_eskobo()
2110         {
2111                 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2112         }
2113
2114         function subscribe_feedfeeds()
2115         {
2116                 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2117         }
2118
2119         function subscribe_feedster()
2120         {
2121                 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2122         }
2123
2124         function subscribe_google()
2125         {
2126                 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2127         }
2128
2129         function subscribe_gritwire()
2130         {
2131                 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2132         }
2133
2134         function subscribe_msn()
2135         {
2136                 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2137         }
2138
2139         function subscribe_netvibes()
2140         {
2141                 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2142         }
2143
2144         function subscribe_newsburst()
2145         {
2146                 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2147         }
2148
2149         function subscribe_newsgator()
2150         {
2151                 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2152         }
2153
2154         function subscribe_odeo()
2155         {
2156                 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2157         }
2158
2159         function subscribe_podnova()
2160         {
2161                 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2162         }
2163
2164         function subscribe_rojo()
2165         {
2166                 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2167         }
2168
2169         function subscribe_yahoo()
2170         {
2171                 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2172         }
2173
2174         function get_feed_tags($namespace, $tag)
2175         {
2176                 $type = $this->get_type();
2177                 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2178                 {
2179                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2180                         {
2181                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2182                         }
2183                 }
2184                 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2185                 {
2186                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2187                         {
2188                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2189                         }
2190                 }
2191                 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2192                 {
2193                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2194                         {
2195                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2196                         }
2197                 }
2198                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2199                 {
2200                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2201                         {
2202                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2203                         }
2204                 }
2205                 return null;
2206         }
2207
2208         function get_channel_tags($namespace, $tag)
2209         {
2210                 $type = $this->get_type();
2211                 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2212                 {
2213                         if ($return = $this->get_feed_tags($namespace, $tag))
2214                         {
2215                                 return $return;
2216                         }
2217                 }
2218                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2219                 {
2220                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2221                         {
2222                                 if (isset($channel[0]['child'][$namespace][$tag]))
2223                                 {
2224                                         return $channel[0]['child'][$namespace][$tag];
2225                                 }
2226                         }
2227                 }
2228                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2229                 {
2230                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2231                         {
2232                                 if (isset($channel[0]['child'][$namespace][$tag]))
2233                                 {
2234                                         return $channel[0]['child'][$namespace][$tag];
2235                                 }
2236                         }
2237                 }
2238                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2239                 {
2240                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2241                         {
2242                                 if (isset($channel[0]['child'][$namespace][$tag]))
2243                                 {
2244                                         return $channel[0]['child'][$namespace][$tag];
2245                                 }
2246                         }
2247                 }
2248                 return null;
2249         }
2250
2251         function get_image_tags($namespace, $tag)
2252         {
2253                 $type = $this->get_type();
2254                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2255                 {
2256                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2257                         {
2258                                 if (isset($image[0]['child'][$namespace][$tag]))
2259                                 {
2260                                         return $image[0]['child'][$namespace][$tag];
2261                                 }
2262                         }
2263                 }
2264                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2265                 {
2266                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2267                         {
2268                                 if (isset($image[0]['child'][$namespace][$tag]))
2269                                 {
2270                                         return $image[0]['child'][$namespace][$tag];
2271                                 }
2272                         }
2273                 }
2274                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2275                 {
2276                         if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2277                         {
2278                                 if (isset($image[0]['child'][$namespace][$tag]))
2279                                 {
2280                                         return $image[0]['child'][$namespace][$tag];
2281                                 }
2282                         }
2283                 }
2284                 return null;
2285         }
2286
2287         function get_base($element = array())
2288         {
2289                 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2290                 {
2291                         return $element['xml_base'];
2292                 }
2293                 elseif ($this->get_link() !== null)
2294                 {
2295                         return $this->get_link();
2296                 }
2297                 else
2298                 {
2299                         return $this->subscribe_url();
2300                 }
2301         }
2302
2303         function sanitize($data, $type, $base = '')
2304         {
2305                 return $this->sanitize->sanitize($data, $type, $base);
2306         }
2307
2308         function get_title()
2309         {
2310                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2311                 {
2312                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2313                 }
2314                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2315                 {
2316                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2317                 }
2318                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2319                 {
2320                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2321                 }
2322                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2323                 {
2324                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2325                 }
2326                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2327                 {
2328                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2329                 }
2330                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2331                 {
2332                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2333                 }
2334                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2335                 {
2336                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2337                 }
2338                 else
2339                 {
2340                         return null;
2341                 }
2342         }
2343
2344         function get_category($key = 0)
2345         {
2346                 $categories = $this->get_categories();
2347                 if (isset($categories[$key]))
2348                 {
2349                         return $categories[$key];
2350                 }
2351                 else
2352                 {
2353                         return null;
2354                 }
2355         }
2356
2357         function get_categories()
2358         {
2359                 $categories = array();
2360
2361                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2362                 {
2363                         $term = null;
2364                         $scheme = null;
2365                         $label = null;
2366                         if (isset($category['attribs']['']['term']))
2367                         {
2368                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2369                         }
2370                         if (isset($category['attribs']['']['scheme']))
2371                         {
2372                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2373                         }
2374                         if (isset($category['attribs']['']['label']))
2375                         {
2376                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2377                         }
2378                         $categories[] =& new $this->category_class($term, $scheme, $label);
2379                 }
2380                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2381                 {
2382                         // This is really the label, but keep this as the term also for BC.
2383                         // Label will also work on retrieving because that falls back to term.
2384                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2385                         if (isset($category['attribs']['']['domain']))
2386                         {
2387                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2388                         }
2389                         else
2390                         {
2391                                 $scheme = null;
2392                         }
2393                         $categories[] =& new $this->category_class($term, $scheme, null);
2394                 }
2395                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2396                 {
2397                         $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2398                 }
2399                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2400                 {
2401                         $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2402                 }
2403
2404                 if (!empty($categories))
2405                 {
2406                         return SimplePie_Misc::array_unique($categories);
2407                 }
2408                 else
2409                 {
2410                         return null;
2411                 }
2412         }
2413
2414         function get_author($key = 0)
2415         {
2416                 $authors = $this->get_authors();
2417                 if (isset($authors[$key]))
2418                 {
2419                         return $authors[$key];
2420                 }
2421                 else
2422                 {
2423                         return null;
2424                 }
2425         }
2426
2427         function get_authors()
2428         {
2429                 $authors = array();
2430                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2431                 {
2432                         $name = null;
2433                         $uri = null;
2434                         $email = null;
2435                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2436                         {
2437                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2438                         }
2439                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2440                         {
2441                                 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2442                         }
2443                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2444                         {
2445                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2446                         }
2447                         if ($name !== null || $email !== null || $uri !== null)
2448                         {
2449                                 $authors[] =& new $this->author_class($name, $uri, $email);
2450                         }
2451                 }
2452                 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2453                 {
2454                         $name = null;
2455                         $url = null;
2456                         $email = null;
2457                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2458                         {
2459                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2460                         }
2461                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2462                         {
2463                                 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2464                         }
2465                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2466                         {
2467                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2468                         }
2469                         if ($name !== null || $email !== null || $url !== null)
2470                         {
2471                                 $authors[] =& new $this->author_class($name, $url, $email);
2472                         }
2473                 }
2474                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2475                 {
2476                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2477                 }
2478                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2479                 {
2480                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2481                 }
2482                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2483                 {
2484                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2485                 }
2486
2487                 if (!empty($authors))
2488                 {
2489                         return SimplePie_Misc::array_unique($authors);
2490                 }
2491                 else
2492                 {
2493                         return null;
2494                 }
2495         }
2496
2497         function get_contributor($key = 0)
2498         {
2499                 $contributors = $this->get_contributors();
2500                 if (isset($contributors[$key]))
2501                 {
2502                         return $contributors[$key];
2503                 }
2504                 else
2505                 {
2506                         return null;
2507                 }
2508         }
2509
2510         function get_contributors()
2511         {
2512                 $contributors = array();
2513                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2514                 {
2515                         $name = null;
2516                         $uri = null;
2517                         $email = null;
2518                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2519                         {
2520                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2521                         }
2522                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2523                         {
2524                                 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2525                         }
2526                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2527                         {
2528                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2529                         }
2530                         if ($name !== null || $email !== null || $uri !== null)
2531                         {
2532                                 $contributors[] =& new $this->author_class($name, $uri, $email);
2533                         }
2534                 }
2535                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2536                 {
2537                         $name = null;
2538                         $url = null;
2539                         $email = null;
2540                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2541                         {
2542                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2543                         }
2544                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2545                         {
2546                                 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2547                         }
2548                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2549                         {
2550                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2551                         }
2552                         if ($name !== null || $email !== null || $url !== null)
2553                         {
2554                                 $contributors[] =& new $this->author_class($name, $url, $email);
2555                         }
2556                 }
2557
2558                 if (!empty($contributors))
2559                 {
2560                         return SimplePie_Misc::array_unique($contributors);
2561                 }
2562                 else
2563                 {
2564                         return null;
2565                 }
2566         }
2567
2568         function get_link($key = 0, $rel = 'alternate')
2569         {
2570                 $links = $this->get_links($rel);
2571                 if (isset($links[$key]))
2572                 {
2573                         return $links[$key];
2574                 }
2575                 else
2576                 {
2577                         return null;
2578                 }
2579         }
2580
2581         /**
2582          * Added for parity between the parent-level and the item/entry-level.
2583          */
2584         function get_permalink()
2585         {
2586                 return $this->get_link(0);
2587         }
2588
2589         function get_links($rel = 'alternate')
2590         {
2591                 if (!isset($this->data['links']))
2592                 {
2593                         $this->data['links'] = array();
2594                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2595                         {
2596                                 foreach ($links as $link)
2597                                 {
2598                                         if (isset($link['attribs']['']['href']))
2599                                         {
2600                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2601                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2602                                         }
2603                                 }
2604                         }
2605                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2606                         {
2607                                 foreach ($links as $link)
2608                                 {
2609                                         if (isset($link['attribs']['']['href']))
2610                                         {
2611                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2612                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2613
2614                                         }
2615                                 }
2616                         }
2617                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2618                         {
2619                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2620                         }
2621                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2622                         {
2623                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2624                         }
2625                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2626                         {
2627                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2628                         }
2629
2630                         $keys = array_keys($this->data['links']);
2631                         foreach ($keys as $key)
2632                         {
2633                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
2634                                 {
2635                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2636                                         {
2637                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2638                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2639                                         }
2640                                         else
2641                                         {
2642                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2643                                         }
2644                                 }
2645                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2646                                 {
2647                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2648                                 }
2649                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2650                         }
2651                 }
2652
2653                 if (isset($this->data['links'][$rel]))
2654                 {
2655                         return $this->data['links'][$rel];
2656                 }
2657                 else
2658                 {
2659                         return null;
2660                 }
2661         }
2662
2663         function get_all_discovered_feeds()
2664         {
2665                 return $this->all_discovered_feeds;
2666         }
2667
2668         function get_description()
2669         {
2670                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2671                 {
2672                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2673                 }
2674                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2675                 {
2676                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2677                 }
2678                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2679                 {
2680                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2681                 }
2682                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2683                 {
2684                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2685                 }
2686                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2687                 {
2688                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2689                 }
2690                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2691                 {
2692                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2693                 }
2694                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2695                 {
2696                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2697                 }
2698                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2699                 {
2700                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2701                 }
2702                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2703                 {
2704                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2705                 }
2706                 else
2707                 {
2708                         return null;
2709                 }
2710         }
2711
2712         function get_copyright()
2713         {
2714                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2715                 {
2716                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2717                 }
2718                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2719                 {
2720                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2721                 }
2722                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2723                 {
2724                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2725                 }
2726                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2727                 {
2728                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2729                 }
2730                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2731                 {
2732                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2733                 }
2734                 else
2735                 {
2736                         return null;
2737                 }
2738         }
2739
2740         function get_language()
2741         {
2742                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2743                 {
2744                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2745                 }
2746                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2747                 {
2748                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2749                 }
2750                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2751                 {
2752                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2753                 }
2754                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2755                 {
2756                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2757                 }
2758                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2759                 {
2760                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2761                 }
2762                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2763                 {
2764                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2765                 }
2766                 elseif (isset($this->data['headers']['content-language']))
2767                 {
2768                         return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2769                 }
2770                 else
2771                 {
2772                         return null;
2773                 }
2774         }
2775
2776         function get_latitude()
2777         {
2778
2779                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2780                 {
2781                         return (float) $return[0]['data'];
2782                 }
2783                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2784                 {
2785                         return (float) $match[1];
2786                 }
2787                 else
2788                 {
2789                         return null;
2790                 }
2791         }
2792
2793         function get_longitude()
2794         {
2795                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2796                 {
2797                         return (float) $return[0]['data'];
2798                 }
2799                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2800                 {
2801                         return (float) $return[0]['data'];
2802                 }
2803                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2804                 {
2805                         return (float) $match[2];
2806                 }
2807                 else
2808                 {
2809                         return null;
2810                 }
2811         }
2812
2813         function get_image_title()
2814         {
2815                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2816                 {
2817                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2818                 }
2819                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2820                 {
2821                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2822                 }
2823                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2824                 {
2825                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2826                 }
2827                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2828                 {
2829                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2830                 }
2831                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2832                 {
2833                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2834                 }
2835                 else
2836                 {
2837                         return null;
2838                 }
2839         }
2840
2841         function get_image_url()
2842         {
2843                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2844                 {
2845                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2846                 }
2847                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2848                 {
2849                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2850                 }
2851                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2852                 {
2853                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2854                 }
2855                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2856                 {
2857                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2858                 }
2859                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2860                 {
2861                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2862                 }
2863                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2864                 {
2865                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2866                 }
2867                 else
2868                 {
2869                         return null;
2870                 }
2871         }
2872
2873         function get_image_link()
2874         {
2875                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2876                 {
2877                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2878                 }
2879                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2880                 {
2881                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2882                 }
2883                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2884                 {
2885                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2886                 }
2887                 else
2888                 {
2889                         return null;
2890                 }
2891         }
2892
2893         function get_image_width()
2894         {
2895                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2896                 {
2897                         return round($return[0]['data']);
2898                 }
2899                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2900                 {
2901                         return 88.0;
2902                 }
2903                 else
2904                 {
2905                         return null;
2906                 }
2907         }
2908
2909         function get_image_height()
2910         {
2911                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2912                 {
2913                         return round($return[0]['data']);
2914                 }
2915                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2916                 {
2917                         return 31.0;
2918                 }
2919                 else
2920                 {
2921                         return null;
2922                 }
2923         }
2924
2925         function get_item_quantity($max = 0)
2926         {
2927                 $max = (int) $max;
2928                 $qty = count($this->get_items());
2929                 if ($max === 0)
2930                 {
2931                         return $qty;
2932                 }
2933                 else
2934                 {
2935                         return ($qty > $max) ? $max : $qty;
2936                 }
2937         }
2938
2939         function get_item($key = 0)
2940         {
2941                 $items = $this->get_items();
2942                 if (isset($items[$key]))
2943                 {
2944                         return $items[$key];
2945                 }
2946                 else
2947                 {
2948                         return null;
2949                 }
2950         }
2951
2952         function get_items($start = 0, $end = 0)
2953         {
2954                 if (!isset($this->data['items']))
2955                 {
2956                         if (!empty($this->multifeed_objects))
2957                         {
2958                                 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2959                         }
2960                         else
2961                         {
2962                                 $this->data['items'] = array();
2963                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2964                                 {
2965                                         $keys = array_keys($items);
2966                                         foreach ($keys as $key)
2967                                         {
2968                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2969                                         }
2970                                 }
2971                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2972                                 {
2973                                         $keys = array_keys($items);
2974                                         foreach ($keys as $key)
2975                                         {
2976                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2977                                         }
2978                                 }
2979                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2980                                 {
2981                                         $keys = array_keys($items);
2982                                         foreach ($keys as $key)
2983                                         {
2984                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2985                                         }
2986                                 }
2987                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2988                                 {
2989                                         $keys = array_keys($items);
2990                                         foreach ($keys as $key)
2991                                         {
2992                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2993                                         }
2994                                 }
2995                                 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2996                                 {
2997                                         $keys = array_keys($items);
2998                                         foreach ($keys as $key)
2999                                         {
3000                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
3001                                         }
3002                                 }
3003                         }
3004                 }
3005
3006                 if (!empty($this->data['items']))
3007                 {
3008                         // If we want to order it by date, check if all items have a date, and then sort it
3009                         if ($this->order_by_date && empty($this->multifeed_objects))
3010                         {
3011                                 if (!isset($this->data['ordered_items']))
3012                                 {
3013                                         $do_sort = true;
3014                                         foreach ($this->data['items'] as $item)
3015                                         {
3016                                                 if (!$item->get_date('U'))
3017                                                 {
3018                                                         $do_sort = false;
3019                                                         break;
3020                                                 }
3021                                         }
3022                                         $item = null;
3023                                         $this->data['ordered_items'] = $this->data['items'];
3024                                         if ($do_sort)
3025                                         {
3026                                                 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3027                                         }
3028                                 }
3029                                 $items = $this->data['ordered_items'];
3030                         }
3031                         else
3032                         {
3033                                 $items = $this->data['items'];
3034                         }
3035
3036                         // Slice the data as desired
3037                         if ($end === 0)
3038                         {
3039                                 return array_slice($items, $start);
3040                         }
3041                         else
3042                         {
3043                                 return array_slice($items, $start, $end);
3044                         }
3045                 }
3046                 else
3047                 {
3048                         return array();
3049                 }
3050         }
3051
3052         /**
3053          * @static
3054          */
3055         function sort_items($a, $b)
3056         {
3057                 return $a->get_date('U') <= $b->get_date('U');
3058         }
3059
3060         /**
3061          * @static
3062          */
3063         function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3064         {
3065                 if (is_array($urls) && sizeof($urls) > 0)
3066                 {
3067                         $items = array();
3068                         foreach ($urls as $arg)
3069                         {
3070                                 if (is_a($arg, 'SimplePie'))
3071                                 {
3072                                         $items = array_merge($items, $arg->get_items(0, $limit));
3073                                 }
3074                                 else
3075                                 {
3076                                         trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3077                                 }
3078                         }
3079
3080                         $do_sort = true;
3081                         foreach ($items as $item)
3082                         {
3083                                 if (!$item->get_date('U'))
3084                                 {
3085                                         $do_sort = false;
3086                                         break;
3087                                 }
3088                         }
3089                         $item = null;
3090                         if ($do_sort)
3091                         {
3092                                 usort($items, array('SimplePie', 'sort_items'));
3093                         }
3094
3095                         if ($end === 0)
3096                         {
3097                                 return array_slice($items, $start);
3098                         }
3099                         else
3100                         {
3101                                 return array_slice($items, $start, $end);
3102                         }
3103                 }
3104                 else
3105                 {
3106                         trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3107                         return array();
3108                 }
3109         }
3110 }
3111
3112 class SimplePie_Item
3113 {
3114         var $feed;
3115         var $data = array();
3116
3117         function SimplePie_Item($feed, $data)
3118         {
3119                 $this->feed = $feed;
3120                 $this->data = $data;
3121         }
3122
3123         function __toString()
3124         {
3125                 return md5(serialize($this->data));
3126         }
3127
3128         /**
3129          * Remove items that link back to this before destroying this object
3130          */
3131         function __destruct()
3132         {
3133                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3134                 {
3135                         unset($this->feed);
3136                 }
3137         }
3138
3139         function get_item_tags($namespace, $tag)
3140         {
3141                 if (isset($this->data['child'][$namespace][$tag]))
3142                 {
3143                         return $this->data['child'][$namespace][$tag];
3144                 }
3145                 else
3146                 {
3147                         return null;
3148                 }
3149         }
3150
3151         function get_base($element = array())
3152         {
3153                 return $this->feed->get_base($element);
3154         }
3155
3156         function sanitize($data, $type, $base = '')
3157         {
3158                 return $this->feed->sanitize($data, $type, $base);
3159         }
3160
3161         function get_feed()
3162         {
3163                 return $this->feed;
3164         }
3165
3166         function get_id($hash = false)
3167         {
3168                 if (!$hash)
3169                 {
3170                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3171                         {
3172                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3173                         }
3174                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3175                         {
3176                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3177                         }
3178                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3179                         {
3180                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3181                         }
3182                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3183                         {
3184                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3185                         }
3186                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3187                         {
3188                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3189                         }
3190                         elseif (($return = $this->get_permalink()) !== null)
3191                         {
3192                                 return $return;
3193                         }
3194                         elseif (($return = $this->get_title()) !== null)
3195                         {
3196                                 return $return;
3197                         }
3198                 }
3199                 if ($this->get_permalink() !== null || $this->get_title() !== null)
3200                 {
3201                         return md5($this->get_permalink() . $this->get_title());
3202                 }
3203                 else
3204                 {
3205                         return md5(serialize($this->data));
3206                 }
3207         }
3208
3209         function get_title()
3210         {
3211                 if (!isset($this->data['title']))
3212                 {
3213                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3214                         {
3215                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3216                         }
3217                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3218                         {
3219                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3220                         }
3221                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3222                         {
3223                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3224                         }
3225                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3226                         {
3227                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3228                         }
3229                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3230                         {
3231                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3232                         }
3233                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3234                         {
3235                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3236                         }
3237                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3238                         {
3239                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3240                         }
3241                         else
3242                         {
3243                                 $this->data['title'] = null;
3244                         }
3245                 }
3246                 return $this->data['title'];
3247         }
3248
3249         function get_description($description_only = false)
3250         {
3251                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3252                 {
3253                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3254                 }
3255                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3256                 {
3257                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3258                 }
3259                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3260                 {
3261                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3262                 }
3263                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3264                 {
3265                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3266                 }
3267                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3268                 {
3269                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3270                 }
3271                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3272                 {
3273                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3274                 }
3275                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3276                 {
3277                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3278                 }
3279                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3280                 {
3281                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3282                 }
3283                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
3284                 {
3285                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
3286                 }
3287
3288                 elseif (!$description_only)
3289                 {
3290                         return $this->get_content(true);
3291                 }
3292                 else
3293                 {
3294                         return null;
3295                 }
3296         }
3297
3298         function get_content($content_only = false)
3299         {
3300                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3301                 {
3302                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3303                 }
3304                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3305                 {
3306                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3307                 }
3308                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3309                 {
3310                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3311                 }
3312                 elseif (!$content_only)
3313                 {
3314                         return $this->get_description(true);
3315                 }
3316                 else
3317                 {
3318                         return null;
3319                 }
3320         }
3321
3322         function get_category($key = 0)
3323         {
3324                 $categories = $this->get_categories();
3325                 if (isset($categories[$key]))
3326                 {
3327                         return $categories[$key];
3328                 }
3329                 else
3330                 {
3331                         return null;
3332                 }
3333         }
3334
3335         function get_categories()
3336         {
3337                 $categories = array();
3338
3339                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3340                 {
3341                         $term = null;
3342                         $scheme = null;
3343                         $label = null;
3344                         if (isset($category['attribs']['']['term']))
3345                         {
3346                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3347                         }
3348                         if (isset($category['attribs']['']['scheme']))
3349                         {
3350                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3351                         }
3352                         if (isset($category['attribs']['']['label']))
3353                         {
3354                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3355                         }
3356                         $categories[] =& new $this->feed->category_class($term, $scheme, $label);
3357                 }
3358                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3359                 {
3360                         // This is really the label, but keep this as the term also for BC.
3361                         // Label will also work on retrieving because that falls back to term.
3362                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3363                         if (isset($category['attribs']['']['domain']))
3364                         {
3365                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3366                         }
3367                         else
3368                         {
3369                                 $scheme = null;
3370                         }
3371                         $categories[] =& new $this->feed->category_class($term, $scheme, null);
3372                 }
3373                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3374                 {
3375                         $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3376                 }
3377                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3378                 {
3379                         $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3380                 }
3381
3382                 if (!empty($categories))
3383                 {
3384                         return SimplePie_Misc::array_unique($categories);
3385                 }
3386                 else
3387                 {
3388                         return null;
3389                 }
3390         }
3391
3392         function get_author($key = 0)
3393         {
3394                 $authors = $this->get_authors();
3395                 if (isset($authors[$key]))
3396                 {
3397                         return $authors[$key];
3398                 }
3399                 else
3400                 {
3401                         return null;
3402                 }
3403         }
3404
3405         function get_contributor($key = 0)
3406         {
3407                 $contributors = $this->get_contributors();
3408                 if (isset($contributors[$key]))
3409                 {
3410                         return $contributors[$key];
3411                 }
3412                 else
3413                 {
3414                         return null;
3415                 }
3416         }
3417
3418         function get_contributors()
3419         {
3420                 $contributors = array();
3421                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3422                 {
3423                         $name = null;
3424                         $uri = null;
3425                         $email = null;
3426                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3427                         {
3428                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3429                         }
3430                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3431                         {
3432                                 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
3433                         }
3434                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3435                         {
3436                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3437                         }
3438                         if ($name !== null || $email !== null || $uri !== null)
3439                         {
3440                                 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
3441                         }
3442                 }
3443                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3444                 {
3445                         $name = null;
3446                         $url = null;
3447                         $email = null;
3448                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3449                         {
3450                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3451                         }
3452                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3453                         {
3454                                 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
3455                         }
3456                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3457                         {
3458                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3459                         }
3460                         if ($name !== null || $email !== null || $url !== null)
3461                         {
3462                                 $contributors[] =& new $this->feed->author_class($name, $url, $email);
3463                         }
3464                 }
3465
3466                 if (!empty($contributors))
3467                 {
3468                         return SimplePie_Misc::array_unique($contributors);
3469                 }
3470                 else
3471                 {
3472                         return null;
3473                 }
3474         }
3475
3476         function get_authors()
3477         {
3478                 $authors = array();
3479                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3480                 {
3481                         $name = null;
3482                         $uri = null;
3483                         $email = null;
3484                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3485                         {
3486                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3487                         }
3488                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3489                         {
3490                                 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
3491                         }
3492                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3493                         {
3494                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3495                         }
3496                         if ($name !== null || $email !== null || $uri !== null)
3497                         {
3498                                 $authors[] =& new $this->feed->author_class($name, $uri, $email);
3499                         }
3500                 }
3501                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3502                 {
3503                         $name = null;
3504                         $url = null;
3505                         $email = null;
3506                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3507                         {
3508                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3509                         }
3510                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3511                         {
3512                                 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
3513                         }
3514                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3515                         {
3516                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3517                         }
3518                         if ($name !== null || $email !== null || $url !== null)
3519                         {
3520                                 $authors[] =& new $this->feed->author_class($name, $url, $email);
3521                         }
3522                 }
3523                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3524                 {
3525                         $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3526                 }
3527                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3528                 {
3529                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3530                 }
3531                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3532                 {
3533                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3534                 }
3535                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3536                 {
3537                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3538                 }
3539
3540                 if (!empty($authors))
3541                 {
3542                         return SimplePie_Misc::array_unique($authors);
3543                 }
3544                 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3545                 {
3546                         return $authors;
3547                 }
3548                 elseif ($authors = $this->feed->get_authors())
3549                 {
3550                         return $authors;
3551                 }
3552                 else
3553                 {
3554                         return null;
3555                 }
3556         }
3557
3558         function get_copyright()
3559         {
3560                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3561                 {
3562                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3563                 }
3564                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3565                 {
3566                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3567                 }
3568                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3569                 {
3570                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3571                 }
3572                 else
3573                 {
3574                         return null;
3575                 }
3576         }
3577
3578         function get_date($date_format = 'j F Y, g:i a')
3579         {
3580                 if (!isset($this->data['date']))
3581                 {
3582                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3583                         {
3584                                 $this->data['date']['raw'] = $return[0]['data'];
3585                         }
3586                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3587                         {
3588                                 $this->data['date']['raw'] = $return[0]['data'];
3589                         }
3590                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3591                         {
3592                                 $this->data['date']['raw'] = $return[0]['data'];
3593                         }
3594                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3595                         {
3596                                 $this->data['date']['raw'] = $return[0]['data'];
3597                         }
3598                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3599                         {
3600                                 $this->data['date']['raw'] = $return[0]['data'];
3601                         }
3602                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3603                         {
3604                                 $this->data['date']['raw'] = $return[0]['data'];
3605                         }
3606                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3607                         {
3608                                 $this->data['date']['raw'] = $return[0]['data'];
3609                         }
3610                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3611                         {
3612                                 $this->data['date']['raw'] = $return[0]['data'];
3613                         }
3614
3615                         if (!empty($this->data['date']['raw']))
3616                         {
3617                                 $parser = SimplePie_Parse_Date::get();
3618                                 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3619                         }
3620                         else
3621                         {
3622                                 $this->data['date'] = null;
3623                         }
3624                 }
3625                 if ($this->data['date'])
3626                 {
3627                         $date_format = (string) $date_format;
3628                         switch ($date_format)
3629                         {
3630                                 case '':
3631                                         return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3632
3633                                 case 'U':
3634                                         return $this->data['date']['parsed'];
3635
3636                                 default:
3637                                         return date($date_format, $this->data['date']['parsed']);
3638                         }
3639                 }
3640                 else
3641                 {
3642                         return null;
3643                 }
3644         }
3645
3646         function get_local_date($date_format = '%c')
3647         {
3648                 if (!$date_format)
3649                 {
3650                         return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3651                 }
3652                 elseif (($date = $this->get_date('U')) !== null && $date !== false)
3653                 {
3654                         return strftime($date_format, $date);
3655                 }
3656                 else
3657                 {
3658                         return null;
3659                 }
3660         }
3661
3662         function get_permalink()
3663         {
3664                 $link = $this->get_link();
3665                 $enclosure = $this->get_enclosure(0);
3666                 if ($link !== null)
3667                 {
3668                         return $link;
3669                 }
3670                 elseif ($enclosure !== null)
3671                 {
3672                         return $enclosure->get_link();
3673                 }
3674                 else
3675                 {
3676                         return null;
3677                 }
3678         }
3679
3680         function get_link($key = 0, $rel = 'alternate')
3681         {
3682                 $links = $this->get_links($rel);
3683                 if ($links[$key] !== null)
3684                 {
3685                         return $links[$key];
3686                 }
3687                 else
3688                 {
3689                         return null;
3690                 }
3691         }
3692
3693         function get_links($rel = 'alternate')
3694         {
3695                 if (!isset($this->data['links']))
3696                 {
3697                         $this->data['links'] = array();
3698                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3699                         {
3700                                 if (isset($link['attribs']['']['href']))
3701                                 {
3702                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3703                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3704
3705                                 }
3706                         }
3707                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3708                         {
3709                                 if (isset($link['attribs']['']['href']))
3710                                 {
3711                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3712                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3713                                 }
3714                         }
3715                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3716                         {
3717                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3718                         }
3719                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3720                         {
3721                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3722                         }
3723                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3724                         {
3725                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3726                         }
3727                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3728                         {
3729                                 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3730                                 {
3731                                         $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3732                                 }
3733                         }
3734
3735                         $keys = array_keys($this->data['links']);
3736                         foreach ($keys as $key)
3737                         {
3738                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
3739                                 {
3740                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3741                                         {
3742                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3743                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3744                                         }
3745                                         else
3746                                         {
3747                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3748                                         }
3749                                 }
3750                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3751                                 {
3752                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3753                                 }
3754                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3755                         }
3756                 }
3757                 if (isset($this->data['links'][$rel]))
3758                 {
3759                         return $this->data['links'][$rel];
3760                 }
3761                 else
3762                 {
3763                         return null;
3764                 }
3765         }
3766
3767         /**
3768          * @todo Add ability to prefer one type of content over another (in a media group).
3769          */
3770         function get_enclosure($key = 0, $prefer = null)
3771         {
3772                 $enclosures = $this->get_enclosures();
3773                 if (isset($enclosures[$key]))
3774                 {
3775                         return $enclosures[$key];
3776                 }
3777                 else
3778                 {
3779                         return null;
3780                 }
3781         }
3782
3783         /**
3784          * Grabs all available enclosures (podcasts, etc.)
3785          *
3786          * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3787          *
3788          * At this point, we're pretty much assuming that all enclosures for an item are the same content.  Anything else is too complicated to properly support.
3789          *
3790          * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3791          * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).
3792          */
3793         function get_enclosures()
3794         {
3795                 if (!isset($this->data['enclosures']))
3796                 {
3797                         $this->data['enclosures'] = array();
3798
3799                         // Elements
3800                         $captions_parent = null;
3801                         $categories_parent = null;
3802                         $copyrights_parent = null;
3803                         $credits_parent = null;
3804                         $description_parent = null;
3805                         $duration_parent = null;
3806                         $hashes_parent = null;
3807                         $keywords_parent = null;
3808                         $player_parent = null;
3809                         $ratings_parent = null;
3810                         $restrictions_parent = null;
3811                         $thumbnails_parent = null;
3812                         $title_parent = null;
3813
3814                         // Let's do the channel and item-level ones first, and just re-use them if we need to.
3815                         $parent = $this->get_feed();
3816
3817                         // CAPTIONS
3818                         if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3819                         {
3820                                 foreach ($captions as $caption)
3821                                 {
3822                                         $caption_type = null;
3823                                         $caption_lang = null;
3824                                         $caption_startTime = null;
3825                                         $caption_endTime = null;
3826                                         $caption_text = null;
3827                                         if (isset($caption['attribs']['']['type']))
3828                                         {
3829                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3830                                         }
3831                                         if (isset($caption['attribs']['']['lang']))
3832                                         {
3833                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3834                                         }
3835                                         if (isset($caption['attribs']['']['start']))
3836                                         {
3837                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3838                                         }
3839                                         if (isset($caption['attribs']['']['end']))
3840                                         {
3841                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3842                                         }
3843                                         if (isset($caption['data']))
3844                                         {
3845                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3846                                         }
3847                                         $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3848                                 }
3849                         }
3850                         elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3851                         {
3852                                 foreach ($captions as $caption)
3853                                 {
3854                                         $caption_type = null;
3855                                         $caption_lang = null;
3856                                         $caption_startTime = null;
3857                                         $caption_endTime = null;
3858                                         $caption_text = null;
3859                                         if (isset($caption['attribs']['']['type']))
3860                                         {
3861                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3862                                         }
3863                                         if (isset($caption['attribs']['']['lang']))
3864                                         {
3865                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3866                                         }
3867                                         if (isset($caption['attribs']['']['start']))
3868                                         {
3869                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3870                                         }
3871                                         if (isset($caption['attribs']['']['end']))
3872                                         {
3873                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3874                                         }
3875                                         if (isset($caption['data']))
3876                                         {
3877                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3878                                         }
3879                                         $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3880                                 }
3881                         }
3882                         if (is_array($captions_parent))
3883                         {
3884                                 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3885                         }
3886
3887                         // CATEGORIES
3888                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3889                         {
3890                                 $term = null;
3891                                 $scheme = null;
3892                                 $label = null;
3893                                 if (isset($category['data']))
3894                                 {
3895                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3896                                 }
3897                                 if (isset($category['attribs']['']['scheme']))
3898                                 {
3899                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3900                                 }
3901                                 else
3902                                 {
3903                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3904                                 }
3905                                 if (isset($category['attribs']['']['label']))
3906                                 {
3907                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3908                                 }
3909                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3910                         }
3911                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3912                         {
3913                                 $term = null;
3914                                 $scheme = null;
3915                                 $label = null;
3916                                 if (isset($category['data']))
3917                                 {
3918                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3919                                 }
3920                                 if (isset($category['attribs']['']['scheme']))
3921                                 {
3922                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3923                                 }
3924                                 else
3925                                 {
3926                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3927                                 }
3928                                 if (isset($category['attribs']['']['label']))
3929                                 {
3930                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3931                                 }
3932                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3933                         }
3934                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3935                         {
3936                                 $term = null;
3937                                 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3938                                 $label = null;
3939                                 if (isset($category['attribs']['']['text']))
3940                                 {
3941                                         $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3942                                 }
3943                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3944
3945                                 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3946                                 {
3947                                         foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3948                                         {
3949                                                 if (isset($subcategory['attribs']['']['text']))
3950                                                 {
3951                                                         $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3952                                                 }
3953                                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3954                                         }
3955                                 }
3956                         }
3957                         if (is_array($categories_parent))
3958                         {
3959                                 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3960                         }
3961
3962                         // COPYRIGHT
3963                         if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3964                         {
3965                                 $copyright_url = null;
3966                                 $copyright_label = null;
3967                                 if (isset($copyright[0]['attribs']['']['url']))
3968                                 {
3969                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3970                                 }
3971                                 if (isset($copyright[0]['data']))
3972                                 {
3973                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3974                                 }
3975                                 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3976                         }
3977                         elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3978                         {
3979                                 $copyright_url = null;
3980                                 $copyright_label = null;
3981                                 if (isset($copyright[0]['attribs']['']['url']))
3982                                 {
3983                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3984                                 }
3985                                 if (isset($copyright[0]['data']))
3986                                 {
3987                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3988                                 }
3989                                 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3990                         }
3991
3992                         // CREDITS
3993                         if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3994                         {
3995                                 foreach ($credits as $credit)
3996                                 {
3997                                         $credit_role = null;
3998                                         $credit_scheme = null;
3999                                         $credit_name = null;
4000                                         if (isset($credit['attribs']['']['role']))
4001                                         {
4002                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4003                                         }
4004                                         if (isset($credit['attribs']['']['scheme']))
4005                                         {
4006                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4007                                         }
4008                                         else
4009                                         {
4010                                                 $credit_scheme = 'urn:ebu';
4011                                         }
4012                                         if (isset($credit['data']))
4013                                         {
4014                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4015                                         }
4016                                         $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4017                                 }
4018                         }
4019                         elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4020                         {
4021                                 foreach ($credits as $credit)
4022                                 {
4023                                         $credit_role = null;
4024                                         $credit_scheme = null;
4025                                         $credit_name = null;
4026                                         if (isset($credit['attribs']['']['role']))
4027                                         {
4028                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4029                                         }
4030                                         if (isset($credit['attribs']['']['scheme']))
4031                                         {
4032                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4033                                         }
4034                                         else
4035                                         {
4036                                                 $credit_scheme = 'urn:ebu';
4037                                         }
4038                                         if (isset($credit['data']))
4039                                         {
4040                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4041                                         }
4042                                         $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4043                                 }
4044                         }
4045                         if (is_array($credits_parent))
4046                         {
4047                                 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4048                         }
4049
4050                         // DESCRIPTION
4051                         if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4052                         {
4053                                 if (isset($description_parent[0]['data']))
4054                                 {
4055                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4056                                 }
4057                         }
4058                         elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4059                         {
4060                                 if (isset($description_parent[0]['data']))
4061                                 {
4062                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4063                                 }
4064                         }
4065
4066                         // DURATION
4067                         if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4068                         {
4069                                 $seconds = null;
4070                                 $minutes = null;
4071                                 $hours = null;
4072                                 if (isset($duration_parent[0]['data']))
4073                                 {
4074                                         $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4075                                         if (sizeof($temp) > 0)
4076                                         {
4077                                                 $seconds = (int) array_pop($temp);
4078                                         }
4079                                         if (sizeof($temp) > 0)
4080                                         {
4081                                                 $minutes = (int) array_pop($temp);
4082                                                 $seconds += $minutes * 60;
4083                                         }
4084                                         if (sizeof($temp) > 0)
4085                                         {
4086                                                 $hours = (int) array_pop($temp);
4087                                                 $seconds += $hours * 3600;
4088                                         }
4089                                         unset($temp);
4090                                         $duration_parent = $seconds;
4091                                 }
4092                         }
4093
4094                         // HASHES
4095                         if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4096                         {
4097                                 foreach ($hashes_iterator as $hash)
4098                                 {
4099                                         $value = null;
4100                                         $algo = null;
4101                                         if (isset($hash['data']))
4102                                         {
4103                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4104                                         }
4105                                         if (isset($hash['attribs']['']['algo']))
4106                                         {
4107                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4108                                         }
4109                                         else
4110                                         {
4111                                                 $algo = 'md5';
4112                                         }
4113                                         $hashes_parent[] = $algo.':'.$value;
4114                                 }
4115                         }
4116                         elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4117                         {
4118                                 foreach ($hashes_iterator as $hash)
4119                                 {
4120                                         $value = null;
4121                                         $algo = null;
4122                                         if (isset($hash['data']))
4123                                         {
4124                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4125                                         }
4126                                         if (isset($hash['attribs']['']['algo']))
4127                                         {
4128                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4129                                         }
4130                                         else
4131                                         {
4132                                                 $algo = 'md5';
4133                                         }
4134                                         $hashes_parent[] = $algo.':'.$value;
4135                                 }
4136                         }
4137                         if (is_array($hashes_parent))
4138                         {
4139                                 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4140                         }
4141
4142                         // KEYWORDS
4143                         if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4144                         {
4145                                 if (isset($keywords[0]['data']))
4146                                 {
4147                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4148                                         foreach ($temp as $word)
4149                                         {
4150                                                 $keywords_parent[] = trim($word);
4151                                         }
4152                                 }
4153                                 unset($temp);
4154                         }
4155                         elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4156                         {
4157                                 if (isset($keywords[0]['data']))
4158                                 {
4159                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4160                                         foreach ($temp as $word)
4161                                         {
4162                                                 $keywords_parent[] = trim($word);
4163                                         }
4164                                 }
4165                                 unset($temp);
4166                         }
4167                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4168                         {
4169                                 if (isset($keywords[0]['data']))
4170                                 {
4171                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4172                                         foreach ($temp as $word)
4173                                         {
4174                                                 $keywords_parent[] = trim($word);
4175                                         }
4176                                 }
4177                                 unset($temp);
4178                         }
4179                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4180                         {
4181                                 if (isset($keywords[0]['data']))
4182                                 {
4183                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4184                                         foreach ($temp as $word)
4185                                         {
4186                                                 $keywords_parent[] = trim($word);
4187                                         }
4188                                 }
4189                                 unset($temp);
4190                         }
4191                         if (is_array($keywords_parent))
4192                         {
4193                                 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4194                         }
4195
4196                         // PLAYER
4197                         if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4198                         {
4199                                 if (isset($player_parent[0]['attribs']['']['url']))
4200                                 {
4201                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4202                                 }
4203                         }
4204                         elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4205                         {
4206                                 if (isset($player_parent[0]['attribs']['']['url']))
4207                                 {
4208                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4209                                 }
4210                         }
4211
4212                         // RATINGS
4213                         if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4214                         {
4215                                 foreach ($ratings as $rating)
4216                                 {
4217                                         $rating_scheme = null;
4218                                         $rating_value = null;
4219                                         if (isset($rating['attribs']['']['scheme']))
4220                                         {
4221                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4222                                         }
4223                                         else
4224                                         {
4225                                                 $rating_scheme = 'urn:simple';
4226                                         }
4227                                         if (isset($rating['data']))
4228                                         {
4229                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4230                                         }
4231                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4232                                 }
4233                         }
4234                         elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4235                         {
4236                                 foreach ($ratings as $rating)
4237                                 {
4238                                         $rating_scheme = 'urn:itunes';
4239                                         $rating_value = null;
4240                                         if (isset($rating['data']))
4241                                         {
4242                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4243                                         }
4244                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4245                                 }
4246                         }
4247                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4248                         {
4249                                 foreach ($ratings as $rating)
4250                                 {
4251                                         $rating_scheme = null;
4252                                         $rating_value = null;
4253                                         if (isset($rating['attribs']['']['scheme']))
4254                                         {
4255                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4256                                         }
4257                                         else
4258                                         {
4259                                                 $rating_scheme = 'urn:simple';
4260                                         }
4261                                         if (isset($rating['data']))
4262                                         {
4263                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4264                                         }
4265                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4266                                 }
4267                         }
4268                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4269                         {
4270                                 foreach ($ratings as $rating)
4271                                 {
4272                                         $rating_scheme = 'urn:itunes';
4273                                         $rating_value = null;
4274                                         if (isset($rating['data']))
4275                                         {
4276                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4277                                         }
4278                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4279                                 }
4280                         }
4281                         if (is_array($ratings_parent))
4282                         {
4283                                 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4284                         }
4285
4286                         // RESTRICTIONS
4287                         if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4288                         {
4289                                 foreach ($restrictions as $restriction)
4290                                 {
4291                                         $restriction_relationship = null;
4292                                         $restriction_type = null;
4293                                         $restriction_value = null;
4294                                         if (isset($restriction['attribs']['']['relationship']))
4295                                         {
4296                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4297                                         }
4298                                         if (isset($restriction['attribs']['']['type']))
4299                                         {
4300                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4301                                         }
4302                                         if (isset($restriction['data']))
4303                                         {
4304                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4305                                         }
4306                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4307                                 }
4308                         }
4309                         elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4310                         {
4311                                 foreach ($restrictions as $restriction)
4312                                 {
4313                                         $restriction_relationship = 'allow';
4314                                         $restriction_type = null;
4315                                         $restriction_value = 'itunes';
4316                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4317                                         {
4318                                                 $restriction_relationship = 'deny';
4319                                         }
4320                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4321                                 }
4322                         }
4323                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4324                         {
4325                                 foreach ($restrictions as $restriction)
4326                                 {
4327                                         $restriction_relationship = null;
4328                                         $restriction_type = null;
4329                                         $restriction_value = null;
4330                                         if (isset($restriction['attribs']['']['relationship']))
4331                                         {
4332                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4333                                         }
4334                                         if (isset($restriction['attribs']['']['type']))
4335                                         {
4336                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4337                                         }
4338                                         if (isset($restriction['data']))
4339                                         {
4340                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4341                                         }
4342                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4343                                 }
4344                         }
4345                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4346                         {
4347                                 foreach ($restrictions as $restriction)
4348                                 {
4349                                         $restriction_relationship = 'allow';
4350                                         $restriction_type = null;
4351                                         $restriction_value = 'itunes';
4352                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4353                                         {
4354                                                 $restriction_relationship = 'deny';
4355                                         }
4356                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4357                                 }
4358                         }
4359                         if (is_array($restrictions_parent))
4360                         {
4361                                 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4362                         }
4363
4364                         // THUMBNAILS
4365                         if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4366                         {
4367                                 foreach ($thumbnails as $thumbnail)
4368                                 {
4369                                         if (isset($thumbnail['attribs']['']['url']))
4370                                         {
4371                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4372                                         }
4373                                 }
4374                         }
4375                         elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4376                         {
4377                                 foreach ($thumbnails as $thumbnail)
4378                                 {
4379                                         if (isset($thumbnail['attribs']['']['url']))
4380                                         {
4381                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4382                                         }
4383                                 }
4384                         }
4385
4386                         // TITLES
4387                         if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4388                         {
4389                                 if (isset($title_parent[0]['data']))
4390                                 {
4391                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4392                                 }
4393                         }
4394                         elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4395                         {
4396                                 if (isset($title_parent[0]['data']))
4397                                 {
4398                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4399                                 }
4400                         }
4401
4402                         // Clear the memory
4403                         unset($parent);
4404
4405                         // Attributes
4406                         $bitrate = null;
4407                         $channels = null;
4408                         $duration = null;
4409                         $expression = null;
4410                         $framerate = null;
4411                         $height = null;
4412                         $javascript = null;
4413                         $lang = null;
4414                         $length = null;
4415                         $medium = null;
4416                         $samplingrate = null;
4417                         $type = null;
4418                         $url = null;
4419                         $width = null;
4420
4421                         // Elements
4422                         $captions = null;
4423                         $categories = null;
4424                         $copyrights = null;
4425                         $credits = null;
4426                         $description = null;
4427                         $hashes = null;
4428                         $keywords = null;
4429                         $player = null;
4430                         $ratings = null;
4431                         $restrictions = null;
4432                         $thumbnails = null;
4433                         $title = null;
4434
4435                         // If we have media:group tags, loop through them.
4436                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4437                         {
4438                                 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4439                                 {
4440                                         // If we have media:content tags, loop through them.
4441                                         foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4442                                         {
4443                                                 if (isset($content['attribs']['']['url']))
4444                                                 {
4445                                                         // Attributes
4446                                                         $bitrate = null;
4447                                                         $channels = null;
4448                                                         $duration = null;
4449                                                         $expression = null;
4450                                                         $framerate = null;
4451                                                         $height = null;
4452                                                         $javascript = null;
4453                                                         $lang = null;
4454                                                         $length = null;
4455                                                         $medium = null;
4456                                                         $samplingrate = null;
4457                                                         $type = null;
4458                                                         $url = null;
4459                                                         $width = null;
4460
4461                                                         // Elements
4462                                                         $captions = null;
4463                                                         $categories = null;
4464                                                         $copyrights = null;
4465                                                         $credits = null;
4466                                                         $description = null;
4467                                                         $hashes = null;
4468                                                         $keywords = null;
4469                                                         $player = null;
4470                                                         $ratings = null;
4471                                                         $restrictions = null;
4472                                                         $thumbnails = null;
4473                                                         $title = null;
4474
4475                                                         // Start checking the attributes of media:content
4476                                                         if (isset($content['attribs']['']['bitrate']))
4477                                                         {
4478                                                                 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4479                                                         }
4480                                                         if (isset($content['attribs']['']['channels']))
4481                                                         {
4482                                                                 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4483                                                         }
4484                                                         if (isset($content['attribs']['']['duration']))
4485                                                         {
4486                                                                 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4487                                                         }
4488                                                         else
4489                                                         {
4490                                                                 $duration = $duration_parent;
4491                                                         }
4492                                                         if (isset($content['attribs']['']['expression']))
4493                                                         {
4494                                                                 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4495                                                         }
4496                                                         if (isset($content['attribs']['']['framerate']))
4497                                                         {
4498                                                                 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4499                                                         }
4500                                                         if (isset($content['attribs']['']['height']))
4501                                                         {
4502                                                                 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4503                                                         }
4504                                                         if (isset($content['attribs']['']['lang']))
4505                                                         {
4506                                                                 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4507                                                         }
4508                                                         if (isset($content['attribs']['']['fileSize']))
4509                                                         {
4510                                                                 $length = ceil($content['attribs']['']['fileSize']);
4511                                                         }
4512                                                         if (isset($content['attribs']['']['medium']))
4513                                                         {
4514                                                                 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4515                                                         }
4516                                                         if (isset($content['attribs']['']['samplingrate']))
4517                                                         {
4518                                                                 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4519                                                         }
4520                                                         if (isset($content['attribs']['']['type']))
4521                                                         {
4522                                                                 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4523                                                         }
4524                                                         if (isset($content['attribs']['']['width']))
4525                                                         {
4526                                                                 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4527                                                         }
4528                                                         $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4529
4530                                                         // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4531
4532                                                         // CAPTIONS
4533                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4534                                                         {
4535                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4536                                                                 {
4537                                                                         $caption_type = null;
4538                                                                         $caption_lang = null;
4539                                                                         $caption_startTime = null;
4540                                                                         $caption_endTime = null;
4541                                                                         $caption_text = null;
4542                                                                         if (isset($caption['attribs']['']['type']))
4543                                                                         {
4544                                                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4545                                                                         }
4546                                                                         if (isset($caption['attribs']['']['lang']))
4547                                                                         {
4548                                                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4549                                                                         }
4550                                                                         if (isset($caption['attribs']['']['start']))
4551                                                                         {
4552                                                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4553                                                                         }
4554                                                                         if (isset($caption['attribs']['']['end']))
4555                                                                         {
4556                                                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4557                                                                         }
4558                                                                         if (isset($caption['data']))
4559                                                                         {
4560                                                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4561                                                                         }
4562                                                                         $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4563                                                                 }
4564                                                                 if (is_array($captions))
4565                                                                 {
4566                                                                         $captions = array_values(SimplePie_Misc::array_unique($captions));
4567                                                                 }
4568                                                         }
4569                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4570                                                         {
4571                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4572                                                                 {
4573                                                                         $caption_type = null;
4574                                                                         $caption_lang = null;
4575                                                                         $caption_startTime = null;
4576                                                                         $caption_endTime = null;
4577                                                                         $caption_text = null;
4578                                                                         if (isset($caption['attribs']['']['type']))
4579                                                                         {
4580                                                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4581                                                                         }
4582                                                                         if (isset($caption['attribs']['']['lang']))
4583                                                                         {
4584                                                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4585                                                                         }
4586                                                                         if (isset($caption['attribs']['']['start']))
4587                                                                         {
4588                                                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4589                                                                         }
4590                                                                         if (isset($caption['attribs']['']['end']))
4591                                                                         {
4592                                                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4593                                                                         }
4594                                                                         if (isset($caption['data']))
4595                                                                         {
4596                                                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4597                                                                         }
4598                                                                         $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4599                                                                 }
4600                                                                 if (is_array($captions))
4601                                                                 {
4602                                                                         $captions = array_values(SimplePie_Misc::array_unique($captions));
4603                                                                 }
4604                                                         }
4605                                                         else
4606                                                         {
4607                                                                 $captions = $captions_parent;
4608                                                         }
4609
4610                                                         // CATEGORIES
4611                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4612                                                         {
4613                                                                 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4614                                                                 {
4615                                                                         $term = null;
4616                                                                         $scheme = null;
4617                                                                         $label = null;
4618                                                                         if (isset($category['data']))
4619                                                                         {
4620                                                                                 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4621                                                                         }
4622                                                                         if (isset($category['attribs']['']['scheme']))
4623                                                                         {
4624                                                                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4625                                                                         }
4626                                                                         else
4627                                                                         {
4628                                                                                 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4629                                                                         }
4630                                                                         if (isset($category['attribs']['']['label']))
4631                                                                         {
4632                                                                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4633                                                                         }
4634                                                                         $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4635                                                                 }
4636                                                         }
4637                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4638                                                         {
4639                                                                 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4640                                                                 {
4641                                                                         $term = null;
4642                                                                         $scheme = null;
4643                                                                         $label = null;
4644                                                                         if (isset($category['data']))
4645                                                                         {
4646                                                                                 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4647                                                                         }
4648                                                                         if (isset($category['attribs']['']['scheme']))
4649                                                                         {
4650                                                                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4651                                                                         }
4652                                                                         else
4653                                                                         {
4654                                                                                 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4655                                                                         }
4656                                                                         if (isset($category['attribs']['']['label']))
4657                                                                         {
4658                                                                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4659                                                                         }
4660                                                                         $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4661                                                                 }
4662                                                         }
4663                                                         if (is_array($categories) && is_array($categories_parent))
4664                                                         {
4665                                                                 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4666                                                         }
4667                                                         elseif (is_array($categories))
4668                                                         {
4669                                                                 $categories = array_values(SimplePie_Misc::array_unique($categories));
4670                                                         }
4671                                                         elseif (is_array($categories_parent))
4672                                                         {
4673                                                                 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4674                                                         }
4675
4676                                                         // COPYRIGHTS
4677                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4678                                                         {
4679                                                                 $copyright_url = null;
4680                                                                 $copyright_label = null;
4681                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4682                                                                 {
4683                                                                         $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4684                                                                 }
4685                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4686                                                                 {
4687                                                                         $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4688                                                                 }
4689                                                                 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4690                                                         }
4691                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4692                                                         {
4693                                                                 $copyright_url = null;
4694                                                                 $copyright_label = null;
4695                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4696                                                                 {
4697                                                                         $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4698                                                                 }
4699                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4700                                                                 {
4701                                                                         $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4702                                                                 }
4703                                                                 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4704                                                         }
4705                                                         else
4706                                                         {
4707                                                                 $copyrights = $copyrights_parent;
4708                                                         }
4709
4710                                                         // CREDITS
4711                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4712                                                         {
4713                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4714                                                                 {
4715                                                                         $credit_role = null;
4716                                                                         $credit_scheme = null;
4717                                                                         $credit_name = null;
4718                                                                         if (isset($credit['attribs']['']['role']))
4719                                                                         {
4720                                                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4721                                                                         }
4722                                                                         if (isset($credit['attribs']['']['scheme']))
4723                                                                         {
4724                                                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4725                                                                         }
4726                                                                         else
4727                                                                         {
4728                                                                                 $credit_scheme = 'urn:ebu';
4729                                                                         }
4730                                                                         if (isset($credit['data']))
4731                                                                         {
4732                                                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4733                                                                         }
4734                                                                         $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4735                                                                 }
4736                                                                 if (is_array($credits))
4737                                                                 {
4738                                                                         $credits = array_values(SimplePie_Misc::array_unique($credits));
4739                                                                 }
4740                                                         }
4741                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4742                                                         {
4743                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4744                                                                 {
4745                                                                         $credit_role = null;
4746                                                                         $credit_scheme = null;
4747                                                                         $credit_name = null;
4748                                                                         if (isset($credit['attribs']['']['role']))
4749                                                                         {
4750                                                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4751                                                                         }
4752                                                                         if (isset($credit['attribs']['']['scheme']))
4753                                                                         {
4754                                                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4755                                                                         }
4756                                                                         else
4757                                                                         {
4758                                                                                 $credit_scheme = 'urn:ebu';
4759                                                                         }
4760                                                                         if (isset($credit['data']))
4761                                                                         {
4762                                                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4763                                                                         }
4764                                                                         $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4765                                                                 }
4766                                                                 if (is_array($credits))
4767                                                                 {
4768                                                                         $credits = array_values(SimplePie_Misc::array_unique($credits));
4769                                                                 }
4770                                                         }
4771                                                         else
4772                                                         {
4773                                                                 $credits = $credits_parent;
4774                                                         }
4775
4776                                                         // DESCRIPTION
4777                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4778                                                         {
4779                                                                 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4780                                                         }
4781                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4782                                                         {
4783                                                                 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4784                                                         }
4785                                                         else
4786                                                         {
4787                                                                 $description = $description_parent;
4788                                                         }
4789
4790                                                         // HASHES
4791                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4792                                                         {
4793                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4794                                                                 {
4795                                                                         $value = null;
4796                                                                         $algo = null;
4797                                                                         if (isset($hash['data']))
4798                                                                         {
4799                                                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4800                                                                         }
4801                                                                         if (isset($hash['attribs']['']['algo']))
4802                                                                         {
4803                                                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4804                                                                         }
4805                                                                         else
4806                                                                         {
4807                                                                                 $algo = 'md5';
4808                                                                         }
4809                                                                         $hashes[] = $algo.':'.$value;
4810                                                                 }
4811                                                                 if (is_array($hashes))
4812                                                                 {
4813                                                                         $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4814                                                                 }
4815                                                         }
4816                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4817                                                         {
4818                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4819                                                                 {
4820                                                                         $value = null;
4821                                                                         $algo = null;
4822                                                                         if (isset($hash['data']))
4823                                                                         {
4824                                                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4825                                                                         }
4826                                                                         if (isset($hash['attribs']['']['algo']))
4827                                                                         {
4828                                                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4829                                                                         }
4830                                                                         else
4831                                                                         {
4832                                                                                 $algo = 'md5';
4833                                                                         }
4834                                                                         $hashes[] = $algo.':'.$value;
4835                                                                 }
4836                                                                 if (is_array($hashes))
4837                                                                 {
4838                                                                         $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4839                                                                 }
4840                                                         }
4841                                                         else
4842                                                         {
4843                                                                 $hashes = $hashes_parent;
4844                                                         }
4845
4846                                                         // KEYWORDS
4847                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4848                                                         {
4849                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4850                                                                 {
4851                                                                         $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4852                                                                         foreach ($temp as $word)
4853                                                                         {
4854                                                                                 $keywords[] = trim($word);
4855                                                                         }
4856                                                                         unset($temp);
4857                                                                 }
4858                                                                 if (is_array($keywords))
4859                                                                 {
4860                                                                         $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4861                                                                 }
4862                                                         }
4863                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4864                                                         {
4865                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4866                                                                 {
4867                                                                         $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4868                                                                         foreach ($temp as $word)
4869                                                                         {
4870                                                                                 $keywords[] = trim($word);
4871                                                                         }
4872                                                                         unset($temp);
4873                                                                 }
4874                                                                 if (is_array($keywords))
4875                                                                 {
4876                                                                         $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4877                                                                 }
4878                                                         }
4879                                                         else
4880                                                         {
4881                                                                 $keywords = $keywords_parent;
4882                                                         }
4883
4884                                                         // PLAYER
4885                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4886                                                         {
4887                                                                 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4888                                                         }
4889                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4890                                                         {
4891                                                                 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4892                                                         }
4893                                                         else
4894                                                         {
4895                                                                 $player = $player_parent;
4896                                                         }
4897
4898                                                         // RATINGS
4899                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4900                                                         {
4901                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4902                                                                 {
4903                                                                         $rating_scheme = null;
4904                                                                         $rating_value = null;
4905                                                                         if (isset($rating['attribs']['']['scheme']))
4906                                                                         {
4907                                                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4908                                                                         }
4909                                                                         else
4910                                                                         {
4911                                                                                 $rating_scheme = 'urn:simple';
4912                                                                         }
4913                                                                         if (isset($rating['data']))
4914                                                                         {
4915                                                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4916                                                                         }
4917                                                                         $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4918                                                                 }
4919                                                                 if (is_array($ratings))
4920                                                                 {
4921                                                                         $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4922                                                                 }
4923                                                         }
4924                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4925                                                         {
4926                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4927                                                                 {
4928                                                                         $rating_scheme = null;
4929                                                                         $rating_value = null;
4930                                                                         if (isset($rating['attribs']['']['scheme']))
4931                                                                         {
4932                                                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4933                                                                         }
4934                                                                         else
4935                                                                         {
4936                                                                                 $rating_scheme = 'urn:simple';
4937                                                                         }
4938                                                                         if (isset($rating['data']))
4939                                                                         {
4940                                                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4941                                                                         }
4942                                                                         $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4943                                                                 }
4944                                                                 if (is_array($ratings))
4945                                                                 {
4946                                                                         $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4947                                                                 }
4948                                                         }
4949                                                         else
4950                                                         {
4951                                                                 $ratings = $ratings_parent;
4952                                                         }
4953
4954                                                         // RESTRICTIONS
4955                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4956                                                         {
4957                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4958                                                                 {
4959                                                                         $restriction_relationship = null;
4960                                                                         $restriction_type = null;
4961                                                                         $restriction_value = null;
4962                                                                         if (isset($restriction['attribs']['']['relationship']))
4963                                                                         {
4964                                                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4965                                                                         }
4966                                                                         if (isset($restriction['attribs']['']['type']))
4967                                                                         {
4968                                                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4969                                                                         }
4970                                                                         if (isset($restriction['data']))
4971                                                                         {
4972                                                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4973                                                                         }
4974                                                                         $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4975                                                                 }
4976                                                                 if (is_array($restrictions))
4977                                                                 {
4978                                                                         $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4979                                                                 }
4980                                                         }
4981                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4982                                                         {
4983                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4984                                                                 {
4985                                                                         $restriction_relationship = null;
4986                                                                         $restriction_type = null;
4987                                                                         $restriction_value = null;
4988                                                                         if (isset($restriction['attribs']['']['relationship']))
4989                                                                         {
4990                                                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4991                                                                         }
4992                                                                         if (isset($restriction['attribs']['']['type']))
4993                                                                         {
4994                                                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4995                                                                         }
4996                                                                         if (isset($restriction['data']))
4997                                                                         {
4998                                                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4999                                                                         }
5000                                                                         $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5001                                                                 }
5002                                                                 if (is_array($restrictions))
5003                                                                 {
5004                                                                         $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5005                                                                 }
5006                                                         }
5007                                                         else
5008                                                         {
5009                                                                 $restrictions = $restrictions_parent;
5010                                                         }
5011
5012                                                         // THUMBNAILS
5013                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5014                                                         {
5015                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5016                                                                 {
5017                                                                         $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5018                                                                 }
5019                                                                 if (is_array($thumbnails))
5020                                                                 {
5021                                                                         $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5022                                                                 }
5023                                                         }
5024                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5025                                                         {
5026                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5027                                                                 {
5028                                                                         $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5029                                                                 }
5030                                                                 if (is_array($thumbnails))
5031                                                                 {
5032                                                                         $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5033                                                                 }
5034                                                         }
5035                                                         else
5036                                                         {
5037                                                                 $thumbnails = $thumbnails_parent;
5038                                                         }
5039
5040                                                         // TITLES
5041                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5042                                                         {
5043                                                                 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5044                                                         }
5045                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5046                                                         {
5047                                                                 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5048                                                         }
5049                                                         else
5050                                                         {
5051                                                                 $title = $title_parent;
5052                                                         }
5053
5054                                                         $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
5055                                                 }
5056                                         }
5057                                 }
5058                         }
5059
5060                         // If we have standalone media:content tags, loop through them.
5061                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5062                         {
5063                                 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5064                                 {
5065                                         if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5066                                         {
5067                                                 // Attributes
5068                                                 $bitrate = null;
5069                                                 $channels = null;
5070                                                 $duration = null;
5071                                                 $expression = null;
5072                                                 $framerate = null;
5073                                                 $height = null;
5074                                                 $javascript = null;
5075                                                 $lang = null;
5076                                                 $length = null;
5077                                                 $medium = null;
5078                                                 $samplingrate = null;
5079                                                 $type = null;
5080                                                 $url = null;
5081                                                 $width = null;
5082
5083                                                 // Elements
5084                                                 $captions = null;
5085                                                 $categories = null;
5086                                                 $copyrights = null;
5087                                                 $credits = null;
5088                                                 $description = null;
5089                                                 $hashes = null;
5090                                                 $keywords = null;
5091                                                 $player = null;
5092                                                 $ratings = null;
5093                                                 $restrictions = null;
5094                                                 $thumbnails = null;
5095                                                 $title = null;
5096
5097                                                 // Start checking the attributes of media:content
5098                                                 if (isset($content['attribs']['']['bitrate']))
5099                                                 {
5100                                                         $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5101                                                 }
5102                                                 if (isset($content['attribs']['']['channels']))
5103                                                 {
5104                                                         $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5105                                                 }
5106                                                 if (isset($content['attribs']['']['duration']))
5107                                                 {
5108                                                         $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5109                                                 }
5110                                                 else
5111                                                 {
5112                                                         $duration = $duration_parent;
5113                                                 }
5114                                                 if (isset($content['attribs']['']['expression']))
5115                                                 {
5116                                                         $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5117                                                 }
5118                                                 if (isset($content['attribs']['']['framerate']))
5119                                                 {
5120                                                         $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5121                                                 }
5122                                                 if (isset($content['attribs']['']['height']))
5123                                                 {
5124                                                         $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5125                                                 }
5126                                                 if (isset($content['attribs']['']['lang']))
5127                                                 {
5128                                                         $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5129                                                 }
5130                                                 if (isset($content['attribs']['']['fileSize']))
5131                                                 {
5132                                                         $length = ceil($content['attribs']['']['fileSize']);
5133                                                 }
5134                                                 if (isset($content['attribs']['']['medium']))
5135                                                 {
5136                                                         $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5137                                                 }
5138                                                 if (isset($content['attribs']['']['samplingrate']))
5139                                                 {
5140                                                         $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5141                                                 }
5142                                                 if (isset($content['attribs']['']['type']))
5143                                                 {
5144                                                         $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5145                                                 }
5146                                                 if (isset($content['attribs']['']['width']))
5147                                                 {
5148                                                         $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5149                                                 }
5150                                                 if (isset($content['attribs']['']['url']))
5151                                                 {
5152                                                         $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5153                                                 }
5154                                                 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5155
5156                                                 // CAPTIONS
5157                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5158                                                 {
5159                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5160                                                         {
5161                                                                 $caption_type = null;
5162                                                                 $caption_lang = null;
5163                                                                 $caption_startTime = null;
5164                                                                 $caption_endTime = null;
5165                                                                 $caption_text = null;
5166                                                                 if (isset($caption['attribs']['']['type']))
5167                                                                 {
5168                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5169                                                                 }
5170                                                                 if (isset($caption['attribs']['']['lang']))
5171                                                                 {
5172                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5173                                                                 }
5174                                                                 if (isset($caption['attribs']['']['start']))
5175                                                                 {
5176                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5177                                                                 }
5178                                                                 if (isset($caption['attribs']['']['end']))
5179                                                                 {
5180                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5181                                                                 }
5182                                                                 if (isset($caption['data']))
5183                                                                 {
5184                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5185                                                                 }
5186                                                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5187                                                         }
5188                                                         if (is_array($captions))
5189                                                         {
5190                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
5191                                                         }
5192                                                 }
5193                                                 else
5194                                                 {
5195                                                         $captions = $captions_parent;
5196                                                 }
5197
5198                                                 // CATEGORIES
5199                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5200                                                 {
5201                                                         foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5202                                                         {
5203                                                                 $term = null;
5204                                                                 $scheme = null;
5205                                                                 $label = null;
5206                                                                 if (isset($category['data']))
5207                                                                 {
5208                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5209                                                                 }
5210                                                                 if (isset($category['attribs']['']['scheme']))
5211                                                                 {
5212                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5213                                                                 }
5214                                                                 else
5215                                                                 {
5216                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
5217                                                                 }
5218                                                                 if (isset($category['attribs']['']['label']))
5219                                                                 {
5220                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5221                                                                 }
5222                                                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
5223                                                         }
5224                                                 }
5225                                                 if (is_array($categories) && is_array($categories_parent))
5226                                                 {
5227                                                         $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5228                                                 }
5229                                                 elseif (is_array($categories))
5230                                                 {
5231                                                         $categories = array_values(SimplePie_Misc::array_unique($categories));
5232                                                 }
5233                                                 elseif (is_array($categories_parent))
5234                                                 {
5235                                                         $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5236                                                 }
5237                                                 else
5238                                                 {
5239                                                         $categories = null;
5240                                                 }
5241
5242                                                 // COPYRIGHTS
5243                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5244                                                 {
5245                                                         $copyright_url = null;
5246                                                         $copyright_label = null;
5247                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5248                                                         {
5249                                                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5250                                                         }
5251                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5252                                                         {
5253                                                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5254                                                         }
5255                                                         $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
5256                                                 }
5257                                                 else
5258                                                 {
5259                                                         $copyrights = $copyrights_parent;
5260                                                 }
5261
5262                                                 // CREDITS
5263                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5264                                                 {
5265                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5266                                                         {
5267                                                                 $credit_role = null;
5268                                                                 $credit_scheme = null;
5269                                                                 $credit_name = null;
5270                                                                 if (isset($credit['attribs']['']['role']))
5271                                                                 {
5272                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5273                                                                 }
5274                                                                 if (isset($credit['attribs']['']['scheme']))
5275                                                                 {
5276                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5277                                                                 }
5278                                                                 else
5279                                                                 {
5280                                                                         $credit_scheme = 'urn:ebu';
5281                                                                 }
5282                                                                 if (isset($credit['data']))
5283                                                                 {
5284                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5285                                                                 }
5286                                                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5287                                                         }
5288                                                         if (is_array($credits))
5289                                                         {
5290                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
5291                                                         }
5292                                                 }
5293                                                 else
5294                                                 {
5295                                                         $credits = $credits_parent;
5296                                                 }
5297
5298                                                 // DESCRIPTION
5299                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5300                                                 {
5301                                                         $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5302                                                 }
5303                                                 else
5304                                                 {
5305                                                         $description = $description_parent;
5306                                                 }
5307
5308                                                 // HASHES
5309                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5310                                                 {
5311                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5312                                                         {
5313                                                                 $value = null;
5314                                                                 $algo = null;
5315                                                                 if (isset($hash['data']))
5316                                                                 {
5317                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5318                                                                 }
5319                                                                 if (isset($hash['attribs']['']['algo']))
5320                                                                 {
5321                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5322                                                                 }
5323                                                                 else
5324                                                                 {
5325                                                                         $algo = 'md5';
5326                                                                 }
5327                                                                 $hashes[] = $algo.':'.$value;
5328                                                         }
5329                                                         if (is_array($hashes))
5330                                                         {
5331                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5332                                                         }
5333                                                 }
5334                                                 else
5335                                                 {
5336                                                         $hashes = $hashes_parent;
5337                                                 }
5338
5339                                                 // KEYWORDS
5340                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5341                                                 {
5342                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5343                                                         {
5344                                                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5345                                                                 foreach ($temp as $word)
5346                                                                 {
5347                                                                         $keywords[] = trim($word);
5348                                                                 }
5349                                                                 unset($temp);
5350                                                         }
5351                                                         if (is_array($keywords))
5352                                                         {
5353                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5354                                                         }
5355                                                 }
5356                                                 else
5357                                                 {
5358                                                         $keywords = $keywords_parent;
5359                                                 }
5360
5361                                                 // PLAYER
5362                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5363                                                 {
5364                                                         $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5365                                                 }
5366                                                 else
5367                                                 {
5368                                                         $player = $player_parent;
5369                                                 }
5370
5371                                                 // RATINGS
5372                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5373                                                 {
5374                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5375                                                         {
5376                                                                 $rating_scheme = null;
5377                                                                 $rating_value = null;
5378                                                                 if (isset($rating['attribs']['']['scheme']))
5379                                                                 {
5380                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5381                                                                 }
5382                                                                 else
5383                                                                 {
5384                                                                         $rating_scheme = 'urn:simple';
5385                                                                 }
5386                                                                 if (isset($rating['data']))
5387                                                                 {
5388                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5389                                                                 }
5390                                                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
5391                                                         }
5392                                                         if (is_array($ratings))
5393                                                         {
5394                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5395                                                         }
5396                                                 }
5397                                                 else
5398                                                 {
5399                                                         $ratings = $ratings_parent;
5400                                                 }
5401
5402                                                 // RESTRICTIONS
5403                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5404                                                 {
5405                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5406                                                         {
5407                                                                 $restriction_relationship = null;
5408                                                                 $restriction_type = null;
5409                                                                 $restriction_value = null;
5410                                                                 if (isset($restriction['attribs']['']['relationship']))
5411                                                                 {
5412                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5413                                                                 }
5414                                                                 if (isset($restriction['attribs']['']['type']))
5415                                                                 {
5416                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5417                                                                 }
5418                                                                 if (isset($restriction['data']))
5419                                                                 {
5420                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5421                                                                 }
5422                                                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5423                                                         }
5424                                                         if (is_array($restrictions))
5425                                                         {
5426                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5427                                                         }
5428                                                 }
5429                                                 else
5430                                                 {
5431                                                         $restrictions = $restrictions_parent;
5432                                                 }
5433
5434                                                 // THUMBNAILS
5435                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5436                                                 {
5437                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5438                                                         {
5439                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5440                                                         }
5441                                                         if (is_array($thumbnails))
5442                                                         {
5443                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5444                                                         }
5445                                                 }
5446                                                 else
5447                                                 {
5448                                                         $thumbnails = $thumbnails_parent;
5449                                                 }
5450
5451                                                 // TITLES
5452                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5453                                                 {
5454                                                         $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5455                                                 }
5456                                                 else
5457                                                 {
5458                                                         $title = $title_parent;
5459                                                 }
5460
5461                                                 $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
5462                                         }
5463                                 }
5464                         }
5465
5466                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5467                         {
5468                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5469                                 {
5470                                         // Attributes
5471                                         $bitrate = null;
5472                                         $channels = null;
5473                                         $duration = null;
5474                                         $expression = null;
5475                                         $framerate = null;
5476                                         $height = null;
5477                                         $javascript = null;
5478                                         $lang = null;
5479                                         $length = null;
5480                                         $medium = null;
5481                                         $samplingrate = null;
5482                                         $type = null;
5483                                         $url = null;
5484                                         $width = null;
5485
5486                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5487                                         if (isset($link['attribs']['']['type']))
5488                                         {
5489                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5490                                         }
5491                                         if (isset($link['attribs']['']['length']))
5492                                         {
5493                                                 $length = ceil($link['attribs']['']['length']);
5494                                         }
5495
5496                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5497                                         $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5498                                 }
5499                         }
5500
5501                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5502                         {
5503                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5504                                 {
5505                                         // Attributes
5506                                         $bitrate = null;
5507                                         $channels = null;
5508                                         $duration = null;
5509                                         $expression = null;
5510                                         $framerate = null;
5511                                         $height = null;
5512                                         $javascript = null;
5513                                         $lang = null;
5514                                         $length = null;
5515                                         $medium = null;
5516                                         $samplingrate = null;
5517                                         $type = null;
5518                                         $url = null;
5519                                         $width = null;
5520
5521                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5522                                         if (isset($link['attribs']['']['type']))
5523                                         {
5524                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5525                                         }
5526                                         if (isset($link['attribs']['']['length']))
5527                                         {
5528                                                 $length = ceil($link['attribs']['']['length']);
5529                                         }
5530
5531                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5532                                         $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5533                                 }
5534                         }
5535
5536                         if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5537                         {
5538                                 if (isset($enclosure[0]['attribs']['']['url']))
5539                                 {
5540                                         // Attributes
5541                                         $bitrate = null;
5542                                         $channels = null;
5543                                         $duration = null;
5544                                         $expression = null;
5545                                         $framerate = null;
5546                                         $height = null;
5547                                         $javascript = null;
5548                                         $lang = null;
5549                                         $length = null;
5550                                         $medium = null;
5551                                         $samplingrate = null;
5552                                         $type = null;
5553                                         $url = null;
5554                                         $width = null;
5555
5556                                         $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5557                                         if (isset($enclosure[0]['attribs']['']['type']))
5558                                         {
5559                                                 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5560                                         }
5561                                         if (isset($enclosure[0]['attribs']['']['length']))
5562                                         {
5563                                                 $length = ceil($enclosure[0]['attribs']['']['length']);
5564                                         }
5565
5566                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5567                                         $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5568                                 }
5569                         }
5570
5571                         if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))
5572                         {
5573                                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5574                                 $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5575                         }
5576
5577                         $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5578                 }
5579                 if (!empty($this->data['enclosures']))
5580                 {
5581                         return $this->data['enclosures'];
5582                 }
5583                 else
5584                 {
5585                         return null;
5586                 }
5587         }
5588
5589         function get_latitude()
5590         {
5591                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5592                 {
5593                         return (float) $return[0]['data'];
5594                 }
5595                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5596                 {
5597                         return (float) $match[1];
5598                 }
5599                 else
5600                 {
5601                         return null;
5602                 }
5603         }
5604
5605         function get_longitude()
5606         {
5607                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5608                 {
5609                         return (float) $return[0]['data'];
5610                 }
5611                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5612                 {
5613                         return (float) $return[0]['data'];
5614                 }
5615                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5616                 {
5617                         return (float) $match[2];
5618                 }
5619                 else
5620                 {
5621                         return null;
5622                 }
5623         }
5624
5625         function get_source()
5626         {
5627                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5628                 {
5629                         return new $this->feed->source_class($this, $return[0]);
5630                 }
5631                 else
5632                 {
5633                         return null;
5634                 }
5635         }
5636
5637         /**
5638          * Creates the add_to_* methods' return data
5639          *
5640          * @access private
5641          * @param string $item_url String to prefix to the item permalink
5642          * @param string $title_url String to prefix to the item title
5643          * (and suffix to the item permalink)
5644          * @return mixed URL if feed exists, false otherwise
5645          */
5646         function add_to_service($item_url, $title_url = null, $summary_url = null)
5647         {
5648                 if ($this->get_permalink() !== null)
5649                 {
5650                         $return = $item_url . rawurlencode($this->get_permalink());
5651                         if ($title_url !== null && $this->get_title() !== null)
5652                         {
5653                                 $return .= $title_url . rawurlencode($this->get_title());
5654                         }
5655                         if ($summary_url !== null && $this->get_description() !== null)
5656                         {
5657                                 $return .= $summary_url . rawurlencode($this->get_description());
5658                         }
5659                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5660                 }
5661                 else
5662                 {
5663                         return null;
5664                 }
5665         }
5666
5667         function add_to_blinklist()
5668         {
5669                 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5670         }
5671
5672         function add_to_blogmarks()
5673         {
5674                 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5675         }
5676
5677         function add_to_delicious()
5678         {
5679                 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5680         }
5681
5682         function add_to_digg()
5683         {
5684                 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5685         }
5686
5687         function add_to_furl()
5688         {
5689                 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5690         }
5691
5692         function add_to_magnolia()
5693         {
5694                 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5695         }
5696
5697         function add_to_myweb20()
5698         {
5699                 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5700         }
5701
5702         function add_to_newsvine()
5703         {
5704                 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5705         }
5706
5707         function add_to_reddit()
5708         {
5709                 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5710         }
5711
5712         function add_to_segnalo()
5713         {
5714                 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5715         }
5716
5717         function add_to_simpy()
5718         {
5719                 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5720         }
5721
5722         function add_to_spurl()
5723         {
5724                 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5725         }
5726
5727         function add_to_wists()
5728         {
5729                 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5730         }
5731
5732         function search_technorati()
5733         {
5734                 return $this->add_to_service('http://www.technorati.com/search/');
5735         }
5736 }
5737
5738 class SimplePie_Source
5739 {
5740         var $item;
5741         var $data = array();
5742
5743         function SimplePie_Source($item, $data)
5744         {
5745                 $this->item = $item;
5746                 $this->data = $data;
5747         }
5748
5749         function __toString()
5750         {
5751                 return md5(serialize($this->data));
5752         }
5753
5754         function get_source_tags($namespace, $tag)
5755         {
5756                 if (isset($this->data['child'][$namespace][$tag]))
5757                 {
5758                         return $this->data['child'][$namespace][$tag];
5759                 }
5760                 else
5761                 {
5762                         return null;
5763                 }
5764         }
5765
5766         function get_base($element = array())
5767         {
5768                 return $this->item->get_base($element);
5769         }
5770
5771         function sanitize($data, $type, $base = '')
5772         {
5773                 return $this->item->sanitize($data, $type, $base);
5774         }
5775
5776         function get_item()
5777         {
5778                 return $this->item;
5779         }
5780
5781         function get_title()
5782         {
5783                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5784                 {
5785                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5786                 }
5787                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5788                 {
5789                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5790                 }
5791                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5792                 {
5793                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5794                 }
5795                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5796                 {
5797                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5798                 }
5799                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5800                 {
5801                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5802                 }
5803                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5804                 {
5805                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5806                 }
5807                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5808                 {
5809                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5810                 }
5811                 else
5812                 {
5813                         return null;
5814                 }
5815         }
5816
5817         function get_category($key = 0)
5818         {
5819                 $categories = $this->get_categories();
5820                 if (isset($categories[$key]))
5821                 {
5822                         return $categories[$key];
5823                 }
5824                 else
5825                 {
5826                         return null;
5827                 }
5828         }
5829
5830         function get_categories()
5831         {
5832                 $categories = array();
5833
5834                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5835                 {
5836                         $term = null;
5837                         $scheme = null;
5838                         $label = null;
5839                         if (isset($category['attribs']['']['term']))
5840                         {
5841                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5842                         }
5843                         if (isset($category['attribs']['']['scheme']))
5844                         {
5845                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5846                         }
5847                         if (isset($category['attribs']['']['label']))
5848                         {
5849                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5850                         }
5851                         $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
5852                 }
5853                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5854                 {
5855                         // This is really the label, but keep this as the term also for BC.
5856                         // Label will also work on retrieving because that falls back to term.
5857                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5858                         if (isset($category['attribs']['']['domain']))
5859                         {
5860                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5861                         }
5862                         else
5863                         {
5864                                 $scheme = null;
5865                         }
5866                         $categories[] =& new $this->item->feed->category_class($term, $scheme, null);
5867                 }
5868                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5869                 {
5870                         $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5871                 }
5872                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5873                 {
5874                         $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5875                 }
5876
5877                 if (!empty($categories))
5878                 {
5879                         return SimplePie_Misc::array_unique($categories);
5880                 }
5881                 else
5882                 {
5883                         return null;
5884                 }
5885         }
5886
5887         function get_author($key = 0)
5888         {
5889                 $authors = $this->get_authors();
5890                 if (isset($authors[$key]))
5891                 {
5892                         return $authors[$key];
5893                 }
5894                 else
5895                 {
5896                         return null;
5897                 }
5898         }
5899
5900         function get_authors()
5901         {
5902                 $authors = array();
5903                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5904                 {
5905                         $name = null;
5906                         $uri = null;
5907                         $email = null;
5908                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5909                         {
5910                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5911                         }
5912                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5913                         {
5914                                 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
5915                         }
5916                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5917                         {
5918                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5919                         }
5920                         if ($name !== null || $email !== null || $uri !== null)
5921                         {
5922                                 $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
5923                         }
5924                 }
5925                 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5926                 {
5927                         $name = null;
5928                         $url = null;
5929                         $email = null;
5930                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5931                         {
5932                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5933                         }
5934                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5935                         {
5936                                 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
5937                         }
5938                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5939                         {
5940                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5941                         }
5942                         if ($name !== null || $email !== null || $url !== null)
5943                         {
5944                                 $authors[] =& new $this->item->feed->author_class($name, $url, $email);
5945                         }
5946                 }
5947                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5948                 {
5949                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5950                 }
5951                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5952                 {
5953                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5954                 }
5955                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5956                 {
5957                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5958                 }
5959
5960                 if (!empty($authors))
5961                 {
5962                         return SimplePie_Misc::array_unique($authors);
5963                 }
5964                 else
5965                 {
5966                         return null;
5967                 }
5968         }
5969
5970         function get_contributor($key = 0)
5971         {
5972                 $contributors = $this->get_contributors();
5973                 if (isset($contributors[$key]))
5974                 {
5975                         return $contributors[$key];
5976                 }
5977                 else
5978                 {
5979                         return null;
5980                 }
5981         }
5982
5983         function get_contributors()
5984         {
5985                 $contributors = array();
5986                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5987                 {
5988                         $name = null;
5989                         $uri = null;
5990                         $email = null;
5991                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5992                         {
5993                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5994                         }
5995                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5996                         {
5997                                 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
5998                         }
5999                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
6000                         {
6001                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6002                         }
6003                         if ($name !== null || $email !== null || $uri !== null)
6004                         {
6005                                 $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
6006                         }
6007                 }
6008                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6009                 {
6010                         $name = null;
6011                         $url = null;
6012                         $email = null;
6013                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6014                         {
6015                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6016                         }
6017                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6018                         {
6019                                 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
6020                         }
6021                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6022                         {
6023                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6024                         }
6025                         if ($name !== null || $email !== null || $url !== null)
6026                         {
6027                                 $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
6028                         }
6029                 }
6030
6031                 if (!empty($contributors))
6032                 {
6033                         return SimplePie_Misc::array_unique($contributors);
6034                 }
6035                 else
6036                 {
6037                         return null;
6038                 }
6039         }
6040
6041         function get_link($key = 0, $rel = 'alternate')
6042         {
6043                 $links = $this->get_links($rel);
6044                 if (isset($links[$key]))
6045                 {
6046                         return $links[$key];
6047                 }
6048                 else
6049                 {
6050                         return null;
6051                 }
6052         }
6053
6054         /**
6055          * Added for parity between the parent-level and the item/entry-level.
6056          */
6057         function get_permalink()
6058         {
6059                 return $this->get_link(0);
6060         }
6061
6062         function get_links($rel = 'alternate')
6063         {
6064                 if (!isset($this->data['links']))
6065                 {
6066                         $this->data['links'] = array();
6067                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6068                         {
6069                                 foreach ($links as $link)
6070                                 {
6071                                         if (isset($link['attribs']['']['href']))
6072                                         {
6073                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6074                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6075                                         }
6076                                 }
6077                         }
6078                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6079                         {
6080                                 foreach ($links as $link)
6081                                 {
6082                                         if (isset($link['attribs']['']['href']))
6083                                         {
6084                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6085                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6086
6087                                         }
6088                                 }
6089                         }
6090                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6091                         {
6092                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6093                         }
6094                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6095                         {
6096                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6097                         }
6098                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6099                         {
6100                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6101                         }
6102
6103                         $keys = array_keys($this->data['links']);
6104                         foreach ($keys as $key)
6105                         {
6106                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
6107                                 {
6108                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6109                                         {
6110                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6111                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6112                                         }
6113                                         else
6114                                         {
6115                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6116                                         }
6117                                 }
6118                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6119                                 {
6120                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6121                                 }
6122                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6123                         }
6124                 }
6125
6126                 if (isset($this->data['links'][$rel]))
6127                 {
6128                         return $this->data['links'][$rel];
6129                 }
6130                 else
6131                 {
6132                         return null;
6133                 }
6134         }
6135
6136         function get_description()
6137         {
6138                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6139                 {
6140                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6141                 }
6142                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6143                 {
6144                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6145                 }
6146                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6147                 {
6148                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6149                 }
6150                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6151                 {
6152                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6153                 }
6154                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6155                 {
6156                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6157                 }
6158                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6159                 {
6160                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6161                 }
6162                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6163                 {
6164                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6165                 }
6166                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6167                 {
6168                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6169                 }
6170                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6171                 {
6172                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6173                 }
6174                 else
6175                 {
6176                         return null;
6177                 }
6178         }
6179
6180         function get_copyright()
6181         {
6182                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6183                 {
6184                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6185                 }
6186                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6187                 {
6188                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6189                 }
6190                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6191                 {
6192                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6193                 }
6194                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6195                 {
6196                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6197                 }
6198                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6199                 {
6200                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6201                 }
6202                 else
6203                 {
6204                         return null;
6205                 }
6206         }
6207
6208         function get_language()
6209         {
6210                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6211                 {
6212                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6213                 }
6214                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6215                 {
6216                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6217                 }
6218                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6219                 {
6220                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6221                 }
6222                 elseif (isset($this->data['xml_lang']))
6223                 {
6224                         return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6225                 }
6226                 else
6227                 {
6228                         return null;
6229                 }
6230         }
6231
6232         function get_latitude()
6233         {
6234                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6235                 {
6236                         return (float) $return[0]['data'];
6237                 }
6238                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6239                 {
6240                         return (float) $match[1];
6241                 }
6242                 else
6243                 {
6244                         return null;
6245                 }
6246         }
6247
6248         function get_longitude()
6249         {
6250                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6251                 {
6252                         return (float) $return[0]['data'];
6253                 }
6254                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6255                 {
6256                         return (float) $return[0]['data'];
6257                 }
6258                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6259                 {
6260                         return (float) $match[2];
6261                 }
6262                 else
6263                 {
6264                         return null;
6265                 }
6266         }
6267
6268         function get_image_url()
6269         {
6270                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6271                 {
6272                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6273                 }
6274                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6275                 {
6276                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6277                 }
6278                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6279                 {
6280                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6281                 }
6282                 else
6283                 {
6284                         return null;
6285                 }
6286         }
6287 }
6288
6289 class SimplePie_Author
6290 {
6291         var $name;
6292         var $link;
6293         var $email;
6294
6295         // Constructor, used to input the data
6296         function SimplePie_Author($name = null, $link = null, $email = null)
6297         {
6298                 $this->name = $name;
6299                 $this->link = $link;
6300                 $this->email = $email;
6301         }
6302
6303         function __toString()
6304         {
6305                 // There is no $this->data here
6306                 return md5(serialize($this));
6307         }
6308
6309         function get_name()
6310         {
6311                 if ($this->name !== null)
6312                 {
6313                         return $this->name;
6314                 }
6315                 else
6316                 {
6317                         return null;
6318                 }
6319         }
6320
6321         function get_link()
6322         {
6323                 if ($this->link !== null)
6324                 {
6325                         return $this->link;
6326                 }
6327                 else
6328                 {
6329                         return null;
6330                 }
6331         }
6332
6333         function get_email()
6334         {
6335                 if ($this->email !== null)
6336                 {
6337                         return $this->email;
6338                 }
6339                 else
6340                 {
6341                         return null;
6342                 }
6343         }
6344 }
6345
6346 class SimplePie_Category
6347 {
6348         var $term;
6349         var $scheme;
6350         var $label;
6351
6352         // Constructor, used to input the data
6353         function SimplePie_Category($term = null, $scheme = null, $label = null)
6354         {
6355                 $this->term = $term;
6356                 $this->scheme = $scheme;
6357                 $this->label = $label;
6358         }
6359
6360         function __toString()
6361         {
6362                 // There is no $this->data here
6363                 return md5(serialize($this));
6364         }
6365
6366         function get_term()
6367         {
6368                 if ($this->term !== null)
6369                 {
6370                         return $this->term;
6371                 }
6372                 else
6373                 {
6374                         return null;
6375                 }
6376         }
6377
6378         function get_scheme()
6379         {
6380                 if ($this->scheme !== null)
6381                 {
6382                         return $this->scheme;
6383                 }
6384                 else
6385                 {
6386                         return null;
6387                 }
6388         }
6389
6390         function get_label()
6391         {
6392                 if ($this->label !== null)
6393                 {
6394                         return $this->label;
6395                 }
6396                 else
6397                 {
6398                         return $this->get_term();
6399                 }
6400         }
6401 }
6402
6403 class SimplePie_Enclosure
6404 {
6405         var $bitrate;
6406         var $captions;
6407         var $categories;
6408         var $channels;
6409         var $copyright;
6410         var $credits;
6411         var $description;
6412         var $duration;
6413         var $expression;
6414         var $framerate;
6415         var $handler;
6416         var $hashes;
6417         var $height;
6418         var $javascript;
6419         var $keywords;
6420         var $lang;
6421         var $length;
6422         var $link;
6423         var $medium;
6424         var $player;
6425         var $ratings;
6426         var $restrictions;
6427         var $samplingrate;
6428         var $thumbnails;
6429         var $title;
6430         var $type;
6431         var $width;
6432
6433         // Constructor, used to input the data
6434         function SimplePie_Enclosure($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
6435         {
6436                 $this->bitrate = $bitrate;
6437                 $this->captions = $captions;
6438                 $this->categories = $categories;
6439                 $this->channels = $channels;
6440                 $this->copyright = $copyright;
6441                 $this->credits = $credits;
6442                 $this->description = $description;
6443                 $this->duration = $duration;
6444                 $this->expression = $expression;
6445                 $this->framerate = $framerate;
6446                 $this->hashes = $hashes;
6447                 $this->height = $height;
6448                 $this->javascript = $javascript;
6449                 $this->keywords = $keywords;
6450                 $this->lang = $lang;
6451                 $this->length = $length;
6452                 $this->link = $link;
6453                 $this->medium = $medium;
6454                 $this->player = $player;
6455                 $this->ratings = $ratings;
6456                 $this->restrictions = $restrictions;
6457                 $this->samplingrate = $samplingrate;
6458                 $this->thumbnails = $thumbnails;
6459                 $this->title = $title;
6460                 $this->type = $type;
6461                 $this->width = $width;
6462                 if (class_exists('idna_convert'))
6463                 {
6464                         $idn =& new idna_convert;
6465                         $parsed = SimplePie_Misc::parse_url($link);
6466                         $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6467                 }
6468                 $this->handler = $this->get_handler(); // Needs to load last
6469         }
6470
6471         function __toString()
6472         {
6473                 // There is no $this->data here
6474                 return md5(serialize($this));
6475         }
6476
6477         function get_bitrate()
6478         {
6479                 if ($this->bitrate !== null)
6480                 {
6481                         return $this->bitrate;
6482                 }
6483                 else
6484                 {
6485                         return null;
6486                 }
6487         }
6488
6489         function get_caption($key = 0)
6490         {
6491                 $captions = $this->get_captions();
6492                 if (isset($captions[$key]))
6493                 {
6494                         return $captions[$key];
6495                 }
6496                 else
6497                 {
6498                         return null;
6499                 }
6500         }
6501
6502         function get_captions()
6503         {
6504                 if ($this->captions !== null)
6505                 {
6506                         return $this->captions;
6507                 }
6508                 else
6509                 {
6510                         return null;
6511                 }
6512         }
6513
6514         function get_category($key = 0)
6515         {
6516                 $categories = $this->get_categories();
6517                 if (isset($categories[$key]))
6518                 {
6519                         return $categories[$key];
6520                 }
6521                 else
6522                 {
6523                         return null;
6524                 }
6525         }
6526
6527         function get_categories()
6528         {
6529                 if ($this->categories !== null)
6530                 {
6531                         return $this->categories;
6532                 }
6533                 else
6534                 {
6535                         return null;
6536                 }
6537         }
6538
6539         function get_channels()
6540         {
6541                 if ($this->channels !== null)
6542                 {
6543                         return $this->channels;
6544                 }
6545                 else
6546                 {
6547                         return null;
6548                 }
6549         }
6550
6551         function get_copyright()
6552         {
6553                 if ($this->copyright !== null)
6554                 {
6555                         return $this->copyright;
6556                 }
6557                 else
6558                 {
6559                         return null;
6560                 }
6561         }
6562
6563         function get_credit($key = 0)
6564         {
6565                 $credits = $this->get_credits();
6566                 if (isset($credits[$key]))
6567                 {
6568                         return $credits[$key];
6569                 }
6570                 else
6571                 {
6572                         return null;
6573                 }
6574         }
6575
6576         function get_credits()
6577         {
6578                 if ($this->credits !== null)
6579                 {
6580                         return $this->credits;
6581                 }
6582                 else
6583                 {
6584                         return null;
6585                 }
6586         }
6587
6588         function get_description()
6589         {
6590                 if ($this->description !== null)
6591                 {
6592                         return $this->description;
6593                 }
6594                 else
6595                 {
6596                         return null;
6597                 }
6598         }
6599
6600         function get_duration($convert = false)
6601         {
6602                 if ($this->duration !== null)
6603                 {
6604                         if ($convert)
6605                         {
6606                                 $time = SimplePie_Misc::time_hms($this->duration);
6607                                 return $time;
6608                         }
6609                         else
6610                         {
6611                                 return $this->duration;
6612                         }
6613                 }
6614                 else
6615                 {
6616                         return null;
6617                 }
6618         }
6619
6620         function get_expression()
6621         {
6622                 if ($this->expression !== null)
6623                 {
6624                         return $this->expression;
6625                 }
6626                 else
6627                 {
6628                         return 'full';
6629                 }
6630         }
6631
6632         function get_extension()
6633         {
6634                 if ($this->link !== null)
6635                 {
6636                         $url = SimplePie_Misc::parse_url($this->link);
6637                         if ($url['path'] !== '')
6638                         {
6639                                 return pathinfo($url['path'], PATHINFO_EXTENSION);
6640                         }
6641                 }
6642                 return null;
6643         }
6644
6645         function get_framerate()
6646         {
6647                 if ($this->framerate !== null)
6648                 {
6649                         return $this->framerate;
6650                 }
6651                 else
6652                 {
6653                         return null;
6654                 }
6655         }
6656
6657         function get_handler()
6658         {
6659                 return $this->get_real_type(true);
6660         }
6661
6662         function get_hash($key = 0)
6663         {
6664                 $hashes = $this->get_hashes();
6665                 if (isset($hashes[$key]))
6666                 {
6667                         return $hashes[$key];
6668                 }
6669                 else
6670                 {
6671                         return null;
6672                 }
6673         }
6674
6675         function get_hashes()
6676         {
6677                 if ($this->hashes !== null)
6678                 {
6679                         return $this->hashes;
6680                 }
6681                 else
6682                 {
6683                         return null;
6684                 }
6685         }
6686
6687         function get_height()
6688         {
6689                 if ($this->height !== null)
6690                 {
6691                         return $this->height;
6692                 }
6693                 else
6694                 {
6695                         return null;
6696                 }
6697         }
6698
6699         function get_language()
6700         {
6701                 if ($this->lang !== null)
6702                 {
6703                         return $this->lang;
6704                 }
6705                 else
6706                 {
6707                         return null;
6708                 }
6709         }
6710
6711         function get_keyword($key = 0)
6712         {
6713                 $keywords = $this->get_keywords();
6714                 if (isset($keywords[$key]))
6715                 {
6716                         return $keywords[$key];
6717                 }
6718                 else
6719                 {
6720                         return null;
6721                 }
6722         }
6723
6724         function get_keywords()
6725         {
6726                 if ($this->keywords !== null)
6727                 {
6728                         return $this->keywords;
6729                 }
6730                 else
6731                 {
6732                         return null;
6733                 }
6734         }
6735
6736         function get_length()
6737         {
6738                 if ($this->length !== null)
6739                 {
6740                         return $this->length;
6741                 }
6742                 else
6743                 {
6744                         return null;
6745                 }
6746         }
6747
6748         function get_link()
6749         {
6750                 if ($this->link !== null)
6751                 {
6752                         return urldecode($this->link);
6753                 }
6754                 else
6755                 {
6756                         return null;
6757                 }
6758         }
6759
6760         function get_medium()
6761         {
6762                 if ($this->medium !== null)
6763                 {
6764                         return $this->medium;
6765                 }
6766                 else
6767                 {
6768                         return null;
6769                 }
6770         }
6771
6772         function get_player()
6773         {
6774                 if ($this->player !== null)
6775                 {
6776                         return $this->player;
6777                 }
6778                 else
6779                 {
6780                         return null;
6781                 }
6782         }
6783
6784         function get_rating($key = 0)
6785         {
6786                 $ratings = $this->get_ratings();
6787                 if (isset($ratings[$key]))
6788                 {
6789                         return $ratings[$key];
6790                 }
6791                 else
6792                 {
6793                         return null;
6794                 }
6795         }
6796
6797         function get_ratings()
6798         {
6799                 if ($this->ratings !== null)
6800                 {
6801                         return $this->ratings;
6802                 }
6803                 else
6804                 {
6805                         return null;
6806                 }
6807         }
6808
6809         function get_restriction($key = 0)
6810         {
6811                 $restrictions = $this->get_restrictions();
6812                 if (isset($restrictions[$key]))
6813                 {
6814                         return $restrictions[$key];
6815                 }
6816                 else
6817                 {
6818                         return null;
6819                 }
6820         }
6821
6822         function get_restrictions()
6823         {
6824                 if ($this->restrictions !== null)
6825                 {
6826                         return $this->restrictions;
6827                 }
6828                 else
6829                 {
6830                         return null;
6831                 }
6832         }
6833
6834         function get_sampling_rate()
6835         {
6836                 if ($this->samplingrate !== null)
6837                 {
6838                         return $this->samplingrate;
6839                 }
6840                 else
6841                 {
6842                         return null;
6843                 }
6844         }
6845
6846         function get_size()
6847         {
6848                 $length = $this->get_length();
6849                 if ($length !== null)
6850                 {
6851                         return round($length/1048576, 2);
6852                 }
6853                 else
6854                 {
6855                         return null;
6856                 }
6857         }
6858
6859         function get_thumbnail($key = 0)
6860         {
6861                 $thumbnails = $this->get_thumbnails();
6862                 if (isset($thumbnails[$key]))
6863                 {
6864                         return $thumbnails[$key];
6865                 }
6866                 else
6867                 {
6868                         return null;
6869                 }
6870         }
6871
6872         function get_thumbnails()
6873         {
6874                 if ($this->thumbnails !== null)
6875                 {
6876                         return $this->thumbnails;
6877                 }
6878                 else
6879                 {
6880                         return null;
6881                 }
6882         }
6883
6884         function get_title()
6885         {
6886                 if ($this->title !== null)
6887                 {
6888                         return $this->title;
6889                 }
6890                 else
6891                 {
6892                         return null;
6893                 }
6894         }
6895
6896         function get_type()
6897         {
6898                 if ($this->type !== null)
6899                 {
6900                         return $this->type;
6901                 }
6902                 else
6903                 {
6904                         return null;
6905                 }
6906         }
6907
6908         function get_width()
6909         {
6910                 if ($this->width !== null)
6911                 {
6912                         return $this->width;
6913                 }
6914                 else
6915                 {
6916                         return null;
6917                 }
6918         }
6919
6920         function native_embed($options='')
6921         {
6922                 return $this->embed($options, true);
6923         }
6924
6925         /**
6926          * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6927          */
6928         function embed($options = '', $native = false)
6929         {
6930                 // Set up defaults
6931                 $audio = '';
6932                 $video = '';
6933                 $alt = '';
6934                 $altclass = '';
6935                 $loop = 'false';
6936                 $width = 'auto';
6937                 $height = 'auto';
6938                 $bgcolor = '#ffffff';
6939                 $mediaplayer = '';
6940                 $widescreen = false;
6941                 $handler = $this->get_handler();
6942                 $type = $this->get_real_type();
6943
6944                 // Process options and reassign values as necessary
6945                 if (is_array($options))
6946                 {
6947                         extract($options);
6948                 }
6949                 else
6950                 {
6951                         $options = explode(',', $options);
6952                         foreach($options as $option)
6953                         {
6954                                 $opt = explode(':', $option, 2);
6955                                 if (isset($opt[0], $opt[1]))
6956                                 {
6957                                         $opt[0] = trim($opt[0]);
6958                                         $opt[1] = trim($opt[1]);
6959                                         switch ($opt[0])
6960                                         {
6961                                                 case 'audio':
6962                                                         $audio = $opt[1];
6963                                                         break;
6964
6965                                                 case 'video':
6966                                                         $video = $opt[1];
6967                                                         break;
6968
6969                                                 case 'alt':
6970                                                         $alt = $opt[1];
6971                                                         break;
6972
6973                                                 case 'altclass':
6974                                                         $altclass = $opt[1];
6975                                                         break;
6976
6977                                                 case 'loop':
6978                                                         $loop = $opt[1];
6979                                                         break;
6980
6981                                                 case 'width':
6982                                                         $width = $opt[1];
6983                                                         break;
6984
6985                                                 case 'height':
6986                                                         $height = $opt[1];
6987                                                         break;
6988
6989                                                 case 'bgcolor':
6990                                                         $bgcolor = $opt[1];
6991                                                         break;
6992
6993                                                 case 'mediaplayer':
6994                                                         $mediaplayer = $opt[1];
6995                                                         break;
6996
6997                                                 case 'widescreen':
6998                                                         $widescreen = $opt[1];
6999                                                         break;
7000                                         }
7001                                 }
7002                         }
7003                 }
7004
7005                 $mime = explode('/', $type, 2);
7006                 $mime = $mime[0];
7007
7008                 // Process values for 'auto'
7009                 if ($width === 'auto')
7010                 {
7011                         if ($mime === 'video')
7012                         {
7013                                 if ($height === 'auto')
7014                                 {
7015                                         $width = 480;
7016                                 }
7017                                 elseif ($widescreen)
7018                                 {
7019                                         $width = round((intval($height)/9)*16);
7020                                 }
7021                                 else
7022                                 {
7023                                         $width = round((intval($height)/3)*4);
7024                                 }
7025                         }
7026                         else
7027                         {
7028                                 $width = '100%';
7029                         }
7030                 }
7031
7032                 if ($height === 'auto')
7033                 {
7034                         if ($mime === 'audio')
7035                         {
7036                                 $height = 0;
7037                         }
7038                         elseif ($mime === 'video')
7039                         {
7040                                 if ($width === 'auto')
7041                                 {
7042                                         if ($widescreen)
7043                                         {
7044                                                 $height = 270;
7045                                         }
7046                                         else
7047                                         {
7048                                                 $height = 360;
7049                                         }
7050                                 }
7051                                 elseif ($widescreen)
7052                                 {
7053                                         $height = round((intval($width)/16)*9);
7054                                 }
7055                                 else
7056                                 {
7057                                         $height = round((intval($width)/4)*3);
7058                                 }
7059                         }
7060                         else
7061                         {
7062                                 $height = 376;
7063                         }
7064                 }
7065                 elseif ($mime === 'audio')
7066                 {
7067                         $height = 0;
7068                 }
7069
7070                 // Set proper placeholder value
7071                 if ($mime === 'audio')
7072                 {
7073                         $placeholder = $audio;
7074                 }
7075                 elseif ($mime === 'video')
7076                 {
7077                         $placeholder = $video;
7078                 }
7079
7080                 $embed = '';
7081
7082                 // Make sure the JS library is included
7083                 if (!$native)
7084                 {
7085                         static $javascript_outputted = null;
7086                         if (!$javascript_outputted && $this->javascript)
7087                         {
7088                                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7089                                 $javascript_outputted = true;
7090                         }
7091                 }
7092
7093                 // Odeo Feed MP3's
7094                 if ($handler === 'odeo')
7095                 {
7096                         if ($native)
7097                         {
7098                                 $embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://adobe.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>';
7099                         }
7100                         else
7101                         {
7102                                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7103                         }
7104                 }
7105
7106                 // Flash
7107                 elseif ($handler === 'flash')
7108                 {
7109                         if ($native)
7110                         {
7111                                 $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
7112                         }
7113                         else
7114                         {
7115                                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7116                         }
7117                 }
7118
7119                 // Flash Media Player file types.
7120                 // Preferred handler for MP3 file types.
7121                 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7122                 {
7123                         $height += 20;
7124                         if ($native)
7125                         {
7126                                 $embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
7127                         }
7128                         else
7129                         {
7130                                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7131                         }
7132                 }
7133
7134                 // QuickTime 7 file types.  Need to test with QuickTime 6.
7135                 // Only handle MP3's if the Flash Media Player is not present.
7136                 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7137                 {
7138                         $height += 16;
7139                         if ($native)
7140                         {
7141                                 if ($placeholder !== '')
7142                                 {
7143                                         $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://apple.com/quicktime/download/\"></embed>";
7144                                 }
7145                                 else
7146                                 {
7147                                         $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://apple.com/quicktime/download/\"></embed>";
7148                                 }
7149                         }
7150                         else
7151                         {
7152                                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7153                         }
7154                 }
7155
7156                 // Windows Media
7157                 elseif ($handler === 'wmedia')
7158                 {
7159                         $height += 45;
7160                         if ($native)
7161                         {
7162                                 $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>";
7163                         }
7164                         else
7165                         {
7166                                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7167                         }
7168                 }
7169
7170                 // Everything else
7171                 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7172
7173                 return $embed;
7174         }
7175
7176         function get_real_type($find_handler = false)
7177         {
7178                 // If it's Odeo, let's get it out of the way.
7179                 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7180                 {
7181                         return 'odeo';
7182                 }
7183
7184                 // Mime-types by handler.
7185                 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7186                 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7187                 $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', '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'); // QuickTime
7188                 $types_wmedia = 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'); // Windows Media
7189                 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7190
7191                 if ($this->get_type() !== null)
7192                 {
7193                         $type = strtolower($this->type);
7194                 }
7195                 else
7196                 {
7197                         $type = null;
7198                 }
7199
7200                 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7201                 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7202                 {
7203                         switch (strtolower($this->get_extension()))
7204                         {
7205                                 // Audio mime-types
7206                                 case 'aac':
7207                                 case 'adts':
7208                                         $type = 'audio/acc';
7209                                         break;
7210
7211                                 case 'aif':
7212                                 case 'aifc':
7213                                 case 'aiff':
7214                                 case 'cdda':
7215                                         $type = 'audio/aiff';
7216                                         break;
7217
7218                                 case 'bwf':
7219                                         $type = 'audio/wav';
7220                                         break;
7221
7222                                 case 'kar':
7223                                 case 'mid':
7224                                 case 'midi':
7225                                 case 'smf':
7226                                         $type = 'audio/midi';
7227                                         break;
7228
7229                                 case 'm4a':
7230                                         $type = 'audio/x-m4a';
7231                                         break;
7232
7233                                 case 'mp3':
7234                                 case 'swa':
7235                                         $type = 'audio/mp3';
7236                                         break;
7237
7238                                 case 'wav':
7239                                         $type = 'audio/wav';
7240                                         break;
7241
7242                                 case 'wax':
7243                                         $type = 'audio/x-ms-wax';
7244                                         break;
7245
7246                                 case 'wma':
7247                                         $type = 'audio/x-ms-wma';
7248                                         break;
7249
7250                                 // Video mime-types
7251                                 case '3gp':
7252                                 case '3gpp':
7253                                         $type = 'video/3gpp';
7254                                         break;
7255
7256                                 case '3g2':
7257                                 case '3gp2':
7258                                         $type = 'video/3gpp2';
7259                                         break;
7260
7261                                 case 'asf':
7262                                         $type = 'video/x-ms-asf';
7263                                         break;
7264
7265                                 case 'flv':
7266                                         $type = 'video/x-flv';
7267                                         break;
7268
7269                                 case 'm1a':
7270                                 case 'm1s':
7271                                 case 'm1v':
7272                                 case 'm15':
7273                                 case 'm75':
7274                                 case 'mp2':
7275                                 case 'mpa':
7276                                 case 'mpeg':
7277                                 case 'mpg':
7278                                 case 'mpm':
7279                                 case 'mpv':
7280                                         $type = 'video/mpeg';
7281                                         break;
7282
7283                                 case 'm4v':
7284                                         $type = 'video/x-m4v';
7285                                         break;
7286
7287                                 case 'mov':
7288                                 case 'qt':
7289                                         $type = 'video/quicktime';
7290                                         break;
7291
7292                                 case 'mp4':
7293                                 case 'mpg4':
7294                                         $type = 'video/mp4';
7295                                         break;
7296
7297                                 case 'sdv':
7298                                         $type = 'video/sd-video';
7299                                         break;
7300
7301                                 case 'wm':
7302                                         $type = 'video/x-ms-wm';
7303                                         break;
7304
7305                                 case 'wmv':
7306                                         $type = 'video/x-ms-wmv';
7307                                         break;
7308
7309                                 case 'wvx':
7310                                         $type = 'video/x-ms-wvx';
7311                                         break;
7312
7313                                 // Flash mime-types
7314                                 case 'spl':
7315                                         $type = 'application/futuresplash';
7316                                         break;
7317
7318                                 case 'swf':
7319                                         $type = 'application/x-shockwave-flash';
7320                                         break;
7321                         }
7322                 }
7323
7324                 if ($find_handler)
7325                 {
7326                         if (in_array($type, $types_flash))
7327                         {
7328                                 return 'flash';
7329                         }
7330                         elseif (in_array($type, $types_fmedia))
7331                         {
7332                                 return 'fmedia';
7333                         }
7334                         elseif (in_array($type, $types_quicktime))
7335                         {
7336                                 return 'quicktime';
7337                         }
7338                         elseif (in_array($type, $types_wmedia))
7339                         {
7340                                 return 'wmedia';
7341                         }
7342                         elseif (in_array($type, $types_mp3))
7343                         {
7344                                 return 'mp3';
7345                         }
7346                         else
7347                         {
7348                                 return null;
7349                         }
7350                 }
7351                 else
7352                 {
7353                         return $type;
7354                 }
7355         }
7356 }
7357
7358 class SimplePie_Caption
7359 {
7360         var $type;
7361         var $lang;
7362         var $startTime;
7363         var $endTime;
7364         var $text;
7365
7366         // Constructor, used to input the data
7367         function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7368         {
7369                 $this->type = $type;
7370                 $this->lang = $lang;
7371                 $this->startTime = $startTime;
7372                 $this->endTime = $endTime;
7373                 $this->text = $text;
7374         }
7375
7376         function __toString()
7377         {
7378                 // There is no $this->data here
7379                 return md5(serialize($this));
7380         }
7381
7382         function get_endtime()
7383         {
7384                 if ($this->endTime !== null)
7385                 {
7386                         return $this->endTime;
7387                 }
7388                 else
7389                 {
7390                         return null;
7391                 }
7392         }
7393
7394         function get_language()
7395         {
7396                 if ($this->lang !== null)
7397                 {
7398                         return $this->lang;
7399                 }
7400                 else
7401                 {
7402                         return null;
7403                 }
7404         }
7405
7406         function get_starttime()
7407         {
7408                 if ($this->startTime !== null)
7409                 {
7410                         return $this->startTime;
7411                 }
7412                 else
7413                 {
7414                         return null;
7415                 }
7416         }
7417
7418         function get_text()
7419         {
7420                 if ($this->text !== null)
7421                 {
7422                         return $this->text;
7423                 }
7424                 else
7425                 {
7426                         return null;
7427                 }
7428         }
7429
7430         function get_type()
7431         {
7432                 if ($this->type !== null)
7433                 {
7434                         return $this->type;
7435                 }
7436                 else
7437                 {
7438                         return null;
7439                 }
7440         }
7441 }
7442
7443 class SimplePie_Credit
7444 {
7445         var $role;
7446         var $scheme;
7447         var $name;
7448
7449         // Constructor, used to input the data
7450         function SimplePie_Credit($role = null, $scheme = null, $name = null)
7451         {
7452                 $this->role = $role;
7453                 $this->scheme = $scheme;
7454                 $this->name = $name;
7455         }
7456
7457         function __toString()
7458         {
7459                 // There is no $this->data here
7460                 return md5(serialize($this));
7461         }
7462
7463         function get_role()
7464         {
7465                 if ($this->role !== null)
7466                 {
7467                         return $this->role;
7468                 }
7469                 else
7470                 {
7471                         return null;
7472                 }
7473         }
7474
7475         function get_scheme()
7476         {
7477                 if ($this->scheme !== null)
7478                 {
7479                         return $this->scheme;
7480                 }
7481                 else
7482                 {
7483                         return null;
7484                 }
7485         }
7486
7487         function get_name()
7488         {
7489                 if ($this->name !== null)
7490                 {
7491                         return $this->name;
7492                 }
7493                 else
7494                 {
7495                         return null;
7496                 }
7497         }
7498 }
7499
7500 class SimplePie_Copyright
7501 {
7502         var $url;
7503         var $label;
7504
7505         // Constructor, used to input the data
7506         function SimplePie_Copyright($url = null, $label = null)
7507         {
7508                 $this->url = $url;
7509                 $this->label = $label;
7510         }
7511
7512         function __toString()
7513         {
7514                 // There is no $this->data here
7515                 return md5(serialize($this));
7516         }
7517
7518         function get_url()
7519         {
7520                 if ($this->url !== null)
7521                 {
7522                         return $this->url;
7523                 }
7524                 else
7525                 {
7526                         return null;
7527                 }
7528         }
7529
7530         function get_attribution()
7531         {
7532                 if ($this->label !== null)
7533                 {
7534                         return $this->label;
7535                 }
7536                 else
7537                 {
7538                         return null;
7539                 }
7540         }
7541 }
7542
7543 class SimplePie_Rating
7544 {
7545         var $scheme;
7546         var $value;
7547
7548         // Constructor, used to input the data
7549         function SimplePie_Rating($scheme = null, $value = null)
7550         {
7551                 $this->scheme = $scheme;
7552                 $this->value = $value;
7553         }
7554
7555         function __toString()
7556         {
7557                 // There is no $this->data here
7558                 return md5(serialize($this));
7559         }
7560
7561         function get_scheme()
7562         {
7563                 if ($this->scheme !== null)
7564                 {
7565                         return $this->scheme;
7566                 }
7567                 else
7568                 {
7569                         return null;
7570                 }
7571         }
7572
7573         function get_value()
7574         {
7575                 if ($this->value !== null)
7576                 {
7577                         return $this->value;
7578                 }
7579                 else
7580                 {
7581                         return null;
7582                 }
7583         }
7584 }
7585
7586 class SimplePie_Restriction
7587 {
7588         var $relationship;
7589         var $type;
7590         var $value;
7591
7592         // Constructor, used to input the data
7593         function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7594         {
7595                 $this->relationship = $relationship;
7596                 $this->type = $type;
7597                 $this->value = $value;
7598         }
7599
7600         function __toString()
7601         {
7602                 // There is no $this->data here
7603                 return md5(serialize($this));
7604         }
7605
7606         function get_relationship()
7607         {
7608                 if ($this->relationship !== null)
7609                 {
7610                         return $this->relationship;
7611                 }
7612                 else
7613                 {
7614                         return null;
7615                 }
7616         }
7617
7618         function get_type()
7619         {
7620                 if ($this->type !== null)
7621                 {
7622                         return $this->type;
7623                 }
7624                 else
7625                 {
7626                         return null;
7627                 }
7628         }
7629
7630         function get_value()
7631         {
7632                 if ($this->value !== null)
7633                 {
7634                         return $this->value;
7635                 }
7636                 else
7637                 {
7638                         return null;
7639                 }
7640         }
7641 }
7642
7643 /**
7644  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7645  */
7646 class SimplePie_File
7647 {
7648         var $url;
7649         var $useragent;
7650         var $success = true;
7651         var $headers = array();
7652         var $body;
7653         var $status_code;
7654         var $redirects = 0;
7655         var $error;
7656         var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7657
7658         function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7659         {
7660                 if (class_exists('idna_convert'))
7661                 {
7662                         $idn =& new idna_convert;
7663                         $parsed = SimplePie_Misc::parse_url($url);
7664                         $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7665                 }
7666                 $this->url = $url;
7667                 $this->useragent = $useragent;
7668                 if (preg_match('/^http(s)?:\/\//i', $url))
7669                 {
7670                         if ($useragent === null)
7671                         {
7672                                 $useragent = ini_get('user_agent');
7673                                 $this->useragent = $useragent;
7674                         }
7675                         if (!is_array($headers))
7676                         {
7677                                 $headers = array();
7678                         }
7679                         if (!$force_fsockopen && function_exists('curl_exec'))
7680                         {
7681                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7682                                 $fp = curl_init();
7683                                 $headers2 = array();
7684                                 foreach ($headers as $key => $value)
7685                                 {
7686                                         $headers2[] = "$key: $value";
7687                                 }
7688                                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7689                                 {
7690                                         curl_setopt($fp, CURLOPT_ENCODING, '');
7691                                 }
7692                                 curl_setopt($fp, CURLOPT_URL, $url);
7693                                 curl_setopt($fp, CURLOPT_HEADER, 1);
7694                                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7695                                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7696                                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7697                                 curl_setopt($fp, CURLOPT_REFERER, $url);
7698                                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7699                                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7700                                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7701                                 {
7702                                         curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7703                                         curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7704                                 }
7705
7706                                 $this->headers = curl_exec($fp);
7707                                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7708                                 {
7709                                         curl_setopt($fp, CURLOPT_ENCODING, 'none');
7710                                         $this->headers = curl_exec($fp);
7711                                 }
7712                                 if (curl_errno($fp))
7713                                 {
7714                                         $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7715                                         $this->success = false;
7716                                 }
7717                                 else
7718                                 {
7719                                         $info = curl_getinfo($fp);
7720                                         curl_close($fp);
7721                                         $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7722                                         $this->headers = array_pop($this->headers);
7723                                         $parser =& new SimplePie_HTTP_Parser($this->headers);
7724                                         if ($parser->parse())
7725                                         {
7726                                                 $this->headers = $parser->headers;
7727                                                 $this->body = $parser->body;
7728                                                 $this->status_code = $parser->status_code;
7729                                                 if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7730                                                 {
7731                                                         $this->redirects++;
7732                                                         $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7733                                                         return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7734                                                 }
7735                                         }
7736                                 }
7737                         }
7738                         else
7739                         {
7740                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7741                                 $url_parts = parse_url($url);
7742                                 $socket_host = $url_parts['host'];
7743                                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7744                                 {
7745                                         $socket_host = "ssl://$url_parts[host]";
7746                                         $url_parts['port'] = 443;
7747                                 }
7748                                 if (!isset($url_parts['port']))
7749                                 {
7750                                         $url_parts['port'] = 80;
7751                                 }
7752                                 $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
7753                                 if (!$fp)
7754                                 {
7755                                         $this->error = 'fsockopen error: ' . $errstr;
7756                                         $this->success = false;
7757                                 }
7758                                 else
7759                                 {
7760                                         stream_set_timeout($fp, $timeout);
7761                                         if (isset($url_parts['path']))
7762                                         {
7763                                                 if (isset($url_parts['query']))
7764                                                 {
7765                                                         $get = "$url_parts[path]?$url_parts[query]";
7766                                                 }
7767                                                 else
7768                                                 {
7769                                                         $get = $url_parts['path'];
7770                                                 }
7771                                         }
7772                                         else
7773                                         {
7774                                                 $get = '/';
7775                                         }
7776                                         $out = "GET $get HTTP/1.0\r\n";
7777                                         $out .= "Host: $url_parts[host]\r\n";
7778                                         $out .= "User-Agent: $useragent\r\n";
7779                                         if (extension_loaded('zlib'))
7780                                         {
7781                                                 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7782                                         }
7783
7784                                         if (isset($url_parts['user']) && isset($url_parts['pass']))
7785                                         {
7786                                                 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7787                                         }
7788                                         foreach ($headers as $key => $value)
7789                                         {
7790                                                 $out .= "$key: $value\r\n";
7791                                         }
7792                                         $out .= "Connection: Close\r\n\r\n";
7793                                         fwrite($fp, $out);
7794
7795                                         $info = stream_get_meta_data($fp);
7796
7797                                         $this->headers = '';
7798                                         while (!$info['eof'] && !$info['timed_out'])
7799                                         {
7800                                                 $this->headers .= fread($fp, 1160);
7801                                                 $info = stream_get_meta_data($fp);
7802                                         }
7803                                         if (!$info['timed_out'])
7804                                         {
7805                                                 $parser =& new SimplePie_HTTP_Parser($this->headers);
7806                                                 if ($parser->parse())
7807                                                 {
7808                                                         $this->headers = $parser->headers;
7809                                                         $this->body = $parser->body;
7810                                                         $this->status_code = $parser->status_code;
7811                                                         if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7812                                                         {
7813                                                                 $this->redirects++;
7814                                                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7815                                                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7816                                                         }
7817                                                         if (isset($this->headers['content-encoding']))
7818                                                         {
7819                                                                 // Hey, we act dumb elsewhere, so let's do that here too
7820                                                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7821                                                                 {
7822                                                                         case 'gzip':
7823                                                                         case 'x-gzip':
7824                                                                                 $decoder =& new SimplePie_gzdecode($this->body);
7825                                                                                 if (!$decoder->parse())
7826                                                                                 {
7827                                                                                         $this->error = 'Unable to decode HTTP "gzip" stream';
7828                                                                                         $this->success = false;
7829                                                                                 }
7830                                                                                 else
7831                                                                                 {
7832                                                                                         $this->body = $decoder->data;
7833                                                                                 }
7834                                                                                 break;
7835
7836                                                                         case 'deflate':
7837                                                                                 if (($body = gzuncompress($this->body)) === false)
7838                                                                                 {
7839                                                                                         if (($body = gzinflate($this->body)) === false)
7840                                                                                         {
7841                                                                                                 $this->error = 'Unable to decode HTTP "deflate" stream';
7842                                                                                                 $this->success = false;
7843                                                                                         }
7844                                                                                 }
7845                                                                                 $this->body = $body;
7846                                                                                 break;
7847
7848                                                                         default:
7849                                                                                 $this->error = 'Unknown content coding';
7850                                                                                 $this->success = false;
7851                                                                 }
7852                                                         }
7853                                                 }
7854                                         }
7855                                         else
7856                                         {
7857                                                 $this->error = 'fsocket timed out';
7858                                                 $this->success = false;
7859                                         }
7860                                         fclose($fp);
7861                                 }
7862                         }
7863                 }
7864                 else
7865                 {
7866                         $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7867                         if (!$this->body = file_get_contents($url))
7868                         {
7869                                 $this->error = 'file_get_contents could not read the file';
7870                                 $this->success = false;
7871                         }
7872                 }
7873         }
7874 }
7875
7876 /**
7877  * HTTP Response Parser
7878  *
7879  * @package SimplePie
7880  */
7881 class SimplePie_HTTP_Parser
7882 {
7883         /**
7884          * HTTP Version
7885          *
7886          * @access public
7887          * @var float
7888          */
7889         var $http_version = 0.0;
7890
7891         /**
7892          * Status code
7893          *
7894          * @access public
7895          * @var int
7896          */
7897         var $status_code = 0;
7898
7899         /**
7900          * Reason phrase
7901          *
7902          * @access public
7903          * @var string
7904          */
7905         var $reason = '';
7906
7907         /**
7908          * Key/value pairs of the headers
7909          *
7910          * @access public
7911          * @var array
7912          */
7913         var $headers = array();
7914
7915         /**
7916          * Body of the response
7917          *
7918          * @access public
7919          * @var string
7920          */
7921         var $body = '';
7922
7923         /**
7924          * Current state of the state machine
7925          *
7926          * @access private
7927          * @var string
7928          */
7929         var $state = 'http_version';
7930
7931         /**
7932          * Input data
7933          *
7934          * @access private
7935          * @var string
7936          */
7937         var $data = '';
7938
7939         /**
7940          * Input data length (to avoid calling strlen() everytime this is needed)
7941          *
7942          * @access private
7943          * @var int
7944          */
7945         var $data_length = 0;
7946
7947         /**
7948          * Current position of the pointer
7949          *
7950          * @var int
7951          * @access private
7952          */
7953         var $position = 0;
7954
7955         /**
7956          * Name of the hedaer currently being parsed
7957          *
7958          * @access private
7959          * @var string
7960          */
7961         var $name = '';
7962
7963         /**
7964          * Value of the hedaer currently being parsed
7965          *
7966          * @access private
7967          * @var string
7968          */
7969         var $value = '';
7970
7971         /**
7972          * Create an instance of the class with the input data
7973          *
7974          * @access public
7975          * @param string $data Input data
7976          */
7977         function SimplePie_HTTP_Parser($data)
7978         {
7979                 $this->data = $data;
7980                 $this->data_length = strlen($this->data);
7981         }
7982
7983         /**
7984          * Parse the input data
7985          *
7986          * @access public
7987          * @return bool true on success, false on failure
7988          */
7989         function parse()
7990         {
7991                 while ($this->state && $this->state !== 'emit' && $this->has_data())
7992                 {
7993                         $state = $this->state;
7994                         $this->$state();
7995                 }
7996                 $this->data = '';
7997                 if ($this->state === 'emit' || $this->state === 'body')
7998                 {
7999                         return true;
8000                 }
8001                 else
8002                 {
8003                         $this->http_version = '';
8004                         $this->status_code = '';
8005                         $this->reason = '';
8006                         $this->headers = array();
8007                         $this->body = '';
8008                         return false;
8009                 }
8010         }
8011
8012         /**
8013          * Check whether there is data beyond the pointer
8014          *
8015          * @access private
8016          * @return bool true if there is further data, false if not
8017          */
8018         function has_data()
8019         {
8020                 return (bool) ($this->position < $this->data_length);
8021         }
8022
8023         /**
8024          * See if the next character is LWS
8025          *
8026          * @access private
8027          * @return bool true if the next character is LWS, false if not
8028          */
8029         function is_linear_whitespace()
8030         {
8031                 return (bool) ($this->data[$this->position] === "\x09"
8032                         || $this->data[$this->position] === "\x20"
8033                         || ($this->data[$this->position] === "\x0A"
8034                                 && isset($this->data[$this->position + 1])
8035                                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8036         }
8037
8038         /**
8039          * Parse the HTTP version
8040          *
8041          * @access private
8042          */
8043         function http_version()
8044         {
8045                 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8046                 {
8047                         $len = strspn($this->data, '0123456789.', 5);
8048                         $this->http_version = substr($this->data, 5, $len);
8049                         $this->position += 5 + $len;
8050                         if (substr_count($this->http_version, '.') <= 1)
8051                         {
8052                                 $this->http_version = (float) $this->http_version;
8053                                 $this->position += strspn($this->data, "\x09\x20", $this->position);
8054                                 $this->state = 'status';
8055                         }
8056                         else
8057                         {
8058                                 $this->state = false;
8059                         }
8060                 }
8061                 else
8062                 {
8063                         $this->state = false;
8064                 }
8065         }
8066
8067         /**
8068          * Parse the status code
8069          *
8070          * @access private
8071          */
8072         function status()
8073         {
8074                 if ($len = strspn($this->data, '0123456789', $this->position))
8075                 {
8076                         $this->status_code = (int) substr($this->data, $this->position, $len);
8077                         $this->position += $len;
8078                         $this->state = 'reason';
8079                 }
8080                 else
8081                 {
8082                         $this->state = false;
8083                 }
8084         }
8085
8086         /**
8087          * Parse the reason phrase
8088          *
8089          * @access private
8090          */
8091         function reason()
8092         {
8093                 $len = strcspn($this->data, "\x0A", $this->position);
8094                 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8095                 $this->position += $len + 1;
8096                 $this->state = 'new_line';
8097         }
8098
8099         /**
8100          * Deal with a new line, shifting data around as needed
8101          *
8102          * @access private
8103          */
8104         function new_line()
8105         {
8106                 $this->value = trim($this->value, "\x0D\x20");
8107                 if ($this->name !== '' && $this->value !== '')
8108                 {
8109                         $this->name = strtolower($this->name);
8110                         if (isset($this->headers[$this->name]))
8111                         {
8112                                 $this->headers[$this->name] .= ', ' . $this->value;
8113                         }
8114                         else
8115                         {
8116                                 $this->headers[$this->name] = $this->value;
8117                         }
8118                 }
8119                 $this->name = '';
8120                 $this->value = '';
8121                 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8122                 {
8123                         $this->position += 2;
8124                         $this->state = 'body';
8125                 }
8126                 elseif ($this->data[$this->position] === "\x0A")
8127                 {
8128                         $this->position++;
8129                         $this->state = 'body';
8130                 }
8131                 else
8132                 {
8133                         $this->state = 'name';
8134                 }
8135         }
8136
8137         /**
8138          * Parse a header name
8139          *
8140          * @access private
8141          */
8142         function name()
8143         {
8144                 $len = strcspn($this->data, "\x0A:", $this->position);
8145                 if (isset($this->data[$this->position + $len]))
8146                 {
8147                         if ($this->data[$this->position + $len] === "\x0A")
8148                         {
8149                                 $this->position += $len;
8150                                 $this->state = 'new_line';
8151                         }
8152                         else
8153                         {
8154                                 $this->name = substr($this->data, $this->position, $len);
8155                                 $this->position += $len + 1;
8156                                 $this->state = 'value';
8157                         }
8158                 }
8159                 else
8160                 {
8161                         $this->state = false;
8162                 }
8163         }
8164
8165         /**
8166          * Parse LWS, replacing consecutive LWS characters with a single space
8167          *
8168          * @access private
8169          */
8170         function linear_whitespace()
8171         {
8172                 do
8173                 {
8174                         if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8175                         {
8176                                 $this->position += 2;
8177                         }
8178                         elseif ($this->data[$this->position] === "\x0A")
8179                         {
8180                                 $this->position++;
8181                         }
8182                         $this->position += strspn($this->data, "\x09\x20", $this->position);
8183                 } while ($this->has_data() && $this->is_linear_whitespace());
8184                 $this->value .= "\x20";
8185         }
8186
8187         /**
8188          * See what state to move to while within non-quoted header values
8189          *
8190          * @access private
8191          */
8192         function value()
8193         {
8194                 if ($this->is_linear_whitespace())
8195                 {
8196                         $this->linear_whitespace();
8197                 }
8198                 else
8199                 {
8200                         switch ($this->data[$this->position])
8201                         {
8202                                 case '"':
8203                                         $this->position++;
8204                                         $this->state = 'quote';
8205                                         break;
8206
8207                                 case "\x0A":
8208                                         $this->position++;
8209                                         $this->state = 'new_line';
8210                                         break;
8211
8212                                 default:
8213                                         $this->state = 'value_char';
8214                                         break;
8215                         }
8216                 }
8217         }
8218
8219         /**
8220          * Parse a header value while outside quotes
8221          *
8222          * @access private
8223          */
8224         function value_char()
8225         {
8226                 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8227                 $this->value .= substr($this->data, $this->position, $len);
8228                 $this->position += $len;
8229                 $this->state = 'value';
8230         }
8231
8232         /**
8233          * See what state to move to while within quoted header values
8234          *
8235          * @access private
8236          */
8237         function quote()
8238         {
8239                 if ($this->is_linear_whitespace())
8240                 {
8241                         $this->linear_whitespace();
8242                 }
8243                 else
8244                 {
8245                         switch ($this->data[$this->position])
8246                         {
8247                                 case '"':
8248                                         $this->position++;
8249                                         $this->state = 'value';
8250                                         break;
8251
8252                                 case "\x0A":
8253                                         $this->position++;
8254                                         $this->state = 'new_line';
8255                                         break;
8256
8257                                 case '\\':
8258                                         $this->position++;
8259                                         $this->state = 'quote_escaped';
8260                                         break;
8261
8262                                 default:
8263                                         $this->state = 'quote_char';
8264                                         break;
8265                         }
8266                 }
8267         }
8268
8269         /**
8270          * Parse a header value while within quotes
8271          *
8272          * @access private
8273          */
8274         function quote_char()
8275         {
8276                 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8277                 $this->value .= substr($this->data, $this->position, $len);
8278                 $this->position += $len;
8279                 $this->state = 'value';
8280         }
8281
8282         /**
8283          * Parse an escaped character within quotes
8284          *
8285          * @access private
8286          */
8287         function quote_escaped()
8288         {
8289                 $this->value .= $this->data[$this->position];
8290                 $this->position++;
8291                 $this->state = 'quote';
8292         }
8293
8294         /**
8295          * Parse the body
8296          *
8297          * @access private
8298          */
8299         function body()
8300         {
8301                 $this->body = substr($this->data, $this->position);
8302                 $this->state = 'emit';
8303         }
8304 }
8305
8306 /**
8307  * gzdecode
8308  *
8309  * @package SimplePie
8310  */
8311 class SimplePie_gzdecode
8312 {
8313         /**
8314          * Compressed data
8315          *
8316          * @access private
8317          * @see gzdecode::$data
8318          */
8319         var $compressed_data;
8320
8321         /**
8322          * Size of compressed data
8323          *
8324          * @access private
8325          */
8326         var $compressed_size;
8327
8328         /**
8329          * Minimum size of a valid gzip string
8330          *
8331          * @access private
8332          */
8333         var $min_compressed_size = 18;
8334
8335         /**
8336          * Current position of pointer
8337          *
8338          * @access private
8339          */
8340         var $position = 0;
8341
8342         /**
8343          * Flags (FLG)
8344          *
8345          * @access private
8346          */
8347         var $flags;
8348
8349         /**
8350          * Uncompressed data
8351          *
8352          * @access public
8353          * @see gzdecode::$compressed_data
8354          */
8355         var $data;
8356
8357         /**
8358          * Modified time
8359          *
8360          * @access public
8361          */
8362         var $MTIME;
8363
8364         /**
8365          * Extra Flags
8366          *
8367          * @access public
8368          */
8369         var $XFL;
8370
8371         /**
8372          * Operating System
8373          *
8374          * @access public
8375          */
8376         var $OS;
8377
8378         /**
8379          * Subfield ID 1
8380          *
8381          * @access public
8382          * @see gzdecode::$extra_field
8383          * @see gzdecode::$SI2
8384          */
8385         var $SI1;
8386
8387         /**
8388          * Subfield ID 2
8389          *
8390          * @access public
8391          * @see gzdecode::$extra_field
8392          * @see gzdecode::$SI1
8393          */
8394         var $SI2;
8395
8396         /**
8397          * Extra field content
8398          *
8399          * @access public
8400          * @see gzdecode::$SI1
8401          * @see gzdecode::$SI2
8402          */
8403         var $extra_field;
8404
8405         /**
8406          * Original filename
8407          *
8408          * @access public
8409          */
8410         var $filename;
8411
8412         /**
8413          * Human readable comment
8414          *
8415          * @access public
8416          */
8417         var $comment;
8418
8419         /**
8420          * Don't allow anything to be set
8421          *
8422          * @access public
8423          */
8424         function __set($name, $value)
8425         {
8426                 trigger_error("Cannot write property $name", E_USER_ERROR);
8427         }
8428
8429         /**
8430          * Set the compressed string and related properties
8431          *
8432          * @access public
8433          */
8434         function SimplePie_gzdecode($data)
8435         {
8436                 $this->compressed_data = $data;
8437                 $this->compressed_size = strlen($data);
8438         }
8439
8440         /**
8441          * Decode the GZIP stream
8442          *
8443          * @access public
8444          */
8445         function parse()
8446         {
8447                 if ($this->compressed_size >= $this->min_compressed_size)
8448                 {
8449                         // Check ID1, ID2, and CM
8450                         if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8451                         {
8452                                 return false;
8453                         }
8454
8455                         // Get the FLG (FLaGs)
8456                         $this->flags = ord($this->compressed_data[3]);
8457
8458                         // FLG bits above (1 << 4) are reserved
8459                         if ($this->flags > 0x1F)
8460                         {
8461                                 return false;
8462                         }
8463
8464                         // Advance the pointer after the above
8465                         $this->position += 4;
8466
8467                         // MTIME
8468                         $mtime = substr($this->compressed_data, $this->position, 4);
8469                         // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8470                         if (current(unpack('S', "\x00\x01")) === 1)
8471                         {
8472                                 $mtime = strrev($mtime);
8473                         }
8474                         $this->MTIME = current(unpack('l', $mtime));
8475                         $this->position += 4;
8476
8477                         // Get the XFL (eXtra FLags)
8478                         $this->XFL = ord($this->compressed_data[$this->position++]);
8479
8480                         // Get the OS (Operating System)
8481                         $this->OS = ord($this->compressed_data[$this->position++]);
8482
8483                         // Parse the FEXTRA
8484                         if ($this->flags & 4)
8485                         {
8486                                 // Read subfield IDs
8487                                 $this->SI1 = $this->compressed_data[$this->position++];
8488                                 $this->SI2 = $this->compressed_data[$this->position++];
8489
8490                                 // SI2 set to zero is reserved for future use
8491                                 if ($this->SI2 === "\x00")
8492                                 {
8493                                         return false;
8494                                 }
8495
8496                                 // Get the length of the extra field
8497                                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8498                                 $this->position += 2;
8499
8500                                 // Check the length of the string is still valid
8501                                 $this->min_compressed_size += $len + 4;
8502                                 if ($this->compressed_size >= $this->min_compressed_size)
8503                                 {
8504                                         // Set the extra field to the given data
8505                                         $this->extra_field = substr($this->compressed_data, $this->position, $len);
8506                                         $this->position += $len;
8507                                 }
8508                                 else
8509                                 {
8510                                         return false;
8511                                 }
8512                         }
8513
8514                         // Parse the FNAME
8515                         if ($this->flags & 8)
8516                         {
8517                                 // Get the length of the filename
8518                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8519
8520                                 // Check the length of the string is still valid
8521                                 $this->min_compressed_size += $len + 1;
8522                                 if ($this->compressed_size >= $this->min_compressed_size)
8523                                 {
8524                                         // Set the original filename to the given string
8525                                         $this->filename = substr($this->compressed_data, $this->position, $len);
8526                                         $this->position += $len + 1;
8527                                 }
8528                                 else
8529                                 {
8530                                         return false;
8531                                 }
8532                         }
8533
8534                         // Parse the FCOMMENT
8535                         if ($this->flags & 16)
8536                         {
8537                                 // Get the length of the comment
8538                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8539
8540                                 // Check the length of the string is still valid
8541                                 $this->min_compressed_size += $len + 1;
8542                                 if ($this->compressed_size >= $this->min_compressed_size)
8543                                 {
8544                                         // Set the original comment to the given string
8545                                         $this->comment = substr($this->compressed_data, $this->position, $len);
8546                                         $this->position += $len + 1;
8547                                 }
8548                                 else
8549                                 {
8550                                         return false;
8551                                 }
8552                         }
8553
8554                         // Parse the FHCRC
8555                         if ($this->flags & 2)
8556                         {
8557                                 // Check the length of the string is still valid
8558                                 $this->min_compressed_size += $len + 2;
8559                                 if ($this->compressed_size >= $this->min_compressed_size)
8560                                 {
8561                                         // Read the CRC
8562                                         $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8563
8564                                         // Check the CRC matches
8565                                         if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8566                                         {
8567                                                 $this->position += 2;
8568                                         }
8569                                         else
8570                                         {
8571                                                 return false;
8572                                         }
8573                                 }
8574                                 else
8575                                 {
8576                                         return false;
8577                                 }
8578                         }
8579
8580                         // Decompress the actual data
8581                         if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8582                         {
8583                                 return false;
8584                         }
8585                         else
8586                         {
8587                                 $this->position = $this->compressed_size - 8;
8588                         }
8589
8590                         // Check CRC of data
8591                         $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8592                         $this->position += 4;
8593                         /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8594                         {
8595                                 return false;
8596                         }*/
8597
8598                         // Check ISIZE of data
8599                         $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8600                         $this->position += 4;
8601                         if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8602                         {
8603                                 return false;
8604                         }
8605
8606                         // Wow, against all odds, we've actually got a valid gzip string
8607                         return true;
8608                 }
8609                 else
8610                 {
8611                         return false;
8612                 }
8613         }
8614 }
8615
8616 class SimplePie_Cache
8617 {
8618         /**
8619          * Don't call the constructor. Please.
8620          *
8621          * @access private
8622          */
8623         function SimplePie_Cache()
8624         {
8625                 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8626         }
8627
8628         /**
8629          * Create a new SimplePie_Cache object
8630          *
8631          * @static
8632          * @access public
8633          */
8634         function create($location, $filename, $extension)
8635         {
8636                 $location_iri =& new SimplePie_IRI($location);
8637                 switch ($location_iri->get_scheme())
8638                 {
8639                         case 'mysql':
8640                                 if (extension_loaded('mysql'))
8641                                 {
8642                                         return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8643                                 }
8644                                 break;
8645
8646                         default:
8647                                 return new SimplePie_Cache_File($location, $filename, $extension);
8648                 }
8649         }
8650 }
8651
8652 class SimplePie_Cache_File
8653 {
8654         var $location;
8655         var $filename;
8656         var $extension;
8657         var $name;
8658
8659         function SimplePie_Cache_File($location, $filename, $extension)
8660         {
8661                 $this->location = $location;
8662                 $this->filename = $filename;
8663                 $this->extension = $extension;
8664                 $this->name = "$this->location/$this->filename.$this->extension";
8665         }
8666
8667         function save($data)
8668         {
8669                 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8670                 {
8671                         if (is_a($data, 'SimplePie'))
8672                         {
8673                                 $data = $data->data;
8674                         }
8675
8676                         $data = serialize($data);
8677
8678                         if (function_exists('file_put_contents'))
8679                         {
8680                                 return (bool) file_put_contents($this->name, $data);
8681                         }
8682                         else
8683                         {
8684                                 $fp = fopen($this->name, 'wb');
8685                                 if ($fp)
8686                                 {
8687                                         fwrite($fp, $data);
8688                                         fclose($fp);
8689                                         return true;
8690                                 }
8691                         }
8692                 }
8693                 return false;
8694         }
8695
8696         function load()
8697         {
8698                 if (file_exists($this->name) && is_readable($this->name))
8699                 {
8700                         return unserialize(file_get_contents($this->name));
8701                 }
8702                 return false;
8703         }
8704
8705         function mtime()
8706         {
8707                 if (file_exists($this->name))
8708                 {
8709                         return filemtime($this->name);
8710                 }
8711                 return false;
8712         }
8713
8714         function touch()
8715         {
8716                 if (file_exists($this->name))
8717                 {
8718                         return touch($this->name);
8719                 }
8720                 return false;
8721         }
8722
8723         function unlink()
8724         {
8725                 if (file_exists($this->name))
8726                 {
8727                         return unlink($this->name);
8728                 }
8729                 return false;
8730         }
8731 }
8732
8733 class SimplePie_Cache_DB
8734 {
8735         function prepare_simplepie_object_for_cache($data)
8736         {
8737                 $items = $data->get_items();
8738                 $items_by_id = array();
8739
8740                 if (!empty($items))
8741                 {
8742                         foreach ($items as $item)
8743                         {
8744                                 $items_by_id[$item->get_id()] = $item;
8745                         }
8746
8747                         if (count($items_by_id) !== count($items))
8748                         {
8749                                 $items_by_id = array();
8750                                 foreach ($items as $item)
8751                                 {
8752                                         $items_by_id[$item->get_id(true)] = $item;
8753                                 }
8754                         }
8755
8756                         if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8757                         {
8758                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8759                         }
8760                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8761                         {
8762                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8763                         }
8764                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8765                         {
8766                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8767                         }
8768                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8769                         {
8770                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8771                         }
8772                         else
8773                         {
8774                                 $channel = null;
8775                         }
8776
8777                         if ($channel !== null)
8778                         {
8779                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8780                                 {
8781                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8782                                 }
8783                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8784                                 {
8785                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8786                                 }
8787                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8788                                 {
8789                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8790                                 }
8791                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8792                                 {
8793                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8794                                 }
8795                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8796                                 {
8797                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8798                                 }
8799                         }
8800                         if (isset($data->data['items']))
8801                         {
8802                                 unset($data->data['items']);
8803                         }
8804                         if (isset($data->data['ordered_items']))
8805                         {
8806                                 unset($data->data['ordered_items']);
8807                         }
8808                 }
8809                 return array(serialize($data->data), $items_by_id);
8810         }
8811 }
8812
8813 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8814 {
8815         var $mysql;
8816         var $options;
8817         var $id;
8818
8819         function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8820         {
8821                 $host = $mysql_location->get_host();
8822                 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8823                 {
8824                         $server = ':' . substr($host, 5, -1);
8825                 }
8826                 else
8827                 {
8828                         $server = $host;
8829                         if ($mysql_location->get_port() !== null)
8830                         {
8831                                 $server .= ':' . $mysql_location->get_port();
8832                         }
8833                 }
8834
8835                 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8836                 {
8837                         list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8838                 }
8839                 else
8840                 {
8841                         $username = $mysql_location->get_userinfo();
8842                         $password = null;
8843                 }
8844
8845                 if ($this->mysql = mysql_connect($server, $username, $password))
8846                 {
8847                         $this->id = $name . $extension;
8848                         $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8849                         if (!isset($this->options['prefix'][0]))
8850                         {
8851                                 $this->options['prefix'][0] = '';
8852                         }
8853
8854                         if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8855                                 && mysql_query('SET NAMES utf8')
8856                                 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8857                         {
8858                                 $db = array();
8859                                 while ($row = mysql_fetch_row($query))
8860                                 {
8861                                         $db[] = $row[0];
8862                                 }
8863
8864                                 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8865                                 {
8866                                         if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))'))
8867                                         {
8868                                                 $this->mysql = null;
8869                                         }
8870                                 }
8871
8872                                 if (!in_array($this->options['prefix'][0] . 'items', $db))
8873                                 {
8874                                         if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'))
8875                                         {
8876                                                 $this->mysql = null;
8877                                         }
8878                                 }
8879                         }
8880                         else
8881                         {
8882                                 $this->mysql = null;
8883                         }
8884                 }
8885         }
8886
8887         function save($data)
8888         {
8889                 if ($this->mysql)
8890                 {
8891                         $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8892
8893                         if (is_a($data, 'SimplePie'))
8894                         {
8895                                 if (SIMPLEPIE_PHP5)
8896                                 {
8897                                         // This keyword needs to defy coding standards for PHP4 compatibility
8898                                         $data = clone($data);
8899                                 }
8900
8901                                 $prepared = $this->prepare_simplepie_object_for_cache($data);
8902
8903                                 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8904                                 {
8905                                         if (mysql_num_rows($query))
8906                                         {
8907                                                 $items = count($prepared[1]);
8908                                                 if ($items)
8909                                                 {
8910                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8911                                                 }
8912                                                 else
8913                                                 {
8914                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8915                                                 }
8916
8917                                                 if (!mysql_query($sql, $this->mysql))
8918                                                 {
8919                                                         return false;
8920                                                 }
8921                                         }
8922                                         elseif (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(' . $feed_id . ', ' . count($prepared[1]) . ', \'' . mysql_real_escape_string($prepared[0]) . '\', ' . time() . ')', $this->mysql))
8923                                         {
8924                                                 return false;
8925                                         }
8926
8927                                         $ids = array_keys($prepared[1]);
8928                                         if (!empty($ids))
8929                                         {
8930                                                 foreach ($ids as $id)
8931                                                 {
8932                                                         $database_ids[] = mysql_real_escape_string($id);
8933                                                 }
8934
8935                                                 if ($query = mysql_unbuffered_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'items` WHERE `id` = \'' . implode('\' OR `id` = \'', $database_ids) . '\' AND `feed_id` = ' . $feed_id, $this->mysql))
8936                                                 {
8937                                                         $existing_ids = array();
8938                                                         while ($row = mysql_fetch_row($query))
8939                                                         {
8940                                                                 $existing_ids[] = $row[0];
8941                                                         }
8942
8943                                                         $new_ids = array_diff($ids, $existing_ids);
8944
8945                                                         foreach ($new_ids as $new_id)
8946                                                         {
8947                                                                 if (!($date = $prepared[1][$new_id]->get_date('U')))
8948                                                                 {
8949                                                                         $date = time();
8950                                                                 }
8951
8952                                                                 if (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(' . $feed_id . ', \'' . mysql_real_escape_string($new_id) . '\', \'' . mysql_real_escape_string(serialize($prepared[1][$new_id]->data)) . '\', ' . $date . ')', $this->mysql))
8953                                                                 {
8954                                                                         return false;
8955                                                                 }
8956                                                         }
8957                                                         return true;
8958                                                 }
8959                                         }
8960                                         else
8961                                         {
8962                                                 return true;
8963                                         }
8964                                 }
8965                         }
8966                         elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8967                         {
8968                                 if (mysql_num_rows($query))
8969                                 {
8970                                         if (mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = 0, `data` = \'' . mysql_real_escape_string(serialize($data)) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id, $this->mysql))
8971                                         {
8972                                                 return true;
8973                                         }
8974                                 }
8975                                 elseif (mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(\'' . mysql_real_escape_string($this->id) . '\', 0, \'' . mysql_real_escape_string(serialize($data)) . '\', ' . time() . ')', $this->mysql))
8976                                 {
8977                                         return true;
8978                                 }
8979                         }
8980                 }
8981                 return false;
8982         }
8983
8984         function load()
8985         {
8986                 if ($this->mysql && ($query = mysql_query('SELECT `items`, `data` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
8987                 {
8988                         $data = unserialize($row[1]);
8989
8990                         if (isset($this->options['items'][0]))
8991                         {
8992                                 $items = (int) $this->options['items'][0];
8993                         }
8994                         else
8995                         {
8996                                 $items = (int) $row[0];
8997                         }
8998
8999                         if ($items !== 0)
9000                         {
9001                                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9002                                 {
9003                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9004                                 }
9005                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9006                                 {
9007                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9008                                 }
9009                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9010                                 {
9011                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9012                                 }
9013                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9014                                 {
9015                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9016                                 }
9017                                 else
9018                                 {
9019                                         $feed = null;
9020                                 }
9021
9022                                 if ($feed !== null)
9023                                 {
9024                                         $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9025                                         if ($items > 0)
9026                                         {
9027                                                 $sql .= ' LIMIT ' . $items;
9028                                         }
9029
9030                                         if ($query = mysql_unbuffered_query($sql, $this->mysql))
9031                                         {
9032                                                 while ($row = mysql_fetch_row($query))
9033                                                 {
9034                                                         $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9035                                                 }
9036                                         }
9037                                         else
9038                                         {
9039                                                 return false;
9040                                         }
9041                                 }
9042                         }
9043                         return $data;
9044                 }
9045                 return false;
9046         }
9047
9048         function mtime()
9049         {
9050                 if ($this->mysql && ($query = mysql_query('SELECT `mtime` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
9051                 {
9052                         return $row[0];
9053                 }
9054                 else
9055                 {
9056                         return false;
9057                 }
9058         }
9059
9060         function touch()
9061         {
9062                 if ($this->mysql && ($query = mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `mtime` = ' . time() . ' WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && mysql_affected_rows($this->mysql))
9063                 {
9064                         return true;
9065                 }
9066                 else
9067                 {
9068                         return false;
9069                 }
9070         }
9071
9072         function unlink()
9073         {
9074                 if ($this->mysql && ($query = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($query2 = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)))
9075                 {
9076                         return true;
9077                 }
9078                 else
9079                 {
9080                         return false;
9081                 }
9082         }
9083 }
9084
9085 class SimplePie_Misc
9086 {
9087         function time_hms($seconds)
9088         {
9089                 $time = '';
9090
9091                 $hours = floor($seconds / 3600);
9092                 $remainder = $seconds % 3600;
9093                 if ($hours > 0)
9094                 {
9095                         $time .= $hours.':';
9096                 }
9097
9098                 $minutes = floor($remainder / 60);
9099                 $seconds = $remainder % 60;
9100                 if ($minutes < 10 && $hours > 0)
9101                 {
9102                         $minutes = '0' . $minutes;
9103                 }
9104                 if ($seconds < 10)
9105                 {
9106                         $seconds = '0' . $seconds;
9107                 }
9108
9109                 $time .= $minutes.':';
9110                 $time .= $seconds;
9111
9112                 return $time;
9113         }
9114
9115         function absolutize_url($relative, $base)
9116         {
9117                 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9118                 return $iri->get_iri();
9119         }
9120
9121         function remove_dot_segments($input)
9122         {
9123                 $output = '';
9124                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9125                 {
9126                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9127                         if (strpos($input, '../') === 0)
9128                         {
9129                                 $input = substr($input, 3);
9130                         }
9131                         elseif (strpos($input, './') === 0)
9132                         {
9133                                 $input = substr($input, 2);
9134                         }
9135                         // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
9136                         elseif (strpos($input, '/./') === 0)
9137                         {
9138                                 $input = substr_replace($input, '/', 0, 3);
9139                         }
9140                         elseif ($input === '/.')
9141                         {
9142                                 $input = '/';
9143                         }
9144                         // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
9145                         elseif (strpos($input, '/../') === 0)
9146                         {
9147                                 $input = substr_replace($input, '/', 0, 4);
9148                                 $output = substr_replace($output, '', strrpos($output, '/'));
9149                         }
9150                         elseif ($input === '/..')
9151                         {
9152                                 $input = '/';
9153                                 $output = substr_replace($output, '', strrpos($output, '/'));
9154                         }
9155                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9156                         elseif ($input === '.' || $input === '..')
9157                         {
9158                                 $input = '';
9159                         }
9160                         // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
9161                         elseif (($pos = strpos($input, '/', 1)) !== false)
9162                         {
9163                                 $output .= substr($input, 0, $pos);
9164                                 $input = substr_replace($input, '', 0, $pos);
9165                         }
9166                         else
9167                         {
9168                                 $output .= $input;
9169                                 $input = '';
9170                         }
9171                 }
9172                 return $output . $input;
9173         }
9174
9175         function get_element($realname, $string)
9176         {
9177                 $return = array();
9178                 $name = preg_quote($realname, '/');
9179                 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9180                 {
9181                         for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9182                         {
9183                                 $return[$i]['tag'] = $realname;
9184                                 $return[$i]['full'] = $matches[$i][0][0];
9185                                 $return[$i]['offset'] = $matches[$i][0][1];
9186                                 if (strlen($matches[$i][3][0]) <= 2)
9187                                 {
9188                                         $return[$i]['self_closing'] = true;
9189                                 }
9190                                 else
9191                                 {
9192                                         $return[$i]['self_closing'] = false;
9193                                         $return[$i]['content'] = $matches[$i][4][0];
9194                                 }
9195                                 $return[$i]['attribs'] = array();
9196                                 if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))
9197                                 {
9198                                         for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9199                                         {
9200                                                 if (count($attribs[$j]) === 2)
9201                                                 {
9202                                                         $attribs[$j][2] = $attribs[$j][1];
9203                                                 }
9204                                                 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9205                                         }
9206                                 }
9207                         }
9208                 }
9209                 return $return;
9210         }
9211
9212         function element_implode($element)
9213         {
9214                 $full = "<$element[tag]";
9215                 foreach ($element['attribs'] as $key => $value)
9216                 {
9217                         $key = strtolower($key);
9218                         $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9219                 }
9220                 if ($element['self_closing'])
9221                 {
9222                         $full .= ' />';
9223                 }
9224                 else
9225                 {
9226                         $full .= ">$element[content]</$element[tag]>";
9227                 }
9228                 return $full;
9229         }
9230
9231         function error($message, $level, $file, $line)
9232         {
9233                 if ((ini_get('error_reporting') & $level) > 0)
9234                 {
9235                         switch ($level)
9236                         {
9237                                 case E_USER_ERROR:
9238                                         $note = 'PHP Error';
9239                                         break;
9240                                 case E_USER_WARNING:
9241                                         $note = 'PHP Warning';
9242                                         break;
9243                                 case E_USER_NOTICE:
9244                                         $note = 'PHP Notice';
9245                                         break;
9246                                 default:
9247                                         $note = 'Unknown Error';
9248                                         break;
9249                         }
9250
9251                         $log_error = true;
9252                         if (!function_exists('error_log'))
9253                         {
9254                                 $log_error = false;
9255                         }
9256
9257                         $log_file = @ini_get('error_log');
9258                         if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9259                         {
9260                                 $log_error = false;
9261                         }
9262
9263                         if ($log_error)
9264                         {
9265                                 @error_log("$note: $message in $file on line $line", 0);
9266                         }
9267                 }
9268
9269                 return $message;
9270         }
9271
9272         /**
9273          * If a file has been cached, retrieve and display it.
9274          *
9275          * This is most useful for caching images (get_favicon(), etc.),
9276          * however it works for all cached files.  This WILL NOT display ANY
9277          * file/image/page/whatever, but rather only display what has already
9278          * been cached by SimplePie.
9279          *
9280          * @access public
9281          * @see SimplePie::get_favicon()
9282          * @param str $identifier_url URL that is used to identify the content.
9283          * This may or may not be the actual URL of the live content.
9284          * @param str $cache_location Location of SimplePie's cache.  Defaults
9285          * to './cache'.
9286          * @param str $cache_extension The file extension that the file was
9287          * cached with.  Defaults to 'spc'.
9288          * @param str $cache_class Name of the cache-handling class being used
9289          * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
9290          * as-is unless you've overloaded the class.
9291          * @param str $cache_name_function Obsolete. Exists for backwards
9292          * compatibility reasons only.
9293          */
9294         function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9295         {
9296                 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9297
9298                 if ($file = $cache->load())
9299                 {
9300                         if (isset($file['headers']['content-type']))
9301                         {
9302                                 header('Content-type:' . $file['headers']['content-type']);
9303                         }
9304                         else
9305                         {
9306                                 header('Content-type: application/octet-stream');
9307                         }
9308                         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9309                         echo $file['body'];
9310                         exit;
9311                 }
9312
9313                 die('Cached file for ' . $identifier_url . ' cannot be found.');
9314         }
9315
9316         function fix_protocol($url, $http = 1)
9317         {
9318                 $url = SimplePie_Misc::normalize_url($url);
9319                 $parsed = SimplePie_Misc::parse_url($url);
9320                 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9321                 {
9322                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9323                 }
9324
9325                 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9326                 {
9327                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9328                 }
9329
9330                 if ($http === 2 && $parsed['scheme'] !== '')
9331                 {
9332                         return "feed:$url";
9333                 }
9334                 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9335                 {
9336                         return substr_replace($url, 'podcast', 0, 4);
9337                 }
9338                 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9339                 {
9340                         return substr_replace($url, 'itpc', 0, 4);
9341                 }
9342                 else
9343                 {
9344                         return $url;
9345                 }
9346         }
9347
9348         function parse_url($url)
9349         {
9350                 $iri =& new SimplePie_IRI($url);
9351                 return array(
9352                         'scheme' => (string) $iri->get_scheme(),
9353                         'authority' => (string) $iri->get_authority(),
9354                         'path' => (string) $iri->get_path(),
9355                         'query' => (string) $iri->get_query(),
9356                         'fragment' => (string) $iri->get_fragment()
9357                 );
9358         }
9359
9360         function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9361         {
9362                 $iri =& new SimplePie_IRI('');
9363                 $iri->set_scheme($scheme);
9364                 $iri->set_authority($authority);
9365                 $iri->set_path($path);
9366                 $iri->set_query($query);
9367                 $iri->set_fragment($fragment);
9368                 return $iri->get_iri();
9369         }
9370
9371         function normalize_url($url)
9372         {
9373                 $iri =& new SimplePie_IRI($url);
9374                 return $iri->get_iri();
9375         }
9376
9377         function percent_encoding_normalization($match)
9378         {
9379                 $integer = hexdec($match[1]);
9380                 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9381                 {
9382                         return chr($integer);
9383                 }
9384                 else
9385                 {
9386                         return strtoupper($match[0]);
9387                 }
9388         }
9389
9390         /**
9391          * Remove bad UTF-8 bytes
9392          *
9393          * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9394          * FAQ: Multilingual Forms (modified to include full ASCII range)
9395          *
9396          * @author Geoffrey Sneddon
9397          * @see http://www.w3.org/International/questions/qa-forms-utf-8
9398          * @param string $str String to remove bad UTF-8 bytes from
9399          * @return string UTF-8 string
9400          */
9401         function utf8_bad_replace($str)
9402         {
9403                 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9404                 {
9405                         return $return;
9406                 }
9407                 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9408                 {
9409                         return $return;
9410                 }
9411                 elseif (preg_match_all('/(?:[\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})+/', $str, $matches))
9412                 {
9413                         return implode("\xEF\xBF\xBD", $matches[0]);
9414                 }
9415                 elseif ($str !== '')
9416                 {
9417                         return "\xEF\xBF\xBD";
9418                 }
9419                 else
9420                 {
9421                         return '';
9422                 }
9423         }
9424
9425         /**
9426          * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9427          *
9428          * @static
9429          * @access public
9430          * @param string $string Windows-1252 encoded string
9431          * @return string UTF-8 encoded string
9432          */
9433         function windows_1252_to_utf8($string)
9434         {
9435                 static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF");
9436
9437                 return strtr($string, $convert_table);
9438         }
9439
9440         function change_encoding($data, $input, $output)
9441         {
9442                 $input = SimplePie_Misc::encoding($input);
9443                 $output = SimplePie_Misc::encoding($output);
9444
9445                 // We fail to fail on non US-ASCII bytes
9446                 if ($input === 'US-ASCII')
9447                 {
9448                         static $non_ascii_octects = '';
9449                         if (!$non_ascii_octects)
9450                         {
9451                                 for ($i = 0x80; $i <= 0xFF; $i++)
9452                                 {
9453                                         $non_ascii_octects .= chr($i);
9454                                 }
9455                         }
9456                         $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9457                 }
9458
9459                 // This is first, as behaviour of this is completely predictable
9460                 if ($input === 'windows-1252' && $output === 'UTF-8')
9461                 {
9462                         return SimplePie_Misc::windows_1252_to_utf8($data);
9463                 }
9464                 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9465                 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && in_array($input, mb_list_encodings()) && ($return = @mb_convert_encoding($data, $output, $input)))
9466                 {
9467                         return $return;
9468                 }
9469                 // This is last, as behaviour of this varies with OS userland and PHP version
9470                 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9471                 {
9472                         return $return;
9473                 }
9474                 // If we can't do anything, just fail
9475                 else
9476                 {
9477                         return false;
9478                 }
9479         }
9480
9481         /**
9482          * Normalize an encoding name
9483          *
9484          * This is automatically generated by create.php
9485          *
9486          * To generate it, run `php create.php` on the command line, and copy the
9487          * output to replace this function.
9488          *
9489          * @param string $charset Character set to standardise
9490          * @return string Standardised name
9491          */
9492         function encoding($charset)
9493         {
9494                 // Normalization from UTS #22
9495                 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9496                 {
9497                         case 'adobestandardencoding':
9498                         case 'csadobestandardencoding':
9499                                 return 'Adobe-Standard-Encoding';
9500
9501                         case 'adobesymbolencoding':
9502                         case 'cshppsmath':
9503                                 return 'Adobe-Symbol-Encoding';
9504
9505                         case 'ami1251':
9506                         case 'amiga1251':
9507                                 return 'Amiga-1251';
9508
9509                         case 'ansix31101983':
9510                         case 'csat5001983':
9511                         case 'csiso99naplps':
9512                         case 'isoir99':
9513                         case 'naplps':
9514                                 return 'ANSI_X3.110-1983';
9515
9516                         case 'arabic7':
9517                         case 'asmo449':
9518                         case 'csiso89asmo449':
9519                         case 'iso9036':
9520                         case 'isoir89':
9521                                 return 'ASMO_449';
9522
9523                         case 'big5':
9524                         case 'csbig5':
9525                                 return 'Big5';
9526
9527                         case 'big5hkscs':
9528                                 return 'Big5-HKSCS';
9529
9530                         case 'bocu1':
9531                         case 'csbocu1':
9532                                 return 'BOCU-1';
9533
9534                         case 'brf':
9535                         case 'csbrf':
9536                                 return 'BRF';
9537
9538                         case 'bs4730':
9539                         case 'csiso4unitedkingdom':
9540                         case 'gb':
9541                         case 'iso646gb':
9542                         case 'isoir4':
9543                         case 'uk':
9544                                 return 'BS_4730';
9545
9546                         case 'bsviewdata':
9547                         case 'csiso47bsviewdata':
9548                         case 'isoir47':
9549                                 return 'BS_viewdata';
9550
9551                         case 'cesu8':
9552                         case 'cscesu8':
9553                                 return 'CESU-8';
9554
9555                         case 'ca':
9556                         case 'csa71':
9557                         case 'csaz243419851':
9558                         case 'csiso121canadian1':
9559                         case 'iso646ca':
9560                         case 'isoir121':
9561                                 return 'CSA_Z243.4-1985-1';
9562
9563                         case 'csa72':
9564                         case 'csaz243419852':
9565                         case 'csiso122canadian2':
9566                         case 'iso646ca2':
9567                         case 'isoir122':
9568                                 return 'CSA_Z243.4-1985-2';
9569
9570                         case 'csaz24341985gr':
9571                         case 'csiso123csaz24341985gr':
9572                         case 'isoir123':
9573                                 return 'CSA_Z243.4-1985-gr';
9574
9575                         case 'csiso139csn369103':
9576                         case 'csn369103':
9577                         case 'isoir139':
9578                                 return 'CSN_369103';
9579
9580                         case 'csdecmcs':
9581                         case 'dec':
9582                         case 'decmcs':
9583                                 return 'DEC-MCS';
9584
9585                         case 'csiso21german':
9586                         case 'de':
9587                         case 'din66003':
9588                         case 'iso646de':
9589                         case 'isoir21':
9590                                 return 'DIN_66003';
9591
9592                         case 'csdkus':
9593                         case 'dkus':
9594                                 return 'dk-us';
9595
9596                         case 'csiso646danish':
9597                         case 'dk':
9598                         case 'ds2089':
9599                         case 'iso646dk':
9600                                 return 'DS_2089';
9601
9602                         case 'csibmebcdicatde':
9603                         case 'ebcdicatde':
9604                                 return 'EBCDIC-AT-DE';
9605
9606                         case 'csebcdicatdea':
9607                         case 'ebcdicatdea':
9608                                 return 'EBCDIC-AT-DE-A';
9609
9610                         case 'csebcdiccafr':
9611                         case 'ebcdiccafr':
9612                                 return 'EBCDIC-CA-FR';
9613
9614                         case 'csebcdicdkno':
9615                         case 'ebcdicdkno':
9616                                 return 'EBCDIC-DK-NO';
9617
9618                         case 'csebcdicdknoa':
9619                         case 'ebcdicdknoa':
9620                                 return 'EBCDIC-DK-NO-A';
9621
9622                         case 'csebcdices':
9623                         case 'ebcdices':
9624                                 return 'EBCDIC-ES';
9625
9626                         case 'csebcdicesa':
9627                         case 'ebcdicesa':
9628                                 return 'EBCDIC-ES-A';
9629
9630                         case 'csebcdicess':
9631                         case 'ebcdicess':
9632                                 return 'EBCDIC-ES-S';
9633
9634                         case 'csebcdicfise':
9635                         case 'ebcdicfise':
9636                                 return 'EBCDIC-FI-SE';
9637
9638                         case 'csebcdicfisea':
9639                         case 'ebcdicfisea':
9640                                 return 'EBCDIC-FI-SE-A';
9641
9642                         case 'csebcdicfr':
9643                         case 'ebcdicfr':
9644                                 return 'EBCDIC-FR';
9645
9646                         case 'csebcdicit':
9647                         case 'ebcdicit':
9648                                 return 'EBCDIC-IT';
9649
9650                         case 'csebcdicpt':
9651                         case 'ebcdicpt':
9652                                 return 'EBCDIC-PT';
9653
9654                         case 'csebcdicuk':
9655                         case 'ebcdicuk':
9656                                 return 'EBCDIC-UK';
9657
9658                         case 'csebcdicus':
9659                         case 'ebcdicus':
9660                                 return 'EBCDIC-US';
9661
9662                         case 'csiso111ecmacyrillic':
9663                         case 'ecmacyrillic':
9664                         case 'isoir111':
9665                         case 'koi8e':
9666                                 return 'ECMA-cyrillic';
9667
9668                         case 'csiso17spanish':
9669                         case 'es':
9670                         case 'iso646es':
9671                         case 'isoir17':
9672                                 return 'ES';
9673
9674                         case 'csiso85spanish2':
9675                         case 'es2':
9676                         case 'iso646es2':
9677                         case 'isoir85':
9678                                 return 'ES2';
9679
9680                         case 'cseucpkdfmtjapanese':
9681                         case 'eucjp':
9682                         case 'extendedunixcodepackedformatforjapanese':
9683                                 return 'EUC-JP';
9684
9685                         case 'cseucfixwidjapanese':
9686                         case 'extendedunixcodefixedwidthforjapanese':
9687                                 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9688
9689                         case 'gb18030':
9690                                 return 'GB18030';
9691
9692                         case 'chinese':
9693                         case 'cp936':
9694                         case 'csgb2312':
9695                         case 'csiso58gb231280':
9696                         case 'gb2312':
9697                         case 'gb231280':
9698                         case 'gbk':
9699                         case 'isoir58':
9700                         case 'ms936':
9701                         case 'windows936':
9702                                 return 'GBK';
9703
9704                         case 'cn':
9705                         case 'csiso57gb1988':
9706                         case 'gb198880':
9707                         case 'iso646cn':
9708                         case 'isoir57':
9709                                 return 'GB_1988-80';
9710
9711                         case 'csiso153gost1976874':
9712                         case 'gost1976874':
9713                         case 'isoir153':
9714                         case 'stsev35888':
9715                                 return 'GOST_19768-74';
9716
9717                         case 'csiso150':
9718                         case 'csiso150greekccitt':
9719                         case 'greekccitt':
9720                         case 'isoir150':
9721                                 return 'greek-ccitt';
9722
9723                         case 'csiso88greek7':
9724                         case 'greek7':
9725                         case 'isoir88':
9726                                 return 'greek7';
9727
9728                         case 'csiso18greek7old':
9729                         case 'greek7old':
9730                         case 'isoir18':
9731                                 return 'greek7-old';
9732
9733                         case 'cshpdesktop':
9734                         case 'hpdesktop':
9735                                 return 'HP-DeskTop';
9736
9737                         case 'cshplegal':
9738                         case 'hplegal':
9739                                 return 'HP-Legal';
9740
9741                         case 'cshpmath8':
9742                         case 'hpmath8':
9743                                 return 'HP-Math8';
9744
9745                         case 'cshppifont':
9746                         case 'hppifont':
9747                                 return 'HP-Pi-font';
9748
9749                         case 'cshproman8':
9750                         case 'hproman8':
9751                         case 'r8':
9752                         case 'roman8':
9753                                 return 'hp-roman8';
9754
9755                         case 'hzgb2312':
9756                                 return 'HZ-GB-2312';
9757
9758                         case 'csibmsymbols':
9759                         case 'ibmsymbols':
9760                                 return 'IBM-Symbols';
9761
9762                         case 'csibmthai':
9763                         case 'ibmthai':
9764                                 return 'IBM-Thai';
9765
9766                         case 'cp37':
9767                         case 'csibm37':
9768                         case 'ebcdiccpca':
9769                         case 'ebcdiccpnl':
9770                         case 'ebcdiccpus':
9771                         case 'ebcdiccpwt':
9772                         case 'ibm37':
9773                                 return 'IBM037';
9774
9775                         case 'cp38':
9776                         case 'csibm38':
9777                         case 'ebcdicint':
9778                         case 'ibm38':
9779                                 return 'IBM038';
9780
9781                         case 'cp273':
9782                         case 'csibm273':
9783                         case 'ibm273':
9784                                 return 'IBM273';
9785
9786                         case 'cp274':
9787                         case 'csibm274':
9788                         case 'ebcdicbe':
9789                         case 'ibm274':
9790                                 return 'IBM274';
9791
9792                         case 'cp275':
9793                         case 'csibm275':
9794                         case 'ebcdicbr':
9795                         case 'ibm275':
9796                                 return 'IBM275';
9797
9798                         case 'csibm277':
9799                         case 'ebcdiccpdk':
9800                         case 'ebcdiccpno':
9801                         case 'ibm277':
9802                                 return 'IBM277';
9803
9804                         case 'cp278':
9805                         case 'csibm278':
9806                         case 'ebcdiccpfi':
9807                         case 'ebcdiccpse':
9808                         case 'ibm278':
9809                                 return 'IBM278';
9810
9811                         case 'cp280':
9812                         case 'csibm280':
9813                         case 'ebcdiccpit':
9814                         case 'ibm280':
9815                                 return 'IBM280';
9816
9817                         case 'cp281':
9818                         case 'csibm281':
9819                         case 'ebcdicjpe':
9820                         case 'ibm281':
9821                                 return 'IBM281';
9822
9823                         case 'cp284':
9824                         case 'csibm284':
9825                         case 'ebcdiccpes':
9826                         case 'ibm284':
9827                                 return 'IBM284';
9828
9829                         case 'cp285':
9830                         case 'csibm285':
9831                         case 'ebcdiccpgb':
9832                         case 'ibm285':
9833                                 return 'IBM285';
9834
9835                         case 'cp290':
9836                         case 'csibm290':
9837                         case 'ebcdicjpkana':
9838                         case 'ibm290':
9839                                 return 'IBM290';
9840
9841                         case 'cp297':
9842                         case 'csibm297':
9843                         case 'ebcdiccpfr':
9844                         case 'ibm297':
9845                                 return 'IBM297';
9846
9847                         case 'cp420':
9848                         case 'csibm420':
9849                         case 'ebcdiccpar1':
9850                         case 'ibm420':
9851                                 return 'IBM420';
9852
9853                         case 'cp423':
9854                         case 'csibm423':
9855                         case 'ebcdiccpgr':
9856                         case 'ibm423':
9857                                 return 'IBM423';
9858
9859                         case 'cp424':
9860                         case 'csibm424':
9861                         case 'ebcdiccphe':
9862                         case 'ibm424':
9863                                 return 'IBM424';
9864
9865                         case '437':
9866                         case 'cp437':
9867                         case 'cspc8codepage437':
9868                         case 'ibm437':
9869                                 return 'IBM437';
9870
9871                         case 'cp500':
9872                         case 'csibm500':
9873                         case 'ebcdiccpbe':
9874                         case 'ebcdiccpch':
9875                         case 'ibm500':
9876                                 return 'IBM500';
9877
9878                         case 'cp775':
9879                         case 'cspc775baltic':
9880                         case 'ibm775':
9881                                 return 'IBM775';
9882
9883                         case '850':
9884                         case 'cp850':
9885                         case 'cspc850multilingual':
9886                         case 'ibm850':
9887                                 return 'IBM850';
9888
9889                         case '851':
9890                         case 'cp851':
9891                         case 'csibm851':
9892                         case 'ibm851':
9893                                 return 'IBM851';
9894
9895                         case '852':
9896                         case 'cp852':
9897                         case 'cspcp852':
9898                         case 'ibm852':
9899                                 return 'IBM852';
9900
9901                         case '855':
9902                         case 'cp855':
9903                         case 'csibm855':
9904                         case 'ibm855':
9905                                 return 'IBM855';
9906
9907                         case '857':
9908                         case 'cp857':
9909                         case 'csibm857':
9910                         case 'ibm857':
9911                                 return 'IBM857';
9912
9913                         case 'ccsid858':
9914                         case 'cp858':
9915                         case 'ibm858':
9916                         case 'pcmultilingual850euro':
9917                                 return 'IBM00858';
9918
9919                         case '860':
9920                         case 'cp860':
9921                         case 'csibm860':
9922                         case 'ibm860':
9923                                 return 'IBM860';
9924
9925                         case '861':
9926                         case 'cp861':
9927                         case 'cpis':
9928                         case 'csibm861':
9929                         case 'ibm861':
9930                                 return 'IBM861';
9931
9932                         case '862':
9933                         case 'cp862':
9934                         case 'cspc862latinhebrew':
9935                         case 'ibm862':
9936                                 return 'IBM862';
9937
9938                         case '863':
9939                         case 'cp863':
9940                         case 'csibm863':
9941                         case 'ibm863':
9942                                 return 'IBM863';
9943
9944                         case 'cp864':
9945                         case 'csibm864':
9946                         case 'ibm864':
9947                                 return 'IBM864';
9948
9949                         case '865':
9950                         case 'cp865':
9951                         case 'csibm865':
9952                         case 'ibm865':
9953                                 return 'IBM865';
9954
9955                         case '866':
9956                         case 'cp866':
9957                         case 'csibm866':
9958                         case 'ibm866':
9959                                 return 'IBM866';
9960
9961                         case 'cp868':
9962                         case 'cpar':
9963                         case 'csibm868':
9964                         case 'ibm868':
9965                                 return 'IBM868';
9966
9967                         case '869':
9968                         case 'cp869':
9969                         case 'cpgr':
9970                         case 'csibm869':
9971                         case 'ibm869':
9972                                 return 'IBM869';
9973
9974                         case 'cp870':
9975                         case 'csibm870':
9976                         case 'ebcdiccproece':
9977                         case 'ebcdiccpyu':
9978                         case 'ibm870':
9979                                 return 'IBM870';
9980
9981                         case 'cp871':
9982                         case 'csibm871':
9983                         case 'ebcdiccpis':
9984                         case 'ibm871':
9985                                 return 'IBM871';
9986
9987                         case 'cp880':
9988                         case 'csibm880':
9989                         case 'ebcdiccyrillic':
9990                         case 'ibm880':
9991                                 return 'IBM880';
9992
9993                         case 'cp891':
9994                         case 'csibm891':
9995                         case 'ibm891':
9996                                 return 'IBM891';
9997
9998                         case 'cp903':
9999                         case 'csibm903':
10000                         case 'ibm903':
10001                                 return 'IBM903';
10002
10003                         case '904':
10004                         case 'cp904':
10005                         case 'csibbm904':
10006                         case 'ibm904':
10007                                 return 'IBM904';
10008
10009                         case 'cp905':
10010                         case 'csibm905':
10011                         case 'ebcdiccptr':
10012                         case 'ibm905':
10013                                 return 'IBM905';
10014
10015                         case 'cp918':
10016                         case 'csibm918':
10017                         case 'ebcdiccpar2':
10018                         case 'ibm918':
10019                                 return 'IBM918';
10020
10021                         case 'ccsid924':
10022                         case 'cp924':
10023                         case 'ebcdiclatin9euro':
10024                         case 'ibm924':
10025                                 return 'IBM00924';
10026
10027                         case 'cp1026':
10028                         case 'csibm1026':
10029                         case 'ibm1026':
10030                                 return 'IBM1026';
10031
10032                         case 'ibm1047':
10033                                 return 'IBM1047';
10034
10035                         case 'ccsid1140':
10036                         case 'cp1140':
10037                         case 'ebcdicus37euro':
10038                         case 'ibm1140':
10039                                 return 'IBM01140';
10040
10041                         case 'ccsid1141':
10042                         case 'cp1141':
10043                         case 'ebcdicde273euro':
10044                         case 'ibm1141':
10045                                 return 'IBM01141';
10046
10047                         case 'ccsid1142':
10048                         case 'cp1142':
10049                         case 'ebcdicdk277euro':
10050                         case 'ebcdicno277euro':
10051                         case 'ibm1142':
10052                                 return 'IBM01142';
10053
10054                         case 'ccsid1143':
10055                         case 'cp1143':
10056                         case 'ebcdicfi278euro':
10057                         case 'ebcdicse278euro':
10058                         case 'ibm1143':
10059                                 return 'IBM01143';
10060
10061                         case 'ccsid1144':
10062                         case 'cp1144':
10063                         case 'ebcdicit280euro':
10064                         case 'ibm1144':
10065                                 return 'IBM01144';
10066
10067                         case 'ccsid1145':
10068                         case 'cp1145':
10069                         case 'ebcdices284euro':
10070                         case 'ibm1145':
10071                                 return 'IBM01145';
10072
10073                         case 'ccsid1146':
10074                         case 'cp1146':
10075                         case 'ebcdicgb285euro':
10076                         case 'ibm1146':
10077                                 return 'IBM01146';
10078
10079                         case 'ccsid1147':
10080                         case 'cp1147':
10081                         case 'ebcdicfr297euro':
10082                         case 'ibm1147':
10083                                 return 'IBM01147';
10084
10085                         case 'ccsid1148':
10086                         case 'cp1148':
10087                         case 'ebcdicinternational500euro':
10088                         case 'ibm1148':
10089                                 return 'IBM01148';
10090
10091                         case 'ccsid1149':
10092                         case 'cp1149':
10093                         case 'ebcdicis871euro':
10094                         case 'ibm1149':
10095                                 return 'IBM01149';
10096
10097                         case 'csiso143iecp271':
10098                         case 'iecp271':
10099                         case 'isoir143':
10100                                 return 'IEC_P27-1';
10101
10102                         case 'csiso49inis':
10103                         case 'inis':
10104                         case 'isoir49':
10105                                 return 'INIS';
10106
10107                         case 'csiso50inis8':
10108                         case 'inis8':
10109                         case 'isoir50':
10110                                 return 'INIS-8';
10111
10112                         case 'csiso51iniscyrillic':
10113                         case 'iniscyrillic':
10114                         case 'isoir51':
10115                                 return 'INIS-cyrillic';
10116
10117                         case 'csinvariant':
10118                         case 'invariant':
10119                                 return 'INVARIANT';
10120
10121                         case 'iso2022cn':
10122                                 return 'ISO-2022-CN';
10123
10124                         case 'iso2022cnext':
10125                                 return 'ISO-2022-CN-EXT';
10126
10127                         case 'csiso2022jp':
10128                         case 'iso2022jp':
10129                                 return 'ISO-2022-JP';
10130
10131                         case 'csiso2022jp2':
10132                         case 'iso2022jp2':
10133                                 return 'ISO-2022-JP-2';
10134
10135                         case 'csiso2022kr':
10136                         case 'iso2022kr':
10137                                 return 'ISO-2022-KR';
10138
10139                         case 'cswindows30latin1':
10140                         case 'iso88591windows30latin1':
10141                                 return 'ISO-8859-1-Windows-3.0-Latin-1';
10142
10143                         case 'cswindows31latin1':
10144                         case 'iso88591windows31latin1':
10145                                 return 'ISO-8859-1-Windows-3.1-Latin-1';
10146
10147                         case 'csisolatin2':
10148                         case 'iso88592':
10149                         case 'iso885921987':
10150                         case 'isoir101':
10151                         case 'l2':
10152                         case 'latin2':
10153                                 return 'ISO-8859-2';
10154
10155                         case 'cswindows31latin2':
10156                         case 'iso88592windowslatin2':
10157                                 return 'ISO-8859-2-Windows-Latin-2';
10158
10159                         case 'csisolatin3':
10160                         case 'iso88593':
10161                         case 'iso885931988':
10162                         case 'isoir109':
10163                         case 'l3':
10164                         case 'latin3':
10165                                 return 'ISO-8859-3';
10166
10167                         case 'csisolatin4':
10168                         case 'iso88594':
10169                         case 'iso885941988':
10170                         case 'isoir110':
10171                         case 'l4':
10172                         case 'latin4':
10173                                 return 'ISO-8859-4';
10174
10175                         case 'csisolatincyrillic':
10176                         case 'cyrillic':
10177                         case 'iso88595':
10178                         case 'iso885951988':
10179                         case 'isoir144':
10180                                 return 'ISO-8859-5';
10181
10182                         case 'arabic':
10183                         case 'asmo708':
10184                         case 'csisolatinarabic':
10185                         case 'ecma114':
10186                         case 'iso88596':
10187                         case 'iso885961987':
10188                         case 'isoir127':
10189                                 return 'ISO-8859-6';
10190
10191                         case 'csiso88596e':
10192                         case 'iso88596e':
10193                                 return 'ISO-8859-6-E';
10194
10195                         case 'csiso88596i':
10196                         case 'iso88596i':
10197                                 return 'ISO-8859-6-I';
10198
10199                         case 'csisolatingreek':
10200                         case 'ecma118':
10201                         case 'elot928':
10202                         case 'greek':
10203                         case 'greek8':
10204                         case 'iso88597':
10205                         case 'iso885971987':
10206                         case 'isoir126':
10207                                 return 'ISO-8859-7';
10208
10209                         case 'csisolatinhebrew':
10210                         case 'hebrew':
10211                         case 'iso88598':
10212                         case 'iso885981988':
10213                         case 'isoir138':
10214                                 return 'ISO-8859-8';
10215
10216                         case 'csiso88598e':
10217                         case 'iso88598e':
10218                                 return 'ISO-8859-8-E';
10219
10220                         case 'csiso88598i':
10221                         case 'iso88598i':
10222                                 return 'ISO-8859-8-I';
10223
10224                         case 'cswindows31latin5':
10225                         case 'iso88599windowslatin5':
10226                                 return 'ISO-8859-9-Windows-Latin-5';
10227
10228                         case 'csisolatin6':
10229                         case 'iso885910':
10230                         case 'iso8859101992':
10231                         case 'isoir157':
10232                         case 'l6':
10233                         case 'latin6':
10234                                 return 'ISO-8859-10';
10235
10236                         case 'iso885913':
10237                                 return 'ISO-8859-13';
10238
10239                         case 'iso885914':
10240                         case 'iso8859141998':
10241                         case 'isoceltic':
10242                         case 'isoir199':
10243                         case 'l8':
10244                         case 'latin8':
10245                                 return 'ISO-8859-14';
10246
10247                         case 'iso885915':
10248                         case 'latin9':
10249                                 return 'ISO-8859-15';
10250
10251                         case 'iso885916':
10252                         case 'iso8859162001':
10253                         case 'isoir226':
10254                         case 'l10':
10255                         case 'latin10':
10256                                 return 'ISO-8859-16';
10257
10258                         case 'iso10646j1':
10259                                 return 'ISO-10646-J-1';
10260
10261                         case 'csunicode':
10262                         case 'iso10646ucs2':
10263                                 return 'ISO-10646-UCS-2';
10264
10265                         case 'csucs4':
10266                         case 'iso10646ucs4':
10267                                 return 'ISO-10646-UCS-4';
10268
10269                         case 'csunicodeascii':
10270                         case 'iso10646ucsbasic':
10271                                 return 'ISO-10646-UCS-Basic';
10272
10273                         case 'csunicodelatin1':
10274                         case 'iso10646':
10275                         case 'iso10646unicodelatin1':
10276                                 return 'ISO-10646-Unicode-Latin1';
10277
10278                         case 'csiso10646utf1':
10279                         case 'iso10646utf1':
10280                                 return 'ISO-10646-UTF-1';
10281
10282                         case 'csiso115481':
10283                         case 'iso115481':
10284                         case 'isotr115481':
10285                                 return 'ISO-11548-1';
10286
10287                         case 'csiso90':
10288                         case 'isoir90':
10289                                 return 'iso-ir-90';
10290
10291                         case 'csunicodeibm1261':
10292                         case 'isounicodeibm1261':
10293                                 return 'ISO-Unicode-IBM-1261';
10294
10295                         case 'csunicodeibm1264':
10296                         case 'isounicodeibm1264':
10297                                 return 'ISO-Unicode-IBM-1264';
10298
10299                         case 'csunicodeibm1265':
10300                         case 'isounicodeibm1265':
10301                                 return 'ISO-Unicode-IBM-1265';
10302
10303                         case 'csunicodeibm1268':
10304                         case 'isounicodeibm1268':
10305                                 return 'ISO-Unicode-IBM-1268';
10306
10307                         case 'csunicodeibm1276':
10308                         case 'isounicodeibm1276':
10309                                 return 'ISO-Unicode-IBM-1276';
10310
10311                         case 'csiso646basic1983':
10312                         case 'iso646basic1983':
10313                         case 'ref':
10314                                 return 'ISO_646.basic:1983';
10315
10316                         case 'csiso2intlrefversion':
10317                         case 'irv':
10318                         case 'iso646irv1983':
10319                         case 'isoir2':
10320                                 return 'ISO_646.irv:1983';
10321
10322                         case 'csiso2033':
10323                         case 'e13b':
10324                         case 'iso20331983':
10325                         case 'isoir98':
10326                                 return 'ISO_2033-1983';
10327
10328                         case 'csiso5427cyrillic':
10329                         case 'iso5427':
10330                         case 'isoir37':
10331                                 return 'ISO_5427';
10332
10333                         case 'iso5427cyrillic1981':
10334                         case 'iso54271981':
10335                         case 'isoir54':
10336                                 return 'ISO_5427:1981';
10337
10338                         case 'csiso5428greek':
10339                         case 'iso54281980':
10340                         case 'isoir55':
10341                                 return 'ISO_5428:1980';
10342
10343                         case 'csiso6937add':
10344                         case 'iso6937225':
10345                         case 'isoir152':
10346                                 return 'ISO_6937-2-25';
10347
10348                         case 'csisotextcomm':
10349                         case 'iso69372add':
10350                         case 'isoir142':
10351                                 return 'ISO_6937-2-add';
10352
10353                         case 'csiso8859supp':
10354                         case 'iso8859supp':
10355                         case 'isoir154':
10356                         case 'latin125':
10357                                 return 'ISO_8859-supp';
10358
10359                         case 'csiso10367box':
10360                         case 'iso10367box':
10361                         case 'isoir155':
10362                                 return 'ISO_10367-box';
10363
10364                         case 'csiso15italian':
10365                         case 'iso646it':
10366                         case 'isoir15':
10367                         case 'it':
10368                                 return 'IT';
10369
10370                         case 'csiso13jisc6220jp':
10371                         case 'isoir13':
10372                         case 'jisc62201969':
10373                         case 'jisc62201969jp':
10374                         case 'katakana':
10375                         case 'x2017':
10376                                 return 'JIS_C6220-1969-jp';
10377
10378                         case 'csiso14jisc6220ro':
10379                         case 'iso646jp':
10380                         case 'isoir14':
10381                         case 'jisc62201969ro':
10382                         case 'jp':
10383                                 return 'JIS_C6220-1969-ro';
10384
10385                         case 'csiso42jisc62261978':
10386                         case 'isoir42':
10387                         case 'jisc62261978':
10388                                 return 'JIS_C6226-1978';
10389
10390                         case 'csiso87jisx208':
10391                         case 'isoir87':
10392                         case 'jisc62261983':
10393                         case 'jisx2081983':
10394                         case 'x208':
10395                                 return 'JIS_C6226-1983';
10396
10397                         case 'csiso91jisc62291984a':
10398                         case 'isoir91':
10399                         case 'jisc62291984a':
10400                         case 'jpocra':
10401                                 return 'JIS_C6229-1984-a';
10402
10403                         case 'csiso92jisc62991984b':
10404                         case 'iso646jpocrb':
10405                         case 'isoir92':
10406                         case 'jisc62291984b':
10407                         case 'jpocrb':
10408                                 return 'JIS_C6229-1984-b';
10409
10410                         case 'csiso93jis62291984badd':
10411                         case 'isoir93':
10412                         case 'jisc62291984badd':
10413                         case 'jpocrbadd':
10414                                 return 'JIS_C6229-1984-b-add';
10415
10416                         case 'csiso94jis62291984hand':
10417                         case 'isoir94':
10418                         case 'jisc62291984hand':
10419                         case 'jpocrhand':
10420                                 return 'JIS_C6229-1984-hand';
10421
10422                         case 'csiso95jis62291984handadd':
10423                         case 'isoir95':
10424                         case 'jisc62291984handadd':
10425                         case 'jpocrhandadd':
10426                                 return 'JIS_C6229-1984-hand-add';
10427
10428                         case 'csiso96jisc62291984kana':
10429                         case 'isoir96':
10430                         case 'jisc62291984kana':
10431                                 return 'JIS_C6229-1984-kana';
10432
10433                         case 'csjisencoding':
10434                         case 'jisencoding':
10435                                 return 'JIS_Encoding';
10436
10437                         case 'cshalfwidthkatakana':
10438                         case 'jisx201':
10439                         case 'x201':
10440                                 return 'JIS_X0201';
10441
10442                         case 'csiso159jisx2121990':
10443                         case 'isoir159':
10444                         case 'jisx2121990':
10445                         case 'x212':
10446                                 return 'JIS_X0212-1990';
10447
10448                         case 'csiso141jusib1002':
10449                         case 'iso646yu':
10450                         case 'isoir141':
10451                         case 'js':
10452                         case 'jusib1002':
10453                         case 'yu':
10454                                 return 'JUS_I.B1.002';
10455
10456                         case 'csiso147macedonian':
10457                         case 'isoir147':
10458                         case 'jusib1003mac':
10459                         case 'macedonian':
10460                                 return 'JUS_I.B1.003-mac';
10461
10462                         case 'csiso146serbian':
10463                         case 'isoir146':
10464                         case 'jusib1003serb':
10465                         case 'serbian':
10466                                 return 'JUS_I.B1.003-serb';
10467
10468                         case 'koi7switched':
10469                                 return 'KOI7-switched';
10470
10471                         case 'cskoi8r':
10472                         case 'koi8r':
10473                                 return 'KOI8-R';
10474
10475                         case 'koi8u':
10476                                 return 'KOI8-U';
10477
10478                         case 'csksc5636':
10479                         case 'iso646kr':
10480                         case 'ksc5636':
10481                                 return 'KSC5636';
10482
10483                         case 'cskz1048':
10484                         case 'kz1048':
10485                         case 'rk1048':
10486                         case 'strk10482002':
10487                                 return 'KZ-1048';
10488
10489                         case 'csiso19latingreek':
10490                         case 'isoir19':
10491                         case 'latingreek':
10492                                 return 'latin-greek';
10493
10494                         case 'csiso27latingreek1':
10495                         case 'isoir27':
10496                         case 'latingreek1':
10497                                 return 'Latin-greek-1';
10498
10499                         case 'csiso158lap':
10500                         case 'isoir158':
10501                         case 'lap':
10502                         case 'latinlap':
10503                                 return 'latin-lap';
10504
10505                         case 'csmacintosh':
10506                         case 'mac':
10507                         case 'macintosh':
10508                                 return 'macintosh';
10509
10510                         case 'csmicrosoftpublishing':
10511                         case 'microsoftpublishing':
10512                                 return 'Microsoft-Publishing';
10513
10514                         case 'csmnem':
10515                         case 'mnem':
10516                                 return 'MNEM';
10517
10518                         case 'csmnemonic':
10519                         case 'mnemonic':
10520                                 return 'MNEMONIC';
10521
10522                         case 'csiso86hungarian':
10523                         case 'hu':
10524                         case 'iso646hu':
10525                         case 'isoir86':
10526                         case 'msz77953':
10527                                 return 'MSZ_7795.3';
10528
10529                         case 'csnatsdano':
10530                         case 'isoir91':
10531                         case 'natsdano':
10532                                 return 'NATS-DANO';
10533
10534                         case 'csnatsdanoadd':
10535                         case 'isoir92':
10536                         case 'natsdanoadd':
10537                                 return 'NATS-DANO-ADD';
10538
10539                         case 'csnatssefi':
10540                         case 'isoir81':
10541                         case 'natssefi':
10542                                 return 'NATS-SEFI';
10543
10544                         case 'csnatssefiadd':
10545                         case 'isoir82':
10546                         case 'natssefiadd':
10547                                 return 'NATS-SEFI-ADD';
10548
10549                         case 'csiso151cuba':
10550                         case 'cuba':
10551                         case 'iso646cu':
10552                         case 'isoir151':
10553                         case 'ncnc1081':
10554                                 return 'NC_NC00-10:81';
10555
10556                         case 'csiso69french':
10557                         case 'fr':
10558                         case 'iso646fr':
10559                         case 'isoir69':
10560                         case 'nfz62010':
10561                                 return 'NF_Z_62-010';
10562
10563                         case 'csiso25french':
10564                         case 'iso646fr1':
10565                         case 'isoir25':
10566                         case 'nfz620101973':
10567                                 return 'NF_Z_62-010_(1973)';
10568
10569                         case 'csiso60danishnorwegian':
10570                         case 'csiso60norwegian1':
10571                         case 'iso646no':
10572                         case 'isoir60':
10573                         case 'no':
10574                         case 'ns45511':
10575                                 return 'NS_4551-1';
10576
10577                         case 'csiso61norwegian2':
10578                         case 'iso646no2':
10579                         case 'isoir61':
10580                         case 'no2':
10581                         case 'ns45512':
10582                                 return 'NS_4551-2';
10583
10584                         case 'osdebcdicdf3irv':
10585                                 return 'OSD_EBCDIC_DF03_IRV';
10586
10587                         case 'osdebcdicdf41':
10588                                 return 'OSD_EBCDIC_DF04_1';
10589
10590                         case 'osdebcdicdf415':
10591                                 return 'OSD_EBCDIC_DF04_15';
10592
10593                         case 'cspc8danishnorwegian':
10594                         case 'pc8danishnorwegian':
10595                                 return 'PC8-Danish-Norwegian';
10596
10597                         case 'cspc8turkish':
10598                         case 'pc8turkish':
10599                                 return 'PC8-Turkish';
10600
10601                         case 'csiso16portuguese':
10602                         case 'iso646pt':
10603                         case 'isoir16':
10604                         case 'pt':
10605                                 return 'PT';
10606
10607                         case 'csiso84portuguese2':
10608                         case 'iso646pt2':
10609                         case 'isoir84':
10610                         case 'pt2':
10611                                 return 'PT2';
10612
10613                         case 'cp154':
10614                         case 'csptcp154':
10615                         case 'cyrillicasian':
10616                         case 'pt154':
10617                         case 'ptcp154':
10618                                 return 'PTCP154';
10619
10620                         case 'scsu':
10621                                 return 'SCSU';
10622
10623                         case 'csiso10swedish':
10624                         case 'fi':
10625                         case 'iso646fi':
10626                         case 'iso646se':
10627                         case 'isoir10':
10628                         case 'se':
10629                         case 'sen850200b':
10630                                 return 'SEN_850200_B';
10631
10632                         case 'csiso11swedishfornames':
10633                         case 'iso646se2':
10634                         case 'isoir11':
10635                         case 'se2':
10636                         case 'sen850200c':
10637                                 return 'SEN_850200_C';
10638
10639                         case 'csiso102t617bit':
10640                         case 'isoir102':
10641                         case 't617bit':
10642                                 return 'T.61-7bit';
10643
10644                         case 'csiso103t618bit':
10645                         case 'isoir103':
10646                         case 't61':
10647                         case 't618bit':
10648                                 return 'T.61-8bit';
10649
10650                         case 'csiso128t101g2':
10651                         case 'isoir128':
10652                         case 't101g2':
10653                                 return 'T.101-G2';
10654
10655                         case 'cstscii':
10656                         case 'tscii':
10657                                 return 'TSCII';
10658
10659                         case 'csunicode11':
10660                         case 'unicode11':
10661                                 return 'UNICODE-1-1';
10662
10663                         case 'csunicode11utf7':
10664                         case 'unicode11utf7':
10665                                 return 'UNICODE-1-1-UTF-7';
10666
10667                         case 'csunknown8bit':
10668                         case 'unknown8bit':
10669                                 return 'UNKNOWN-8BIT';
10670
10671                         case 'ansix341968':
10672                         case 'ansix341986':
10673                         case 'ascii':
10674                         case 'cp367':
10675                         case 'csascii':
10676                         case 'ibm367':
10677                         case 'iso646irv1991':
10678                         case 'iso646us':
10679                         case 'isoir6':
10680                         case 'us':
10681                         case 'usascii':
10682                                 return 'US-ASCII';
10683
10684                         case 'csusdk':
10685                         case 'usdk':
10686                                 return 'us-dk';
10687
10688                         case 'utf7':
10689                                 return 'UTF-7';
10690
10691                         case 'utf8':
10692                                 return 'UTF-8';
10693
10694                         case 'utf16':
10695                                 return 'UTF-16';
10696
10697                         case 'utf16be':
10698                                 return 'UTF-16BE';
10699
10700                         case 'utf16le':
10701                                 return 'UTF-16LE';
10702
10703                         case 'utf32':
10704                                 return 'UTF-32';
10705
10706                         case 'utf32be':
10707                                 return 'UTF-32BE';
10708
10709                         case 'utf32le':
10710                                 return 'UTF-32LE';
10711
10712                         case 'csventurainternational':
10713                         case 'venturainternational':
10714                                 return 'Ventura-International';
10715
10716                         case 'csventuramath':
10717                         case 'venturamath':
10718                                 return 'Ventura-Math';
10719
10720                         case 'csventuraus':
10721                         case 'venturaus':
10722                                 return 'Ventura-US';
10723
10724                         case 'csiso70videotexsupp1':
10725                         case 'isoir70':
10726                         case 'videotexsuppl':
10727                                 return 'videotex-suppl';
10728
10729                         case 'csviqr':
10730                         case 'viqr':
10731                                 return 'VIQR';
10732
10733                         case 'csviscii':
10734                         case 'viscii':
10735                                 return 'VISCII';
10736
10737                         case 'csshiftjis':
10738                         case 'cswindows31j':
10739                         case 'mskanji':
10740                         case 'shiftjis':
10741                         case 'windows31j':
10742                                 return 'Windows-31J';
10743
10744                         case 'iso885911':
10745                         case 'tis620':
10746                                 return 'windows-874';
10747
10748                         case 'cseuckr':
10749                         case 'csksc56011987':
10750                         case 'euckr':
10751                         case 'isoir149':
10752                         case 'korean':
10753                         case 'ksc5601':
10754                         case 'ksc56011987':
10755                         case 'ksc56011989':
10756                         case 'windows949':
10757                                 return 'windows-949';
10758
10759                         case 'windows1250':
10760                                 return 'windows-1250';
10761
10762                         case 'windows1251':
10763                                 return 'windows-1251';
10764
10765                         case 'cp819':
10766                         case 'csisolatin1':
10767                         case 'ibm819':
10768                         case 'iso88591':
10769                         case 'iso885911987':
10770                         case 'isoir100':
10771                         case 'l1':
10772                         case 'latin1':
10773                         case 'windows1252':
10774                                 return 'windows-1252';
10775
10776                         case 'windows1253':
10777                                 return 'windows-1253';
10778
10779                         case 'csisolatin5':
10780                         case 'iso88599':
10781                         case 'iso885991989':
10782                         case 'isoir148':
10783                         case 'l5':
10784                         case 'latin5':
10785                         case 'windows1254':
10786                                 return 'windows-1254';
10787
10788                         case 'windows1255':
10789                                 return 'windows-1255';
10790
10791                         case 'windows1256':
10792                                 return 'windows-1256';
10793
10794                         case 'windows1257':
10795                                 return 'windows-1257';
10796
10797                         case 'windows1258':
10798                                 return 'windows-1258';
10799
10800                         default:
10801                                 return $charset;
10802                 }
10803         }
10804
10805         function get_curl_version()
10806         {
10807                 if (is_array($curl = curl_version()))
10808                 {
10809                         $curl = $curl['version'];
10810                 }
10811                 elseif (substr($curl, 0, 5) === 'curl/')
10812                 {
10813                         $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10814                 }
10815                 elseif (substr($curl, 0, 8) === 'libcurl/')
10816                 {
10817                         $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10818                 }
10819                 else
10820                 {
10821                         $curl = 0;
10822                 }
10823                 return $curl;
10824         }
10825
10826         function is_subclass_of($class1, $class2)
10827         {
10828                 if (func_num_args() !== 2)
10829                 {
10830                         trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10831                 }
10832                 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10833                 {
10834                         return is_subclass_of($class1, $class2);
10835                 }
10836                 elseif (is_string($class1) && is_string($class2))
10837                 {
10838                         if (class_exists($class1))
10839                         {
10840                                 if (class_exists($class2))
10841                                 {
10842                                         $class2 = strtolower($class2);
10843                                         while ($class1 = strtolower(get_parent_class($class1)))
10844                                         {
10845                                                 if ($class1 === $class2)
10846                                                 {
10847                                                         return true;
10848                                                 }
10849                                         }
10850                                 }
10851                         }
10852                         else
10853                         {
10854                                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10855                         }
10856                 }
10857                 return false;
10858         }
10859
10860         /**
10861          * Strip HTML comments
10862          *
10863          * @access public
10864          * @param string $data Data to strip comments from
10865          * @return string Comment stripped string
10866          */
10867         function strip_comments($data)
10868         {
10869                 $output = '';
10870                 while (($start = strpos($data, '<!--')) !== false)
10871                 {
10872                         $output .= substr($data, 0, $start);
10873                         if (($end = strpos($data, '-->', $start)) !== false)
10874                         {
10875                                 $data = substr_replace($data, '', 0, $end + 3);
10876                         }
10877                         else
10878                         {
10879                                 $data = '';
10880                         }
10881                 }
10882                 return $output . $data;
10883         }
10884
10885         function parse_date($dt)
10886         {
10887                 $parser = SimplePie_Parse_Date::get();
10888                 return $parser->parse($dt);
10889         }
10890
10891         /**
10892          * Decode HTML entities
10893          *
10894          * @static
10895          * @access public
10896          * @param string $data Input data
10897          * @return string Output data
10898          */
10899         function entities_decode($data)
10900         {
10901                 $decoder =& new SimplePie_Decode_HTML_Entities($data);
10902                 return $decoder->parse();
10903         }
10904
10905         /**
10906          * Remove RFC822 comments
10907          *
10908          * @access public
10909          * @param string $data Data to strip comments from
10910          * @return string Comment stripped string
10911          */
10912         function uncomment_rfc822($string)
10913         {
10914                 $string = (string) $string;
10915                 $position = 0;
10916                 $length = strlen($string);
10917                 $depth = 0;
10918
10919                 $output = '';
10920
10921                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10922                 {
10923                         $output .= substr($string, $position, $pos - $position);
10924                         $position = $pos + 1;
10925                         if ($string[$pos - 1] !== '\\')
10926                         {
10927                                 $depth++;
10928                                 while ($depth && $position < $length)
10929                                 {
10930                                         $position += strcspn($string, '()', $position);
10931                                         if ($string[$position - 1] === '\\')
10932                                         {
10933                                                 $position++;
10934                                                 continue;
10935                                         }
10936                                         elseif (isset($string[$position]))
10937                                         {
10938                                                 switch ($string[$position])
10939                                                 {
10940                                                         case '(':
10941                                                                 $depth++;
10942                                                                 break;
10943
10944                                                         case ')':
10945                                                                 $depth--;
10946                                                                 break;
10947                                                 }
10948                                                 $position++;
10949                                         }
10950                                         else
10951                                         {
10952                                                 break;
10953                                         }
10954                                 }
10955                         }
10956                         else
10957                         {
10958                                 $output .= '(';
10959                         }
10960                 }
10961                 $output .= substr($string, $position);
10962
10963                 return $output;
10964         }
10965
10966         function parse_mime($mime)
10967         {
10968                 if (($pos = strpos($mime, ';')) === false)
10969                 {
10970                         return trim($mime);
10971                 }
10972                 else
10973                 {
10974                         return trim(substr($mime, 0, $pos));
10975                 }
10976         }
10977
10978         function htmlspecialchars_decode($string, $quote_style)
10979         {
10980                 if (function_exists('htmlspecialchars_decode'))
10981                 {
10982                         return htmlspecialchars_decode($string, $quote_style);
10983                 }
10984                 else
10985                 {
10986                         return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10987                 }
10988         }
10989
10990         function atom_03_construct_type($attribs)
10991         {
10992                 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10993                 {
10994                         $mode = SIMPLEPIE_CONSTRUCT_BASE64;
10995                 }
10996                 else
10997                 {
10998                         $mode = SIMPLEPIE_CONSTRUCT_NONE;
10999                 }
11000                 if (isset($attribs['']['type']))
11001                 {
11002                         switch (strtolower(trim($attribs['']['type'])))
11003                         {
11004                                 case 'text':
11005                                 case 'text/plain':
11006                                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11007
11008                                 case 'html':
11009                                 case 'text/html':
11010                                         return SIMPLEPIE_CONSTRUCT_HTML | $mode;
11011
11012                                 case 'xhtml':
11013                                 case 'application/xhtml+xml':
11014                                         return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
11015
11016                                 default:
11017                                         return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11018                         }
11019                 }
11020                 else
11021                 {
11022                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11023                 }
11024         }
11025
11026         function atom_10_construct_type($attribs)
11027         {
11028                 if (isset($attribs['']['type']))
11029                 {
11030                         switch (strtolower(trim($attribs['']['type'])))
11031                         {
11032                                 case 'text':
11033                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11034
11035                                 case 'html':
11036                                         return SIMPLEPIE_CONSTRUCT_HTML;
11037
11038                                 case 'xhtml':
11039                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11040
11041                                 default:
11042                                         return SIMPLEPIE_CONSTRUCT_NONE;
11043                         }
11044                 }
11045                 return SIMPLEPIE_CONSTRUCT_TEXT;
11046         }
11047
11048         function atom_10_content_construct_type($attribs)
11049         {
11050                 if (isset($attribs['']['type']))
11051                 {
11052                         $type = strtolower(trim($attribs['']['type']));
11053                         switch ($type)
11054                         {
11055                                 case 'text':
11056                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11057
11058                                 case 'html':
11059                                         return SIMPLEPIE_CONSTRUCT_HTML;
11060
11061                                 case 'xhtml':
11062                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11063                         }
11064                         if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11065                         {
11066                                 return SIMPLEPIE_CONSTRUCT_NONE;
11067                         }
11068                         else
11069                         {
11070                                 return SIMPLEPIE_CONSTRUCT_BASE64;
11071                         }
11072                 }
11073                 else
11074                 {
11075                         return SIMPLEPIE_CONSTRUCT_TEXT;
11076                 }
11077         }
11078
11079         function is_isegment_nz_nc($string)
11080         {
11081                 return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);
11082         }
11083
11084         function space_seperated_tokens($string)
11085         {
11086                 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11087                 $string_length = strlen($string);
11088
11089                 $position = strspn($string, $space_characters);
11090                 $tokens = array();
11091
11092                 while ($position < $string_length)
11093                 {
11094                         $len = strcspn($string, $space_characters, $position);
11095                         $tokens[] = substr($string, $position, $len);
11096                         $position += $len;
11097                         $position += strspn($string, $space_characters, $position);
11098                 }
11099
11100                 return $tokens;
11101         }
11102
11103         function array_unique($array)
11104         {
11105                 if (version_compare(PHP_VERSION, '5.2', '>='))
11106                 {
11107                         return array_unique($array);
11108                 }
11109                 else
11110                 {
11111                         $array = (array) $array;
11112                         $new_array = array();
11113                         $new_array_strings = array();
11114                         foreach ($array as $key => $value)
11115                         {
11116                                 if (is_object($value))
11117                                 {
11118                                         if (method_exists($value, '__toString'))
11119                                         {
11120                                                 $cmp = $value->__toString();
11121                                         }
11122                                         else
11123                                         {
11124                                                 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11125                                         }
11126                                 }
11127                                 elseif (is_array($value))
11128                                 {
11129                                         $cmp = (string) reset($value);
11130                                 }
11131                                 else
11132                                 {
11133                                         $cmp = (string) $value;
11134                                 }
11135                                 if (!in_array($cmp, $new_array_strings))
11136                                 {
11137                                         $new_array[$key] = $value;
11138                                         $new_array_strings[] = $cmp;
11139                                 }
11140                         }
11141                         return $new_array;
11142                 }
11143         }
11144
11145         /**
11146          * Converts a unicode codepoint to a UTF-8 character
11147          *
11148          * @static
11149          * @access public
11150          * @param int $codepoint Unicode codepoint
11151          * @return string UTF-8 character
11152          */
11153         function codepoint_to_utf8($codepoint)
11154         {
11155                 $codepoint = (int) $codepoint;
11156                 if ($codepoint < 0)
11157                 {
11158                         return false;
11159                 }
11160                 else if ($codepoint <= 0x7f)
11161                 {
11162                         return chr($codepoint);
11163                 }
11164                 else if ($codepoint <= 0x7ff)
11165                 {
11166                         return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11167                 }
11168                 else if ($codepoint <= 0xffff)
11169                 {
11170                         return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11171                 }
11172                 else if ($codepoint <= 0x10ffff)
11173                 {
11174                         return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11175                 }
11176                 else
11177                 {
11178                         // U+FFFD REPLACEMENT CHARACTER
11179                         return "\xEF\xBF\xBD";
11180                 }
11181         }
11182
11183         /**
11184          * Re-implementation of PHP 5's stripos()
11185          *
11186          * Returns the numeric position of the first occurrence of needle in the
11187          * haystack string.
11188          *
11189          * @static
11190          * @access string
11191          * @param object $haystack
11192          * @param string $needle Note that the needle may be a string of one or more
11193          *     characters. If needle is not a string, it is converted to an integer
11194          *     and applied as the ordinal value of a character.
11195          * @param int $offset The optional offset parameter allows you to specify which
11196          *     character in haystack to start searching. The position returned is still
11197          *     relative to the beginning of haystack.
11198          * @return bool If needle is not found, stripos() will return boolean false.
11199          */
11200         function stripos($haystack, $needle, $offset = 0)
11201         {
11202                 if (function_exists('stripos'))
11203                 {
11204                         return stripos($haystack, $needle, $offset);
11205                 }
11206                 else
11207                 {
11208                         if (is_string($needle))
11209                         {
11210                                 $needle = strtolower($needle);
11211                         }
11212                         elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11213                         {
11214                                 $needle = strtolower(chr($needle));
11215                         }
11216                         else
11217                         {
11218                                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11219                                 return false;
11220                         }
11221
11222                         return strpos(strtolower($haystack), $needle, $offset);
11223                 }
11224         }
11225
11226         /**
11227          * Similar to parse_str()
11228          *
11229          * Returns an associative array of name/value pairs, where the value is an
11230          * array of values that have used the same name
11231          *
11232          * @static
11233          * @access string
11234          * @param string $str The input string.
11235          * @return array
11236          */
11237         function parse_str($str)
11238         {
11239                 $return = array();
11240                 $str = explode('&', $str);
11241
11242                 foreach ($str as $section)
11243                 {
11244                         if (strpos($section, '=') !== false)
11245                         {
11246                                 list($name, $value) = explode('=', $section, 2);
11247                                 $return[urldecode($name)][] = urldecode($value);
11248                         }
11249                         else
11250                         {
11251                                 $return[urldecode($section)][] = null;
11252                         }
11253                 }
11254
11255                 return $return;
11256         }
11257
11258         /**
11259          * Detect XML encoding, as per XML 1.0 Appendix F.1
11260          *
11261          * @todo Add support for EBCDIC
11262          * @param string $data XML data
11263          * @return array Possible encodings
11264          */
11265         function xml_encoding($data)
11266         {
11267                 // UTF-32 Big Endian BOM
11268                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11269                 {
11270                         $encoding[] = 'UTF-32BE';
11271                 }
11272                 // UTF-32 Little Endian BOM
11273                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11274                 {
11275                         $encoding[] = 'UTF-32LE';
11276                 }
11277                 // UTF-16 Big Endian BOM
11278                 elseif (substr($data, 0, 2) === "\xFE\xFF")
11279                 {
11280                         $encoding[] = 'UTF-16BE';
11281                 }
11282                 // UTF-16 Little Endian BOM
11283                 elseif (substr($data, 0, 2) === "\xFF\xFE")
11284                 {
11285                         $encoding[] = 'UTF-16LE';
11286                 }
11287                 // UTF-8 BOM
11288                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11289                 {
11290                         $encoding[] = 'UTF-8';
11291                 }
11292                 // UTF-32 Big Endian Without BOM
11293                 elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C")
11294                 {
11295                         if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11296                         {
11297                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11298                                 if ($parser->parse())
11299                                 {
11300                                         $encoding[] = $parser->encoding;
11301                                 }
11302                         }
11303                         $encoding[] = 'UTF-32BE';
11304                 }
11305                 // UTF-32 Little Endian Without BOM
11306                 elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00")
11307                 {
11308                         if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11309                         {
11310                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11311                                 if ($parser->parse())
11312                                 {
11313                                         $encoding[] = $parser->encoding;
11314                                 }
11315                         }
11316                         $encoding[] = 'UTF-32LE';
11317                 }
11318                 // UTF-16 Big Endian Without BOM
11319                 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11320                 {
11321                         if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11322                         {
11323                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11324                                 if ($parser->parse())
11325                                 {
11326                                         $encoding[] = $parser->encoding;
11327                                 }
11328                         }
11329                         $encoding[] = 'UTF-16BE';
11330                 }
11331                 // UTF-16 Little Endian Without BOM
11332                 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11333                 {
11334                         if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11335                         {
11336                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11337                                 if ($parser->parse())
11338                                 {
11339                                         $encoding[] = $parser->encoding;
11340                                 }
11341                         }
11342                         $encoding[] = 'UTF-16LE';
11343                 }
11344                 // US-ASCII (or superset)
11345                 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11346                 {
11347                         if ($pos = strpos($data, "\x3F\x3E"))
11348                         {
11349                                 $parser =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11350                                 if ($parser->parse())
11351                                 {
11352                                         $encoding[] = $parser->encoding;
11353                                 }
11354                         }
11355                         $encoding[] = 'UTF-8';
11356                 }
11357                 // Fallback to UTF-8
11358                 else
11359                 {
11360                         $encoding[] = 'UTF-8';
11361                 }
11362                 return $encoding;
11363         }
11364
11365         function output_javascript()
11366         {
11367                 if (function_exists('ob_gzhandler'))
11368                 {
11369                         ob_start('ob_gzhandler');
11370                 }
11371                 header('Content-type: text/javascript; charset: UTF-8');
11372                 header('Cache-Control: must-revalidate');
11373                 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11374                 ?>
11375 function embed_odeo(link) {
11376         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>');
11377 }
11378
11379 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11380         if (placeholder != '') {
11381                 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>');
11382         }
11383         else {
11384                 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>');
11385         }
11386 }
11387
11388 function embed_flash(bgcolor, width, height, link, loop, type) {
11389         document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
11390 }
11391
11392 function embed_flv(width, height, link, placeholder, loop, player) {
11393         document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>');
11394 }
11395
11396 function embed_wmedia(width, height, link) {
11397         document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11398 }
11399                 <?php
11400         }
11401
11402
11403
11404         /**
11405          * Format debugging information
11406          */
11407         function debug($sp)
11408         {
11409                 $info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n";
11410                 $info .= 'PHP ' . PHP_VERSION . "\n";
11411                 if ($sp->error() !== null)
11412                 {
11413                         $info .= 'Error occurred: ' . $sp->error() . "\n";
11414                 }
11415                 else
11416                 {
11417                         $info .= "No error found.\n";
11418                 }
11419                 $info .= "Extensions:\n";
11420                 $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');
11421                 foreach ($extensions as $ext)
11422                 {
11423                         if (extension_loaded($ext))
11424                         {
11425                                 $info .= "    $ext loaded\n";
11426                                 switch ($ext)
11427                                 {
11428                                         case 'pcre':
11429                                                 $info .= '      Version ' . PCRE_VERSION . "\n";
11430                                                 break;
11431                                         case 'curl':
11432                                                 $version = curl_version();
11433                                                 $info .= '      Version ' . $version['version'] . "\n";
11434                                                 break;
11435                                         case 'mbstring':
11436                                                 $info .= '      Overloading: ' . mb_get_info('func_overload') . "\n";
11437                                                 break;
11438                                         case 'iconv':
11439                                                 $info .= '      Version ' . ICONV_VERSION . "\n";
11440                                                 break;
11441                                         case 'xml':
11442                                                 $info .= '      Version ' . LIBXML_DOTTED_VERSION . "\n";
11443                                                 break;
11444                                 }
11445                         }
11446                         else
11447                         {
11448                                 $info .= "    $ext not loaded\n";
11449                         }
11450                 }
11451                 return $info;
11452         }
11453 }
11454
11455 /**
11456  * Decode HTML Entities
11457  *
11458  * This implements HTML5 as of revision 967 (2007-06-28)
11459  *
11460  * @package SimplePie
11461  */
11462 class SimplePie_Decode_HTML_Entities
11463 {
11464         /**
11465          * Data to be parsed
11466          *
11467          * @access private
11468          * @var string
11469          */
11470         var $data = '';
11471
11472         /**
11473          * Currently consumed bytes
11474          *
11475          * @access private
11476          * @var string
11477          */
11478         var $consumed = '';
11479
11480         /**
11481          * Position of the current byte being parsed
11482          *
11483          * @access private
11484          * @var int
11485          */
11486         var $position = 0;
11487
11488         /**
11489          * Create an instance of the class with the input data
11490          *
11491          * @access public
11492          * @param string $data Input data
11493          */
11494         function SimplePie_Decode_HTML_Entities($data)
11495         {
11496                 $this->data = $data;
11497         }
11498
11499         /**
11500          * Parse the input data
11501          *
11502          * @access public
11503          * @return string Output data
11504          */
11505         function parse()
11506         {
11507                 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11508                 {
11509                         $this->consume();
11510                         $this->entity();
11511                         $this->consumed = '';
11512                 }
11513                 return $this->data;
11514         }
11515
11516         /**
11517          * Consume the next byte
11518          *
11519          * @access private
11520          * @return mixed The next byte, or false, if there is no more data
11521          */
11522         function consume()
11523         {
11524                 if (isset($this->data[$this->position]))
11525                 {
11526                         $this->consumed .= $this->data[$this->position];
11527                         return $this->data[$this->position++];
11528                 }
11529                 else
11530                 {
11531                         return false;
11532                 }
11533         }
11534
11535         /**
11536          * Consume a range of characters
11537          *
11538          * @access private
11539          * @param string $chars Characters to consume
11540          * @return mixed A series of characters that match the range, or false
11541          */
11542         function consume_range($chars)
11543         {
11544                 if ($len = strspn($this->data, $chars, $this->position))
11545                 {
11546                         $data = substr($this->data, $this->position, $len);
11547                         $this->consumed .= $data;
11548                         $this->position += $len;
11549                         return $data;
11550                 }
11551                 else
11552                 {
11553                         return false;
11554                 }
11555         }
11556
11557         /**
11558          * Unconsume one byte
11559          *
11560          * @access private
11561          */
11562         function unconsume()
11563         {
11564                 $this->consumed = substr($this->consumed, 0, -1);
11565                 $this->position--;
11566         }
11567
11568         /**
11569          * Decode an entity
11570          *
11571          * @access private
11572          */
11573         function entity()
11574         {
11575                 switch ($this->consume())
11576                 {
11577                         case "\x09":
11578                         case "\x0A":
11579                         case "\x0B":
11580                         case "\x0B":
11581                         case "\x0C":
11582                         case "\x20":
11583                         case "\x3C":
11584                         case "\x26":
11585                         case false:
11586                                 break;
11587
11588                         case "\x23":
11589                                 switch ($this->consume())
11590                                 {
11591                                         case "\x78":
11592                                         case "\x58":
11593                                                 $range = '0123456789ABCDEFabcdef';
11594                                                 $hex = true;
11595                                                 break;
11596
11597                                         default:
11598                                                 $range = '0123456789';
11599                                                 $hex = false;
11600                                                 $this->unconsume();
11601                                                 break;
11602                                 }
11603
11604                                 if ($codepoint = $this->consume_range($range))
11605                                 {
11606                                         static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8");
11607
11608                                         if ($hex)
11609                                         {
11610                                                 $codepoint = hexdec($codepoint);
11611                                         }
11612                                         else
11613                                         {
11614                                                 $codepoint = intval($codepoint);
11615                                         }
11616
11617                                         if (isset($windows_1252_specials[$codepoint]))
11618                                         {
11619                                                 $replacement = $windows_1252_specials[$codepoint];
11620                                         }
11621                                         else
11622                                         {
11623                                                 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11624                                         }
11625
11626                                         if (!in_array($this->consume(), array(';', false), true))
11627                                         {
11628                                                 $this->unconsume();
11629                                         }
11630
11631                                         $consumed_length = strlen($this->consumed);
11632                                         $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11633                                         $this->position += strlen($replacement) - $consumed_length;
11634                                 }
11635                                 break;
11636
11637                         default:
11638                                 static $entities = array('Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C");
11639
11640                                 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11641                                 {
11642                                         $consumed = substr($this->consumed, 1);
11643                                         if (isset($entities[$consumed]))
11644                                         {
11645                                                 $match = $consumed;
11646                                         }
11647                                 }
11648
11649                                 if ($match !== null)
11650                                 {
11651                                         $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11652                                         $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11653                                 }
11654                                 break;
11655                 }
11656         }
11657 }
11658
11659 /**
11660  * IRI parser/serialiser
11661  *
11662  * @package SimplePie
11663  */
11664 class SimplePie_IRI
11665 {
11666         /**
11667          * Scheme
11668          *
11669          * @access private
11670          * @var string
11671          */
11672         var $scheme;
11673
11674         /**
11675          * User Information
11676          *
11677          * @access private
11678          * @var string
11679          */
11680         var $userinfo;
11681
11682         /**
11683          * Host
11684          *
11685          * @access private
11686          * @var string
11687          */
11688         var $host;
11689
11690         /**
11691          * Port
11692          *
11693          * @access private
11694          * @var string
11695          */
11696         var $port;
11697
11698         /**
11699          * Path
11700          *
11701          * @access private
11702          * @var string
11703          */
11704         var $path;
11705
11706         /**
11707          * Query
11708          *
11709          * @access private
11710          * @var string
11711          */
11712         var $query;
11713
11714         /**
11715          * Fragment
11716          *
11717          * @access private
11718          * @var string
11719          */
11720         var $fragment;
11721
11722         /**
11723          * Whether the object represents a valid IRI
11724          *
11725          * @access private
11726          * @var array
11727          */
11728         var $valid = array();
11729
11730         /**
11731          * Return the entire IRI when you try and read the object as a string
11732          *
11733          * @access public
11734          * @return string
11735          */
11736         function __toString()
11737         {
11738                 return $this->get_iri();
11739         }
11740
11741         /**
11742          * Create a new IRI object, from a specified string
11743          *
11744          * @access public
11745          * @param string $iri
11746          * @return SimplePie_IRI
11747          */
11748         function SimplePie_IRI($iri)
11749         {
11750                 $iri = (string) $iri;
11751                 if ($iri !== '')
11752                 {
11753                         $parsed = $this->parse_iri($iri);
11754                         $this->set_scheme($parsed['scheme']);
11755                         $this->set_authority($parsed['authority']);
11756                         $this->set_path($parsed['path']);
11757                         $this->set_query($parsed['query']);
11758                         $this->set_fragment($parsed['fragment']);
11759                 }
11760         }
11761
11762         /**
11763          * Create a new IRI object by resolving a relative IRI
11764          *
11765          * @static
11766          * @access public
11767          * @param SimplePie_IRI $base Base IRI
11768          * @param string $relative Relative IRI
11769          * @return SimplePie_IRI
11770          */
11771         function absolutize($base, $relative)
11772         {
11773                 $relative = (string) $relative;
11774                 if ($relative !== '')
11775                 {
11776                         $relative =& new SimplePie_IRI($relative);
11777                         if ($relative->get_scheme() !== null)
11778                         {
11779                                 $target = $relative;
11780                         }
11781                         elseif ($base->get_iri() !== null)
11782                         {
11783                                 if ($relative->get_authority() !== null)
11784                                 {
11785                                         $target = $relative;
11786                                         $target->set_scheme($base->get_scheme());
11787                                 }
11788                                 else
11789                                 {
11790                                         $target =& new SimplePie_IRI('');
11791                                         $target->set_scheme($base->get_scheme());
11792                                         $target->set_userinfo($base->get_userinfo());
11793                                         $target->set_host($base->get_host());
11794                                         $target->set_port($base->get_port());
11795                                         if ($relative->get_path() !== null)
11796                                         {
11797                                                 if (strpos($relative->get_path(), '/') === 0)
11798                                                 {
11799                                                         $target->set_path($relative->get_path());
11800                                                 }
11801                                                 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11802                                                 {
11803                                                         $target->set_path('/' . $relative->get_path());
11804                                                 }
11805                                                 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11806                                                 {
11807                                                         $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11808                                                 }
11809                                                 else
11810                                                 {
11811                                                         $target->set_path($relative->get_path());
11812                                                 }
11813                                                 $target->set_query($relative->get_query());
11814                                         }
11815                                         else
11816                                         {
11817                                                 $target->set_path($base->get_path());
11818                                                 if ($relative->get_query() !== null)
11819                                                 {
11820                                                         $target->set_query($relative->get_query());
11821                                                 }
11822                                                 elseif ($base->get_query() !== null)
11823                                                 {
11824                                                         $target->set_query($base->get_query());
11825                                                 }
11826                                         }
11827                                 }
11828                                 $target->set_fragment($relative->get_fragment());
11829                         }
11830                         else
11831                         {
11832                                 // No base URL, just return the relative URL
11833                                 $target = $relative;
11834                         }
11835                 }
11836                 else
11837                 {
11838                         $target = $base;
11839                 }
11840                 return $target;
11841         }
11842
11843         /**
11844          * Parse an IRI into scheme/authority/path/query/fragment segments
11845          *
11846          * @access private
11847          * @param string $iri
11848          * @return array
11849          */
11850         function parse_iri($iri)
11851         {
11852                 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11853                 for ($i = count($match); $i <= 9; $i++)
11854                 {
11855                         $match[$i] = '';
11856                 }
11857                 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11858         }
11859
11860         /**
11861          * Remove dot segments from a path
11862          *
11863          * @access private
11864          * @param string $input
11865          * @return string
11866          */
11867         function remove_dot_segments($input)
11868         {
11869                 $output = '';
11870                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11871                 {
11872                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11873                         if (strpos($input, '../') === 0)
11874                         {
11875                                 $input = substr($input, 3);
11876                         }
11877                         elseif (strpos($input, './') === 0)
11878                         {
11879                                 $input = substr($input, 2);
11880                         }
11881                         // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
11882                         elseif (strpos($input, '/./') === 0)
11883                         {
11884                                 $input = substr_replace($input, '/', 0, 3);
11885                         }
11886                         elseif ($input === '/.')
11887                         {
11888                                 $input = '/';
11889                         }
11890                         // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
11891                         elseif (strpos($input, '/../') === 0)
11892                         {
11893                                 $input = substr_replace($input, '/', 0, 4);
11894                                 $output = substr_replace($output, '', strrpos($output, '/'));
11895                         }
11896                         elseif ($input === '/..')
11897                         {
11898                                 $input = '/';
11899                                 $output = substr_replace($output, '', strrpos($output, '/'));
11900                         }
11901                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11902                         elseif ($input === '.' || $input === '..')
11903                         {
11904                                 $input = '';
11905                         }
11906                         // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
11907                         elseif (($pos = strpos($input, '/', 1)) !== false)
11908                         {
11909                                 $output .= substr($input, 0, $pos);
11910                                 $input = substr_replace($input, '', 0, $pos);
11911                         }
11912                         else
11913                         {
11914                                 $output .= $input;
11915                                 $input = '';
11916                         }
11917                 }
11918                 return $output . $input;
11919         }
11920
11921         /**
11922          * Replace invalid character with percent encoding
11923          *
11924          * @param string $string Input string
11925          * @param string $valid_chars Valid characters
11926          * @param int $case Normalise case
11927          * @return string
11928          */
11929         function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE, $iprivate = false)
11930         {
11931                 // Normalize as many pct-encoded sections as possible
11932                 $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string);
11933
11934                 // Replace invalid percent characters
11935                 $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
11936
11937                 // Add unreserved and % to $valid_chars (the latter is safe because all
11938                 // pct-encoded sections are now valid).
11939                 $valid_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
11940
11941                 // Now replace any bytes that aren't allowed with their pct-encoded versions
11942                 $position = 0;
11943                 $strlen = strlen($string);
11944                 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11945                 {
11946                         $value = ord($string[$position]);
11947
11948                         // Start position
11949                         $start = $position;
11950
11951                         // By default we are valid
11952                         $valid = true;
11953
11954                         // No one byte sequences are valid due to the while.
11955                         // Two byte sequence:
11956                         if (($value & 0xE0) === 0xC0)
11957                         {
11958                                 $character = ($value & 0x1F) << 6;
11959                                 $length = 2;
11960                                 $remaining = 1;
11961                         }
11962                         // Three byte sequence:
11963                         elseif (($value & 0xF0) === 0xE0)
11964                         {
11965                                 $character = ($value & 0x0F) << 12;
11966                                 $length = 3;
11967                                 $remaining = 2;
11968                         }
11969                         // Four byte sequence:
11970                         elseif (($value & 0xF8) === 0xF0)
11971                         {
11972                                 $character = ($value & 0x07) << 18;
11973                                 $length = 4;
11974                                 $remaining = 3;
11975                         }
11976                         // Invalid byte:
11977                         else
11978                         {
11979                                 $valid = false;
11980                                 $length = 1;
11981                                 $remaining = 0;
11982                         }
11983
11984                         if ($remaining)
11985                         {
11986                                 if ($position + $length <= $strlen)
11987                                 {
11988                                         for ($position++; $remaining; $position++)
11989                                         {
11990                                                 $value = ord($string[$position]);
11991
11992                                                 // Check that the byte is valid, then add it to the character:
11993                                                 if (($value & 0xC0) === 0x80)
11994                                                 {
11995                                                         $character |= ($value & 0x3F) << (--$remaining * 6);
11996                                                 }
11997                                                 // If it is invalid, count the sequence as invalid and reprocess the current byte:
11998                                                 else
11999                                                 {
12000                                                         $valid = false;
12001                                                         $position--;
12002                                                         break;
12003                                                 }
12004                                         }
12005                                 }
12006                                 else
12007                                 {
12008                                         $position = $strlen - 1;
12009                                         $valid = false;
12010                                 }
12011                         }
12012
12013                         // Percent encode anything invalid or not in ucschar
12014                         if (
12015                                 // Invalid sequences
12016                                 !$valid
12017                                 // Non-shortest form sequences are invalid
12018                                 || $length > 1 && $character <= 0x7F
12019                                 || $length > 2 && $character <= 0x7FF
12020                                 || $length > 3 && $character <= 0xFFFF
12021                                 // Outside of range of ucschar codepoints
12022                                 // Noncharacters
12023                                 || ($character & 0xFFFE) === 0xFFFE
12024                                 || $character >= 0xFDD0 && $character <= 0xFDEF
12025                                 || (
12026                                         // Everything else not in ucschar
12027                                            $character > 0xD7FF && $character < 0xF900
12028                                         || $character < 0xA0
12029                                         || $character > 0xEFFFD
12030                                 )
12031                                 && (
12032                                         // Everything not in iprivate, if it applies
12033                                            !$iprivate
12034                                         || $character < 0xE000
12035                                         || $character > 0x10FFFD
12036                                 )
12037                         )
12038                         {
12039                                 // If we were a character, pretend we weren't, but rather an error.
12040                                 if ($valid)
12041                                         $position--;
12042
12043                                 for ($j = $start; $j <= $position; $j++)
12044                                 {
12045                                         $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
12046                                         $j += 2;
12047                                         $position += 2;
12048                                         $strlen += 2;
12049                                 }
12050                         }
12051                 }
12052
12053                 // Normalise case
12054                 if ($case & SIMPLEPIE_LOWERCASE)
12055                 {
12056                         $string = strtolower($string);
12057                 }
12058                 elseif ($case & SIMPLEPIE_UPPERCASE)
12059                 {
12060                         $string = strtoupper($string);
12061                 }
12062
12063                 return $string;
12064         }
12065
12066         /**
12067          * Callback function for preg_replace_callback.
12068          *
12069          * Removes sequences of percent encoded bytes that represent UTF-8
12070          * encoded characters in iunreserved
12071          *
12072          * @access private
12073          * @param array $match PCRE match
12074          * @return string Replacement
12075          */
12076         function remove_iunreserved_percent_encoded($match)
12077         {
12078                 // As we just have valid percent encoded sequences we can just explode
12079                 // and ignore the first member of the returned array (an empty string).
12080                 $bytes = explode('%', $match[0]);
12081
12082                 // Initialize the new string (this is what will be returned) and that
12083                 // there are no bytes remaining in the current sequence (unsurprising
12084                 // at the first byte!).
12085                 $string = '';
12086                 $remaining = 0;
12087
12088                 // Loop over each and every byte, and set $value to its value
12089                 for ($i = 1, $len = count($bytes); $i < $len; $i++)
12090                 {
12091                         $value = hexdec($bytes[$i]);
12092
12093                         // If we're the first byte of sequence:
12094                         if (!$remaining)
12095                         {
12096                                 // Start position
12097                                 $start = $i;
12098
12099                                 // By default we are valid
12100                                 $valid = true;
12101
12102                                 // One byte sequence:
12103                                 if ($value <= 0x7F)
12104                                 {
12105                                         $character = $value;
12106                                         $length = 1;
12107                                 }
12108                                 // Two byte sequence:
12109                                 elseif (($value & 0xE0) === 0xC0)
12110                                 {
12111                                         $character = ($value & 0x1F) << 6;
12112                                         $length = 2;
12113                                         $remaining = 1;
12114                                 }
12115                                 // Three byte sequence:
12116                                 elseif (($value & 0xF0) === 0xE0)
12117                                 {
12118                                         $character = ($value & 0x0F) << 12;
12119                                         $length = 3;
12120                                         $remaining = 2;
12121                                 }
12122                                 // Four byte sequence:
12123                                 elseif (($value & 0xF8) === 0xF0)
12124                                 {
12125                                         $character = ($value & 0x07) << 18;
12126                                         $length = 4;
12127                                         $remaining = 3;
12128                                 }
12129                                 // Invalid byte:
12130                                 else
12131                                 {
12132                                         $valid = false;
12133                                         $remaining = 0;
12134                                 }
12135                         }
12136                         // Continuation byte:
12137                         else
12138                         {
12139                                 // Check that the byte is valid, then add it to the character:
12140                                 if (($value & 0xC0) === 0x80)
12141                                 {
12142                                         $remaining--;
12143                                         $character |= ($value & 0x3F) << ($remaining * 6);
12144                                 }
12145                                 // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
12146                                 else
12147                                 {
12148                                         $valid = false;
12149                                         $remaining = 0;
12150                                         $i--;
12151                                 }
12152                         }
12153
12154                         // If we've reached the end of the current byte sequence, append it to Unicode::$data
12155                         if (!$remaining)
12156                         {
12157                                 // Percent encode anything invalid or not in iunreserved
12158                                 if (
12159                                         // Invalid sequences
12160                                         !$valid
12161                                         // Non-shortest form sequences are invalid
12162                                         || $length > 1 && $character <= 0x7F
12163                                         || $length > 2 && $character <= 0x7FF
12164                                         || $length > 3 && $character <= 0xFFFF
12165                                         // Outside of range of iunreserved codepoints
12166                                         || $character < 0x2D
12167                                         || $character > 0xEFFFD
12168                                         // Noncharacters
12169                                         || ($character & 0xFFFE) === 0xFFFE
12170                                         || $character >= 0xFDD0 && $character <= 0xFDEF
12171                                         // Everything else not in iunreserved (this is all BMP)
12172                                         || $character === 0x2F
12173                                         || $character > 0x39 && $character < 0x41
12174                                         || $character > 0x5A && $character < 0x61
12175                                         || $character > 0x7A && $character < 0x7E
12176                                         || $character > 0x7E && $character < 0xA0
12177                                         || $character > 0xD7FF && $character < 0xF900
12178                                 )
12179                                 {
12180                                         for ($j = $start; $j <= $i; $j++)
12181                                         {
12182                                                 $string .= '%' . strtoupper($bytes[$j]);
12183                                         }
12184                                 }
12185                                 else
12186                                 {
12187                                         for ($j = $start; $j <= $i; $j++)
12188                                         {
12189                                                 $string .= chr(hexdec($bytes[$j]));
12190                                         }
12191                                 }
12192                         }
12193                 }
12194
12195                 // If we have any bytes left over they are invalid (i.e., we are
12196                 // mid-way through a multi-byte sequence)
12197                 if ($remaining)
12198                 {
12199                         for ($j = $start; $j < $len; $j++)
12200                         {
12201                                 $string .= '%' . strtoupper($bytes[$j]);
12202                         }
12203                 }
12204
12205                 return $string;
12206         }
12207
12208         /**
12209          * Check if the object represents a valid IRI
12210          *
12211          * @access public
12212          * @return bool
12213          */
12214         function is_valid()
12215         {
12216                 return array_sum($this->valid) === count($this->valid);
12217         }
12218
12219         /**
12220          * Set the scheme. Returns true on success, false on failure (if there are
12221          * any invalid characters).
12222          *
12223          * @access public
12224          * @param string $scheme
12225          * @return bool
12226          */
12227         function set_scheme($scheme)
12228         {
12229                 if ($scheme === null || $scheme === '')
12230                 {
12231                         $this->scheme = null;
12232                 }
12233                 else
12234                 {
12235                         $len = strlen($scheme);
12236                         switch (true)
12237                         {
12238                                 case $len > 1:
12239                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
12240                                         {
12241                                                 $this->scheme = null;
12242                                                 $this->valid[__FUNCTION__] = false;
12243                                                 return false;
12244                                         }
12245
12246                                 case $len > 0:
12247                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12248                                         {
12249                                                 $this->scheme = null;
12250                                                 $this->valid[__FUNCTION__] = false;
12251                                                 return false;
12252                                         }
12253                         }
12254                         $this->scheme = strtolower($scheme);
12255                 }
12256                 $this->valid[__FUNCTION__] = true;
12257                 return true;
12258         }
12259
12260         /**
12261          * Set the authority. Returns true on success, false on failure (if there are
12262          * any invalid characters).
12263          *
12264          * @access public
12265          * @param string $authority
12266          * @return bool
12267          */
12268         function set_authority($authority)
12269         {
12270                 if (($userinfo_end = strrpos($authority, '@')) !== false)
12271                 {
12272                         $userinfo = substr($authority, 0, $userinfo_end);
12273                         $authority = substr($authority, $userinfo_end + 1);
12274                 }
12275                 else
12276                 {
12277                         $userinfo = null;
12278                 }
12279
12280                 if (($port_start = strpos($authority, ':')) !== false)
12281                 {
12282                         $port = substr($authority, $port_start + 1);
12283                         $authority = substr($authority, 0, $port_start);
12284                 }
12285                 else
12286                 {
12287                         $port = null;
12288                 }
12289
12290                 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12291         }
12292
12293         /**
12294          * Set the userinfo.
12295          *
12296          * @access public
12297          * @param string $userinfo
12298          * @return bool
12299          */
12300         function set_userinfo($userinfo)
12301         {
12302                 if ($userinfo === null || $userinfo === '')
12303                 {
12304                         $this->userinfo = null;
12305                 }
12306                 else
12307                 {
12308                         $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12309                 }
12310                 $this->valid[__FUNCTION__] = true;
12311                 return true;
12312         }
12313
12314         /**
12315          * Set the host. Returns true on success, false on failure (if there are
12316          * any invalid characters).
12317          *
12318          * @access public
12319          * @param string $host
12320          * @return bool
12321          */
12322         function set_host($host)
12323         {
12324                 if ($host === null || $host === '')
12325                 {
12326                         $this->host = null;
12327                         $this->valid[__FUNCTION__] = true;
12328                         return true;
12329                 }
12330                 elseif ($host[0] === '[' && substr($host, -1) === ']')
12331                 {
12332                         if (SimplePie_Net_IPv6::checkIPv6(substr($host, 1, -1)))
12333                         {
12334                                 $this->host = $host;
12335                                 $this->valid[__FUNCTION__] = true;
12336                                 return true;
12337                         }
12338                         else
12339                         {
12340                                 $this->host = null;
12341                                 $this->valid[__FUNCTION__] = false;
12342                                 return false;
12343                         }
12344                 }
12345                 else
12346                 {
12347                         $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12348                         $this->valid[__FUNCTION__] = true;
12349                         return true;
12350                 }
12351         }
12352
12353         /**
12354          * Set the port. Returns true on success, false on failure (if there are
12355          * any invalid characters).
12356          *
12357          * @access public
12358          * @param string $port
12359          * @return bool
12360          */
12361         function set_port($port)
12362         {
12363                 if ($port === null || $port === '')
12364                 {
12365                         $this->port = null;
12366                         $this->valid[__FUNCTION__] = true;
12367                         return true;
12368                 }
12369                 elseif (strspn($port, '0123456789') === strlen($port))
12370                 {
12371                         $this->port = (int) $port;
12372                         $this->valid[__FUNCTION__] = true;
12373                         return true;
12374                 }
12375                 else
12376                 {
12377                         $this->port = null;
12378                         $this->valid[__FUNCTION__] = false;
12379                         return false;
12380                 }
12381         }
12382
12383         /**
12384          * Set the path.
12385          *
12386          * @access public
12387          * @param string $path
12388          * @return bool
12389          */
12390         function set_path($path)
12391         {
12392                 if ($path === null || $path === '')
12393                 {
12394                         $this->path = null;
12395                         $this->valid[__FUNCTION__] = true;
12396                         return true;
12397                 }
12398                 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12399                 {
12400                         $this->path = null;
12401                         $this->valid[__FUNCTION__] = false;
12402                         return false;
12403                 }
12404                 else
12405                 {
12406                         $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12407                         if ($this->scheme !== null)
12408                         {
12409                                 $this->path = $this->remove_dot_segments($this->path);
12410                         }
12411                         $this->valid[__FUNCTION__] = true;
12412                         return true;
12413                 }
12414         }
12415
12416         /**
12417          * Set the query.
12418          *
12419          * @access public
12420          * @param string $query
12421          * @return bool
12422          */
12423         function set_query($query)
12424         {
12425                 if ($query === null || $query === '')
12426                 {
12427                         $this->query = null;
12428                 }
12429                 else
12430                 {
12431                         $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&=');
12432                 }
12433                 $this->valid[__FUNCTION__] = true;
12434                 return true;
12435         }
12436
12437         /**
12438          * Set the fragment.
12439          *
12440          * @access public
12441          * @param string $fragment
12442          * @return bool
12443          */
12444         function set_fragment($fragment)
12445         {
12446                 if ($fragment === null || $fragment === '')
12447                 {
12448                         $this->fragment = null;
12449                 }
12450                 else
12451                 {
12452                         $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12453                 }
12454                 $this->valid[__FUNCTION__] = true;
12455                 return true;
12456         }
12457
12458         /**
12459          * Get the complete IRI
12460          *
12461          * @access public
12462          * @return string
12463          */
12464         function get_iri()
12465         {
12466                 $iri = '';
12467                 if ($this->scheme !== null)
12468                 {
12469                         $iri .= $this->scheme . ':';
12470                 }
12471                 if (($authority = $this->get_authority()) !== null)
12472                 {
12473                         $iri .= '//' . $authority;
12474                 }
12475                 if ($this->path !== null)
12476                 {
12477                         $iri .= $this->path;
12478                 }
12479                 if ($this->query !== null)
12480                 {
12481                         $iri .= '?' . $this->query;
12482                 }
12483                 if ($this->fragment !== null)
12484                 {
12485                         $iri .= '#' . $this->fragment;
12486                 }
12487
12488                 if ($iri !== '')
12489                 {
12490                         return $iri;
12491                 }
12492                 else
12493                 {
12494                         return null;
12495                 }
12496         }
12497
12498         /**
12499          * Get the scheme
12500          *
12501          * @access public
12502          * @return string
12503          */
12504         function get_scheme()
12505         {
12506                 return $this->scheme;
12507         }
12508
12509         /**
12510          * Get the complete authority
12511          *
12512          * @access public
12513          * @return string
12514          */
12515         function get_authority()
12516         {
12517                 $authority = '';
12518                 if ($this->userinfo !== null)
12519                 {
12520                         $authority .= $this->userinfo . '@';
12521                 }
12522                 if ($this->host !== null)
12523                 {
12524                         $authority .= $this->host;
12525                 }
12526                 if ($this->port !== null)
12527                 {
12528                         $authority .= ':' . $this->port;
12529                 }
12530
12531                 if ($authority !== '')
12532                 {
12533                         return $authority;
12534                 }
12535                 else
12536                 {
12537                         return null;
12538                 }
12539         }
12540
12541         /**
12542          * Get the user information
12543          *
12544          * @access public
12545          * @return string
12546          */
12547         function get_userinfo()
12548         {
12549                 return $this->userinfo;
12550         }
12551
12552         /**
12553          * Get the host
12554          *
12555          * @access public
12556          * @return string
12557          */
12558         function get_host()
12559         {
12560                 return $this->host;
12561         }
12562
12563         /**
12564          * Get the port
12565          *
12566          * @access public
12567          * @return string
12568          */
12569         function get_port()
12570         {
12571                 return $this->port;
12572         }
12573
12574         /**
12575          * Get the path
12576          *
12577          * @access public
12578          * @return string
12579          */
12580         function get_path()
12581         {
12582                 return $this->path;
12583         }
12584
12585         /**
12586          * Get the query
12587          *
12588          * @access public
12589          * @return string
12590          */
12591         function get_query()
12592         {
12593                 return $this->query;
12594         }
12595
12596         /**
12597          * Get the fragment
12598          *
12599          * @access public
12600          * @return string
12601          */
12602         function get_fragment()
12603         {
12604                 return $this->fragment;
12605         }
12606 }
12607
12608 /**
12609  * Class to validate and to work with IPv6 addresses.
12610  *
12611  * @package SimplePie
12612  * @copyright 2003-2005 The PHP Group
12613  * @license http://www.opensource.org/licenses/bsd-license.php
12614  * @link http://pear.php.net/package/Net_IPv6
12615  * @author Alexander Merz <alexander.merz@web.de>
12616  * @author elfrink at introweb dot nl
12617  * @author Josh Peck <jmp at joshpeck dot org>
12618  * @author Geoffrey Sneddon <geoffers@gmail.com>
12619  */
12620 class SimplePie_Net_IPv6
12621 {
12622         /**
12623          * Removes a possible existing netmask specification of an IP address.
12624          *
12625          * @param string $ip the (compressed) IP as Hex representation
12626          * @return string the IP the without netmask
12627          * @since 1.1.0
12628          * @access public
12629          * @static
12630          */
12631         function removeNetmaskSpec($ip)
12632         {
12633                 if (strpos($ip, '/') !== false)
12634                 {
12635                         list($addr, $nm) = explode('/', $ip);
12636                 }
12637                 else
12638                 {
12639                         $addr = $ip;
12640                 }
12641                 return $addr;
12642         }
12643
12644         /**
12645          * Uncompresses an IPv6 address
12646          *
12647          * RFC 2373 allows you to compress zeros in an address to '::'. This
12648          * function expects an valid IPv6 address and expands the '::' to
12649          * the required zeros.
12650          *
12651          * Example:      FF01::101      ->      FF01:0:0:0:0:0:0:101
12652          *                       ::1            ->      0:0:0:0:0:0:0:1
12653          *
12654          * @access public
12655          * @static
12656          * @param string $ip a valid IPv6-address (hex format)
12657          * @return string the uncompressed IPv6-address (hex format)
12658          */
12659         function Uncompress($ip)
12660         {
12661                 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12662                 $c1 = -1;
12663                 $c2 = -1;
12664                 if (strpos($ip, '::') !== false)
12665                 {
12666                         list($ip1, $ip2) = explode('::', $ip);
12667                         if ($ip1 === '')
12668                         {
12669                                 $c1 = -1;
12670                         }
12671                         else
12672                         {
12673                                 $pos = 0;
12674                                 if (($pos = substr_count($ip1, ':')) > 0)
12675                                 {
12676                                         $c1 = $pos;
12677                                 }
12678                                 else
12679                                 {
12680                                         $c1 = 0;
12681                                 }
12682                         }
12683                         if ($ip2 === '')
12684                         {
12685                                 $c2 = -1;
12686                         }
12687                         else
12688                         {
12689                                 $pos = 0;
12690                                 if (($pos = substr_count($ip2, ':')) > 0)
12691                                 {
12692                                         $c2 = $pos;
12693                                 }
12694                                 else
12695                                 {
12696                                         $c2 = 0;
12697                                 }
12698                         }
12699                         if (strstr($ip2, '.'))
12700                         {
12701                                 $c2++;
12702                         }
12703                         // ::
12704                         if ($c1 === -1 && $c2 === -1)
12705                         {
12706                                 $uip = '0:0:0:0:0:0:0:0';
12707                         }
12708                         // ::xxx
12709                         else if ($c1 === -1)
12710                         {
12711                                 $fill = str_repeat('0:', 7 - $c2);
12712                                 $uip =  str_replace('::', $fill, $uip);
12713                         }
12714                         // xxx::
12715                         else if ($c2 === -1)
12716                         {
12717                                 $fill = str_repeat(':0', 7 - $c1);
12718                                 $uip =  str_replace('::', $fill, $uip);
12719                         }
12720                         // xxx::xxx
12721                         else
12722                         {
12723                                 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12724                                 $uip =  str_replace('::', $fill, $uip);
12725                                 $uip =  str_replace('::', ':', $uip);
12726                         }
12727                 }
12728                 return $uip;
12729         }
12730
12731         /**
12732          * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12733          *
12734          * RFC 2373 allows you to note the last two parts of an IPv6 address as
12735          * an IPv4 compatible address
12736          *
12737          * Example:      0:0:0:0:0:0:13.1.68.3
12738          *                       0:0:0:0:0:FFFF:129.144.52.38
12739          *
12740          * @access public
12741          * @static
12742          * @param string $ip a valid IPv6-address (hex format)
12743          * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12744          */
12745         function SplitV64($ip)
12746         {
12747                 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12748                 if (strstr($ip, '.'))
12749                 {
12750                         $pos = strrpos($ip, ':');
12751                         $ip[$pos] = '_';
12752                         $ipPart = explode('_', $ip);
12753                         return $ipPart;
12754                 }
12755                 else
12756                 {
12757                         return array($ip, '');
12758                 }
12759         }
12760
12761         /**
12762          * Checks an IPv6 address
12763          *
12764          * Checks if the given IP is IPv6-compatible
12765          *
12766          * @access public
12767          * @static
12768          * @param string $ip a valid IPv6-address
12769          * @return bool true if $ip is an IPv6 address
12770          */
12771         function checkIPv6($ip)
12772         {
12773                 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12774                 $count = 0;
12775                 if (!empty($ipPart[0]))
12776                 {
12777                         $ipv6 = explode(':', $ipPart[0]);
12778                         for ($i = 0; $i < count($ipv6); $i++)
12779                         {
12780                                 $dec = hexdec($ipv6[$i]);
12781                                 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12782                                 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12783                                 {
12784                                         $count++;
12785                                 }
12786                         }
12787                         if ($count === 8)
12788                         {
12789                                 return true;
12790                         }
12791                         elseif ($count === 6 && !empty($ipPart[1]))
12792                         {
12793                                 $ipv4 = explode('.', $ipPart[1]);
12794                                 $count = 0;
12795                                 foreach ($ipv4 as $ipv4_part)
12796                                 {
12797                                         if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12798                                         {
12799                                                 $count++;
12800                                         }
12801                                 }
12802                                 if ($count === 4)
12803                                 {
12804                                         return true;
12805                                 }
12806                         }
12807                         else
12808                         {
12809                                 return false;
12810                         }
12811
12812                 }
12813                 else
12814                 {
12815                         return false;
12816                 }
12817         }
12818 }
12819
12820 /**
12821  * Date Parser
12822  *
12823  * @package SimplePie
12824  */
12825 class SimplePie_Parse_Date
12826 {
12827         /**
12828          * Input data
12829          *
12830          * @access protected
12831          * @var string
12832          */
12833         var $date;
12834
12835         /**
12836          * List of days, calendar day name => ordinal day number in the week
12837          *
12838          * @access protected
12839          * @var array
12840          */
12841         var $day = array(
12842                 // English
12843                 'mon' => 1,
12844                 'monday' => 1,
12845                 'tue' => 2,
12846                 'tuesday' => 2,
12847                 'wed' => 3,
12848                 'wednesday' => 3,
12849                 'thu' => 4,
12850                 'thursday' => 4,
12851                 'fri' => 5,
12852                 'friday' => 5,
12853                 'sat' => 6,
12854                 'saturday' => 6,
12855                 'sun' => 7,
12856                 'sunday' => 7,
12857                 // Dutch
12858                 'maandag' => 1,
12859                 'dinsdag' => 2,
12860                 'woensdag' => 3,
12861                 'donderdag' => 4,
12862                 'vrijdag' => 5,
12863                 'zaterdag' => 6,
12864                 'zondag' => 7,
12865                 // French
12866                 'lundi' => 1,
12867                 'mardi' => 2,
12868                 'mercredi' => 3,
12869                 'jeudi' => 4,
12870                 'vendredi' => 5,
12871                 'samedi' => 6,
12872                 'dimanche' => 7,
12873                 // German
12874                 'montag' => 1,
12875                 'dienstag' => 2,
12876                 'mittwoch' => 3,
12877                 'donnerstag' => 4,
12878                 'freitag' => 5,
12879                 'samstag' => 6,
12880                 'sonnabend' => 6,
12881                 'sonntag' => 7,
12882                 // Italian
12883                 'lunedì' => 1,
12884                 'martedì' => 2,
12885                 'mercoledì' => 3,
12886                 'giovedì' => 4,
12887                 'venerdì' => 5,
12888                 'sabato' => 6,
12889                 'domenica' => 7,
12890                 // Spanish
12891                 'lunes' => 1,
12892                 'martes' => 2,
12893                 'miércoles' => 3,
12894                 'jueves' => 4,
12895                 'viernes' => 5,
12896                 'sábado' => 6,
12897                 'domingo' => 7,
12898                 // Finnish
12899                 'maanantai' => 1,
12900                 'tiistai' => 2,
12901                 'keskiviikko' => 3,
12902                 'torstai' => 4,
12903                 'perjantai' => 5,
12904                 'lauantai' => 6,
12905                 'sunnuntai' => 7,
12906                 // Hungarian
12907                 'hétfő' => 1,
12908                 'kedd' => 2,
12909                 'szerda' => 3,
12910                 'csütörtok' => 4,
12911                 'péntek' => 5,
12912                 'szombat' => 6,
12913                 'vasárnap' => 7,
12914                 // Greek
12915                 'Δευ' => 1,
12916                 'Τρι' => 2,
12917                 'Τετ' => 3,
12918                 'Πεμ' => 4,
12919                 'Παρ' => 5,
12920                 'Σαβ' => 6,
12921                 'Κυρ' => 7,
12922         );
12923
12924         /**
12925          * List of months, calendar month name => calendar month number
12926          *
12927          * @access protected
12928          * @var array
12929          */
12930         var $month = array(
12931                 // English
12932                 'jan' => 1,
12933                 'january' => 1,
12934                 'feb' => 2,
12935                 'february' => 2,
12936                 'mar' => 3,
12937                 'march' => 3,
12938                 'apr' => 4,
12939                 'april' => 4,
12940                 'may' => 5,
12941                 // No long form of May
12942                 'jun' => 6,
12943                 'june' => 6,
12944                 'jul' => 7,
12945                 'july' => 7,
12946                 'aug' => 8,
12947                 'august' => 8,
12948                 'sep' => 9,
12949                 'september' => 8,
12950                 'oct' => 10,
12951                 'october' => 10,
12952                 'nov' => 11,
12953                 'november' => 11,
12954                 'dec' => 12,
12955                 'december' => 12,
12956                 // Dutch
12957                 'januari' => 1,
12958                 'februari' => 2,
12959                 'maart' => 3,
12960                 'april' => 4,
12961                 'mei' => 5,
12962                 'juni' => 6,
12963                 'juli' => 7,
12964                 'augustus' => 8,
12965                 'september' => 9,
12966                 'oktober' => 10,
12967                 'november' => 11,
12968                 'december' => 12,
12969                 // French
12970                 'janvier' => 1,
12971                 'février' => 2,
12972                 'mars' => 3,
12973                 'avril' => 4,
12974                 'mai' => 5,
12975                 'juin' => 6,
12976                 'juillet' => 7,
12977                 'août' => 8,
12978                 'septembre' => 9,
12979                 'octobre' => 10,
12980                 'novembre' => 11,
12981                 'décembre' => 12,
12982                 // German
12983                 'januar' => 1,
12984                 'februar' => 2,
12985                 'märz' => 3,
12986                 'april' => 4,
12987                 'mai' => 5,
12988                 'juni' => 6,
12989                 'juli' => 7,
12990                 'august' => 8,
12991                 'september' => 9,
12992                 'oktober' => 10,
12993                 'november' => 11,
12994                 'dezember' => 12,
12995                 // Italian
12996                 'gennaio' => 1,
12997                 'febbraio' => 2,
12998                 'marzo' => 3,
12999                 'aprile' => 4,
13000                 'maggio' => 5,
13001                 'giugno' => 6,
13002                 'luglio' => 7,
13003                 'agosto' => 8,
13004                 'settembre' => 9,
13005                 'ottobre' => 10,
13006                 'novembre' => 11,
13007                 'dicembre' => 12,
13008                 // Spanish
13009                 'enero' => 1,
13010                 'febrero' => 2,
13011                 'marzo' => 3,
13012                 'abril' => 4,
13013                 'mayo' => 5,
13014                 'junio' => 6,
13015                 'julio' => 7,
13016                 'agosto' => 8,
13017                 'septiembre' => 9,
13018                 'setiembre' => 9,
13019                 'octubre' => 10,
13020                 'noviembre' => 11,
13021                 'diciembre' => 12,
13022                 // Finnish
13023                 'tammikuu' => 1,
13024                 'helmikuu' => 2,
13025                 'maaliskuu' => 3,
13026                 'huhtikuu' => 4,
13027                 'toukokuu' => 5,
13028                 'kesäkuu' => 6,
13029                 'heinäkuu' => 7,
13030                 'elokuu' => 8,
13031                 'suuskuu' => 9,
13032                 'lokakuu' => 10,
13033                 'marras' => 11,
13034                 'joulukuu' => 12,
13035                 // Hungarian
13036                 'január' => 1,
13037                 'február' => 2,
13038                 'március' => 3,
13039                 'április' => 4,
13040                 'május' => 5,
13041                 'június' => 6,
13042                 'július' => 7,
13043                 'augusztus' => 8,
13044                 'szeptember' => 9,
13045                 'október' => 10,
13046                 'november' => 11,
13047                 'december' => 12,
13048                 // Greek
13049                 'Ιαν' => 1,
13050                 'Φεβ' => 2,
13051                 'Μάώ' => 3,
13052                 'Μαώ' => 3,
13053                 'Απρ' => 4,
13054                 'Μάι' => 5,
13055                 'Μαϊ' => 5,
13056                 'Μαι' => 5,
13057                 'Ιούν' => 6,
13058                 'Ιον' => 6,
13059                 'Ιούλ' => 7,
13060                 'Ιολ' => 7,
13061                 'Αύγ' => 8,
13062                 'Αυγ' => 8,
13063                 'Σεπ' => 9,
13064                 'Οκτ' => 10,
13065                 'Νοέ' => 11,
13066                 'Δεκ' => 12,
13067         );
13068
13069         /**
13070          * List of timezones, abbreviation => offset from UTC
13071          *
13072          * @access protected
13073          * @var array
13074          */
13075         var $timezone = array(
13076                 'ACDT' => 37800,
13077                 'ACIT' => 28800,
13078                 'ACST' => 34200,
13079                 'ACT' => -18000,
13080                 'ACWDT' => 35100,
13081                 'ACWST' => 31500,
13082                 'AEDT' => 39600,
13083                 'AEST' => 36000,
13084                 'AFT' => 16200,
13085                 'AKDT' => -28800,
13086                 'AKST' => -32400,
13087                 'AMDT' => 18000,
13088                 'AMT' => -14400,
13089                 'ANAST' => 46800,
13090                 'ANAT' => 43200,
13091                 'ART' => -10800,
13092                 'AZOST' => -3600,
13093                 'AZST' => 18000,
13094                 'AZT' => 14400,
13095                 'BIOT' => 21600,
13096                 'BIT' => -43200,
13097                 'BOT' => -14400,
13098                 'BRST' => -7200,
13099                 'BRT' => -10800,
13100                 'BST' => 3600,
13101                 'BTT' => 21600,
13102                 'CAST' => 18000,
13103                 'CAT' => 7200,
13104                 'CCT' => 23400,
13105                 'CDT' => -18000,
13106                 'CEDT' => 7200,
13107                 'CET' => 3600,
13108                 'CGST' => -7200,
13109                 'CGT' => -10800,
13110                 'CHADT' => 49500,
13111                 'CHAST' => 45900,
13112                 'CIST' => -28800,
13113                 'CKT' => -36000,
13114                 'CLDT' => -10800,
13115                 'CLST' => -14400,
13116                 'COT' => -18000,
13117                 'CST' => -21600,
13118                 'CVT' => -3600,
13119                 'CXT' => 25200,
13120                 'DAVT' => 25200,
13121                 'DTAT' => 36000,
13122                 'EADT' => -18000,
13123                 'EAST' => -21600,
13124                 'EAT' => 10800,
13125                 'ECT' => -18000,
13126                 'EDT' => -14400,
13127                 'EEST' => 10800,
13128                 'EET' => 7200,
13129                 'EGT' => -3600,
13130                 'EKST' => 21600,
13131                 'EST' => -18000,
13132                 'FJT' => 43200,
13133                 'FKDT' => -10800,
13134                 'FKST' => -14400,
13135                 'FNT' => -7200,
13136                 'GALT' => -21600,
13137                 'GEDT' => 14400,
13138                 'GEST' => 10800,
13139                 'GFT' => -10800,
13140                 'GILT' => 43200,
13141                 'GIT' => -32400,
13142                 'GST' => 14400,
13143                 'GST' => -7200,
13144                 'GYT' => -14400,
13145                 'HAA' => -10800,
13146                 'HAC' => -18000,
13147                 'HADT' => -32400,
13148                 'HAE' => -14400,
13149                 'HAP' => -25200,
13150                 'HAR' => -21600,
13151                 'HAST' => -36000,
13152                 'HAT' => -9000,
13153                 'HAY' => -28800,
13154                 'HKST' => 28800,
13155                 'HMT' => 18000,
13156                 'HNA' => -14400,
13157                 'HNC' => -21600,
13158                 'HNE' => -18000,
13159                 'HNP' => -28800,
13160                 'HNR' => -25200,
13161                 'HNT' => -12600,
13162                 'HNY' => -32400,
13163                 'IRDT' => 16200,
13164                 'IRKST' => 32400,
13165                 'IRKT' => 28800,
13166                 'IRST' => 12600,
13167                 'JFDT' => -10800,
13168                 'JFST' => -14400,
13169                 'JST' => 32400,
13170                 'KGST' => 21600,
13171                 'KGT' => 18000,
13172                 'KOST' => 39600,
13173                 'KOVST' => 28800,
13174                 'KOVT' => 25200,
13175                 'KRAST' => 28800,
13176                 'KRAT' => 25200,
13177                 'KST' => 32400,
13178                 'LHDT' => 39600,
13179                 'LHST' => 37800,
13180                 'LINT' => 50400,
13181                 'LKT' => 21600,
13182                 'MAGST' => 43200,
13183                 'MAGT' => 39600,
13184                 'MAWT' => 21600,
13185                 'MDT' => -21600,
13186                 'MESZ' => 7200,
13187                 'MEZ' => 3600,
13188                 'MHT' => 43200,
13189                 'MIT' => -34200,
13190                 'MNST' => 32400,
13191                 'MSDT' => 14400,
13192                 'MSST' => 10800,
13193                 'MST' => -25200,
13194                 'MUT' => 14400,
13195                 'MVT' => 18000,
13196                 'MYT' => 28800,
13197                 'NCT' => 39600,
13198                 'NDT' => -9000,
13199                 'NFT' => 41400,
13200                 'NMIT' => 36000,
13201                 'NOVST' => 25200,
13202                 'NOVT' => 21600,
13203                 'NPT' => 20700,
13204                 'NRT' => 43200,
13205                 'NST' => -12600,
13206                 'NUT' => -39600,
13207                 'NZDT' => 46800,
13208                 'NZST' => 43200,
13209                 'OMSST' => 25200,
13210                 'OMST' => 21600,
13211                 'PDT' => -25200,
13212                 'PET' => -18000,
13213                 'PETST' => 46800,
13214                 'PETT' => 43200,
13215                 'PGT' => 36000,
13216                 'PHOT' => 46800,
13217                 'PHT' => 28800,
13218                 'PKT' => 18000,
13219                 'PMDT' => -7200,
13220                 'PMST' => -10800,
13221                 'PONT' => 39600,
13222                 'PST' => -28800,
13223                 'PWT' => 32400,
13224                 'PYST' => -10800,
13225                 'PYT' => -14400,
13226                 'RET' => 14400,
13227                 'ROTT' => -10800,
13228                 'SAMST' => 18000,
13229                 'SAMT' => 14400,
13230                 'SAST' => 7200,
13231                 'SBT' => 39600,
13232                 'SCDT' => 46800,
13233                 'SCST' => 43200,
13234                 'SCT' => 14400,
13235                 'SEST' => 3600,
13236                 'SGT' => 28800,
13237                 'SIT' => 28800,
13238                 'SRT' => -10800,
13239                 'SST' => -39600,
13240                 'SYST' => 10800,
13241                 'SYT' => 7200,
13242                 'TFT' => 18000,
13243                 'THAT' => -36000,
13244                 'TJT' => 18000,
13245                 'TKT' => -36000,
13246                 'TMT' => 18000,
13247                 'TOT' => 46800,
13248                 'TPT' => 32400,
13249                 'TRUT' => 36000,
13250                 'TVT' => 43200,
13251                 'TWT' => 28800,
13252                 'UYST' => -7200,
13253                 'UYT' => -10800,
13254                 'UZT' => 18000,
13255                 'VET' => -14400,
13256                 'VLAST' => 39600,
13257                 'VLAT' => 36000,
13258                 'VOST' => 21600,
13259                 'VUT' => 39600,
13260                 'WAST' => 7200,
13261                 'WAT' => 3600,
13262                 'WDT' => 32400,
13263                 'WEST' => 3600,
13264                 'WFT' => 43200,
13265                 'WIB' => 25200,
13266                 'WIT' => 32400,
13267                 'WITA' => 28800,
13268                 'WKST' => 18000,
13269                 'WST' => 28800,
13270                 'YAKST' => 36000,
13271                 'YAKT' => 32400,
13272                 'YAPT' => 36000,
13273                 'YEKST' => 21600,
13274                 'YEKT' => 18000,
13275         );
13276
13277         /**
13278          * Cached PCRE for SimplePie_Parse_Date::$day
13279          *
13280          * @access protected
13281          * @var string
13282          */
13283         var $day_pcre;
13284
13285         /**
13286          * Cached PCRE for SimplePie_Parse_Date::$month
13287          *
13288          * @access protected
13289          * @var string
13290          */
13291         var $month_pcre;
13292
13293         /**
13294          * Array of user-added callback methods
13295          *
13296          * @access private
13297          * @var array
13298          */
13299         var $built_in = array();
13300
13301         /**
13302          * Array of user-added callback methods
13303          *
13304          * @access private
13305          * @var array
13306          */
13307         var $user = array();
13308
13309         /**
13310          * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13311          * self::month_pcre, and self::built_in
13312          *
13313          * @access private
13314          */
13315         function SimplePie_Parse_Date()
13316         {
13317                 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13318                 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13319
13320                 static $cache;
13321                 if (!isset($cache[get_class($this)]))
13322                 {
13323                         $all_methods = get_class_methods($this);
13324
13325                         foreach ($all_methods as $method)
13326                         {
13327                                 if (strtolower(substr($method, 0, 5)) === 'date_')
13328                                 {
13329                                         $cache[get_class($this)][] = $method;
13330                                 }
13331                         }
13332                 }
13333
13334                 foreach ($cache[get_class($this)] as $method)
13335                 {
13336                         $this->built_in[] = $method;
13337                 }
13338         }
13339
13340         /**
13341          * Get the object
13342          *
13343          * @access public
13344          */
13345         function get()
13346         {
13347                 static $object;
13348                 if (!$object)
13349                 {
13350                         $object =& new SimplePie_Parse_Date;
13351                 }
13352                 return $object;
13353         }
13354
13355         /**
13356          * Parse a date
13357          *
13358          * @final
13359          * @access public
13360          * @param string $date Date to parse
13361          * @return int Timestamp corresponding to date string, or false on failure
13362          */
13363         function parse($date)
13364         {
13365                 foreach ($this->user as $method)
13366                 {
13367                         if (($returned = call_user_func($method, $date)) !== false)
13368                         {
13369                                 return $returned;
13370                         }
13371                 }
13372
13373                 foreach ($this->built_in as $method)
13374                 {
13375                         if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13376                         {
13377                                 return $returned;
13378                         }
13379                 }
13380
13381                 return false;
13382         }
13383
13384         /**
13385          * Add a callback method to parse a date
13386          *
13387          * @final
13388          * @access public
13389          * @param callback $callback
13390          */
13391         function add_callback($callback)
13392         {
13393                 if (is_callable($callback))
13394                 {
13395                         $this->user[] = $callback;
13396                 }
13397                 else
13398                 {
13399                         trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13400                 }
13401         }
13402
13403         /**
13404          * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13405          * well as allowing any of upper or lower case "T", horizontal tabs, or
13406          * spaces to be used as the time seperator (including more than one))
13407          *
13408          * @access protected
13409          * @return int Timestamp
13410          */
13411         function date_w3cdtf($date)
13412         {
13413                 static $pcre;
13414                 if (!$pcre)
13415                 {
13416                         $year = '([0-9]{4})';
13417                         $month = $day = $hour = $minute = $second = '([0-9]{2})';
13418                         $decimal = '([0-9]*)';
13419                         $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13420                         $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13421                 }
13422                 if (preg_match($pcre, $date, $match))
13423                 {
13424                         /*
13425                         Capturing subpatterns:
13426                         1: Year
13427                         2: Month
13428                         3: Day
13429                         4: Hour
13430                         5: Minute
13431                         6: Second
13432                         7: Decimal fraction of a second
13433                         8: Zulu
13434                         9: Timezone ±
13435                         10: Timezone hours
13436                         11: Timezone minutes
13437                         */
13438
13439                         // Fill in empty matches
13440                         for ($i = count($match); $i <= 3; $i++)
13441                         {
13442                                 $match[$i] = '1';
13443                         }
13444
13445                         for ($i = count($match); $i <= 7; $i++)
13446                         {
13447                                 $match[$i] = '0';
13448                         }
13449
13450                         // Numeric timezone
13451                         if (isset($match[9]) && $match[9] !== '')
13452                         {
13453                                 $timezone = $match[10] * 3600;
13454                                 $timezone += $match[11] * 60;
13455                                 if ($match[9] === '-')
13456                                 {
13457                                         $timezone = 0 - $timezone;
13458                                 }
13459                         }
13460                         else
13461                         {
13462                                 $timezone = 0;
13463                         }
13464
13465                         // Convert the number of seconds to an integer, taking decimals into account
13466                         $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13467
13468                         return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13469                 }
13470                 else
13471                 {
13472                         return false;
13473                 }
13474         }
13475
13476         /**
13477          * Remove RFC822 comments
13478          *
13479          * @access protected
13480          * @param string $data Data to strip comments from
13481          * @return string Comment stripped string
13482          */
13483         function remove_rfc2822_comments($string)
13484         {
13485                 $string = (string) $string;
13486                 $position = 0;
13487                 $length = strlen($string);
13488                 $depth = 0;
13489
13490                 $output = '';
13491
13492                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13493                 {
13494                         $output .= substr($string, $position, $pos - $position);
13495                         $position = $pos + 1;
13496                         if ($string[$pos - 1] !== '\\')
13497                         {
13498                                 $depth++;
13499                                 while ($depth && $position < $length)
13500                                 {
13501                                         $position += strcspn($string, '()', $position);
13502                                         if ($string[$position - 1] === '\\')
13503                                         {
13504                                                 $position++;
13505                                                 continue;
13506                                         }
13507                                         elseif (isset($string[$position]))
13508                                         {
13509                                                 switch ($string[$position])
13510                                                 {
13511                                                         case '(':
13512                                                                 $depth++;
13513                                                                 break;
13514
13515                                                         case ')':
13516                                                                 $depth--;
13517                                                                 break;
13518                                                 }
13519                                                 $position++;
13520                                         }
13521                                         else
13522                                         {
13523                                                 break;
13524                                         }
13525                                 }
13526                         }
13527                         else
13528                         {
13529                                 $output .= '(';
13530                         }
13531                 }
13532                 $output .= substr($string, $position);
13533
13534                 return $output;
13535         }
13536
13537         /**
13538          * Parse RFC2822's date format
13539          *
13540          * @access protected
13541          * @return int Timestamp
13542          */
13543         function date_rfc2822($date)
13544         {
13545                 static $pcre;
13546                 if (!$pcre)
13547                 {
13548                         $wsp = '[\x09\x20]';
13549                         $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13550                         $optional_fws = $fws . '?';
13551                         $day_name = $this->day_pcre;
13552                         $month = $this->month_pcre;
13553                         $day = '([0-9]{1,2})';
13554                         $hour = $minute = $second = '([0-9]{2})';
13555                         $year = '([0-9]{2,4})';
13556                         $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13557                         $character_zone = '([A-Z]{1,5})';
13558                         $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13559                         $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
13560                 }
13561                 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13562                 {
13563                         /*
13564                         Capturing subpatterns:
13565                         1: Day name
13566                         2: Day
13567                         3: Month
13568                         4: Year
13569                         5: Hour
13570                         6: Minute
13571                         7: Second
13572                         8: Timezone ±
13573                         9: Timezone hours
13574                         10: Timezone minutes
13575                         11: Alphabetic timezone
13576                         */
13577
13578                         // Find the month number
13579                         $month = $this->month[strtolower($match[3])];
13580
13581                         // Numeric timezone
13582                         if ($match[8] !== '')
13583                         {
13584                                 $timezone = $match[9] * 3600;
13585                                 $timezone += $match[10] * 60;
13586                                 if ($match[8] === '-')
13587                                 {
13588                                         $timezone = 0 - $timezone;
13589                                 }
13590                         }
13591                         // Character timezone
13592                         elseif (isset($this->timezone[strtoupper($match[11])]))
13593                         {
13594                                 $timezone = $this->timezone[strtoupper($match[11])];
13595                         }
13596                         // Assume everything else to be -0000
13597                         else
13598                         {
13599                                 $timezone = 0;
13600                         }
13601
13602                         // Deal with 2/3 digit years
13603                         if ($match[4] < 50)
13604                         {
13605                                 $match[4] += 2000;
13606                         }
13607                         elseif ($match[4] < 1000)
13608                         {
13609                                 $match[4] += 1900;
13610                         }
13611
13612                         // Second is optional, if it is empty set it to zero
13613                         if ($match[7] !== '')
13614                         {
13615                                 $second = $match[7];
13616                         }
13617                         else
13618                         {
13619                                 $second = 0;
13620                         }
13621
13622                         return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13623                 }
13624                 else
13625                 {
13626                         return false;
13627                 }
13628         }
13629
13630         /**
13631          * Parse RFC850's date format
13632          *
13633          * @access protected
13634          * @return int Timestamp
13635          */
13636         function date_rfc850($date)
13637         {
13638                 static $pcre;
13639                 if (!$pcre)
13640                 {
13641                         $space = '[\x09\x20]+';
13642                         $day_name = $this->day_pcre;
13643                         $month = $this->month_pcre;
13644                         $day = '([0-9]{1,2})';
13645                         $year = $hour = $minute = $second = '([0-9]{2})';
13646                         $zone = '([A-Z]{1,5})';
13647                         $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13648                 }
13649                 if (preg_match($pcre, $date, $match))
13650                 {
13651                         /*
13652                         Capturing subpatterns:
13653                         1: Day name
13654                         2: Day
13655                         3: Month
13656                         4: Year
13657                         5: Hour
13658                         6: Minute
13659                         7: Second
13660                         8: Timezone
13661                         */
13662
13663                         // Month
13664                         $month = $this->month[strtolower($match[3])];
13665
13666                         // Character timezone
13667                         if (isset($this->timezone[strtoupper($match[8])]))
13668                         {
13669                                 $timezone = $this->timezone[strtoupper($match[8])];
13670                         }
13671                         // Assume everything else to be -0000
13672                         else
13673                         {
13674                                 $timezone = 0;
13675                         }
13676
13677                         // Deal with 2 digit year
13678                         if ($match[4] < 50)
13679                         {
13680                                 $match[4] += 2000;
13681                         }
13682                         else
13683                         {
13684                                 $match[4] += 1900;
13685                         }
13686
13687                         return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13688                 }
13689                 else
13690                 {
13691                         return false;
13692                 }
13693         }
13694
13695         /**
13696          * Parse C99's asctime()'s date format
13697          *
13698          * @access protected
13699          * @return int Timestamp
13700          */
13701         function date_asctime($date)
13702         {
13703                 static $pcre;
13704                 if (!$pcre)
13705                 {
13706                         $space = '[\x09\x20]+';
13707                         $wday_name = $this->day_pcre;
13708                         $mon_name = $this->month_pcre;
13709                         $day = '([0-9]{1,2})';
13710                         $hour = $sec = $min = '([0-9]{2})';
13711                         $year = '([0-9]{4})';
13712                         $terminator = '\x0A?\x00?';
13713                         $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13714                 }
13715                 if (preg_match($pcre, $date, $match))
13716                 {
13717                         /*
13718                         Capturing subpatterns:
13719                         1: Day name
13720                         2: Month
13721                         3: Day
13722                         4: Hour
13723                         5: Minute
13724                         6: Second
13725                         7: Year
13726                         */
13727
13728                         $month = $this->month[strtolower($match[2])];
13729                         return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13730                 }
13731                 else
13732                 {
13733                         return false;
13734                 }
13735         }
13736
13737         /**
13738          * Parse dates using strtotime()
13739          *
13740          * @access protected
13741          * @return int Timestamp
13742          */
13743         function date_strtotime($date)
13744         {
13745                 $strtotime = strtotime($date);
13746                 if ($strtotime === -1 || $strtotime === false)
13747                 {
13748                         return false;
13749                 }
13750                 else
13751                 {
13752                         return $strtotime;
13753                 }
13754         }
13755 }
13756
13757 /**
13758  * Content-type sniffing
13759  *
13760  * @package SimplePie
13761  */
13762 class SimplePie_Content_Type_Sniffer
13763 {
13764         /**
13765          * File object
13766          *
13767          * @var SimplePie_File
13768          * @access private
13769          */
13770         var $file;
13771
13772         /**
13773          * Create an instance of the class with the input file
13774          *
13775          * @access public
13776          * @param SimplePie_Content_Type_Sniffer $file Input file
13777          */
13778         function SimplePie_Content_Type_Sniffer($file)
13779         {
13780                 $this->file = $file;
13781         }
13782
13783         /**
13784          * Get the Content-Type of the specified file
13785          *
13786          * @access public
13787          * @return string Actual Content-Type
13788          */
13789         function get_type()
13790         {
13791                 if (isset($this->file->headers['content-type']))
13792                 {
13793                         if (!isset($this->file->headers['content-encoding'])
13794                                 && ($this->file->headers['content-type'] === 'text/plain'
13795                                         || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13796                                         || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13797                         {
13798                                 return $this->text_or_binary();
13799                         }
13800
13801                         if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13802                         {
13803                                 $official = substr($this->file->headers['content-type'], 0, $pos);
13804                         }
13805                         else
13806                         {
13807                                 $official = $this->file->headers['content-type'];
13808                         }
13809                         $official = strtolower($official);
13810
13811                         if ($official === 'unknown/unknown'
13812                                 || $official === 'application/unknown')
13813                         {
13814                                 return $this->unknown();
13815                         }
13816                         elseif (substr($official, -4) === '+xml'
13817                                 || $official === 'text/xml'
13818                                 || $official === 'application/xml')
13819                         {
13820                                 return $official;
13821                         }
13822                         elseif (substr($official, 0, 6) === 'image/')
13823                         {
13824                                 if ($return = $this->image())
13825                                 {
13826                                         return $return;
13827                                 }
13828                                 else
13829                                 {
13830                                         return $official;
13831                                 }
13832                         }
13833                         elseif ($official === 'text/html')
13834                         {
13835                                 return $this->feed_or_html();
13836                         }
13837                         else
13838                         {
13839                                 return $official;
13840                         }
13841                 }
13842                 else
13843                 {
13844                         return $this->unknown();
13845                 }
13846         }
13847
13848         /**
13849          * Sniff text or binary
13850          *
13851          * @access private
13852          * @return string Actual Content-Type
13853          */
13854         function text_or_binary()
13855         {
13856                 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13857                         || substr($this->file->body, 0, 2) === "\xFF\xFE"
13858                         || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13859                         || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13860                 {
13861                         return 'text/plain';
13862                 }
13863                 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13864                 {
13865                         return 'application/octect-stream';
13866                 }
13867                 else
13868                 {
13869                         return 'text/plain';
13870                 }
13871         }
13872
13873         /**
13874          * Sniff unknown
13875          *
13876          * @access private
13877          * @return string Actual Content-Type
13878          */
13879         function unknown()
13880         {
13881                 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13882                 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13883                         || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13884                         || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13885                 {
13886                         return 'text/html';
13887                 }
13888                 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13889                 {
13890                         return 'application/pdf';
13891                 }
13892                 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13893                 {
13894                         return 'application/postscript';
13895                 }
13896                 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13897                         || substr($this->file->body, 0, 6) === 'GIF89a')
13898                 {
13899                         return 'image/gif';
13900                 }
13901                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13902                 {
13903                         return 'image/png';
13904                 }
13905                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13906                 {
13907                         return 'image/jpeg';
13908                 }
13909                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13910                 {
13911                         return 'image/bmp';
13912                 }
13913                 else
13914                 {
13915                         return $this->text_or_binary();
13916                 }
13917         }
13918
13919         /**
13920          * Sniff images
13921          *
13922          * @access private
13923          * @return string Actual Content-Type
13924          */
13925         function image()
13926         {
13927                 if (substr($this->file->body, 0, 6) === 'GIF87a'
13928                         || substr($this->file->body, 0, 6) === 'GIF89a')
13929                 {
13930                         return 'image/gif';
13931                 }
13932                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13933                 {
13934                         return 'image/png';
13935                 }
13936                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13937                 {
13938                         return 'image/jpeg';
13939                 }
13940                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13941                 {
13942                         return 'image/bmp';
13943                 }
13944                 else
13945                 {
13946                         return false;
13947                 }
13948         }
13949
13950         /**
13951          * Sniff HTML
13952          *
13953          * @access private
13954          * @return string Actual Content-Type
13955          */
13956         function feed_or_html()
13957         {
13958                 $len = strlen($this->file->body);
13959                 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13960
13961                 while ($pos < $len)
13962                 {
13963                         switch ($this->file->body[$pos])
13964                         {
13965                                 case "\x09":
13966                                 case "\x0A":
13967                                 case "\x0D":
13968                                 case "\x20":
13969                                         $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13970                                         continue 2;
13971
13972                                 case '<':
13973                                         $pos++;
13974                                         break;
13975
13976                                 default:
13977                                         return 'text/html';
13978                         }
13979
13980                         if (substr($this->file->body, $pos, 3) === '!--')
13981                         {
13982                                 $pos += 3;
13983                                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13984                                 {
13985                                         $pos += 3;
13986                                 }
13987                                 else
13988                                 {
13989                                         return 'text/html';
13990                                 }
13991                         }
13992                         elseif (substr($this->file->body, $pos, 1) === '!')
13993                         {
13994                                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13995                                 {
13996                                         $pos++;
13997                                 }
13998                                 else
13999                                 {
14000                                         return 'text/html';
14001                                 }
14002                         }
14003                         elseif (substr($this->file->body, $pos, 1) === '?')
14004                         {
14005                                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
14006                                 {
14007                                         $pos += 2;
14008                                 }
14009                                 else
14010                                 {
14011                                         return 'text/html';
14012                                 }
14013                         }
14014                         elseif (substr($this->file->body, $pos, 3) === 'rss'
14015                                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
14016                         {
14017                                 return 'application/rss+xml';
14018                         }
14019                         elseif (substr($this->file->body, $pos, 4) === 'feed')
14020                         {
14021                                 return 'application/atom+xml';
14022                         }
14023                         else
14024                         {
14025                                 return 'text/html';
14026                         }
14027                 }
14028
14029                 return 'text/html';
14030         }
14031 }
14032
14033 /**
14034  * Parses the XML Declaration
14035  *
14036  * @package SimplePie
14037  */
14038 class SimplePie_XML_Declaration_Parser
14039 {
14040         /**
14041          * XML Version
14042          *
14043          * @access public
14044          * @var string
14045          */
14046         var $version = '1.0';
14047
14048         /**
14049          * Encoding
14050          *
14051          * @access public
14052          * @var string
14053          */
14054         var $encoding = 'UTF-8';
14055
14056         /**
14057          * Standalone
14058          *
14059          * @access public
14060          * @var bool
14061          */
14062         var $standalone = false;
14063
14064         /**
14065          * Current state of the state machine
14066          *
14067          * @access private
14068          * @var string
14069          */
14070         var $state = 'before_version_name';
14071
14072         /**
14073          * Input data
14074          *
14075          * @access private
14076          * @var string
14077          */
14078         var $data = '';
14079
14080         /**
14081          * Input data length (to avoid calling strlen() everytime this is needed)
14082          *
14083          * @access private
14084          * @var int
14085          */
14086         var $data_length = 0;
14087
14088         /**
14089          * Current position of the pointer
14090          *
14091          * @var int
14092          * @access private
14093          */
14094         var $position = 0;
14095
14096         /**
14097          * Create an instance of the class with the input data
14098          *
14099          * @access public
14100          * @param string $data Input data
14101          */
14102         function SimplePie_XML_Declaration_Parser($data)
14103         {
14104                 $this->data = $data;
14105                 $this->data_length = strlen($this->data);
14106         }
14107
14108         /**
14109          * Parse the input data
14110          *
14111          * @access public
14112          * @return bool true on success, false on failure
14113          */
14114         function parse()
14115         {
14116                 while ($this->state && $this->state !== 'emit' && $this->has_data())
14117                 {
14118                         $state = $this->state;
14119                         $this->$state();
14120                 }
14121                 $this->data = '';
14122                 if ($this->state === 'emit')
14123                 {
14124                         return true;
14125                 }
14126                 else
14127                 {
14128                         $this->version = '';
14129                         $this->encoding = '';
14130                         $this->standalone = '';
14131                         return false;
14132                 }
14133         }
14134
14135         /**
14136          * Check whether there is data beyond the pointer
14137          *
14138          * @access private
14139          * @return bool true if there is further data, false if not
14140          */
14141         function has_data()
14142         {
14143                 return (bool) ($this->position < $this->data_length);
14144         }
14145
14146         /**
14147          * Advance past any whitespace
14148          *
14149          * @return int Number of whitespace characters passed
14150          */
14151         function skip_whitespace()
14152         {
14153                 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
14154                 $this->position += $whitespace;
14155                 return $whitespace;
14156         }
14157
14158         /**
14159          * Read value
14160          */
14161         function get_value()
14162         {
14163                 $quote = substr($this->data, $this->position, 1);
14164                 if ($quote === '"' || $quote === "'")
14165                 {
14166                         $this->position++;
14167                         $len = strcspn($this->data, $quote, $this->position);
14168                         if ($this->has_data())
14169                         {
14170                                 $value = substr($this->data, $this->position, $len);
14171                                 $this->position += $len + 1;
14172                                 return $value;
14173                         }
14174                 }
14175                 return false;
14176         }
14177
14178         function before_version_name()
14179         {
14180                 if ($this->skip_whitespace())
14181                 {
14182                         $this->state = 'version_name';
14183                 }
14184                 else
14185                 {
14186                         $this->state = false;
14187                 }
14188         }
14189
14190         function version_name()
14191         {
14192                 if (substr($this->data, $this->position, 7) === 'version')
14193                 {
14194                         $this->position += 7;
14195                         $this->skip_whitespace();
14196                         $this->state = 'version_equals';
14197                 }
14198                 else
14199                 {
14200                         $this->state = false;
14201                 }
14202         }
14203
14204         function version_equals()
14205         {
14206                 if (substr($this->data, $this->position, 1) === '=')
14207                 {
14208                         $this->position++;
14209                         $this->skip_whitespace();
14210                         $this->state = 'version_value';
14211                 }
14212                 else
14213                 {
14214                         $this->state = false;
14215                 }
14216         }
14217
14218         function version_value()
14219         {
14220                 if ($this->version = $this->get_value())
14221                 {
14222                         $this->skip_whitespace();
14223                         if ($this->has_data())
14224                         {
14225                                 $this->state = 'encoding_name';
14226                         }
14227                         else
14228                         {
14229                                 $this->state = 'emit';
14230                         }
14231                 }
14232                 else
14233                 {
14234                         $this->state = false;
14235                 }
14236         }
14237
14238         function encoding_name()
14239         {
14240                 if (substr($this->data, $this->position, 8) === 'encoding')
14241                 {
14242                         $this->position += 8;
14243                         $this->skip_whitespace();
14244                         $this->state = 'encoding_equals';
14245                 }
14246                 else
14247                 {
14248                         $this->state = 'standalone_name';
14249                 }
14250         }
14251
14252         function encoding_equals()
14253         {
14254                 if (substr($this->data, $this->position, 1) === '=')
14255                 {
14256                         $this->position++;
14257                         $this->skip_whitespace();
14258                         $this->state = 'encoding_value';
14259                 }
14260                 else
14261                 {
14262                         $this->state = false;
14263                 }
14264         }
14265
14266         function encoding_value()
14267         {
14268                 if ($this->encoding = $this->get_value())
14269                 {
14270                         $this->skip_whitespace();
14271                         if ($this->has_data())
14272                         {
14273                                 $this->state = 'standalone_name';
14274                         }
14275                         else
14276                         {
14277                                 $this->state = 'emit';
14278                         }
14279                 }
14280                 else
14281                 {
14282                         $this->state = false;
14283                 }
14284         }
14285
14286         function standalone_name()
14287         {
14288                 if (substr($this->data, $this->position, 10) === 'standalone')
14289                 {
14290                         $this->position += 10;
14291                         $this->skip_whitespace();
14292                         $this->state = 'standalone_equals';
14293                 }
14294                 else
14295                 {
14296                         $this->state = false;
14297                 }
14298         }
14299
14300         function standalone_equals()
14301         {
14302                 if (substr($this->data, $this->position, 1) === '=')
14303                 {
14304                         $this->position++;
14305                         $this->skip_whitespace();
14306                         $this->state = 'standalone_value';
14307                 }
14308                 else
14309                 {
14310                         $this->state = false;
14311                 }
14312         }
14313
14314         function standalone_value()
14315         {
14316                 if ($standalone = $this->get_value())
14317                 {
14318                         switch ($standalone)
14319                         {
14320                                 case 'yes':
14321                                         $this->standalone = true;
14322                                         break;
14323
14324                                 case 'no':
14325                                         $this->standalone = false;
14326                                         break;
14327
14328                                 default:
14329                                         $this->state = false;
14330                                         return;
14331                         }
14332
14333                         $this->skip_whitespace();
14334                         if ($this->has_data())
14335                         {
14336                                 $this->state = false;
14337                         }
14338                         else
14339                         {
14340                                 $this->state = 'emit';
14341                         }
14342                 }
14343                 else
14344                 {
14345                         $this->state = false;
14346                 }
14347         }
14348 }
14349
14350 class SimplePie_Locator
14351 {
14352         var $useragent;
14353         var $timeout;
14354         var $file;
14355         var $local = array();
14356         var $elsewhere = array();
14357         var $file_class = 'SimplePie_File';
14358         var $cached_entities = array();
14359         var $http_base;
14360         var $base;
14361         var $base_location = 0;
14362         var $checked_feeds = 0;
14363         var $max_checked_feeds = 10;
14364         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14365
14366         function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14367         {
14368                 $this->file =& $file;
14369                 $this->file_class = $file_class;
14370                 $this->useragent = $useragent;
14371                 $this->timeout = $timeout;
14372                 $this->max_checked_feeds = $max_checked_feeds;
14373                 $this->content_type_sniffer_class = $content_type_sniffer_class;
14374         }
14375
14376         function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14377         {
14378                 if ($this->is_feed($this->file))
14379                 {
14380                         return $this->file;
14381                 }
14382
14383                 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14384                 {
14385                         $sniffer =& new $this->content_type_sniffer_class($this->file);
14386                         if ($sniffer->get_type() !== 'text/html')
14387                         {
14388                                 return null;
14389                         }
14390                 }
14391
14392                 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14393                 {
14394                         $this->get_base();
14395                 }
14396
14397                 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14398                 {
14399                         return $working[0];
14400                 }
14401
14402                 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14403                 {
14404                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14405                         {
14406                                 return $working;
14407                         }
14408
14409                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14410                         {
14411                                 return $working;
14412                         }
14413
14414                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14415                         {
14416                                 return $working;
14417                         }
14418
14419                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14420                         {
14421                                 return $working;
14422                         }
14423                 }
14424                 return null;
14425         }
14426
14427         function is_feed(&$file)
14428         {
14429                 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14430                 {
14431                         $sniffer =& new $this->content_type_sniffer_class($file);
14432                         $sniffed = $sniffer->get_type();
14433                         if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14434                         {
14435                                 return true;
14436                         }
14437                         else
14438                         {
14439                                 return false;
14440                         }
14441                 }
14442                 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14443                 {
14444                         return true;
14445                 }
14446                 else
14447                 {
14448                         return false;
14449                 }
14450         }
14451
14452         function get_base()
14453         {
14454                 $this->http_base = $this->file->url;
14455                 $this->base = $this->http_base;
14456                 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14457                 foreach ($elements as $element)
14458                 {
14459                         if ($element['attribs']['href']['data'] !== '')
14460                         {
14461                                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14462                                 $this->base_location = $element['offset'];
14463                                 break;
14464                         }
14465                 }
14466         }
14467
14468         function autodiscovery()
14469         {
14470                 $links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body));
14471                 $done = array();
14472                 $feeds = array();
14473                 foreach ($links as $link)
14474                 {
14475                         if ($this->checked_feeds === $this->max_checked_feeds)
14476                         {
14477                                 break;
14478                         }
14479                         if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14480                         {
14481                                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14482
14483                                 if ($this->base_location < $link['offset'])
14484                                 {
14485                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14486                                 }
14487                                 else
14488                                 {
14489                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14490                                 }
14491
14492                                 if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
14493                                 {
14494                                         $this->checked_feeds++;
14495                                         $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14496                                         if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
14497                                         {
14498                                                 $feeds[$href] = $feed;
14499                                         }
14500                                 }
14501                                 $done[] = $href;
14502                         }
14503                 }
14504
14505                 if (!empty($feeds))
14506                 {
14507                         return array_values($feeds);
14508                 }
14509                 else {
14510                         return null;
14511                 }
14512         }
14513
14514         function get_links()
14515         {
14516                 $links = SimplePie_Misc::get_element('a', $this->file->body);
14517                 foreach ($links as $link)
14518                 {
14519                         if (isset($link['attribs']['href']['data']))
14520                         {
14521                                 $href = trim($link['attribs']['href']['data']);
14522                                 $parsed = SimplePie_Misc::parse_url($href);
14523                                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14524                                 {
14525                                         if ($this->base_location < $link['offset'])
14526                                         {
14527                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14528                                         }
14529                                         else
14530                                         {
14531                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14532                                         }
14533
14534                                         $current = SimplePie_Misc::parse_url($this->file->url);
14535
14536                                         if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14537                                         {
14538                                                 $this->local[] = $href;
14539                                         }
14540                                         else
14541                                         {
14542                                                 $this->elsewhere[] = $href;
14543                                         }
14544                                 }
14545                         }
14546                 }
14547                 $this->local = array_unique($this->local);
14548                 $this->elsewhere = array_unique($this->elsewhere);
14549                 if (!empty($this->local) || !empty($this->elsewhere))
14550                 {
14551                         return true;
14552                 }
14553                 return null;
14554         }
14555
14556         function extension(&$array)
14557         {
14558                 foreach ($array as $key => $value)
14559                 {
14560                         if ($this->checked_feeds === $this->max_checked_feeds)
14561                         {
14562                                 break;
14563                         }
14564                         if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14565                         {
14566                                 $this->checked_feeds++;
14567                                 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14568                                 if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
14569                                 {
14570                                         return $feed;
14571                                 }
14572                                 else
14573                                 {
14574                                         unset($array[$key]);
14575                                 }
14576                         }
14577                 }
14578                 return null;
14579         }
14580
14581         function body(&$array)
14582         {
14583                 foreach ($array as $key => $value)
14584                 {
14585                         if ($this->checked_feeds === $this->max_checked_feeds)
14586                         {
14587                                 break;
14588                         }
14589                         if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14590                         {
14591                                 $this->checked_feeds++;
14592                                 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14593                                 if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
14594                                 {
14595                                         return $feed;
14596                                 }
14597                                 else
14598                                 {
14599                                         unset($array[$key]);
14600                                 }
14601                         }
14602                 }
14603                 return null;
14604         }
14605 }
14606
14607 class SimplePie_Parser
14608 {
14609         var $error_code;
14610         var $error_string;
14611         var $current_line;
14612         var $current_column;
14613         var $current_byte;
14614         var $separator = ' ';
14615         var $namespace = array('');
14616         var $element = array('');
14617         var $xml_base = array('');
14618         var $xml_base_explicit = array(false);
14619         var $xml_lang = array('');
14620         var $data = array();
14621         var $datas = array(array());
14622         var $current_xhtml_construct = -1;
14623         var $encoding;
14624
14625         function parse(&$data, $encoding)
14626         {
14627                 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14628                 if (strtoupper($encoding) === 'US-ASCII')
14629                 {
14630                         $this->encoding = 'UTF-8';
14631                 }
14632                 else
14633                 {
14634                         $this->encoding = $encoding;
14635                 }
14636
14637                 // Strip BOM:
14638                 // UTF-32 Big Endian BOM
14639                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14640                 {
14641                         $data = substr($data, 4);
14642                 }
14643                 // UTF-32 Little Endian BOM
14644                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14645                 {
14646                         $data = substr($data, 4);
14647                 }
14648                 // UTF-16 Big Endian BOM
14649                 elseif (substr($data, 0, 2) === "\xFE\xFF")
14650                 {
14651                         $data = substr($data, 2);
14652                 }
14653                 // UTF-16 Little Endian BOM
14654                 elseif (substr($data, 0, 2) === "\xFF\xFE")
14655                 {
14656                         $data = substr($data, 2);
14657                 }
14658                 // UTF-8 BOM
14659                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14660                 {
14661                         $data = substr($data, 3);
14662                 }
14663
14664                 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14665                 {
14666                         $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14667                         if ($declaration->parse())
14668                         {
14669                                 $data = substr($data, $pos + 2);
14670                                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14671                         }
14672                         else
14673                         {
14674                                 $this->error_string = 'SimplePie bug! Please report this!';
14675                                 return false;
14676                         }
14677                 }
14678
14679                 $return = true;
14680
14681                 static $xml_is_sane = null;
14682                 if ($xml_is_sane === null)
14683                 {
14684                         $parser_check = xml_parser_create();
14685                         xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14686                         xml_parser_free($parser_check);
14687                         $xml_is_sane = isset($values[0]['value']);
14688                 }
14689
14690                 // Create the parser
14691                 if ($xml_is_sane)
14692                 {
14693                         $xml = xml_parser_create_ns($this->encoding, $this->separator);
14694                         xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14695                         xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14696                         xml_set_object($xml, $this);
14697                         xml_set_character_data_handler($xml, 'cdata');
14698                         xml_set_element_handler($xml, 'tag_open', 'tag_close');
14699
14700                         // Parse!
14701                         if (!xml_parse($xml, $data, true))
14702                         {
14703                                 $this->error_code = xml_get_error_code($xml);
14704                                 $this->error_string = xml_error_string($this->error_code);
14705                                 $return = false;
14706                         }
14707                         $this->current_line = xml_get_current_line_number($xml);
14708                         $this->current_column = xml_get_current_column_number($xml);
14709                         $this->current_byte = xml_get_current_byte_index($xml);
14710                         xml_parser_free($xml);
14711                         return $return;
14712                 }
14713                 else
14714                 {
14715                         libxml_clear_errors();
14716                         $xml =& new XMLReader();
14717                         $xml->xml($data);
14718                         while (@$xml->read())
14719                         {
14720                                 switch ($xml->nodeType)
14721                                 {
14722
14723                                         case constant('XMLReader::END_ELEMENT'):
14724                                                 if ($xml->namespaceURI !== '')
14725                                                 {
14726                                                         $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
14727                                                 }
14728                                                 else
14729                                                 {
14730                                                         $tagName = $xml->localName;
14731                                                 }
14732                                                 $this->tag_close(null, $tagName);
14733                                                 break;
14734                                         case constant('XMLReader::ELEMENT'):
14735                                                 $empty = $xml->isEmptyElement;
14736                                                 if ($xml->namespaceURI !== '')
14737                                                 {
14738                                                         $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
14739                                                 }
14740                                                 else
14741                                                 {
14742                                                         $tagName = $xml->localName;
14743                                                 }
14744                                                 $attributes = array();
14745                                                 while ($xml->moveToNextAttribute())
14746                                                 {
14747                                                         if ($xml->namespaceURI !== '')
14748                                                         {
14749                                                                 $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
14750                                                         }
14751                                                         else
14752                                                         {
14753                                                                 $attrName = $xml->localName;
14754                                                         }
14755                                                         $attributes[$attrName] = $xml->value;
14756                                                 }
14757                                                 $this->tag_open(null, $tagName, $attributes);
14758                                                 if ($empty)
14759                                                 {
14760                                                         $this->tag_close(null, $tagName);
14761                                                 }
14762                                                 break;
14763                                         case constant('XMLReader::TEXT'):
14764
14765                                         case constant('XMLReader::CDATA'):
14766                                                 $this->cdata(null, $xml->value);
14767                                                 break;
14768                                 }
14769                         }
14770                         if ($error = libxml_get_last_error())
14771                         {
14772                                 $this->error_code = $error->code;
14773                                 $this->error_string = $error->message;
14774                                 $this->current_line = $error->line;
14775                                 $this->current_column = $error->column;
14776                                 return false;
14777                         }
14778                         else
14779                         {
14780                                 return true;
14781                         }
14782                 }
14783         }
14784
14785         function get_error_code()
14786         {
14787                 return $this->error_code;
14788         }
14789
14790         function get_error_string()
14791         {
14792                 return $this->error_string;
14793         }
14794
14795         function get_current_line()
14796         {
14797                 return $this->current_line;
14798         }
14799
14800         function get_current_column()
14801         {
14802                 return $this->current_column;
14803         }
14804
14805         function get_current_byte()
14806         {
14807                 return $this->current_byte;
14808         }
14809
14810         function get_data()
14811         {
14812                 return $this->data;
14813         }
14814
14815         function tag_open($parser, $tag, $attributes)
14816         {
14817                 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14818
14819                 $attribs = array();
14820                 foreach ($attributes as $name => $value)
14821                 {
14822                         list($attrib_namespace, $attribute) = $this->split_ns($name);
14823                         $attribs[$attrib_namespace][$attribute] = $value;
14824                 }
14825
14826                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14827                 {
14828                         $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14829                         $this->xml_base_explicit[] = true;
14830                 }
14831                 else
14832                 {
14833                         $this->xml_base[] = end($this->xml_base);
14834                         $this->xml_base_explicit[] = end($this->xml_base_explicit);
14835                 }
14836
14837                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14838                 {
14839                         $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14840                 }
14841                 else
14842                 {
14843                         $this->xml_lang[] = end($this->xml_lang);
14844                 }
14845
14846                 if ($this->current_xhtml_construct >= 0)
14847                 {
14848                         $this->current_xhtml_construct++;
14849                         if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14850                         {
14851                                 $this->data['data'] .= '<' . end($this->element);
14852                                 if (isset($attribs['']))
14853                                 {
14854                                         foreach ($attribs[''] as $name => $value)
14855                                         {
14856                                                 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14857                                         }
14858                                 }
14859                                 $this->data['data'] .= '>';
14860                         }
14861                 }
14862                 else
14863                 {
14864                         $this->datas[] =& $this->data;
14865                         $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14866                         $this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));
14867                         if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')
14868                         || (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml'))
14869                         {
14870                                 $this->current_xhtml_construct = 0;
14871                         }
14872                 }
14873         }
14874
14875         function cdata($parser, $cdata)
14876         {
14877                 if ($this->current_xhtml_construct >= 0)
14878                 {
14879                         $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14880                 }
14881                 else
14882                 {
14883                         $this->data['data'] .= $cdata;
14884                 }
14885         }
14886
14887         function tag_close($parser, $tag)
14888         {
14889                 if ($this->current_xhtml_construct >= 0)
14890                 {
14891                         $this->current_xhtml_construct--;
14892                         if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
14893                         {
14894                                 $this->data['data'] .= '</' . end($this->element) . '>';
14895                         }
14896                 }
14897                 if ($this->current_xhtml_construct === -1)
14898                 {
14899                         $this->data =& $this->datas[count($this->datas) - 1];
14900                         array_pop($this->datas);
14901                 }
14902
14903                 array_pop($this->element);
14904                 array_pop($this->namespace);
14905                 array_pop($this->xml_base);
14906                 array_pop($this->xml_base_explicit);
14907                 array_pop($this->xml_lang);
14908         }
14909
14910         function split_ns($string)
14911         {
14912                 static $cache = array();
14913                 if (!isset($cache[$string]))
14914                 {
14915                         if ($pos = strpos($string, $this->separator))
14916                         {
14917                                 static $separator_length;
14918                                 if (!$separator_length)
14919                                 {
14920                                         $separator_length = strlen($this->separator);
14921                                 }
14922                                 $namespace = substr($string, 0, $pos);
14923                                 $local_name = substr($string, $pos + $separator_length);
14924                                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14925                                 {
14926                                         $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14927                                 }
14928
14929                                 // Normalize the Media RSS namespaces
14930                                 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14931                                 {
14932                                         $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14933                                 }
14934                                 $cache[$string] = array($namespace, $local_name);
14935                         }
14936                         else
14937                         {
14938                                 $cache[$string] = array('', $string);
14939                         }
14940                 }
14941                 return $cache[$string];
14942         }
14943 }
14944
14945 /**
14946  * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags
14947  */
14948 class SimplePie_Sanitize
14949 {
14950         // Private vars
14951         var $base;
14952
14953         // Options
14954         var $remove_div = true;
14955         var $image_handler = '';
14956         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14957         var $encode_instead_of_strip = false;
14958         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14959         var $strip_comments = false;
14960         var $output_encoding = 'UTF-8';
14961         var $enable_cache = true;
14962         var $cache_location = './cache';
14963         var $cache_name_function = 'md5';
14964         var $cache_class = 'SimplePie_Cache';
14965         var $file_class = 'SimplePie_File';
14966         var $timeout = 10;
14967         var $useragent = '';
14968         var $force_fsockopen = false;
14969
14970         var $replace_url_attributes = array(
14971                 'a' => 'href',
14972                 'area' => 'href',
14973                 'blockquote' => 'cite',
14974                 'del' => 'cite',
14975                 'form' => 'action',
14976                 'img' => array('longdesc', 'src'),
14977                 'input' => 'src',
14978                 'ins' => 'cite',
14979                 'q' => 'cite'
14980         );
14981
14982         function remove_div($enable = true)
14983         {
14984                 $this->remove_div = (bool) $enable;
14985         }
14986
14987         function set_image_handler($page = false)
14988         {
14989                 if ($page)
14990                 {
14991                         $this->image_handler = (string) $page;
14992                 }
14993                 else
14994                 {
14995                         $this->image_handler = false;
14996                 }
14997         }
14998
14999         function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
15000         {
15001                 if (isset($enable_cache))
15002                 {
15003                         $this->enable_cache = (bool) $enable_cache;
15004                 }
15005
15006                 if ($cache_location)
15007                 {
15008                         $this->cache_location = (string) $cache_location;
15009                 }
15010
15011                 if ($cache_name_function)
15012                 {
15013                         $this->cache_name_function = (string) $cache_name_function;
15014                 }
15015
15016                 if ($cache_class)
15017                 {
15018                         $this->cache_class = (string) $cache_class;
15019                 }
15020         }
15021
15022         function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
15023         {
15024                 if ($file_class)
15025                 {
15026                         $this->file_class = (string) $file_class;
15027                 }
15028
15029                 if ($timeout)
15030                 {
15031                         $this->timeout = (string) $timeout;
15032                 }
15033
15034                 if ($useragent)
15035                 {
15036                         $this->useragent = (string) $useragent;
15037                 }
15038
15039                 if ($force_fsockopen)
15040                 {
15041                         $this->force_fsockopen = (string) $force_fsockopen;
15042                 }
15043         }
15044
15045         function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
15046         {
15047                 if ($tags)
15048                 {
15049                         if (is_array($tags))
15050                         {
15051                                 $this->strip_htmltags = $tags;
15052                         }
15053                         else
15054                         {
15055                                 $this->strip_htmltags = explode(',', $tags);
15056                         }
15057                 }
15058                 else
15059                 {
15060                         $this->strip_htmltags = false;
15061                 }
15062         }
15063
15064         function encode_instead_of_strip($encode = false)
15065         {
15066                 $this->encode_instead_of_strip = (bool) $encode;
15067         }
15068
15069         function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
15070         {
15071                 if ($attribs)
15072                 {
15073                         if (is_array($attribs))
15074                         {
15075                                 $this->strip_attributes = $attribs;
15076                         }
15077                         else
15078                         {
15079                                 $this->strip_attributes = explode(',', $attribs);
15080                         }
15081                 }
15082                 else
15083                 {
15084                         $this->strip_attributes = false;
15085                 }
15086         }
15087
15088         function strip_comments($strip = false)
15089         {
15090                 $this->strip_comments = (bool) $strip;
15091         }
15092
15093         function set_output_encoding($encoding = 'UTF-8')
15094         {
15095                 $this->output_encoding = (string) $encoding;
15096         }
15097
15098         /**
15099          * Set element/attribute key/value pairs of HTML attributes
15100          * containing URLs that need to be resolved relative to the feed
15101          *
15102          * @access public
15103          * @since 1.0
15104          * @param array $element_attribute Element/attribute key/value pairs
15105          */
15106         function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
15107         {
15108                 $this->replace_url_attributes = (array) $element_attribute;
15109         }
15110
15111         function sanitize($data, $type, $base = '')
15112         {
15113                 $data = trim($data);
15114                 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
15115                 {
15116                         if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
15117                         {
15118                                 if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
15119                                 {
15120                                         $type |= SIMPLEPIE_CONSTRUCT_HTML;
15121                                 }
15122                                 else
15123                                 {
15124                                         $type |= SIMPLEPIE_CONSTRUCT_TEXT;
15125                                 }
15126                         }
15127
15128                         if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
15129                         {
15130                                 $data = base64_decode($data);
15131                         }
15132
15133                         if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
15134                         {
15135                                 if ($this->remove_div)
15136                                 {
15137                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
15138                                         $data = preg_replace('/<\/div>$/', '', $data);
15139                                 }
15140                                 else
15141                                 {
15142                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
15143                                 }
15144                         }
15145
15146                         if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
15147                         {
15148                                 // Strip comments
15149                                 if ($this->strip_comments)
15150                                 {
15151                                         $data = SimplePie_Misc::strip_comments($data);
15152                                 }
15153
15154                                 // Strip out HTML tags and attributes that might cause various security problems.
15155                                 // Based on recommendations by Mark Pilgrim at:
15156                                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
15157                                 if ($this->strip_htmltags)
15158                                 {
15159                                         foreach ($this->strip_htmltags as $tag)
15160                                         {
15161                                                 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
15162                                                 while (preg_match($pcre, $data))
15163                                                 {
15164                                                         $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
15165                                                 }
15166                                         }
15167                                 }
15168
15169                                 if ($this->strip_attributes)
15170                                 {
15171                                         foreach ($this->strip_attributes as $attrib)
15172                                         {
15173                                                 $data = preg_replace('/(<[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*)' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . trim($attrib) . '(?:\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>/', '\1\2\3>', $data);
15174                                         }
15175                                 }
15176
15177                                 // Replace relative URLs
15178                                 $this->base = $base;
15179                                 foreach ($this->replace_url_attributes as $element => $attributes)
15180                                 {
15181                                         $data = $this->replace_urls($data, $element, $attributes);
15182                                 }
15183
15184                                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
15185                                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
15186                                 {
15187                                         $images = SimplePie_Misc::get_element('img', $data);
15188                                         foreach ($images as $img)
15189                                         {
15190                                                 if (isset($img['attribs']['src']['data']))
15191                                                 {
15192                                                         $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
15193                                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
15194
15195                                                         if ($cache->load())
15196                                                         {
15197                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15198                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15199                                                         }
15200                                                         else
15201                                                         {
15202                                                                 $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
15203                                                                 $headers = $file->headers;
15204
15205                                                                 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
15206                                                                 {
15207                                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
15208                                                                         {
15209                                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15210                                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15211                                                                         }
15212                                                                         else
15213                                                                         {
15214                                                                                 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
15215                                                                         }
15216                                                                 }
15217                                                         }
15218                                                 }
15219                                         }
15220                                 }
15221
15222                                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
15223                                 $data = trim($data);
15224                         }
15225
15226                         if ($type & SIMPLEPIE_CONSTRUCT_IRI)
15227                         {
15228                                 $data = SimplePie_Misc::absolutize_url($data, $base);
15229                         }
15230
15231                         if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
15232                         {
15233                                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
15234                         }
15235
15236                         if ($this->output_encoding !== 'UTF-8')
15237                         {
15238                                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
15239                         }
15240                 }
15241                 return $data;
15242         }
15243
15244         function replace_urls($data, $tag, $attributes)
15245         {
15246                 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15247                 {
15248                         $elements = SimplePie_Misc::get_element($tag, $data);
15249                         foreach ($elements as $element)
15250                         {
15251                                 if (is_array($attributes))
15252                                 {
15253                                         foreach ($attributes as $attribute)
15254                                         {
15255                                                 if (isset($element['attribs'][$attribute]['data']))
15256                                                 {
15257                                                         $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15258                                                         $new_element = SimplePie_Misc::element_implode($element);
15259                                                         $data = str_replace($element['full'], $new_element, $data);
15260                                                         $element['full'] = $new_element;
15261                                                 }
15262                                         }
15263                                 }
15264                                 elseif (isset($element['attribs'][$attributes]['data']))
15265                                 {
15266                                         $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15267                                         $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15268                                 }
15269                         }
15270                 }
15271                 return $data;
15272         }
15273
15274         function do_strip_htmltags($match)
15275         {
15276                 if ($this->encode_instead_of_strip)
15277                 {
15278                         if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15279                         {
15280                                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15281                                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15282                                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
15283                         }
15284                         else
15285                         {
15286                                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15287                         }
15288                 }
15289                 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15290                 {
15291                         return $match[4];
15292                 }
15293                 else
15294                 {
15295                         return '';
15296                 }
15297         }
15298 }
15299 endif;
15300 ?>