]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/class-simplepie.php
Wordpress 2.9.1
[autoinstalls/wordpress.git] / wp-includes / class-simplepie.php
1 <?php
2 /**
3  * SimplePie
4  *
5  * A PHP-Based RSS and Atom Feed Framework.
6  * Takes the hard work out of managing a complete RSS/Atom solution.
7  *
8  * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification, are
12  * permitted provided that the following conditions are met:
13  *
14  *      * Redistributions of source code must retain the above copyright notice, this list of
15  *        conditions and the following disclaimer.
16  *
17  *      * Redistributions in binary form must reproduce the above copyright notice, this list
18  *        of conditions and the following disclaimer in the documentation and/or other materials
19  *        provided with the distribution.
20  *
21  *      * Neither the name of the SimplePie Team nor the names of its contributors may be used
22  *        to endorse or promote products derived from this software without specific prior
23  *        written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28  * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * @package SimplePie
36  * @version 1.2
37  * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
38  * @author Ryan Parman
39  * @author Geoffrey Sneddon
40  * @link http://simplepie.org/ SimplePie
41  * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
42  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43  * @todo phpDoc comments
44  */
45
46 /**
47  * SimplePie Name
48  */
49 define('SIMPLEPIE_NAME', 'SimplePie');
50
51 /**
52  * SimplePie Version
53  */
54 define('SIMPLEPIE_VERSION', '1.2');
55
56 /**
57  * SimplePie Build
58  */
59 define('SIMPLEPIE_BUILD', '20090627192103');
60
61 /**
62  * SimplePie Website URL
63  */
64 define('SIMPLEPIE_URL', 'http://simplepie.org');
65
66 /**
67  * SimplePie Useragent
68  * @see SimplePie::set_useragent()
69  */
70 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
71
72 /**
73  * SimplePie Linkback
74  */
75 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
76
77 /**
78  * No Autodiscovery
79  * @see SimplePie::set_autodiscovery_level()
80  */
81 define('SIMPLEPIE_LOCATOR_NONE', 0);
82
83 /**
84  * Feed Link Element Autodiscovery
85  * @see SimplePie::set_autodiscovery_level()
86  */
87 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
88
89 /**
90  * Local Feed Extension Autodiscovery
91  * @see SimplePie::set_autodiscovery_level()
92  */
93 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
94
95 /**
96  * Local Feed Body Autodiscovery
97  * @see SimplePie::set_autodiscovery_level()
98  */
99 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
100
101 /**
102  * Remote Feed Extension Autodiscovery
103  * @see SimplePie::set_autodiscovery_level()
104  */
105 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
106
107 /**
108  * Remote Feed Body Autodiscovery
109  * @see SimplePie::set_autodiscovery_level()
110  */
111 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
112
113 /**
114  * All Feed Autodiscovery
115  * @see SimplePie::set_autodiscovery_level()
116  */
117 define('SIMPLEPIE_LOCATOR_ALL', 31);
118
119 /**
120  * No known feed type
121  */
122 define('SIMPLEPIE_TYPE_NONE', 0);
123
124 /**
125  * RSS 0.90
126  */
127 define('SIMPLEPIE_TYPE_RSS_090', 1);
128
129 /**
130  * RSS 0.91 (Netscape)
131  */
132 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
133
134 /**
135  * RSS 0.91 (Userland)
136  */
137 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
138
139 /**
140  * RSS 0.91 (both Netscape and Userland)
141  */
142 define('SIMPLEPIE_TYPE_RSS_091', 6);
143
144 /**
145  * RSS 0.92
146  */
147 define('SIMPLEPIE_TYPE_RSS_092', 8);
148
149 /**
150  * RSS 0.93
151  */
152 define('SIMPLEPIE_TYPE_RSS_093', 16);
153
154 /**
155  * RSS 0.94
156  */
157 define('SIMPLEPIE_TYPE_RSS_094', 32);
158
159 /**
160  * RSS 1.0
161  */
162 define('SIMPLEPIE_TYPE_RSS_10', 64);
163
164 /**
165  * RSS 2.0
166  */
167 define('SIMPLEPIE_TYPE_RSS_20', 128);
168
169 /**
170  * RDF-based RSS
171  */
172 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
173
174 /**
175  * Non-RDF-based RSS (truly intended as syndication format)
176  */
177 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
178
179 /**
180  * All RSS
181  */
182 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
183
184 /**
185  * Atom 0.3
186  */
187 define('SIMPLEPIE_TYPE_ATOM_03', 256);
188
189 /**
190  * Atom 1.0
191  */
192 define('SIMPLEPIE_TYPE_ATOM_10', 512);
193
194 /**
195  * All Atom
196  */
197 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
198
199 /**
200  * All feed types
201  */
202 define('SIMPLEPIE_TYPE_ALL', 1023);
203
204 /**
205  * No construct
206  */
207 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
208
209 /**
210  * Text construct
211  */
212 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
213
214 /**
215  * HTML construct
216  */
217 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
218
219 /**
220  * XHTML construct
221  */
222 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
223
224 /**
225  * base64-encoded construct
226  */
227 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
228
229 /**
230  * IRI construct
231  */
232 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
233
234 /**
235  * A construct that might be HTML
236  */
237 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
238
239 /**
240  * All constructs
241  */
242 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
243
244 /**
245  * Don't change case
246  */
247 define('SIMPLEPIE_SAME_CASE', 1);
248
249 /**
250  * Change to lowercase
251  */
252 define('SIMPLEPIE_LOWERCASE', 2);
253
254 /**
255  * Change to uppercase
256  */
257 define('SIMPLEPIE_UPPERCASE', 4);
258
259 /**
260  * PCRE for HTML attributes
261  */
262 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]*');
263
264 /**
265  * PCRE for XML attributes
266  */
267 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
268
269 /**
270  * XML Namespace
271  */
272 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
273
274 /**
275  * Atom 1.0 Namespace
276  */
277 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
278
279 /**
280  * Atom 0.3 Namespace
281  */
282 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
283
284 /**
285  * RDF Namespace
286  */
287 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
288
289 /**
290  * RSS 0.90 Namespace
291  */
292 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
293
294 /**
295  * RSS 1.0 Namespace
296  */
297 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
298
299 /**
300  * RSS 1.0 Content Module Namespace
301  */
302 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
303
304 /**
305  * RSS 2.0 Namespace
306  * (Stupid, I know, but I'm certain it will confuse people less with support.)
307  */
308 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
309
310 /**
311  * DC 1.0 Namespace
312  */
313 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
314
315 /**
316  * DC 1.1 Namespace
317  */
318 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
319
320 /**
321  * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
322  */
323 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
324
325 /**
326  * GeoRSS Namespace
327  */
328 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
329
330 /**
331  * Media RSS Namespace
332  */
333 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
334
335 /**
336  * Wrong Media RSS Namespace
337  */
338 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
339
340 /**
341  * iTunes RSS Namespace
342  */
343 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
344
345 /**
346  * XHTML Namespace
347  */
348 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
349
350 /**
351  * IANA Link Relations Registry
352  */
353 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
354
355 /**
356  * Whether we're running on PHP5
357  */
358 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
359
360 /**
361  * No file source
362  */
363 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
364
365 /**
366  * Remote file source
367  */
368 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
369
370 /**
371  * Local file source
372  */
373 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
374
375 /**
376  * fsockopen() file source
377  */
378 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
379
380 /**
381  * cURL file source
382  */
383 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
384
385 /**
386  * file_get_contents() file source
387  */
388 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
389
390 /**
391  * SimplePie
392  *
393  * @package SimplePie
394  */
395 class SimplePie
396 {
397         /**
398          * @var array Raw data
399          * @access private
400          */
401         var $data = array();
402
403         /**
404          * @var mixed Error string
405          * @access private
406          */
407         var $error;
408
409         /**
410          * @var object Instance of SimplePie_Sanitize (or other class)
411          * @see SimplePie::set_sanitize_class()
412          * @access private
413          */
414         var $sanitize;
415
416         /**
417          * @var string SimplePie Useragent
418          * @see SimplePie::set_useragent()
419          * @access private
420          */
421         var $useragent = SIMPLEPIE_USERAGENT;
422
423         /**
424          * @var string Feed URL
425          * @see SimplePie::set_feed_url()
426          * @access private
427          */
428         var $feed_url;
429
430         /**
431          * @var object Instance of SimplePie_File to use as a feed
432          * @see SimplePie::set_file()
433          * @access private
434          */
435         var $file;
436
437         /**
438          * @var string Raw feed data
439          * @see SimplePie::set_raw_data()
440          * @access private
441          */
442         var $raw_data;
443
444         /**
445          * @var int Timeout for fetching remote files
446          * @see SimplePie::set_timeout()
447          * @access private
448          */
449         var $timeout = 10;
450
451         /**
452          * @var bool Forces fsockopen() to be used for remote files instead
453          * of cURL, even if a new enough version is installed
454          * @see SimplePie::force_fsockopen()
455          * @access private
456          */
457         var $force_fsockopen = false;
458
459         /**
460          * @var bool Force the given data/URL to be treated as a feed no matter what
461          * it appears like
462          * @see SimplePie::force_feed()
463          * @access private
464          */
465         var $force_feed = false;
466
467         /**
468          * @var bool Enable/Disable XML dump
469          * @see SimplePie::enable_xml_dump()
470          * @access private
471          */
472         var $xml_dump = false;
473
474         /**
475          * @var bool Enable/Disable Caching
476          * @see SimplePie::enable_cache()
477          * @access private
478          */
479         var $cache = true;
480
481         /**
482          * @var int Cache duration (in seconds)
483          * @see SimplePie::set_cache_duration()
484          * @access private
485          */
486         var $cache_duration = 3600;
487
488         /**
489          * @var int Auto-discovery cache duration (in seconds)
490          * @see SimplePie::set_autodiscovery_cache_duration()
491          * @access private
492          */
493         var $autodiscovery_cache_duration = 604800; // 7 Days.
494
495         /**
496          * @var string Cache location (relative to executing script)
497          * @see SimplePie::set_cache_location()
498          * @access private
499          */
500         var $cache_location = './cache';
501
502         /**
503          * @var string Function that creates the cache filename
504          * @see SimplePie::set_cache_name_function()
505          * @access private
506          */
507         var $cache_name_function = 'md5';
508
509         /**
510          * @var bool Reorder feed by date descending
511          * @see SimplePie::enable_order_by_date()
512          * @access private
513          */
514         var $order_by_date = true;
515
516         /**
517          * @var mixed Force input encoding to be set to the follow value
518          * (false, or anything type-cast to false, disables this feature)
519          * @see SimplePie::set_input_encoding()
520          * @access private
521          */
522         var $input_encoding = false;
523
524         /**
525          * @var int Feed Autodiscovery Level
526          * @see SimplePie::set_autodiscovery_level()
527          * @access private
528          */
529         var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
530
531         /**
532          * @var string Class used for caching feeds
533          * @see SimplePie::set_cache_class()
534          * @access private
535          */
536         var $cache_class = 'SimplePie_Cache';
537
538         /**
539          * @var string Class used for locating feeds
540          * @see SimplePie::set_locator_class()
541          * @access private
542          */
543         var $locator_class = 'SimplePie_Locator';
544
545         /**
546          * @var string Class used for parsing feeds
547          * @see SimplePie::set_parser_class()
548          * @access private
549          */
550         var $parser_class = 'SimplePie_Parser';
551
552         /**
553          * @var string Class used for fetching feeds
554          * @see SimplePie::set_file_class()
555          * @access private
556          */
557         var $file_class = 'SimplePie_File';
558
559         /**
560          * @var string Class used for items
561          * @see SimplePie::set_item_class()
562          * @access private
563          */
564         var $item_class = 'SimplePie_Item';
565
566         /**
567          * @var string Class used for authors
568          * @see SimplePie::set_author_class()
569          * @access private
570          */
571         var $author_class = 'SimplePie_Author';
572
573         /**
574          * @var string Class used for categories
575          * @see SimplePie::set_category_class()
576          * @access private
577          */
578         var $category_class = 'SimplePie_Category';
579
580         /**
581          * @var string Class used for enclosures
582          * @see SimplePie::set_enclosures_class()
583          * @access private
584          */
585         var $enclosure_class = 'SimplePie_Enclosure';
586
587         /**
588          * @var string Class used for Media RSS <media:text> captions
589          * @see SimplePie::set_caption_class()
590          * @access private
591          */
592         var $caption_class = 'SimplePie_Caption';
593
594         /**
595          * @var string Class used for Media RSS <media:copyright>
596          * @see SimplePie::set_copyright_class()
597          * @access private
598          */
599         var $copyright_class = 'SimplePie_Copyright';
600
601         /**
602          * @var string Class used for Media RSS <media:credit>
603          * @see SimplePie::set_credit_class()
604          * @access private
605          */
606         var $credit_class = 'SimplePie_Credit';
607
608         /**
609          * @var string Class used for Media RSS <media:rating>
610          * @see SimplePie::set_rating_class()
611          * @access private
612          */
613         var $rating_class = 'SimplePie_Rating';
614
615         /**
616          * @var string Class used for Media RSS <media:restriction>
617          * @see SimplePie::set_restriction_class()
618          * @access private
619          */
620         var $restriction_class = 'SimplePie_Restriction';
621
622         /**
623          * @var string Class used for content-type sniffing
624          * @see SimplePie::set_content_type_sniffer_class()
625          * @access private
626          */
627         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
628
629         /**
630          * @var string Class used for item sources.
631          * @see SimplePie::set_source_class()
632          * @access private
633          */
634         var $source_class = 'SimplePie_Source';
635
636         /**
637          * @var mixed Set javascript query string parameter (false, or
638          * anything type-cast to false, disables this feature)
639          * @see SimplePie::set_javascript()
640          * @access private
641          */
642         var $javascript = 'js';
643
644         /**
645          * @var int Maximum number of feeds to check with autodiscovery
646          * @see SimplePie::set_max_checked_feeds()
647          * @access private
648          */
649         var $max_checked_feeds = 10;
650
651         /**
652          * @var array All the feeds found during the autodiscovery process
653          * @see SimplePie::get_all_discovered_feeds()
654          * @access private
655          */
656         var $all_discovered_feeds = array();
657
658         /**
659          * @var string Web-accessible path to the handler_favicon.php file.
660          * @see SimplePie::set_favicon_handler()
661          * @access private
662          */
663         var $favicon_handler = '';
664
665         /**
666          * @var string Web-accessible path to the handler_image.php file.
667          * @see SimplePie::set_image_handler()
668          * @access private
669          */
670         var $image_handler = '';
671
672         /**
673          * @var array Stores the URLs when multiple feeds are being initialized.
674          * @see SimplePie::set_feed_url()
675          * @access private
676          */
677         var $multifeed_url = array();
678
679         /**
680          * @var array Stores SimplePie objects when multiple feeds initialized.
681          * @access private
682          */
683         var $multifeed_objects = array();
684
685         /**
686          * @var array Stores the get_object_vars() array for use with multifeeds.
687          * @see SimplePie::set_feed_url()
688          * @access private
689          */
690         var $config_settings = null;
691
692         /**
693          * @var integer Stores the number of items to return per-feed with multifeeds.
694          * @see SimplePie::set_item_limit()
695          * @access private
696          */
697         var $item_limit = 0;
698
699         /**
700          * @var array Stores the default attributes to be stripped by strip_attributes().
701          * @see SimplePie::strip_attributes()
702          * @access private
703          */
704         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
705
706         /**
707          * @var array Stores the default tags to be stripped by strip_htmltags().
708          * @see SimplePie::strip_htmltags()
709          * @access private
710          */
711         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
712
713         /**
714          * The SimplePie class contains feed level data and options
715          *
716          * There are two ways that you can create a new SimplePie object. The first
717          * is by passing a feed URL as a parameter to the SimplePie constructor
718          * (as well as optionally setting the cache location and cache expiry). This
719          * will initialise the whole feed with all of the default settings, and you
720          * can begin accessing methods and properties immediately.
721          *
722          * The second way is to create the SimplePie object with no parameters
723          * at all. This will enable you to set configuration options. After setting
724          * them, you must initialise the feed using $feed->init(). At that point the
725          * object's methods and properties will be available to you. This format is
726          * what is used throughout this documentation.
727          *
728          * @access public
729          * @since 1.0 Preview Release
730          * @param string $feed_url This is the URL you want to parse.
731          * @param string $cache_location This is where you want the cache to be stored.
732          * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
733          */
734         function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
735         {
736                 // Other objects, instances created here so we can set options on them
737                 $this->sanitize =& new SimplePie_Sanitize;
738
739                 // Set options if they're passed to the constructor
740                 if ($cache_location !== null)
741                 {
742                         $this->set_cache_location($cache_location);
743                 }
744
745                 if ($cache_duration !== null)
746                 {
747                         $this->set_cache_duration($cache_duration);
748                 }
749
750                 // Only init the script if we're passed a feed URL
751                 if ($feed_url !== null)
752                 {
753                         $this->set_feed_url($feed_url);
754                         $this->init();
755                 }
756         }
757
758         /**
759          * Used for converting object to a string
760          */
761         function __toString()
762         {
763                 return md5(serialize($this->data));
764         }
765
766         /**
767          * Remove items that link back to this before destroying this object
768          */
769         function __destruct()
770         {
771                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
772                 {
773                         if (!empty($this->data['items']))
774                         {
775                                 foreach ($this->data['items'] as $item)
776                                 {
777                                         $item->__destruct();
778                                 }
779                                 unset($item, $this->data['items']);
780                         }
781                         if (!empty($this->data['ordered_items']))
782                         {
783                                 foreach ($this->data['ordered_items'] as $item)
784                                 {
785                                         $item->__destruct();
786                                 }
787                                 unset($item, $this->data['ordered_items']);
788                         }
789                 }
790         }
791
792         /**
793          * Force the given data/URL to be treated as a feed no matter what it
794          * appears like
795          *
796          * @access public
797          * @since 1.1
798          * @param bool $enable Force the given data/URL to be treated as a feed
799          */
800         function force_feed($enable = false)
801         {
802                 $this->force_feed = (bool) $enable;
803         }
804
805         /**
806          * This is the URL of the feed you want to parse.
807          *
808          * This allows you to enter the URL of the feed you want to parse, or the
809          * website you want to try to use auto-discovery on. This takes priority
810          * over any set raw data.
811          *
812          * You can set multiple feeds to mash together by passing an array instead
813          * of a string for the $url. Remember that with each additional feed comes
814          * additional processing and resources.
815          *
816          * @access public
817          * @since 1.0 Preview Release
818          * @param mixed $url This is the URL (or array of URLs) that you want to parse.
819          * @see SimplePie::set_raw_data()
820          */
821         function set_feed_url($url)
822         {
823                 if (is_array($url))
824                 {
825                         $this->multifeed_url = array();
826                         foreach ($url as $value)
827                         {
828                                 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
829                         }
830                 }
831                 else
832                 {
833                         $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
834                 }
835         }
836
837         /**
838          * Provides an instance of SimplePie_File to use as a feed
839          *
840          * @access public
841          * @param object &$file Instance of SimplePie_File (or subclass)
842          * @return bool True on success, false on failure
843          */
844         function set_file(&$file)
845         {
846                 if (is_a($file, 'SimplePie_File'))
847                 {
848                         $this->feed_url = $file->url;
849                         $this->file =& $file;
850                         return true;
851                 }
852                 return false;
853         }
854
855         /**
856          * Allows you to use a string of RSS/Atom data instead of a remote feed.
857          *
858          * If you have a feed available as a string in PHP, you can tell SimplePie
859          * to parse that data string instead of a remote feed. Any set feed URL
860          * takes precedence.
861          *
862          * @access public
863          * @since 1.0 Beta 3
864          * @param string $data RSS or Atom data as a string.
865          * @see SimplePie::set_feed_url()
866          */
867         function set_raw_data($data)
868         {
869                 $this->raw_data = $data;
870         }
871
872         /**
873          * Allows you to override the default timeout for fetching remote feeds.
874          *
875          * This allows you to change the maximum time the feed's server to respond
876          * and send the feed back.
877          *
878          * @access public
879          * @since 1.0 Beta 3
880          * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
881          */
882         function set_timeout($timeout = 10)
883         {
884                 $this->timeout = (int) $timeout;
885         }
886
887         /**
888          * Forces SimplePie to use fsockopen() instead of the preferred cURL
889          * functions.
890          *
891          * @access public
892          * @since 1.0 Beta 3
893          * @param bool $enable Force fsockopen() to be used
894          */
895         function force_fsockopen($enable = false)
896         {
897                 $this->force_fsockopen = (bool) $enable;
898         }
899
900         /**
901          * Outputs the raw XML content of the feed, after it has gone through
902          * SimplePie's filters.
903          *
904          * Used only for debugging, this function will output the XML content as
905          * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
906          * before trying to parse it. Many parts of the feed are re-written in
907          * memory, and in the end, you have a parsable feed. XML dump shows you the
908          * actual XML that SimplePie tries to parse, which may or may not be very
909          * different from the original feed.
910          *
911          * @access public
912          * @since 1.0 Preview Release
913          * @param bool $enable Enable XML dump
914          */
915         function enable_xml_dump($enable = false)
916         {
917                 $this->xml_dump = (bool) $enable;
918         }
919
920         /**
921          * Enables/disables caching in SimplePie.
922          *
923          * This option allows you to disable caching all-together in SimplePie.
924          * However, disabling the cache can lead to longer load times.
925          *
926          * @access public
927          * @since 1.0 Preview Release
928          * @param bool $enable Enable caching
929          */
930         function enable_cache($enable = true)
931         {
932                 $this->cache = (bool) $enable;
933         }
934
935         /**
936          * Set the length of time (in seconds) that the contents of a feed
937          * will be cached.
938          *
939          * @access public
940          * @param int $seconds The feed content cache duration.
941          */
942         function set_cache_duration($seconds = 3600)
943         {
944                 $this->cache_duration = (int) $seconds;
945         }
946
947         /**
948          * Set the length of time (in seconds) that the autodiscovered feed
949          * URL will be cached.
950          *
951          * @access public
952          * @param int $seconds The autodiscovered feed URL cache duration.
953          */
954         function set_autodiscovery_cache_duration($seconds = 604800)
955         {
956                 $this->autodiscovery_cache_duration = (int) $seconds;
957         }
958
959         /**
960          * Set the file system location where the cached files should be stored.
961          *
962          * @access public
963          * @param string $location The file system location.
964          */
965         function set_cache_location($location = './cache')
966         {
967                 $this->cache_location = (string) $location;
968         }
969
970         /**
971          * Determines whether feed items should be sorted into reverse chronological order.
972          *
973          * @access public
974          * @param bool $enable Sort as reverse chronological order.
975          */
976         function enable_order_by_date($enable = true)
977         {
978                 $this->order_by_date = (bool) $enable;
979         }
980
981         /**
982          * Allows you to override the character encoding reported by the feed.
983          *
984          * @access public
985          * @param string $encoding Character encoding.
986          */
987         function set_input_encoding($encoding = false)
988         {
989                 if ($encoding)
990                 {
991                         $this->input_encoding = (string) $encoding;
992                 }
993                 else
994                 {
995                         $this->input_encoding = false;
996                 }
997         }
998
999         /**
1000          * Set how much feed autodiscovery to do
1001          *
1002          * @access public
1003          * @see SIMPLEPIE_LOCATOR_NONE
1004          * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1005          * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1006          * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1007          * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1008          * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1009          * @see SIMPLEPIE_LOCATOR_ALL
1010          * @param int $level Feed Autodiscovery Level (level can be a
1011          * combination of the above constants, see bitwise OR operator)
1012          */
1013         function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1014         {
1015                 $this->autodiscovery = (int) $level;
1016         }
1017
1018         /**
1019          * Allows you to change which class SimplePie uses for caching.
1020          * Useful when you are overloading or extending SimplePie's default classes.
1021          *
1022          * @access public
1023          * @param string $class Name of custom class.
1024          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1025          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1026          */
1027         function set_cache_class($class = 'SimplePie_Cache')
1028         {
1029                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1030                 {
1031                         $this->cache_class = $class;
1032                         return true;
1033                 }
1034                 return false;
1035         }
1036
1037         /**
1038          * Allows you to change which class SimplePie uses for auto-discovery.
1039          * Useful when you are overloading or extending SimplePie's default classes.
1040          *
1041          * @access public
1042          * @param string $class Name of custom class.
1043          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1044          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1045          */
1046         function set_locator_class($class = 'SimplePie_Locator')
1047         {
1048                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1049                 {
1050                         $this->locator_class = $class;
1051                         return true;
1052                 }
1053                 return false;
1054         }
1055
1056         /**
1057          * Allows you to change which class SimplePie uses for XML parsing.
1058          * Useful when you are overloading or extending SimplePie's default classes.
1059          *
1060          * @access public
1061          * @param string $class Name of custom class.
1062          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1063          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1064          */
1065         function set_parser_class($class = 'SimplePie_Parser')
1066         {
1067                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1068                 {
1069                         $this->parser_class = $class;
1070                         return true;
1071                 }
1072                 return false;
1073         }
1074
1075         /**
1076          * Allows you to change which class SimplePie uses for remote file fetching.
1077          * Useful when you are overloading or extending SimplePie's default classes.
1078          *
1079          * @access public
1080          * @param string $class Name of custom class.
1081          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1082          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1083          */
1084         function set_file_class($class = 'SimplePie_File')
1085         {
1086                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1087                 {
1088                         $this->file_class = $class;
1089                         return true;
1090                 }
1091                 return false;
1092         }
1093
1094         /**
1095          * Allows you to change which class SimplePie uses for data sanitization.
1096          * Useful when you are overloading or extending SimplePie's default classes.
1097          *
1098          * @access public
1099          * @param string $class Name of custom class.
1100          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1101          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1102          */
1103         function set_sanitize_class($class = 'SimplePie_Sanitize')
1104         {
1105                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1106                 {
1107                         $this->sanitize =& new $class;
1108                         return true;
1109                 }
1110                 return false;
1111         }
1112
1113         /**
1114          * Allows you to change which class SimplePie uses for handling feed items.
1115          * Useful when you are overloading or extending SimplePie's default classes.
1116          *
1117          * @access public
1118          * @param string $class Name of custom class.
1119          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1120          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1121          */
1122         function set_item_class($class = 'SimplePie_Item')
1123         {
1124                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1125                 {
1126                         $this->item_class = $class;
1127                         return true;
1128                 }
1129                 return false;
1130         }
1131
1132         /**
1133          * Allows you to change which class SimplePie uses for handling author data.
1134          * Useful when you are overloading or extending SimplePie's default classes.
1135          *
1136          * @access public
1137          * @param string $class Name of custom class.
1138          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1139          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1140          */
1141         function set_author_class($class = 'SimplePie_Author')
1142         {
1143                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1144                 {
1145                         $this->author_class = $class;
1146                         return true;
1147                 }
1148                 return false;
1149         }
1150
1151         /**
1152          * Allows you to change which class SimplePie uses for handling category data.
1153          * Useful when you are overloading or extending SimplePie's default classes.
1154          *
1155          * @access public
1156          * @param string $class Name of custom class.
1157          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1158          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1159          */
1160         function set_category_class($class = 'SimplePie_Category')
1161         {
1162                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1163                 {
1164                         $this->category_class = $class;
1165                         return true;
1166                 }
1167                 return false;
1168         }
1169
1170         /**
1171          * Allows you to change which class SimplePie uses for feed enclosures.
1172          * Useful when you are overloading or extending SimplePie's default classes.
1173          *
1174          * @access public
1175          * @param string $class Name of custom class.
1176          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1177          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1178          */
1179         function set_enclosure_class($class = 'SimplePie_Enclosure')
1180         {
1181                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1182                 {
1183                         $this->enclosure_class = $class;
1184                         return true;
1185                 }
1186                 return false;
1187         }
1188
1189         /**
1190          * Allows you to change which class SimplePie uses for <media:text> captions
1191          * Useful when you are overloading or extending SimplePie's default classes.
1192          *
1193          * @access public
1194          * @param string $class Name of custom class.
1195          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1196          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1197          */
1198         function set_caption_class($class = 'SimplePie_Caption')
1199         {
1200                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1201                 {
1202                         $this->caption_class = $class;
1203                         return true;
1204                 }
1205                 return false;
1206         }
1207
1208         /**
1209          * Allows you to change which class SimplePie uses for <media:copyright>
1210          * Useful when you are overloading or extending SimplePie's default classes.
1211          *
1212          * @access public
1213          * @param string $class Name of custom class.
1214          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1215          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1216          */
1217         function set_copyright_class($class = 'SimplePie_Copyright')
1218         {
1219                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1220                 {
1221                         $this->copyright_class = $class;
1222                         return true;
1223                 }
1224                 return false;
1225         }
1226
1227         /**
1228          * Allows you to change which class SimplePie uses for <media:credit>
1229          * Useful when you are overloading or extending SimplePie's default classes.
1230          *
1231          * @access public
1232          * @param string $class Name of custom class.
1233          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1234          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1235          */
1236         function set_credit_class($class = 'SimplePie_Credit')
1237         {
1238                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1239                 {
1240                         $this->credit_class = $class;
1241                         return true;
1242                 }
1243                 return false;
1244         }
1245
1246         /**
1247          * Allows you to change which class SimplePie uses for <media:rating>
1248          * Useful when you are overloading or extending SimplePie's default classes.
1249          *
1250          * @access public
1251          * @param string $class Name of custom class.
1252          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1253          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1254          */
1255         function set_rating_class($class = 'SimplePie_Rating')
1256         {
1257                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1258                 {
1259                         $this->rating_class = $class;
1260                         return true;
1261                 }
1262                 return false;
1263         }
1264
1265         /**
1266          * Allows you to change which class SimplePie uses for <media:restriction>
1267          * Useful when you are overloading or extending SimplePie's default classes.
1268          *
1269          * @access public
1270          * @param string $class Name of custom class.
1271          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1272          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1273          */
1274         function set_restriction_class($class = 'SimplePie_Restriction')
1275         {
1276                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1277                 {
1278                         $this->restriction_class = $class;
1279                         return true;
1280                 }
1281                 return false;
1282         }
1283
1284         /**
1285          * Allows you to change which class SimplePie uses for content-type sniffing.
1286          * Useful when you are overloading or extending SimplePie's default classes.
1287          *
1288          * @access public
1289          * @param string $class Name of custom class.
1290          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1291          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1292          */
1293         function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1294         {
1295                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1296                 {
1297                         $this->content_type_sniffer_class = $class;
1298                         return true;
1299                 }
1300                 return false;
1301         }
1302
1303         /**
1304          * Allows you to change which class SimplePie uses item sources.
1305          * Useful when you are overloading or extending SimplePie's default classes.
1306          *
1307          * @access public
1308          * @param string $class Name of custom class.
1309          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1310          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1311          */
1312         function set_source_class($class = 'SimplePie_Source')
1313         {
1314                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1315                 {
1316                         $this->source_class = $class;
1317                         return true;
1318                 }
1319                 return false;
1320         }
1321
1322         /**
1323          * Allows you to override the default user agent string.
1324          *
1325          * @access public
1326          * @param string $ua New user agent string.
1327          */
1328         function set_useragent($ua = SIMPLEPIE_USERAGENT)
1329         {
1330                 $this->useragent = (string) $ua;
1331         }
1332
1333         /**
1334          * Set callback function to create cache filename with
1335          *
1336          * @access public
1337          * @param mixed $function Callback function
1338          */
1339         function set_cache_name_function($function = 'md5')
1340         {
1341                 if (is_callable($function))
1342                 {
1343                         $this->cache_name_function = $function;
1344                 }
1345         }
1346
1347         /**
1348          * Set javascript query string parameter
1349          *
1350          * @access public
1351          * @param mixed $get Javascript query string parameter
1352          */
1353         function set_javascript($get = 'js')
1354         {
1355                 if ($get)
1356                 {
1357                         $this->javascript = (string) $get;
1358                 }
1359                 else
1360                 {
1361                         $this->javascript = false;
1362                 }
1363         }
1364
1365         /**
1366          * Set options to make SP as fast as possible.  Forgoes a
1367          * substantial amount of data sanitization in favor of speed.
1368          *
1369          * @access public
1370          * @param bool $set Whether to set them or not
1371          */
1372         function set_stupidly_fast($set = false)
1373         {
1374                 if ($set)
1375                 {
1376                         $this->enable_order_by_date(false);
1377                         $this->remove_div(false);
1378                         $this->strip_comments(false);
1379                         $this->strip_htmltags(false);
1380                         $this->strip_attributes(false);
1381                         $this->set_image_handler(false);
1382                 }
1383         }
1384
1385         /**
1386          * Set maximum number of feeds to check with autodiscovery
1387          *
1388          * @access public
1389          * @param int $max Maximum number of feeds to check
1390          */
1391         function set_max_checked_feeds($max = 10)
1392         {
1393                 $this->max_checked_feeds = (int) $max;
1394         }
1395
1396         function remove_div($enable = true)
1397         {
1398                 $this->sanitize->remove_div($enable);
1399         }
1400
1401         function strip_htmltags($tags = '', $encode = null)
1402         {
1403                 if ($tags === '')
1404                 {
1405                         $tags = $this->strip_htmltags;
1406                 }
1407                 $this->sanitize->strip_htmltags($tags);
1408                 if ($encode !== null)
1409                 {
1410                         $this->sanitize->encode_instead_of_strip($tags);
1411                 }
1412         }
1413
1414         function encode_instead_of_strip($enable = true)
1415         {
1416                 $this->sanitize->encode_instead_of_strip($enable);
1417         }
1418
1419         function strip_attributes($attribs = '')
1420         {
1421                 if ($attribs === '')
1422                 {
1423                         $attribs = $this->strip_attributes;
1424                 }
1425                 $this->sanitize->strip_attributes($attribs);
1426         }
1427
1428         function set_output_encoding($encoding = 'UTF-8')
1429         {
1430                 $this->sanitize->set_output_encoding($encoding);
1431         }
1432
1433         function strip_comments($strip = false)
1434         {
1435                 $this->sanitize->strip_comments($strip);
1436         }
1437
1438         /**
1439          * Set element/attribute key/value pairs of HTML attributes
1440          * containing URLs that need to be resolved relative to the feed
1441          *
1442          * @access public
1443          * @since 1.0
1444          * @param array $element_attribute Element/attribute key/value pairs
1445          */
1446         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'))
1447         {
1448                 $this->sanitize->set_url_replacements($element_attribute);
1449         }
1450
1451         /**
1452          * Set the handler to enable the display of cached favicons.
1453          *
1454          * @access public
1455          * @param str $page Web-accessible path to the handler_favicon.php file.
1456          * @param str $qs The query string that the value should be passed to.
1457          */
1458         function set_favicon_handler($page = false, $qs = 'i')
1459         {
1460                 if ($page !== false)
1461                 {
1462                         $this->favicon_handler = $page . '?' . $qs . '=';
1463                 }
1464                 else
1465                 {
1466                         $this->favicon_handler = '';
1467                 }
1468         }
1469
1470         /**
1471          * Set the handler to enable the display of cached images.
1472          *
1473          * @access public
1474          * @param str $page Web-accessible path to the handler_image.php file.
1475          * @param str $qs The query string that the value should be passed to.
1476          */
1477         function set_image_handler($page = false, $qs = 'i')
1478         {
1479                 if ($page !== false)
1480                 {
1481                         $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1482                 }
1483                 else
1484                 {
1485                         $this->image_handler = '';
1486                 }
1487         }
1488
1489         /**
1490          * Set the limit for items returned per-feed with multifeeds.
1491          *
1492          * @access public
1493          * @param integer $limit The maximum number of items to return.
1494          */
1495         function set_item_limit($limit = 0)
1496         {
1497                 $this->item_limit = (int) $limit;
1498         }
1499
1500         function init()
1501         {
1502                 // Check absolute bare minimum requirements.
1503                 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1504                 {
1505                         return false;
1506                 }
1507                 // 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.
1508                 elseif (!extension_loaded('xmlreader'))
1509                 {
1510                         static $xml_is_sane = null;
1511                         if ($xml_is_sane === null)
1512                         {
1513                                 $parser_check = xml_parser_create();
1514                                 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1515                                 xml_parser_free($parser_check);
1516                                 $xml_is_sane = isset($values[0]['value']);
1517                         }
1518                         if (!$xml_is_sane)
1519                         {
1520                                 return false;
1521                         }
1522                 }
1523
1524                 if (isset($_GET[$this->javascript]))
1525                 {
1526                         SimplePie_Misc::output_javascript();
1527                         exit;
1528                 }
1529
1530                 // Pass whatever was set with config options over to the sanitizer.
1531                 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1532                 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1533
1534                 if ($this->feed_url !== null || $this->raw_data !== null)
1535                 {
1536                         $this->data = array();
1537                         $this->multifeed_objects = array();
1538                         $cache = false;
1539
1540                         if ($this->feed_url !== null)
1541                         {
1542                                 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1543                                 // Decide whether to enable caching
1544                                 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1545                                 {
1546                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1547                                 }
1548                                 // If it's enabled and we don't want an XML dump, use the cache
1549                                 if ($cache && !$this->xml_dump)
1550                                 {
1551                                         // Load the Cache
1552                                         $this->data = $cache->load();
1553                                         if (!empty($this->data))
1554                                         {
1555                                                 // If the cache is for an outdated build of SimplePie
1556                                                 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1557                                                 {
1558                                                         $cache->unlink();
1559                                                         $this->data = array();
1560                                                 }
1561                                                 // If we've hit a collision just rerun it with caching disabled
1562                                                 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1563                                                 {
1564                                                         $cache = false;
1565                                                         $this->data = array();
1566                                                 }
1567                                                 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1568                                                 elseif (isset($this->data['feed_url']))
1569                                                 {
1570                                                         // If the autodiscovery cache is still valid use it.
1571                                                         if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1572                                                         {
1573                                                                 // Do not need to do feed autodiscovery yet.
1574                                                                 if ($this->data['feed_url'] === $this->data['url'])
1575                                                                 {
1576                                                                         $cache->unlink();
1577                                                                         $this->data = array();
1578                                                                 }
1579                                                                 else
1580                                                                 {
1581                                                                         $this->set_feed_url($this->data['feed_url']);
1582                                                                         return $this->init();
1583                                                                 }
1584                                                         }
1585                                                 }
1586                                                 // Check if the cache has been updated
1587                                                 elseif ($cache->mtime() + $this->cache_duration < time())
1588                                                 {
1589                                                         // If we have last-modified and/or etag set
1590                                                         if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1591                                                         {
1592                                                                 $headers = array();
1593                                                                 if (isset($this->data['headers']['last-modified']))
1594                                                                 {
1595                                                                         $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1596                                                                 }
1597                                                                 if (isset($this->data['headers']['etag']))
1598                                                                 {
1599                                                                         $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1600                                                                 }
1601                                                                 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1602                                                                 if ($file->success)
1603                                                                 {
1604                                                                         if ($file->status_code === 304)
1605                                                                         {
1606                                                                                 $cache->touch();
1607                                                                                 return true;
1608                                                                         }
1609                                                                         else
1610                                                                         {
1611                                                                                 $headers = $file->headers;
1612                                                                         }
1613                                                                 }
1614                                                                 else
1615                                                                 {
1616                                                                         unset($file);
1617                                                                 }
1618                                                         }
1619                                                 }
1620                                                 // If the cache is still valid, just return true
1621                                                 else
1622                                                 {
1623                                                         return true;
1624                                                 }
1625                                         }
1626                                         // If the cache is empty, delete it
1627                                         else
1628                                         {
1629                                                 $cache->unlink();
1630                                                 $this->data = array();
1631                                         }
1632                                 }
1633                                 // 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.
1634                                 if (!isset($file))
1635                                 {
1636                                         if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1637                                         {
1638                                                 $file =& $this->file;
1639                                         }
1640                                         else
1641                                         {
1642                                                 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1643                                         }
1644                                 }
1645                                 // If the file connection has an error, set SimplePie::error to that and quit
1646                                 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1647                                 {
1648                                         $this->error = $file->error;
1649                                         if (!empty($this->data))
1650                                         {
1651                                                 return true;
1652                                         }
1653                                         else
1654                                         {
1655                                                 return false;
1656                                         }
1657                                 }
1658
1659                                 if (!$this->force_feed)
1660                                 {
1661                                         // Check if the supplied URL is a feed, if it isn't, look for it.
1662                                         $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1663                                         if (!$locate->is_feed($file))
1664                                         {
1665                                                 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1666                                                 unset($file);
1667                                                 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1668                                                 {
1669                                                         if ($cache)
1670                                                         {
1671                                                                 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1672                                                                 if (!$cache->save($this))
1673                                                                 {
1674                                                                         trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
1675                                                                 }
1676                                                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1677                                                         }
1678                                                         $this->feed_url = $file->url;
1679                                                 }
1680                                                 else
1681                                                 {
1682                                                         $this->error = "A feed could not be found at $this->feed_url";
1683                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1684                                                         return false;
1685                                                 }
1686                                         }
1687                                         $locate = null;
1688                                 }
1689
1690                                 $headers = $file->headers;
1691                                 $data = $file->body;
1692                                 $sniffer =& new $this->content_type_sniffer_class($file);
1693                                 $sniffed = $sniffer->get_type();
1694                         }
1695                         else
1696                         {
1697                                 $data = $this->raw_data;
1698                         }
1699
1700                         // Set up array of possible encodings
1701                         $encodings = array();
1702
1703                         // First check to see if input has been overridden.
1704                         if ($this->input_encoding !== false)
1705                         {
1706                                 $encodings[] = $this->input_encoding;
1707                         }
1708
1709                         $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1710                         $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1711
1712                         // RFC 3023 (only applies to sniffed content)
1713                         if (isset($sniffed))
1714                         {
1715                                 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1716                                 {
1717                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1718                                         {
1719                                                 $encodings[] = strtoupper($charset[1]);
1720                                         }
1721                                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1722                                         $encodings[] = 'UTF-8';
1723                                 }
1724                                 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1725                                 {
1726                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1727                                         {
1728                                                 $encodings[] = $charset[1];
1729                                         }
1730                                         $encodings[] = 'US-ASCII';
1731                                 }
1732                                 // Text MIME-type default
1733                                 elseif (substr($sniffed, 0, 5) === 'text/')
1734                                 {
1735                                         $encodings[] = 'US-ASCII';
1736                                 }
1737                         }
1738
1739                         // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1740                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1741                         $encodings[] = 'UTF-8';
1742                         $encodings[] = 'ISO-8859-1';
1743
1744                         // There's no point in trying an encoding twice
1745                         $encodings = array_unique($encodings);
1746
1747                         // If we want the XML, just output that with the most likely encoding and quit
1748                         if ($this->xml_dump)
1749                         {
1750                                 header('Content-type: text/xml; charset=' . $encodings[0]);
1751                                 echo $data;
1752                                 exit;
1753                         }
1754
1755                         // Loop through each possible encoding, till we return something, or run out of possibilities
1756                         foreach ($encodings as $encoding)
1757                         {
1758                                 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1759                                 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1760                                 {
1761                                         // Create new parser
1762                                         $parser =& new $this->parser_class();
1763
1764                                         // If it's parsed fine
1765                                         if ($parser->parse($utf8_data, 'UTF-8'))
1766                                         {
1767                                                 $this->data = $parser->get_data();
1768                                                 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1769                                                 {
1770                                                         if (isset($headers))
1771                                                         {
1772                                                                 $this->data['headers'] = $headers;
1773                                                         }
1774                                                         $this->data['build'] = SIMPLEPIE_BUILD;
1775
1776                                                         // Cache the file if caching is enabled
1777                                                         if ($cache && !$cache->save($this))
1778                                                         {
1779                                                                 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1780                                                         }
1781                                                         return true;
1782                                                 }
1783                                                 else
1784                                                 {
1785                                                         $this->error = "A feed could not be found at $this->feed_url";
1786                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1787                                                         return false;
1788                                                 }
1789                                         }
1790                                 }
1791                         }
1792                         if(isset($parser))
1793                         {
1794                                 // We have an error, just set SimplePie_Misc::error to it and quit
1795                                 $this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1796                         }
1797                         else
1798                         {
1799                                 $this->error = 'The data could not be converted to UTF-8';
1800                         }
1801                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1802                         return false;
1803                 }
1804                 elseif (!empty($this->multifeed_url))
1805                 {
1806                         $i = 0;
1807                         $success = 0;
1808                         $this->multifeed_objects = array();
1809                         foreach ($this->multifeed_url as $url)
1810                         {
1811                                 if (SIMPLEPIE_PHP5)
1812                                 {
1813                                         // This keyword needs to defy coding standards for PHP4 compatibility
1814                                         $this->multifeed_objects[$i] = clone($this);
1815                                 }
1816                                 else
1817                                 {
1818                                         $this->multifeed_objects[$i] = $this;
1819                                 }
1820                                 $this->multifeed_objects[$i]->set_feed_url($url);
1821                                 $success |= $this->multifeed_objects[$i]->init();
1822                                 $i++;
1823                         }
1824                         return (bool) $success;
1825                 }
1826                 else
1827                 {
1828                         return false;
1829                 }
1830         }
1831
1832         /**
1833          * Return the error message for the occured error
1834          *
1835          * @access public
1836          * @return string Error message
1837          */
1838         function error()
1839         {
1840                 return $this->error;
1841         }
1842
1843         function get_encoding()
1844         {
1845                 return $this->sanitize->output_encoding;
1846         }
1847
1848         function handle_content_type($mime = 'text/html')
1849         {
1850                 if (!headers_sent())
1851                 {
1852                         $header = "Content-type: $mime;";
1853                         if ($this->get_encoding())
1854                         {
1855                                 $header .= ' charset=' . $this->get_encoding();
1856                         }
1857                         else
1858                         {
1859                                 $header .= ' charset=UTF-8';
1860                         }
1861                         header($header);
1862                 }
1863         }
1864
1865         function get_type()
1866         {
1867                 if (!isset($this->data['type']))
1868                 {
1869                         $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1870                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1871                         {
1872                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1873                         }
1874                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1875                         {
1876                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1877                         }
1878                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1879                         {
1880                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1881                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1882                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1883                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1884                                 {
1885                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1886                                 }
1887                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1888                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1889                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1890                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1891                                 {
1892                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1893                                 }
1894                         }
1895                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1896                         {
1897                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1898                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1899                                 {
1900                                         switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1901                                         {
1902                                                 case '0.91':
1903                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1904                                                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1905                                                         {
1906                                                                 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1907                                                                 {
1908                                                                         case '0':
1909                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1910                                                                                 break;
1911
1912                                                                         case '24':
1913                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1914                                                                                 break;
1915                                                                 }
1916                                                         }
1917                                                         break;
1918
1919                                                 case '0.92':
1920                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1921                                                         break;
1922
1923                                                 case '0.93':
1924                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1925                                                         break;
1926
1927                                                 case '0.94':
1928                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1929                                                         break;
1930
1931                                                 case '2.0':
1932                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1933                                                         break;
1934                                         }
1935                                 }
1936                         }
1937                         else
1938                         {
1939                                 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1940                         }
1941                 }
1942                 return $this->data['type'];
1943         }
1944
1945         /**
1946          * Returns the URL for the favicon of the feed's website.
1947          *
1948          * @todo Cache atom:icon
1949          * @access public
1950          * @since 1.0
1951          */
1952         function get_favicon()
1953         {
1954                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1955                 {
1956                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1957                 }
1958                 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1959                 {
1960                         $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1961
1962                         if ($this->cache && $this->favicon_handler)
1963                         {
1964                                 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1965                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1966
1967                                 if ($cache->load())
1968                                 {
1969                                         return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1970                                 }
1971                                 else
1972                                 {
1973                                         $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1974
1975                                         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)
1976                                         {
1977                                                 $sniffer =& new $this->content_type_sniffer_class($file);
1978                                                 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1979                                                 {
1980                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1981                                                         {
1982                                                                 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1983                                                         }
1984                                                         else
1985                                                         {
1986                                                                 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1987                                                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1988                                                         }
1989                                                 }
1990                                                 // not an image
1991                                                 else
1992                                                 {
1993                                                         return false;
1994                                                 }
1995                                         }
1996                                 }
1997                         }
1998                         else
1999                         {
2000                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2001                         }
2002                 }
2003                 return false;
2004         }
2005
2006         /**
2007          * @todo If we have a perm redirect we should return the new URL
2008          * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2009          * @todo Also, |atom:link|@rel=self
2010          */
2011         function subscribe_url()
2012         {
2013                 if ($this->feed_url !== null)
2014                 {
2015                         return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2016                 }
2017                 else
2018                 {
2019                         return null;
2020                 }
2021         }
2022
2023         function subscribe_feed()
2024         {
2025                 if ($this->feed_url !== null)
2026                 {
2027                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2028                 }
2029                 else
2030                 {
2031                         return null;
2032                 }
2033         }
2034
2035         function subscribe_outlook()
2036         {
2037                 if ($this->feed_url !== null)
2038                 {
2039                         return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2040                 }
2041                 else
2042                 {
2043                         return null;
2044                 }
2045         }
2046
2047         function subscribe_podcast()
2048         {
2049                 if ($this->feed_url !== null)
2050                 {
2051                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2052                 }
2053                 else
2054                 {
2055                         return null;
2056                 }
2057         }
2058
2059         function subscribe_itunes()
2060         {
2061                 if ($this->feed_url !== null)
2062                 {
2063                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2064                 }
2065                 else
2066                 {
2067                         return null;
2068                 }
2069         }
2070
2071         /**
2072          * Creates the subscribe_* methods' return data
2073          *
2074          * @access private
2075          * @param string $feed_url String to prefix to the feed URL
2076          * @param string $site_url String to prefix to the site URL (and
2077          * suffix to the feed URL)
2078          * @return mixed URL if feed exists, false otherwise
2079          */
2080         function subscribe_service($feed_url, $site_url = null)
2081         {
2082                 if ($this->subscribe_url())
2083                 {
2084                         $return = $feed_url . rawurlencode($this->feed_url);
2085                         if ($site_url !== null && $this->get_link() !== null)
2086                         {
2087                                 $return .= $site_url . rawurlencode($this->get_link());
2088                         }
2089                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2090                 }
2091                 else
2092                 {
2093                         return null;
2094                 }
2095         }
2096
2097         function subscribe_aol()
2098         {
2099                 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2100         }
2101
2102         function subscribe_bloglines()
2103         {
2104                 return $this->subscribe_service('http://www.bloglines.com/sub/');
2105         }
2106
2107         function subscribe_eskobo()
2108         {
2109                 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2110         }
2111
2112         function subscribe_feedfeeds()
2113         {
2114                 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2115         }
2116
2117         function subscribe_feedster()
2118         {
2119                 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2120         }
2121
2122         function subscribe_google()
2123         {
2124                 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2125         }
2126
2127         function subscribe_gritwire()
2128         {
2129                 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2130         }
2131
2132         function subscribe_msn()
2133         {
2134                 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2135         }
2136
2137         function subscribe_netvibes()
2138         {
2139                 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2140         }
2141
2142         function subscribe_newsburst()
2143         {
2144                 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2145         }
2146
2147         function subscribe_newsgator()
2148         {
2149                 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2150         }
2151
2152         function subscribe_odeo()
2153         {
2154                 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2155         }
2156
2157         function subscribe_podnova()
2158         {
2159                 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2160         }
2161
2162         function subscribe_rojo()
2163         {
2164                 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2165         }
2166
2167         function subscribe_yahoo()
2168         {
2169                 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2170         }
2171
2172         function get_feed_tags($namespace, $tag)
2173         {
2174                 $type = $this->get_type();
2175                 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2176                 {
2177                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2178                         {
2179                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2180                         }
2181                 }
2182                 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2183                 {
2184                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2185                         {
2186                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2187                         }
2188                 }
2189                 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2190                 {
2191                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2192                         {
2193                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2194                         }
2195                 }
2196                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2197                 {
2198                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2199                         {
2200                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2201                         }
2202                 }
2203                 return null;
2204         }
2205
2206         function get_channel_tags($namespace, $tag)
2207         {
2208                 $type = $this->get_type();
2209                 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2210                 {
2211                         if ($return = $this->get_feed_tags($namespace, $tag))
2212                         {
2213                                 return $return;
2214                         }
2215                 }
2216                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2217                 {
2218                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2219                         {
2220                                 if (isset($channel[0]['child'][$namespace][$tag]))
2221                                 {
2222                                         return $channel[0]['child'][$namespace][$tag];
2223                                 }
2224                         }
2225                 }
2226                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2227                 {
2228                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2229                         {
2230                                 if (isset($channel[0]['child'][$namespace][$tag]))
2231                                 {
2232                                         return $channel[0]['child'][$namespace][$tag];
2233                                 }
2234                         }
2235                 }
2236                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2237                 {
2238                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2239                         {
2240                                 if (isset($channel[0]['child'][$namespace][$tag]))
2241                                 {
2242                                         return $channel[0]['child'][$namespace][$tag];
2243                                 }
2244                         }
2245                 }
2246                 return null;
2247         }
2248
2249         function get_image_tags($namespace, $tag)
2250         {
2251                 $type = $this->get_type();
2252                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2253                 {
2254                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2255                         {
2256                                 if (isset($image[0]['child'][$namespace][$tag]))
2257                                 {
2258                                         return $image[0]['child'][$namespace][$tag];
2259                                 }
2260                         }
2261                 }
2262                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2263                 {
2264                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2265                         {
2266                                 if (isset($image[0]['child'][$namespace][$tag]))
2267                                 {
2268                                         return $image[0]['child'][$namespace][$tag];
2269                                 }
2270                         }
2271                 }
2272                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2273                 {
2274                         if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2275                         {
2276                                 if (isset($image[0]['child'][$namespace][$tag]))
2277                                 {
2278                                         return $image[0]['child'][$namespace][$tag];
2279                                 }
2280                         }
2281                 }
2282                 return null;
2283         }
2284
2285         function get_base($element = array())
2286         {
2287                 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2288                 {
2289                         return $element['xml_base'];
2290                 }
2291                 elseif ($this->get_link() !== null)
2292                 {
2293                         return $this->get_link();
2294                 }
2295                 else
2296                 {
2297                         return $this->subscribe_url();
2298                 }
2299         }
2300
2301         function sanitize($data, $type, $base = '')
2302         {
2303                 return $this->sanitize->sanitize($data, $type, $base);
2304         }
2305
2306         function get_title()
2307         {
2308                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2309                 {
2310                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2311                 }
2312                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2313                 {
2314                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2315                 }
2316                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2317                 {
2318                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2319                 }
2320                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2321                 {
2322                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2323                 }
2324                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2325                 {
2326                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2327                 }
2328                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2329                 {
2330                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2331                 }
2332                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2333                 {
2334                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2335                 }
2336                 else
2337                 {
2338                         return null;
2339                 }
2340         }
2341
2342         function get_category($key = 0)
2343         {
2344                 $categories = $this->get_categories();
2345                 if (isset($categories[$key]))
2346                 {
2347                         return $categories[$key];
2348                 }
2349                 else
2350                 {
2351                         return null;
2352                 }
2353         }
2354
2355         function get_categories()
2356         {
2357                 $categories = array();
2358
2359                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2360                 {
2361                         $term = null;
2362                         $scheme = null;
2363                         $label = null;
2364                         if (isset($category['attribs']['']['term']))
2365                         {
2366                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2367                         }
2368                         if (isset($category['attribs']['']['scheme']))
2369                         {
2370                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2371                         }
2372                         if (isset($category['attribs']['']['label']))
2373                         {
2374                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2375                         }
2376                         $categories[] =& new $this->category_class($term, $scheme, $label);
2377                 }
2378                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2379                 {
2380                         // This is really the label, but keep this as the term also for BC.
2381                         // Label will also work on retrieving because that falls back to term.
2382                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2383                         if (isset($category['attribs']['']['domain']))
2384                         {
2385                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2386                         }
2387                         else
2388                         {
2389                                 $scheme = null;
2390                         }
2391                         $categories[] =& new $this->category_class($term, $scheme, null);
2392                 }
2393                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2394                 {
2395                         $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2396                 }
2397                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2398                 {
2399                         $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2400                 }
2401
2402                 if (!empty($categories))
2403                 {
2404                         return SimplePie_Misc::array_unique($categories);
2405                 }
2406                 else
2407                 {
2408                         return null;
2409                 }
2410         }
2411
2412         function get_author($key = 0)
2413         {
2414                 $authors = $this->get_authors();
2415                 if (isset($authors[$key]))
2416                 {
2417                         return $authors[$key];
2418                 }
2419                 else
2420                 {
2421                         return null;
2422                 }
2423         }
2424
2425         function get_authors()
2426         {
2427                 $authors = array();
2428                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2429                 {
2430                         $name = null;
2431                         $uri = null;
2432                         $email = null;
2433                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2434                         {
2435                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2436                         }
2437                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2438                         {
2439                                 $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]));
2440                         }
2441                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2442                         {
2443                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2444                         }
2445                         if ($name !== null || $email !== null || $uri !== null)
2446                         {
2447                                 $authors[] =& new $this->author_class($name, $uri, $email);
2448                         }
2449                 }
2450                 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2451                 {
2452                         $name = null;
2453                         $url = null;
2454                         $email = null;
2455                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2456                         {
2457                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2458                         }
2459                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2460                         {
2461                                 $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]));
2462                         }
2463                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2464                         {
2465                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2466                         }
2467                         if ($name !== null || $email !== null || $url !== null)
2468                         {
2469                                 $authors[] =& new $this->author_class($name, $url, $email);
2470                         }
2471                 }
2472                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2473                 {
2474                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2475                 }
2476                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2477                 {
2478                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2479                 }
2480                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2481                 {
2482                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2483                 }
2484
2485                 if (!empty($authors))
2486                 {
2487                         return SimplePie_Misc::array_unique($authors);
2488                 }
2489                 else
2490                 {
2491                         return null;
2492                 }
2493         }
2494
2495         function get_contributor($key = 0)
2496         {
2497                 $contributors = $this->get_contributors();
2498                 if (isset($contributors[$key]))
2499                 {
2500                         return $contributors[$key];
2501                 }
2502                 else
2503                 {
2504                         return null;
2505                 }
2506         }
2507
2508         function get_contributors()
2509         {
2510                 $contributors = array();
2511                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2512                 {
2513                         $name = null;
2514                         $uri = null;
2515                         $email = null;
2516                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2517                         {
2518                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2519                         }
2520                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2521                         {
2522                                 $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]));
2523                         }
2524                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2525                         {
2526                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2527                         }
2528                         if ($name !== null || $email !== null || $uri !== null)
2529                         {
2530                                 $contributors[] =& new $this->author_class($name, $uri, $email);
2531                         }
2532                 }
2533                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2534                 {
2535                         $name = null;
2536                         $url = null;
2537                         $email = null;
2538                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2539                         {
2540                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2541                         }
2542                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2543                         {
2544                                 $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]));
2545                         }
2546                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2547                         {
2548                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2549                         }
2550                         if ($name !== null || $email !== null || $url !== null)
2551                         {
2552                                 $contributors[] =& new $this->author_class($name, $url, $email);
2553                         }
2554                 }
2555
2556                 if (!empty($contributors))
2557                 {
2558                         return SimplePie_Misc::array_unique($contributors);
2559                 }
2560                 else
2561                 {
2562                         return null;
2563                 }
2564         }
2565
2566         function get_link($key = 0, $rel = 'alternate')
2567         {
2568                 $links = $this->get_links($rel);
2569                 if (isset($links[$key]))
2570                 {
2571                         return $links[$key];
2572                 }
2573                 else
2574                 {
2575                         return null;
2576                 }
2577         }
2578
2579         /**
2580          * Added for parity between the parent-level and the item/entry-level.
2581          */
2582         function get_permalink()
2583         {
2584                 return $this->get_link(0);
2585         }
2586
2587         function get_links($rel = 'alternate')
2588         {
2589                 if (!isset($this->data['links']))
2590                 {
2591                         $this->data['links'] = array();
2592                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2593                         {
2594                                 foreach ($links as $link)
2595                                 {
2596                                         if (isset($link['attribs']['']['href']))
2597                                         {
2598                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2599                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2600                                         }
2601                                 }
2602                         }
2603                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2604                         {
2605                                 foreach ($links as $link)
2606                                 {
2607                                         if (isset($link['attribs']['']['href']))
2608                                         {
2609                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2610                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2611
2612                                         }
2613                                 }
2614                         }
2615                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2616                         {
2617                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2618                         }
2619                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2620                         {
2621                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2622                         }
2623                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2624                         {
2625                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2626                         }
2627
2628                         $keys = array_keys($this->data['links']);
2629                         foreach ($keys as $key)
2630                         {
2631                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
2632                                 {
2633                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2634                                         {
2635                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2636                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2637                                         }
2638                                         else
2639                                         {
2640                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2641                                         }
2642                                 }
2643                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2644                                 {
2645                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2646                                 }
2647                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2648                         }
2649                 }
2650
2651                 if (isset($this->data['links'][$rel]))
2652                 {
2653                         return $this->data['links'][$rel];
2654                 }
2655                 else
2656                 {
2657                         return null;
2658                 }
2659         }
2660
2661         function get_all_discovered_feeds()
2662         {
2663                 return $this->all_discovered_feeds;
2664         }
2665
2666         function get_description()
2667         {
2668                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2669                 {
2670                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2671                 }
2672                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2673                 {
2674                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2675                 }
2676                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2677                 {
2678                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2679                 }
2680                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2681                 {
2682                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2683                 }
2684                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2685                 {
2686                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2687                 }
2688                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2689                 {
2690                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2691                 }
2692                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2693                 {
2694                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2695                 }
2696                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2697                 {
2698                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2699                 }
2700                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2701                 {
2702                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2703                 }
2704                 else
2705                 {
2706                         return null;
2707                 }
2708         }
2709
2710         function get_copyright()
2711         {
2712                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2713                 {
2714                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2715                 }
2716                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2717                 {
2718                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2719                 }
2720                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2721                 {
2722                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2723                 }
2724                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2725                 {
2726                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2727                 }
2728                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2729                 {
2730                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2731                 }
2732                 else
2733                 {
2734                         return null;
2735                 }
2736         }
2737
2738         function get_language()
2739         {
2740                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2741                 {
2742                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2743                 }
2744                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2745                 {
2746                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2747                 }
2748                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2749                 {
2750                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2751                 }
2752                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2753                 {
2754                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2755                 }
2756                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2757                 {
2758                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2759                 }
2760                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2761                 {
2762                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2763                 }
2764                 elseif (isset($this->data['headers']['content-language']))
2765                 {
2766                         return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2767                 }
2768                 else
2769                 {
2770                         return null;
2771                 }
2772         }
2773
2774         function get_latitude()
2775         {
2776                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2777                 {
2778                         return (float) $return[0]['data'];
2779                 }
2780                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2781                 {
2782                         return (float) $match[1];
2783                 }
2784                 else
2785                 {
2786                         return null;
2787                 }
2788         }
2789
2790         function get_longitude()
2791         {
2792                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2793                 {
2794                         return (float) $return[0]['data'];
2795                 }
2796                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2797                 {
2798                         return (float) $return[0]['data'];
2799                 }
2800                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2801                 {
2802                         return (float) $match[2];
2803                 }
2804                 else
2805                 {
2806                         return null;
2807                 }
2808         }
2809
2810         function get_image_title()
2811         {
2812                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2813                 {
2814                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2815                 }
2816                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2817                 {
2818                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2819                 }
2820                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2821                 {
2822                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2823                 }
2824                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2825                 {
2826                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2827                 }
2828                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2829                 {
2830                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2831                 }
2832                 else
2833                 {
2834                         return null;
2835                 }
2836         }
2837
2838         function get_image_url()
2839         {
2840                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2841                 {
2842                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2843                 }
2844                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2845                 {
2846                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2847                 }
2848                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2849                 {
2850                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2851                 }
2852                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2853                 {
2854                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2855                 }
2856                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2857                 {
2858                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2859                 }
2860                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2861                 {
2862                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2863                 }
2864                 else
2865                 {
2866                         return null;
2867                 }
2868         }
2869
2870         function get_image_link()
2871         {
2872                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2873                 {
2874                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2875                 }
2876                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2877                 {
2878                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2879                 }
2880                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2881                 {
2882                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2883                 }
2884                 else
2885                 {
2886                         return null;
2887                 }
2888         }
2889
2890         function get_image_width()
2891         {
2892                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2893                 {
2894                         return round($return[0]['data']);
2895                 }
2896                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2897                 {
2898                         return 88.0;
2899                 }
2900                 else
2901                 {
2902                         return null;
2903                 }
2904         }
2905
2906         function get_image_height()
2907         {
2908                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2909                 {
2910                         return round($return[0]['data']);
2911                 }
2912                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2913                 {
2914                         return 31.0;
2915                 }
2916                 else
2917                 {
2918                         return null;
2919                 }
2920         }
2921
2922         function get_item_quantity($max = 0)
2923         {
2924                 $max = (int) $max;
2925                 $qty = count($this->get_items());
2926                 if ($max === 0)
2927                 {
2928                         return $qty;
2929                 }
2930                 else
2931                 {
2932                         return ($qty > $max) ? $max : $qty;
2933                 }
2934         }
2935
2936         function get_item($key = 0)
2937         {
2938                 $items = $this->get_items();
2939                 if (isset($items[$key]))
2940                 {
2941                         return $items[$key];
2942                 }
2943                 else
2944                 {
2945                         return null;
2946                 }
2947         }
2948
2949         function get_items($start = 0, $end = 0)
2950         {
2951                 if (!isset($this->data['items']))
2952                 {
2953                         if (!empty($this->multifeed_objects))
2954                         {
2955                                 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2956                         }
2957                         else
2958                         {
2959                                 $this->data['items'] = array();
2960                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2961                                 {
2962                                         $keys = array_keys($items);
2963                                         foreach ($keys as $key)
2964                                         {
2965                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2966                                         }
2967                                 }
2968                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2969                                 {
2970                                         $keys = array_keys($items);
2971                                         foreach ($keys as $key)
2972                                         {
2973                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2974                                         }
2975                                 }
2976                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2977                                 {
2978                                         $keys = array_keys($items);
2979                                         foreach ($keys as $key)
2980                                         {
2981                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2982                                         }
2983                                 }
2984                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2985                                 {
2986                                         $keys = array_keys($items);
2987                                         foreach ($keys as $key)
2988                                         {
2989                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2990                                         }
2991                                 }
2992                                 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2993                                 {
2994                                         $keys = array_keys($items);
2995                                         foreach ($keys as $key)
2996                                         {
2997                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2998                                         }
2999                                 }
3000                         }
3001                 }
3002
3003                 if (!empty($this->data['items']))
3004                 {
3005                         // If we want to order it by date, check if all items have a date, and then sort it
3006                         if ($this->order_by_date && empty($this->multifeed_objects))
3007                         {
3008                                 if (!isset($this->data['ordered_items']))
3009                                 {
3010                                         $do_sort = true;
3011                                         foreach ($this->data['items'] as $item)
3012                                         {
3013                                                 if (!$item->get_date('U'))
3014                                                 {
3015                                                         $do_sort = false;
3016                                                         break;
3017                                                 }
3018                                         }
3019                                         $item = null;
3020                                         $this->data['ordered_items'] = $this->data['items'];
3021                                         if ($do_sort)
3022                                         {
3023                                                 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3024                                         }
3025                                 }
3026                                 $items = $this->data['ordered_items'];
3027                         }
3028                         else
3029                         {
3030                                 $items = $this->data['items'];
3031                         }
3032
3033                         // Slice the data as desired
3034                         if ($end === 0)
3035                         {
3036                                 return array_slice($items, $start);
3037                         }
3038                         else
3039                         {
3040                                 return array_slice($items, $start, $end);
3041                         }
3042                 }
3043                 else
3044                 {
3045                         return array();
3046                 }
3047         }
3048
3049         /**
3050          * @static
3051          */
3052         function sort_items($a, $b)
3053         {
3054                 return $a->get_date('U') <= $b->get_date('U');
3055         }
3056
3057         /**
3058          * @static
3059          */
3060         function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3061         {
3062                 if (is_array($urls) && sizeof($urls) > 0)
3063                 {
3064                         $items = array();
3065                         foreach ($urls as $arg)
3066                         {
3067                                 if (is_a($arg, 'SimplePie'))
3068                                 {
3069                                         $items = array_merge($items, $arg->get_items(0, $limit));
3070                                 }
3071                                 else
3072                                 {
3073                                         trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3074                                 }
3075                         }
3076
3077                         $do_sort = true;
3078                         foreach ($items as $item)
3079                         {
3080                                 if (!$item->get_date('U'))
3081                                 {
3082                                         $do_sort = false;
3083                                         break;
3084                                 }
3085                         }
3086                         $item = null;
3087                         if ($do_sort)
3088                         {
3089                                 usort($items, array('SimplePie', 'sort_items'));
3090                         }
3091
3092                         if ($end === 0)
3093                         {
3094                                 return array_slice($items, $start);
3095                         }
3096                         else
3097                         {
3098                                 return array_slice($items, $start, $end);
3099                         }
3100                 }
3101                 else
3102                 {
3103                         trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3104                         return array();
3105                 }
3106         }
3107 }
3108
3109 class SimplePie_Item
3110 {
3111         var $feed;
3112         var $data = array();
3113
3114         function SimplePie_Item($feed, $data)
3115         {
3116                 $this->feed = $feed;
3117                 $this->data = $data;
3118         }
3119
3120         function __toString()
3121         {
3122                 return md5(serialize($this->data));
3123         }
3124
3125         /**
3126          * Remove items that link back to this before destroying this object
3127          */
3128         function __destruct()
3129         {
3130                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3131                 {
3132                         unset($this->feed);
3133                 }
3134         }
3135
3136         function get_item_tags($namespace, $tag)
3137         {
3138                 if (isset($this->data['child'][$namespace][$tag]))
3139                 {
3140                         return $this->data['child'][$namespace][$tag];
3141                 }
3142                 else
3143                 {
3144                         return null;
3145                 }
3146         }
3147
3148         function get_base($element = array())
3149         {
3150                 return $this->feed->get_base($element);
3151         }
3152
3153         function sanitize($data, $type, $base = '')
3154         {
3155                 return $this->feed->sanitize($data, $type, $base);
3156         }
3157
3158         function get_feed()
3159         {
3160                 return $this->feed;
3161         }
3162
3163         function get_id($hash = false)
3164         {
3165                 if (!$hash)
3166                 {
3167                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3168                         {
3169                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3170                         }
3171                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3172                         {
3173                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3174                         }
3175                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3176                         {
3177                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3178                         }
3179                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3180                         {
3181                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3182                         }
3183                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3184                         {
3185                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3186                         }
3187                         elseif (($return = $this->get_permalink()) !== null)
3188                         {
3189                                 return $return;
3190                         }
3191                         elseif (($return = $this->get_title()) !== null)
3192                         {
3193                                 return $return;
3194                         }
3195                 }
3196                 if ($this->get_permalink() !== null || $this->get_title() !== null)
3197                 {
3198                         return md5($this->get_permalink() . $this->get_title());
3199                 }
3200                 else
3201                 {
3202                         return md5(serialize($this->data));
3203                 }
3204         }
3205
3206         function get_title()
3207         {
3208                 if (!isset($this->data['title']))
3209                 {
3210                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3211                         {
3212                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3213                         }
3214                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3215                         {
3216                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3217                         }
3218                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3219                         {
3220                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3221                         }
3222                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3223                         {
3224                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3225                         }
3226                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3227                         {
3228                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3229                         }
3230                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3231                         {
3232                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3233                         }
3234                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3235                         {
3236                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3237                         }
3238                         else
3239                         {
3240                                 $this->data['title'] = null;
3241                         }
3242                 }
3243                 return $this->data['title'];
3244         }
3245
3246         function get_description($description_only = false)
3247         {
3248                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3249                 {
3250                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3251                 }
3252                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3253                 {
3254                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3255                 }
3256                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3257                 {
3258                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3259                 }
3260                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3261                 {
3262                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3263                 }
3264                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3265                 {
3266                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3267                 }
3268                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3269                 {
3270                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3271                 }
3272                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3273                 {
3274                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3275                 }
3276                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3277                 {
3278                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3279                 }
3280                 elseif (!$description_only)
3281                 {
3282                         return $this->get_content(true);
3283                 }
3284                 else
3285                 {
3286                         return null;
3287                 }
3288         }
3289
3290         function get_content($content_only = false)
3291         {
3292                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3293                 {
3294                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3295                 }
3296                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3297                 {
3298                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3299                 }
3300                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3301                 {
3302                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3303                 }
3304                 elseif (!$content_only)
3305                 {
3306                         return $this->get_description(true);
3307                 }
3308                 else
3309                 {
3310                         return null;
3311                 }
3312         }
3313
3314         function get_category($key = 0)
3315         {
3316                 $categories = $this->get_categories();
3317                 if (isset($categories[$key]))
3318                 {
3319                         return $categories[$key];
3320                 }
3321                 else
3322                 {
3323                         return null;
3324                 }
3325         }
3326
3327         function get_categories()
3328         {
3329                 $categories = array();
3330
3331                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3332                 {
3333                         $term = null;
3334                         $scheme = null;
3335                         $label = null;
3336                         if (isset($category['attribs']['']['term']))
3337                         {
3338                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3339                         }
3340                         if (isset($category['attribs']['']['scheme']))
3341                         {
3342                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3343                         }
3344                         if (isset($category['attribs']['']['label']))
3345                         {
3346                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3347                         }
3348                         $categories[] =& new $this->feed->category_class($term, $scheme, $label);
3349                 }
3350                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3351                 {
3352                         // This is really the label, but keep this as the term also for BC.
3353                         // Label will also work on retrieving because that falls back to term.
3354                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3355                         if (isset($category['attribs']['']['domain']))
3356                         {
3357                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3358                         }
3359                         else
3360                         {
3361                                 $scheme = null;
3362                         }
3363                         $categories[] =& new $this->feed->category_class($term, $scheme, null);
3364                 }
3365                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3366                 {
3367                         $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3368                 }
3369                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3370                 {
3371                         $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3372                 }
3373
3374                 if (!empty($categories))
3375                 {
3376                         return SimplePie_Misc::array_unique($categories);
3377                 }
3378                 else
3379                 {
3380                         return null;
3381                 }
3382         }
3383
3384         function get_author($key = 0)
3385         {
3386                 $authors = $this->get_authors();
3387                 if (isset($authors[$key]))
3388                 {
3389                         return $authors[$key];
3390                 }
3391                 else
3392                 {
3393                         return null;
3394                 }
3395         }
3396
3397         function get_contributor($key = 0)
3398         {
3399                 $contributors = $this->get_contributors();
3400                 if (isset($contributors[$key]))
3401                 {
3402                         return $contributors[$key];
3403                 }
3404                 else
3405                 {
3406                         return null;
3407                 }
3408         }
3409
3410         function get_contributors()
3411         {
3412                 $contributors = array();
3413                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3414                 {
3415                         $name = null;
3416                         $uri = null;
3417                         $email = null;
3418                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3419                         {
3420                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3421                         }
3422                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3423                         {
3424                                 $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]));
3425                         }
3426                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3427                         {
3428                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3429                         }
3430                         if ($name !== null || $email !== null || $uri !== null)
3431                         {
3432                                 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
3433                         }
3434                 }
3435                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3436                 {
3437                         $name = null;
3438                         $url = null;
3439                         $email = null;
3440                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3441                         {
3442                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3443                         }
3444                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3445                         {
3446                                 $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]));
3447                         }
3448                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3449                         {
3450                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3451                         }
3452                         if ($name !== null || $email !== null || $url !== null)
3453                         {
3454                                 $contributors[] =& new $this->feed->author_class($name, $url, $email);
3455                         }
3456                 }
3457
3458                 if (!empty($contributors))
3459                 {
3460                         return SimplePie_Misc::array_unique($contributors);
3461                 }
3462                 else
3463                 {
3464                         return null;
3465                 }
3466         }
3467
3468         function get_authors()
3469         {
3470                 $authors = array();
3471                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3472                 {
3473                         $name = null;
3474                         $uri = null;
3475                         $email = null;
3476                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3477                         {
3478                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3479                         }
3480                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3481                         {
3482                                 $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]));
3483                         }
3484                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3485                         {
3486                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3487                         }
3488                         if ($name !== null || $email !== null || $uri !== null)
3489                         {
3490                                 $authors[] =& new $this->feed->author_class($name, $uri, $email);
3491                         }
3492                 }
3493                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3494                 {
3495                         $name = null;
3496                         $url = null;
3497                         $email = null;
3498                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3499                         {
3500                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3501                         }
3502                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3503                         {
3504                                 $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]));
3505                         }
3506                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3507                         {
3508                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3509                         }
3510                         if ($name !== null || $email !== null || $url !== null)
3511                         {
3512                                 $authors[] =& new $this->feed->author_class($name, $url, $email);
3513                         }
3514                 }
3515                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3516                 {
3517                         $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3518                 }
3519                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3520                 {
3521                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3522                 }
3523                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3524                 {
3525                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3526                 }
3527                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3528                 {
3529                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3530                 }
3531
3532                 if (!empty($authors))
3533                 {
3534                         return SimplePie_Misc::array_unique($authors);
3535                 }
3536                 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3537                 {
3538                         return $authors;
3539                 }
3540                 elseif ($authors = $this->feed->get_authors())
3541                 {
3542                         return $authors;
3543                 }
3544                 else
3545                 {
3546                         return null;
3547                 }
3548         }
3549
3550         function get_copyright()
3551         {
3552                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3553                 {
3554                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3555                 }
3556                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3557                 {
3558                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3559                 }
3560                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3561                 {
3562                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3563                 }
3564                 else
3565                 {
3566                         return null;
3567                 }
3568         }
3569
3570         function get_date($date_format = 'j F Y, g:i a')
3571         {
3572                 if (!isset($this->data['date']))
3573                 {
3574                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3575                         {
3576                                 $this->data['date']['raw'] = $return[0]['data'];
3577                         }
3578                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3579                         {
3580                                 $this->data['date']['raw'] = $return[0]['data'];
3581                         }
3582                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3583                         {
3584                                 $this->data['date']['raw'] = $return[0]['data'];
3585                         }
3586                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3587                         {
3588                                 $this->data['date']['raw'] = $return[0]['data'];
3589                         }
3590                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3591                         {
3592                                 $this->data['date']['raw'] = $return[0]['data'];
3593                         }
3594                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3595                         {
3596                                 $this->data['date']['raw'] = $return[0]['data'];
3597                         }
3598                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3599                         {
3600                                 $this->data['date']['raw'] = $return[0]['data'];
3601                         }
3602                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3603                         {
3604                                 $this->data['date']['raw'] = $return[0]['data'];
3605                         }
3606
3607                         if (!empty($this->data['date']['raw']))
3608                         {
3609                                 $parser = SimplePie_Parse_Date::get();
3610                                 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3611                         }
3612                         else
3613                         {
3614                                 $this->data['date'] = null;
3615                         }
3616                 }
3617                 if ($this->data['date'])
3618                 {
3619                         $date_format = (string) $date_format;
3620                         switch ($date_format)
3621                         {
3622                                 case '':
3623                                         return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3624
3625                                 case 'U':
3626                                         return $this->data['date']['parsed'];
3627
3628                                 default:
3629                                         return date($date_format, $this->data['date']['parsed']);
3630                         }
3631                 }
3632                 else
3633                 {
3634                         return null;
3635                 }
3636         }
3637
3638         function get_local_date($date_format = '%c')
3639         {
3640                 if (!$date_format)
3641                 {
3642                         return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3643                 }
3644                 elseif (($date = $this->get_date('U')) !== null)
3645                 {
3646                         return strftime($date_format, $date);
3647                 }
3648                 else
3649                 {
3650                         return null;
3651                 }
3652         }
3653
3654         function get_permalink()
3655         {
3656                 $link = $this->get_link();
3657                 $enclosure = $this->get_enclosure(0);
3658                 if ($link !== null)
3659                 {
3660                         return $link;
3661                 }
3662                 elseif ($enclosure !== null)
3663                 {
3664                         return $enclosure->get_link();
3665                 }
3666                 else
3667                 {
3668                         return null;
3669                 }
3670         }
3671
3672         function get_link($key = 0, $rel = 'alternate')
3673         {
3674                 $links = $this->get_links($rel);
3675                 if ($links[$key] !== null)
3676                 {
3677                         return $links[$key];
3678                 }
3679                 else
3680                 {
3681                         return null;
3682                 }
3683         }
3684
3685         function get_links($rel = 'alternate')
3686         {
3687                 if (!isset($this->data['links']))
3688                 {
3689                         $this->data['links'] = array();
3690                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3691                         {
3692                                 if (isset($link['attribs']['']['href']))
3693                                 {
3694                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3695                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3696
3697                                 }
3698                         }
3699                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3700                         {
3701                                 if (isset($link['attribs']['']['href']))
3702                                 {
3703                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3704                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3705                                 }
3706                         }
3707                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3708                         {
3709                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3710                         }
3711                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3712                         {
3713                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3714                         }
3715                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, '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_20, 'guid'))
3720                         {
3721                                 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3722                                 {
3723                                         $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3724                                 }
3725                         }
3726
3727                         $keys = array_keys($this->data['links']);
3728                         foreach ($keys as $key)
3729                         {
3730                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
3731                                 {
3732                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3733                                         {
3734                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3735                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3736                                         }
3737                                         else
3738                                         {
3739                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3740                                         }
3741                                 }
3742                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3743                                 {
3744                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3745                                 }
3746                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3747                         }
3748                 }
3749                 if (isset($this->data['links'][$rel]))
3750                 {
3751                         return $this->data['links'][$rel];
3752                 }
3753                 else
3754                 {
3755                         return null;
3756                 }
3757         }
3758
3759         /**
3760          * @todo Add ability to prefer one type of content over another (in a media group).
3761          */
3762         function get_enclosure($key = 0, $prefer = null)
3763         {
3764                 $enclosures = $this->get_enclosures();
3765                 if (isset($enclosures[$key]))
3766                 {
3767                         return $enclosures[$key];
3768                 }
3769                 else
3770                 {
3771                         return null;
3772                 }
3773         }
3774
3775         /**
3776          * Grabs all available enclosures (podcasts, etc.)
3777          *
3778          * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3779          *
3780          * 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.
3781          *
3782          * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3783          * @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).
3784          */
3785         function get_enclosures()
3786         {
3787                 if (!isset($this->data['enclosures']))
3788                 {
3789                         $this->data['enclosures'] = array();
3790
3791                         // Elements
3792                         $captions_parent = null;
3793                         $categories_parent = null;
3794                         $copyrights_parent = null;
3795                         $credits_parent = null;
3796                         $description_parent = null;
3797                         $duration_parent = null;
3798                         $hashes_parent = null;
3799                         $keywords_parent = null;
3800                         $player_parent = null;
3801                         $ratings_parent = null;
3802                         $restrictions_parent = null;
3803                         $thumbnails_parent = null;
3804                         $title_parent = null;
3805
3806                         // Let's do the channel and item-level ones first, and just re-use them if we need to.
3807                         $parent = $this->get_feed();
3808
3809                         // CAPTIONS
3810                         if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3811                         {
3812                                 foreach ($captions as $caption)
3813                                 {
3814                                         $caption_type = null;
3815                                         $caption_lang = null;
3816                                         $caption_startTime = null;
3817                                         $caption_endTime = null;
3818                                         $caption_text = null;
3819                                         if (isset($caption['attribs']['']['type']))
3820                                         {
3821                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3822                                         }
3823                                         if (isset($caption['attribs']['']['lang']))
3824                                         {
3825                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3826                                         }
3827                                         if (isset($caption['attribs']['']['start']))
3828                                         {
3829                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3830                                         }
3831                                         if (isset($caption['attribs']['']['end']))
3832                                         {
3833                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3834                                         }
3835                                         if (isset($caption['data']))
3836                                         {
3837                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3838                                         }
3839                                         $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3840                                 }
3841                         }
3842                         elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3843                         {
3844                                 foreach ($captions as $caption)
3845                                 {
3846                                         $caption_type = null;
3847                                         $caption_lang = null;
3848                                         $caption_startTime = null;
3849                                         $caption_endTime = null;
3850                                         $caption_text = null;
3851                                         if (isset($caption['attribs']['']['type']))
3852                                         {
3853                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3854                                         }
3855                                         if (isset($caption['attribs']['']['lang']))
3856                                         {
3857                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3858                                         }
3859                                         if (isset($caption['attribs']['']['start']))
3860                                         {
3861                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3862                                         }
3863                                         if (isset($caption['attribs']['']['end']))
3864                                         {
3865                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3866                                         }
3867                                         if (isset($caption['data']))
3868                                         {
3869                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3870                                         }
3871                                         $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3872                                 }
3873                         }
3874                         if (is_array($captions_parent))
3875                         {
3876                                 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3877                         }
3878
3879                         // CATEGORIES
3880                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3881                         {
3882                                 $term = null;
3883                                 $scheme = null;
3884                                 $label = null;
3885                                 if (isset($category['data']))
3886                                 {
3887                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3888                                 }
3889                                 if (isset($category['attribs']['']['scheme']))
3890                                 {
3891                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3892                                 }
3893                                 else
3894                                 {
3895                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3896                                 }
3897                                 if (isset($category['attribs']['']['label']))
3898                                 {
3899                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3900                                 }
3901                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3902                         }
3903                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3904                         {
3905                                 $term = null;
3906                                 $scheme = null;
3907                                 $label = null;
3908                                 if (isset($category['data']))
3909                                 {
3910                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3911                                 }
3912                                 if (isset($category['attribs']['']['scheme']))
3913                                 {
3914                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3915                                 }
3916                                 else
3917                                 {
3918                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3919                                 }
3920                                 if (isset($category['attribs']['']['label']))
3921                                 {
3922                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3923                                 }
3924                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3925                         }
3926                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3927                         {
3928                                 $term = null;
3929                                 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3930                                 $label = null;
3931                                 if (isset($category['attribs']['']['text']))
3932                                 {
3933                                         $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3934                                 }
3935                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3936
3937                                 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3938                                 {
3939                                         foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3940                                         {
3941                                                 if (isset($subcategory['attribs']['']['text']))
3942                                                 {
3943                                                         $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3944                                                 }
3945                                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3946                                         }
3947                                 }
3948                         }
3949                         if (is_array($categories_parent))
3950                         {
3951                                 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3952                         }
3953
3954                         // COPYRIGHT
3955                         if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3956                         {
3957                                 $copyright_url = null;
3958                                 $copyright_label = null;
3959                                 if (isset($copyright[0]['attribs']['']['url']))
3960                                 {
3961                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3962                                 }
3963                                 if (isset($copyright[0]['data']))
3964                                 {
3965                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3966                                 }
3967                                 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3968                         }
3969                         elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3970                         {
3971                                 $copyright_url = null;
3972                                 $copyright_label = null;
3973                                 if (isset($copyright[0]['attribs']['']['url']))
3974                                 {
3975                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3976                                 }
3977                                 if (isset($copyright[0]['data']))
3978                                 {
3979                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3980                                 }
3981                                 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3982                         }
3983
3984                         // CREDITS
3985                         if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3986                         {
3987                                 foreach ($credits as $credit)
3988                                 {
3989                                         $credit_role = null;
3990                                         $credit_scheme = null;
3991                                         $credit_name = null;
3992                                         if (isset($credit['attribs']['']['role']))
3993                                         {
3994                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3995                                         }
3996                                         if (isset($credit['attribs']['']['scheme']))
3997                                         {
3998                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3999                                         }
4000                                         else
4001                                         {
4002                                                 $credit_scheme = 'urn:ebu';
4003                                         }
4004                                         if (isset($credit['data']))
4005                                         {
4006                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4007                                         }
4008                                         $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4009                                 }
4010                         }
4011                         elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4012                         {
4013                                 foreach ($credits as $credit)
4014                                 {
4015                                         $credit_role = null;
4016                                         $credit_scheme = null;
4017                                         $credit_name = null;
4018                                         if (isset($credit['attribs']['']['role']))
4019                                         {
4020                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4021                                         }
4022                                         if (isset($credit['attribs']['']['scheme']))
4023                                         {
4024                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4025                                         }
4026                                         else
4027                                         {
4028                                                 $credit_scheme = 'urn:ebu';
4029                                         }
4030                                         if (isset($credit['data']))
4031                                         {
4032                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4033                                         }
4034                                         $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4035                                 }
4036                         }
4037                         if (is_array($credits_parent))
4038                         {
4039                                 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4040                         }
4041
4042                         // DESCRIPTION
4043                         if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4044                         {
4045                                 if (isset($description_parent[0]['data']))
4046                                 {
4047                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4048                                 }
4049                         }
4050                         elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4051                         {
4052                                 if (isset($description_parent[0]['data']))
4053                                 {
4054                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4055                                 }
4056                         }
4057
4058                         // DURATION
4059                         if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4060                         {
4061                                 $seconds = null;
4062                                 $minutes = null;
4063                                 $hours = null;
4064                                 if (isset($duration_parent[0]['data']))
4065                                 {
4066                                         $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4067                                         if (sizeof($temp) > 0)
4068                                         {
4069                                                 (int) $seconds = array_pop($temp);
4070                                         }
4071                                         if (sizeof($temp) > 0)
4072                                         {
4073                                                 (int) $minutes = array_pop($temp);
4074                                                 $seconds += $minutes * 60;
4075                                         }
4076                                         if (sizeof($temp) > 0)
4077                                         {
4078                                                 (int) $hours = array_pop($temp);
4079                                                 $seconds += $hours * 3600;
4080                                         }
4081                                         unset($temp);
4082                                         $duration_parent = $seconds;
4083                                 }
4084                         }
4085
4086                         // HASHES
4087                         if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4088                         {
4089                                 foreach ($hashes_iterator as $hash)
4090                                 {
4091                                         $value = null;
4092                                         $algo = null;
4093                                         if (isset($hash['data']))
4094                                         {
4095                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4096                                         }
4097                                         if (isset($hash['attribs']['']['algo']))
4098                                         {
4099                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4100                                         }
4101                                         else
4102                                         {
4103                                                 $algo = 'md5';
4104                                         }
4105                                         $hashes_parent[] = $algo.':'.$value;
4106                                 }
4107                         }
4108                         elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4109                         {
4110                                 foreach ($hashes_iterator as $hash)
4111                                 {
4112                                         $value = null;
4113                                         $algo = null;
4114                                         if (isset($hash['data']))
4115                                         {
4116                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4117                                         }
4118                                         if (isset($hash['attribs']['']['algo']))
4119                                         {
4120                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4121                                         }
4122                                         else
4123                                         {
4124                                                 $algo = 'md5';
4125                                         }
4126                                         $hashes_parent[] = $algo.':'.$value;
4127                                 }
4128                         }
4129                         if (is_array($hashes_parent))
4130                         {
4131                                 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4132                         }
4133
4134                         // KEYWORDS
4135                         if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4136                         {
4137                                 if (isset($keywords[0]['data']))
4138                                 {
4139                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4140                                         foreach ($temp as $word)
4141                                         {
4142                                                 $keywords_parent[] = trim($word);
4143                                         }
4144                                 }
4145                                 unset($temp);
4146                         }
4147                         elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4148                         {
4149                                 if (isset($keywords[0]['data']))
4150                                 {
4151                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4152                                         foreach ($temp as $word)
4153                                         {
4154                                                 $keywords_parent[] = trim($word);
4155                                         }
4156                                 }
4157                                 unset($temp);
4158                         }
4159                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4160                         {
4161                                 if (isset($keywords[0]['data']))
4162                                 {
4163                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4164                                         foreach ($temp as $word)
4165                                         {
4166                                                 $keywords_parent[] = trim($word);
4167                                         }
4168                                 }
4169                                 unset($temp);
4170                         }
4171                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4172                         {
4173                                 if (isset($keywords[0]['data']))
4174                                 {
4175                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4176                                         foreach ($temp as $word)
4177                                         {
4178                                                 $keywords_parent[] = trim($word);
4179                                         }
4180                                 }
4181                                 unset($temp);
4182                         }
4183                         if (is_array($keywords_parent))
4184                         {
4185                                 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4186                         }
4187
4188                         // PLAYER
4189                         if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4190                         {
4191                                 if (isset($player_parent[0]['attribs']['']['url']))
4192                                 {
4193                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4194                                 }
4195                         }
4196                         elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4197                         {
4198                                 if (isset($player_parent[0]['attribs']['']['url']))
4199                                 {
4200                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4201                                 }
4202                         }
4203
4204                         // RATINGS
4205                         if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4206                         {
4207                                 foreach ($ratings as $rating)
4208                                 {
4209                                         $rating_scheme = null;
4210                                         $rating_value = null;
4211                                         if (isset($rating['attribs']['']['scheme']))
4212                                         {
4213                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4214                                         }
4215                                         else
4216                                         {
4217                                                 $rating_scheme = 'urn:simple';
4218                                         }
4219                                         if (isset($rating['data']))
4220                                         {
4221                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4222                                         }
4223                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4224                                 }
4225                         }
4226                         elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4227                         {
4228                                 foreach ($ratings as $rating)
4229                                 {
4230                                         $rating_scheme = 'urn:itunes';
4231                                         $rating_value = null;
4232                                         if (isset($rating['data']))
4233                                         {
4234                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4235                                         }
4236                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4237                                 }
4238                         }
4239                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4240                         {
4241                                 foreach ($ratings as $rating)
4242                                 {
4243                                         $rating_scheme = null;
4244                                         $rating_value = null;
4245                                         if (isset($rating['attribs']['']['scheme']))
4246                                         {
4247                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4248                                         }
4249                                         else
4250                                         {
4251                                                 $rating_scheme = 'urn:simple';
4252                                         }
4253                                         if (isset($rating['data']))
4254                                         {
4255                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4256                                         }
4257                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4258                                 }
4259                         }
4260                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4261                         {
4262                                 foreach ($ratings as $rating)
4263                                 {
4264                                         $rating_scheme = 'urn:itunes';
4265                                         $rating_value = null;
4266                                         if (isset($rating['data']))
4267                                         {
4268                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4269                                         }
4270                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4271                                 }
4272                         }
4273                         if (is_array($ratings_parent))
4274                         {
4275                                 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4276                         }
4277
4278                         // RESTRICTIONS
4279                         if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4280                         {
4281                                 foreach ($restrictions as $restriction)
4282                                 {
4283                                         $restriction_relationship = null;
4284                                         $restriction_type = null;
4285                                         $restriction_value = null;
4286                                         if (isset($restriction['attribs']['']['relationship']))
4287                                         {
4288                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4289                                         }
4290                                         if (isset($restriction['attribs']['']['type']))
4291                                         {
4292                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4293                                         }
4294                                         if (isset($restriction['data']))
4295                                         {
4296                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4297                                         }
4298                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4299                                 }
4300                         }
4301                         elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4302                         {
4303                                 foreach ($restrictions as $restriction)
4304                                 {
4305                                         $restriction_relationship = 'allow';
4306                                         $restriction_type = null;
4307                                         $restriction_value = 'itunes';
4308                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4309                                         {
4310                                                 $restriction_relationship = 'deny';
4311                                         }
4312                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4313                                 }
4314                         }
4315                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4316                         {
4317                                 foreach ($restrictions as $restriction)
4318                                 {
4319                                         $restriction_relationship = null;
4320                                         $restriction_type = null;
4321                                         $restriction_value = null;
4322                                         if (isset($restriction['attribs']['']['relationship']))
4323                                         {
4324                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4325                                         }
4326                                         if (isset($restriction['attribs']['']['type']))
4327                                         {
4328                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4329                                         }
4330                                         if (isset($restriction['data']))
4331                                         {
4332                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4333                                         }
4334                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4335                                 }
4336                         }
4337                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4338                         {
4339                                 foreach ($restrictions as $restriction)
4340                                 {
4341                                         $restriction_relationship = 'allow';
4342                                         $restriction_type = null;
4343                                         $restriction_value = 'itunes';
4344                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4345                                         {
4346                                                 $restriction_relationship = 'deny';
4347                                         }
4348                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4349                                 }
4350                         }
4351                         if (is_array($restrictions_parent))
4352                         {
4353                                 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4354                         }
4355
4356                         // THUMBNAILS
4357                         if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4358                         {
4359                                 foreach ($thumbnails as $thumbnail)
4360                                 {
4361                                         if (isset($thumbnail['attribs']['']['url']))
4362                                         {
4363                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4364                                         }
4365                                 }
4366                         }
4367                         elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4368                         {
4369                                 foreach ($thumbnails as $thumbnail)
4370                                 {
4371                                         if (isset($thumbnail['attribs']['']['url']))
4372                                         {
4373                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4374                                         }
4375                                 }
4376                         }
4377
4378                         // TITLES
4379                         if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4380                         {
4381                                 if (isset($title_parent[0]['data']))
4382                                 {
4383                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4384                                 }
4385                         }
4386                         elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4387                         {
4388                                 if (isset($title_parent[0]['data']))
4389                                 {
4390                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4391                                 }
4392                         }
4393
4394                         // Clear the memory
4395                         unset($parent);
4396
4397                         // Attributes
4398                         $bitrate = null;
4399                         $channels = null;
4400                         $duration = null;
4401                         $expression = null;
4402                         $framerate = null;
4403                         $height = null;
4404                         $javascript = null;
4405                         $lang = null;
4406                         $length = null;
4407                         $medium = null;
4408                         $samplingrate = null;
4409                         $type = null;
4410                         $url = null;
4411                         $width = null;
4412
4413                         // Elements
4414                         $captions = null;
4415                         $categories = null;
4416                         $copyrights = null;
4417                         $credits = null;
4418                         $description = null;
4419                         $hashes = null;
4420                         $keywords = null;
4421                         $player = null;
4422                         $ratings = null;
4423                         $restrictions = null;
4424                         $thumbnails = null;
4425                         $title = null;
4426
4427                         // If we have media:group tags, loop through them.
4428                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4429                         {
4430                                 // If we have media:content tags, loop through them.
4431                                 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4432                                 {
4433                                         if (isset($content['attribs']['']['url']))
4434                                         {
4435                                                 // Attributes
4436                                                 $bitrate = null;
4437                                                 $channels = null;
4438                                                 $duration = null;
4439                                                 $expression = null;
4440                                                 $framerate = null;
4441                                                 $height = null;
4442                                                 $javascript = null;
4443                                                 $lang = null;
4444                                                 $length = null;
4445                                                 $medium = null;
4446                                                 $samplingrate = null;
4447                                                 $type = null;
4448                                                 $url = null;
4449                                                 $width = null;
4450
4451                                                 // Elements
4452                                                 $captions = null;
4453                                                 $categories = null;
4454                                                 $copyrights = null;
4455                                                 $credits = null;
4456                                                 $description = null;
4457                                                 $hashes = null;
4458                                                 $keywords = null;
4459                                                 $player = null;
4460                                                 $ratings = null;
4461                                                 $restrictions = null;
4462                                                 $thumbnails = null;
4463                                                 $title = null;
4464
4465                                                 // Start checking the attributes of media:content
4466                                                 if (isset($content['attribs']['']['bitrate']))
4467                                                 {
4468                                                         $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4469                                                 }
4470                                                 if (isset($content['attribs']['']['channels']))
4471                                                 {
4472                                                         $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4473                                                 }
4474                                                 if (isset($content['attribs']['']['duration']))
4475                                                 {
4476                                                         $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4477                                                 }
4478                                                 else
4479                                                 {
4480                                                         $duration = $duration_parent;
4481                                                 }
4482                                                 if (isset($content['attribs']['']['expression']))
4483                                                 {
4484                                                         $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4485                                                 }
4486                                                 if (isset($content['attribs']['']['framerate']))
4487                                                 {
4488                                                         $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4489                                                 }
4490                                                 if (isset($content['attribs']['']['height']))
4491                                                 {
4492                                                         $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4493                                                 }
4494                                                 if (isset($content['attribs']['']['lang']))
4495                                                 {
4496                                                         $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4497                                                 }
4498                                                 if (isset($content['attribs']['']['fileSize']))
4499                                                 {
4500                                                         $length = ceil($content['attribs']['']['fileSize']);
4501                                                 }
4502                                                 if (isset($content['attribs']['']['medium']))
4503                                                 {
4504                                                         $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4505                                                 }
4506                                                 if (isset($content['attribs']['']['samplingrate']))
4507                                                 {
4508                                                         $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4509                                                 }
4510                                                 if (isset($content['attribs']['']['type']))
4511                                                 {
4512                                                         $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4513                                                 }
4514                                                 if (isset($content['attribs']['']['width']))
4515                                                 {
4516                                                         $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4517                                                 }
4518                                                 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4519
4520                                                 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4521
4522                                                 // CAPTIONS
4523                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4524                                                 {
4525                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4526                                                         {
4527                                                                 $caption_type = null;
4528                                                                 $caption_lang = null;
4529                                                                 $caption_startTime = null;
4530                                                                 $caption_endTime = null;
4531                                                                 $caption_text = null;
4532                                                                 if (isset($caption['attribs']['']['type']))
4533                                                                 {
4534                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4535                                                                 }
4536                                                                 if (isset($caption['attribs']['']['lang']))
4537                                                                 {
4538                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4539                                                                 }
4540                                                                 if (isset($caption['attribs']['']['start']))
4541                                                                 {
4542                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4543                                                                 }
4544                                                                 if (isset($caption['attribs']['']['end']))
4545                                                                 {
4546                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4547                                                                 }
4548                                                                 if (isset($caption['data']))
4549                                                                 {
4550                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4551                                                                 }
4552                                                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4553                                                         }
4554                                                         if (is_array($captions))
4555                                                         {
4556                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
4557                                                         }
4558                                                 }
4559                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4560                                                 {
4561                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4562                                                         {
4563                                                                 $caption_type = null;
4564                                                                 $caption_lang = null;
4565                                                                 $caption_startTime = null;
4566                                                                 $caption_endTime = null;
4567                                                                 $caption_text = null;
4568                                                                 if (isset($caption['attribs']['']['type']))
4569                                                                 {
4570                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4571                                                                 }
4572                                                                 if (isset($caption['attribs']['']['lang']))
4573                                                                 {
4574                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4575                                                                 }
4576                                                                 if (isset($caption['attribs']['']['start']))
4577                                                                 {
4578                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4579                                                                 }
4580                                                                 if (isset($caption['attribs']['']['end']))
4581                                                                 {
4582                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4583                                                                 }
4584                                                                 if (isset($caption['data']))
4585                                                                 {
4586                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4587                                                                 }
4588                                                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4589                                                         }
4590                                                         if (is_array($captions))
4591                                                         {
4592                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
4593                                                         }
4594                                                 }
4595                                                 else
4596                                                 {
4597                                                         $captions = $captions_parent;
4598                                                 }
4599
4600                                                 // CATEGORIES
4601                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4602                                                 {
4603                                                         foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4604                                                         {
4605                                                                 $term = null;
4606                                                                 $scheme = null;
4607                                                                 $label = null;
4608                                                                 if (isset($category['data']))
4609                                                                 {
4610                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4611                                                                 }
4612                                                                 if (isset($category['attribs']['']['scheme']))
4613                                                                 {
4614                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4615                                                                 }
4616                                                                 else
4617                                                                 {
4618                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
4619                                                                 }
4620                                                                 if (isset($category['attribs']['']['label']))
4621                                                                 {
4622                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4623                                                                 }
4624                                                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4625                                                         }
4626                                                 }
4627                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4628                                                 {
4629                                                         foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4630                                                         {
4631                                                                 $term = null;
4632                                                                 $scheme = null;
4633                                                                 $label = null;
4634                                                                 if (isset($category['data']))
4635                                                                 {
4636                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4637                                                                 }
4638                                                                 if (isset($category['attribs']['']['scheme']))
4639                                                                 {
4640                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4641                                                                 }
4642                                                                 else
4643                                                                 {
4644                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
4645                                                                 }
4646                                                                 if (isset($category['attribs']['']['label']))
4647                                                                 {
4648                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4649                                                                 }
4650                                                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4651                                                         }
4652                                                 }
4653                                                 if (is_array($categories) && is_array($categories_parent))
4654                                                 {
4655                                                         $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4656                                                 }
4657                                                 elseif (is_array($categories))
4658                                                 {
4659                                                         $categories = array_values(SimplePie_Misc::array_unique($categories));
4660                                                 }
4661                                                 elseif (is_array($categories_parent))
4662                                                 {
4663                                                         $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4664                                                 }
4665
4666                                                 // COPYRIGHTS
4667                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4668                                                 {
4669                                                         $copyright_url = null;
4670                                                         $copyright_label = null;
4671                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4672                                                         {
4673                                                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4674                                                         }
4675                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4676                                                         {
4677                                                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4678                                                         }
4679                                                         $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4680                                                 }
4681                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4682                                                 {
4683                                                         $copyright_url = null;
4684                                                         $copyright_label = null;
4685                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4686                                                         {
4687                                                                 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4688                                                         }
4689                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4690                                                         {
4691                                                                 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4692                                                         }
4693                                                         $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4694                                                 }
4695                                                 else
4696                                                 {
4697                                                         $copyrights = $copyrights_parent;
4698                                                 }
4699
4700                                                 // CREDITS
4701                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4702                                                 {
4703                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4704                                                         {
4705                                                                 $credit_role = null;
4706                                                                 $credit_scheme = null;
4707                                                                 $credit_name = null;
4708                                                                 if (isset($credit['attribs']['']['role']))
4709                                                                 {
4710                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4711                                                                 }
4712                                                                 if (isset($credit['attribs']['']['scheme']))
4713                                                                 {
4714                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4715                                                                 }
4716                                                                 else
4717                                                                 {
4718                                                                         $credit_scheme = 'urn:ebu';
4719                                                                 }
4720                                                                 if (isset($credit['data']))
4721                                                                 {
4722                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4723                                                                 }
4724                                                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4725                                                         }
4726                                                         if (is_array($credits))
4727                                                         {
4728                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
4729                                                         }
4730                                                 }
4731                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4732                                                 {
4733                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4734                                                         {
4735                                                                 $credit_role = null;
4736                                                                 $credit_scheme = null;
4737                                                                 $credit_name = null;
4738                                                                 if (isset($credit['attribs']['']['role']))
4739                                                                 {
4740                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4741                                                                 }
4742                                                                 if (isset($credit['attribs']['']['scheme']))
4743                                                                 {
4744                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4745                                                                 }
4746                                                                 else
4747                                                                 {
4748                                                                         $credit_scheme = 'urn:ebu';
4749                                                                 }
4750                                                                 if (isset($credit['data']))
4751                                                                 {
4752                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4753                                                                 }
4754                                                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4755                                                         }
4756                                                         if (is_array($credits))
4757                                                         {
4758                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
4759                                                         }
4760                                                 }
4761                                                 else
4762                                                 {
4763                                                         $credits = $credits_parent;
4764                                                 }
4765
4766                                                 // DESCRIPTION
4767                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4768                                                 {
4769                                                         $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4770                                                 }
4771                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4772                                                 {
4773                                                         $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4774                                                 }
4775                                                 else
4776                                                 {
4777                                                         $description = $description_parent;
4778                                                 }
4779
4780                                                 // HASHES
4781                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4782                                                 {
4783                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4784                                                         {
4785                                                                 $value = null;
4786                                                                 $algo = null;
4787                                                                 if (isset($hash['data']))
4788                                                                 {
4789                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4790                                                                 }
4791                                                                 if (isset($hash['attribs']['']['algo']))
4792                                                                 {
4793                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4794                                                                 }
4795                                                                 else
4796                                                                 {
4797                                                                         $algo = 'md5';
4798                                                                 }
4799                                                                 $hashes[] = $algo.':'.$value;
4800                                                         }
4801                                                         if (is_array($hashes))
4802                                                         {
4803                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4804                                                         }
4805                                                 }
4806                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4807                                                 {
4808                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4809                                                         {
4810                                                                 $value = null;
4811                                                                 $algo = null;
4812                                                                 if (isset($hash['data']))
4813                                                                 {
4814                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4815                                                                 }
4816                                                                 if (isset($hash['attribs']['']['algo']))
4817                                                                 {
4818                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4819                                                                 }
4820                                                                 else
4821                                                                 {
4822                                                                         $algo = 'md5';
4823                                                                 }
4824                                                                 $hashes[] = $algo.':'.$value;
4825                                                         }
4826                                                         if (is_array($hashes))
4827                                                         {
4828                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4829                                                         }
4830                                                 }
4831                                                 else
4832                                                 {
4833                                                         $hashes = $hashes_parent;
4834                                                 }
4835
4836                                                 // KEYWORDS
4837                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4838                                                 {
4839                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4840                                                         {
4841                                                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4842                                                                 foreach ($temp as $word)
4843                                                                 {
4844                                                                         $keywords[] = trim($word);
4845                                                                 }
4846                                                                 unset($temp);
4847                                                         }
4848                                                         if (is_array($keywords))
4849                                                         {
4850                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4851                                                         }
4852                                                 }
4853                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4854                                                 {
4855                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4856                                                         {
4857                                                                 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4858                                                                 foreach ($temp as $word)
4859                                                                 {
4860                                                                         $keywords[] = trim($word);
4861                                                                 }
4862                                                                 unset($temp);
4863                                                         }
4864                                                         if (is_array($keywords))
4865                                                         {
4866                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4867                                                         }
4868                                                 }
4869                                                 else
4870                                                 {
4871                                                         $keywords = $keywords_parent;
4872                                                 }
4873
4874                                                 // PLAYER
4875                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4876                                                 {
4877                                                         $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4878                                                 }
4879                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4880                                                 {
4881                                                         $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4882                                                 }
4883                                                 else
4884                                                 {
4885                                                         $player = $player_parent;
4886                                                 }
4887
4888                                                 // RATINGS
4889                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4890                                                 {
4891                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4892                                                         {
4893                                                                 $rating_scheme = null;
4894                                                                 $rating_value = null;
4895                                                                 if (isset($rating['attribs']['']['scheme']))
4896                                                                 {
4897                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4898                                                                 }
4899                                                                 else
4900                                                                 {
4901                                                                         $rating_scheme = 'urn:simple';
4902                                                                 }
4903                                                                 if (isset($rating['data']))
4904                                                                 {
4905                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4906                                                                 }
4907                                                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4908                                                         }
4909                                                         if (is_array($ratings))
4910                                                         {
4911                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4912                                                         }
4913                                                 }
4914                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4915                                                 {
4916                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4917                                                         {
4918                                                                 $rating_scheme = null;
4919                                                                 $rating_value = null;
4920                                                                 if (isset($rating['attribs']['']['scheme']))
4921                                                                 {
4922                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4923                                                                 }
4924                                                                 else
4925                                                                 {
4926                                                                         $rating_scheme = 'urn:simple';
4927                                                                 }
4928                                                                 if (isset($rating['data']))
4929                                                                 {
4930                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4931                                                                 }
4932                                                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4933                                                         }
4934                                                         if (is_array($ratings))
4935                                                         {
4936                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4937                                                         }
4938                                                 }
4939                                                 else
4940                                                 {
4941                                                         $ratings = $ratings_parent;
4942                                                 }
4943
4944                                                 // RESTRICTIONS
4945                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4946                                                 {
4947                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4948                                                         {
4949                                                                 $restriction_relationship = null;
4950                                                                 $restriction_type = null;
4951                                                                 $restriction_value = null;
4952                                                                 if (isset($restriction['attribs']['']['relationship']))
4953                                                                 {
4954                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4955                                                                 }
4956                                                                 if (isset($restriction['attribs']['']['type']))
4957                                                                 {
4958                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4959                                                                 }
4960                                                                 if (isset($restriction['data']))
4961                                                                 {
4962                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4963                                                                 }
4964                                                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4965                                                         }
4966                                                         if (is_array($restrictions))
4967                                                         {
4968                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4969                                                         }
4970                                                 }
4971                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4972                                                 {
4973                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4974                                                         {
4975                                                                 $restriction_relationship = null;
4976                                                                 $restriction_type = null;
4977                                                                 $restriction_value = null;
4978                                                                 if (isset($restriction['attribs']['']['relationship']))
4979                                                                 {
4980                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4981                                                                 }
4982                                                                 if (isset($restriction['attribs']['']['type']))
4983                                                                 {
4984                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4985                                                                 }
4986                                                                 if (isset($restriction['data']))
4987                                                                 {
4988                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4989                                                                 }
4990                                                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4991                                                         }
4992                                                         if (is_array($restrictions))
4993                                                         {
4994                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4995                                                         }
4996                                                 }
4997                                                 else
4998                                                 {
4999                                                         $restrictions = $restrictions_parent;
5000                                                 }
5001
5002                                                 // THUMBNAILS
5003                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5004                                                 {
5005                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5006                                                         {
5007                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5008                                                         }
5009                                                         if (is_array($thumbnails))
5010                                                         {
5011                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5012                                                         }
5013                                                 }
5014                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5015                                                 {
5016                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5017                                                         {
5018                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5019                                                         }
5020                                                         if (is_array($thumbnails))
5021                                                         {
5022                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5023                                                         }
5024                                                 }
5025                                                 else
5026                                                 {
5027                                                         $thumbnails = $thumbnails_parent;
5028                                                 }
5029
5030                                                 // TITLES
5031                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5032                                                 {
5033                                                         $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5034                                                 }
5035                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5036                                                 {
5037                                                         $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5038                                                 }
5039                                                 else
5040                                                 {
5041                                                         $title = $title_parent;
5042                                                 }
5043
5044                                                 $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);
5045                                         }
5046                                 }
5047                         }
5048
5049                         // If we have standalone media:content tags, loop through them.
5050                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5051                         {
5052                                 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5053                                 {
5054                                         if (isset($content['attribs']['']['url']))
5055                                         {
5056                                                 // Attributes
5057                                                 $bitrate = null;
5058                                                 $channels = null;
5059                                                 $duration = null;
5060                                                 $expression = null;
5061                                                 $framerate = null;
5062                                                 $height = null;
5063                                                 $javascript = null;
5064                                                 $lang = null;
5065                                                 $length = null;
5066                                                 $medium = null;
5067                                                 $samplingrate = null;
5068                                                 $type = null;
5069                                                 $url = null;
5070                                                 $width = null;
5071
5072                                                 // Elements
5073                                                 $captions = null;
5074                                                 $categories = null;
5075                                                 $copyrights = null;
5076                                                 $credits = null;
5077                                                 $description = null;
5078                                                 $hashes = null;
5079                                                 $keywords = null;
5080                                                 $player = null;
5081                                                 $ratings = null;
5082                                                 $restrictions = null;
5083                                                 $thumbnails = null;
5084                                                 $title = null;
5085
5086                                                 // Start checking the attributes of media:content
5087                                                 if (isset($content['attribs']['']['bitrate']))
5088                                                 {
5089                                                         $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5090                                                 }
5091                                                 if (isset($content['attribs']['']['channels']))
5092                                                 {
5093                                                         $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5094                                                 }
5095                                                 if (isset($content['attribs']['']['duration']))
5096                                                 {
5097                                                         $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5098                                                 }
5099                                                 else
5100                                                 {
5101                                                         $duration = $duration_parent;
5102                                                 }
5103                                                 if (isset($content['attribs']['']['expression']))
5104                                                 {
5105                                                         $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5106                                                 }
5107                                                 if (isset($content['attribs']['']['framerate']))
5108                                                 {
5109                                                         $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5110                                                 }
5111                                                 if (isset($content['attribs']['']['height']))
5112                                                 {
5113                                                         $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5114                                                 }
5115                                                 if (isset($content['attribs']['']['lang']))
5116                                                 {
5117                                                         $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5118                                                 }
5119                                                 if (isset($content['attribs']['']['fileSize']))
5120                                                 {
5121                                                         $length = ceil($content['attribs']['']['fileSize']);
5122                                                 }
5123                                                 if (isset($content['attribs']['']['medium']))
5124                                                 {
5125                                                         $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5126                                                 }
5127                                                 if (isset($content['attribs']['']['samplingrate']))
5128                                                 {
5129                                                         $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5130                                                 }
5131                                                 if (isset($content['attribs']['']['type']))
5132                                                 {
5133                                                         $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5134                                                 }
5135                                                 if (isset($content['attribs']['']['width']))
5136                                                 {
5137                                                         $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5138                                                 }
5139                                                 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5140
5141                                                 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5142
5143                                                 // CAPTIONS
5144                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5145                                                 {
5146                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5147                                                         {
5148                                                                 $caption_type = null;
5149                                                                 $caption_lang = null;
5150                                                                 $caption_startTime = null;
5151                                                                 $caption_endTime = null;
5152                                                                 $caption_text = null;
5153                                                                 if (isset($caption['attribs']['']['type']))
5154                                                                 {
5155                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5156                                                                 }
5157                                                                 if (isset($caption['attribs']['']['lang']))
5158                                                                 {
5159                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5160                                                                 }
5161                                                                 if (isset($caption['attribs']['']['start']))
5162                                                                 {
5163                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5164                                                                 }
5165                                                                 if (isset($caption['attribs']['']['end']))
5166                                                                 {
5167                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5168                                                                 }
5169                                                                 if (isset($caption['data']))
5170                                                                 {
5171                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5172                                                                 }
5173                                                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5174                                                         }
5175                                                         if (is_array($captions))
5176                                                         {
5177                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
5178                                                         }
5179                                                 }
5180                                                 else
5181                                                 {
5182                                                         $captions = $captions_parent;
5183                                                 }
5184
5185                                                 // CATEGORIES
5186                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5187                                                 {
5188                                                         foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5189                                                         {
5190                                                                 $term = null;
5191                                                                 $scheme = null;
5192                                                                 $label = null;
5193                                                                 if (isset($category['data']))
5194                                                                 {
5195                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5196                                                                 }
5197                                                                 if (isset($category['attribs']['']['scheme']))
5198                                                                 {
5199                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5200                                                                 }
5201                                                                 else
5202                                                                 {
5203                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
5204                                                                 }
5205                                                                 if (isset($category['attribs']['']['label']))
5206                                                                 {
5207                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5208                                                                 }
5209                                                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
5210                                                         }
5211                                                 }
5212                                                 if (is_array($categories) && is_array($categories_parent))
5213                                                 {
5214                                                         $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5215                                                 }
5216                                                 elseif (is_array($categories))
5217                                                 {
5218                                                         $categories = array_values(SimplePie_Misc::array_unique($categories));
5219                                                 }
5220                                                 elseif (is_array($categories_parent))
5221                                                 {
5222                                                         $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5223                                                 }
5224                                                 else
5225                                                 {
5226                                                         $categories = null;
5227                                                 }
5228
5229                                                 // COPYRIGHTS
5230                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5231                                                 {
5232                                                         $copyright_url = null;
5233                                                         $copyright_label = null;
5234                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5235                                                         {
5236                                                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5237                                                         }
5238                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5239                                                         {
5240                                                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5241                                                         }
5242                                                         $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
5243                                                 }
5244                                                 else
5245                                                 {
5246                                                         $copyrights = $copyrights_parent;
5247                                                 }
5248
5249                                                 // CREDITS
5250                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5251                                                 {
5252                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5253                                                         {
5254                                                                 $credit_role = null;
5255                                                                 $credit_scheme = null;
5256                                                                 $credit_name = null;
5257                                                                 if (isset($credit['attribs']['']['role']))
5258                                                                 {
5259                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5260                                                                 }
5261                                                                 if (isset($credit['attribs']['']['scheme']))
5262                                                                 {
5263                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5264                                                                 }
5265                                                                 else
5266                                                                 {
5267                                                                         $credit_scheme = 'urn:ebu';
5268                                                                 }
5269                                                                 if (isset($credit['data']))
5270                                                                 {
5271                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5272                                                                 }
5273                                                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5274                                                         }
5275                                                         if (is_array($credits))
5276                                                         {
5277                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
5278                                                         }
5279                                                 }
5280                                                 else
5281                                                 {
5282                                                         $credits = $credits_parent;
5283                                                 }
5284
5285                                                 // DESCRIPTION
5286                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5287                                                 {
5288                                                         $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5289                                                 }
5290                                                 else
5291                                                 {
5292                                                         $description = $description_parent;
5293                                                 }
5294
5295                                                 // HASHES
5296                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5297                                                 {
5298                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5299                                                         {
5300                                                                 $value = null;
5301                                                                 $algo = null;
5302                                                                 if (isset($hash['data']))
5303                                                                 {
5304                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5305                                                                 }
5306                                                                 if (isset($hash['attribs']['']['algo']))
5307                                                                 {
5308                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5309                                                                 }
5310                                                                 else
5311                                                                 {
5312                                                                         $algo = 'md5';
5313                                                                 }
5314                                                                 $hashes[] = $algo.':'.$value;
5315                                                         }
5316                                                         if (is_array($hashes))
5317                                                         {
5318                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5319                                                         }
5320                                                 }
5321                                                 else
5322                                                 {
5323                                                         $hashes = $hashes_parent;
5324                                                 }
5325
5326                                                 // KEYWORDS
5327                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5328                                                 {
5329                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5330                                                         {
5331                                                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5332                                                                 foreach ($temp as $word)
5333                                                                 {
5334                                                                         $keywords[] = trim($word);
5335                                                                 }
5336                                                                 unset($temp);
5337                                                         }
5338                                                         if (is_array($keywords))
5339                                                         {
5340                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5341                                                         }
5342                                                 }
5343                                                 else
5344                                                 {
5345                                                         $keywords = $keywords_parent;
5346                                                 }
5347
5348                                                 // PLAYER
5349                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5350                                                 {
5351                                                         $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5352                                                 }
5353                                                 else
5354                                                 {
5355                                                         $player = $player_parent;
5356                                                 }
5357
5358                                                 // RATINGS
5359                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5360                                                 {
5361                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5362                                                         {
5363                                                                 $rating_scheme = null;
5364                                                                 $rating_value = null;
5365                                                                 if (isset($rating['attribs']['']['scheme']))
5366                                                                 {
5367                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5368                                                                 }
5369                                                                 else
5370                                                                 {
5371                                                                         $rating_scheme = 'urn:simple';
5372                                                                 }
5373                                                                 if (isset($rating['data']))
5374                                                                 {
5375                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5376                                                                 }
5377                                                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
5378                                                         }
5379                                                         if (is_array($ratings))
5380                                                         {
5381                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5382                                                         }
5383                                                 }
5384                                                 else
5385                                                 {
5386                                                         $ratings = $ratings_parent;
5387                                                 }
5388
5389                                                 // RESTRICTIONS
5390                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5391                                                 {
5392                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5393                                                         {
5394                                                                 $restriction_relationship = null;
5395                                                                 $restriction_type = null;
5396                                                                 $restriction_value = null;
5397                                                                 if (isset($restriction['attribs']['']['relationship']))
5398                                                                 {
5399                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5400                                                                 }
5401                                                                 if (isset($restriction['attribs']['']['type']))
5402                                                                 {
5403                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5404                                                                 }
5405                                                                 if (isset($restriction['data']))
5406                                                                 {
5407                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5408                                                                 }
5409                                                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5410                                                         }
5411                                                         if (is_array($restrictions))
5412                                                         {
5413                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5414                                                         }
5415                                                 }
5416                                                 else
5417                                                 {
5418                                                         $restrictions = $restrictions_parent;
5419                                                 }
5420
5421                                                 // THUMBNAILS
5422                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5423                                                 {
5424                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5425                                                         {
5426                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5427                                                         }
5428                                                         if (is_array($thumbnails))
5429                                                         {
5430                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5431                                                         }
5432                                                 }
5433                                                 else
5434                                                 {
5435                                                         $thumbnails = $thumbnails_parent;
5436                                                 }
5437
5438                                                 // TITLES
5439                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5440                                                 {
5441                                                         $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5442                                                 }
5443                                                 else
5444                                                 {
5445                                                         $title = $title_parent;
5446                                                 }
5447
5448                                                 $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);
5449                                         }
5450                                 }
5451                         }
5452
5453                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5454                         {
5455                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5456                                 {
5457                                         // Attributes
5458                                         $bitrate = null;
5459                                         $channels = null;
5460                                         $duration = null;
5461                                         $expression = null;
5462                                         $framerate = null;
5463                                         $height = null;
5464                                         $javascript = null;
5465                                         $lang = null;
5466                                         $length = null;
5467                                         $medium = null;
5468                                         $samplingrate = null;
5469                                         $type = null;
5470                                         $url = null;
5471                                         $width = null;
5472
5473                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5474                                         if (isset($link['attribs']['']['type']))
5475                                         {
5476                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5477                                         }
5478                                         if (isset($link['attribs']['']['length']))
5479                                         {
5480                                                 $length = ceil($link['attribs']['']['length']);
5481                                         }
5482
5483                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5484                                         $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);
5485                                 }
5486                         }
5487
5488                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5489                         {
5490                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5491                                 {
5492                                         // Attributes
5493                                         $bitrate = null;
5494                                         $channels = null;
5495                                         $duration = null;
5496                                         $expression = null;
5497                                         $framerate = null;
5498                                         $height = null;
5499                                         $javascript = null;
5500                                         $lang = null;
5501                                         $length = null;
5502                                         $medium = null;
5503                                         $samplingrate = null;
5504                                         $type = null;
5505                                         $url = null;
5506                                         $width = null;
5507
5508                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5509                                         if (isset($link['attribs']['']['type']))
5510                                         {
5511                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5512                                         }
5513                                         if (isset($link['attribs']['']['length']))
5514                                         {
5515                                                 $length = ceil($link['attribs']['']['length']);
5516                                         }
5517
5518                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5519                                         $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);
5520                                 }
5521                         }
5522
5523                         if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5524                         {
5525                                 if (isset($enclosure[0]['attribs']['']['url']))
5526                                 {
5527                                         // Attributes
5528                                         $bitrate = null;
5529                                         $channels = null;
5530                                         $duration = null;
5531                                         $expression = null;
5532                                         $framerate = null;
5533                                         $height = null;
5534                                         $javascript = null;
5535                                         $lang = null;
5536                                         $length = null;
5537                                         $medium = null;
5538                                         $samplingrate = null;
5539                                         $type = null;
5540                                         $url = null;
5541                                         $width = null;
5542
5543                                         $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5544                                         if (isset($enclosure[0]['attribs']['']['type']))
5545                                         {
5546                                                 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5547                                         }
5548                                         if (isset($enclosure[0]['attribs']['']['length']))
5549                                         {
5550                                                 $length = ceil($enclosure[0]['attribs']['']['length']);
5551                                         }
5552
5553                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5554                                         $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);
5555                                 }
5556                         }
5557
5558                         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))
5559                         {
5560                                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5561                                 $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);
5562                         }
5563
5564                         $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5565                 }
5566                 if (!empty($this->data['enclosures']))
5567                 {
5568                         return $this->data['enclosures'];
5569                 }
5570                 else
5571                 {
5572                         return null;
5573                 }
5574         }
5575
5576         function get_latitude()
5577         {
5578                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5579                 {
5580                         return (float) $return[0]['data'];
5581                 }
5582                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5583                 {
5584                         return (float) $match[1];
5585                 }
5586                 else
5587                 {
5588                         return null;
5589                 }
5590         }
5591
5592         function get_longitude()
5593         {
5594                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5595                 {
5596                         return (float) $return[0]['data'];
5597                 }
5598                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5599                 {
5600                         return (float) $return[0]['data'];
5601                 }
5602                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5603                 {
5604                         return (float) $match[2];
5605                 }
5606                 else
5607                 {
5608                         return null;
5609                 }
5610         }
5611
5612         function get_source()
5613         {
5614                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5615                 {
5616                         return new $this->feed->source_class($this, $return[0]);
5617                 }
5618                 else
5619                 {
5620                         return null;
5621                 }
5622         }
5623
5624         /**
5625          * Creates the add_to_* methods' return data
5626          *
5627          * @access private
5628          * @param string $item_url String to prefix to the item permalink
5629          * @param string $title_url String to prefix to the item title
5630          * (and suffix to the item permalink)
5631          * @return mixed URL if feed exists, false otherwise
5632          */
5633         function add_to_service($item_url, $title_url = null, $summary_url = null)
5634         {
5635                 if ($this->get_permalink() !== null)
5636                 {
5637                         $return = $item_url . rawurlencode($this->get_permalink());
5638                         if ($title_url !== null && $this->get_title() !== null)
5639                         {
5640                                 $return .= $title_url . rawurlencode($this->get_title());
5641                         }
5642                         if ($summary_url !== null && $this->get_description() !== null)
5643                         {
5644                                 $return .= $summary_url . rawurlencode($this->get_description());
5645                         }
5646                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5647                 }
5648                 else
5649                 {
5650                         return null;
5651                 }
5652         }
5653
5654         function add_to_blinklist()
5655         {
5656                 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5657         }
5658
5659         function add_to_blogmarks()
5660         {
5661                 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5662         }
5663
5664         function add_to_delicious()
5665         {
5666                 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5667         }
5668
5669         function add_to_digg()
5670         {
5671                 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5672         }
5673
5674         function add_to_furl()
5675         {
5676                 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5677         }
5678
5679         function add_to_magnolia()
5680         {
5681                 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5682         }
5683
5684         function add_to_myweb20()
5685         {
5686                 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5687         }
5688
5689         function add_to_newsvine()
5690         {
5691                 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5692         }
5693
5694         function add_to_reddit()
5695         {
5696                 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5697         }
5698
5699         function add_to_segnalo()
5700         {
5701                 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5702         }
5703
5704         function add_to_simpy()
5705         {
5706                 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5707         }
5708
5709         function add_to_spurl()
5710         {
5711                 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5712         }
5713
5714         function add_to_wists()
5715         {
5716                 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5717         }
5718
5719         function search_technorati()
5720         {
5721                 return $this->add_to_service('http://www.technorati.com/search/');
5722         }
5723 }
5724
5725 class SimplePie_Source
5726 {
5727         var $item;
5728         var $data = array();
5729
5730         function SimplePie_Source($item, $data)
5731         {
5732                 $this->item = $item;
5733                 $this->data = $data;
5734         }
5735
5736         function __toString()
5737         {
5738                 return md5(serialize($this->data));
5739         }
5740
5741         function get_source_tags($namespace, $tag)
5742         {
5743                 if (isset($this->data['child'][$namespace][$tag]))
5744                 {
5745                         return $this->data['child'][$namespace][$tag];
5746                 }
5747                 else
5748                 {
5749                         return null;
5750                 }
5751         }
5752
5753         function get_base($element = array())
5754         {
5755                 return $this->item->get_base($element);
5756         }
5757
5758         function sanitize($data, $type, $base = '')
5759         {
5760                 return $this->item->sanitize($data, $type, $base);
5761         }
5762
5763         function get_item()
5764         {
5765                 return $this->item;
5766         }
5767
5768         function get_title()
5769         {
5770                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5771                 {
5772                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5773                 }
5774                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5775                 {
5776                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5777                 }
5778                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5779                 {
5780                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5781                 }
5782                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5783                 {
5784                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5785                 }
5786                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5787                 {
5788                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5789                 }
5790                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5791                 {
5792                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5793                 }
5794                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5795                 {
5796                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5797                 }
5798                 else
5799                 {
5800                         return null;
5801                 }
5802         }
5803
5804         function get_category($key = 0)
5805         {
5806                 $categories = $this->get_categories();
5807                 if (isset($categories[$key]))
5808                 {
5809                         return $categories[$key];
5810                 }
5811                 else
5812                 {
5813                         return null;
5814                 }
5815         }
5816
5817         function get_categories()
5818         {
5819                 $categories = array();
5820
5821                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5822                 {
5823                         $term = null;
5824                         $scheme = null;
5825                         $label = null;
5826                         if (isset($category['attribs']['']['term']))
5827                         {
5828                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5829                         }
5830                         if (isset($category['attribs']['']['scheme']))
5831                         {
5832                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5833                         }
5834                         if (isset($category['attribs']['']['label']))
5835                         {
5836                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5837                         }
5838                         $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
5839                 }
5840                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5841                 {
5842                         // This is really the label, but keep this as the term also for BC.
5843                         // Label will also work on retrieving because that falls back to term.
5844                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5845                         if (isset($category['attribs']['']['domain']))
5846                         {
5847                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5848                         }
5849                         else
5850                         {
5851                                 $scheme = null;
5852                         }
5853                         $categories[] =& new $this->item->feed->category_class($term, $scheme, null);
5854                 }
5855                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5856                 {
5857                         $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5858                 }
5859                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5860                 {
5861                         $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5862                 }
5863
5864                 if (!empty($categories))
5865                 {
5866                         return SimplePie_Misc::array_unique($categories);
5867                 }
5868                 else
5869                 {
5870                         return null;
5871                 }
5872         }
5873
5874         function get_author($key = 0)
5875         {
5876                 $authors = $this->get_authors();
5877                 if (isset($authors[$key]))
5878                 {
5879                         return $authors[$key];
5880                 }
5881                 else
5882                 {
5883                         return null;
5884                 }
5885         }
5886
5887         function get_authors()
5888         {
5889                 $authors = array();
5890                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5891                 {
5892                         $name = null;
5893                         $uri = null;
5894                         $email = null;
5895                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5896                         {
5897                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5898                         }
5899                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5900                         {
5901                                 $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]));
5902                         }
5903                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5904                         {
5905                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5906                         }
5907                         if ($name !== null || $email !== null || $uri !== null)
5908                         {
5909                                 $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
5910                         }
5911                 }
5912                 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5913                 {
5914                         $name = null;
5915                         $url = null;
5916                         $email = null;
5917                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5918                         {
5919                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5920                         }
5921                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5922                         {
5923                                 $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]));
5924                         }
5925                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5926                         {
5927                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5928                         }
5929                         if ($name !== null || $email !== null || $url !== null)
5930                         {
5931                                 $authors[] =& new $this->item->feed->author_class($name, $url, $email);
5932                         }
5933                 }
5934                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5935                 {
5936                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5937                 }
5938                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5939                 {
5940                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5941                 }
5942                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5943                 {
5944                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5945                 }
5946
5947                 if (!empty($authors))
5948                 {
5949                         return SimplePie_Misc::array_unique($authors);
5950                 }
5951                 else
5952                 {
5953                         return null;
5954                 }
5955         }
5956
5957         function get_contributor($key = 0)
5958         {
5959                 $contributors = $this->get_contributors();
5960                 if (isset($contributors[$key]))
5961                 {
5962                         return $contributors[$key];
5963                 }
5964                 else
5965                 {
5966                         return null;
5967                 }
5968         }
5969
5970         function get_contributors()
5971         {
5972                 $contributors = array();
5973                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5974                 {
5975                         $name = null;
5976                         $uri = null;
5977                         $email = null;
5978                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5979                         {
5980                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5981                         }
5982                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5983                         {
5984                                 $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]));
5985                         }
5986                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5987                         {
5988                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5989                         }
5990                         if ($name !== null || $email !== null || $uri !== null)
5991                         {
5992                                 $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
5993                         }
5994                 }
5995                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
5996                 {
5997                         $name = null;
5998                         $url = null;
5999                         $email = null;
6000                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6001                         {
6002                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6003                         }
6004                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6005                         {
6006                                 $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]));
6007                         }
6008                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6009                         {
6010                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6011                         }
6012                         if ($name !== null || $email !== null || $url !== null)
6013                         {
6014                                 $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
6015                         }
6016                 }
6017
6018                 if (!empty($contributors))
6019                 {
6020                         return SimplePie_Misc::array_unique($contributors);
6021                 }
6022                 else
6023                 {
6024                         return null;
6025                 }
6026         }
6027
6028         function get_link($key = 0, $rel = 'alternate')
6029         {
6030                 $links = $this->get_links($rel);
6031                 if (isset($links[$key]))
6032                 {
6033                         return $links[$key];
6034                 }
6035                 else
6036                 {
6037                         return null;
6038                 }
6039         }
6040
6041         /**
6042          * Added for parity between the parent-level and the item/entry-level.
6043          */
6044         function get_permalink()
6045         {
6046                 return $this->get_link(0);
6047         }
6048
6049         function get_links($rel = 'alternate')
6050         {
6051                 if (!isset($this->data['links']))
6052                 {
6053                         $this->data['links'] = array();
6054                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6055                         {
6056                                 foreach ($links as $link)
6057                                 {
6058                                         if (isset($link['attribs']['']['href']))
6059                                         {
6060                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6061                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6062                                         }
6063                                 }
6064                         }
6065                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6066                         {
6067                                 foreach ($links as $link)
6068                                 {
6069                                         if (isset($link['attribs']['']['href']))
6070                                         {
6071                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6072                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6073
6074                                         }
6075                                 }
6076                         }
6077                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6078                         {
6079                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6080                         }
6081                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6082                         {
6083                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6084                         }
6085                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6086                         {
6087                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6088                         }
6089
6090                         $keys = array_keys($this->data['links']);
6091                         foreach ($keys as $key)
6092                         {
6093                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
6094                                 {
6095                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6096                                         {
6097                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6098                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6099                                         }
6100                                         else
6101                                         {
6102                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6103                                         }
6104                                 }
6105                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6106                                 {
6107                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6108                                 }
6109                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6110                         }
6111                 }
6112
6113                 if (isset($this->data['links'][$rel]))
6114                 {
6115                         return $this->data['links'][$rel];
6116                 }
6117                 else
6118                 {
6119                         return null;
6120                 }
6121         }
6122
6123         function get_description()
6124         {
6125                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6126                 {
6127                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6128                 }
6129                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6130                 {
6131                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6132                 }
6133                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6134                 {
6135                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6136                 }
6137                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6138                 {
6139                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6140                 }
6141                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6142                 {
6143                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6144                 }
6145                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6146                 {
6147                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6148                 }
6149                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6150                 {
6151                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6152                 }
6153                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6154                 {
6155                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6156                 }
6157                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6158                 {
6159                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6160                 }
6161                 else
6162                 {
6163                         return null;
6164                 }
6165         }
6166
6167         function get_copyright()
6168         {
6169                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6170                 {
6171                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6172                 }
6173                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6174                 {
6175                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6176                 }
6177                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6178                 {
6179                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6180                 }
6181                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6182                 {
6183                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6184                 }
6185                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6186                 {
6187                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6188                 }
6189                 else
6190                 {
6191                         return null;
6192                 }
6193         }
6194
6195         function get_language()
6196         {
6197                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6198                 {
6199                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6200                 }
6201                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6202                 {
6203                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6204                 }
6205                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6206                 {
6207                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6208                 }
6209                 elseif (isset($this->data['xml_lang']))
6210                 {
6211                         return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6212                 }
6213                 else
6214                 {
6215                         return null;
6216                 }
6217         }
6218
6219         function get_latitude()
6220         {
6221                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6222                 {
6223                         return (float) $return[0]['data'];
6224                 }
6225                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6226                 {
6227                         return (float) $match[1];
6228                 }
6229                 else
6230                 {
6231                         return null;
6232                 }
6233         }
6234
6235         function get_longitude()
6236         {
6237                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6238                 {
6239                         return (float) $return[0]['data'];
6240                 }
6241                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6242                 {
6243                         return (float) $return[0]['data'];
6244                 }
6245                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6246                 {
6247                         return (float) $match[2];
6248                 }
6249                 else
6250                 {
6251                         return null;
6252                 }
6253         }
6254
6255         function get_image_url()
6256         {
6257                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6258                 {
6259                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6260                 }
6261                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6262                 {
6263                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6264                 }
6265                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6266                 {
6267                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6268                 }
6269                 else
6270                 {
6271                         return null;
6272                 }
6273         }
6274 }
6275
6276 class SimplePie_Author
6277 {
6278         var $name;
6279         var $link;
6280         var $email;
6281
6282         // Constructor, used to input the data
6283         function SimplePie_Author($name = null, $link = null, $email = null)
6284         {
6285                 $this->name = $name;
6286                 $this->link = $link;
6287                 $this->email = $email;
6288         }
6289
6290         function __toString()
6291         {
6292                 // There is no $this->data here
6293                 return md5(serialize($this));
6294         }
6295
6296         function get_name()
6297         {
6298                 if ($this->name !== null)
6299                 {
6300                         return $this->name;
6301                 }
6302                 else
6303                 {
6304                         return null;
6305                 }
6306         }
6307
6308         function get_link()
6309         {
6310                 if ($this->link !== null)
6311                 {
6312                         return $this->link;
6313                 }
6314                 else
6315                 {
6316                         return null;
6317                 }
6318         }
6319
6320         function get_email()
6321         {
6322                 if ($this->email !== null)
6323                 {
6324                         return $this->email;
6325                 }
6326                 else
6327                 {
6328                         return null;
6329                 }
6330         }
6331 }
6332
6333 class SimplePie_Category
6334 {
6335         var $term;
6336         var $scheme;
6337         var $label;
6338
6339         // Constructor, used to input the data
6340         function SimplePie_Category($term = null, $scheme = null, $label = null)
6341         {
6342                 $this->term = $term;
6343                 $this->scheme = $scheme;
6344                 $this->label = $label;
6345         }
6346
6347         function __toString()
6348         {
6349                 // There is no $this->data here
6350                 return md5(serialize($this));
6351         }
6352
6353         function get_term()
6354         {
6355                 if ($this->term !== null)
6356                 {
6357                         return $this->term;
6358                 }
6359                 else
6360                 {
6361                         return null;
6362                 }
6363         }
6364
6365         function get_scheme()
6366         {
6367                 if ($this->scheme !== null)
6368                 {
6369                         return $this->scheme;
6370                 }
6371                 else
6372                 {
6373                         return null;
6374                 }
6375         }
6376
6377         function get_label()
6378         {
6379                 if ($this->label !== null)
6380                 {
6381                         return $this->label;
6382                 }
6383                 else
6384                 {
6385                         return $this->get_term();
6386                 }
6387         }
6388 }
6389
6390 class SimplePie_Enclosure
6391 {
6392         var $bitrate;
6393         var $captions;
6394         var $categories;
6395         var $channels;
6396         var $copyright;
6397         var $credits;
6398         var $description;
6399         var $duration;
6400         var $expression;
6401         var $framerate;
6402         var $handler;
6403         var $hashes;
6404         var $height;
6405         var $javascript;
6406         var $keywords;
6407         var $lang;
6408         var $length;
6409         var $link;
6410         var $medium;
6411         var $player;
6412         var $ratings;
6413         var $restrictions;
6414         var $samplingrate;
6415         var $thumbnails;
6416         var $title;
6417         var $type;
6418         var $width;
6419
6420         // Constructor, used to input the data
6421         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)
6422         {
6423                 $this->bitrate = $bitrate;
6424                 $this->captions = $captions;
6425                 $this->categories = $categories;
6426                 $this->channels = $channels;
6427                 $this->copyright = $copyright;
6428                 $this->credits = $credits;
6429                 $this->description = $description;
6430                 $this->duration = $duration;
6431                 $this->expression = $expression;
6432                 $this->framerate = $framerate;
6433                 $this->hashes = $hashes;
6434                 $this->height = $height;
6435                 $this->javascript = $javascript;
6436                 $this->keywords = $keywords;
6437                 $this->lang = $lang;
6438                 $this->length = $length;
6439                 $this->link = $link;
6440                 $this->medium = $medium;
6441                 $this->player = $player;
6442                 $this->ratings = $ratings;
6443                 $this->restrictions = $restrictions;
6444                 $this->samplingrate = $samplingrate;
6445                 $this->thumbnails = $thumbnails;
6446                 $this->title = $title;
6447                 $this->type = $type;
6448                 $this->width = $width;
6449                 if (class_exists('idna_convert'))
6450                 {
6451                         $idn =& new idna_convert;
6452                         $parsed = SimplePie_Misc::parse_url($link);
6453                         $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6454                 }
6455                 $this->handler = $this->get_handler(); // Needs to load last
6456         }
6457
6458         function __toString()
6459         {
6460                 // There is no $this->data here
6461                 return md5(serialize($this));
6462         }
6463
6464         function get_bitrate()
6465         {
6466                 if ($this->bitrate !== null)
6467                 {
6468                         return $this->bitrate;
6469                 }
6470                 else
6471                 {
6472                         return null;
6473                 }
6474         }
6475
6476         function get_caption($key = 0)
6477         {
6478                 $captions = $this->get_captions();
6479                 if (isset($captions[$key]))
6480                 {
6481                         return $captions[$key];
6482                 }
6483                 else
6484                 {
6485                         return null;
6486                 }
6487         }
6488
6489         function get_captions()
6490         {
6491                 if ($this->captions !== null)
6492                 {
6493                         return $this->captions;
6494                 }
6495                 else
6496                 {
6497                         return null;
6498                 }
6499         }
6500
6501         function get_category($key = 0)
6502         {
6503                 $categories = $this->get_categories();
6504                 if (isset($categories[$key]))
6505                 {
6506                         return $categories[$key];
6507                 }
6508                 else
6509                 {
6510                         return null;
6511                 }
6512         }
6513
6514         function get_categories()
6515         {
6516                 if ($this->categories !== null)
6517                 {
6518                         return $this->categories;
6519                 }
6520                 else
6521                 {
6522                         return null;
6523                 }
6524         }
6525
6526         function get_channels()
6527         {
6528                 if ($this->channels !== null)
6529                 {
6530                         return $this->channels;
6531                 }
6532                 else
6533                 {
6534                         return null;
6535                 }
6536         }
6537
6538         function get_copyright()
6539         {
6540                 if ($this->copyright !== null)
6541                 {
6542                         return $this->copyright;
6543                 }
6544                 else
6545                 {
6546                         return null;
6547                 }
6548         }
6549
6550         function get_credit($key = 0)
6551         {
6552                 $credits = $this->get_credits();
6553                 if (isset($credits[$key]))
6554                 {
6555                         return $credits[$key];
6556                 }
6557                 else
6558                 {
6559                         return null;
6560                 }
6561         }
6562
6563         function get_credits()
6564         {
6565                 if ($this->credits !== null)
6566                 {
6567                         return $this->credits;
6568                 }
6569                 else
6570                 {
6571                         return null;
6572                 }
6573         }
6574
6575         function get_description()
6576         {
6577                 if ($this->description !== null)
6578                 {
6579                         return $this->description;
6580                 }
6581                 else
6582                 {
6583                         return null;
6584                 }
6585         }
6586
6587         function get_duration($convert = false)
6588         {
6589                 if ($this->duration !== null)
6590                 {
6591                         if ($convert)
6592                         {
6593                                 $time = SimplePie_Misc::time_hms($this->duration);
6594                                 return $time;
6595                         }
6596                         else
6597                         {
6598                                 return $this->duration;
6599                         }
6600                 }
6601                 else
6602                 {
6603                         return null;
6604                 }
6605         }
6606
6607         function get_expression()
6608         {
6609                 if ($this->expression !== null)
6610                 {
6611                         return $this->expression;
6612                 }
6613                 else
6614                 {
6615                         return 'full';
6616                 }
6617         }
6618
6619         function get_extension()
6620         {
6621                 if ($this->link !== null)
6622                 {
6623                         $url = SimplePie_Misc::parse_url($this->link);
6624                         if ($url['path'] !== '')
6625                         {
6626                                 return pathinfo($url['path'], PATHINFO_EXTENSION);
6627                         }
6628                 }
6629                 return null;
6630         }
6631
6632         function get_framerate()
6633         {
6634                 if ($this->framerate !== null)
6635                 {
6636                         return $this->framerate;
6637                 }
6638                 else
6639                 {
6640                         return null;
6641                 }
6642         }
6643
6644         function get_handler()
6645         {
6646                 return $this->get_real_type(true);
6647         }
6648
6649         function get_hash($key = 0)
6650         {
6651                 $hashes = $this->get_hashes();
6652                 if (isset($hashes[$key]))
6653                 {
6654                         return $hashes[$key];
6655                 }
6656                 else
6657                 {
6658                         return null;
6659                 }
6660         }
6661
6662         function get_hashes()
6663         {
6664                 if ($this->hashes !== null)
6665                 {
6666                         return $this->hashes;
6667                 }
6668                 else
6669                 {
6670                         return null;
6671                 }
6672         }
6673
6674         function get_height()
6675         {
6676                 if ($this->height !== null)
6677                 {
6678                         return $this->height;
6679                 }
6680                 else
6681                 {
6682                         return null;
6683                 }
6684         }
6685
6686         function get_language()
6687         {
6688                 if ($this->lang !== null)
6689                 {
6690                         return $this->lang;
6691                 }
6692                 else
6693                 {
6694                         return null;
6695                 }
6696         }
6697
6698         function get_keyword($key = 0)
6699         {
6700                 $keywords = $this->get_keywords();
6701                 if (isset($keywords[$key]))
6702                 {
6703                         return $keywords[$key];
6704                 }
6705                 else
6706                 {
6707                         return null;
6708                 }
6709         }
6710
6711         function get_keywords()
6712         {
6713                 if ($this->keywords !== null)
6714                 {
6715                         return $this->keywords;
6716                 }
6717                 else
6718                 {
6719                         return null;
6720                 }
6721         }
6722
6723         function get_length()
6724         {
6725                 if ($this->length !== null)
6726                 {
6727                         return $this->length;
6728                 }
6729                 else
6730                 {
6731                         return null;
6732                 }
6733         }
6734
6735         function get_link()
6736         {
6737                 if ($this->link !== null)
6738                 {
6739                         return urldecode($this->link);
6740                 }
6741                 else
6742                 {
6743                         return null;
6744                 }
6745         }
6746
6747         function get_medium()
6748         {
6749                 if ($this->medium !== null)
6750                 {
6751                         return $this->medium;
6752                 }
6753                 else
6754                 {
6755                         return null;
6756                 }
6757         }
6758
6759         function get_player()
6760         {
6761                 if ($this->player !== null)
6762                 {
6763                         return $this->player;
6764                 }
6765                 else
6766                 {
6767                         return null;
6768                 }
6769         }
6770
6771         function get_rating($key = 0)
6772         {
6773                 $ratings = $this->get_ratings();
6774                 if (isset($ratings[$key]))
6775                 {
6776                         return $ratings[$key];
6777                 }
6778                 else
6779                 {
6780                         return null;
6781                 }
6782         }
6783
6784         function get_ratings()
6785         {
6786                 if ($this->ratings !== null)
6787                 {
6788                         return $this->ratings;
6789                 }
6790                 else
6791                 {
6792                         return null;
6793                 }
6794         }
6795
6796         function get_restriction($key = 0)
6797         {
6798                 $restrictions = $this->get_restrictions();
6799                 if (isset($restrictions[$key]))
6800                 {
6801                         return $restrictions[$key];
6802                 }
6803                 else
6804                 {
6805                         return null;
6806                 }
6807         }
6808
6809         function get_restrictions()
6810         {
6811                 if ($this->restrictions !== null)
6812                 {
6813                         return $this->restrictions;
6814                 }
6815                 else
6816                 {
6817                         return null;
6818                 }
6819         }
6820
6821         function get_sampling_rate()
6822         {
6823                 if ($this->samplingrate !== null)
6824                 {
6825                         return $this->samplingrate;
6826                 }
6827                 else
6828                 {
6829                         return null;
6830                 }
6831         }
6832
6833         function get_size()
6834         {
6835                 $length = $this->get_length();
6836                 if ($length !== null)
6837                 {
6838                         return round($length/1048576, 2);
6839                 }
6840                 else
6841                 {
6842                         return null;
6843                 }
6844         }
6845
6846         function get_thumbnail($key = 0)
6847         {
6848                 $thumbnails = $this->get_thumbnails();
6849                 if (isset($thumbnails[$key]))
6850                 {
6851                         return $thumbnails[$key];
6852                 }
6853                 else
6854                 {
6855                         return null;
6856                 }
6857         }
6858
6859         function get_thumbnails()
6860         {
6861                 if ($this->thumbnails !== null)
6862                 {
6863                         return $this->thumbnails;
6864                 }
6865                 else
6866                 {
6867                         return null;
6868                 }
6869         }
6870
6871         function get_title()
6872         {
6873                 if ($this->title !== null)
6874                 {
6875                         return $this->title;
6876                 }
6877                 else
6878                 {
6879                         return null;
6880                 }
6881         }
6882
6883         function get_type()
6884         {
6885                 if ($this->type !== null)
6886                 {
6887                         return $this->type;
6888                 }
6889                 else
6890                 {
6891                         return null;
6892                 }
6893         }
6894
6895         function get_width()
6896         {
6897                 if ($this->width !== null)
6898                 {
6899                         return $this->width;
6900                 }
6901                 else
6902                 {
6903                         return null;
6904                 }
6905         }
6906
6907         function native_embed($options='')
6908         {
6909                 return $this->embed($options, true);
6910         }
6911
6912         /**
6913          * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6914          */
6915         function embed($options = '', $native = false)
6916         {
6917                 // Set up defaults
6918                 $audio = '';
6919                 $video = '';
6920                 $alt = '';
6921                 $altclass = '';
6922                 $loop = 'false';
6923                 $width = 'auto';
6924                 $height = 'auto';
6925                 $bgcolor = '#ffffff';
6926                 $mediaplayer = '';
6927                 $widescreen = false;
6928                 $handler = $this->get_handler();
6929                 $type = $this->get_real_type();
6930
6931                 // Process options and reassign values as necessary
6932                 if (is_array($options))
6933                 {
6934                         extract($options);
6935                 }
6936                 else
6937                 {
6938                         $options = explode(',', $options);
6939                         foreach($options as $option)
6940                         {
6941                                 $opt = explode(':', $option, 2);
6942                                 if (isset($opt[0], $opt[1]))
6943                                 {
6944                                         $opt[0] = trim($opt[0]);
6945                                         $opt[1] = trim($opt[1]);
6946                                         switch ($opt[0])
6947                                         {
6948                                                 case 'audio':
6949                                                         $audio = $opt[1];
6950                                                         break;
6951
6952                                                 case 'video':
6953                                                         $video = $opt[1];
6954                                                         break;
6955
6956                                                 case 'alt':
6957                                                         $alt = $opt[1];
6958                                                         break;
6959
6960                                                 case 'altclass':
6961                                                         $altclass = $opt[1];
6962                                                         break;
6963
6964                                                 case 'loop':
6965                                                         $loop = $opt[1];
6966                                                         break;
6967
6968                                                 case 'width':
6969                                                         $width = $opt[1];
6970                                                         break;
6971
6972                                                 case 'height':
6973                                                         $height = $opt[1];
6974                                                         break;
6975
6976                                                 case 'bgcolor':
6977                                                         $bgcolor = $opt[1];
6978                                                         break;
6979
6980                                                 case 'mediaplayer':
6981                                                         $mediaplayer = $opt[1];
6982                                                         break;
6983
6984                                                 case 'widescreen':
6985                                                         $widescreen = $opt[1];
6986                                                         break;
6987                                         }
6988                                 }
6989                         }
6990                 }
6991
6992                 $mime = explode('/', $type, 2);
6993                 $mime = $mime[0];
6994
6995                 // Process values for 'auto'
6996                 if ($width === 'auto')
6997                 {
6998                         if ($mime === 'video')
6999                         {
7000                                 if ($height === 'auto')
7001                                 {
7002                                         $width = 480;
7003                                 }
7004                                 elseif ($widescreen)
7005                                 {
7006                                         $width = round((intval($height)/9)*16);
7007                                 }
7008                                 else
7009                                 {
7010                                         $width = round((intval($height)/3)*4);
7011                                 }
7012                         }
7013                         else
7014                         {
7015                                 $width = '100%';
7016                         }
7017                 }
7018
7019                 if ($height === 'auto')
7020                 {
7021                         if ($mime === 'audio')
7022                         {
7023                                 $height = 0;
7024                         }
7025                         elseif ($mime === 'video')
7026                         {
7027                                 if ($width === 'auto')
7028                                 {
7029                                         if ($widescreen)
7030                                         {
7031                                                 $height = 270;
7032                                         }
7033                                         else
7034                                         {
7035                                                 $height = 360;
7036                                         }
7037                                 }
7038                                 elseif ($widescreen)
7039                                 {
7040                                         $height = round((intval($width)/16)*9);
7041                                 }
7042                                 else
7043                                 {
7044                                         $height = round((intval($width)/4)*3);
7045                                 }
7046                         }
7047                         else
7048                         {
7049                                 $height = 376;
7050                         }
7051                 }
7052                 elseif ($mime === 'audio')
7053                 {
7054                         $height = 0;
7055                 }
7056
7057                 // Set proper placeholder value
7058                 if ($mime === 'audio')
7059                 {
7060                         $placeholder = $audio;
7061                 }
7062                 elseif ($mime === 'video')
7063                 {
7064                         $placeholder = $video;
7065                 }
7066
7067                 $embed = '';
7068
7069                 // Make sure the JS library is included
7070                 if (!$native)
7071                 {
7072                         static $javascript_outputted = null;
7073                         if (!$javascript_outputted && $this->javascript)
7074                         {
7075                                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7076                                 $javascript_outputted = true;
7077                         }
7078                 }
7079
7080                 // Odeo Feed MP3's
7081                 if ($handler === 'odeo')
7082                 {
7083                         if ($native)
7084                         {
7085                                 $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>';
7086                         }
7087                         else
7088                         {
7089                                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7090                         }
7091                 }
7092
7093                 // Flash
7094                 elseif ($handler === 'flash')
7095                 {
7096                         if ($native)
7097                         {
7098                                 $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>";
7099                         }
7100                         else
7101                         {
7102                                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7103                         }
7104                 }
7105
7106                 // Flash Media Player file types.
7107                 // Preferred handler for MP3 file types.
7108                 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7109                 {
7110                         $height += 20;
7111                         if ($native)
7112                         {
7113                                 $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>";
7114                         }
7115                         else
7116                         {
7117                                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7118                         }
7119                 }
7120
7121                 // QuickTime 7 file types.  Need to test with QuickTime 6.
7122                 // Only handle MP3's if the Flash Media Player is not present.
7123                 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7124                 {
7125                         $height += 16;
7126                         if ($native)
7127                         {
7128                                 if ($placeholder !== '')
7129                                 {
7130                                         $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>";
7131                                 }
7132                                 else
7133                                 {
7134                                         $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>";
7135                                 }
7136                         }
7137                         else
7138                         {
7139                                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7140                         }
7141                 }
7142
7143                 // Windows Media
7144                 elseif ($handler === 'wmedia')
7145                 {
7146                         $height += 45;
7147                         if ($native)
7148                         {
7149                                 $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>";
7150                         }
7151                         else
7152                         {
7153                                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7154                         }
7155                 }
7156
7157                 // Everything else
7158                 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7159
7160                 return $embed;
7161         }
7162
7163         function get_real_type($find_handler = false)
7164         {
7165                 // If it's Odeo, let's get it out of the way.
7166                 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7167                 {
7168                         return 'odeo';
7169                 }
7170
7171                 // Mime-types by handler.
7172                 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7173                 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7174                 $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
7175                 $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
7176                 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7177
7178                 if ($this->get_type() !== null)
7179                 {
7180                         $type = strtolower($this->type);
7181                 }
7182                 else
7183                 {
7184                         $type = null;
7185                 }
7186
7187                 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7188                 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7189                 {
7190                         switch (strtolower($this->get_extension()))
7191                         {
7192                                 // Audio mime-types
7193                                 case 'aac':
7194                                 case 'adts':
7195                                         $type = 'audio/acc';
7196                                         break;
7197
7198                                 case 'aif':
7199                                 case 'aifc':
7200                                 case 'aiff':
7201                                 case 'cdda':
7202                                         $type = 'audio/aiff';
7203                                         break;
7204
7205                                 case 'bwf':
7206                                         $type = 'audio/wav';
7207                                         break;
7208
7209                                 case 'kar':
7210                                 case 'mid':
7211                                 case 'midi':
7212                                 case 'smf':
7213                                         $type = 'audio/midi';
7214                                         break;
7215
7216                                 case 'm4a':
7217                                         $type = 'audio/x-m4a';
7218                                         break;
7219
7220                                 case 'mp3':
7221                                 case 'swa':
7222                                         $type = 'audio/mp3';
7223                                         break;
7224
7225                                 case 'wav':
7226                                         $type = 'audio/wav';
7227                                         break;
7228
7229                                 case 'wax':
7230                                         $type = 'audio/x-ms-wax';
7231                                         break;
7232
7233                                 case 'wma':
7234                                         $type = 'audio/x-ms-wma';
7235                                         break;
7236
7237                                 // Video mime-types
7238                                 case '3gp':
7239                                 case '3gpp':
7240                                         $type = 'video/3gpp';
7241                                         break;
7242
7243                                 case '3g2':
7244                                 case '3gp2':
7245                                         $type = 'video/3gpp2';
7246                                         break;
7247
7248                                 case 'asf':
7249                                         $type = 'video/x-ms-asf';
7250                                         break;
7251
7252                                 case 'flv':
7253                                         $type = 'video/x-flv';
7254                                         break;
7255
7256                                 case 'm1a':
7257                                 case 'm1s':
7258                                 case 'm1v':
7259                                 case 'm15':
7260                                 case 'm75':
7261                                 case 'mp2':
7262                                 case 'mpa':
7263                                 case 'mpeg':
7264                                 case 'mpg':
7265                                 case 'mpm':
7266                                 case 'mpv':
7267                                         $type = 'video/mpeg';
7268                                         break;
7269
7270                                 case 'm4v':
7271                                         $type = 'video/x-m4v';
7272                                         break;
7273
7274                                 case 'mov':
7275                                 case 'qt':
7276                                         $type = 'video/quicktime';
7277                                         break;
7278
7279                                 case 'mp4':
7280                                 case 'mpg4':
7281                                         $type = 'video/mp4';
7282                                         break;
7283
7284                                 case 'sdv':
7285                                         $type = 'video/sd-video';
7286                                         break;
7287
7288                                 case 'wm':
7289                                         $type = 'video/x-ms-wm';
7290                                         break;
7291
7292                                 case 'wmv':
7293                                         $type = 'video/x-ms-wmv';
7294                                         break;
7295
7296                                 case 'wvx':
7297                                         $type = 'video/x-ms-wvx';
7298                                         break;
7299
7300                                 // Flash mime-types
7301                                 case 'spl':
7302                                         $type = 'application/futuresplash';
7303                                         break;
7304
7305                                 case 'swf':
7306                                         $type = 'application/x-shockwave-flash';
7307                                         break;
7308                         }
7309                 }
7310
7311                 if ($find_handler)
7312                 {
7313                         if (in_array($type, $types_flash))
7314                         {
7315                                 return 'flash';
7316                         }
7317                         elseif (in_array($type, $types_fmedia))
7318                         {
7319                                 return 'fmedia';
7320                         }
7321                         elseif (in_array($type, $types_quicktime))
7322                         {
7323                                 return 'quicktime';
7324                         }
7325                         elseif (in_array($type, $types_wmedia))
7326                         {
7327                                 return 'wmedia';
7328                         }
7329                         elseif (in_array($type, $types_mp3))
7330                         {
7331                                 return 'mp3';
7332                         }
7333                         else
7334                         {
7335                                 return null;
7336                         }
7337                 }
7338                 else
7339                 {
7340                         return $type;
7341                 }
7342         }
7343 }
7344
7345 class SimplePie_Caption
7346 {
7347         var $type;
7348         var $lang;
7349         var $startTime;
7350         var $endTime;
7351         var $text;
7352
7353         // Constructor, used to input the data
7354         function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7355         {
7356                 $this->type = $type;
7357                 $this->lang = $lang;
7358                 $this->startTime = $startTime;
7359                 $this->endTime = $endTime;
7360                 $this->text = $text;
7361         }
7362
7363         function __toString()
7364         {
7365                 // There is no $this->data here
7366                 return md5(serialize($this));
7367         }
7368
7369         function get_endtime()
7370         {
7371                 if ($this->endTime !== null)
7372                 {
7373                         return $this->endTime;
7374                 }
7375                 else
7376                 {
7377                         return null;
7378                 }
7379         }
7380
7381         function get_language()
7382         {
7383                 if ($this->lang !== null)
7384                 {
7385                         return $this->lang;
7386                 }
7387                 else
7388                 {
7389                         return null;
7390                 }
7391         }
7392
7393         function get_starttime()
7394         {
7395                 if ($this->startTime !== null)
7396                 {
7397                         return $this->startTime;
7398                 }
7399                 else
7400                 {
7401                         return null;
7402                 }
7403         }
7404
7405         function get_text()
7406         {
7407                 if ($this->text !== null)
7408                 {
7409                         return $this->text;
7410                 }
7411                 else
7412                 {
7413                         return null;
7414                 }
7415         }
7416
7417         function get_type()
7418         {
7419                 if ($this->type !== null)
7420                 {
7421                         return $this->type;
7422                 }
7423                 else
7424                 {
7425                         return null;
7426                 }
7427         }
7428 }
7429
7430 class SimplePie_Credit
7431 {
7432         var $role;
7433         var $scheme;
7434         var $name;
7435
7436         // Constructor, used to input the data
7437         function SimplePie_Credit($role = null, $scheme = null, $name = null)
7438         {
7439                 $this->role = $role;
7440                 $this->scheme = $scheme;
7441                 $this->name = $name;
7442         }
7443
7444         function __toString()
7445         {
7446                 // There is no $this->data here
7447                 return md5(serialize($this));
7448         }
7449
7450         function get_role()
7451         {
7452                 if ($this->role !== null)
7453                 {
7454                         return $this->role;
7455                 }
7456                 else
7457                 {
7458                         return null;
7459                 }
7460         }
7461
7462         function get_scheme()
7463         {
7464                 if ($this->scheme !== null)
7465                 {
7466                         return $this->scheme;
7467                 }
7468                 else
7469                 {
7470                         return null;
7471                 }
7472         }
7473
7474         function get_name()
7475         {
7476                 if ($this->name !== null)
7477                 {
7478                         return $this->name;
7479                 }
7480                 else
7481                 {
7482                         return null;
7483                 }
7484         }
7485 }
7486
7487 class SimplePie_Copyright
7488 {
7489         var $url;
7490         var $label;
7491
7492         // Constructor, used to input the data
7493         function SimplePie_Copyright($url = null, $label = null)
7494         {
7495                 $this->url = $url;
7496                 $this->label = $label;
7497         }
7498
7499         function __toString()
7500         {
7501                 // There is no $this->data here
7502                 return md5(serialize($this));
7503         }
7504
7505         function get_url()
7506         {
7507                 if ($this->url !== null)
7508                 {
7509                         return $this->url;
7510                 }
7511                 else
7512                 {
7513                         return null;
7514                 }
7515         }
7516
7517         function get_attribution()
7518         {
7519                 if ($this->label !== null)
7520                 {
7521                         return $this->label;
7522                 }
7523                 else
7524                 {
7525                         return null;
7526                 }
7527         }
7528 }
7529
7530 class SimplePie_Rating
7531 {
7532         var $scheme;
7533         var $value;
7534
7535         // Constructor, used to input the data
7536         function SimplePie_Rating($scheme = null, $value = null)
7537         {
7538                 $this->scheme = $scheme;
7539                 $this->value = $value;
7540         }
7541
7542         function __toString()
7543         {
7544                 // There is no $this->data here
7545                 return md5(serialize($this));
7546         }
7547
7548         function get_scheme()
7549         {
7550                 if ($this->scheme !== null)
7551                 {
7552                         return $this->scheme;
7553                 }
7554                 else
7555                 {
7556                         return null;
7557                 }
7558         }
7559
7560         function get_value()
7561         {
7562                 if ($this->value !== null)
7563                 {
7564                         return $this->value;
7565                 }
7566                 else
7567                 {
7568                         return null;
7569                 }
7570         }
7571 }
7572
7573 class SimplePie_Restriction
7574 {
7575         var $relationship;
7576         var $type;
7577         var $value;
7578
7579         // Constructor, used to input the data
7580         function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7581         {
7582                 $this->relationship = $relationship;
7583                 $this->type = $type;
7584                 $this->value = $value;
7585         }
7586
7587         function __toString()
7588         {
7589                 // There is no $this->data here
7590                 return md5(serialize($this));
7591         }
7592
7593         function get_relationship()
7594         {
7595                 if ($this->relationship !== null)
7596                 {
7597                         return $this->relationship;
7598                 }
7599                 else
7600                 {
7601                         return null;
7602                 }
7603         }
7604
7605         function get_type()
7606         {
7607                 if ($this->type !== null)
7608                 {
7609                         return $this->type;
7610                 }
7611                 else
7612                 {
7613                         return null;
7614                 }
7615         }
7616
7617         function get_value()
7618         {
7619                 if ($this->value !== null)
7620                 {
7621                         return $this->value;
7622                 }
7623                 else
7624                 {
7625                         return null;
7626                 }
7627         }
7628 }
7629
7630 /**
7631  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7632  */
7633 class SimplePie_File
7634 {
7635         var $url;
7636         var $useragent;
7637         var $success = true;
7638         var $headers = array();
7639         var $body;
7640         var $status_code;
7641         var $redirects = 0;
7642         var $error;
7643         var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7644
7645         function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7646         {
7647                 if (class_exists('idna_convert'))
7648                 {
7649                         $idn =& new idna_convert;
7650                         $parsed = SimplePie_Misc::parse_url($url);
7651                         $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7652                 }
7653                 $this->url = $url;
7654                 $this->useragent = $useragent;
7655                 if (preg_match('/^http(s)?:\/\//i', $url))
7656                 {
7657                         if ($useragent === null)
7658                         {
7659                                 $useragent = ini_get('user_agent');
7660                                 $this->useragent = $useragent;
7661                         }
7662                         if (!is_array($headers))
7663                         {
7664                                 $headers = array();
7665                         }
7666                         if (!$force_fsockopen && function_exists('curl_exec'))
7667                         {
7668                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7669                                 $fp = curl_init();
7670                                 $headers2 = array();
7671                                 foreach ($headers as $key => $value)
7672                                 {
7673                                         $headers2[] = "$key: $value";
7674                                 }
7675                                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7676                                 {
7677                                         curl_setopt($fp, CURLOPT_ENCODING, '');
7678                                 }
7679                                 curl_setopt($fp, CURLOPT_URL, $url);
7680                                 curl_setopt($fp, CURLOPT_HEADER, 1);
7681                                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7682                                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7683                                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7684                                 curl_setopt($fp, CURLOPT_REFERER, $url);
7685                                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7686                                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7687                                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7688                                 {
7689                                         curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7690                                         curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7691                                 }
7692
7693                                 $this->headers = curl_exec($fp);
7694                                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7695                                 {
7696                                         curl_setopt($fp, CURLOPT_ENCODING, 'none');
7697                                         $this->headers = curl_exec($fp);
7698                                 }
7699                                 if (curl_errno($fp))
7700                                 {
7701                                         $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7702                                         $this->success = false;
7703                                 }
7704                                 else
7705                                 {
7706                                         $info = curl_getinfo($fp);
7707                                         curl_close($fp);
7708                                         $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7709                                         $this->headers = array_pop($this->headers);
7710                                         $parser =& new SimplePie_HTTP_Parser($this->headers);
7711                                         if ($parser->parse())
7712                                         {
7713                                                 $this->headers = $parser->headers;
7714                                                 $this->body = $parser->body;
7715                                                 $this->status_code = $parser->status_code;
7716                                                 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)
7717                                                 {
7718                                                         $this->redirects++;
7719                                                         $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7720                                                         return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7721                                                 }
7722                                         }
7723                                 }
7724                         }
7725                         else
7726                         {
7727                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7728                                 $url_parts = parse_url($url);
7729                                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7730                                 {
7731                                         $url_parts['host'] = "ssl://$url_parts[host]";
7732                                         $url_parts['port'] = 443;
7733                                 }
7734                                 if (!isset($url_parts['port']))
7735                                 {
7736                                         $url_parts['port'] = 80;
7737                                 }
7738                                 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7739                                 if (!$fp)
7740                                 {
7741                                         $this->error = 'fsockopen error: ' . $errstr;
7742                                         $this->success = false;
7743                                 }
7744                                 else
7745                                 {
7746                                         stream_set_timeout($fp, $timeout);
7747                                         if (isset($url_parts['path']))
7748                                         {
7749                                                 if (isset($url_parts['query']))
7750                                                 {
7751                                                         $get = "$url_parts[path]?$url_parts[query]";
7752                                                 }
7753                                                 else
7754                                                 {
7755                                                         $get = $url_parts['path'];
7756                                                 }
7757                                         }
7758                                         else
7759                                         {
7760                                                 $get = '/';
7761                                         }
7762                                         $out = "GET $get HTTP/1.0\r\n";
7763                                         $out .= "Host: $url_parts[host]\r\n";
7764                                         $out .= "User-Agent: $useragent\r\n";
7765                                         if (extension_loaded('zlib'))
7766                                         {
7767                                                 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7768                                         }
7769
7770                                         if (isset($url_parts['user']) && isset($url_parts['pass']))
7771                                         {
7772                                                 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7773                                         }
7774                                         foreach ($headers as $key => $value)
7775                                         {
7776                                                 $out .= "$key: $value\r\n";
7777                                         }
7778                                         $out .= "Connection: Close\r\n\r\n";
7779                                         fwrite($fp, $out);
7780
7781                                         $info = stream_get_meta_data($fp);
7782
7783                                         $this->headers = '';
7784                                         while (!$info['eof'] && !$info['timed_out'])
7785                                         {
7786                                                 $this->headers .= fread($fp, 1160);
7787                                                 $info = stream_get_meta_data($fp);
7788                                         }
7789                                         if (!$info['timed_out'])
7790                                         {
7791                                                 $parser =& new SimplePie_HTTP_Parser($this->headers);
7792                                                 if ($parser->parse())
7793                                                 {
7794                                                         $this->headers = $parser->headers;
7795                                                         $this->body = $parser->body;
7796                                                         $this->status_code = $parser->status_code;
7797                                                         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)
7798                                                         {
7799                                                                 $this->redirects++;
7800                                                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7801                                                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7802                                                         }
7803                                                         if (isset($this->headers['content-encoding']))
7804                                                         {
7805                                                                 // Hey, we act dumb elsewhere, so let's do that here too
7806                                                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7807                                                                 {
7808                                                                         case 'gzip':
7809                                                                         case 'x-gzip':
7810                                                                                 $decoder =& new SimplePie_gzdecode($this->body);
7811                                                                                 if (!$decoder->parse())
7812                                                                                 {
7813                                                                                         $this->error = 'Unable to decode HTTP "gzip" stream';
7814                                                                                         $this->success = false;
7815                                                                                 }
7816                                                                                 else
7817                                                                                 {
7818                                                                                         $this->body = $decoder->data;
7819                                                                                 }
7820                                                                                 break;
7821
7822                                                                         case 'deflate':
7823                                                                                 if (($body = gzuncompress($this->body)) === false)
7824                                                                                 {
7825                                                                                         if (($body = gzinflate($this->body)) === false)
7826                                                                                         {
7827                                                                                                 $this->error = 'Unable to decode HTTP "deflate" stream';
7828                                                                                                 $this->success = false;
7829                                                                                         }
7830                                                                                 }
7831                                                                                 $this->body = $body;
7832                                                                                 break;
7833
7834                                                                         default:
7835                                                                                 $this->error = 'Unknown content coding';
7836                                                                                 $this->success = false;
7837                                                                 }
7838                                                         }
7839                                                 }
7840                                         }
7841                                         else
7842                                         {
7843                                                 $this->error = 'fsocket timed out';
7844                                                 $this->success = false;
7845                                         }
7846                                         fclose($fp);
7847                                 }
7848                         }
7849                 }
7850                 else
7851                 {
7852                         $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7853                         if (!$this->body = file_get_contents($url))
7854                         {
7855                                 $this->error = 'file_get_contents could not read the file';
7856                                 $this->success = false;
7857                         }
7858                 }
7859         }
7860 }
7861
7862 /**
7863  * HTTP Response Parser
7864  *
7865  * @package SimplePie
7866  */
7867 class SimplePie_HTTP_Parser
7868 {
7869         /**
7870          * HTTP Version
7871          *
7872          * @access public
7873          * @var float
7874          */
7875         var $http_version = 0.0;
7876
7877         /**
7878          * Status code
7879          *
7880          * @access public
7881          * @var int
7882          */
7883         var $status_code = 0;
7884
7885         /**
7886          * Reason phrase
7887          *
7888          * @access public
7889          * @var string
7890          */
7891         var $reason = '';
7892
7893         /**
7894          * Key/value pairs of the headers
7895          *
7896          * @access public
7897          * @var array
7898          */
7899         var $headers = array();
7900
7901         /**
7902          * Body of the response
7903          *
7904          * @access public
7905          * @var string
7906          */
7907         var $body = '';
7908
7909         /**
7910          * Current state of the state machine
7911          *
7912          * @access private
7913          * @var string
7914          */
7915         var $state = 'http_version';
7916
7917         /**
7918          * Input data
7919          *
7920          * @access private
7921          * @var string
7922          */
7923         var $data = '';
7924
7925         /**
7926          * Input data length (to avoid calling strlen() everytime this is needed)
7927          *
7928          * @access private
7929          * @var int
7930          */
7931         var $data_length = 0;
7932
7933         /**
7934          * Current position of the pointer
7935          *
7936          * @var int
7937          * @access private
7938          */
7939         var $position = 0;
7940
7941         /**
7942          * Name of the hedaer currently being parsed
7943          *
7944          * @access private
7945          * @var string
7946          */
7947         var $name = '';
7948
7949         /**
7950          * Value of the hedaer currently being parsed
7951          *
7952          * @access private
7953          * @var string
7954          */
7955         var $value = '';
7956
7957         /**
7958          * Create an instance of the class with the input data
7959          *
7960          * @access public
7961          * @param string $data Input data
7962          */
7963         function SimplePie_HTTP_Parser($data)
7964         {
7965                 $this->data = $data;
7966                 $this->data_length = strlen($this->data);
7967         }
7968
7969         /**
7970          * Parse the input data
7971          *
7972          * @access public
7973          * @return bool true on success, false on failure
7974          */
7975         function parse()
7976         {
7977                 while ($this->state && $this->state !== 'emit' && $this->has_data())
7978                 {
7979                         $state = $this->state;
7980                         $this->$state();
7981                 }
7982                 $this->data = '';
7983                 if ($this->state === 'emit' || $this->state === 'body')
7984                 {
7985                         return true;
7986                 }
7987                 else
7988                 {
7989                         $this->http_version = '';
7990                         $this->status_code = '';
7991                         $this->reason = '';
7992                         $this->headers = array();
7993                         $this->body = '';
7994                         return false;
7995                 }
7996         }
7997
7998         /**
7999          * Check whether there is data beyond the pointer
8000          *
8001          * @access private
8002          * @return bool true if there is further data, false if not
8003          */
8004         function has_data()
8005         {
8006                 return (bool) ($this->position < $this->data_length);
8007         }
8008
8009         /**
8010          * See if the next character is LWS
8011          *
8012          * @access private
8013          * @return bool true if the next character is LWS, false if not
8014          */
8015         function is_linear_whitespace()
8016         {
8017                 return (bool) ($this->data[$this->position] === "\x09"
8018                         || $this->data[$this->position] === "\x20"
8019                         || ($this->data[$this->position] === "\x0A"
8020                                 && isset($this->data[$this->position + 1])
8021                                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8022         }
8023
8024         /**
8025          * Parse the HTTP version
8026          *
8027          * @access private
8028          */
8029         function http_version()
8030         {
8031                 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8032                 {
8033                         $len = strspn($this->data, '0123456789.', 5);
8034                         $this->http_version = substr($this->data, 5, $len);
8035                         $this->position += 5 + $len;
8036                         if (substr_count($this->http_version, '.') <= 1)
8037                         {
8038                                 $this->http_version = (float) $this->http_version;
8039                                 $this->position += strspn($this->data, "\x09\x20", $this->position);
8040                                 $this->state = 'status';
8041                         }
8042                         else
8043                         {
8044                                 $this->state = false;
8045                         }
8046                 }
8047                 else
8048                 {
8049                         $this->state = false;
8050                 }
8051         }
8052
8053         /**
8054          * Parse the status code
8055          *
8056          * @access private
8057          */
8058         function status()
8059         {
8060                 if ($len = strspn($this->data, '0123456789', $this->position))
8061                 {
8062                         $this->status_code = (int) substr($this->data, $this->position, $len);
8063                         $this->position += $len;
8064                         $this->state = 'reason';
8065                 }
8066                 else
8067                 {
8068                         $this->state = false;
8069                 }
8070         }
8071
8072         /**
8073          * Parse the reason phrase
8074          *
8075          * @access private
8076          */
8077         function reason()
8078         {
8079                 $len = strcspn($this->data, "\x0A", $this->position);
8080                 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8081                 $this->position += $len + 1;
8082                 $this->state = 'new_line';
8083         }
8084
8085         /**
8086          * Deal with a new line, shifting data around as needed
8087          *
8088          * @access private
8089          */
8090         function new_line()
8091         {
8092                 $this->value = trim($this->value, "\x0D\x20");
8093                 if ($this->name !== '' && $this->value !== '')
8094                 {
8095                         $this->name = strtolower($this->name);
8096                         if (isset($this->headers[$this->name]))
8097                         {
8098                                 $this->headers[$this->name] .= ', ' . $this->value;
8099                         }
8100                         else
8101                         {
8102                                 $this->headers[$this->name] = $this->value;
8103                         }
8104                 }
8105                 $this->name = '';
8106                 $this->value = '';
8107                 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8108                 {
8109                         $this->position += 2;
8110                         $this->state = 'body';
8111                 }
8112                 elseif ($this->data[$this->position] === "\x0A")
8113                 {
8114                         $this->position++;
8115                         $this->state = 'body';
8116                 }
8117                 else
8118                 {
8119                         $this->state = 'name';
8120                 }
8121         }
8122
8123         /**
8124          * Parse a header name
8125          *
8126          * @access private
8127          */
8128         function name()
8129         {
8130                 $len = strcspn($this->data, "\x0A:", $this->position);
8131                 if (isset($this->data[$this->position + $len]))
8132                 {
8133                         if ($this->data[$this->position + $len] === "\x0A")
8134                         {
8135                                 $this->position += $len;
8136                                 $this->state = 'new_line';
8137                         }
8138                         else
8139                         {
8140                                 $this->name = substr($this->data, $this->position, $len);
8141                                 $this->position += $len + 1;
8142                                 $this->state = 'value';
8143                         }
8144                 }
8145                 else
8146                 {
8147                         $this->state = false;
8148                 }
8149         }
8150
8151         /**
8152          * Parse LWS, replacing consecutive LWS characters with a single space
8153          *
8154          * @access private
8155          */
8156         function linear_whitespace()
8157         {
8158                 do
8159                 {
8160                         if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8161                         {
8162                                 $this->position += 2;
8163                         }
8164                         elseif ($this->data[$this->position] === "\x0A")
8165                         {
8166                                 $this->position++;
8167                         }
8168                         $this->position += strspn($this->data, "\x09\x20", $this->position);
8169                 } while ($this->has_data() && $this->is_linear_whitespace());
8170                 $this->value .= "\x20";
8171         }
8172
8173         /**
8174          * See what state to move to while within non-quoted header values
8175          *
8176          * @access private
8177          */
8178         function value()
8179         {
8180                 if ($this->is_linear_whitespace())
8181                 {
8182                         $this->linear_whitespace();
8183                 }
8184                 else
8185                 {
8186                         switch ($this->data[$this->position])
8187                         {
8188                                 case '"':
8189                                         $this->position++;
8190                                         $this->state = 'quote';
8191                                         break;
8192
8193                                 case "\x0A":
8194                                         $this->position++;
8195                                         $this->state = 'new_line';
8196                                         break;
8197
8198                                 default:
8199                                         $this->state = 'value_char';
8200                                         break;
8201                         }
8202                 }
8203         }
8204
8205         /**
8206          * Parse a header value while outside quotes
8207          *
8208          * @access private
8209          */
8210         function value_char()
8211         {
8212                 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8213                 $this->value .= substr($this->data, $this->position, $len);
8214                 $this->position += $len;
8215                 $this->state = 'value';
8216         }
8217
8218         /**
8219          * See what state to move to while within quoted header values
8220          *
8221          * @access private
8222          */
8223         function quote()
8224         {
8225                 if ($this->is_linear_whitespace())
8226                 {
8227                         $this->linear_whitespace();
8228                 }
8229                 else
8230                 {
8231                         switch ($this->data[$this->position])
8232                         {
8233                                 case '"':
8234                                         $this->position++;
8235                                         $this->state = 'value';
8236                                         break;
8237
8238                                 case "\x0A":
8239                                         $this->position++;
8240                                         $this->state = 'new_line';
8241                                         break;
8242
8243                                 case '\\':
8244                                         $this->position++;
8245                                         $this->state = 'quote_escaped';
8246                                         break;
8247
8248                                 default:
8249                                         $this->state = 'quote_char';
8250                                         break;
8251                         }
8252                 }
8253         }
8254
8255         /**
8256          * Parse a header value while within quotes
8257          *
8258          * @access private
8259          */
8260         function quote_char()
8261         {
8262                 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8263                 $this->value .= substr($this->data, $this->position, $len);
8264                 $this->position += $len;
8265                 $this->state = 'value';
8266         }
8267
8268         /**
8269          * Parse an escaped character within quotes
8270          *
8271          * @access private
8272          */
8273         function quote_escaped()
8274         {
8275                 $this->value .= $this->data[$this->position];
8276                 $this->position++;
8277                 $this->state = 'quote';
8278         }
8279
8280         /**
8281          * Parse the body
8282          *
8283          * @access private
8284          */
8285         function body()
8286         {
8287                 $this->body = substr($this->data, $this->position);
8288                 $this->state = 'emit';
8289         }
8290 }
8291
8292 /**
8293  * gzdecode
8294  *
8295  * @package SimplePie
8296  */
8297 class SimplePie_gzdecode
8298 {
8299         /**
8300          * Compressed data
8301          *
8302          * @access private
8303          * @see gzdecode::$data
8304          */
8305         var $compressed_data;
8306
8307         /**
8308          * Size of compressed data
8309          *
8310          * @access private
8311          */
8312         var $compressed_size;
8313
8314         /**
8315          * Minimum size of a valid gzip string
8316          *
8317          * @access private
8318          */
8319         var $min_compressed_size = 18;
8320
8321         /**
8322          * Current position of pointer
8323          *
8324          * @access private
8325          */
8326         var $position = 0;
8327
8328         /**
8329          * Flags (FLG)
8330          *
8331          * @access private
8332          */
8333         var $flags;
8334
8335         /**
8336          * Uncompressed data
8337          *
8338          * @access public
8339          * @see gzdecode::$compressed_data
8340          */
8341         var $data;
8342
8343         /**
8344          * Modified time
8345          *
8346          * @access public
8347          */
8348         var $MTIME;
8349
8350         /**
8351          * Extra Flags
8352          *
8353          * @access public
8354          */
8355         var $XFL;
8356
8357         /**
8358          * Operating System
8359          *
8360          * @access public
8361          */
8362         var $OS;
8363
8364         /**
8365          * Subfield ID 1
8366          *
8367          * @access public
8368          * @see gzdecode::$extra_field
8369          * @see gzdecode::$SI2
8370          */
8371         var $SI1;
8372
8373         /**
8374          * Subfield ID 2
8375          *
8376          * @access public
8377          * @see gzdecode::$extra_field
8378          * @see gzdecode::$SI1
8379          */
8380         var $SI2;
8381
8382         /**
8383          * Extra field content
8384          *
8385          * @access public
8386          * @see gzdecode::$SI1
8387          * @see gzdecode::$SI2
8388          */
8389         var $extra_field;
8390
8391         /**
8392          * Original filename
8393          *
8394          * @access public
8395          */
8396         var $filename;
8397
8398         /**
8399          * Human readable comment
8400          *
8401          * @access public
8402          */
8403         var $comment;
8404
8405         /**
8406          * Don't allow anything to be set
8407          *
8408          * @access public
8409          */
8410         function __set($name, $value)
8411         {
8412                 trigger_error("Cannot write property $name", E_USER_ERROR);
8413         }
8414
8415         /**
8416          * Set the compressed string and related properties
8417          *
8418          * @access public
8419          */
8420         function SimplePie_gzdecode($data)
8421         {
8422                 $this->compressed_data = $data;
8423                 $this->compressed_size = strlen($data);
8424         }
8425
8426         /**
8427          * Decode the GZIP stream
8428          *
8429          * @access public
8430          */
8431         function parse()
8432         {
8433                 if ($this->compressed_size >= $this->min_compressed_size)
8434                 {
8435                         // Check ID1, ID2, and CM
8436                         if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8437                         {
8438                                 return false;
8439                         }
8440
8441                         // Get the FLG (FLaGs)
8442                         $this->flags = ord($this->compressed_data[3]);
8443
8444                         // FLG bits above (1 << 4) are reserved
8445                         if ($this->flags > 0x1F)
8446                         {
8447                                 return false;
8448                         }
8449
8450                         // Advance the pointer after the above
8451                         $this->position += 4;
8452
8453                         // MTIME
8454                         $mtime = substr($this->compressed_data, $this->position, 4);
8455                         // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8456                         if (current(unpack('S', "\x00\x01")) === 1)
8457                         {
8458                                 $mtime = strrev($mtime);
8459                         }
8460                         $this->MTIME = current(unpack('l', $mtime));
8461                         $this->position += 4;
8462
8463                         // Get the XFL (eXtra FLags)
8464                         $this->XFL = ord($this->compressed_data[$this->position++]);
8465
8466                         // Get the OS (Operating System)
8467                         $this->OS = ord($this->compressed_data[$this->position++]);
8468
8469                         // Parse the FEXTRA
8470                         if ($this->flags & 4)
8471                         {
8472                                 // Read subfield IDs
8473                                 $this->SI1 = $this->compressed_data[$this->position++];
8474                                 $this->SI2 = $this->compressed_data[$this->position++];
8475
8476                                 // SI2 set to zero is reserved for future use
8477                                 if ($this->SI2 === "\x00")
8478                                 {
8479                                         return false;
8480                                 }
8481
8482                                 // Get the length of the extra field
8483                                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8484                                 $position += 2;
8485
8486                                 // Check the length of the string is still valid
8487                                 $this->min_compressed_size += $len + 4;
8488                                 if ($this->compressed_size >= $this->min_compressed_size)
8489                                 {
8490                                         // Set the extra field to the given data
8491                                         $this->extra_field = substr($this->compressed_data, $this->position, $len);
8492                                         $this->position += $len;
8493                                 }
8494                                 else
8495                                 {
8496                                         return false;
8497                                 }
8498                         }
8499
8500                         // Parse the FNAME
8501                         if ($this->flags & 8)
8502                         {
8503                                 // Get the length of the filename
8504                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8505
8506                                 // Check the length of the string is still valid
8507                                 $this->min_compressed_size += $len + 1;
8508                                 if ($this->compressed_size >= $this->min_compressed_size)
8509                                 {
8510                                         // Set the original filename to the given string
8511                                         $this->filename = substr($this->compressed_data, $this->position, $len);
8512                                         $this->position += $len + 1;
8513                                 }
8514                                 else
8515                                 {
8516                                         return false;
8517                                 }
8518                         }
8519
8520                         // Parse the FCOMMENT
8521                         if ($this->flags & 16)
8522                         {
8523                                 // Get the length of the comment
8524                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8525
8526                                 // Check the length of the string is still valid
8527                                 $this->min_compressed_size += $len + 1;
8528                                 if ($this->compressed_size >= $this->min_compressed_size)
8529                                 {
8530                                         // Set the original comment to the given string
8531                                         $this->comment = substr($this->compressed_data, $this->position, $len);
8532                                         $this->position += $len + 1;
8533                                 }
8534                                 else
8535                                 {
8536                                         return false;
8537                                 }
8538                         }
8539
8540                         // Parse the FHCRC
8541                         if ($this->flags & 2)
8542                         {
8543                                 // Check the length of the string is still valid
8544                                 $this->min_compressed_size += $len + 2;
8545                                 if ($this->compressed_size >= $this->min_compressed_size)
8546                                 {
8547                                         // Read the CRC
8548                                         $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8549
8550                                         // Check the CRC matches
8551                                         if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8552                                         {
8553                                                 $this->position += 2;
8554                                         }
8555                                         else
8556                                         {
8557                                                 return false;
8558                                         }
8559                                 }
8560                                 else
8561                                 {
8562                                         return false;
8563                                 }
8564                         }
8565
8566                         // Decompress the actual data
8567                         if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8568                         {
8569                                 return false;
8570                         }
8571                         else
8572                         {
8573                                 $this->position = $this->compressed_size - 8;
8574                         }
8575
8576                         // Check CRC of data
8577                         $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8578                         $this->position += 4;
8579                         /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8580                         {
8581                                 return false;
8582                         }*/
8583
8584                         // Check ISIZE of data
8585                         $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8586                         $this->position += 4;
8587                         if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8588                         {
8589                                 return false;
8590                         }
8591
8592                         // Wow, against all odds, we've actually got a valid gzip string
8593                         return true;
8594                 }
8595                 else
8596                 {
8597                         return false;
8598                 }
8599         }
8600 }
8601
8602 class SimplePie_Cache
8603 {
8604         /**
8605          * Don't call the constructor. Please.
8606          *
8607          * @access private
8608          */
8609         function SimplePie_Cache()
8610         {
8611                 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8612         }
8613
8614         /**
8615          * Create a new SimplePie_Cache object
8616          *
8617          * @static
8618          * @access public
8619          */
8620         function create($location, $filename, $extension)
8621         {
8622                 $location_iri =& new SimplePie_IRI($location);
8623                 switch ($location_iri->get_scheme())
8624                 {
8625                         case 'mysql':
8626                                 if (extension_loaded('mysql'))
8627                                 {
8628                                         return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8629                                 }
8630                                 break;
8631
8632                         default:
8633                                 return new SimplePie_Cache_File($location, $filename, $extension);
8634                 }
8635         }
8636 }
8637
8638 class SimplePie_Cache_File
8639 {
8640         var $location;
8641         var $filename;
8642         var $extension;
8643         var $name;
8644
8645         function SimplePie_Cache_File($location, $filename, $extension)
8646         {
8647                 $this->location = $location;
8648                 $this->filename = $filename;
8649                 $this->extension = $extension;
8650                 $this->name = "$this->location/$this->filename.$this->extension";
8651         }
8652
8653         function save($data)
8654         {
8655                 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8656                 {
8657                         if (is_a($data, 'SimplePie'))
8658                         {
8659                                 $data = $data->data;
8660                         }
8661
8662                         $data = serialize($data);
8663
8664                         if (function_exists('file_put_contents'))
8665                         {
8666                                 return (bool) file_put_contents($this->name, $data);
8667                         }
8668                         else
8669                         {
8670                                 $fp = fopen($this->name, 'wb');
8671                                 if ($fp)
8672                                 {
8673                                         fwrite($fp, $data);
8674                                         fclose($fp);
8675                                         return true;
8676                                 }
8677                         }
8678                 }
8679                 return false;
8680         }
8681
8682         function load()
8683         {
8684                 if (file_exists($this->name) && is_readable($this->name))
8685                 {
8686                         return unserialize(file_get_contents($this->name));
8687                 }
8688                 return false;
8689         }
8690
8691         function mtime()
8692         {
8693                 if (file_exists($this->name))
8694                 {
8695                         return filemtime($this->name);
8696                 }
8697                 return false;
8698         }
8699
8700         function touch()
8701         {
8702                 if (file_exists($this->name))
8703                 {
8704                         return touch($this->name);
8705                 }
8706                 return false;
8707         }
8708
8709         function unlink()
8710         {
8711                 if (file_exists($this->name))
8712                 {
8713                         return unlink($this->name);
8714                 }
8715                 return false;
8716         }
8717 }
8718
8719 class SimplePie_Cache_DB
8720 {
8721         function prepare_simplepie_object_for_cache($data)
8722         {
8723                 $items = $data->get_items();
8724                 $items_by_id = array();
8725
8726                 if (!empty($items))
8727                 {
8728                         foreach ($items as $item)
8729                         {
8730                                 $items_by_id[$item->get_id()] = $item;
8731                         }
8732
8733                         if (count($items_by_id) !== count($items))
8734                         {
8735                                 $items_by_id = array();
8736                                 foreach ($items as $item)
8737                                 {
8738                                         $items_by_id[$item->get_id(true)] = $item;
8739                                 }
8740                         }
8741
8742                         if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8743                         {
8744                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8745                         }
8746                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8747                         {
8748                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8749                         }
8750                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8751                         {
8752                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8753                         }
8754                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8755                         {
8756                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8757                         }
8758                         else
8759                         {
8760                                 $channel = null;
8761                         }
8762
8763                         if ($channel !== null)
8764                         {
8765                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8766                                 {
8767                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8768                                 }
8769                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8770                                 {
8771                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8772                                 }
8773                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8774                                 {
8775                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8776                                 }
8777                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8778                                 {
8779                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8780                                 }
8781                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8782                                 {
8783                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8784                                 }
8785                         }
8786                         if (isset($data->data['items']))
8787                         {
8788                                 unset($data->data['items']);
8789                         }
8790                         if (isset($data->data['ordered_items']))
8791                         {
8792                                 unset($data->data['ordered_items']);
8793                         }
8794                 }
8795                 return array(serialize($data->data), $items_by_id);
8796         }
8797 }
8798
8799 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8800 {
8801         var $mysql;
8802         var $options;
8803         var $id;
8804
8805         function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8806         {
8807                 $host = $mysql_location->get_host();
8808                 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8809                 {
8810                         $server = ':' . substr($host, 5, -1);
8811                 }
8812                 else
8813                 {
8814                         $server = $host;
8815                         if ($mysql_location->get_port() !== null)
8816                         {
8817                                 $server .= ':' . $mysql_location->get_port();
8818                         }
8819                 }
8820
8821                 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8822                 {
8823                         list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8824                 }
8825                 else
8826                 {
8827                         $username = $mysql_location->get_userinfo();
8828                         $password = null;
8829                 }
8830
8831                 if ($this->mysql = mysql_connect($server, $username, $password))
8832                 {
8833                         $this->id = $name . $extension;
8834                         $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8835                         if (!isset($this->options['prefix'][0]))
8836                         {
8837                                 $this->options['prefix'][0] = '';
8838                         }
8839
8840                         if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8841                                 && mysql_query('SET NAMES utf8')
8842                                 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8843                         {
8844                                 $db = array();
8845                                 while ($row = mysql_fetch_row($query))
8846                                 {
8847                                         $db[] = $row[0];
8848                                 }
8849
8850                                 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8851                                 {
8852                                         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)))'))
8853                                         {
8854                                                 $this->mysql = null;
8855                                         }
8856                                 }
8857
8858                                 if (!in_array($this->options['prefix'][0] . 'items', $db))
8859                                 {
8860                                         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)))'))
8861                                         {
8862                                                 $this->mysql = null;
8863                                         }
8864                                 }
8865                         }
8866                         else
8867                         {
8868                                 $this->mysql = null;
8869                         }
8870                 }
8871         }
8872
8873         function save($data)
8874         {
8875                 if ($this->mysql)
8876                 {
8877                         $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8878
8879                         if (is_a($data, 'SimplePie'))
8880                         {
8881                                 if (SIMPLEPIE_PHP5)
8882                                 {
8883                                         // This keyword needs to defy coding standards for PHP4 compatibility
8884                                         $data = clone($data);
8885                                 }
8886
8887                                 $prepared = $this->prepare_simplepie_object_for_cache($data);
8888
8889                                 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8890                                 {
8891                                         if (mysql_num_rows($query))
8892                                         {
8893                                                 $items = count($prepared[1]);
8894                                                 if ($items)
8895                                                 {
8896                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8897                                                 }
8898                                                 else
8899                                                 {
8900                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8901                                                 }
8902
8903                                                 if (!mysql_query($sql, $this->mysql))
8904                                                 {
8905                                                         return false;
8906                                                 }
8907                                         }
8908                                         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))
8909                                         {
8910                                                 return false;
8911                                         }
8912
8913                                         $ids = array_keys($prepared[1]);
8914                                         if (!empty($ids))
8915                                         {
8916                                                 foreach ($ids as $id)
8917                                                 {
8918                                                         $database_ids[] = mysql_real_escape_string($id);
8919                                                 }
8920
8921                                                 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))
8922                                                 {
8923                                                         $existing_ids = array();
8924                                                         while ($row = mysql_fetch_row($query))
8925                                                         {
8926                                                                 $existing_ids[] = $row[0];
8927                                                         }
8928
8929                                                         $new_ids = array_diff($ids, $existing_ids);
8930
8931                                                         foreach ($new_ids as $new_id)
8932                                                         {
8933                                                                 if (!($date = $prepared[1][$new_id]->get_date('U')))
8934                                                                 {
8935                                                                         $date = time();
8936                                                                 }
8937
8938                                                                 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))
8939                                                                 {
8940                                                                         return false;
8941                                                                 }
8942                                                         }
8943                                                         return true;
8944                                                 }
8945                                         }
8946                                         else
8947                                         {
8948                                                 return true;
8949                                         }
8950                                 }
8951                         }
8952                         elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8953                         {
8954                                 if (mysql_num_rows($query))
8955                                 {
8956                                         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))
8957                                         {
8958                                                 return true;
8959                                         }
8960                                 }
8961                                 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))
8962                                 {
8963                                         return true;
8964                                 }
8965                         }
8966                 }
8967                 return false;
8968         }
8969
8970         function load()
8971         {
8972                 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)))
8973                 {
8974                         $data = unserialize($row[1]);
8975
8976                         if (isset($this->options['items'][0]))
8977                         {
8978                                 $items = (int) $this->options['items'][0];
8979                         }
8980                         else
8981                         {
8982                                 $items = (int) $row[0];
8983                         }
8984
8985                         if ($items !== 0)
8986                         {
8987                                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8988                                 {
8989                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8990                                 }
8991                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8992                                 {
8993                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8994                                 }
8995                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8996                                 {
8997                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8998                                 }
8999                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9000                                 {
9001                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9002                                 }
9003                                 else
9004                                 {
9005                                         $feed = null;
9006                                 }
9007
9008                                 if ($feed !== null)
9009                                 {
9010                                         $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9011                                         if ($items > 0)
9012                                         {
9013                                                 $sql .= ' LIMIT ' . $items;
9014                                         }
9015
9016                                         if ($query = mysql_unbuffered_query($sql, $this->mysql))
9017                                         {
9018                                                 while ($row = mysql_fetch_row($query))
9019                                                 {
9020                                                         $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9021                                                 }
9022                                         }
9023                                         else
9024                                         {
9025                                                 return false;
9026                                         }
9027                                 }
9028                         }
9029                         return $data;
9030                 }
9031                 return false;
9032         }
9033
9034         function mtime()
9035         {
9036                 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)))
9037                 {
9038                         return $row[0];
9039                 }
9040                 else
9041                 {
9042                         return false;
9043                 }
9044         }
9045
9046         function touch()
9047         {
9048                 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))
9049                 {
9050                         return true;
9051                 }
9052                 else
9053                 {
9054                         return false;
9055                 }
9056         }
9057
9058         function unlink()
9059         {
9060                 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)))
9061                 {
9062                         return true;
9063                 }
9064                 else
9065                 {
9066                         return false;
9067                 }
9068         }
9069 }
9070
9071 class SimplePie_Misc
9072 {
9073         function time_hms($seconds)
9074         {
9075                 $time = '';
9076
9077                 $hours = floor($seconds / 3600);
9078                 $remainder = $seconds % 3600;
9079                 if ($hours > 0)
9080                 {
9081                         $time .= $hours.':';
9082                 }
9083
9084                 $minutes = floor($remainder / 60);
9085                 $seconds = $remainder % 60;
9086                 if ($minutes < 10 && $hours > 0)
9087                 {
9088                         $minutes = '0' . $minutes;
9089                 }
9090                 if ($seconds < 10)
9091                 {
9092                         $seconds = '0' . $seconds;
9093                 }
9094
9095                 $time .= $minutes.':';
9096                 $time .= $seconds;
9097
9098                 return $time;
9099         }
9100
9101         function absolutize_url($relative, $base)
9102         {
9103                 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9104                 return $iri->get_iri();
9105         }
9106
9107         function remove_dot_segments($input)
9108         {
9109                 $output = '';
9110                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9111                 {
9112                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9113                         if (strpos($input, '../') === 0)
9114                         {
9115                                 $input = substr($input, 3);
9116                         }
9117                         elseif (strpos($input, './') === 0)
9118                         {
9119                                 $input = substr($input, 2);
9120                         }
9121                         // 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,
9122                         elseif (strpos($input, '/./') === 0)
9123                         {
9124                                 $input = substr_replace($input, '/', 0, 3);
9125                         }
9126                         elseif ($input === '/.')
9127                         {
9128                                 $input = '/';
9129                         }
9130                         // 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,
9131                         elseif (strpos($input, '/../') === 0)
9132                         {
9133                                 $input = substr_replace($input, '/', 0, 4);
9134                                 $output = substr_replace($output, '', strrpos($output, '/'));
9135                         }
9136                         elseif ($input === '/..')
9137                         {
9138                                 $input = '/';
9139                                 $output = substr_replace($output, '', strrpos($output, '/'));
9140                         }
9141                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9142                         elseif ($input === '.' || $input === '..')
9143                         {
9144                                 $input = '';
9145                         }
9146                         // 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
9147                         elseif (($pos = strpos($input, '/', 1)) !== false)
9148                         {
9149                                 $output .= substr($input, 0, $pos);
9150                                 $input = substr_replace($input, '', 0, $pos);
9151                         }
9152                         else
9153                         {
9154                                 $output .= $input;
9155                                 $input = '';
9156                         }
9157                 }
9158                 return $output . $input;
9159         }
9160
9161         function get_element($realname, $string)
9162         {
9163                 $return = array();
9164                 $name = preg_quote($realname, '/');
9165                 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9166                 {
9167                         for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9168                         {
9169                                 $return[$i]['tag'] = $realname;
9170                                 $return[$i]['full'] = $matches[$i][0][0];
9171                                 $return[$i]['offset'] = $matches[$i][0][1];
9172                                 if (strlen($matches[$i][3][0]) <= 2)
9173                                 {
9174                                         $return[$i]['self_closing'] = true;
9175                                 }
9176                                 else
9177                                 {
9178                                         $return[$i]['self_closing'] = false;
9179                                         $return[$i]['content'] = $matches[$i][4][0];
9180                                 }
9181                                 $return[$i]['attribs'] = array();
9182                                 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))
9183                                 {
9184                                         for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9185                                         {
9186                                                 if (count($attribs[$j]) === 2)
9187                                                 {
9188                                                         $attribs[$j][2] = $attribs[$j][1];
9189                                                 }
9190                                                 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9191                                         }
9192                                 }
9193                         }
9194                 }
9195                 return $return;
9196         }
9197
9198         function element_implode($element)
9199         {
9200                 $full = "<$element[tag]";
9201                 foreach ($element['attribs'] as $key => $value)
9202                 {
9203                         $key = strtolower($key);
9204                         $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9205                 }
9206                 if ($element['self_closing'])
9207                 {
9208                         $full .= ' />';
9209                 }
9210                 else
9211                 {
9212                         $full .= ">$element[content]</$element[tag]>";
9213                 }
9214                 return $full;
9215         }
9216
9217         function error($message, $level, $file, $line)
9218         {
9219                 if ((ini_get('error_reporting') & $level) > 0)
9220                 {
9221                         switch ($level)
9222                         {
9223                                 case E_USER_ERROR:
9224                                         $note = 'PHP Error';
9225                                         break;
9226                                 case E_USER_WARNING:
9227                                         $note = 'PHP Warning';
9228                                         break;
9229                                 case E_USER_NOTICE:
9230                                         $note = 'PHP Notice';
9231                                         break;
9232                                 default:
9233                                         $note = 'Unknown Error';
9234                                         break;
9235                         }
9236                         error_log("$note: $message in $file on line $line", 0);
9237                 }
9238                 return $message;
9239         }
9240
9241         /**
9242          * If a file has been cached, retrieve and display it.
9243          *
9244          * This is most useful for caching images (get_favicon(), etc.),
9245          * however it works for all cached files.  This WILL NOT display ANY
9246          * file/image/page/whatever, but rather only display what has already
9247          * been cached by SimplePie.
9248          *
9249          * @access public
9250          * @see SimplePie::get_favicon()
9251          * @param str $identifier_url URL that is used to identify the content.
9252          * This may or may not be the actual URL of the live content.
9253          * @param str $cache_location Location of SimplePie's cache.  Defaults
9254          * to './cache'.
9255          * @param str $cache_extension The file extension that the file was
9256          * cached with.  Defaults to 'spc'.
9257          * @param str $cache_class Name of the cache-handling class being used
9258          * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
9259          * as-is unless you've overloaded the class.
9260          * @param str $cache_name_function Obsolete. Exists for backwards
9261          * compatibility reasons only.
9262          */
9263         function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9264         {
9265                 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9266
9267                 if ($file = $cache->load())
9268                 {
9269                         if (isset($file['headers']['content-type']))
9270                         {
9271                                 header('Content-type:' . $file['headers']['content-type']);
9272                         }
9273                         else
9274                         {
9275                                 header('Content-type: application/octet-stream');
9276                         }
9277                         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9278                         echo $file['body'];
9279                         exit;
9280                 }
9281
9282                 die('Cached file for ' . $identifier_url . ' cannot be found.');
9283         }
9284
9285         function fix_protocol($url, $http = 1)
9286         {
9287                 $url = SimplePie_Misc::normalize_url($url);
9288                 $parsed = SimplePie_Misc::parse_url($url);
9289                 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9290                 {
9291                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9292                 }
9293
9294                 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9295                 {
9296                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9297                 }
9298
9299                 if ($http === 2 && $parsed['scheme'] !== '')
9300                 {
9301                         return "feed:$url";
9302                 }
9303                 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9304                 {
9305                         return substr_replace($url, 'podcast', 0, 4);
9306                 }
9307                 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9308                 {
9309                         return substr_replace($url, 'itpc', 0, 4);
9310                 }
9311                 else
9312                 {
9313                         return $url;
9314                 }
9315         }
9316
9317         function parse_url($url)
9318         {
9319                 $iri =& new SimplePie_IRI($url);
9320                 return array(
9321                         'scheme' => (string) $iri->get_scheme(),
9322                         'authority' => (string) $iri->get_authority(),
9323                         'path' => (string) $iri->get_path(),
9324                         'query' => (string) $iri->get_query(),
9325                         'fragment' => (string) $iri->get_fragment()
9326                 );
9327         }
9328
9329         function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9330         {
9331                 $iri =& new SimplePie_IRI('');
9332                 $iri->set_scheme($scheme);
9333                 $iri->set_authority($authority);
9334                 $iri->set_path($path);
9335                 $iri->set_query($query);
9336                 $iri->set_fragment($fragment);
9337                 return $iri->get_iri();
9338         }
9339
9340         function normalize_url($url)
9341         {
9342                 $iri =& new SimplePie_IRI($url);
9343                 return $iri->get_iri();
9344         }
9345
9346         function percent_encoding_normalization($match)
9347         {
9348                 $integer = hexdec($match[1]);
9349                 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9350                 {
9351                         return chr($integer);
9352                 }
9353                 else
9354                 {
9355                         return strtoupper($match[0]);
9356                 }
9357         }
9358
9359         /**
9360          * Remove bad UTF-8 bytes
9361          *
9362          * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9363          * FAQ: Multilingual Forms (modified to include full ASCII range)
9364          *
9365          * @author Geoffrey Sneddon
9366          * @see http://www.w3.org/International/questions/qa-forms-utf-8
9367          * @param string $str String to remove bad UTF-8 bytes from
9368          * @return string UTF-8 string
9369          */
9370         function utf8_bad_replace($str)
9371         {
9372                 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9373                 {
9374                         return $return;
9375                 }
9376                 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9377                 {
9378                         return $return;
9379                 }
9380                 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))
9381                 {
9382                         return implode("\xEF\xBF\xBD", $matches[0]);
9383                 }
9384                 elseif ($str !== '')
9385                 {
9386                         return "\xEF\xBF\xBD";
9387                 }
9388                 else
9389                 {
9390                         return '';
9391                 }
9392         }
9393
9394         /**
9395          * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9396          *
9397          * @static
9398          * @access public
9399          * @param string $string Windows-1252 encoded string
9400          * @return string UTF-8 encoded string
9401          */
9402         function windows_1252_to_utf8($string)
9403         {
9404                 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");
9405
9406                 return strtr($string, $convert_table);
9407         }
9408
9409         function change_encoding($data, $input, $output)
9410         {
9411                 $input = SimplePie_Misc::encoding($input);
9412                 $output = SimplePie_Misc::encoding($output);
9413
9414                 // We fail to fail on non US-ASCII bytes
9415                 if ($input === 'US-ASCII')
9416                 {
9417                         static $non_ascii_octects = '';
9418                         if (!$non_ascii_octects)
9419                         {
9420                                 for ($i = 0x80; $i <= 0xFF; $i++)
9421                                 {
9422                                         $non_ascii_octects .= chr($i);
9423                                 }
9424                         }
9425                         $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9426                 }
9427
9428                 // This is first, as behaviour of this is completely predictable
9429                 if ($input === 'windows-1252' && $output === 'UTF-8')
9430                 {
9431                         return SimplePie_Misc::windows_1252_to_utf8($data);
9432                 }
9433                 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9434                 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9435                 {
9436                         return $return;
9437                 }
9438                 // This is last, as behaviour of this varies with OS userland and PHP version
9439                 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9440                 {
9441                         return $return;
9442                 }
9443                 // If we can't do anything, just fail
9444                 else
9445                 {
9446                         return false;
9447                 }
9448         }
9449
9450         function encoding($charset)
9451         {
9452                 // Normalization from UTS #22
9453                 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9454                 {
9455                         case 'adobestandardencoding':
9456                         case 'csadobestandardencoding':
9457                                 return 'Adobe-Standard-Encoding';
9458
9459                         case 'adobesymbolencoding':
9460                         case 'cshppsmath':
9461                                 return 'Adobe-Symbol-Encoding';
9462
9463                         case 'ami1251':
9464                         case 'amiga1251':
9465                                 return 'Amiga-1251';
9466
9467                         case 'ansix31101983':
9468                         case 'csat5001983':
9469                         case 'csiso99naplps':
9470                         case 'isoir99':
9471                         case 'naplps':
9472                                 return 'ANSI_X3.110-1983';
9473
9474                         case 'arabic7':
9475                         case 'asmo449':
9476                         case 'csiso89asmo449':
9477                         case 'iso9036':
9478                         case 'isoir89':
9479                                 return 'ASMO_449';
9480
9481                         case 'big5':
9482                         case 'csbig5':
9483                         case 'xxbig5':
9484                                 return 'Big5';
9485
9486                         case 'big5hkscs':
9487                                 return 'Big5-HKSCS';
9488
9489                         case 'bocu1':
9490                         case 'csbocu1':
9491                                 return 'BOCU-1';
9492
9493                         case 'brf':
9494                         case 'csbrf':
9495                                 return 'BRF';
9496
9497                         case 'bs4730':
9498                         case 'csiso4unitedkingdom':
9499                         case 'gb':
9500                         case 'iso646gb':
9501                         case 'isoir4':
9502                         case 'uk':
9503                                 return 'BS_4730';
9504
9505                         case 'bsviewdata':
9506                         case 'csiso47bsviewdata':
9507                         case 'isoir47':
9508                                 return 'BS_viewdata';
9509
9510                         case 'cesu8':
9511                         case 'cscesu8':
9512                                 return 'CESU-8';
9513
9514                         case 'ca':
9515                         case 'csa71':
9516                         case 'csaz243419851':
9517                         case 'csiso121canadian1':
9518                         case 'iso646ca':
9519                         case 'isoir121':
9520                                 return 'CSA_Z243.4-1985-1';
9521
9522                         case 'csa72':
9523                         case 'csaz243419852':
9524                         case 'csiso122canadian2':
9525                         case 'iso646ca2':
9526                         case 'isoir122':
9527                                 return 'CSA_Z243.4-1985-2';
9528
9529                         case 'csaz24341985gr':
9530                         case 'csiso123csaz24341985gr':
9531                         case 'isoir123':
9532                                 return 'CSA_Z243.4-1985-gr';
9533
9534                         case 'csiso139csn369103':
9535                         case 'csn369103':
9536                         case 'isoir139':
9537                                 return 'CSN_369103';
9538
9539                         case 'csdecmcs':
9540                         case 'dec':
9541                         case 'decmcs':
9542                                 return 'DEC-MCS';
9543
9544                         case 'csiso21german':
9545                         case 'de':
9546                         case 'din66003':
9547                         case 'iso646de':
9548                         case 'isoir21':
9549                                 return 'DIN_66003';
9550
9551                         case 'csdkus':
9552                         case 'dkus':
9553                                 return 'dk-us';
9554
9555                         case 'csiso646danish':
9556                         case 'dk':
9557                         case 'ds2089':
9558                         case 'iso646dk':
9559                                 return 'DS_2089';
9560
9561                         case 'csibmebcdicatde':
9562                         case 'ebcdicatde':
9563                                 return 'EBCDIC-AT-DE';
9564
9565                         case 'csebcdicatdea':
9566                         case 'ebcdicatdea':
9567                                 return 'EBCDIC-AT-DE-A';
9568
9569                         case 'csebcdiccafr':
9570                         case 'ebcdiccafr':
9571                                 return 'EBCDIC-CA-FR';
9572
9573                         case 'csebcdicdkno':
9574                         case 'ebcdicdkno':
9575                                 return 'EBCDIC-DK-NO';
9576
9577                         case 'csebcdicdknoa':
9578                         case 'ebcdicdknoa':
9579                                 return 'EBCDIC-DK-NO-A';
9580
9581                         case 'csebcdices':
9582                         case 'ebcdices':
9583                                 return 'EBCDIC-ES';
9584
9585                         case 'csebcdicesa':
9586                         case 'ebcdicesa':
9587                                 return 'EBCDIC-ES-A';
9588
9589                         case 'csebcdicess':
9590                         case 'ebcdicess':
9591                                 return 'EBCDIC-ES-S';
9592
9593                         case 'csebcdicfise':
9594                         case 'ebcdicfise':
9595                                 return 'EBCDIC-FI-SE';
9596
9597                         case 'csebcdicfisea':
9598                         case 'ebcdicfisea':
9599                                 return 'EBCDIC-FI-SE-A';
9600
9601                         case 'csebcdicfr':
9602                         case 'ebcdicfr':
9603                                 return 'EBCDIC-FR';
9604
9605                         case 'csebcdicit':
9606                         case 'ebcdicit':
9607                                 return 'EBCDIC-IT';
9608
9609                         case 'csebcdicpt':
9610                         case 'ebcdicpt':
9611                                 return 'EBCDIC-PT';
9612
9613                         case 'csebcdicuk':
9614                         case 'ebcdicuk':
9615                                 return 'EBCDIC-UK';
9616
9617                         case 'csebcdicus':
9618                         case 'ebcdicus':
9619                                 return 'EBCDIC-US';
9620
9621                         case 'csiso111ecmacyrillic':
9622                         case 'ecmacyrillic':
9623                         case 'isoir111':
9624                         case 'koi8e':
9625                                 return 'ECMA-cyrillic';
9626
9627                         case 'csiso17spanish':
9628                         case 'es':
9629                         case 'iso646es':
9630                         case 'isoir17':
9631                                 return 'ES';
9632
9633                         case 'csiso85spanish2':
9634                         case 'es2':
9635                         case 'iso646es2':
9636                         case 'isoir85':
9637                                 return 'ES2';
9638
9639                         case 'cseucfixwidjapanese':
9640                         case 'extendedunixcodefixedwidthforjapanese':
9641                                 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9642
9643                         case 'cseucpkdfmtjapanese':
9644                         case 'eucjp':
9645                         case 'extendedunixcodepackedformatforjapanese':
9646                                 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9647
9648                         case 'gb18030':
9649                                 return 'GB18030';
9650
9651                         case 'chinese':
9652                         case 'cp936':
9653                         case 'csgb2312':
9654                         case 'csiso58gb231280':
9655                         case 'gb2312':
9656                         case 'gb231280':
9657                         case 'gbk':
9658                         case 'isoir58':
9659                         case 'ms936':
9660                         case 'windows936':
9661                                 return 'GBK';
9662
9663                         case 'cn':
9664                         case 'csiso57gb1988':
9665                         case 'gb198880':
9666                         case 'iso646cn':
9667                         case 'isoir57':
9668                                 return 'GB_1988-80';
9669
9670                         case 'csiso153gost1976874':
9671                         case 'gost1976874':
9672                         case 'isoir153':
9673                         case 'stsev35888':
9674                                 return 'GOST_19768-74';
9675
9676                         case 'csiso150':
9677                         case 'csiso150greekccitt':
9678                         case 'greekccitt':
9679                         case 'isoir150':
9680                                 return 'greek-ccitt';
9681
9682                         case 'csiso88greek7':
9683                         case 'greek7':
9684                         case 'isoir88':
9685                                 return 'greek7';
9686
9687                         case 'csiso18greek7old':
9688                         case 'greek7old':
9689                         case 'isoir18':
9690                                 return 'greek7-old';
9691
9692                         case 'cshpdesktop':
9693                         case 'hpdesktop':
9694                                 return 'HP-DeskTop';
9695
9696                         case 'cshplegal':
9697                         case 'hplegal':
9698                                 return 'HP-Legal';
9699
9700                         case 'cshpmath8':
9701                         case 'hpmath8':
9702                                 return 'HP-Math8';
9703
9704                         case 'cshppifont':
9705                         case 'hppifont':
9706                                 return 'HP-Pi-font';
9707
9708                         case 'cshproman8':
9709                         case 'hproman8':
9710                         case 'r8':
9711                         case 'roman8':
9712                                 return 'hp-roman8';
9713
9714                         case 'hzgb2312':
9715                                 return 'HZ-GB-2312';
9716
9717                         case 'csibmsymbols':
9718                         case 'ibmsymbols':
9719                                 return 'IBM-Symbols';
9720
9721                         case 'csibmthai':
9722                         case 'ibmthai':
9723                                 return 'IBM-Thai';
9724
9725                         case 'ccsid858':
9726                         case 'cp858':
9727                         case 'ibm858':
9728                         case 'pcmultilingual850euro':
9729                                 return 'IBM00858';
9730
9731                         case 'ccsid924':
9732                         case 'cp924':
9733                         case 'ebcdiclatin9euro':
9734                         case 'ibm924':
9735                                 return 'IBM00924';
9736
9737                         case 'ccsid1140':
9738                         case 'cp1140':
9739                         case 'ebcdicus37euro':
9740                         case 'ibm1140':
9741                                 return 'IBM01140';
9742
9743                         case 'ccsid1141':
9744                         case 'cp1141':
9745                         case 'ebcdicde273euro':
9746                         case 'ibm1141':
9747                                 return 'IBM01141';
9748
9749                         case 'ccsid1142':
9750                         case 'cp1142':
9751                         case 'ebcdicdk277euro':
9752                         case 'ebcdicno277euro':
9753                         case 'ibm1142':
9754                                 return 'IBM01142';
9755
9756                         case 'ccsid1143':
9757                         case 'cp1143':
9758                         case 'ebcdicfi278euro':
9759                         case 'ebcdicse278euro':
9760                         case 'ibm1143':
9761                                 return 'IBM01143';
9762
9763                         case 'ccsid1144':
9764                         case 'cp1144':
9765                         case 'ebcdicit280euro':
9766                         case 'ibm1144':
9767                                 return 'IBM01144';
9768
9769                         case 'ccsid1145':
9770                         case 'cp1145':
9771                         case 'ebcdices284euro':
9772                         case 'ibm1145':
9773                                 return 'IBM01145';
9774
9775                         case 'ccsid1146':
9776                         case 'cp1146':
9777                         case 'ebcdicgb285euro':
9778                         case 'ibm1146':
9779                                 return 'IBM01146';
9780
9781                         case 'ccsid1147':
9782                         case 'cp1147':
9783                         case 'ebcdicfr297euro':
9784                         case 'ibm1147':
9785                                 return 'IBM01147';
9786
9787                         case 'ccsid1148':
9788                         case 'cp1148':
9789                         case 'ebcdicinternational500euro':
9790                         case 'ibm1148':
9791                                 return 'IBM01148';
9792
9793                         case 'ccsid1149':
9794                         case 'cp1149':
9795                         case 'ebcdicis871euro':
9796                         case 'ibm1149':
9797                                 return 'IBM01149';
9798
9799                         case 'cp37':
9800                         case 'csibm37':
9801                         case 'ebcdiccpca':
9802                         case 'ebcdiccpnl':
9803                         case 'ebcdiccpus':
9804                         case 'ebcdiccpwt':
9805                         case 'ibm37':
9806                                 return 'IBM037';
9807
9808                         case 'cp38':
9809                         case 'csibm38':
9810                         case 'ebcdicint':
9811                         case 'ibm38':
9812                                 return 'IBM038';
9813
9814                         case 'cp273':
9815                         case 'csibm273':
9816                         case 'ibm273':
9817                                 return 'IBM273';
9818
9819                         case 'cp274':
9820                         case 'csibm274':
9821                         case 'ebcdicbe':
9822                         case 'ibm274':
9823                                 return 'IBM274';
9824
9825                         case 'cp275':
9826                         case 'csibm275':
9827                         case 'ebcdicbr':
9828                         case 'ibm275':
9829                                 return 'IBM275';
9830
9831                         case 'csibm277':
9832                         case 'ebcdiccpdk':
9833                         case 'ebcdiccpno':
9834                         case 'ibm277':
9835                                 return 'IBM277';
9836
9837                         case 'cp278':
9838                         case 'csibm278':
9839                         case 'ebcdiccpfi':
9840                         case 'ebcdiccpse':
9841                         case 'ibm278':
9842                                 return 'IBM278';
9843
9844                         case 'cp280':
9845                         case 'csibm280':
9846                         case 'ebcdiccpit':
9847                         case 'ibm280':
9848                                 return 'IBM280';
9849
9850                         case 'cp281':
9851                         case 'csibm281':
9852                         case 'ebcdicjpe':
9853                         case 'ibm281':
9854                                 return 'IBM281';
9855
9856                         case 'cp284':
9857                         case 'csibm284':
9858                         case 'ebcdiccpes':
9859                         case 'ibm284':
9860                                 return 'IBM284';
9861
9862                         case 'cp285':
9863                         case 'csibm285':
9864                         case 'ebcdiccpgb':
9865                         case 'ibm285':
9866                                 return 'IBM285';
9867
9868                         case 'cp290':
9869                         case 'csibm290':
9870                         case 'ebcdicjpkana':
9871                         case 'ibm290':
9872                                 return 'IBM290';
9873
9874                         case 'cp297':
9875                         case 'csibm297':
9876                         case 'ebcdiccpfr':
9877                         case 'ibm297':
9878                                 return 'IBM297';
9879
9880                         case 'cp420':
9881                         case 'csibm420':
9882                         case 'ebcdiccpar1':
9883                         case 'ibm420':
9884                                 return 'IBM420';
9885
9886                         case 'cp423':
9887                         case 'csibm423':
9888                         case 'ebcdiccpgr':
9889                         case 'ibm423':
9890                                 return 'IBM423';
9891
9892                         case 'cp424':
9893                         case 'csibm424':
9894                         case 'ebcdiccphe':
9895                         case 'ibm424':
9896                                 return 'IBM424';
9897
9898                         case '437':
9899                         case 'cp437':
9900                         case 'cspc8codepage437':
9901                         case 'ibm437':
9902                                 return 'IBM437';
9903
9904                         case 'cp500':
9905                         case 'csibm500':
9906                         case 'ebcdiccpbe':
9907                         case 'ebcdiccpch':
9908                         case 'ibm500':
9909                                 return 'IBM500';
9910
9911                         case 'cp775':
9912                         case 'cspc775baltic':
9913                         case 'ibm775':
9914                                 return 'IBM775';
9915
9916                         case '850':
9917                         case 'cp850':
9918                         case 'cspc850multilingual':
9919                         case 'ibm850':
9920                                 return 'IBM850';
9921
9922                         case '851':
9923                         case 'cp851':
9924                         case 'csibm851':
9925                         case 'ibm851':
9926                                 return 'IBM851';
9927
9928                         case '852':
9929                         case 'cp852':
9930                         case 'cspcp852':
9931                         case 'ibm852':
9932                                 return 'IBM852';
9933
9934                         case '855':
9935                         case 'cp855':
9936                         case 'csibm855':
9937                         case 'ibm855':
9938                                 return 'IBM855';
9939
9940                         case '857':
9941                         case 'cp857':
9942                         case 'csibm857':
9943                         case 'ibm857':
9944                                 return 'IBM857';
9945
9946                         case '860':
9947                         case 'cp860':
9948                         case 'csibm860':
9949                         case 'ibm860':
9950                                 return 'IBM860';
9951
9952                         case '861':
9953                         case 'cp861':
9954                         case 'cpis':
9955                         case 'csibm861':
9956                         case 'ibm861':
9957                                 return 'IBM861';
9958
9959                         case '862':
9960                         case 'cp862':
9961                         case 'cspc862latinhebrew':
9962                         case 'ibm862':
9963                                 return 'IBM862';
9964
9965                         case '863':
9966                         case 'cp863':
9967                         case 'csibm863':
9968                         case 'ibm863':
9969                                 return 'IBM863';
9970
9971                         case 'cp864':
9972                         case 'csibm864':
9973                         case 'ibm864':
9974                                 return 'IBM864';
9975
9976                         case '865':
9977                         case 'cp865':
9978                         case 'csibm865':
9979                         case 'ibm865':
9980                                 return 'IBM865';
9981
9982                         case '866':
9983                         case 'cp866':
9984                         case 'csibm866':
9985                         case 'ibm866':
9986                                 return 'IBM866';
9987
9988                         case 'cp868':
9989                         case 'cpar':
9990                         case 'csibm868':
9991                         case 'ibm868':
9992                                 return 'IBM868';
9993
9994                         case '869':
9995                         case 'cp869':
9996                         case 'cpgr':
9997                         case 'csibm869':
9998                         case 'ibm869':
9999                                 return 'IBM869';
10000
10001                         case 'cp870':
10002                         case 'csibm870':
10003                         case 'ebcdiccproece':
10004                         case 'ebcdiccpyu':
10005                         case 'ibm870':
10006                                 return 'IBM870';
10007
10008                         case 'cp871':
10009                         case 'csibm871':
10010                         case 'ebcdiccpis':
10011                         case 'ibm871':
10012                                 return 'IBM871';
10013
10014                         case 'cp880':
10015                         case 'csibm880':
10016                         case 'ebcdiccyrillic':
10017                         case 'ibm880':
10018                                 return 'IBM880';
10019
10020                         case 'cp891':
10021                         case 'csibm891':
10022                         case 'ibm891':
10023                                 return 'IBM891';
10024
10025                         case 'cp903':
10026                         case 'csibm903':
10027                         case 'ibm903':
10028                                 return 'IBM903';
10029
10030                         case '904':
10031                         case 'cp904':
10032                         case 'csibbm904':
10033                         case 'ibm904':
10034                                 return 'IBM904';
10035
10036                         case 'cp905':
10037                         case 'csibm905':
10038                         case 'ebcdiccptr':
10039                         case 'ibm905':
10040                                 return 'IBM905';
10041
10042                         case 'cp918':
10043                         case 'csibm918':
10044                         case 'ebcdiccpar2':
10045                         case 'ibm918':
10046                                 return 'IBM918';
10047
10048                         case 'cp1026':
10049                         case 'csibm1026':
10050                         case 'ibm1026':
10051                                 return 'IBM1026';
10052
10053                         case 'ibm1047':
10054                                 return 'IBM1047';
10055
10056                         case 'csiso143iecp271':
10057                         case 'iecp271':
10058                         case 'isoir143':
10059                                 return 'IEC_P27-1';
10060
10061                         case 'csiso49inis':
10062                         case 'inis':
10063                         case 'isoir49':
10064                                 return 'INIS';
10065
10066                         case 'csiso50inis8':
10067                         case 'inis8':
10068                         case 'isoir50':
10069                                 return 'INIS-8';
10070
10071                         case 'csiso51iniscyrillic':
10072                         case 'iniscyrillic':
10073                         case 'isoir51':
10074                                 return 'INIS-cyrillic';
10075
10076                         case 'csinvariant':
10077                         case 'invariant':
10078                                 return 'INVARIANT';
10079
10080                         case 'iso2022cn':
10081                                 return 'ISO-2022-CN';
10082
10083                         case 'iso2022cnext':
10084                                 return 'ISO-2022-CN-EXT';
10085
10086                         case 'csiso2022jp':
10087                         case 'iso2022jp':
10088                                 return 'ISO-2022-JP';
10089
10090                         case 'csiso2022jp2':
10091                         case 'iso2022jp2':
10092                                 return 'ISO-2022-JP-2';
10093
10094                         case 'csiso2022kr':
10095                         case 'iso2022kr':
10096                                 return 'ISO-2022-KR';
10097
10098                         case 'cswindows30latin1':
10099                         case 'iso88591windows30latin1':
10100                                 return 'ISO-8859-1-Windows-3.0-Latin-1';
10101
10102                         case 'cswindows31latin1':
10103                         case 'iso88591windows31latin1':
10104                                 return 'ISO-8859-1-Windows-3.1-Latin-1';
10105
10106                         case 'csisolatin2':
10107                         case 'iso88592':
10108                         case 'iso885921987':
10109                         case 'isoir101':
10110                         case 'l2':
10111                         case 'latin2':
10112                                 return 'ISO-8859-2';
10113
10114                         case 'cswindows31latin2':
10115                         case 'iso88592windowslatin2':
10116                                 return 'ISO-8859-2-Windows-Latin-2';
10117
10118                         case 'csisolatin3':
10119                         case 'iso88593':
10120                         case 'iso885931988':
10121                         case 'isoir109':
10122                         case 'l3':
10123                         case 'latin3':
10124                                 return 'ISO-8859-3';
10125
10126                         case 'csisolatin4':
10127                         case 'iso88594':
10128                         case 'iso885941988':
10129                         case 'isoir110':
10130                         case 'l4':
10131                         case 'latin4':
10132                                 return 'ISO-8859-4';
10133
10134                         case 'csisolatincyrillic':
10135                         case 'cyrillic':
10136                         case 'iso88595':
10137                         case 'iso885951988':
10138                         case 'isoir144':
10139                                 return 'ISO-8859-5';
10140
10141                         case 'arabic':
10142                         case 'asmo708':
10143                         case 'csisolatinarabic':
10144                         case 'ecma114':
10145                         case 'iso88596':
10146                         case 'iso885961987':
10147                         case 'isoir127':
10148                                 return 'ISO-8859-6';
10149
10150                         case 'csiso88596e':
10151                         case 'iso88596e':
10152                                 return 'ISO-8859-6-E';
10153
10154                         case 'csiso88596i':
10155                         case 'iso88596i':
10156                                 return 'ISO-8859-6-I';
10157
10158                         case 'csisolatingreek':
10159                         case 'ecma118':
10160                         case 'elot928':
10161                         case 'greek':
10162                         case 'greek8':
10163                         case 'iso88597':
10164                         case 'iso885971987':
10165                         case 'isoir126':
10166                                 return 'ISO-8859-7';
10167
10168                         case 'csisolatinhebrew':
10169                         case 'hebrew':
10170                         case 'iso88598':
10171                         case 'iso885981988':
10172                         case 'isoir138':
10173                                 return 'ISO-8859-8';
10174
10175                         case 'csiso88598e':
10176                         case 'iso88598e':
10177                                 return 'ISO-8859-8-E';
10178
10179                         case 'csiso88598i':
10180                         case 'iso88598i':
10181                                 return 'ISO-8859-8-I';
10182
10183                         case 'cswindows31latin5':
10184                         case 'iso88599windowslatin5':
10185                                 return 'ISO-8859-9-Windows-Latin-5';
10186
10187                         case 'csisolatin6':
10188                         case 'iso885910':
10189                         case 'iso8859101992':
10190                         case 'isoir157':
10191                         case 'l6':
10192                         case 'latin6':
10193                                 return 'ISO-8859-10';
10194
10195                         case 'iso885913':
10196                                 return 'ISO-8859-13';
10197
10198                         case 'iso885914':
10199                         case 'iso8859141998':
10200                         case 'isoceltic':
10201                         case 'isoir199':
10202                         case 'l8':
10203                         case 'latin8':
10204                                 return 'ISO-8859-14';
10205
10206                         case 'iso885915':
10207                         case 'latin9':
10208                                 return 'ISO-8859-15';
10209
10210                         case 'iso885916':
10211                         case 'iso8859162001':
10212                         case 'isoir226':
10213                         case 'l10':
10214                         case 'latin10':
10215                                 return 'ISO-8859-16';
10216
10217                         case 'iso10646j1':
10218                                 return 'ISO-10646-J-1';
10219
10220                         case 'csunicode':
10221                         case 'iso10646ucs2':
10222                                 return 'ISO-10646-UCS-2';
10223
10224                         case 'csucs4':
10225                         case 'iso10646ucs4':
10226                                 return 'ISO-10646-UCS-4';
10227
10228                         case 'csunicodeascii':
10229                         case 'iso10646ucsbasic':
10230                                 return 'ISO-10646-UCS-Basic';
10231
10232                         case 'csunicodelatin1':
10233                         case 'iso10646':
10234                         case 'iso10646unicodelatin1':
10235                                 return 'ISO-10646-Unicode-Latin1';
10236
10237                         case 'csiso10646utf1':
10238                         case 'iso10646utf1':
10239                                 return 'ISO-10646-UTF-1';
10240
10241                         case 'csiso115481':
10242                         case 'iso115481':
10243                         case 'isotr115481':
10244                                 return 'ISO-11548-1';
10245
10246                         case 'csiso90':
10247                         case 'isoir90':
10248                                 return 'iso-ir-90';
10249
10250                         case 'csunicodeibm1261':
10251                         case 'isounicodeibm1261':
10252                                 return 'ISO-Unicode-IBM-1261';
10253
10254                         case 'csunicodeibm1264':
10255                         case 'isounicodeibm1264':
10256                                 return 'ISO-Unicode-IBM-1264';
10257
10258                         case 'csunicodeibm1265':
10259                         case 'isounicodeibm1265':
10260                                 return 'ISO-Unicode-IBM-1265';
10261
10262                         case 'csunicodeibm1268':
10263                         case 'isounicodeibm1268':
10264                                 return 'ISO-Unicode-IBM-1268';
10265
10266                         case 'csunicodeibm1276':
10267                         case 'isounicodeibm1276':
10268                                 return 'ISO-Unicode-IBM-1276';
10269
10270                         case 'csiso646basic1983':
10271                         case 'iso646basic1983':
10272                         case 'ref':
10273                                 return 'ISO_646.basic:1983';
10274
10275                         case 'csiso2intlrefversion':
10276                         case 'irv':
10277                         case 'iso646irv1983':
10278                         case 'isoir2':
10279                                 return 'ISO_646.irv:1983';
10280
10281                         case 'csiso2033':
10282                         case 'e13b':
10283                         case 'iso20331983':
10284                         case 'isoir98':
10285                                 return 'ISO_2033-1983';
10286
10287                         case 'csiso5427cyrillic':
10288                         case 'iso5427':
10289                         case 'isoir37':
10290                                 return 'ISO_5427';
10291
10292                         case 'iso5427cyrillic1981':
10293                         case 'iso54271981':
10294                         case 'isoir54':
10295                                 return 'ISO_5427:1981';
10296
10297                         case 'csiso5428greek':
10298                         case 'iso54281980':
10299                         case 'isoir55':
10300                                 return 'ISO_5428:1980';
10301
10302                         case 'csiso6937add':
10303                         case 'iso6937225':
10304                         case 'isoir152':
10305                                 return 'ISO_6937-2-25';
10306
10307                         case 'csisotextcomm':
10308                         case 'iso69372add':
10309                         case 'isoir142':
10310                                 return 'ISO_6937-2-add';
10311
10312                         case 'csiso8859supp':
10313                         case 'iso8859supp':
10314                         case 'isoir154':
10315                         case 'latin125':
10316                                 return 'ISO_8859-supp';
10317
10318                         case 'csiso10367box':
10319                         case 'iso10367box':
10320                         case 'isoir155':
10321                                 return 'ISO_10367-box';
10322
10323                         case 'csiso15italian':
10324                         case 'iso646it':
10325                         case 'isoir15':
10326                         case 'it':
10327                                 return 'IT';
10328
10329                         case 'csiso13jisc6220jp':
10330                         case 'isoir13':
10331                         case 'jisc62201969':
10332                         case 'jisc62201969jp':
10333                         case 'katakana':
10334                         case 'x2017':
10335                                 return 'JIS_C6220-1969-jp';
10336
10337                         case 'csiso14jisc6220ro':
10338                         case 'iso646jp':
10339                         case 'isoir14':
10340                         case 'jisc62201969ro':
10341                         case 'jp':
10342                                 return 'JIS_C6220-1969-ro';
10343
10344                         case 'csiso42jisc62261978':
10345                         case 'isoir42':
10346                         case 'jisc62261978':
10347                                 return 'JIS_C6226-1978';
10348
10349                         case 'csiso87jisx208':
10350                         case 'isoir87':
10351                         case 'jisc62261983':
10352                         case 'jisx2081983':
10353                         case 'x208':
10354                                 return 'JIS_C6226-1983';
10355
10356                         case 'csiso91jisc62291984a':
10357                         case 'isoir91':
10358                         case 'jisc62291984a':
10359                         case 'jpocra':
10360                                 return 'JIS_C6229-1984-a';
10361
10362                         case 'csiso92jisc62991984b':
10363                         case 'iso646jpocrb':
10364                         case 'isoir92':
10365                         case 'jisc62291984b':
10366                         case 'jpocrb':
10367                                 return 'JIS_C6229-1984-b';
10368
10369                         case 'csiso93jis62291984badd':
10370                         case 'isoir93':
10371                         case 'jisc62291984badd':
10372                         case 'jpocrbadd':
10373                                 return 'JIS_C6229-1984-b-add';
10374
10375                         case 'csiso94jis62291984hand':
10376                         case 'isoir94':
10377                         case 'jisc62291984hand':
10378                         case 'jpocrhand':
10379                                 return 'JIS_C6229-1984-hand';
10380
10381                         case 'csiso95jis62291984handadd':
10382                         case 'isoir95':
10383                         case 'jisc62291984handadd':
10384                         case 'jpocrhandadd':
10385                                 return 'JIS_C6229-1984-hand-add';
10386
10387                         case 'csiso96jisc62291984kana':
10388                         case 'isoir96':
10389                         case 'jisc62291984kana':
10390                                 return 'JIS_C6229-1984-kana';
10391
10392                         case 'csjisencoding':
10393                         case 'jisencoding':
10394                                 return 'JIS_Encoding';
10395
10396                         case 'cshalfwidthkatakana':
10397                         case 'jisx201':
10398                         case 'x201':
10399                                 return 'JIS_X0201';
10400
10401                         case 'csiso159jisx2121990':
10402                         case 'isoir159':
10403                         case 'jisx2121990':
10404                         case 'x212':
10405                                 return 'JIS_X0212-1990';
10406
10407                         case 'csiso141jusib1002':
10408                         case 'iso646yu':
10409                         case 'isoir141':
10410                         case 'js':
10411                         case 'jusib1002':
10412                         case 'yu':
10413                                 return 'JUS_I.B1.002';
10414
10415                         case 'csiso147macedonian':
10416                         case 'isoir147':
10417                         case 'jusib1003mac':
10418                         case 'macedonian':
10419                                 return 'JUS_I.B1.003-mac';
10420
10421                         case 'csiso146serbian':
10422                         case 'isoir146':
10423                         case 'jusib1003serb':
10424                         case 'serbian':
10425                                 return 'JUS_I.B1.003-serb';
10426
10427                         case 'koi7switched':
10428                                 return 'KOI7-switched';
10429
10430                         case 'cskoi8r':
10431                         case 'koi8r':
10432                                 return 'KOI8-R';
10433
10434                         case 'koi8u':
10435                                 return 'KOI8-U';
10436
10437                         case 'csksc5636':
10438                         case 'iso646kr':
10439                         case 'ksc5636':
10440                                 return 'KSC5636';
10441
10442                         case 'cskz1048':
10443                         case 'kz1048':
10444                         case 'rk1048':
10445                         case 'strk10482002':
10446                                 return 'KZ-1048';
10447
10448                         case 'csiso19latingreek':
10449                         case 'isoir19':
10450                         case 'latingreek':
10451                                 return 'latin-greek';
10452
10453                         case 'csiso27latingreek1':
10454                         case 'isoir27':
10455                         case 'latingreek1':
10456                                 return 'Latin-greek-1';
10457
10458                         case 'csiso158lap':
10459                         case 'isoir158':
10460                         case 'lap':
10461                         case 'latinlap':
10462                                 return 'latin-lap';
10463
10464                         case 'csmacintosh':
10465                         case 'mac':
10466                         case 'macintosh':
10467                                 return 'macintosh';
10468
10469                         case 'csmicrosoftpublishing':
10470                         case 'microsoftpublishing':
10471                                 return 'Microsoft-Publishing';
10472
10473                         case 'csmnem':
10474                         case 'mnem':
10475                                 return 'MNEM';
10476
10477                         case 'csmnemonic':
10478                         case 'mnemonic':
10479                                 return 'MNEMONIC';
10480
10481                         case 'csiso86hungarian':
10482                         case 'hu':
10483                         case 'iso646hu':
10484                         case 'isoir86':
10485                         case 'msz77953':
10486                                 return 'MSZ_7795.3';
10487
10488                         case 'csnatsdano':
10489                         case 'isoir91':
10490                         case 'natsdano':
10491                                 return 'NATS-DANO';
10492
10493                         case 'csnatsdanoadd':
10494                         case 'isoir92':
10495                         case 'natsdanoadd':
10496                                 return 'NATS-DANO-ADD';
10497
10498                         case 'csnatssefi':
10499                         case 'isoir81':
10500                         case 'natssefi':
10501                                 return 'NATS-SEFI';
10502
10503                         case 'csnatssefiadd':
10504                         case 'isoir82':
10505                         case 'natssefiadd':
10506                                 return 'NATS-SEFI-ADD';
10507
10508                         case 'csiso151cuba':
10509                         case 'cuba':
10510                         case 'iso646cu':
10511                         case 'isoir151':
10512                         case 'ncnc1081':
10513                                 return 'NC_NC00-10:81';
10514
10515                         case 'csiso69french':
10516                         case 'fr':
10517                         case 'iso646fr':
10518                         case 'isoir69':
10519                         case 'nfz62010':
10520                                 return 'NF_Z_62-010';
10521
10522                         case 'csiso25french':
10523                         case 'iso646fr1':
10524                         case 'isoir25':
10525                         case 'nfz620101973':
10526                                 return 'NF_Z_62-010_(1973)';
10527
10528                         case 'csiso60danishnorwegian':
10529                         case 'csiso60norwegian1':
10530                         case 'iso646no':
10531                         case 'isoir60':
10532                         case 'no':
10533                         case 'ns45511':
10534                                 return 'NS_4551-1';
10535
10536                         case 'csiso61norwegian2':
10537                         case 'iso646no2':
10538                         case 'isoir61':
10539                         case 'no2':
10540                         case 'ns45512':
10541                                 return 'NS_4551-2';
10542
10543                         case 'osdebcdicdf3irv':
10544                                 return 'OSD_EBCDIC_DF03_IRV';
10545
10546                         case 'osdebcdicdf41':
10547                                 return 'OSD_EBCDIC_DF04_1';
10548
10549                         case 'osdebcdicdf415':
10550                                 return 'OSD_EBCDIC_DF04_15';
10551
10552                         case 'cspc8danishnorwegian':
10553                         case 'pc8danishnorwegian':
10554                                 return 'PC8-Danish-Norwegian';
10555
10556                         case 'cspc8turkish':
10557                         case 'pc8turkish':
10558                                 return 'PC8-Turkish';
10559
10560                         case 'csiso16portuguese':
10561                         case 'iso646pt':
10562                         case 'isoir16':
10563                         case 'pt':
10564                                 return 'PT';
10565
10566                         case 'csiso84portuguese2':
10567                         case 'iso646pt2':
10568                         case 'isoir84':
10569                         case 'pt2':
10570                                 return 'PT2';
10571
10572                         case 'cp154':
10573                         case 'csptcp154':
10574                         case 'cyrillicasian':
10575                         case 'pt154':
10576                         case 'ptcp154':
10577                                 return 'PTCP154';
10578
10579                         case 'scsu':
10580                                 return 'SCSU';
10581
10582                         case 'csiso10swedish':
10583                         case 'fi':
10584                         case 'iso646fi':
10585                         case 'iso646se':
10586                         case 'isoir10':
10587                         case 'se':
10588                         case 'sen850200b':
10589                                 return 'SEN_850200_B';
10590
10591                         case 'csiso11swedishfornames':
10592                         case 'iso646se2':
10593                         case 'isoir11':
10594                         case 'se2':
10595                         case 'sen850200c':
10596                                 return 'SEN_850200_C';
10597
10598                         case 'csshiftjis':
10599                         case 'mskanji':
10600                         case 'shiftjis':
10601                                 return 'Shift_JIS';
10602
10603                         case 'csiso102t617bit':
10604                         case 'isoir102':
10605                         case 't617bit':
10606                                 return 'T.61-7bit';
10607
10608                         case 'csiso103t618bit':
10609                         case 'isoir103':
10610                         case 't61':
10611                         case 't618bit':
10612                                 return 'T.61-8bit';
10613
10614                         case 'csiso128t101g2':
10615                         case 'isoir128':
10616                         case 't101g2':
10617                                 return 'T.101-G2';
10618
10619                         case 'cstscii':
10620                         case 'tscii':
10621                                 return 'TSCII';
10622
10623                         case 'csunicode11':
10624                         case 'unicode11':
10625                                 return 'UNICODE-1-1';
10626
10627                         case 'csunicode11utf7':
10628                         case 'unicode11utf7':
10629                                 return 'UNICODE-1-1-UTF-7';
10630
10631                         case 'csunknown8bit':
10632                         case 'unknown8bit':
10633                                 return 'UNKNOWN-8BIT';
10634
10635                         case 'ansix341968':
10636                         case 'ansix341986':
10637                         case 'ascii':
10638                         case 'cp367':
10639                         case 'csascii':
10640                         case 'ibm367':
10641                         case 'iso646irv1991':
10642                         case 'iso646us':
10643                         case 'isoir6':
10644                         case 'us':
10645                         case 'usascii':
10646                                 return 'US-ASCII';
10647
10648                         case 'csusdk':
10649                         case 'usdk':
10650                                 return 'us-dk';
10651
10652                         case 'utf7':
10653                                 return 'UTF-7';
10654
10655                         case 'utf8':
10656                                 return 'UTF-8';
10657
10658                         case 'utf16':
10659                                 return 'UTF-16';
10660
10661                         case 'utf16be':
10662                                 return 'UTF-16BE';
10663
10664                         case 'utf16le':
10665                                 return 'UTF-16LE';
10666
10667                         case 'utf32':
10668                                 return 'UTF-32';
10669
10670                         case 'utf32be':
10671                                 return 'UTF-32BE';
10672
10673                         case 'utf32le':
10674                                 return 'UTF-32LE';
10675
10676                         case 'csventurainternational':
10677                         case 'venturainternational':
10678                                 return 'Ventura-International';
10679
10680                         case 'csventuramath':
10681                         case 'venturamath':
10682                                 return 'Ventura-Math';
10683
10684                         case 'csventuraus':
10685                         case 'venturaus':
10686                                 return 'Ventura-US';
10687
10688                         case 'csiso70videotexsupp1':
10689                         case 'isoir70':
10690                         case 'videotexsuppl':
10691                                 return 'videotex-suppl';
10692
10693                         case 'csviqr':
10694                         case 'viqr':
10695                                 return 'VIQR';
10696
10697                         case 'csviscii':
10698                         case 'viscii':
10699                                 return 'VISCII';
10700
10701                         case 'cswindows31j':
10702                         case 'windows31j':
10703                                 return 'Windows-31J';
10704
10705                         case 'iso885911':
10706                         case 'tis620':
10707                                 return 'windows-874';
10708
10709                         case 'cseuckr':
10710                         case 'csksc56011987':
10711                         case 'euckr':
10712                         case 'isoir149':
10713                         case 'korean':
10714                         case 'ksc5601':
10715                         case 'ksc56011987':
10716                         case 'ksc56011989':
10717                         case 'windows949':
10718                                 return 'windows-949';
10719
10720                         case 'windows1250':
10721                                 return 'windows-1250';
10722
10723                         case 'windows1251':
10724                                 return 'windows-1251';
10725
10726                         case 'cp819':
10727                         case 'csisolatin1':
10728                         case 'ibm819':
10729                         case 'iso88591':
10730                         case 'iso885911987':
10731                         case 'isoir100':
10732                         case 'l1':
10733                         case 'latin1':
10734                         case 'windows1252':
10735                                 return 'windows-1252';
10736
10737                         case 'windows1253':
10738                                 return 'windows-1253';
10739
10740                         case 'csisolatin5':
10741                         case 'iso88599':
10742                         case 'iso885991989':
10743                         case 'isoir148':
10744                         case 'l5':
10745                         case 'latin5':
10746                         case 'windows1254':
10747                                 return 'windows-1254';
10748
10749                         case 'windows1255':
10750                                 return 'windows-1255';
10751
10752                         case 'windows1256':
10753                                 return 'windows-1256';
10754
10755                         case 'windows1257':
10756                                 return 'windows-1257';
10757
10758                         case 'windows1258':
10759                                 return 'windows-1258';
10760
10761                         default:
10762                                 return $charset;
10763                 }
10764         }
10765
10766         function get_curl_version()
10767         {
10768                 if (is_array($curl = curl_version()))
10769                 {
10770                         $curl = $curl['version'];
10771                 }
10772                 elseif (substr($curl, 0, 5) === 'curl/')
10773                 {
10774                         $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10775                 }
10776                 elseif (substr($curl, 0, 8) === 'libcurl/')
10777                 {
10778                         $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10779                 }
10780                 else
10781                 {
10782                         $curl = 0;
10783                 }
10784                 return $curl;
10785         }
10786
10787         function is_subclass_of($class1, $class2)
10788         {
10789                 if (func_num_args() !== 2)
10790                 {
10791                         trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10792                 }
10793                 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10794                 {
10795                         return is_subclass_of($class1, $class2);
10796                 }
10797                 elseif (is_string($class1) && is_string($class2))
10798                 {
10799                         if (class_exists($class1))
10800                         {
10801                                 if (class_exists($class2))
10802                                 {
10803                                         $class2 = strtolower($class2);
10804                                         while ($class1 = strtolower(get_parent_class($class1)))
10805                                         {
10806                                                 if ($class1 === $class2)
10807                                                 {
10808                                                         return true;
10809                                                 }
10810                                         }
10811                                 }
10812                         }
10813                         else
10814                         {
10815                                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10816                         }
10817                 }
10818                 return false;
10819         }
10820
10821         /**
10822          * Strip HTML comments
10823          *
10824          * @access public
10825          * @param string $data Data to strip comments from
10826          * @return string Comment stripped string
10827          */
10828         function strip_comments($data)
10829         {
10830                 $output = '';
10831                 while (($start = strpos($data, '<!--')) !== false)
10832                 {
10833                         $output .= substr($data, 0, $start);
10834                         if (($end = strpos($data, '-->', $start)) !== false)
10835                         {
10836                                 $data = substr_replace($data, '', 0, $end + 3);
10837                         }
10838                         else
10839                         {
10840                                 $data = '';
10841                         }
10842                 }
10843                 return $output . $data;
10844         }
10845
10846         function parse_date($dt)
10847         {
10848                 $parser = SimplePie_Parse_Date::get();
10849                 return $parser->parse($dt);
10850         }
10851
10852         /**
10853          * Decode HTML entities
10854          *
10855          * @static
10856          * @access public
10857          * @param string $data Input data
10858          * @return string Output data
10859          */
10860         function entities_decode($data)
10861         {
10862                 $decoder =& new SimplePie_Decode_HTML_Entities($data);
10863                 return $decoder->parse();
10864         }
10865
10866         /**
10867          * Remove RFC822 comments
10868          *
10869          * @access public
10870          * @param string $data Data to strip comments from
10871          * @return string Comment stripped string
10872          */
10873         function uncomment_rfc822($string)
10874         {
10875                 $string = (string) $string;
10876                 $position = 0;
10877                 $length = strlen($string);
10878                 $depth = 0;
10879
10880                 $output = '';
10881
10882                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10883                 {
10884                         $output .= substr($string, $position, $pos - $position);
10885                         $position = $pos + 1;
10886                         if ($string[$pos - 1] !== '\\')
10887                         {
10888                                 $depth++;
10889                                 while ($depth && $position < $length)
10890                                 {
10891                                         $position += strcspn($string, '()', $position);
10892                                         if ($string[$position - 1] === '\\')
10893                                         {
10894                                                 $position++;
10895                                                 continue;
10896                                         }
10897                                         elseif (isset($string[$position]))
10898                                         {
10899                                                 switch ($string[$position])
10900                                                 {
10901                                                         case '(':
10902                                                                 $depth++;
10903                                                                 break;
10904
10905                                                         case ')':
10906                                                                 $depth--;
10907                                                                 break;
10908                                                 }
10909                                                 $position++;
10910                                         }
10911                                         else
10912                                         {
10913                                                 break;
10914                                         }
10915                                 }
10916                         }
10917                         else
10918                         {
10919                                 $output .= '(';
10920                         }
10921                 }
10922                 $output .= substr($string, $position);
10923
10924                 return $output;
10925         }
10926
10927         function parse_mime($mime)
10928         {
10929                 if (($pos = strpos($mime, ';')) === false)
10930                 {
10931                         return trim($mime);
10932                 }
10933                 else
10934                 {
10935                         return trim(substr($mime, 0, $pos));
10936                 }
10937         }
10938
10939         function htmlspecialchars_decode($string, $quote_style)
10940         {
10941                 if (function_exists('htmlspecialchars_decode'))
10942                 {
10943                         return htmlspecialchars_decode($string, $quote_style);
10944                 }
10945                 else
10946                 {
10947                         return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10948                 }
10949         }
10950
10951         function atom_03_construct_type($attribs)
10952         {
10953                 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10954                 {
10955                         $mode = SIMPLEPIE_CONSTRUCT_BASE64;
10956                 }
10957                 else
10958                 {
10959                         $mode = SIMPLEPIE_CONSTRUCT_NONE;
10960                 }
10961                 if (isset($attribs['']['type']))
10962                 {
10963                         switch (strtolower(trim($attribs['']['type'])))
10964                         {
10965                                 case 'text':
10966                                 case 'text/plain':
10967                                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10968
10969                                 case 'html':
10970                                 case 'text/html':
10971                                         return SIMPLEPIE_CONSTRUCT_HTML | $mode;
10972
10973                                 case 'xhtml':
10974                                 case 'application/xhtml+xml':
10975                                         return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
10976
10977                                 default:
10978                                         return SIMPLEPIE_CONSTRUCT_NONE | $mode;
10979                         }
10980                 }
10981                 else
10982                 {
10983                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10984                 }
10985         }
10986
10987         function atom_10_construct_type($attribs)
10988         {
10989                 if (isset($attribs['']['type']))
10990                 {
10991                         switch (strtolower(trim($attribs['']['type'])))
10992                         {
10993                                 case 'text':
10994                                         return SIMPLEPIE_CONSTRUCT_TEXT;
10995
10996                                 case 'html':
10997                                         return SIMPLEPIE_CONSTRUCT_HTML;
10998
10999                                 case 'xhtml':
11000                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11001
11002                                 default:
11003                                         return SIMPLEPIE_CONSTRUCT_NONE;
11004                         }
11005                 }
11006                 return SIMPLEPIE_CONSTRUCT_TEXT;
11007         }
11008
11009         function atom_10_content_construct_type($attribs)
11010         {
11011                 if (isset($attribs['']['type']))
11012                 {
11013                         $type = strtolower(trim($attribs['']['type']));
11014                         switch ($type)
11015                         {
11016                                 case 'text':
11017                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11018
11019                                 case 'html':
11020                                         return SIMPLEPIE_CONSTRUCT_HTML;
11021
11022                                 case 'xhtml':
11023                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11024                         }
11025                         if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11026                         {
11027                                 return SIMPLEPIE_CONSTRUCT_NONE;
11028                         }
11029                         else
11030                         {
11031                                 return SIMPLEPIE_CONSTRUCT_BASE64;
11032                         }
11033                 }
11034                 else
11035                 {
11036                         return SIMPLEPIE_CONSTRUCT_TEXT;
11037                 }
11038         }
11039
11040         function is_isegment_nz_nc($string)
11041         {
11042                 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);
11043         }
11044
11045         function space_seperated_tokens($string)
11046         {
11047                 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11048                 $string_length = strlen($string);
11049
11050                 $position = strspn($string, $space_characters);
11051                 $tokens = array();
11052
11053                 while ($position < $string_length)
11054                 {
11055                         $len = strcspn($string, $space_characters, $position);
11056                         $tokens[] = substr($string, $position, $len);
11057                         $position += $len;
11058                         $position += strspn($string, $space_characters, $position);
11059                 }
11060
11061                 return $tokens;
11062         }
11063
11064         function array_unique($array)
11065         {
11066                 if (version_compare(PHP_VERSION, '5.2', '>='))
11067                 {
11068                         return array_unique($array);
11069                 }
11070                 else
11071                 {
11072                         $array = (array) $array;
11073                         $new_array = array();
11074                         $new_array_strings = array();
11075                         foreach ($array as $key => $value)
11076                         {
11077                                 if (is_object($value))
11078                                 {
11079                                         if (method_exists($value, '__toString'))
11080                                         {
11081                                                 $cmp = $value->__toString();
11082                                         }
11083                                         else
11084                                         {
11085                                                 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11086                                         }
11087                                 }
11088                                 elseif (is_array($value))
11089                                 {
11090                                         $cmp = (string) reset($value);
11091                                 }
11092                                 else
11093                                 {
11094                                         $cmp = (string) $value;
11095                                 }
11096                                 if (!in_array($cmp, $new_array_strings))
11097                                 {
11098                                         $new_array[$key] = $value;
11099                                         $new_array_strings[] = $cmp;
11100                                 }
11101                         }
11102                         return $new_array;
11103                 }
11104         }
11105
11106         /**
11107          * Converts a unicode codepoint to a UTF-8 character
11108          *
11109          * @static
11110          * @access public
11111          * @param int $codepoint Unicode codepoint
11112          * @return string UTF-8 character
11113          */
11114         function codepoint_to_utf8($codepoint)
11115         {
11116                 $codepoint = (int) $codepoint;
11117                 if ($codepoint < 0)
11118                 {
11119                         return false;
11120                 }
11121                 else if ($codepoint <= 0x7f)
11122                 {
11123                         return chr($codepoint);
11124                 }
11125                 else if ($codepoint <= 0x7ff)
11126                 {
11127                         return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11128                 }
11129                 else if ($codepoint <= 0xffff)
11130                 {
11131                         return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11132                 }
11133                 else if ($codepoint <= 0x10ffff)
11134                 {
11135                         return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11136                 }
11137                 else
11138                 {
11139                         // U+FFFD REPLACEMENT CHARACTER
11140                         return "\xEF\xBF\xBD";
11141                 }
11142         }
11143
11144         /**
11145          * Re-implementation of PHP 5's stripos()
11146          *
11147          * Returns the numeric position of the first occurrence of needle in the
11148          * haystack string.
11149          *
11150          * @static
11151          * @access string
11152          * @param object $haystack
11153          * @param string $needle Note that the needle may be a string of one or more
11154          *     characters. If needle is not a string, it is converted to an integer
11155          *     and applied as the ordinal value of a character.
11156          * @param int $offset The optional offset parameter allows you to specify which
11157          *     character in haystack to start searching. The position returned is still
11158          *     relative to the beginning of haystack.
11159          * @return bool If needle is not found, stripos() will return boolean false.
11160          */
11161         function stripos($haystack, $needle, $offset = 0)
11162         {
11163                 if (function_exists('stripos'))
11164                 {
11165                         return stripos($haystack, $needle, $offset);
11166                 }
11167                 else
11168                 {
11169                         if (is_string($needle))
11170                         {
11171                                 $needle = strtolower($needle);
11172                         }
11173                         elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11174                         {
11175                                 $needle = strtolower(chr($needle));
11176                         }
11177                         else
11178                         {
11179                                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11180                                 return false;
11181                         }
11182
11183                         return strpos(strtolower($haystack), $needle, $offset);
11184                 }
11185         }
11186
11187         /**
11188          * Similar to parse_str()
11189          *
11190          * Returns an associative array of name/value pairs, where the value is an
11191          * array of values that have used the same name
11192          *
11193          * @static
11194          * @access string
11195          * @param string $str The input string.
11196          * @return array
11197          */
11198         function parse_str($str)
11199         {
11200                 $return = array();
11201                 $str = explode('&', $str);
11202
11203                 foreach ($str as $section)
11204                 {
11205                         if (strpos($section, '=') !== false)
11206                         {
11207                                 list($name, $value) = explode('=', $section, 2);
11208                                 $return[urldecode($name)][] = urldecode($value);
11209                         }
11210                         else
11211                         {
11212                                 $return[urldecode($section)][] = null;
11213                         }
11214                 }
11215
11216                 return $return;
11217         }
11218
11219         /**
11220          * Detect XML encoding, as per XML 1.0 Appendix F.1
11221          *
11222          * @todo Add support for EBCDIC
11223          * @param string $data XML data
11224          * @return array Possible encodings
11225          */
11226         function xml_encoding($data)
11227         {
11228                 // UTF-32 Big Endian BOM
11229                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11230                 {
11231                         $encoding[] = 'UTF-32BE';
11232                 }
11233                 // UTF-32 Little Endian BOM
11234                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11235                 {
11236                         $encoding[] = 'UTF-32LE';
11237                 }
11238                 // UTF-16 Big Endian BOM
11239                 elseif (substr($data, 0, 2) === "\xFE\xFF")
11240                 {
11241                         $encoding[] = 'UTF-16BE';
11242                 }
11243                 // UTF-16 Little Endian BOM
11244                 elseif (substr($data, 0, 2) === "\xFF\xFE")
11245                 {
11246                         $encoding[] = 'UTF-16LE';
11247                 }
11248                 // UTF-8 BOM
11249                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11250                 {
11251                         $encoding[] = 'UTF-8';
11252                 }
11253                 // UTF-32 Big Endian Without BOM
11254                 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")
11255                 {
11256                         if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11257                         {
11258                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11259                                 if ($parser->parse())
11260                                 {
11261                                         $encoding[] = $parser->encoding;
11262                                 }
11263                         }
11264                         $encoding[] = 'UTF-32BE';
11265                 }
11266                 // UTF-32 Little Endian Without BOM
11267                 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")
11268                 {
11269                         if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11270                         {
11271                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11272                                 if ($parser->parse())
11273                                 {
11274                                         $encoding[] = $parser->encoding;
11275                                 }
11276                         }
11277                         $encoding[] = 'UTF-32LE';
11278                 }
11279                 // UTF-16 Big Endian Without BOM
11280                 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11281                 {
11282                         if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11283                         {
11284                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11285                                 if ($parser->parse())
11286                                 {
11287                                         $encoding[] = $parser->encoding;
11288                                 }
11289                         }
11290                         $encoding[] = 'UTF-16BE';
11291                 }
11292                 // UTF-16 Little Endian Without BOM
11293                 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11294                 {
11295                         if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11296                         {
11297                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11298                                 if ($parser->parse())
11299                                 {
11300                                         $encoding[] = $parser->encoding;
11301                                 }
11302                         }
11303                         $encoding[] = 'UTF-16LE';
11304                 }
11305                 // US-ASCII (or superset)
11306                 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11307                 {
11308                         if ($pos = strpos($data, "\x3F\x3E"))
11309                         {
11310                                 $parser =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11311                                 if ($parser->parse())
11312                                 {
11313                                         $encoding[] = $parser->encoding;
11314                                 }
11315                         }
11316                         $encoding[] = 'UTF-8';
11317                 }
11318                 // Fallback to UTF-8
11319                 else
11320                 {
11321                         $encoding[] = 'UTF-8';
11322                 }
11323                 return $encoding;
11324         }
11325
11326         function output_javascript()
11327         {
11328                 if (function_exists('ob_gzhandler'))
11329                 {
11330                         ob_start('ob_gzhandler');
11331                 }
11332                 header('Content-type: text/javascript; charset: UTF-8');
11333                 header('Cache-Control: must-revalidate');
11334                 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11335                 ?>
11336 function embed_odeo(link) {
11337         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>');
11338 }
11339
11340 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11341         if (placeholder != '') {
11342                 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>');
11343         }
11344         else {
11345                 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>');
11346         }
11347 }
11348
11349 function embed_flash(bgcolor, width, height, link, loop, type) {
11350         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>');
11351 }
11352
11353 function embed_flv(width, height, link, placeholder, loop, player) {
11354         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>');
11355 }
11356
11357 function embed_wmedia(width, height, link) {
11358         document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11359 }
11360                 <?php
11361         }
11362 }
11363
11364 /**
11365  * Decode HTML Entities
11366  *
11367  * This implements HTML5 as of revision 967 (2007-06-28)
11368  *
11369  * @package SimplePie
11370  */
11371 class SimplePie_Decode_HTML_Entities
11372 {
11373         /**
11374          * Data to be parsed
11375          *
11376          * @access private
11377          * @var string
11378          */
11379         var $data = '';
11380
11381         /**
11382          * Currently consumed bytes
11383          *
11384          * @access private
11385          * @var string
11386          */
11387         var $consumed = '';
11388
11389         /**
11390          * Position of the current byte being parsed
11391          *
11392          * @access private
11393          * @var int
11394          */
11395         var $position = 0;
11396
11397         /**
11398          * Create an instance of the class with the input data
11399          *
11400          * @access public
11401          * @param string $data Input data
11402          */
11403         function SimplePie_Decode_HTML_Entities($data)
11404         {
11405                 $this->data = $data;
11406         }
11407
11408         /**
11409          * Parse the input data
11410          *
11411          * @access public
11412          * @return string Output data
11413          */
11414         function parse()
11415         {
11416                 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11417                 {
11418                         $this->consume();
11419                         $this->entity();
11420                         $this->consumed = '';
11421                 }
11422                 return $this->data;
11423         }
11424
11425         /**
11426          * Consume the next byte
11427          *
11428          * @access private
11429          * @return mixed The next byte, or false, if there is no more data
11430          */
11431         function consume()
11432         {
11433                 if (isset($this->data[$this->position]))
11434                 {
11435                         $this->consumed .= $this->data[$this->position];
11436                         return $this->data[$this->position++];
11437                 }
11438                 else
11439                 {
11440                         return false;
11441                 }
11442         }
11443
11444         /**
11445          * Consume a range of characters
11446          *
11447          * @access private
11448          * @param string $chars Characters to consume
11449          * @return mixed A series of characters that match the range, or false
11450          */
11451         function consume_range($chars)
11452         {
11453                 if ($len = strspn($this->data, $chars, $this->position))
11454                 {
11455                         $data = substr($this->data, $this->position, $len);
11456                         $this->consumed .= $data;
11457                         $this->position += $len;
11458                         return $data;
11459                 }
11460                 else
11461                 {
11462                         return false;
11463                 }
11464         }
11465
11466         /**
11467          * Unconsume one byte
11468          *
11469          * @access private
11470          */
11471         function unconsume()
11472         {
11473                 $this->consumed = substr($this->consumed, 0, -1);
11474                 $this->position--;
11475         }
11476
11477         /**
11478          * Decode an entity
11479          *
11480          * @access private
11481          */
11482         function entity()
11483         {
11484                 switch ($this->consume())
11485                 {
11486                         case "\x09":
11487                         case "\x0A":
11488                         case "\x0B":
11489                         case "\x0B":
11490                         case "\x0C":
11491                         case "\x20":
11492                         case "\x3C":
11493                         case "\x26":
11494                         case false:
11495                                 break;
11496
11497                         case "\x23":
11498                                 switch ($this->consume())
11499                                 {
11500                                         case "\x78":
11501                                         case "\x58":
11502                                                 $range = '0123456789ABCDEFabcdef';
11503                                                 $hex = true;
11504                                                 break;
11505
11506                                         default:
11507                                                 $range = '0123456789';
11508                                                 $hex = false;
11509                                                 $this->unconsume();
11510                                                 break;
11511                                 }
11512
11513                                 if ($codepoint = $this->consume_range($range))
11514                                 {
11515                                         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");
11516
11517                                         if ($hex)
11518                                         {
11519                                                 $codepoint = hexdec($codepoint);
11520                                         }
11521                                         else
11522                                         {
11523                                                 $codepoint = intval($codepoint);
11524                                         }
11525
11526                                         if (isset($windows_1252_specials[$codepoint]))
11527                                         {
11528                                                 $replacement = $windows_1252_specials[$codepoint];
11529                                         }
11530                                         else
11531                                         {
11532                                                 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11533                                         }
11534
11535                                         if (!in_array($this->consume(), array(';', false), true))
11536                                         {
11537                                                 $this->unconsume();
11538                                         }
11539
11540                                         $consumed_length = strlen($this->consumed);
11541                                         $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11542                                         $this->position += strlen($replacement) - $consumed_length;
11543                                 }
11544                                 break;
11545
11546                         default:
11547                                 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");
11548
11549                                 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11550                                 {
11551                                         $consumed = substr($this->consumed, 1);
11552                                         if (isset($entities[$consumed]))
11553                                         {
11554                                                 $match = $consumed;
11555                                         }
11556                                 }
11557
11558                                 if ($match !== null)
11559                                 {
11560                                         $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11561                                         $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11562                                 }
11563                                 break;
11564                 }
11565         }
11566 }
11567
11568 /**
11569  * IRI parser/serialiser
11570  *
11571  * @package SimplePie
11572  */
11573 class SimplePie_IRI
11574 {
11575         /**
11576          * Scheme
11577          *
11578          * @access private
11579          * @var string
11580          */
11581         var $scheme;
11582
11583         /**
11584          * User Information
11585          *
11586          * @access private
11587          * @var string
11588          */
11589         var $userinfo;
11590
11591         /**
11592          * Host
11593          *
11594          * @access private
11595          * @var string
11596          */
11597         var $host;
11598
11599         /**
11600          * Port
11601          *
11602          * @access private
11603          * @var string
11604          */
11605         var $port;
11606
11607         /**
11608          * Path
11609          *
11610          * @access private
11611          * @var string
11612          */
11613         var $path;
11614
11615         /**
11616          * Query
11617          *
11618          * @access private
11619          * @var string
11620          */
11621         var $query;
11622
11623         /**
11624          * Fragment
11625          *
11626          * @access private
11627          * @var string
11628          */
11629         var $fragment;
11630
11631         /**
11632          * Whether the object represents a valid IRI
11633          *
11634          * @access private
11635          * @var array
11636          */
11637         var $valid = array();
11638
11639         /**
11640          * Return the entire IRI when you try and read the object as a string
11641          *
11642          * @access public
11643          * @return string
11644          */
11645         function __toString()
11646         {
11647                 return $this->get_iri();
11648         }
11649
11650         /**
11651          * Create a new IRI object, from a specified string
11652          *
11653          * @access public
11654          * @param string $iri
11655          * @return SimplePie_IRI
11656          */
11657         function SimplePie_IRI($iri)
11658         {
11659                 $iri = (string) $iri;
11660                 if ($iri !== '')
11661                 {
11662                         $parsed = $this->parse_iri($iri);
11663                         $this->set_scheme($parsed['scheme']);
11664                         $this->set_authority($parsed['authority']);
11665                         $this->set_path($parsed['path']);
11666                         $this->set_query($parsed['query']);
11667                         $this->set_fragment($parsed['fragment']);
11668                 }
11669         }
11670
11671         /**
11672          * Create a new IRI object by resolving a relative IRI
11673          *
11674          * @static
11675          * @access public
11676          * @param SimplePie_IRI $base Base IRI
11677          * @param string $relative Relative IRI
11678          * @return SimplePie_IRI
11679          */
11680         function absolutize($base, $relative)
11681         {
11682                 $relative = (string) $relative;
11683                 if ($relative !== '')
11684                 {
11685                         $relative =& new SimplePie_IRI($relative);
11686                         if ($relative->get_scheme() !== null)
11687                         {
11688                                 $target = $relative;
11689                         }
11690                         elseif ($base->get_iri() !== null)
11691                         {
11692                                 if ($relative->get_authority() !== null)
11693                                 {
11694                                         $target = $relative;
11695                                         $target->set_scheme($base->get_scheme());
11696                                 }
11697                                 else
11698                                 {
11699                                         $target =& new SimplePie_IRI('');
11700                                         $target->set_scheme($base->get_scheme());
11701                                         $target->set_userinfo($base->get_userinfo());
11702                                         $target->set_host($base->get_host());
11703                                         $target->set_port($base->get_port());
11704                                         if ($relative->get_path() !== null)
11705                                         {
11706                                                 if (strpos($relative->get_path(), '/') === 0)
11707                                                 {
11708                                                         $target->set_path($relative->get_path());
11709                                                 }
11710                                                 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11711                                                 {
11712                                                         $target->set_path('/' . $relative->get_path());
11713                                                 }
11714                                                 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11715                                                 {
11716                                                         $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11717                                                 }
11718                                                 else
11719                                                 {
11720                                                         $target->set_path($relative->get_path());
11721                                                 }
11722                                                 $target->set_query($relative->get_query());
11723                                         }
11724                                         else
11725                                         {
11726                                                 $target->set_path($base->get_path());
11727                                                 if ($relative->get_query() !== null)
11728                                                 {
11729                                                         $target->set_query($relative->get_query());
11730                                                 }
11731                                                 elseif ($base->get_query() !== null)
11732                                                 {
11733                                                         $target->set_query($base->get_query());
11734                                                 }
11735                                         }
11736                                 }
11737                                 $target->set_fragment($relative->get_fragment());
11738                         }
11739                         else
11740                         {
11741                                 // No base URL, just return the relative URL
11742                                 $target = $relative;
11743                         }
11744                 }
11745                 else
11746                 {
11747                         $target = $base;
11748                 }
11749                 return $target;
11750         }
11751
11752         /**
11753          * Parse an IRI into scheme/authority/path/query/fragment segments
11754          *
11755          * @access private
11756          * @param string $iri
11757          * @return array
11758          */
11759         function parse_iri($iri)
11760         {
11761                 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11762                 for ($i = count($match); $i <= 9; $i++)
11763                 {
11764                         $match[$i] = '';
11765                 }
11766                 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11767         }
11768
11769         /**
11770          * Remove dot segments from a path
11771          *
11772          * @access private
11773          * @param string $input
11774          * @return string
11775          */
11776         function remove_dot_segments($input)
11777         {
11778                 $output = '';
11779                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11780                 {
11781                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11782                         if (strpos($input, '../') === 0)
11783                         {
11784                                 $input = substr($input, 3);
11785                         }
11786                         elseif (strpos($input, './') === 0)
11787                         {
11788                                 $input = substr($input, 2);
11789                         }
11790                         // 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,
11791                         elseif (strpos($input, '/./') === 0)
11792                         {
11793                                 $input = substr_replace($input, '/', 0, 3);
11794                         }
11795                         elseif ($input === '/.')
11796                         {
11797                                 $input = '/';
11798                         }
11799                         // 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,
11800                         elseif (strpos($input, '/../') === 0)
11801                         {
11802                                 $input = substr_replace($input, '/', 0, 4);
11803                                 $output = substr_replace($output, '', strrpos($output, '/'));
11804                         }
11805                         elseif ($input === '/..')
11806                         {
11807                                 $input = '/';
11808                                 $output = substr_replace($output, '', strrpos($output, '/'));
11809                         }
11810                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11811                         elseif ($input === '.' || $input === '..')
11812                         {
11813                                 $input = '';
11814                         }
11815                         // 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
11816                         elseif (($pos = strpos($input, '/', 1)) !== false)
11817                         {
11818                                 $output .= substr($input, 0, $pos);
11819                                 $input = substr_replace($input, '', 0, $pos);
11820                         }
11821                         else
11822                         {
11823                                 $output .= $input;
11824                                 $input = '';
11825                         }
11826                 }
11827                 return $output . $input;
11828         }
11829
11830         /**
11831          * Replace invalid character with percent encoding
11832          *
11833          * @access private
11834          * @param string $string Input string
11835          * @param string $valid_chars Valid characters
11836          * @param int $case Normalise case
11837          * @return string
11838          */
11839         function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11840         {
11841                 // Normalise case
11842                 if ($case & SIMPLEPIE_LOWERCASE)
11843                 {
11844                         $string = strtolower($string);
11845                 }
11846                 elseif ($case & SIMPLEPIE_UPPERCASE)
11847                 {
11848                         $string = strtoupper($string);
11849                 }
11850
11851                 // Store position and string length (to avoid constantly recalculating this)
11852                 $position = 0;
11853                 $strlen = strlen($string);
11854
11855                 // Loop as long as we have invalid characters, advancing the position to the next invalid character
11856                 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11857                 {
11858                         // If we have a % character
11859                         if ($string[$position] === '%')
11860                         {
11861                                 // If we have a pct-encoded section
11862                                 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
11863                                 {
11864                                         // Get the the represented character
11865                                         $chr = chr(hexdec(substr($string, $position + 1, 2)));
11866
11867                                         // If the character is valid, replace the pct-encoded with the actual character while normalising case
11868                                         if (strpos($valid_chars, $chr) !== false)
11869                                         {
11870                                                 if ($case & SIMPLEPIE_LOWERCASE)
11871                                                 {
11872                                                         $chr = strtolower($chr);
11873                                                 }
11874                                                 elseif ($case & SIMPLEPIE_UPPERCASE)
11875                                                 {
11876                                                         $chr = strtoupper($chr);
11877                                                 }
11878                                                 $string = substr_replace($string, $chr, $position, 3);
11879                                                 $strlen -= 2;
11880                                                 $position++;
11881                                         }
11882
11883                                         // Otherwise just normalise the pct-encoded to uppercase
11884                                         else
11885                                         {
11886                                                 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
11887                                                 $position += 3;
11888                                         }
11889                                 }
11890                                 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
11891                                 else
11892                                 {
11893                                         $string = substr_replace($string, '%25', $position, 1);
11894                                         $strlen += 2;
11895                                         $position += 3;
11896                                 }
11897                         }
11898                         // If we have an invalid character, change into its pct-encoded form
11899                         else
11900                         {
11901                                 $replacement = sprintf("%%%02X", ord($string[$position]));
11902                                 $string = str_replace($string[$position], $replacement, $string);
11903                                 $strlen = strlen($string);
11904                         }
11905                 }
11906                 return $string;
11907         }
11908
11909         /**
11910          * Check if the object represents a valid IRI
11911          *
11912          * @access public
11913          * @return bool
11914          */
11915         function is_valid()
11916         {
11917                 return array_sum($this->valid) === count($this->valid);
11918         }
11919
11920         /**
11921          * Set the scheme. Returns true on success, false on failure (if there are
11922          * any invalid characters).
11923          *
11924          * @access public
11925          * @param string $scheme
11926          * @return bool
11927          */
11928         function set_scheme($scheme)
11929         {
11930                 if ($scheme === null || $scheme === '')
11931                 {
11932                         $this->scheme = null;
11933                 }
11934                 else
11935                 {
11936                         $len = strlen($scheme);
11937                         switch (true)
11938                         {
11939                                 case $len > 1:
11940                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
11941                                         {
11942                                                 $this->scheme = null;
11943                                                 $this->valid[__FUNCTION__] = false;
11944                                                 return false;
11945                                         }
11946
11947                                 case $len > 0:
11948                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
11949                                         {
11950                                                 $this->scheme = null;
11951                                                 $this->valid[__FUNCTION__] = false;
11952                                                 return false;
11953                                         }
11954                         }
11955                         $this->scheme = strtolower($scheme);
11956                 }
11957                 $this->valid[__FUNCTION__] = true;
11958                 return true;
11959         }
11960
11961         /**
11962          * Set the authority. Returns true on success, false on failure (if there are
11963          * any invalid characters).
11964          *
11965          * @access public
11966          * @param string $authority
11967          * @return bool
11968          */
11969         function set_authority($authority)
11970         {
11971                 if (($userinfo_end = strrpos($authority, '@')) !== false)
11972                 {
11973                         $userinfo = substr($authority, 0, $userinfo_end);
11974                         $authority = substr($authority, $userinfo_end + 1);
11975                 }
11976                 else
11977                 {
11978                         $userinfo = null;
11979                 }
11980
11981                 if (($port_start = strpos($authority, ':')) !== false)
11982                 {
11983                         $port = substr($authority, $port_start + 1);
11984                         $authority = substr($authority, 0, $port_start);
11985                 }
11986                 else
11987                 {
11988                         $port = null;
11989                 }
11990
11991                 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
11992         }
11993
11994         /**
11995          * Set the userinfo.
11996          *
11997          * @access public
11998          * @param string $userinfo
11999          * @return bool
12000          */
12001         function set_userinfo($userinfo)
12002         {
12003                 if ($userinfo === null || $userinfo === '')
12004                 {
12005                         $this->userinfo = null;
12006                 }
12007                 else
12008                 {
12009                         $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12010                 }
12011                 $this->valid[__FUNCTION__] = true;
12012                 return true;
12013         }
12014
12015         /**
12016          * Set the host. Returns true on success, false on failure (if there are
12017          * any invalid characters).
12018          *
12019          * @access public
12020          * @param string $host
12021          * @return bool
12022          */
12023         function set_host($host)
12024         {
12025                 if ($host === null || $host === '')
12026                 {
12027                         $this->host = null;
12028                         $this->valid[__FUNCTION__] = true;
12029                         return true;
12030                 }
12031                 elseif ($host[0] === '[' && substr($host, -1) === ']')
12032                 {
12033                         if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12034                         {
12035                                 $this->host = $host;
12036                                 $this->valid[__FUNCTION__] = true;
12037                                 return true;
12038                         }
12039                         else
12040                         {
12041                                 $this->host = null;
12042                                 $this->valid[__FUNCTION__] = false;
12043                                 return false;
12044                         }
12045                 }
12046                 else
12047                 {
12048                         $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12049                         $this->valid[__FUNCTION__] = true;
12050                         return true;
12051                 }
12052         }
12053
12054         /**
12055          * Set the port. Returns true on success, false on failure (if there are
12056          * any invalid characters).
12057          *
12058          * @access public
12059          * @param string $port
12060          * @return bool
12061          */
12062         function set_port($port)
12063         {
12064                 if ($port === null || $port === '')
12065                 {
12066                         $this->port = null;
12067                         $this->valid[__FUNCTION__] = true;
12068                         return true;
12069                 }
12070                 elseif (strspn($port, '0123456789') === strlen($port))
12071                 {
12072                         $this->port = (int) $port;
12073                         $this->valid[__FUNCTION__] = true;
12074                         return true;
12075                 }
12076                 else
12077                 {
12078                         $this->port = null;
12079                         $this->valid[__FUNCTION__] = false;
12080                         return false;
12081                 }
12082         }
12083
12084         /**
12085          * Set the path.
12086          *
12087          * @access public
12088          * @param string $path
12089          * @return bool
12090          */
12091         function set_path($path)
12092         {
12093                 if ($path === null || $path === '')
12094                 {
12095                         $this->path = null;
12096                         $this->valid[__FUNCTION__] = true;
12097                         return true;
12098                 }
12099                 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12100                 {
12101                         $this->path = null;
12102                         $this->valid[__FUNCTION__] = false;
12103                         return false;
12104                 }
12105                 else
12106                 {
12107                         $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12108                         if ($this->scheme !== null)
12109                         {
12110                                 $this->path = $this->remove_dot_segments($this->path);
12111                         }
12112                         $this->valid[__FUNCTION__] = true;
12113                         return true;
12114                 }
12115         }
12116
12117         /**
12118          * Set the query.
12119          *
12120          * @access public
12121          * @param string $query
12122          * @return bool
12123          */
12124         function set_query($query)
12125         {
12126                 if ($query === null || $query === '')
12127                 {
12128                         $this->query = null;
12129                 }
12130                 else
12131                 {
12132                         $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12133                 }
12134                 $this->valid[__FUNCTION__] = true;
12135                 return true;
12136         }
12137
12138         /**
12139          * Set the fragment.
12140          *
12141          * @access public
12142          * @param string $fragment
12143          * @return bool
12144          */
12145         function set_fragment($fragment)
12146         {
12147                 if ($fragment === null || $fragment === '')
12148                 {
12149                         $this->fragment = null;
12150                 }
12151                 else
12152                 {
12153                         $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12154                 }
12155                 $this->valid[__FUNCTION__] = true;
12156                 return true;
12157         }
12158
12159         /**
12160          * Get the complete IRI
12161          *
12162          * @access public
12163          * @return string
12164          */
12165         function get_iri()
12166         {
12167                 $iri = '';
12168                 if ($this->scheme !== null)
12169                 {
12170                         $iri .= $this->scheme . ':';
12171                 }
12172                 if (($authority = $this->get_authority()) !== null)
12173                 {
12174                         $iri .= '//' . $authority;
12175                 }
12176                 if ($this->path !== null)
12177                 {
12178                         $iri .= $this->path;
12179                 }
12180                 if ($this->query !== null)
12181                 {
12182                         $iri .= '?' . $this->query;
12183                 }
12184                 if ($this->fragment !== null)
12185                 {
12186                         $iri .= '#' . $this->fragment;
12187                 }
12188
12189                 if ($iri !== '')
12190                 {
12191                         return $iri;
12192                 }
12193                 else
12194                 {
12195                         return null;
12196                 }
12197         }
12198
12199         /**
12200          * Get the scheme
12201          *
12202          * @access public
12203          * @return string
12204          */
12205         function get_scheme()
12206         {
12207                 return $this->scheme;
12208         }
12209
12210         /**
12211          * Get the complete authority
12212          *
12213          * @access public
12214          * @return string
12215          */
12216         function get_authority()
12217         {
12218                 $authority = '';
12219                 if ($this->userinfo !== null)
12220                 {
12221                         $authority .= $this->userinfo . '@';
12222                 }
12223                 if ($this->host !== null)
12224                 {
12225                         $authority .= $this->host;
12226                 }
12227                 if ($this->port !== null)
12228                 {
12229                         $authority .= ':' . $this->port;
12230                 }
12231
12232                 if ($authority !== '')
12233                 {
12234                         return $authority;
12235                 }
12236                 else
12237                 {
12238                         return null;
12239                 }
12240         }
12241
12242         /**
12243          * Get the user information
12244          *
12245          * @access public
12246          * @return string
12247          */
12248         function get_userinfo()
12249         {
12250                 return $this->userinfo;
12251         }
12252
12253         /**
12254          * Get the host
12255          *
12256          * @access public
12257          * @return string
12258          */
12259         function get_host()
12260         {
12261                 return $this->host;
12262         }
12263
12264         /**
12265          * Get the port
12266          *
12267          * @access public
12268          * @return string
12269          */
12270         function get_port()
12271         {
12272                 return $this->port;
12273         }
12274
12275         /**
12276          * Get the path
12277          *
12278          * @access public
12279          * @return string
12280          */
12281         function get_path()
12282         {
12283                 return $this->path;
12284         }
12285
12286         /**
12287          * Get the query
12288          *
12289          * @access public
12290          * @return string
12291          */
12292         function get_query()
12293         {
12294                 return $this->query;
12295         }
12296
12297         /**
12298          * Get the fragment
12299          *
12300          * @access public
12301          * @return string
12302          */
12303         function get_fragment()
12304         {
12305                 return $this->fragment;
12306         }
12307 }
12308
12309 /**
12310  * Class to validate and to work with IPv6 addresses.
12311  *
12312  * @package SimplePie
12313  * @copyright 2003-2005 The PHP Group
12314  * @license http://www.opensource.org/licenses/bsd-license.php
12315  * @link http://pear.php.net/package/Net_IPv6
12316  * @author Alexander Merz <alexander.merz@web.de>
12317  * @author elfrink at introweb dot nl
12318  * @author Josh Peck <jmp at joshpeck dot org>
12319  * @author Geoffrey Sneddon <geoffers@gmail.com>
12320  */
12321 class SimplePie_Net_IPv6
12322 {
12323         /**
12324          * Removes a possible existing netmask specification of an IP address.
12325          *
12326          * @param string $ip the (compressed) IP as Hex representation
12327          * @return string the IP the without netmask
12328          * @since 1.1.0
12329          * @access public
12330          * @static
12331          */
12332         function removeNetmaskSpec($ip)
12333         {
12334                 if (strpos($ip, '/') !== false)
12335                 {
12336                         list($addr, $nm) = explode('/', $ip);
12337                 }
12338                 else
12339                 {
12340                         $addr = $ip;
12341                 }
12342                 return $addr;
12343         }
12344
12345         /**
12346          * Uncompresses an IPv6 address
12347          *
12348          * RFC 2373 allows you to compress zeros in an address to '::'. This
12349          * function expects an valid IPv6 address and expands the '::' to
12350          * the required zeros.
12351          *
12352          * Example:      FF01::101      ->      FF01:0:0:0:0:0:0:101
12353          *                       ::1            ->      0:0:0:0:0:0:0:1
12354          *
12355          * @access public
12356          * @static
12357          * @param string $ip a valid IPv6-address (hex format)
12358          * @return string the uncompressed IPv6-address (hex format)
12359          */
12360         function Uncompress($ip)
12361         {
12362                 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12363                 $c1 = -1;
12364                 $c2 = -1;
12365                 if (strpos($ip, '::') !== false)
12366                 {
12367                         list($ip1, $ip2) = explode('::', $ip);
12368                         if ($ip1 === '')
12369                         {
12370                                 $c1 = -1;
12371                         }
12372                         else
12373                         {
12374                                 $pos = 0;
12375                                 if (($pos = substr_count($ip1, ':')) > 0)
12376                                 {
12377                                         $c1 = $pos;
12378                                 }
12379                                 else
12380                                 {
12381                                         $c1 = 0;
12382                                 }
12383                         }
12384                         if ($ip2 === '')
12385                         {
12386                                 $c2 = -1;
12387                         }
12388                         else
12389                         {
12390                                 $pos = 0;
12391                                 if (($pos = substr_count($ip2, ':')) > 0)
12392                                 {
12393                                         $c2 = $pos;
12394                                 }
12395                                 else
12396                                 {
12397                                         $c2 = 0;
12398                                 }
12399                         }
12400                         if (strstr($ip2, '.'))
12401                         {
12402                                 $c2++;
12403                         }
12404                         // ::
12405                         if ($c1 === -1 && $c2 === -1)
12406                         {
12407                                 $uip = '0:0:0:0:0:0:0:0';
12408                         }
12409                         // ::xxx
12410                         else if ($c1 === -1)
12411                         {
12412                                 $fill = str_repeat('0:', 7 - $c2);
12413                                 $uip =  str_replace('::', $fill, $uip);
12414                         }
12415                         // xxx::
12416                         else if ($c2 === -1)
12417                         {
12418                                 $fill = str_repeat(':0', 7 - $c1);
12419                                 $uip =  str_replace('::', $fill, $uip);
12420                         }
12421                         // xxx::xxx
12422                         else
12423                         {
12424                                 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12425                                 $uip =  str_replace('::', $fill, $uip);
12426                                 $uip =  str_replace('::', ':', $uip);
12427                         }
12428                 }
12429                 return $uip;
12430         }
12431
12432         /**
12433          * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12434          *
12435          * RFC 2373 allows you to note the last two parts of an IPv6 address as
12436          * an IPv4 compatible address
12437          *
12438          * Example:      0:0:0:0:0:0:13.1.68.3
12439          *                       0:0:0:0:0:FFFF:129.144.52.38
12440          *
12441          * @access public
12442          * @static
12443          * @param string $ip a valid IPv6-address (hex format)
12444          * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12445          */
12446         function SplitV64($ip)
12447         {
12448                 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12449                 if (strstr($ip, '.'))
12450                 {
12451                         $pos = strrpos($ip, ':');
12452                         $ip[$pos] = '_';
12453                         $ipPart = explode('_', $ip);
12454                         return $ipPart;
12455                 }
12456                 else
12457                 {
12458                         return array($ip, '');
12459                 }
12460         }
12461
12462         /**
12463          * Checks an IPv6 address
12464          *
12465          * Checks if the given IP is IPv6-compatible
12466          *
12467          * @access public
12468          * @static
12469          * @param string $ip a valid IPv6-address
12470          * @return bool true if $ip is an IPv6 address
12471          */
12472         function checkIPv6($ip)
12473         {
12474                 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12475                 $count = 0;
12476                 if (!empty($ipPart[0]))
12477                 {
12478                         $ipv6 = explode(':', $ipPart[0]);
12479                         for ($i = 0; $i < count($ipv6); $i++)
12480                         {
12481                                 $dec = hexdec($ipv6[$i]);
12482                                 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12483                                 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12484                                 {
12485                                         $count++;
12486                                 }
12487                         }
12488                         if ($count === 8)
12489                         {
12490                                 return true;
12491                         }
12492                         elseif ($count === 6 && !empty($ipPart[1]))
12493                         {
12494                                 $ipv4 = explode('.', $ipPart[1]);
12495                                 $count = 0;
12496                                 foreach ($ipv4 as $ipv4_part)
12497                                 {
12498                                         if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12499                                         {
12500                                                 $count++;
12501                                         }
12502                                 }
12503                                 if ($count === 4)
12504                                 {
12505                                         return true;
12506                                 }
12507                         }
12508                         else
12509                         {
12510                                 return false;
12511                         }
12512
12513                 }
12514                 else
12515                 {
12516                         return false;
12517                 }
12518         }
12519 }
12520
12521 /**
12522  * Date Parser
12523  *
12524  * @package SimplePie
12525  */
12526 class SimplePie_Parse_Date
12527 {
12528         /**
12529          * Input data
12530          *
12531          * @access protected
12532          * @var string
12533          */
12534         var $date;
12535
12536         /**
12537          * List of days, calendar day name => ordinal day number in the week
12538          *
12539          * @access protected
12540          * @var array
12541          */
12542         var $day = array(
12543                 // English
12544                 'mon' => 1,
12545                 'monday' => 1,
12546                 'tue' => 2,
12547                 'tuesday' => 2,
12548                 'wed' => 3,
12549                 'wednesday' => 3,
12550                 'thu' => 4,
12551                 'thursday' => 4,
12552                 'fri' => 5,
12553                 'friday' => 5,
12554                 'sat' => 6,
12555                 'saturday' => 6,
12556                 'sun' => 7,
12557                 'sunday' => 7,
12558                 // Dutch
12559                 'maandag' => 1,
12560                 'dinsdag' => 2,
12561                 'woensdag' => 3,
12562                 'donderdag' => 4,
12563                 'vrijdag' => 5,
12564                 'zaterdag' => 6,
12565                 'zondag' => 7,
12566                 // French
12567                 'lundi' => 1,
12568                 'mardi' => 2,
12569                 'mercredi' => 3,
12570                 'jeudi' => 4,
12571                 'vendredi' => 5,
12572                 'samedi' => 6,
12573                 'dimanche' => 7,
12574                 // German
12575                 'montag' => 1,
12576                 'dienstag' => 2,
12577                 'mittwoch' => 3,
12578                 'donnerstag' => 4,
12579                 'freitag' => 5,
12580                 'samstag' => 6,
12581                 'sonnabend' => 6,
12582                 'sonntag' => 7,
12583                 // Italian
12584                 'lunedì' => 1,
12585                 'martedì' => 2,
12586                 'mercoledì' => 3,
12587                 'giovedì' => 4,
12588                 'venerdì' => 5,
12589                 'sabato' => 6,
12590                 'domenica' => 7,
12591                 // Spanish
12592                 'lunes' => 1,
12593                 'martes' => 2,
12594                 'miércoles' => 3,
12595                 'jueves' => 4,
12596                 'viernes' => 5,
12597                 'sábado' => 6,
12598                 'domingo' => 7,
12599                 // Finnish
12600                 'maanantai' => 1,
12601                 'tiistai' => 2,
12602                 'keskiviikko' => 3,
12603                 'torstai' => 4,
12604                 'perjantai' => 5,
12605                 'lauantai' => 6,
12606                 'sunnuntai' => 7,
12607                 // Hungarian
12608                 'hétfő' => 1,
12609                 'kedd' => 2,
12610                 'szerda' => 3,
12611                 'csütörtok' => 4,
12612                 'péntek' => 5,
12613                 'szombat' => 6,
12614                 'vasárnap' => 7,
12615                 // Greek
12616                 'Δευ' => 1,
12617                 'Τρι' => 2,
12618                 'Τετ' => 3,
12619                 'Πεμ' => 4,
12620                 'Παρ' => 5,
12621                 'Σαβ' => 6,
12622                 'Κυρ' => 7,
12623         );
12624
12625         /**
12626          * List of months, calendar month name => calendar month number
12627          *
12628          * @access protected
12629          * @var array
12630          */
12631         var $month = array(
12632                 // English
12633                 'jan' => 1,
12634                 'january' => 1,
12635                 'feb' => 2,
12636                 'february' => 2,
12637                 'mar' => 3,
12638                 'march' => 3,
12639                 'apr' => 4,
12640                 'april' => 4,
12641                 'may' => 5,
12642                 // No long form of May
12643                 'jun' => 6,
12644                 'june' => 6,
12645                 'jul' => 7,
12646                 'july' => 7,
12647                 'aug' => 8,
12648                 'august' => 8,
12649                 'sep' => 9,
12650                 'september' => 8,
12651                 'oct' => 10,
12652                 'october' => 10,
12653                 'nov' => 11,
12654                 'november' => 11,
12655                 'dec' => 12,
12656                 'december' => 12,
12657                 // Dutch
12658                 'januari' => 1,
12659                 'februari' => 2,
12660                 'maart' => 3,
12661                 'april' => 4,
12662                 'mei' => 5,
12663                 'juni' => 6,
12664                 'juli' => 7,
12665                 'augustus' => 8,
12666                 'september' => 9,
12667                 'oktober' => 10,
12668                 'november' => 11,
12669                 'december' => 12,
12670                 // French
12671                 'janvier' => 1,
12672                 'février' => 2,
12673                 'mars' => 3,
12674                 'avril' => 4,
12675                 'mai' => 5,
12676                 'juin' => 6,
12677                 'juillet' => 7,
12678                 'août' => 8,
12679                 'septembre' => 9,
12680                 'octobre' => 10,
12681                 'novembre' => 11,
12682                 'décembre' => 12,
12683                 // German
12684                 'januar' => 1,
12685                 'februar' => 2,
12686                 'märz' => 3,
12687                 'april' => 4,
12688                 'mai' => 5,
12689                 'juni' => 6,
12690                 'juli' => 7,
12691                 'august' => 8,
12692                 'september' => 9,
12693                 'oktober' => 10,
12694                 'november' => 11,
12695                 'dezember' => 12,
12696                 // Italian
12697                 'gennaio' => 1,
12698                 'febbraio' => 2,
12699                 'marzo' => 3,
12700                 'aprile' => 4,
12701                 'maggio' => 5,
12702                 'giugno' => 6,
12703                 'luglio' => 7,
12704                 'agosto' => 8,
12705                 'settembre' => 9,
12706                 'ottobre' => 10,
12707                 'novembre' => 11,
12708                 'dicembre' => 12,
12709                 // Spanish
12710                 'enero' => 1,
12711                 'febrero' => 2,
12712                 'marzo' => 3,
12713                 'abril' => 4,
12714                 'mayo' => 5,
12715                 'junio' => 6,
12716                 'julio' => 7,
12717                 'agosto' => 8,
12718                 'septiembre' => 9,
12719                 'setiembre' => 9,
12720                 'octubre' => 10,
12721                 'noviembre' => 11,
12722                 'diciembre' => 12,
12723                 // Finnish
12724                 'tammikuu' => 1,
12725                 'helmikuu' => 2,
12726                 'maaliskuu' => 3,
12727                 'huhtikuu' => 4,
12728                 'toukokuu' => 5,
12729                 'kesäkuu' => 6,
12730                 'heinäkuu' => 7,
12731                 'elokuu' => 8,
12732                 'suuskuu' => 9,
12733                 'lokakuu' => 10,
12734                 'marras' => 11,
12735                 'joulukuu' => 12,
12736                 // Hungarian
12737                 'január' => 1,
12738                 'február' => 2,
12739                 'március' => 3,
12740                 'április' => 4,
12741                 'május' => 5,
12742                 'június' => 6,
12743                 'július' => 7,
12744                 'augusztus' => 8,
12745                 'szeptember' => 9,
12746                 'október' => 10,
12747                 'november' => 11,
12748                 'december' => 12,
12749                 // Greek
12750                 'Ιαν' => 1,
12751                 'Φεβ' => 2,
12752                 'Μάώ' => 3,
12753                 'Μαώ' => 3,
12754                 'Απρ' => 4,
12755                 'Μάι' => 5,
12756                 'Μαϊ' => 5,
12757                 'Μαι' => 5,
12758                 'Ιούν' => 6,
12759                 'Ιον' => 6,
12760                 'Ιούλ' => 7,
12761                 'Ιολ' => 7,
12762                 'Αύγ' => 8,
12763                 'Αυγ' => 8,
12764                 'Σεπ' => 9,
12765                 'Οκτ' => 10,
12766                 'Νοέ' => 11,
12767                 'Δεκ' => 12,
12768         );
12769
12770         /**
12771          * List of timezones, abbreviation => offset from UTC
12772          *
12773          * @access protected
12774          * @var array
12775          */
12776         var $timezone = array(
12777                 'ACDT' => 37800,
12778                 'ACIT' => 28800,
12779                 'ACST' => 34200,
12780                 'ACT' => -18000,
12781                 'ACWDT' => 35100,
12782                 'ACWST' => 31500,
12783                 'AEDT' => 39600,
12784                 'AEST' => 36000,
12785                 'AFT' => 16200,
12786                 'AKDT' => -28800,
12787                 'AKST' => -32400,
12788                 'AMDT' => 18000,
12789                 'AMT' => -14400,
12790                 'ANAST' => 46800,
12791                 'ANAT' => 43200,
12792                 'ART' => -10800,
12793                 'AZOST' => -3600,
12794                 'AZST' => 18000,
12795                 'AZT' => 14400,
12796                 'BIOT' => 21600,
12797                 'BIT' => -43200,
12798                 'BOT' => -14400,
12799                 'BRST' => -7200,
12800                 'BRT' => -10800,
12801                 'BST' => 3600,
12802                 'BTT' => 21600,
12803                 'CAST' => 18000,
12804                 'CAT' => 7200,
12805                 'CCT' => 23400,
12806                 'CDT' => -18000,
12807                 'CEDT' => 7200,
12808                 'CET' => 3600,
12809                 'CGST' => -7200,
12810                 'CGT' => -10800,
12811                 'CHADT' => 49500,
12812                 'CHAST' => 45900,
12813                 'CIST' => -28800,
12814                 'CKT' => -36000,
12815                 'CLDT' => -10800,
12816                 'CLST' => -14400,
12817                 'COT' => -18000,
12818                 'CST' => -21600,
12819                 'CVT' => -3600,
12820                 'CXT' => 25200,
12821                 'DAVT' => 25200,
12822                 'DTAT' => 36000,
12823                 'EADT' => -18000,
12824                 'EAST' => -21600,
12825                 'EAT' => 10800,
12826                 'ECT' => -18000,
12827                 'EDT' => -14400,
12828                 'EEST' => 10800,
12829                 'EET' => 7200,
12830                 'EGT' => -3600,
12831                 'EKST' => 21600,
12832                 'EST' => -18000,
12833                 'FJT' => 43200,
12834                 'FKDT' => -10800,
12835                 'FKST' => -14400,
12836                 'FNT' => -7200,
12837                 'GALT' => -21600,
12838                 'GEDT' => 14400,
12839                 'GEST' => 10800,
12840                 'GFT' => -10800,
12841                 'GILT' => 43200,
12842                 'GIT' => -32400,
12843                 'GST' => 14400,
12844                 'GST' => -7200,
12845                 'GYT' => -14400,
12846                 'HAA' => -10800,
12847                 'HAC' => -18000,
12848                 'HADT' => -32400,
12849                 'HAE' => -14400,
12850                 'HAP' => -25200,
12851                 'HAR' => -21600,
12852                 'HAST' => -36000,
12853                 'HAT' => -9000,
12854                 'HAY' => -28800,
12855                 'HKST' => 28800,
12856                 'HMT' => 18000,
12857                 'HNA' => -14400,
12858                 'HNC' => -21600,
12859                 'HNE' => -18000,
12860                 'HNP' => -28800,
12861                 'HNR' => -25200,
12862                 'HNT' => -12600,
12863                 'HNY' => -32400,
12864                 'IRDT' => 16200,
12865                 'IRKST' => 32400,
12866                 'IRKT' => 28800,
12867                 'IRST' => 12600,
12868                 'JFDT' => -10800,
12869                 'JFST' => -14400,
12870                 'JST' => 32400,
12871                 'KGST' => 21600,
12872                 'KGT' => 18000,
12873                 'KOST' => 39600,
12874                 'KOVST' => 28800,
12875                 'KOVT' => 25200,
12876                 'KRAST' => 28800,
12877                 'KRAT' => 25200,
12878                 'KST' => 32400,
12879                 'LHDT' => 39600,
12880                 'LHST' => 37800,
12881                 'LINT' => 50400,
12882                 'LKT' => 21600,
12883                 'MAGST' => 43200,
12884                 'MAGT' => 39600,
12885                 'MAWT' => 21600,
12886                 'MDT' => -21600,
12887                 'MESZ' => 7200,
12888                 'MEZ' => 3600,
12889                 'MHT' => 43200,
12890                 'MIT' => -34200,
12891                 'MNST' => 32400,
12892                 'MSDT' => 14400,
12893                 'MSST' => 10800,
12894                 'MST' => -25200,
12895                 'MUT' => 14400,
12896                 'MVT' => 18000,
12897                 'MYT' => 28800,
12898                 'NCT' => 39600,
12899                 'NDT' => -9000,
12900                 'NFT' => 41400,
12901                 'NMIT' => 36000,
12902                 'NOVST' => 25200,
12903                 'NOVT' => 21600,
12904                 'NPT' => 20700,
12905                 'NRT' => 43200,
12906                 'NST' => -12600,
12907                 'NUT' => -39600,
12908                 'NZDT' => 46800,
12909                 'NZST' => 43200,
12910                 'OMSST' => 25200,
12911                 'OMST' => 21600,
12912                 'PDT' => -25200,
12913                 'PET' => -18000,
12914                 'PETST' => 46800,
12915                 'PETT' => 43200,
12916                 'PGT' => 36000,
12917                 'PHOT' => 46800,
12918                 'PHT' => 28800,
12919                 'PKT' => 18000,
12920                 'PMDT' => -7200,
12921                 'PMST' => -10800,
12922                 'PONT' => 39600,
12923                 'PST' => -28800,
12924                 'PWT' => 32400,
12925                 'PYST' => -10800,
12926                 'PYT' => -14400,
12927                 'RET' => 14400,
12928                 'ROTT' => -10800,
12929                 'SAMST' => 18000,
12930                 'SAMT' => 14400,
12931                 'SAST' => 7200,
12932                 'SBT' => 39600,
12933                 'SCDT' => 46800,
12934                 'SCST' => 43200,
12935                 'SCT' => 14400,
12936                 'SEST' => 3600,
12937                 'SGT' => 28800,
12938                 'SIT' => 28800,
12939                 'SRT' => -10800,
12940                 'SST' => -39600,
12941                 'SYST' => 10800,
12942                 'SYT' => 7200,
12943                 'TFT' => 18000,
12944                 'THAT' => -36000,
12945                 'TJT' => 18000,
12946                 'TKT' => -36000,
12947                 'TMT' => 18000,
12948                 'TOT' => 46800,
12949                 'TPT' => 32400,
12950                 'TRUT' => 36000,
12951                 'TVT' => 43200,
12952                 'TWT' => 28800,
12953                 'UYST' => -7200,
12954                 'UYT' => -10800,
12955                 'UZT' => 18000,
12956                 'VET' => -14400,
12957                 'VLAST' => 39600,
12958                 'VLAT' => 36000,
12959                 'VOST' => 21600,
12960                 'VUT' => 39600,
12961                 'WAST' => 7200,
12962                 'WAT' => 3600,
12963                 'WDT' => 32400,
12964                 'WEST' => 3600,
12965                 'WFT' => 43200,
12966                 'WIB' => 25200,
12967                 'WIT' => 32400,
12968                 'WITA' => 28800,
12969                 'WKST' => 18000,
12970                 'WST' => 28800,
12971                 'YAKST' => 36000,
12972                 'YAKT' => 32400,
12973                 'YAPT' => 36000,
12974                 'YEKST' => 21600,
12975                 'YEKT' => 18000,
12976         );
12977
12978         /**
12979          * Cached PCRE for SimplePie_Parse_Date::$day
12980          *
12981          * @access protected
12982          * @var string
12983          */
12984         var $day_pcre;
12985
12986         /**
12987          * Cached PCRE for SimplePie_Parse_Date::$month
12988          *
12989          * @access protected
12990          * @var string
12991          */
12992         var $month_pcre;
12993
12994         /**
12995          * Array of user-added callback methods
12996          *
12997          * @access private
12998          * @var array
12999          */
13000         var $built_in = array();
13001
13002         /**
13003          * Array of user-added callback methods
13004          *
13005          * @access private
13006          * @var array
13007          */
13008         var $user = array();
13009
13010         /**
13011          * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13012          * self::month_pcre, and self::built_in
13013          *
13014          * @access private
13015          */
13016         function SimplePie_Parse_Date()
13017         {
13018                 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13019                 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13020
13021                 static $cache;
13022                 if (!isset($cache[get_class($this)]))
13023                 {
13024                         $all_methods = get_class_methods($this);
13025
13026                         foreach ($all_methods as $method)
13027                         {
13028                                 if (strtolower(substr($method, 0, 5)) === 'date_')
13029                                 {
13030                                         $cache[get_class($this)][] = $method;
13031                                 }
13032                         }
13033                 }
13034
13035                 foreach ($cache[get_class($this)] as $method)
13036                 {
13037                         $this->built_in[] = $method;
13038                 }
13039         }
13040
13041         /**
13042          * Get the object
13043          *
13044          * @access public
13045          */
13046         function get()
13047         {
13048                 static $object;
13049                 if (!$object)
13050                 {
13051                         $object =& new SimplePie_Parse_Date;
13052                 }
13053                 return $object;
13054         }
13055
13056         /**
13057          * Parse a date
13058          *
13059          * @final
13060          * @access public
13061          * @param string $date Date to parse
13062          * @return int Timestamp corresponding to date string, or false on failure
13063          */
13064         function parse($date)
13065         {
13066                 foreach ($this->user as $method)
13067                 {
13068                         if (($returned = call_user_func($method, $date)) !== false)
13069                         {
13070                                 return $returned;
13071                         }
13072                 }
13073
13074                 foreach ($this->built_in as $method)
13075                 {
13076                         if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13077                         {
13078                                 return $returned;
13079                         }
13080                 }
13081
13082                 return false;
13083         }
13084
13085         /**
13086          * Add a callback method to parse a date
13087          *
13088          * @final
13089          * @access public
13090          * @param callback $callback
13091          */
13092         function add_callback($callback)
13093         {
13094                 if (is_callable($callback))
13095                 {
13096                         $this->user[] = $callback;
13097                 }
13098                 else
13099                 {
13100                         trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13101                 }
13102         }
13103
13104         /**
13105          * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13106          * well as allowing any of upper or lower case "T", horizontal tabs, or
13107          * spaces to be used as the time seperator (including more than one))
13108          *
13109          * @access protected
13110          * @return int Timestamp
13111          */
13112         function date_w3cdtf($date)
13113         {
13114                 static $pcre;
13115                 if (!$pcre)
13116                 {
13117                         $year = '([0-9]{4})';
13118                         $month = $day = $hour = $minute = $second = '([0-9]{2})';
13119                         $decimal = '([0-9]*)';
13120                         $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13121                         $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13122                 }
13123                 if (preg_match($pcre, $date, $match))
13124                 {
13125                         /*
13126                         Capturing subpatterns:
13127                         1: Year
13128                         2: Month
13129                         3: Day
13130                         4: Hour
13131                         5: Minute
13132                         6: Second
13133                         7: Decimal fraction of a second
13134                         8: Zulu
13135                         9: Timezone ±
13136                         10: Timezone hours
13137                         11: Timezone minutes
13138                         */
13139
13140                         // Fill in empty matches
13141                         for ($i = count($match); $i <= 3; $i++)
13142                         {
13143                                 $match[$i] = '1';
13144                         }
13145
13146                         for ($i = count($match); $i <= 7; $i++)
13147                         {
13148                                 $match[$i] = '0';
13149                         }
13150
13151                         // Numeric timezone
13152                         if (isset($match[9]) && $match[9] !== '')
13153                         {
13154                                 $timezone = $match[10] * 3600;
13155                                 $timezone += $match[11] * 60;
13156                                 if ($match[9] === '-')
13157                                 {
13158                                         $timezone = 0 - $timezone;
13159                                 }
13160                         }
13161                         else
13162                         {
13163                                 $timezone = 0;
13164                         }
13165
13166                         // Convert the number of seconds to an integer, taking decimals into account
13167                         $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13168
13169                         return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13170                 }
13171                 else
13172                 {
13173                         return false;
13174                 }
13175         }
13176
13177         /**
13178          * Remove RFC822 comments
13179          *
13180          * @access protected
13181          * @param string $data Data to strip comments from
13182          * @return string Comment stripped string
13183          */
13184         function remove_rfc2822_comments($string)
13185         {
13186                 $string = (string) $string;
13187                 $position = 0;
13188                 $length = strlen($string);
13189                 $depth = 0;
13190
13191                 $output = '';
13192
13193                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13194                 {
13195                         $output .= substr($string, $position, $pos - $position);
13196                         $position = $pos + 1;
13197                         if ($string[$pos - 1] !== '\\')
13198                         {
13199                                 $depth++;
13200                                 while ($depth && $position < $length)
13201                                 {
13202                                         $position += strcspn($string, '()', $position);
13203                                         if ($string[$position - 1] === '\\')
13204                                         {
13205                                                 $position++;
13206                                                 continue;
13207                                         }
13208                                         elseif (isset($string[$position]))
13209                                         {
13210                                                 switch ($string[$position])
13211                                                 {
13212                                                         case '(':
13213                                                                 $depth++;
13214                                                                 break;
13215
13216                                                         case ')':
13217                                                                 $depth--;
13218                                                                 break;
13219                                                 }
13220                                                 $position++;
13221                                         }
13222                                         else
13223                                         {
13224                                                 break;
13225                                         }
13226                                 }
13227                         }
13228                         else
13229                         {
13230                                 $output .= '(';
13231                         }
13232                 }
13233                 $output .= substr($string, $position);
13234
13235                 return $output;
13236         }
13237
13238         /**
13239          * Parse RFC2822's date format
13240          *
13241          * @access protected
13242          * @return int Timestamp
13243          */
13244         function date_rfc2822($date)
13245         {
13246                 static $pcre;
13247                 if (!$pcre)
13248                 {
13249                         $wsp = '[\x09\x20]';
13250                         $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13251                         $optional_fws = $fws . '?';
13252                         $day_name = $this->day_pcre;
13253                         $month = $this->month_pcre;
13254                         $day = '([0-9]{1,2})';
13255                         $hour = $minute = $second = '([0-9]{2})';
13256                         $year = '([0-9]{2,4})';
13257                         $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13258                         $character_zone = '([A-Z]{1,5})';
13259                         $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13260                         $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';
13261                 }
13262                 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13263                 {
13264                         /*
13265                         Capturing subpatterns:
13266                         1: Day name
13267                         2: Day
13268                         3: Month
13269                         4: Year
13270                         5: Hour
13271                         6: Minute
13272                         7: Second
13273                         8: Timezone ±
13274                         9: Timezone hours
13275                         10: Timezone minutes
13276                         11: Alphabetic timezone
13277                         */
13278
13279                         // Find the month number
13280                         $month = $this->month[strtolower($match[3])];
13281
13282                         // Numeric timezone
13283                         if ($match[8] !== '')
13284                         {
13285                                 $timezone = $match[9] * 3600;
13286                                 $timezone += $match[10] * 60;
13287                                 if ($match[8] === '-')
13288                                 {
13289                                         $timezone = 0 - $timezone;
13290                                 }
13291                         }
13292                         // Character timezone
13293                         elseif (isset($this->timezone[strtoupper($match[11])]))
13294                         {
13295                                 $timezone = $this->timezone[strtoupper($match[11])];
13296                         }
13297                         // Assume everything else to be -0000
13298                         else
13299                         {
13300                                 $timezone = 0;
13301                         }
13302
13303                         // Deal with 2/3 digit years
13304                         if ($match[4] < 50)
13305                         {
13306                                 $match[4] += 2000;
13307                         }
13308                         elseif ($match[4] < 1000)
13309                         {
13310                                 $match[4] += 1900;
13311                         }
13312
13313                         // Second is optional, if it is empty set it to zero
13314                         if ($match[7] !== '')
13315                         {
13316                                 $second = $match[7];
13317                         }
13318                         else
13319                         {
13320                                 $second = 0;
13321                         }
13322
13323                         return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13324                 }
13325                 else
13326                 {
13327                         return false;
13328                 }
13329         }
13330
13331         /**
13332          * Parse RFC850's date format
13333          *
13334          * @access protected
13335          * @return int Timestamp
13336          */
13337         function date_rfc850($date)
13338         {
13339                 static $pcre;
13340                 if (!$pcre)
13341                 {
13342                         $space = '[\x09\x20]+';
13343                         $day_name = $this->day_pcre;
13344                         $month = $this->month_pcre;
13345                         $day = '([0-9]{1,2})';
13346                         $year = $hour = $minute = $second = '([0-9]{2})';
13347                         $zone = '([A-Z]{1,5})';
13348                         $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13349                 }
13350                 if (preg_match($pcre, $date, $match))
13351                 {
13352                         /*
13353                         Capturing subpatterns:
13354                         1: Day name
13355                         2: Day
13356                         3: Month
13357                         4: Year
13358                         5: Hour
13359                         6: Minute
13360                         7: Second
13361                         8: Timezone
13362                         */
13363
13364                         // Month
13365                         $month = $this->month[strtolower($match[3])];
13366
13367                         // Character timezone
13368                         if (isset($this->timezone[strtoupper($match[8])]))
13369                         {
13370                                 $timezone = $this->timezone[strtoupper($match[8])];
13371                         }
13372                         // Assume everything else to be -0000
13373                         else
13374                         {
13375                                 $timezone = 0;
13376                         }
13377
13378                         // Deal with 2 digit year
13379                         if ($match[4] < 50)
13380                         {
13381                                 $match[4] += 2000;
13382                         }
13383                         else
13384                         {
13385                                 $match[4] += 1900;
13386                         }
13387
13388                         return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13389                 }
13390                 else
13391                 {
13392                         return false;
13393                 }
13394         }
13395
13396         /**
13397          * Parse C99's asctime()'s date format
13398          *
13399          * @access protected
13400          * @return int Timestamp
13401          */
13402         function date_asctime($date)
13403         {
13404                 static $pcre;
13405                 if (!$pcre)
13406                 {
13407                         $space = '[\x09\x20]+';
13408                         $wday_name = $this->day_pcre;
13409                         $mon_name = $this->month_pcre;
13410                         $day = '([0-9]{1,2})';
13411                         $hour = $sec = $min = '([0-9]{2})';
13412                         $year = '([0-9]{4})';
13413                         $terminator = '\x0A?\x00?';
13414                         $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13415                 }
13416                 if (preg_match($pcre, $date, $match))
13417                 {
13418                         /*
13419                         Capturing subpatterns:
13420                         1: Day name
13421                         2: Month
13422                         3: Day
13423                         4: Hour
13424                         5: Minute
13425                         6: Second
13426                         7: Year
13427                         */
13428
13429                         $month = $this->month[strtolower($match[2])];
13430                         return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13431                 }
13432                 else
13433                 {
13434                         return false;
13435                 }
13436         }
13437
13438         /**
13439          * Parse dates using strtotime()
13440          *
13441          * @access protected
13442          * @return int Timestamp
13443          */
13444         function date_strtotime($date)
13445         {
13446                 $strtotime = strtotime($date);
13447                 if ($strtotime === -1 || $strtotime === false)
13448                 {
13449                         return false;
13450                 }
13451                 else
13452                 {
13453                         return $strtotime;
13454                 }
13455         }
13456 }
13457
13458 /**
13459  * Content-type sniffing
13460  *
13461  * @package SimplePie
13462  */
13463 class SimplePie_Content_Type_Sniffer
13464 {
13465         /**
13466          * File object
13467          *
13468          * @var SimplePie_File
13469          * @access private
13470          */
13471         var $file;
13472
13473         /**
13474          * Create an instance of the class with the input file
13475          *
13476          * @access public
13477          * @param SimplePie_Content_Type_Sniffer $file Input file
13478          */
13479         function SimplePie_Content_Type_Sniffer($file)
13480         {
13481                 $this->file = $file;
13482         }
13483
13484         /**
13485          * Get the Content-Type of the specified file
13486          *
13487          * @access public
13488          * @return string Actual Content-Type
13489          */
13490         function get_type()
13491         {
13492                 if (isset($this->file->headers['content-type']))
13493                 {
13494                         if (!isset($this->file->headers['content-encoding'])
13495                                 && ($this->file->headers['content-type'] === 'text/plain'
13496                                         || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13497                                         || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13498                         {
13499                                 return $this->text_or_binary();
13500                         }
13501
13502                         if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13503                         {
13504                                 $official = substr($this->file->headers['content-type'], 0, $pos);
13505                         }
13506                         else
13507                         {
13508                                 $official = $this->file->headers['content-type'];
13509                         }
13510                         $official = strtolower($official);
13511
13512                         if ($official === 'unknown/unknown'
13513                                 || $official === 'application/unknown')
13514                         {
13515                                 return $this->unknown();
13516                         }
13517                         elseif (substr($official, -4) === '+xml'
13518                                 || $official === 'text/xml'
13519                                 || $official === 'application/xml')
13520                         {
13521                                 return $official;
13522                         }
13523                         elseif (substr($official, 0, 6) === 'image/')
13524                         {
13525                                 if ($return = $this->image())
13526                                 {
13527                                         return $return;
13528                                 }
13529                                 else
13530                                 {
13531                                         return $official;
13532                                 }
13533                         }
13534                         elseif ($official === 'text/html')
13535                         {
13536                                 return $this->feed_or_html();
13537                         }
13538                         else
13539                         {
13540                                 return $official;
13541                         }
13542                 }
13543                 else
13544                 {
13545                         return $this->unknown();
13546                 }
13547         }
13548
13549         /**
13550          * Sniff text or binary
13551          *
13552          * @access private
13553          * @return string Actual Content-Type
13554          */
13555         function text_or_binary()
13556         {
13557                 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13558                         || substr($this->file->body, 0, 2) === "\xFF\xFE"
13559                         || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13560                         || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13561                 {
13562                         return 'text/plain';
13563                 }
13564                 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13565                 {
13566                         return 'application/octect-stream';
13567                 }
13568                 else
13569                 {
13570                         return 'text/plain';
13571                 }
13572         }
13573
13574         /**
13575          * Sniff unknown
13576          *
13577          * @access private
13578          * @return string Actual Content-Type
13579          */
13580         function unknown()
13581         {
13582                 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13583                 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13584                         || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13585                         || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13586                 {
13587                         return 'text/html';
13588                 }
13589                 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13590                 {
13591                         return 'application/pdf';
13592                 }
13593                 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13594                 {
13595                         return 'application/postscript';
13596                 }
13597                 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13598                         || substr($this->file->body, 0, 6) === 'GIF89a')
13599                 {
13600                         return 'image/gif';
13601                 }
13602                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13603                 {
13604                         return 'image/png';
13605                 }
13606                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13607                 {
13608                         return 'image/jpeg';
13609                 }
13610                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13611                 {
13612                         return 'image/bmp';
13613                 }
13614                 else
13615                 {
13616                         return $this->text_or_binary();
13617                 }
13618         }
13619
13620         /**
13621          * Sniff images
13622          *
13623          * @access private
13624          * @return string Actual Content-Type
13625          */
13626         function image()
13627         {
13628                 if (substr($this->file->body, 0, 6) === 'GIF87a'
13629                         || substr($this->file->body, 0, 6) === 'GIF89a')
13630                 {
13631                         return 'image/gif';
13632                 }
13633                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13634                 {
13635                         return 'image/png';
13636                 }
13637                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13638                 {
13639                         return 'image/jpeg';
13640                 }
13641                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13642                 {
13643                         return 'image/bmp';
13644                 }
13645                 else
13646                 {
13647                         return false;
13648                 }
13649         }
13650
13651         /**
13652          * Sniff HTML
13653          *
13654          * @access private
13655          * @return string Actual Content-Type
13656          */
13657         function feed_or_html()
13658         {
13659                 $len = strlen($this->file->body);
13660                 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13661
13662                 while ($pos < $len)
13663                 {
13664                         switch ($this->file->body[$pos])
13665                         {
13666                                 case "\x09":
13667                                 case "\x0A":
13668                                 case "\x0D":
13669                                 case "\x20":
13670                                         $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13671                                         continue 2;
13672
13673                                 case '<':
13674                                         $pos++;
13675                                         break;
13676
13677                                 default:
13678                                         return 'text/html';
13679                         }
13680
13681                         if (substr($this->file->body, $pos, 3) === '!--')
13682                         {
13683                                 $pos += 3;
13684                                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13685                                 {
13686                                         $pos += 3;
13687                                 }
13688                                 else
13689                                 {
13690                                         return 'text/html';
13691                                 }
13692                         }
13693                         elseif (substr($this->file->body, $pos, 1) === '!')
13694                         {
13695                                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13696                                 {
13697                                         $pos++;
13698                                 }
13699                                 else
13700                                 {
13701                                         return 'text/html';
13702                                 }
13703                         }
13704                         elseif (substr($this->file->body, $pos, 1) === '?')
13705                         {
13706                                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13707                                 {
13708                                         $pos += 2;
13709                                 }
13710                                 else
13711                                 {
13712                                         return 'text/html';
13713                                 }
13714                         }
13715                         elseif (substr($this->file->body, $pos, 3) === 'rss'
13716                                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13717                         {
13718                                 return 'application/rss+xml';
13719                         }
13720                         elseif (substr($this->file->body, $pos, 4) === 'feed')
13721                         {
13722                                 return 'application/atom+xml';
13723                         }
13724                         else
13725                         {
13726                                 return 'text/html';
13727                         }
13728                 }
13729
13730                 return 'text/html';
13731         }
13732 }
13733
13734 /**
13735  * Parses the XML Declaration
13736  *
13737  * @package SimplePie
13738  */
13739 class SimplePie_XML_Declaration_Parser
13740 {
13741         /**
13742          * XML Version
13743          *
13744          * @access public
13745          * @var string
13746          */
13747         var $version = '1.0';
13748
13749         /**
13750          * Encoding
13751          *
13752          * @access public
13753          * @var string
13754          */
13755         var $encoding = 'UTF-8';
13756
13757         /**
13758          * Standalone
13759          *
13760          * @access public
13761          * @var bool
13762          */
13763         var $standalone = false;
13764
13765         /**
13766          * Current state of the state machine
13767          *
13768          * @access private
13769          * @var string
13770          */
13771         var $state = 'before_version_name';
13772
13773         /**
13774          * Input data
13775          *
13776          * @access private
13777          * @var string
13778          */
13779         var $data = '';
13780
13781         /**
13782          * Input data length (to avoid calling strlen() everytime this is needed)
13783          *
13784          * @access private
13785          * @var int
13786          */
13787         var $data_length = 0;
13788
13789         /**
13790          * Current position of the pointer
13791          *
13792          * @var int
13793          * @access private
13794          */
13795         var $position = 0;
13796
13797         /**
13798          * Create an instance of the class with the input data
13799          *
13800          * @access public
13801          * @param string $data Input data
13802          */
13803         function SimplePie_XML_Declaration_Parser($data)
13804         {
13805                 $this->data = $data;
13806                 $this->data_length = strlen($this->data);
13807         }
13808
13809         /**
13810          * Parse the input data
13811          *
13812          * @access public
13813          * @return bool true on success, false on failure
13814          */
13815         function parse()
13816         {
13817                 while ($this->state && $this->state !== 'emit' && $this->has_data())
13818                 {
13819                         $state = $this->state;
13820                         $this->$state();
13821                 }
13822                 $this->data = '';
13823                 if ($this->state === 'emit')
13824                 {
13825                         return true;
13826                 }
13827                 else
13828                 {
13829                         $this->version = '';
13830                         $this->encoding = '';
13831                         $this->standalone = '';
13832                         return false;
13833                 }
13834         }
13835
13836         /**
13837          * Check whether there is data beyond the pointer
13838          *
13839          * @access private
13840          * @return bool true if there is further data, false if not
13841          */
13842         function has_data()
13843         {
13844                 return (bool) ($this->position < $this->data_length);
13845         }
13846
13847         /**
13848          * Advance past any whitespace
13849          *
13850          * @return int Number of whitespace characters passed
13851          */
13852         function skip_whitespace()
13853         {
13854                 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13855                 $this->position += $whitespace;
13856                 return $whitespace;
13857         }
13858
13859         /**
13860          * Read value
13861          */
13862         function get_value()
13863         {
13864                 $quote = substr($this->data, $this->position, 1);
13865                 if ($quote === '"' || $quote === "'")
13866                 {
13867                         $this->position++;
13868                         $len = strcspn($this->data, $quote, $this->position);
13869                         if ($this->has_data())
13870                         {
13871                                 $value = substr($this->data, $this->position, $len);
13872                                 $this->position += $len + 1;
13873                                 return $value;
13874                         }
13875                 }
13876                 return false;
13877         }
13878
13879         function before_version_name()
13880         {
13881                 if ($this->skip_whitespace())
13882                 {
13883                         $this->state = 'version_name';
13884                 }
13885                 else
13886                 {
13887                         $this->state = false;
13888                 }
13889         }
13890
13891         function version_name()
13892         {
13893                 if (substr($this->data, $this->position, 7) === 'version')
13894                 {
13895                         $this->position += 7;
13896                         $this->skip_whitespace();
13897                         $this->state = 'version_equals';
13898                 }
13899                 else
13900                 {
13901                         $this->state = false;
13902                 }
13903         }
13904
13905         function version_equals()
13906         {
13907                 if (substr($this->data, $this->position, 1) === '=')
13908                 {
13909                         $this->position++;
13910                         $this->skip_whitespace();
13911                         $this->state = 'version_value';
13912                 }
13913                 else
13914                 {
13915                         $this->state = false;
13916                 }
13917         }
13918
13919         function version_value()
13920         {
13921                 if ($this->version = $this->get_value())
13922                 {
13923                         $this->skip_whitespace();
13924                         if ($this->has_data())
13925                         {
13926                                 $this->state = 'encoding_name';
13927                         }
13928                         else
13929                         {
13930                                 $this->state = 'emit';
13931                         }
13932                 }
13933                 else
13934                 {
13935                         $this->state = 'standalone_name';
13936                 }
13937         }
13938
13939         function encoding_name()
13940         {
13941                 if (substr($this->data, $this->position, 8) === 'encoding')
13942                 {
13943                         $this->position += 8;
13944                         $this->skip_whitespace();
13945                         $this->state = 'encoding_equals';
13946                 }
13947                 else
13948                 {
13949                         $this->state = false;
13950                 }
13951         }
13952
13953         function encoding_equals()
13954         {
13955                 if (substr($this->data, $this->position, 1) === '=')
13956                 {
13957                         $this->position++;
13958                         $this->skip_whitespace();
13959                         $this->state = 'encoding_value';
13960                 }
13961                 else
13962                 {
13963                         $this->state = false;
13964                 }
13965         }
13966
13967         function encoding_value()
13968         {
13969                 if ($this->encoding = $this->get_value())
13970                 {
13971                         $this->skip_whitespace();
13972                         if ($this->has_data())
13973                         {
13974                                 $this->state = 'standalone_name';
13975                         }
13976                         else
13977                         {
13978                                 $this->state = 'emit';
13979                         }
13980                 }
13981                 else
13982                 {
13983                         $this->state = false;
13984                 }
13985         }
13986
13987         function standalone_name()
13988         {
13989                 if (substr($this->data, $this->position, 10) === 'standalone')
13990                 {
13991                         $this->position += 10;
13992                         $this->skip_whitespace();
13993                         $this->state = 'standalone_equals';
13994                 }
13995                 else
13996                 {
13997                         $this->state = false;
13998                 }
13999         }
14000
14001         function standalone_equals()
14002         {
14003                 if (substr($this->data, $this->position, 1) === '=')
14004                 {
14005                         $this->position++;
14006                         $this->skip_whitespace();
14007                         $this->state = 'standalone_value';
14008                 }
14009                 else
14010                 {
14011                         $this->state = false;
14012                 }
14013         }
14014
14015         function standalone_value()
14016         {
14017                 if ($standalone = $this->get_value())
14018                 {
14019                         switch ($standalone)
14020                         {
14021                                 case 'yes':
14022                                         $this->standalone = true;
14023                                         break;
14024
14025                                 case 'no':
14026                                         $this->standalone = false;
14027                                         break;
14028
14029                                 default:
14030                                         $this->state = false;
14031                                         return;
14032                         }
14033
14034                         $this->skip_whitespace();
14035                         if ($this->has_data())
14036                         {
14037                                 $this->state = false;
14038                         }
14039                         else
14040                         {
14041                                 $this->state = 'emit';
14042                         }
14043                 }
14044                 else
14045                 {
14046                         $this->state = false;
14047                 }
14048         }
14049 }
14050
14051 class SimplePie_Locator
14052 {
14053         var $useragent;
14054         var $timeout;
14055         var $file;
14056         var $local = array();
14057         var $elsewhere = array();
14058         var $file_class = 'SimplePie_File';
14059         var $cached_entities = array();
14060         var $http_base;
14061         var $base;
14062         var $base_location = 0;
14063         var $checked_feeds = 0;
14064         var $max_checked_feeds = 10;
14065         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14066
14067         function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14068         {
14069                 $this->file =& $file;
14070                 $this->file_class = $file_class;
14071                 $this->useragent = $useragent;
14072                 $this->timeout = $timeout;
14073                 $this->max_checked_feeds = $max_checked_feeds;
14074                 $this->content_type_sniffer_class = $content_type_sniffer_class;
14075         }
14076
14077         function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14078         {
14079                 if ($this->is_feed($this->file))
14080                 {
14081                         return $this->file;
14082                 }
14083
14084                 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14085                 {
14086                         $sniffer =& new $this->content_type_sniffer_class($this->file);
14087                         if ($sniffer->get_type() !== 'text/html')
14088                         {
14089                                 return null;
14090                         }
14091                 }
14092
14093                 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14094                 {
14095                         $this->get_base();
14096                 }
14097
14098                 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14099                 {
14100                         return $working[0];
14101                 }
14102
14103                 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14104                 {
14105                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14106                         {
14107                                 return $working;
14108                         }
14109
14110                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14111                         {
14112                                 return $working;
14113                         }
14114
14115                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14116                         {
14117                                 return $working;
14118                         }
14119
14120                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14121                         {
14122                                 return $working;
14123                         }
14124                 }
14125                 return null;
14126         }
14127
14128         function is_feed(&$file)
14129         {
14130                 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14131                 {
14132                         $sniffer =& new $this->content_type_sniffer_class($file);
14133                         $sniffed = $sniffer->get_type();
14134                         if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14135                         {
14136                                 return true;
14137                         }
14138                         else
14139                         {
14140                                 return false;
14141                         }
14142                 }
14143                 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14144                 {
14145                         return true;
14146                 }
14147                 else
14148                 {
14149                         return false;
14150                 }
14151         }
14152
14153         function get_base()
14154         {
14155                 $this->http_base = $this->file->url;
14156                 $this->base = $this->http_base;
14157                 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14158                 foreach ($elements as $element)
14159                 {
14160                         if ($element['attribs']['href']['data'] !== '')
14161                         {
14162                                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14163                                 $this->base_location = $element['offset'];
14164                                 break;
14165                         }
14166                 }
14167         }
14168
14169         function autodiscovery()
14170         {
14171                 $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));
14172                 $done = array();
14173                 $feeds = array();
14174                 foreach ($links as $link)
14175                 {
14176                         if ($this->checked_feeds === $this->max_checked_feeds)
14177                         {
14178                                 break;
14179                         }
14180                         if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14181                         {
14182                                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14183
14184                                 if ($this->base_location < $link['offset'])
14185                                 {
14186                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14187                                 }
14188                                 else
14189                                 {
14190                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14191                                 }
14192
14193                                 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]))
14194                                 {
14195                                         $this->checked_feeds++;
14196                                         $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14197                                         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))
14198                                         {
14199                                                 $feeds[$href] = $feed;
14200                                         }
14201                                 }
14202                                 $done[] = $href;
14203                         }
14204                 }
14205
14206                 if (!empty($feeds))
14207                 {
14208                         return array_values($feeds);
14209                 }
14210                 else {
14211                         return null;
14212                 }
14213         }
14214
14215         function get_links()
14216         {
14217                 $links = SimplePie_Misc::get_element('a', $this->file->body);
14218                 foreach ($links as $link)
14219                 {
14220                         if (isset($link['attribs']['href']['data']))
14221                         {
14222                                 $href = trim($link['attribs']['href']['data']);
14223                                 $parsed = SimplePie_Misc::parse_url($href);
14224                                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14225                                 {
14226                                         if ($this->base_location < $link['offset'])
14227                                         {
14228                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14229                                         }
14230                                         else
14231                                         {
14232                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14233                                         }
14234
14235                                         $current = SimplePie_Misc::parse_url($this->file->url);
14236
14237                                         if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14238                                         {
14239                                                 $this->local[] = $href;
14240                                         }
14241                                         else
14242                                         {
14243                                                 $this->elsewhere[] = $href;
14244                                         }
14245                                 }
14246                         }
14247                 }
14248                 $this->local = array_unique($this->local);
14249                 $this->elsewhere = array_unique($this->elsewhere);
14250                 if (!empty($this->local) || !empty($this->elsewhere))
14251                 {
14252                         return true;
14253                 }
14254                 return null;
14255         }
14256
14257         function extension(&$array)
14258         {
14259                 foreach ($array as $key => $value)
14260                 {
14261                         if ($this->checked_feeds === $this->max_checked_feeds)
14262                         {
14263                                 break;
14264                         }
14265                         if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14266                         {
14267                                 $this->checked_feeds++;
14268                                 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14269                                 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))
14270                                 {
14271                                         return $feed;
14272                                 }
14273                                 else
14274                                 {
14275                                         unset($array[$key]);
14276                                 }
14277                         }
14278                 }
14279                 return null;
14280         }
14281
14282         function body(&$array)
14283         {
14284                 foreach ($array as $key => $value)
14285                 {
14286                         if ($this->checked_feeds === $this->max_checked_feeds)
14287                         {
14288                                 break;
14289                         }
14290                         if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14291                         {
14292                                 $this->checked_feeds++;
14293                                 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14294                                 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))
14295                                 {
14296                                         return $feed;
14297                                 }
14298                                 else
14299                                 {
14300                                         unset($array[$key]);
14301                                 }
14302                         }
14303                 }
14304                 return null;
14305         }
14306 }
14307
14308 class SimplePie_Parser
14309 {
14310         var $error_code;
14311         var $error_string;
14312         var $current_line;
14313         var $current_column;
14314         var $current_byte;
14315         var $separator = ' ';
14316         var $namespace = array('');
14317         var $element = array('');
14318         var $xml_base = array('');
14319         var $xml_base_explicit = array(false);
14320         var $xml_lang = array('');
14321         var $data = array();
14322         var $datas = array(array());
14323         var $current_xhtml_construct = -1;
14324         var $encoding;
14325
14326         function parse(&$data, $encoding)
14327         {
14328                 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14329                 if (strtoupper($encoding) === 'US-ASCII')
14330                 {
14331                         $this->encoding = 'UTF-8';
14332                 }
14333                 else
14334                 {
14335                         $this->encoding = $encoding;
14336                 }
14337
14338                 // Strip BOM:
14339                 // UTF-32 Big Endian BOM
14340                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14341                 {
14342                         $data = substr($data, 4);
14343                 }
14344                 // UTF-32 Little Endian BOM
14345                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14346                 {
14347                         $data = substr($data, 4);
14348                 }
14349                 // UTF-16 Big Endian BOM
14350                 elseif (substr($data, 0, 2) === "\xFE\xFF")
14351                 {
14352                         $data = substr($data, 2);
14353                 }
14354                 // UTF-16 Little Endian BOM
14355                 elseif (substr($data, 0, 2) === "\xFF\xFE")
14356                 {
14357                         $data = substr($data, 2);
14358                 }
14359                 // UTF-8 BOM
14360                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14361                 {
14362                         $data = substr($data, 3);
14363                 }
14364
14365                 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14366                 {
14367                         $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14368                         if ($declaration->parse())
14369                         {
14370                                 $data = substr($data, $pos + 2);
14371                                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14372                         }
14373                         else
14374                         {
14375                                 $this->error_string = 'SimplePie bug! Please report this!';
14376                                 return false;
14377                         }
14378                 }
14379
14380                 $return = true;
14381
14382                 static $xml_is_sane = null;
14383                 if ($xml_is_sane === null)
14384                 {
14385                         $parser_check = xml_parser_create();
14386                         xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14387                         xml_parser_free($parser_check);
14388                         $xml_is_sane = isset($values[0]['value']);
14389                 }
14390
14391                 // Create the parser
14392                 if ($xml_is_sane)
14393                 {
14394                         $xml = xml_parser_create_ns($this->encoding, $this->separator);
14395                         xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14396                         xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14397                         xml_set_object($xml, $this);
14398                         xml_set_character_data_handler($xml, 'cdata');
14399                         xml_set_element_handler($xml, 'tag_open', 'tag_close');
14400
14401                         // Parse!
14402                         if (!xml_parse($xml, $data, true))
14403                         {
14404                                 $this->error_code = xml_get_error_code($xml);
14405                                 $this->error_string = xml_error_string($this->error_code);
14406                                 $return = false;
14407                         }
14408                         $this->current_line = xml_get_current_line_number($xml);
14409                         $this->current_column = xml_get_current_column_number($xml);
14410                         $this->current_byte = xml_get_current_byte_index($xml);
14411                         xml_parser_free($xml);
14412                         return $return;
14413                 }
14414                 else
14415                 {
14416                         libxml_clear_errors();
14417                         $xml =& new XMLReader();
14418                         $xml->xml($data);
14419                         while (@$xml->read())
14420                         {
14421                                 switch ($xml->nodeType)
14422                                 {
14423
14424                                         case constant('XMLReader::END_ELEMENT'):
14425                                                 if ($xml->namespaceURI !== '')
14426                                                 {
14427                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14428                                                 }
14429                                                 else
14430                                                 {
14431                                                         $tagName = $xml->localName;
14432                                                 }
14433                                                 $this->tag_close(null, $tagName);
14434                                                 break;
14435                                         case constant('XMLReader::ELEMENT'):
14436                                                 $empty = $xml->isEmptyElement;
14437                                                 if ($xml->namespaceURI !== '')
14438                                                 {
14439                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14440                                                 }
14441                                                 else
14442                                                 {
14443                                                         $tagName = $xml->localName;
14444                                                 }
14445                                                 $attributes = array();
14446                                                 while ($xml->moveToNextAttribute())
14447                                                 {
14448                                                         if ($xml->namespaceURI !== '')
14449                                                         {
14450                                                                 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14451                                                         }
14452                                                         else
14453                                                         {
14454                                                                 $attrName = $xml->localName;
14455                                                         }
14456                                                         $attributes[$attrName] = $xml->value;
14457                                                 }
14458                                                 $this->tag_open(null, $tagName, $attributes);
14459                                                 if ($empty)
14460                                                 {
14461                                                         $this->tag_close(null, $tagName);
14462                                                 }
14463                                                 break;
14464                                         case constant('XMLReader::TEXT'):
14465
14466                                         case constant('XMLReader::CDATA'):
14467                                                 $this->cdata(null, $xml->value);
14468                                                 break;
14469                                 }
14470                         }
14471                         if ($error = libxml_get_last_error())
14472                         {
14473                                 $this->error_code = $error->code;
14474                                 $this->error_string = $error->message;
14475                                 $this->current_line = $error->line;
14476                                 $this->current_column = $error->column;
14477                                 return false;
14478                         }
14479                         else
14480                         {
14481                                 return true;
14482                         }
14483                 }
14484         }
14485
14486         function get_error_code()
14487         {
14488                 return $this->error_code;
14489         }
14490
14491         function get_error_string()
14492         {
14493                 return $this->error_string;
14494         }
14495
14496         function get_current_line()
14497         {
14498                 return $this->current_line;
14499         }
14500
14501         function get_current_column()
14502         {
14503                 return $this->current_column;
14504         }
14505
14506         function get_current_byte()
14507         {
14508                 return $this->current_byte;
14509         }
14510
14511         function get_data()
14512         {
14513                 return $this->data;
14514         }
14515
14516         function tag_open($parser, $tag, $attributes)
14517         {
14518                 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14519
14520                 $attribs = array();
14521                 foreach ($attributes as $name => $value)
14522                 {
14523                         list($attrib_namespace, $attribute) = $this->split_ns($name);
14524                         $attribs[$attrib_namespace][$attribute] = $value;
14525                 }
14526
14527                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14528                 {
14529                         $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14530                         $this->xml_base_explicit[] = true;
14531                 }
14532                 else
14533                 {
14534                         $this->xml_base[] = end($this->xml_base);
14535                         $this->xml_base_explicit[] = end($this->xml_base_explicit);
14536                 }
14537
14538                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14539                 {
14540                         $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14541                 }
14542                 else
14543                 {
14544                         $this->xml_lang[] = end($this->xml_lang);
14545                 }
14546
14547                 if ($this->current_xhtml_construct >= 0)
14548                 {
14549                         $this->current_xhtml_construct++;
14550                         if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14551                         {
14552                                 $this->data['data'] .= '<' . end($this->element);
14553                                 if (isset($attribs['']))
14554                                 {
14555                                         foreach ($attribs[''] as $name => $value)
14556                                         {
14557                                                 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14558                                         }
14559                                 }
14560                                 $this->data['data'] .= '>';
14561                         }
14562                 }
14563                 else
14564                 {
14565                         $this->datas[] =& $this->data;
14566                         $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14567                         $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));
14568                         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')
14569                         || (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'))
14570                         {
14571                                 $this->current_xhtml_construct = 0;
14572                         }
14573                 }
14574         }
14575
14576         function cdata($parser, $cdata)
14577         {
14578                 if ($this->current_xhtml_construct >= 0)
14579                 {
14580                         $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14581                 }
14582                 else
14583                 {
14584                         $this->data['data'] .= $cdata;
14585                 }
14586         }
14587
14588         function tag_close($parser, $tag)
14589         {
14590                 if ($this->current_xhtml_construct >= 0)
14591                 {
14592                         $this->current_xhtml_construct--;
14593                         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')))
14594                         {
14595                                 $this->data['data'] .= '</' . end($this->element) . '>';
14596                         }
14597                 }
14598                 if ($this->current_xhtml_construct === -1)
14599                 {
14600                         $this->data =& $this->datas[count($this->datas) - 1];
14601                         array_pop($this->datas);
14602                 }
14603
14604                 array_pop($this->element);
14605                 array_pop($this->namespace);
14606                 array_pop($this->xml_base);
14607                 array_pop($this->xml_base_explicit);
14608                 array_pop($this->xml_lang);
14609         }
14610
14611         function split_ns($string)
14612         {
14613                 static $cache = array();
14614                 if (!isset($cache[$string]))
14615                 {
14616                         if ($pos = strpos($string, $this->separator))
14617                         {
14618                                 static $separator_length;
14619                                 if (!$separator_length)
14620                                 {
14621                                         $separator_length = strlen($this->separator);
14622                                 }
14623                                 $namespace = substr($string, 0, $pos);
14624                                 $local_name = substr($string, $pos + $separator_length);
14625                                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14626                                 {
14627                                         $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14628                                 }
14629
14630                                 // Normalize the Media RSS namespaces
14631                                 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14632                                 {
14633                                         $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14634                                 }
14635                                 $cache[$string] = array($namespace, $local_name);
14636                         }
14637                         else
14638                         {
14639                                 $cache[$string] = array('', $string);
14640                         }
14641                 }
14642                 return $cache[$string];
14643         }
14644 }
14645
14646 /**
14647  * @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
14648  */
14649 class SimplePie_Sanitize
14650 {
14651         // Private vars
14652         var $base;
14653
14654         // Options
14655         var $remove_div = true;
14656         var $image_handler = '';
14657         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14658         var $encode_instead_of_strip = false;
14659         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14660         var $strip_comments = false;
14661         var $output_encoding = 'UTF-8';
14662         var $enable_cache = true;
14663         var $cache_location = './cache';
14664         var $cache_name_function = 'md5';
14665         var $cache_class = 'SimplePie_Cache';
14666         var $file_class = 'SimplePie_File';
14667         var $timeout = 10;
14668         var $useragent = '';
14669         var $force_fsockopen = false;
14670
14671         var $replace_url_attributes = array(
14672                 'a' => 'href',
14673                 'area' => 'href',
14674                 'blockquote' => 'cite',
14675                 'del' => 'cite',
14676                 'form' => 'action',
14677                 'img' => array('longdesc', 'src'),
14678                 'input' => 'src',
14679                 'ins' => 'cite',
14680                 'q' => 'cite'
14681         );
14682
14683         function remove_div($enable = true)
14684         {
14685                 $this->remove_div = (bool) $enable;
14686         }
14687
14688         function set_image_handler($page = false)
14689         {
14690                 if ($page)
14691                 {
14692                         $this->image_handler = (string) $page;
14693                 }
14694                 else
14695                 {
14696                         $this->image_handler = false;
14697                 }
14698         }
14699
14700         function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14701         {
14702                 if (isset($enable_cache))
14703                 {
14704                         $this->enable_cache = (bool) $enable_cache;
14705                 }
14706
14707                 if ($cache_location)
14708                 {
14709                         $this->cache_location = (string) $cache_location;
14710                 }
14711
14712                 if ($cache_name_function)
14713                 {
14714                         $this->cache_name_function = (string) $cache_name_function;
14715                 }
14716
14717                 if ($cache_class)
14718                 {
14719                         $this->cache_class = (string) $cache_class;
14720                 }
14721         }
14722
14723         function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14724         {
14725                 if ($file_class)
14726                 {
14727                         $this->file_class = (string) $file_class;
14728                 }
14729
14730                 if ($timeout)
14731                 {
14732                         $this->timeout = (string) $timeout;
14733                 }
14734
14735                 if ($useragent)
14736                 {
14737                         $this->useragent = (string) $useragent;
14738                 }
14739
14740                 if ($force_fsockopen)
14741                 {
14742                         $this->force_fsockopen = (string) $force_fsockopen;
14743                 }
14744         }
14745
14746         function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14747         {
14748                 if ($tags)
14749                 {
14750                         if (is_array($tags))
14751                         {
14752                                 $this->strip_htmltags = $tags;
14753                         }
14754                         else
14755                         {
14756                                 $this->strip_htmltags = explode(',', $tags);
14757                         }
14758                 }
14759                 else
14760                 {
14761                         $this->strip_htmltags = false;
14762                 }
14763         }
14764
14765         function encode_instead_of_strip($encode = false)
14766         {
14767                 $this->encode_instead_of_strip = (bool) $encode;
14768         }
14769
14770         function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14771         {
14772                 if ($attribs)
14773                 {
14774                         if (is_array($attribs))
14775                         {
14776                                 $this->strip_attributes = $attribs;
14777                         }
14778                         else
14779                         {
14780                                 $this->strip_attributes = explode(',', $attribs);
14781                         }
14782                 }
14783                 else
14784                 {
14785                         $this->strip_attributes = false;
14786                 }
14787         }
14788
14789         function strip_comments($strip = false)
14790         {
14791                 $this->strip_comments = (bool) $strip;
14792         }
14793
14794         function set_output_encoding($encoding = 'UTF-8')
14795         {
14796                 $this->output_encoding = (string) $encoding;
14797         }
14798
14799         /**
14800          * Set element/attribute key/value pairs of HTML attributes
14801          * containing URLs that need to be resolved relative to the feed
14802          *
14803          * @access public
14804          * @since 1.0
14805          * @param array $element_attribute Element/attribute key/value pairs
14806          */
14807         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'))
14808         {
14809                 $this->replace_url_attributes = (array) $element_attribute;
14810         }
14811
14812         function sanitize($data, $type, $base = '')
14813         {
14814                 $data = trim($data);
14815                 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14816                 {
14817                         if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14818                         {
14819                                 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))
14820                                 {
14821                                         $type |= SIMPLEPIE_CONSTRUCT_HTML;
14822                                 }
14823                                 else
14824                                 {
14825                                         $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14826                                 }
14827                         }
14828
14829                         if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14830                         {
14831                                 $data = base64_decode($data);
14832                         }
14833
14834                         if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14835                         {
14836                                 if ($this->remove_div)
14837                                 {
14838                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14839                                         $data = preg_replace('/<\/div>$/', '', $data);
14840                                 }
14841                                 else
14842                                 {
14843                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14844                                 }
14845                         }
14846
14847                         if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14848                         {
14849                                 // Strip comments
14850                                 if ($this->strip_comments)
14851                                 {
14852                                         $data = SimplePie_Misc::strip_comments($data);
14853                                 }
14854
14855                                 // Strip out HTML tags and attributes that might cause various security problems.
14856                                 // Based on recommendations by Mark Pilgrim at:
14857                                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
14858                                 if ($this->strip_htmltags)
14859                                 {
14860                                         foreach ($this->strip_htmltags as $tag)
14861                                         {
14862                                                 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
14863                                                 while (preg_match($pcre, $data))
14864                                                 {
14865                                                         $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
14866                                                 }
14867                                         }
14868                                 }
14869
14870                                 if ($this->strip_attributes)
14871                                 {
14872                                         foreach ($this->strip_attributes as $attrib)
14873                                         {
14874                                                 $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);
14875                                         }
14876                                 }
14877
14878                                 // Replace relative URLs
14879                                 $this->base = $base;
14880                                 foreach ($this->replace_url_attributes as $element => $attributes)
14881                                 {
14882                                         $data = $this->replace_urls($data, $element, $attributes);
14883                                 }
14884
14885                                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
14886                                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
14887                                 {
14888                                         $images = SimplePie_Misc::get_element('img', $data);
14889                                         foreach ($images as $img)
14890                                         {
14891                                                 if (isset($img['attribs']['src']['data']))
14892                                                 {
14893                                                         $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
14894                                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
14895
14896                                                         if ($cache->load())
14897                                                         {
14898                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14899                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14900                                                         }
14901                                                         else
14902                                                         {
14903                                                                 $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
14904                                                                 $headers = $file->headers;
14905
14906                                                                 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
14907                                                                 {
14908                                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
14909                                                                         {
14910                                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14911                                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14912                                                                         }
14913                                                                         else
14914                                                                         {
14915                                                                                 trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
14916                                                                         }
14917                                                                 }
14918                                                         }
14919                                                 }
14920                                         }
14921                                 }
14922
14923                                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
14924                                 $data = trim($data);
14925                         }
14926
14927                         if ($type & SIMPLEPIE_CONSTRUCT_IRI)
14928                         {
14929                                 $data = SimplePie_Misc::absolutize_url($data, $base);
14930                         }
14931
14932                         if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
14933                         {
14934                                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
14935                         }
14936
14937                         if ($this->output_encoding !== 'UTF-8')
14938                         {
14939                                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
14940                         }
14941                 }
14942                 return $data;
14943         }
14944
14945         function replace_urls($data, $tag, $attributes)
14946         {
14947                 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
14948                 {
14949                         $elements = SimplePie_Misc::get_element($tag, $data);
14950                         foreach ($elements as $element)
14951                         {
14952                                 if (is_array($attributes))
14953                                 {
14954                                         foreach ($attributes as $attribute)
14955                                         {
14956                                                 if (isset($element['attribs'][$attribute]['data']))
14957                                                 {
14958                                                         $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
14959                                                         $new_element = SimplePie_Misc::element_implode($element);
14960                                                         $data = str_replace($element['full'], $new_element, $data);
14961                                                         $element['full'] = $new_element;
14962                                                 }
14963                                         }
14964                                 }
14965                                 elseif (isset($element['attribs'][$attributes]['data']))
14966                                 {
14967                                         $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
14968                                         $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
14969                                 }
14970                         }
14971                 }
14972                 return $data;
14973         }
14974
14975         function do_strip_htmltags($match)
14976         {
14977                 if ($this->encode_instead_of_strip)
14978                 {
14979                         if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14980                         {
14981                                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
14982                                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
14983                                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
14984                         }
14985                         else
14986                         {
14987                                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
14988                         }
14989                 }
14990                 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14991                 {
14992                         return $match[4];
14993                 }
14994                 else
14995                 {
14996                         return '';
14997                 }
14998         }
14999 }
15000
15001 ?>